Font::primaryFontData() should return a reference
[WebKit-https.git] / Source / WebCore / platform / graphics / mac / ComplexTextController.cpp
1 /*
2  * Copyright (C) 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16  * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
17  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
22  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23  */
24
25 #include "config.h"
26 #include "ComplexTextController.h"
27
28 #include "FloatSize.h"
29 #include "Font.h"
30 #include "RenderBlock.h"
31 #include "RenderText.h"
32 #include "TextBreakIterator.h"
33 #include "TextRun.h"
34 #if !PLATFORM(IOS)
35 #include <ApplicationServices/ApplicationServices.h>
36 #else
37 #include <CoreText/CoreText.h>
38 #endif
39 #include <wtf/StdLibExtras.h>
40 #include <wtf/unicode/CharacterNames.h>
41
42 namespace WebCore {
43
44 class TextLayout {
45 public:
46     static bool isNeeded(RenderText* text, const Font& font)
47     {
48         TextRun run = RenderBlock::constructTextRun(text, font, text, text->style());
49         return font.codePath(run) == Font::Complex;
50     }
51
52     TextLayout(RenderText* text, const Font& font, float xPos)
53         : m_font(font)
54         , m_run(constructTextRun(text, font, xPos))
55         , m_controller(std::make_unique<ComplexTextController>(&m_font, m_run, true))
56     {
57     }
58
59     float width(unsigned from, unsigned len, HashSet<const SimpleFontData*>* fallbackFonts)
60     {
61         m_controller->advance(from, 0, ByWholeGlyphs, fallbackFonts);
62         float beforeWidth = m_controller->runWidthSoFar();
63         if (m_font.wordSpacing() && from && Font::treatAsSpace(m_run[from]))
64             beforeWidth += m_font.wordSpacing();
65         m_controller->advance(from + len, 0, ByWholeGlyphs, fallbackFonts);
66         float afterWidth = m_controller->runWidthSoFar();
67         return afterWidth - beforeWidth;
68     }
69
70 private:
71     static TextRun constructTextRun(RenderText* text, const Font& font, float xPos)
72     {
73         TextRun run = RenderBlock::constructTextRun(text, font, text, text->style());
74         run.setCharactersLength(text->textLength());
75         ASSERT(run.charactersLength() >= run.length());
76
77         run.setXPos(xPos);
78         return run;
79     }
80
81     // ComplexTextController has only references to its Font and TextRun so they must be kept alive here.
82     Font m_font;
83     TextRun m_run;
84     std::unique_ptr<ComplexTextController> m_controller;
85 };
86
87 PassOwnPtr<TextLayout> Font::createLayout(RenderText* text, float xPos, bool collapseWhiteSpace) const
88 {
89     if (!collapseWhiteSpace || !TextLayout::isNeeded(text, *this))
90         return nullptr;
91     return adoptPtr(new TextLayout(text, *this, xPos));
92 }
93
94 void Font::deleteLayout(TextLayout* layout)
95 {
96     delete layout;
97 }
98
99 float Font::width(TextLayout& layout, unsigned from, unsigned len, HashSet<const SimpleFontData*>* fallbackFonts)
100 {
101     return layout.width(from, len, fallbackFonts);
102 }
103
104 static inline CGFloat roundCGFloat(CGFloat f)
105 {
106     if (sizeof(CGFloat) == sizeof(float))
107         return roundf(static_cast<float>(f));
108     return static_cast<CGFloat>(round(f));
109 }
110
111 static inline CGFloat ceilCGFloat(CGFloat f)
112 {
113     if (sizeof(CGFloat) == sizeof(float))
114         return ceilf(static_cast<float>(f));
115     return static_cast<CGFloat>(ceil(f));
116 }
117
118 ComplexTextController::ComplexTextController(const Font* font, const TextRun& run, bool mayUseNaturalWritingDirection, HashSet<const SimpleFontData*>* fallbackFonts, bool forTextEmphasis)
119     : m_font(*font)
120     , m_run(run)
121     , m_isLTROnly(true)
122     , m_mayUseNaturalWritingDirection(mayUseNaturalWritingDirection)
123     , m_forTextEmphasis(forTextEmphasis)
124     , m_currentCharacter(0)
125     , m_end(run.length())
126     , m_totalWidth(0)
127     , m_runWidthSoFar(0)
128     , m_numGlyphsSoFar(0)
129     , m_currentRun(0)
130     , m_glyphInCurrentRun(0)
131     , m_characterInCurrentGlyph(0)
132     , m_finalRoundingWidth(0)
133     , m_expansion(run.expansion())
134     , m_leadingExpansion(0)
135     , m_afterExpansion(!run.allowsLeadingExpansion())
136     , m_fallbackFonts(fallbackFonts)
137     , m_minGlyphBoundingBoxX(std::numeric_limits<float>::max())
138     , m_maxGlyphBoundingBoxX(std::numeric_limits<float>::min())
139     , m_minGlyphBoundingBoxY(std::numeric_limits<float>::max())
140     , m_maxGlyphBoundingBoxY(std::numeric_limits<float>::min())
141     , m_lastRoundingGlyph(0)
142 {
143     if (!m_expansion)
144         m_expansionPerOpportunity = 0;
145     else {
146         bool isAfterExpansion = m_afterExpansion;
147         unsigned expansionOpportunityCount = Font::expansionOpportunityCount(m_run.text(), m_run.ltr() ? LTR : RTL, isAfterExpansion);
148         if (isAfterExpansion && !m_run.allowsTrailingExpansion())
149             expansionOpportunityCount--;
150
151         if (!expansionOpportunityCount)
152             m_expansionPerOpportunity = 0;
153         else
154             m_expansionPerOpportunity = m_expansion / expansionOpportunityCount;
155     }
156
157     collectComplexTextRuns();
158     adjustGlyphsAndAdvances();
159
160     if (!m_isLTROnly) {
161         m_runIndices.reserveInitialCapacity(m_complexTextRuns.size());
162
163         m_glyphCountFromStartToIndex.reserveInitialCapacity(m_complexTextRuns.size());
164         unsigned glyphCountSoFar = 0;
165         for (unsigned i = 0; i < m_complexTextRuns.size(); ++i) {
166             m_glyphCountFromStartToIndex.uncheckedAppend(glyphCountSoFar);
167             glyphCountSoFar += m_complexTextRuns[i]->glyphCount();
168         }
169     }
170
171     m_runWidthSoFar = m_leadingExpansion;
172 }
173
174 int ComplexTextController::offsetForPosition(float h, bool includePartialGlyphs)
175 {
176     if (h >= m_totalWidth)
177         return m_run.ltr() ? m_end : 0;
178
179     h -= m_leadingExpansion;
180     if (h < 0)
181         return m_run.ltr() ? 0 : m_end;
182
183     CGFloat x = h;
184
185     size_t runCount = m_complexTextRuns.size();
186     size_t offsetIntoAdjustedGlyphs = 0;
187
188     for (size_t r = 0; r < runCount; ++r) {
189         const ComplexTextRun& complexTextRun = *m_complexTextRuns[r];
190         for (unsigned j = 0; j < complexTextRun.glyphCount(); ++j) {
191             size_t index = offsetIntoAdjustedGlyphs + j;
192             CGFloat adjustedAdvance = m_adjustedAdvances[index].width;
193             if (!index)
194                 adjustedAdvance += complexTextRun.initialAdvance().width;
195             if (x < adjustedAdvance) {
196                 CFIndex hitGlyphStart = complexTextRun.indexAt(j);
197                 CFIndex hitGlyphEnd;
198                 if (m_run.ltr())
199                     hitGlyphEnd = std::max<CFIndex>(hitGlyphStart, j + 1 < complexTextRun.glyphCount() ? complexTextRun.indexAt(j + 1) : static_cast<CFIndex>(complexTextRun.indexEnd()));
200                 else
201                     hitGlyphEnd = std::max<CFIndex>(hitGlyphStart, j > 0 ? complexTextRun.indexAt(j - 1) : static_cast<CFIndex>(complexTextRun.indexEnd()));
202
203                 // FIXME: Instead of dividing the glyph's advance equally between the characters, this
204                 // could use the glyph's "ligature carets". However, there is no Core Text API to get the
205                 // ligature carets.
206                 CFIndex hitIndex = hitGlyphStart + (hitGlyphEnd - hitGlyphStart) * (m_run.ltr() ? x / adjustedAdvance : 1 - x / adjustedAdvance);
207                 int stringLength = complexTextRun.stringLength();
208                 TextBreakIterator* cursorPositionIterator = cursorMovementIterator(StringView(complexTextRun.characters(), stringLength));
209                 int clusterStart;
210                 if (isTextBreak(cursorPositionIterator, hitIndex))
211                     clusterStart = hitIndex;
212                 else {
213                     clusterStart = textBreakPreceding(cursorPositionIterator, hitIndex);
214                     if (clusterStart == TextBreakDone)
215                         clusterStart = 0;
216                 }
217
218                 if (!includePartialGlyphs)
219                     return complexTextRun.stringLocation() + clusterStart;
220
221                 int clusterEnd = textBreakFollowing(cursorPositionIterator, hitIndex);
222                 if (clusterEnd == TextBreakDone)
223                     clusterEnd = stringLength;
224
225                 CGFloat clusterWidth;
226                 // FIXME: The search stops at the boundaries of complexTextRun. In theory, it should go on into neighboring ComplexTextRuns
227                 // derived from the same CTLine. In practice, we do not expect there to be more than one CTRun in a CTLine, as no
228                 // reordering and no font fallback should occur within a CTLine.
229                 if (clusterEnd - clusterStart > 1) {
230                     clusterWidth = adjustedAdvance;
231                     int firstGlyphBeforeCluster = j - 1;
232                     while (firstGlyphBeforeCluster >= 0 && complexTextRun.indexAt(firstGlyphBeforeCluster) >= clusterStart && complexTextRun.indexAt(firstGlyphBeforeCluster) < clusterEnd) {
233                         CGFloat width = m_adjustedAdvances[offsetIntoAdjustedGlyphs + firstGlyphBeforeCluster].width;
234                         clusterWidth += width;
235                         x += width;
236                         firstGlyphBeforeCluster--;
237                     }
238                     unsigned firstGlyphAfterCluster = j + 1;
239                     while (firstGlyphAfterCluster < complexTextRun.glyphCount() && complexTextRun.indexAt(firstGlyphAfterCluster) >= clusterStart && complexTextRun.indexAt(firstGlyphAfterCluster) < clusterEnd) {
240                         clusterWidth += m_adjustedAdvances[offsetIntoAdjustedGlyphs + firstGlyphAfterCluster].width;
241                         firstGlyphAfterCluster++;
242                     }
243                 } else {
244                     clusterWidth = adjustedAdvance / (hitGlyphEnd - hitGlyphStart);
245                     x -=  clusterWidth * (m_run.ltr() ? hitIndex - hitGlyphStart : hitGlyphEnd - hitIndex - 1);
246                 }
247                 if (x <= clusterWidth / 2)
248                     return complexTextRun.stringLocation() + (m_run.ltr() ? clusterStart : clusterEnd);
249                 else
250                     return complexTextRun.stringLocation() + (m_run.ltr() ? clusterEnd : clusterStart);
251             }
252             x -= adjustedAdvance;
253         }
254         offsetIntoAdjustedGlyphs += complexTextRun.glyphCount();
255     }
256
257     ASSERT_NOT_REACHED();
258     return 0;
259 }
260
261 static bool advanceByCombiningCharacterSequence(const UChar*& iterator, const UChar* end, UChar32& baseCharacter, unsigned& markCount)
262 {
263     ASSERT(iterator < end);
264
265     markCount = 0;
266
267     unsigned i = 0;
268     unsigned remainingCharacters = end - iterator;
269     U16_NEXT(iterator, i, remainingCharacters, baseCharacter);
270     iterator = iterator + i;
271
272     if (U_IS_SURROGATE(baseCharacter))
273         return false;
274
275     // Consume marks.
276     while (iterator < end) {
277         UChar32 nextCharacter;
278         int markLength = 0;
279         U16_NEXT(iterator, markLength, end - iterator, nextCharacter);
280         if (!(U_GET_GC_MASK(nextCharacter) & U_GC_M_MASK))
281             break;
282         markCount += markLength;
283         iterator += markLength;
284     }
285
286     return true;
287 }
288
289 void ComplexTextController::collectComplexTextRuns()
290 {
291     if (!m_end)
292         return;
293
294     // We break up glyph run generation for the string by FontData.
295     const UChar* cp;
296
297     if (m_run.is8Bit()) {
298         String stringFor8BitRun = String::make16BitFrom8BitSource(m_run.characters8(), m_run.length());
299         cp = stringFor8BitRun.characters16();
300         m_stringsFor8BitRuns.append(stringFor8BitRun);
301     } else
302         cp = m_run.characters16();
303
304     if (m_font.isSmallCaps())
305         m_smallCapsBuffer.resize(m_end);
306
307     unsigned indexOfFontTransition = 0;
308     const UChar* curr = cp;
309     const UChar* end = cp + m_end;
310
311     const SimpleFontData* fontData;
312     bool isMissingGlyph;
313     const SimpleFontData* nextFontData;
314     bool nextIsMissingGlyph;
315
316     unsigned markCount;
317     const UChar* sequenceStart = curr;
318     UChar32 baseCharacter;
319     if (!advanceByCombiningCharacterSequence(curr, end, baseCharacter, markCount))
320         return;
321
322     UChar uppercaseCharacter = 0;
323
324     bool isSmallCaps;
325     bool nextIsSmallCaps = m_font.isSmallCaps() && !(U_GET_GC_MASK(baseCharacter) & U_GC_M_MASK) && (uppercaseCharacter = u_toupper(baseCharacter)) != baseCharacter;
326     ASSERT(uppercaseCharacter == 0 || u_toupper(baseCharacter) <= 0xFFFF);
327
328     if (nextIsSmallCaps) {
329         m_smallCapsBuffer[sequenceStart - cp] = uppercaseCharacter;
330         for (unsigned i = 0; i < markCount; ++i)
331             m_smallCapsBuffer[sequenceStart - cp + i + 1] = sequenceStart[i + 1];
332     }
333
334     nextIsMissingGlyph = false;
335     nextFontData = m_font.fontDataForCombiningCharacterSequence(sequenceStart, curr - sequenceStart, nextIsSmallCaps ? SmallCapsVariant : NormalVariant);
336     if (!nextFontData)
337         nextIsMissingGlyph = true;
338
339     while (curr < end) {
340         fontData = nextFontData;
341         isMissingGlyph = nextIsMissingGlyph;
342         isSmallCaps = nextIsSmallCaps;
343         int index = curr - cp;
344
345         if (!advanceByCombiningCharacterSequence(curr, end, baseCharacter, markCount))
346             return;
347
348         if (m_font.isSmallCaps()) {
349             ASSERT(u_toupper(baseCharacter) <= 0xFFFF);
350             uppercaseCharacter = u_toupper(baseCharacter);
351             nextIsSmallCaps = uppercaseCharacter != baseCharacter;
352             if (nextIsSmallCaps) {
353                 m_smallCapsBuffer[index] = uppercaseCharacter;
354                 for (unsigned i = 0; i < markCount; ++i)
355                     m_smallCapsBuffer[index + i + 1] = cp[index + i + 1];
356             }
357         }
358
359         nextIsMissingGlyph = false;
360         if (baseCharacter == zeroWidthJoiner)
361             nextFontData = fontData;
362         else {
363             nextFontData = m_font.fontDataForCombiningCharacterSequence(cp + index, curr - cp - index, nextIsSmallCaps ? SmallCapsVariant : NormalVariant);
364             if (!nextFontData)
365                 nextIsMissingGlyph = true;
366         }
367
368         if (nextFontData != fontData || nextIsMissingGlyph != isMissingGlyph) {
369             int itemStart = static_cast<int>(indexOfFontTransition);
370             int itemLength = index - indexOfFontTransition;
371             collectComplexTextRunsForCharacters((isSmallCaps ? m_smallCapsBuffer.data() : cp) + itemStart, itemLength, itemStart, !isMissingGlyph ? fontData : 0);
372             indexOfFontTransition = index;
373         }
374     }
375
376     int itemLength = m_end - indexOfFontTransition;
377     if (itemLength) {
378         int itemStart = indexOfFontTransition;
379         collectComplexTextRunsForCharacters((nextIsSmallCaps ? m_smallCapsBuffer.data() : cp) + itemStart, itemLength, itemStart, !nextIsMissingGlyph ? nextFontData : 0);
380     }
381
382     if (!m_run.ltr())
383         m_complexTextRuns.reverse();
384 }
385
386 CFIndex ComplexTextController::ComplexTextRun::indexAt(size_t i) const
387 {
388     ASSERT(i < m_glyphCount);
389
390     return m_coreTextIndices[i];
391 }
392
393 void ComplexTextController::ComplexTextRun::setIsNonMonotonic()
394 {
395     ASSERT(m_isMonotonic);
396     m_isMonotonic = false;
397
398     Vector<bool, 64> mappedIndices(m_stringLength);
399     for (size_t i = 0; i < m_glyphCount; ++i) {
400         ASSERT(indexAt(i) < static_cast<CFIndex>(m_stringLength));
401         mappedIndices[indexAt(i)] = true;
402     }
403
404     m_glyphEndOffsets.grow(m_glyphCount);
405     for (size_t i = 0; i < m_glyphCount; ++i) {
406         CFIndex nextMappedIndex = m_indexEnd;
407         for (size_t j = indexAt(i) + 1; j < m_stringLength; ++j) {
408             if (mappedIndices[j]) {
409                 nextMappedIndex = j;
410                 break;
411             }
412         }
413         m_glyphEndOffsets[i] = nextMappedIndex;
414     }
415 }
416
417 unsigned ComplexTextController::indexOfCurrentRun(unsigned& leftmostGlyph)
418 {
419     leftmostGlyph = 0;
420     
421     size_t runCount = m_complexTextRuns.size();
422     if (m_currentRun >= runCount)
423         return runCount;
424
425     if (m_isLTROnly) {
426         for (unsigned i = 0; i < m_currentRun; ++i)
427             leftmostGlyph += m_complexTextRuns[i]->glyphCount();
428         return m_currentRun;
429     }
430
431     if (m_runIndices.isEmpty()) {
432         unsigned firstRun = 0;
433         unsigned firstRunOffset = stringBegin(*m_complexTextRuns[0]);
434         for (unsigned i = 1; i < runCount; ++i) {
435             unsigned offset = stringBegin(*m_complexTextRuns[i]);
436             if (offset < firstRunOffset) {
437                 firstRun = i;
438                 firstRunOffset = offset;
439             }
440         }
441         m_runIndices.uncheckedAppend(firstRun);
442     }
443
444     while (m_runIndices.size() <= m_currentRun) {
445         unsigned offset = stringEnd(*m_complexTextRuns[m_runIndices.last()]);
446
447         for (unsigned i = 0; i < runCount; ++i) {
448             if (offset == stringBegin(*m_complexTextRuns[i])) {
449                 m_runIndices.uncheckedAppend(i);
450                 break;
451             }
452         }
453     }
454
455     unsigned currentRunIndex = m_runIndices[m_currentRun];
456     leftmostGlyph = m_glyphCountFromStartToIndex[currentRunIndex];
457     return currentRunIndex;
458 }
459
460 unsigned ComplexTextController::incrementCurrentRun(unsigned& leftmostGlyph)
461 {
462     if (m_isLTROnly) {
463         leftmostGlyph += m_complexTextRuns[m_currentRun++]->glyphCount();
464         return m_currentRun;
465     }
466
467     m_currentRun++;
468     leftmostGlyph = 0;
469     return indexOfCurrentRun(leftmostGlyph);
470 }
471
472 void ComplexTextController::advance(unsigned offset, GlyphBuffer* glyphBuffer, GlyphIterationStyle iterationStyle, HashSet<const SimpleFontData*>* fallbackFonts)
473 {
474     if (static_cast<int>(offset) > m_end)
475         offset = m_end;
476
477     if (offset <= m_currentCharacter) {
478         m_runWidthSoFar = m_leadingExpansion;
479         m_numGlyphsSoFar = 0;
480         m_currentRun = 0;
481         m_glyphInCurrentRun = 0;
482         m_characterInCurrentGlyph = 0;
483     }
484
485     m_currentCharacter = offset;
486
487     size_t runCount = m_complexTextRuns.size();
488
489     unsigned leftmostGlyph = 0;
490     unsigned currentRunIndex = indexOfCurrentRun(leftmostGlyph);
491     while (m_currentRun < runCount) {
492         const ComplexTextRun& complexTextRun = *m_complexTextRuns[currentRunIndex];
493         bool ltr = complexTextRun.isLTR();
494         size_t glyphCount = complexTextRun.glyphCount();
495         unsigned g = ltr ? m_glyphInCurrentRun : glyphCount - 1 - m_glyphInCurrentRun;
496         unsigned k = leftmostGlyph + g;
497         if (fallbackFonts && &complexTextRun.fontData() != &m_font.primaryFontData())
498             fallbackFonts->add(&complexTextRun.fontData());
499
500         // We must store the initial advance for the first glyph we are going to draw.
501         // When leftmostGlyph is 0, it represents the first glyph to draw, taking into
502         // account the text direction.
503         if (glyphBuffer && !leftmostGlyph)
504             glyphBuffer->setInitialAdvance(complexTextRun.initialAdvance());
505
506         while (m_glyphInCurrentRun < glyphCount) {
507             unsigned glyphStartOffset = complexTextRun.indexAt(g);
508             unsigned glyphEndOffset;
509             if (complexTextRun.isMonotonic()) {
510                 if (ltr)
511                     glyphEndOffset = std::max<unsigned>(glyphStartOffset, static_cast<unsigned>(g + 1 < glyphCount ? complexTextRun.indexAt(g + 1) : complexTextRun.indexEnd()));
512                 else
513                     glyphEndOffset = std::max<unsigned>(glyphStartOffset, static_cast<unsigned>(g > 0 ? complexTextRun.indexAt(g - 1) : complexTextRun.indexEnd()));
514             } else
515                 glyphEndOffset = complexTextRun.endOffsetAt(g);
516
517             CGSize adjustedAdvance = m_adjustedAdvances[k];
518
519             if (glyphStartOffset + complexTextRun.stringLocation() >= m_currentCharacter)
520                 return;
521
522             if (glyphBuffer && !m_characterInCurrentGlyph)
523                 glyphBuffer->add(m_adjustedGlyphs[k], &complexTextRun.fontData(), adjustedAdvance, complexTextRun.indexAt(m_glyphInCurrentRun));
524
525             unsigned oldCharacterInCurrentGlyph = m_characterInCurrentGlyph;
526             m_characterInCurrentGlyph = std::min(m_currentCharacter - complexTextRun.stringLocation(), glyphEndOffset) - glyphStartOffset;
527             // FIXME: Instead of dividing the glyph's advance equally between the characters, this
528             // could use the glyph's "ligature carets". However, there is no Core Text API to get the
529             // ligature carets.
530             if (glyphStartOffset == glyphEndOffset) {
531                 // When there are multiple glyphs per character we need to advance by the full width of the glyph.
532                 ASSERT(m_characterInCurrentGlyph == oldCharacterInCurrentGlyph);
533                 m_runWidthSoFar += adjustedAdvance.width;
534             } else if (iterationStyle == ByWholeGlyphs) {
535                 if (!oldCharacterInCurrentGlyph)
536                     m_runWidthSoFar += adjustedAdvance.width;
537             } else
538                 m_runWidthSoFar += adjustedAdvance.width * (m_characterInCurrentGlyph - oldCharacterInCurrentGlyph) / (glyphEndOffset - glyphStartOffset);
539
540             if (glyphEndOffset + complexTextRun.stringLocation() > m_currentCharacter)
541                 return;
542
543             m_numGlyphsSoFar++;
544             m_glyphInCurrentRun++;
545             m_characterInCurrentGlyph = 0;
546             if (ltr) {
547                 g++;
548                 k++;
549             } else {
550                 g--;
551                 k--;
552             }
553         }
554         currentRunIndex = incrementCurrentRun(leftmostGlyph);
555         m_glyphInCurrentRun = 0;
556     }
557     if (!m_run.ltr() && m_numGlyphsSoFar == m_adjustedAdvances.size())
558         m_runWidthSoFar += m_finalRoundingWidth;
559 }
560
561 void ComplexTextController::adjustGlyphsAndAdvances()
562 {
563     CGFloat widthSinceLastCommit = 0;
564     size_t runCount = m_complexTextRuns.size();
565     bool hasExtraSpacing = (m_font.letterSpacing() || m_font.wordSpacing() || m_expansion) && !m_run.spacingDisabled();
566     for (size_t r = 0; r < runCount; ++r) {
567         ComplexTextRun& complexTextRun = *m_complexTextRuns[r];
568         unsigned glyphCount = complexTextRun.glyphCount();
569         const SimpleFontData& fontData = complexTextRun.fontData();
570 #if PLATFORM(IOS)
571         bool isEmoji = fontData.platformData().m_isEmoji;
572 #endif
573
574         // Represent the initial advance for a text run by adjusting the advance
575         // of the last glyph of the previous text run in the glyph buffer.
576         if (r && m_adjustedAdvances.size()) {
577             CGSize previousAdvance = m_adjustedAdvances.last();
578             previousAdvance.width += complexTextRun.initialAdvance().width;
579             previousAdvance.height -= complexTextRun.initialAdvance().height;
580             m_adjustedAdvances[m_adjustedAdvances.size() - 1] = previousAdvance;
581         }
582         widthSinceLastCommit += complexTextRun.initialAdvance().width;
583
584         if (!complexTextRun.isLTR())
585             m_isLTROnly = false;
586
587         const CGGlyph* glyphs = complexTextRun.glyphs();
588         const CGSize* advances = complexTextRun.advances();
589
590         bool lastRun = r + 1 == runCount;
591         bool roundsAdvances = !m_font.isPrinterFont() && fontData.platformData().roundsGlyphAdvances();
592         float spaceWidth = fontData.spaceWidth() - fontData.syntheticBoldOffset();
593         CGFloat roundedSpaceWidth = roundCGFloat(spaceWidth);
594         const UChar* cp = complexTextRun.characters();
595         CGPoint glyphOrigin = CGPointZero;
596         CFIndex lastCharacterIndex = m_run.ltr() ? std::numeric_limits<CFIndex>::min() : std::numeric_limits<CFIndex>::max();
597         bool isMonotonic = true;
598
599         for (unsigned i = 0; i < glyphCount; i++) {
600             CFIndex characterIndex = complexTextRun.indexAt(i);
601             if (m_run.ltr()) {
602                 if (characterIndex < lastCharacterIndex)
603                     isMonotonic = false;
604             } else {
605                 if (characterIndex > lastCharacterIndex)
606                     isMonotonic = false;
607             }
608             UChar ch = *(cp + characterIndex);
609             bool lastGlyph = lastRun && i + 1 == glyphCount;
610             UChar nextCh;
611             if (lastGlyph)
612                 nextCh = ' ';
613             else if (i + 1 < glyphCount)
614                 nextCh = *(cp + complexTextRun.indexAt(i + 1));
615             else
616                 nextCh = *(m_complexTextRuns[r + 1]->characters() + m_complexTextRuns[r + 1]->indexAt(0));
617
618             bool treatAsSpace = Font::treatAsSpace(ch);
619             CGGlyph glyph = treatAsSpace ? fontData.spaceGlyph() : glyphs[i];
620             CGSize advance = treatAsSpace ? CGSizeMake(spaceWidth, advances[i].height) : advances[i];
621 #if PLATFORM(IOS)
622             if (isEmoji && advance.width)
623                 advance.width = fontData->widthForGlyph(glyph);
624 #endif
625
626             if (ch == '\t' && m_run.allowTabs())
627                 advance.width = m_font.tabWidth(fontData, m_run.tabSize(), m_run.xPos() + m_totalWidth + widthSinceLastCommit);
628             else if (Font::treatAsZeroWidthSpace(ch) && !treatAsSpace) {
629                 advance.width = 0;
630                 glyph = fontData.spaceGlyph();
631             }
632
633             float roundedAdvanceWidth = roundf(advance.width);
634             if (roundsAdvances)
635                 advance.width = roundedAdvanceWidth;
636
637             advance.width += fontData.syntheticBoldOffset();
638
639  
640             // We special case spaces in two ways when applying word rounding. 
641             // First, we round spaces to an adjusted width in all fonts. 
642             // Second, in fixed-pitch fonts we ensure that all glyphs that 
643             // match the width of the space glyph have the same width as the space glyph. 
644             if (m_run.applyWordRounding() && roundedAdvanceWidth == roundedSpaceWidth && (fontData.pitch() == FixedPitch || glyph == fontData.spaceGlyph()))
645                 advance.width = fontData.adjustedSpaceWidth();
646
647             if (hasExtraSpacing) {
648                 // If we're a glyph with an advance, go ahead and add in letter-spacing.
649                 // That way we weed out zero width lurkers.  This behavior matches the fast text code path.
650                 if (advance.width && m_font.letterSpacing())
651                     advance.width += m_font.letterSpacing();
652
653                 // Handle justification and word-spacing.
654                 if (treatAsSpace || Font::isCJKIdeographOrSymbol(ch)) {
655                     // Distribute the run's total expansion evenly over all expansion opportunities in the run.
656                     if (m_expansion) {
657                         float previousExpansion = m_expansion;
658                         if (!treatAsSpace && !m_afterExpansion) {
659                             // Take the expansion opportunity before this ideograph.
660                             m_expansion -= m_expansionPerOpportunity;
661                             float expansionAtThisOpportunity = !m_run.applyWordRounding() ? m_expansionPerOpportunity : roundf(previousExpansion) - roundf(m_expansion);
662                             m_totalWidth += expansionAtThisOpportunity;
663                             if (m_adjustedAdvances.isEmpty())
664                                 m_leadingExpansion = expansionAtThisOpportunity;
665                             else
666                                 m_adjustedAdvances.last().width += expansionAtThisOpportunity;
667                             previousExpansion = m_expansion;
668                         }
669                         if (!lastGlyph || m_run.allowsTrailingExpansion()) {
670                             m_expansion -= m_expansionPerOpportunity;
671                             advance.width += !m_run.applyWordRounding() ? m_expansionPerOpportunity : roundf(previousExpansion) - roundf(m_expansion);
672                             m_afterExpansion = true;
673                         }
674                     } else
675                         m_afterExpansion = false;
676
677                     // Account for word-spacing.
678                     if (treatAsSpace && (ch != '\t' || !m_run.allowTabs()) && (characterIndex > 0 || r > 0) && m_font.wordSpacing())
679                         advance.width += m_font.wordSpacing();
680                 } else
681                     m_afterExpansion = false;
682             }
683
684             // Apply rounding hacks if needed.
685             // We adjust the width of the last character of a "word" to ensure an integer width. 
686             // Force characters that are used to determine word boundaries for the rounding hack 
687             // to be integer width, so the following words will start on an integer boundary. 
688             if (m_run.applyWordRounding() && Font::isRoundingHackCharacter(ch)) 
689                 advance.width = ceilCGFloat(advance.width); 
690
691             // Check to see if the next character is a "rounding hack character", if so, adjust the 
692             // width so that the total run width will be on an integer boundary. 
693             if ((m_run.applyWordRounding() && !lastGlyph && Font::isRoundingHackCharacter(nextCh)) || (m_run.applyRunRounding() && lastGlyph)) { 
694                 CGFloat totalWidth = widthSinceLastCommit + advance.width; 
695                 widthSinceLastCommit = ceilCGFloat(totalWidth); 
696                 CGFloat extraWidth = widthSinceLastCommit - totalWidth; 
697                 if (m_run.ltr()) 
698                     advance.width += extraWidth; 
699                 else { 
700                     if (m_lastRoundingGlyph) 
701                         m_adjustedAdvances[m_lastRoundingGlyph - 1].width += extraWidth; 
702                     else 
703                         m_finalRoundingWidth = extraWidth; 
704                     m_lastRoundingGlyph = m_adjustedAdvances.size() + 1; 
705                 } 
706                 m_totalWidth += widthSinceLastCommit; 
707                 widthSinceLastCommit = 0; 
708             } else 
709                 widthSinceLastCommit += advance.width; 
710
711             // FIXME: Combining marks should receive a text emphasis mark if they are combine with a space.
712             if (m_forTextEmphasis && (!Font::canReceiveTextEmphasis(ch) || (U_GET_GC_MASK(ch) & U_GC_M_MASK)))
713                 glyph = 0;
714
715             advance.height *= -1;
716             m_adjustedAdvances.append(advance);
717             m_adjustedGlyphs.append(glyph);
718             
719             FloatRect glyphBounds = fontData.boundsForGlyph(glyph);
720             glyphBounds.move(glyphOrigin.x, glyphOrigin.y);
721             m_minGlyphBoundingBoxX = std::min(m_minGlyphBoundingBoxX, glyphBounds.x());
722             m_maxGlyphBoundingBoxX = std::max(m_maxGlyphBoundingBoxX, glyphBounds.maxX());
723             m_minGlyphBoundingBoxY = std::min(m_minGlyphBoundingBoxY, glyphBounds.y());
724             m_maxGlyphBoundingBoxY = std::max(m_maxGlyphBoundingBoxY, glyphBounds.maxY());
725             glyphOrigin.x += advance.width;
726             glyphOrigin.y += advance.height;
727             
728             lastCharacterIndex = characterIndex;
729         }
730         if (!isMonotonic)
731             complexTextRun.setIsNonMonotonic();
732     }
733     m_totalWidth += widthSinceLastCommit;
734 }
735
736 } // namespace WebCore