Speculative 32-bit Mac build fix after r170402.
[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(adoptPtr(new 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     OwnPtr<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;
148         if (m_run.is8Bit())
149             expansionOpportunityCount = Font::expansionOpportunityCount(m_run.characters8(), m_end, m_run.ltr() ? LTR : RTL, isAfterExpansion);
150          else
151              expansionOpportunityCount = Font::expansionOpportunityCount(m_run.characters16(), m_end, m_run.ltr() ? LTR : RTL, isAfterExpansion);
152         if (isAfterExpansion && !m_run.allowsTrailingExpansion())
153             expansionOpportunityCount--;
154
155         if (!expansionOpportunityCount)
156             m_expansionPerOpportunity = 0;
157         else
158             m_expansionPerOpportunity = m_expansion / expansionOpportunityCount;
159     }
160
161     collectComplexTextRuns();
162     adjustGlyphsAndAdvances();
163
164     if (!m_isLTROnly) {
165         m_runIndices.reserveInitialCapacity(m_complexTextRuns.size());
166
167         m_glyphCountFromStartToIndex.reserveInitialCapacity(m_complexTextRuns.size());
168         unsigned glyphCountSoFar = 0;
169         for (unsigned i = 0; i < m_complexTextRuns.size(); ++i) {
170             m_glyphCountFromStartToIndex.uncheckedAppend(glyphCountSoFar);
171             glyphCountSoFar += m_complexTextRuns[i]->glyphCount();
172         }
173     }
174
175     m_runWidthSoFar = m_leadingExpansion;
176 }
177
178 int ComplexTextController::offsetForPosition(float h, bool includePartialGlyphs)
179 {
180     if (h >= m_totalWidth)
181         return m_run.ltr() ? m_end : 0;
182
183     h -= m_leadingExpansion;
184     if (h < 0)
185         return m_run.ltr() ? 0 : m_end;
186
187     CGFloat x = h;
188
189     size_t runCount = m_complexTextRuns.size();
190     size_t offsetIntoAdjustedGlyphs = 0;
191
192     for (size_t r = 0; r < runCount; ++r) {
193         const ComplexTextRun& complexTextRun = *m_complexTextRuns[r];
194         for (unsigned j = 0; j < complexTextRun.glyphCount(); ++j) {
195             size_t index = offsetIntoAdjustedGlyphs + j;
196             CGFloat adjustedAdvance = m_adjustedAdvances[index].width;
197             if (!index)
198                 adjustedAdvance += complexTextRun.initialAdvance().width;
199             if (x < adjustedAdvance) {
200                 CFIndex hitGlyphStart = complexTextRun.indexAt(j);
201                 CFIndex hitGlyphEnd;
202                 if (m_run.ltr())
203                     hitGlyphEnd = std::max<CFIndex>(hitGlyphStart, j + 1 < complexTextRun.glyphCount() ? complexTextRun.indexAt(j + 1) : static_cast<CFIndex>(complexTextRun.indexEnd()));
204                 else
205                     hitGlyphEnd = std::max<CFIndex>(hitGlyphStart, j > 0 ? complexTextRun.indexAt(j - 1) : static_cast<CFIndex>(complexTextRun.indexEnd()));
206
207                 // FIXME: Instead of dividing the glyph's advance equally between the characters, this
208                 // could use the glyph's "ligature carets". However, there is no Core Text API to get the
209                 // ligature carets.
210                 CFIndex hitIndex = hitGlyphStart + (hitGlyphEnd - hitGlyphStart) * (m_run.ltr() ? x / adjustedAdvance : 1 - x / adjustedAdvance);
211                 int stringLength = complexTextRun.stringLength();
212                 TextBreakIterator* cursorPositionIterator = cursorMovementIterator(StringView(complexTextRun.characters(), stringLength));
213                 int clusterStart;
214                 if (isTextBreak(cursorPositionIterator, hitIndex))
215                     clusterStart = hitIndex;
216                 else {
217                     clusterStart = textBreakPreceding(cursorPositionIterator, hitIndex);
218                     if (clusterStart == TextBreakDone)
219                         clusterStart = 0;
220                 }
221
222                 if (!includePartialGlyphs)
223                     return complexTextRun.stringLocation() + clusterStart;
224
225                 int clusterEnd = textBreakFollowing(cursorPositionIterator, hitIndex);
226                 if (clusterEnd == TextBreakDone)
227                     clusterEnd = stringLength;
228
229                 CGFloat clusterWidth;
230                 // FIXME: The search stops at the boundaries of complexTextRun. In theory, it should go on into neighboring ComplexTextRuns
231                 // derived from the same CTLine. In practice, we do not expect there to be more than one CTRun in a CTLine, as no
232                 // reordering and no font fallback should occur within a CTLine.
233                 if (clusterEnd - clusterStart > 1) {
234                     clusterWidth = adjustedAdvance;
235                     int firstGlyphBeforeCluster = j - 1;
236                     while (firstGlyphBeforeCluster >= 0 && complexTextRun.indexAt(firstGlyphBeforeCluster) >= clusterStart && complexTextRun.indexAt(firstGlyphBeforeCluster) < clusterEnd) {
237                         CGFloat width = m_adjustedAdvances[offsetIntoAdjustedGlyphs + firstGlyphBeforeCluster].width;
238                         clusterWidth += width;
239                         x += width;
240                         firstGlyphBeforeCluster--;
241                     }
242                     unsigned firstGlyphAfterCluster = j + 1;
243                     while (firstGlyphAfterCluster < complexTextRun.glyphCount() && complexTextRun.indexAt(firstGlyphAfterCluster) >= clusterStart && complexTextRun.indexAt(firstGlyphAfterCluster) < clusterEnd) {
244                         clusterWidth += m_adjustedAdvances[offsetIntoAdjustedGlyphs + firstGlyphAfterCluster].width;
245                         firstGlyphAfterCluster++;
246                     }
247                 } else {
248                     clusterWidth = adjustedAdvance / (hitGlyphEnd - hitGlyphStart);
249                     x -=  clusterWidth * (m_run.ltr() ? hitIndex - hitGlyphStart : hitGlyphEnd - hitIndex - 1);
250                 }
251                 if (x <= clusterWidth / 2)
252                     return complexTextRun.stringLocation() + (m_run.ltr() ? clusterStart : clusterEnd);
253                 else
254                     return complexTextRun.stringLocation() + (m_run.ltr() ? clusterEnd : clusterStart);
255             }
256             x -= adjustedAdvance;
257         }
258         offsetIntoAdjustedGlyphs += complexTextRun.glyphCount();
259     }
260
261     ASSERT_NOT_REACHED();
262     return 0;
263 }
264
265 static bool advanceByCombiningCharacterSequence(const UChar*& iterator, const UChar* end, UChar32& baseCharacter, unsigned& markCount)
266 {
267     ASSERT(iterator < end);
268
269     markCount = 0;
270
271     unsigned i = 0;
272     unsigned remainingCharacters = end - iterator;
273     U16_NEXT(iterator, i, remainingCharacters, baseCharacter);
274     iterator = iterator + i;
275
276     if (U16_IS_SURROGATE(baseCharacter))
277         return false;
278
279     // Consume marks.
280     while (iterator < end) {
281         UChar32 nextCharacter;
282         int markLength = 0;
283         U16_NEXT(iterator, markLength, end - iterator, nextCharacter);
284         if (!(U_GET_GC_MASK(nextCharacter) & U_GC_M_MASK))
285             break;
286         markCount += markLength;
287         iterator += markLength;
288     }
289
290     return true;
291 }
292
293 void ComplexTextController::collectComplexTextRuns()
294 {
295     if (!m_end)
296         return;
297
298     // We break up glyph run generation for the string by FontData.
299     const UChar* cp;
300
301     if (m_run.is8Bit()) {
302         String stringFor8BitRun = String::make16BitFrom8BitSource(m_run.characters8(), m_run.length());
303         cp = stringFor8BitRun.characters16();
304         m_stringsFor8BitRuns.append(stringFor8BitRun);
305     } else
306         cp = m_run.characters16();
307
308     if (m_font.isSmallCaps())
309         m_smallCapsBuffer.resize(m_end);
310
311     unsigned indexOfFontTransition = 0;
312     const UChar* curr = cp;
313     const UChar* end = cp + m_end;
314
315     const SimpleFontData* fontData;
316     bool isMissingGlyph;
317     const SimpleFontData* nextFontData;
318     bool nextIsMissingGlyph;
319
320     unsigned markCount;
321     const UChar* sequenceStart = curr;
322     UChar32 baseCharacter;
323     if (!advanceByCombiningCharacterSequence(curr, end, baseCharacter, markCount))
324         return;
325
326     UChar uppercaseCharacter = 0;
327
328     bool isSmallCaps;
329     bool nextIsSmallCaps = m_font.isSmallCaps() && !(U_GET_GC_MASK(baseCharacter) & U_GC_M_MASK) && (uppercaseCharacter = u_toupper(baseCharacter)) != baseCharacter;
330     ASSERT(uppercaseCharacter == 0 || u_toupper(baseCharacter) <= 0xFFFF);
331
332     if (nextIsSmallCaps) {
333         m_smallCapsBuffer[sequenceStart - cp] = uppercaseCharacter;
334         for (unsigned i = 0; i < markCount; ++i)
335             m_smallCapsBuffer[sequenceStart - cp + i + 1] = sequenceStart[i + 1];
336     }
337
338     nextIsMissingGlyph = false;
339     nextFontData = m_font.fontDataForCombiningCharacterSequence(sequenceStart, curr - sequenceStart, nextIsSmallCaps ? SmallCapsVariant : NormalVariant);
340     if (!nextFontData)
341         nextIsMissingGlyph = true;
342
343     while (curr < end) {
344         fontData = nextFontData;
345         isMissingGlyph = nextIsMissingGlyph;
346         isSmallCaps = nextIsSmallCaps;
347         int index = curr - cp;
348
349         if (!advanceByCombiningCharacterSequence(curr, end, baseCharacter, markCount))
350             return;
351
352         if (m_font.isSmallCaps()) {
353             ASSERT(u_toupper(baseCharacter) <= 0xFFFF);
354             uppercaseCharacter = u_toupper(baseCharacter);
355             nextIsSmallCaps = uppercaseCharacter != baseCharacter;
356             if (nextIsSmallCaps) {
357                 m_smallCapsBuffer[index] = uppercaseCharacter;
358                 for (unsigned i = 0; i < markCount; ++i)
359                     m_smallCapsBuffer[index + i + 1] = cp[index + i + 1];
360             }
361         }
362
363         nextIsMissingGlyph = false;
364         if (baseCharacter == zeroWidthJoiner)
365             nextFontData = fontData;
366         else {
367             nextFontData = m_font.fontDataForCombiningCharacterSequence(cp + index, curr - cp - index, nextIsSmallCaps ? SmallCapsVariant : NormalVariant);
368             if (!nextFontData)
369                 nextIsMissingGlyph = true;
370         }
371
372         if (nextFontData != fontData || nextIsMissingGlyph != isMissingGlyph) {
373             int itemStart = static_cast<int>(indexOfFontTransition);
374             int itemLength = index - indexOfFontTransition;
375             collectComplexTextRunsForCharacters((isSmallCaps ? m_smallCapsBuffer.data() : cp) + itemStart, itemLength, itemStart, !isMissingGlyph ? fontData : 0);
376             indexOfFontTransition = index;
377         }
378     }
379
380     int itemLength = m_end - indexOfFontTransition;
381     if (itemLength) {
382         int itemStart = indexOfFontTransition;
383         collectComplexTextRunsForCharacters((nextIsSmallCaps ? m_smallCapsBuffer.data() : cp) + itemStart, itemLength, itemStart, !nextIsMissingGlyph ? nextFontData : 0);
384     }
385
386     if (!m_run.ltr())
387         m_complexTextRuns.reverse();
388 }
389
390 CFIndex ComplexTextController::ComplexTextRun::indexAt(size_t i) const
391 {
392     ASSERT(i < m_glyphCount);
393
394     return m_coreTextIndices[i];
395 }
396
397 void ComplexTextController::ComplexTextRun::setIsNonMonotonic()
398 {
399     ASSERT(m_isMonotonic);
400     m_isMonotonic = false;
401
402     Vector<bool, 64> mappedIndices(m_stringLength);
403     for (size_t i = 0; i < m_glyphCount; ++i) {
404         ASSERT(indexAt(i) < static_cast<CFIndex>(m_stringLength));
405         mappedIndices[indexAt(i)] = true;
406     }
407
408     m_glyphEndOffsets.grow(m_glyphCount);
409     for (size_t i = 0; i < m_glyphCount; ++i) {
410         CFIndex nextMappedIndex = m_indexEnd;
411         for (size_t j = indexAt(i) + 1; j < m_stringLength; ++j) {
412             if (mappedIndices[j]) {
413                 nextMappedIndex = j;
414                 break;
415             }
416         }
417         m_glyphEndOffsets[i] = nextMappedIndex;
418     }
419 }
420
421 unsigned ComplexTextController::indexOfCurrentRun(unsigned& leftmostGlyph)
422 {
423     leftmostGlyph = 0;
424     
425     size_t runCount = m_complexTextRuns.size();
426     if (m_currentRun >= runCount)
427         return runCount;
428
429     if (m_isLTROnly) {
430         for (unsigned i = 0; i < m_currentRun; ++i)
431             leftmostGlyph += m_complexTextRuns[i]->glyphCount();
432         return m_currentRun;
433     }
434
435     if (m_runIndices.isEmpty()) {
436         unsigned firstRun = 0;
437         unsigned firstRunOffset = stringBegin(*m_complexTextRuns[0]);
438         for (unsigned i = 1; i < runCount; ++i) {
439             unsigned offset = stringBegin(*m_complexTextRuns[i]);
440             if (offset < firstRunOffset) {
441                 firstRun = i;
442                 firstRunOffset = offset;
443             }
444         }
445         m_runIndices.uncheckedAppend(firstRun);
446     }
447
448     while (m_runIndices.size() <= m_currentRun) {
449         unsigned offset = stringEnd(*m_complexTextRuns[m_runIndices.last()]);
450
451         for (unsigned i = 0; i < runCount; ++i) {
452             if (offset == stringBegin(*m_complexTextRuns[i])) {
453                 m_runIndices.uncheckedAppend(i);
454                 break;
455             }
456         }
457     }
458
459     unsigned currentRunIndex = m_runIndices[m_currentRun];
460     leftmostGlyph = m_glyphCountFromStartToIndex[currentRunIndex];
461     return currentRunIndex;
462 }
463
464 unsigned ComplexTextController::incrementCurrentRun(unsigned& leftmostGlyph)
465 {
466     if (m_isLTROnly) {
467         leftmostGlyph += m_complexTextRuns[m_currentRun++]->glyphCount();
468         return m_currentRun;
469     }
470
471     m_currentRun++;
472     leftmostGlyph = 0;
473     return indexOfCurrentRun(leftmostGlyph);
474 }
475
476 void ComplexTextController::advance(unsigned offset, GlyphBuffer* glyphBuffer, GlyphIterationStyle iterationStyle, HashSet<const SimpleFontData*>* fallbackFonts)
477 {
478     if (static_cast<int>(offset) > m_end)
479         offset = m_end;
480
481     if (offset <= m_currentCharacter) {
482         m_runWidthSoFar = m_leadingExpansion;
483         m_numGlyphsSoFar = 0;
484         m_currentRun = 0;
485         m_glyphInCurrentRun = 0;
486         m_characterInCurrentGlyph = 0;
487     }
488
489     m_currentCharacter = offset;
490
491     size_t runCount = m_complexTextRuns.size();
492
493     unsigned leftmostGlyph = 0;
494     unsigned currentRunIndex = indexOfCurrentRun(leftmostGlyph);
495     while (m_currentRun < runCount) {
496         const ComplexTextRun& complexTextRun = *m_complexTextRuns[currentRunIndex];
497         bool ltr = complexTextRun.isLTR();
498         size_t glyphCount = complexTextRun.glyphCount();
499         unsigned g = ltr ? m_glyphInCurrentRun : glyphCount - 1 - m_glyphInCurrentRun;
500         unsigned k = leftmostGlyph + g;
501         if (fallbackFonts && complexTextRun.fontData() != m_font.primaryFont())
502             fallbackFonts->add(complexTextRun.fontData());
503
504         // We must store the initial advance for the first glyph we are going to draw.
505         // When leftmostGlyph is 0, it represents the first glyph to draw, taking into
506         // account the text direction.
507         if (glyphBuffer && !leftmostGlyph)
508             glyphBuffer->setInitialAdvance(complexTextRun.initialAdvance());
509
510         while (m_glyphInCurrentRun < glyphCount) {
511             unsigned glyphStartOffset = complexTextRun.indexAt(g);
512             unsigned glyphEndOffset;
513             if (complexTextRun.isMonotonic()) {
514                 if (ltr)
515                     glyphEndOffset = std::max<unsigned>(glyphStartOffset, static_cast<unsigned>(g + 1 < glyphCount ? complexTextRun.indexAt(g + 1) : complexTextRun.indexEnd()));
516                 else
517                     glyphEndOffset = std::max<unsigned>(glyphStartOffset, static_cast<unsigned>(g > 0 ? complexTextRun.indexAt(g - 1) : complexTextRun.indexEnd()));
518             } else
519                 glyphEndOffset = complexTextRun.endOffsetAt(g);
520
521             CGSize adjustedAdvance = m_adjustedAdvances[k];
522
523             if (glyphStartOffset + complexTextRun.stringLocation() >= m_currentCharacter)
524                 return;
525
526             if (glyphBuffer && !m_characterInCurrentGlyph)
527                 glyphBuffer->add(m_adjustedGlyphs[k], complexTextRun.fontData(), adjustedAdvance, complexTextRun.indexAt(m_glyphInCurrentRun));
528
529             unsigned oldCharacterInCurrentGlyph = m_characterInCurrentGlyph;
530             m_characterInCurrentGlyph = std::min(m_currentCharacter - complexTextRun.stringLocation(), glyphEndOffset) - glyphStartOffset;
531             // FIXME: Instead of dividing the glyph's advance equally between the characters, this
532             // could use the glyph's "ligature carets". However, there is no Core Text API to get the
533             // ligature carets.
534             if (glyphStartOffset == glyphEndOffset) {
535                 // When there are multiple glyphs per character we need to advance by the full width of the glyph.
536                 ASSERT(m_characterInCurrentGlyph == oldCharacterInCurrentGlyph);
537                 m_runWidthSoFar += adjustedAdvance.width;
538             } else if (iterationStyle == ByWholeGlyphs) {
539                 if (!oldCharacterInCurrentGlyph)
540                     m_runWidthSoFar += adjustedAdvance.width;
541             } else
542                 m_runWidthSoFar += adjustedAdvance.width * (m_characterInCurrentGlyph - oldCharacterInCurrentGlyph) / (glyphEndOffset - glyphStartOffset);
543
544             if (glyphEndOffset + complexTextRun.stringLocation() > m_currentCharacter)
545                 return;
546
547             m_numGlyphsSoFar++;
548             m_glyphInCurrentRun++;
549             m_characterInCurrentGlyph = 0;
550             if (ltr) {
551                 g++;
552                 k++;
553             } else {
554                 g--;
555                 k--;
556             }
557         }
558         currentRunIndex = incrementCurrentRun(leftmostGlyph);
559         m_glyphInCurrentRun = 0;
560     }
561     if (!m_run.ltr() && m_numGlyphsSoFar == m_adjustedAdvances.size())
562         m_runWidthSoFar += m_finalRoundingWidth;
563 }
564
565 void ComplexTextController::adjustGlyphsAndAdvances()
566 {
567     CGFloat widthSinceLastCommit = 0;
568     size_t runCount = m_complexTextRuns.size();
569     bool hasExtraSpacing = (m_font.letterSpacing() || m_font.wordSpacing() || m_expansion) && !m_run.spacingDisabled();
570     for (size_t r = 0; r < runCount; ++r) {
571         ComplexTextRun& complexTextRun = *m_complexTextRuns[r];
572         unsigned glyphCount = complexTextRun.glyphCount();
573         const SimpleFontData* fontData = complexTextRun.fontData();
574 #if PLATFORM(IOS)
575         bool isEmoji = fontData->platformData().m_isEmoji;
576 #endif
577
578         // Represent the initial advance for a text run by adjusting the advance
579         // of the last glyph of the previous text run in the glyph buffer.
580         if (r && m_adjustedAdvances.size()) {
581             CGSize previousAdvance = m_adjustedAdvances.last();
582             previousAdvance.width += complexTextRun.initialAdvance().width;
583             previousAdvance.height -= complexTextRun.initialAdvance().height;
584             m_adjustedAdvances[m_adjustedAdvances.size() - 1] = previousAdvance;
585         }
586         widthSinceLastCommit += complexTextRun.initialAdvance().width;
587
588         if (!complexTextRun.isLTR())
589             m_isLTROnly = false;
590
591         const CGGlyph* glyphs = complexTextRun.glyphs();
592         const CGSize* advances = complexTextRun.advances();
593
594         bool lastRun = r + 1 == runCount;
595         bool roundsAdvances = !m_font.isPrinterFont() && fontData->platformData().roundsGlyphAdvances();
596         float spaceWidth = fontData->spaceWidth() - fontData->syntheticBoldOffset();
597         CGFloat roundedSpaceWidth = roundCGFloat(spaceWidth);
598         const UChar* cp = complexTextRun.characters();
599         CGPoint glyphOrigin = CGPointZero;
600         CFIndex lastCharacterIndex = m_run.ltr() ? std::numeric_limits<CFIndex>::min() : std::numeric_limits<CFIndex>::max();
601         bool isMonotonic = true;
602
603         for (unsigned i = 0; i < glyphCount; i++) {
604             CFIndex characterIndex = complexTextRun.indexAt(i);
605             if (m_run.ltr()) {
606                 if (characterIndex < lastCharacterIndex)
607                     isMonotonic = false;
608             } else {
609                 if (characterIndex > lastCharacterIndex)
610                     isMonotonic = false;
611             }
612             UChar ch = *(cp + characterIndex);
613             bool lastGlyph = lastRun && i + 1 == glyphCount;
614             UChar nextCh;
615             if (lastGlyph)
616                 nextCh = ' ';
617             else if (i + 1 < glyphCount)
618                 nextCh = *(cp + complexTextRun.indexAt(i + 1));
619             else
620                 nextCh = *(m_complexTextRuns[r + 1]->characters() + m_complexTextRuns[r + 1]->indexAt(0));
621
622             bool treatAsSpace = Font::treatAsSpace(ch);
623             CGGlyph glyph = treatAsSpace ? fontData->spaceGlyph() : glyphs[i];
624             CGSize advance = treatAsSpace ? CGSizeMake(spaceWidth, advances[i].height) : advances[i];
625 #if PLATFORM(IOS)
626             if (isEmoji && advance.width)
627                 advance.width = fontData->widthForGlyph(glyph);
628 #endif
629
630             if (ch == '\t' && m_run.allowTabs())
631                 advance.width = m_font.tabWidth(*fontData, m_run.tabSize(), m_run.xPos() + m_totalWidth + widthSinceLastCommit);
632             else if (Font::treatAsZeroWidthSpace(ch) && !treatAsSpace) {
633                 advance.width = 0;
634                 glyph = fontData->spaceGlyph();
635             }
636
637             float roundedAdvanceWidth = roundf(advance.width);
638             if (roundsAdvances)
639                 advance.width = roundedAdvanceWidth;
640
641             advance.width += fontData->syntheticBoldOffset();
642
643  
644             // We special case spaces in two ways when applying word rounding. 
645             // First, we round spaces to an adjusted width in all fonts. 
646             // Second, in fixed-pitch fonts we ensure that all glyphs that 
647             // match the width of the space glyph have the same width as the space glyph. 
648             if (m_run.applyWordRounding() && roundedAdvanceWidth == roundedSpaceWidth && (fontData->pitch() == FixedPitch || glyph == fontData->spaceGlyph()))
649                 advance.width = fontData->adjustedSpaceWidth();
650
651             if (hasExtraSpacing) {
652                 // If we're a glyph with an advance, go ahead and add in letter-spacing.
653                 // That way we weed out zero width lurkers.  This behavior matches the fast text code path.
654                 if (advance.width && m_font.letterSpacing())
655                     advance.width += m_font.letterSpacing();
656
657                 // Handle justification and word-spacing.
658                 if (treatAsSpace || Font::isCJKIdeographOrSymbol(ch)) {
659                     // Distribute the run's total expansion evenly over all expansion opportunities in the run.
660                     if (m_expansion) {
661                         float previousExpansion = m_expansion;
662                         if (!treatAsSpace && !m_afterExpansion) {
663                             // Take the expansion opportunity before this ideograph.
664                             m_expansion -= m_expansionPerOpportunity;
665                             float expansionAtThisOpportunity = !m_run.applyWordRounding() ? m_expansionPerOpportunity : roundf(previousExpansion) - roundf(m_expansion);
666                             m_totalWidth += expansionAtThisOpportunity;
667                             if (m_adjustedAdvances.isEmpty())
668                                 m_leadingExpansion = expansionAtThisOpportunity;
669                             else
670                                 m_adjustedAdvances.last().width += expansionAtThisOpportunity;
671                             previousExpansion = m_expansion;
672                         }
673                         if (!lastGlyph || m_run.allowsTrailingExpansion()) {
674                             m_expansion -= m_expansionPerOpportunity;
675                             advance.width += !m_run.applyWordRounding() ? m_expansionPerOpportunity : roundf(previousExpansion) - roundf(m_expansion);
676                             m_afterExpansion = true;
677                         }
678                     } else
679                         m_afterExpansion = false;
680
681                     // Account for word-spacing.
682                     if (treatAsSpace && (ch != '\t' || !m_run.allowTabs()) && (characterIndex > 0 || r > 0) && m_font.wordSpacing())
683                         advance.width += m_font.wordSpacing();
684                 } else
685                     m_afterExpansion = false;
686             }
687
688             // Apply rounding hacks if needed.
689             // We adjust the width of the last character of a "word" to ensure an integer width. 
690             // Force characters that are used to determine word boundaries for the rounding hack 
691             // to be integer width, so the following words will start on an integer boundary. 
692             if (m_run.applyWordRounding() && Font::isRoundingHackCharacter(ch)) 
693                 advance.width = ceilCGFloat(advance.width); 
694
695             // Check to see if the next character is a "rounding hack character", if so, adjust the 
696             // width so that the total run width will be on an integer boundary. 
697             if ((m_run.applyWordRounding() && !lastGlyph && Font::isRoundingHackCharacter(nextCh)) || (m_run.applyRunRounding() && lastGlyph)) { 
698                 CGFloat totalWidth = widthSinceLastCommit + advance.width; 
699                 widthSinceLastCommit = ceilCGFloat(totalWidth); 
700                 CGFloat extraWidth = widthSinceLastCommit - totalWidth; 
701                 if (m_run.ltr()) 
702                     advance.width += extraWidth; 
703                 else { 
704                     if (m_lastRoundingGlyph) 
705                         m_adjustedAdvances[m_lastRoundingGlyph - 1].width += extraWidth; 
706                     else 
707                         m_finalRoundingWidth = extraWidth; 
708                     m_lastRoundingGlyph = m_adjustedAdvances.size() + 1; 
709                 } 
710                 m_totalWidth += widthSinceLastCommit; 
711                 widthSinceLastCommit = 0; 
712             } else 
713                 widthSinceLastCommit += advance.width; 
714
715             // FIXME: Combining marks should receive a text emphasis mark if they are combine with a space.
716             if (m_forTextEmphasis && (!Font::canReceiveTextEmphasis(ch) || (U_GET_GC_MASK(ch) & U_GC_M_MASK)))
717                 glyph = 0;
718
719             advance.height *= -1;
720             m_adjustedAdvances.append(advance);
721             m_adjustedGlyphs.append(glyph);
722             
723             FloatRect glyphBounds = fontData->boundsForGlyph(glyph);
724             glyphBounds.move(glyphOrigin.x, glyphOrigin.y);
725             m_minGlyphBoundingBoxX = std::min(m_minGlyphBoundingBoxX, glyphBounds.x());
726             m_maxGlyphBoundingBoxX = std::max(m_maxGlyphBoundingBoxX, glyphBounds.maxX());
727             m_minGlyphBoundingBoxY = std::min(m_minGlyphBoundingBoxY, glyphBounds.y());
728             m_maxGlyphBoundingBoxY = std::max(m_maxGlyphBoundingBoxY, glyphBounds.maxY());
729             glyphOrigin.x += advance.width;
730             glyphOrigin.y += advance.height;
731             
732             lastCharacterIndex = characterIndex;
733         }
734         if (!isMonotonic)
735             complexTextRun.setIsNonMonotonic();
736     }
737     m_totalWidth += widthSinceLastCommit;
738 }
739
740 } // namespace WebCore