15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/* 25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2003, 2006, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved. 35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2008 Holger Hans Peter Freyther 45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * This library is free software; you can redistribute it and/or 65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * modify it under the terms of the GNU Library General Public 75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * License as published by the Free Software Foundation; either 85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * version 2 of the License, or (at your option) any later version. 95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * This library is distributed in the hope that it will be useful, 115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * but WITHOUT ANY WARRANTY; without even the implied warranty of 125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Library General Public License for more details. 145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * You should have received a copy of the GNU Library General Public License 165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * along with this library; see the file COPYING.LIB. If not, write to 175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Boston, MA 02110-1301, USA. 195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */ 215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "config.h" 2353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/platform/graphics/WidthIterator.h" 245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/platform/graphics/Font.h" 2653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/platform/graphics/GlyphBuffer.h" 2753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/platform/graphics/Latin1TextIterator.h" 2853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/platform/graphics/SimpleFontData.h" 2953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/platform/graphics/SurrogatePairAwareTextIterator.h" 307757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#include "wtf/MathExtras.h" 315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)using namespace WTF; 335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)using namespace Unicode; 345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)using namespace std; 355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)namespace WebCore { 375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)WidthIterator::WidthIterator(const Font* font, const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts, bool accountForGlyphBounds, bool forTextEmphasis) 395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) : m_font(font) 405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_run(run) 415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_currentCharacter(0) 425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_runWidthSoFar(0) 435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_isAfterExpansion(!run.allowsLeadingExpansion()) 445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_finalRoundingWidth(0) 455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_typesettingFeatures(font->typesettingFeatures()) 465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_fallbackFonts(fallbackFonts) 475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_accountForGlyphBounds(accountForGlyphBounds) 485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_maxGlyphBoundingBoxY(numeric_limits<float>::min()) 495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_minGlyphBoundingBoxY(numeric_limits<float>::max()) 505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_firstGlyphOverflow(0) 515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_lastGlyphOverflow(0) 525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_forTextEmphasis(forTextEmphasis) 535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // If the padding is non-zero, count the number of spaces in the run 555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // and divide that by the padding for per space addition. 565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_expansion = m_run.expansion(); 575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!m_expansion) 585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_expansionPerOpportunity = 0; 595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else { 605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool isAfterExpansion = m_isAfterExpansion; 615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) unsigned expansionOpportunityCount = m_run.is8Bit() ? Font::expansionOpportunityCount(m_run.characters8(), m_run.length(), m_run.ltr() ? LTR : RTL, isAfterExpansion) : Font::expansionOpportunityCount(m_run.characters16(), m_run.length(), m_run.ltr() ? LTR : RTL, isAfterExpansion); 625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (isAfterExpansion && !m_run.allowsTrailingExpansion()) 635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) expansionOpportunityCount--; 645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!expansionOpportunityCount) 665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_expansionPerOpportunity = 0; 675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else 685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_expansionPerOpportunity = m_expansion / expansionOpportunityCount; 695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)GlyphData WidthIterator::glyphDataForCharacter(UChar32 character, bool mirror, int currentCharacter, unsigned& advanceLength) 735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(m_font); 755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#if ENABLE(SVG_FONTS) 775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (TextRun::RenderingContext* renderingContext = m_run.renderingContext()) 785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return renderingContext->glyphDataForCharacter(*m_font, m_run, *this, character, mirror, currentCharacter, advanceLength); 795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#else 805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) UNUSED_PARAM(currentCharacter); 815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) UNUSED_PARAM(advanceLength); 825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#endif 835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return m_font->glyphDataForCharacter(character, mirror); 855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)struct OriginalAdvancesForCharacterTreatedAsSpace { 885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)public: 895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) OriginalAdvancesForCharacterTreatedAsSpace(bool isSpace, float advanceBefore, float advanceAt) 905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) : characterIsSpace(isSpace) 915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , advanceBeforeCharacter(advanceBefore) 925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , advanceAtCharacter(advanceAt) 935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) { 945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool characterIsSpace; 975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) float advanceBeforeCharacter; 985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) float advanceAtCharacter; 995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}; 1005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)typedef Vector<pair<int, OriginalAdvancesForCharacterTreatedAsSpace>, 64> CharactersTreatedAsSpace; 1025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static inline float applyFontTransforms(GlyphBuffer* glyphBuffer, bool ltr, int& lastGlyphCount, const SimpleFontData* fontData, TypesettingFeatures typesettingFeatures, CharactersTreatedAsSpace& charactersTreatedAsSpace) 1045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(typesettingFeatures & (Kerning | Ligatures)); 1065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!glyphBuffer) 1085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return 0; 1095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int glyphBufferSize = glyphBuffer->size(); 1115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (glyphBuffer->size() <= lastGlyphCount + 1) 1125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return 0; 1135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) GlyphBufferAdvance* advances = glyphBuffer->advances(0); 1155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) float widthDifference = 0; 1165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (int i = lastGlyphCount; i < glyphBufferSize; ++i) 1175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) widthDifference -= advances[i].width(); 1185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!ltr) 1205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) glyphBuffer->reverse(lastGlyphCount, glyphBufferSize - lastGlyphCount); 1215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) fontData->applyTransforms(glyphBuffer->glyphs(lastGlyphCount), advances + lastGlyphCount, glyphBufferSize - lastGlyphCount, typesettingFeatures); 1235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!ltr) 1255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) glyphBuffer->reverse(lastGlyphCount, glyphBufferSize - lastGlyphCount); 1265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (size_t i = 0; i < charactersTreatedAsSpace.size(); ++i) { 1285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int spaceOffset = charactersTreatedAsSpace[i].first; 1295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) const OriginalAdvancesForCharacterTreatedAsSpace& originalAdvances = charactersTreatedAsSpace[i].second; 1305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (spaceOffset && !originalAdvances.characterIsSpace) 1315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) glyphBuffer->advances(spaceOffset - 1)->setWidth(originalAdvances.advanceBeforeCharacter); 1325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) glyphBuffer->advances(spaceOffset)->setWidth(originalAdvances.advanceAtCharacter); 1335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) charactersTreatedAsSpace.clear(); 1355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (int i = lastGlyphCount; i < glyphBufferSize; ++i) 1375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) widthDifference += advances[i].width(); 1385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) lastGlyphCount = glyphBufferSize; 1405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return widthDifference; 1415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)template <typename TextIterator> 1445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)inline unsigned WidthIterator::advanceInternal(TextIterator& textIterator, GlyphBuffer* glyphBuffer) 1455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool rtl = m_run.rtl(); 1475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool hasExtraSpacing = (m_font->letterSpacing() || m_font->wordSpacing() || m_expansion) && !m_run.spacingDisabled(); 1485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) float widthSinceLastRounding = m_runWidthSoFar; 1505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_runWidthSoFar = floorf(m_runWidthSoFar); 1515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) widthSinceLastRounding -= m_runWidthSoFar; 1525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) float lastRoundingWidth = m_finalRoundingWidth; 1545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) FloatRect bounds; 1555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) const SimpleFontData* primaryFont = m_font->primaryFont(); 1575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) const SimpleFontData* lastFontData = primaryFont; 1585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int lastGlyphCount = glyphBuffer ? glyphBuffer->size() : 0; 1595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) UChar32 character = 0; 1615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) unsigned clusterLength = 0; 1625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) CharactersTreatedAsSpace charactersTreatedAsSpace; 1635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) while (textIterator.consume(character, clusterLength)) { 1645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) unsigned advanceLength = clusterLength; 1655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) const GlyphData& glyphData = glyphDataForCharacter(character, rtl, textIterator.currentCharacter(), advanceLength); 1665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Glyph glyph = glyphData.glyph; 1675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) const SimpleFontData* fontData = glyphData.fontData; 1685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(fontData); 1705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Now that we have a glyph and font data, get its width. 1725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) float width; 1735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (character == '\t' && m_run.allowTabs()) 1745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) width = m_font->tabWidth(*fontData, m_run.tabSize(), m_run.xPos() + m_runWidthSoFar + widthSinceLastRounding); 1755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else { 1765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) width = fontData->widthForGlyph(glyph); 1775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // SVG uses horizontalGlyphStretch(), when textLength is used to stretch/squeeze text. 1795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) width *= m_run.horizontalGlyphStretch(); 1805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // We special case spaces in two ways when applying word rounding. 1825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // First, we round spaces to an adjusted width in all fonts. 1835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Second, in fixed-pitch fonts we ensure that all characters that 1845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // match the width of the space character have the same width as the space character. 1855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_run.applyWordRounding() && width == fontData->spaceWidth() && (fontData->pitch() == FixedPitch || glyph == fontData->spaceGlyph())) 1865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) width = fontData->adjustedSpaceWidth(); 1875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (fontData != lastFontData && width) { 1905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (shouldApplyFontTransforms()) 1915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_runWidthSoFar += applyFontTransforms(glyphBuffer, m_run.ltr(), lastGlyphCount, lastFontData, m_typesettingFeatures, charactersTreatedAsSpace); 1925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) lastFontData = fontData; 1945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_fallbackFonts && fontData != primaryFont) { 1955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // FIXME: This does a little extra work that could be avoided if 1965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // glyphDataForCharacter() returned whether it chose to use a small caps font. 1975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!m_font->isSmallCaps() || character == toUpper(character)) 1985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_fallbackFonts->add(fontData); 1995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else { 2005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) const GlyphData& uppercaseGlyphData = m_font->glyphDataForCharacter(toUpper(character), rtl); 2015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (uppercaseGlyphData.fontData != primaryFont) 2025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_fallbackFonts->add(uppercaseGlyphData.fontData); 2035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (hasExtraSpacing) { 2085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Account for letter-spacing. 2095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (width && m_font->letterSpacing()) 2105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) width += m_font->letterSpacing(); 2115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) static bool expandAroundIdeographs = Font::canExpandAroundIdeographsInComplexText(); 2135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool treatAsSpace = Font::treatAsSpace(character); 2145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (treatAsSpace || (expandAroundIdeographs && Font::isCJKIdeographOrSymbol(character))) { 2155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Distribute the run's total expansion evenly over all expansion opportunities in the run. 2165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_expansion) { 2175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) float previousExpansion = m_expansion; 2185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!treatAsSpace && !m_isAfterExpansion) { 2195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Take the expansion opportunity before this ideograph. 2205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_expansion -= m_expansionPerOpportunity; 2215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) float expansionAtThisOpportunity = !m_run.applyWordRounding() ? m_expansionPerOpportunity : roundf(previousExpansion) - roundf(m_expansion); 2225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_runWidthSoFar += expansionAtThisOpportunity; 2235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (glyphBuffer) { 224926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (glyphBuffer->isEmpty()) { 225926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (m_forTextEmphasis) 226926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) glyphBuffer->add(fontData->zeroWidthSpaceGlyph(), fontData, m_expansionPerOpportunity); 227926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) else 228926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) glyphBuffer->add(fontData->spaceGlyph(), fontData, expansionAtThisOpportunity); 229926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } else 2305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) glyphBuffer->expandLastAdvance(expansionAtThisOpportunity); 2315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) previousExpansion = m_expansion; 2335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_run.allowsTrailingExpansion() || (m_run.ltr() && textIterator.currentCharacter() + advanceLength < static_cast<size_t>(m_run.length())) 2355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) || (m_run.rtl() && textIterator.currentCharacter())) { 2365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_expansion -= m_expansionPerOpportunity; 2375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) width += !m_run.applyWordRounding() ? m_expansionPerOpportunity : roundf(previousExpansion) - roundf(m_expansion); 2385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_isAfterExpansion = true; 2395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else 2415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_isAfterExpansion = false; 2425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Account for word spacing. 2445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // We apply additional space between "words" by adding width to the space character. 245926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (treatAsSpace && (character != '\t' || !m_run.allowTabs()) && (textIterator.currentCharacter() || character == noBreakSpace) && m_font->wordSpacing()) 2465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) width += m_font->wordSpacing(); 2475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else 2485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_isAfterExpansion = false; 2495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (shouldApplyFontTransforms() && glyphBuffer && Font::treatAsSpace(character)) 2525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) charactersTreatedAsSpace.append(make_pair(glyphBuffer->size(), 2535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) OriginalAdvancesForCharacterTreatedAsSpace(character == ' ', glyphBuffer->size() ? glyphBuffer->advanceAt(glyphBuffer->size() - 1) : 0, width))); 2545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_accountForGlyphBounds) { 2565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bounds = fontData->boundsForGlyph(glyph); 2575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!textIterator.currentCharacter()) 2585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_firstGlyphOverflow = max<float>(0, -bounds.x()); 2595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_forTextEmphasis && !Font::canReceiveTextEmphasis(character)) 2625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) glyph = 0; 2635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Advance past the character we just dealt with. 2655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) textIterator.advance(advanceLength); 2665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) float oldWidth = width; 2685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Force characters that are used to determine word boundaries for the rounding hack 2705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // to be integer width, so following words will start on an integer boundary. 2715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_run.applyWordRounding() && Font::isRoundingHackCharacter(character)) { 2725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) width = ceilf(width); 2735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Since widthSinceLastRounding can lose precision if we include measurements for 2755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // preceding whitespace, we bypass it here. 2765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_runWidthSoFar += width; 2775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Since this is a rounding hack character, we should have reset this sum on the previous 2795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // iteration. 2805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(!widthSinceLastRounding); 2815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else { 2825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Check to see if the next character is a "rounding hack character", if so, adjust 2835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // width so that the total run width will be on an integer boundary. 2845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if ((m_run.applyWordRounding() && textIterator.currentCharacter() < m_run.length() && Font::isRoundingHackCharacter(*(textIterator.characters()))) 2855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) || (m_run.applyRunRounding() && textIterator.currentCharacter() >= m_run.length())) { 2865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) float totalWidth = widthSinceLastRounding + width; 2875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) widthSinceLastRounding = ceilf(totalWidth); 2885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) width += widthSinceLastRounding - totalWidth; 2895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_runWidthSoFar += widthSinceLastRounding; 2905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) widthSinceLastRounding = 0; 2915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else 2925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) widthSinceLastRounding += width; 2935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (glyphBuffer) 2965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) glyphBuffer->add(glyph, fontData, (rtl ? oldWidth + lastRoundingWidth : width)); 2975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) lastRoundingWidth = width - oldWidth; 2995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_accountForGlyphBounds) { 3015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_maxGlyphBoundingBoxY = max(m_maxGlyphBoundingBoxY, bounds.maxY()); 3025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_minGlyphBoundingBoxY = min(m_minGlyphBoundingBoxY, bounds.y()); 3035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_lastGlyphOverflow = max<float>(0, bounds.maxX() - width); 3045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (shouldApplyFontTransforms()) 3085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_runWidthSoFar += applyFontTransforms(glyphBuffer, m_run.ltr(), lastGlyphCount, lastFontData, m_typesettingFeatures, charactersTreatedAsSpace); 3095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) unsigned consumedCharacters = textIterator.currentCharacter() - m_currentCharacter; 3115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_currentCharacter = textIterator.currentCharacter(); 3125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_runWidthSoFar += widthSinceLastRounding; 3135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_finalRoundingWidth = lastRoundingWidth; 3145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return consumedCharacters; 3155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 3165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)unsigned WidthIterator::advance(int offset, GlyphBuffer* glyphBuffer) 3185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 3195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int length = m_run.length(); 3205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (offset > length) 3225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) offset = length; 3235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_currentCharacter >= static_cast<unsigned>(offset)) 3255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return 0; 3265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_run.is8Bit()) { 3285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Latin1TextIterator textIterator(m_run.data8(m_currentCharacter), m_currentCharacter, offset, length); 3295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return advanceInternal(textIterator, glyphBuffer); 3305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) SurrogatePairAwareTextIterator textIterator(m_run.data16(m_currentCharacter), m_currentCharacter, offset, length); 3335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return advanceInternal(textIterator, glyphBuffer); 3345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 3355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool WidthIterator::advanceOneCharacter(float& width, GlyphBuffer& glyphBuffer) 3375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 3385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int oldSize = glyphBuffer.size(); 3395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) advance(m_currentCharacter + 1, &glyphBuffer); 3405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) float w = 0; 3415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (int i = oldSize; i < glyphBuffer.size(); ++i) 3425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) w += glyphBuffer.advanceAt(i); 3435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) width = w; 3445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return glyphBuffer.size() > oldSize; 3455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 3465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 348