62878d3ef789ed666bfbc0b315fb51246c3a202c
[WebKit-https.git] / WebCore / platform / Font.cpp
1 /**
2  * This file is part of the html renderer for KDE.
3  *
4  * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
5  *           (C) 1999 Antti Koivisto (koivisto@kde.org)
6  *           (C) 2000 Dirk Mueller (mueller@kde.org)
7  * Copyright (C) 2003, 2006 Apple Computer, Inc.
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Library General Public
11  * License as published by the Free Software Foundation; either
12  * version 2 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Library General Public License for more details.
18  *
19  * You should have received a copy of the GNU Library General Public License
20  * along with this library; see the file COPYING.LIB.  If not, write to
21  * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22  * Boston, MA 02111-1307, USA.
23  *
24  */
25
26 #include "config.h"
27 #include "Font.h"
28
29 #include "CharacterNames.h"
30 #include "FloatRect.h"
31 #include "FontCache.h"
32 #include "FontFallbackList.h"
33 #include "IntPoint.h"
34 #include "GlyphBuffer.h"
35 #include "TextStyle.h"
36 #include <wtf/unicode/Unicode.h>
37 #include <wtf/MathExtras.h>
38
39 #if USE(ICU_UNICODE)
40 #include <unicode/unorm.h>
41 #endif
42
43 using namespace WTF;
44 using namespace Unicode;
45
46 namespace WebCore {
47
48 // According to http://www.unicode.org/Public/UNIDATA/UCD.html#Canonical_Combining_Class_Values
49 const uint8_t hiraganaKatakanaVoicingMarksCombiningClass = 8;
50
51 const uint8_t Font::gRoundingHackCharacterTable[256] = {
52     0, 0, 0, 0, 0, 0, 0, 0, 0, 1 /*\t*/, 1 /*\n*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
53     1 /*space*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 /*-*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 /*?*/,
54     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
55     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
56     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
57     1 /*no-break space*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
58     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
59     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
60 };
61
62 Font::CodePath Font::codePath = Auto;
63
64 struct WidthIterator {
65     WidthIterator(const Font* font, const TextRun& run, const TextStyle& style);
66
67     void advance(int to, GlyphBuffer* glyphBuffer = 0);
68     bool advanceOneCharacter(float& width, GlyphBuffer* glyphBuffer = 0);
69     
70     const Font* m_font;
71
72     const TextRun& m_run;
73     int m_end;
74
75     const TextStyle& m_style;
76     
77     unsigned m_currentCharacter;
78     float m_runWidthSoFar;
79     float m_widthToStart;
80     float m_padding;
81     float m_padPerSpace;
82     float m_finalRoundingWidth;
83     
84 private:
85     UChar32 normalizeVoicingMarks(int currentCharacter);
86 };
87
88 WidthIterator::WidthIterator(const Font* font, const TextRun& run, const TextStyle& style)
89     : m_font(font)
90     , m_run(run)
91     , m_end(style.rtl() ? run.length() : run.to())
92     , m_style(style)
93     , m_currentCharacter(run.from())
94     , m_runWidthSoFar(0)
95     , m_finalRoundingWidth(0)
96 {
97     // If the padding is non-zero, count the number of spaces in the run
98     // and divide that by the padding for per space addition.
99     m_padding = m_style.padding();
100     if (!m_padding)
101         m_padPerSpace = 0;
102     else {
103         float numSpaces = 0;
104         for (int i = run.from(); i < m_end; i++)
105             if (Font::treatAsSpace(m_run[i]))
106                 numSpaces++;
107
108         if (numSpaces == 0)
109             m_padPerSpace = 0;
110         else
111             m_padPerSpace = ceilf(m_style.padding() / numSpaces);
112     }
113     
114     // Calculate width up to starting position of the run.  This is
115     // necessary to ensure that our rounding hacks are always consistently
116     // applied.
117     if (run.from() == 0)
118         m_widthToStart = 0;
119     else {
120         TextRun completeRun(run);
121         completeRun.makeComplete();
122         WidthIterator startPositionIterator(font, completeRun, style);
123         startPositionIterator.advance(run.from());
124         m_widthToStart = startPositionIterator.m_runWidthSoFar;
125     }
126 }
127
128 void WidthIterator::advance(int offset, GlyphBuffer* glyphBuffer)
129 {
130     if (offset > m_end)
131         offset = m_end;
132
133     int currentCharacter = m_currentCharacter;
134     const UChar* cp = m_run.data(currentCharacter);
135
136     bool rtl = m_style.rtl();
137     bool attemptFontSubstitution = m_style.attemptFontSubstitution();
138     bool hasExtraSpacing = m_font->letterSpacing() || m_font->wordSpacing() || m_padding;
139
140     float runWidthSoFar = m_runWidthSoFar;
141     float lastRoundingWidth = m_finalRoundingWidth;
142     
143     while (currentCharacter < offset) {
144         UChar32 c = *cp;
145         unsigned clusterLength = 1;
146         if (c >= 0x3041) {
147             if (c <= 0x30FE) {
148                 // Deal with Hiragana and Katakana voiced and semi-voiced syllables.
149                 // Normalize into composed form, and then look for glyph with base + combined mark.
150                 // Check above for character range to minimize performance impact.
151                 UChar32 normalized = normalizeVoicingMarks(currentCharacter);
152                 if (normalized) {
153                     c = normalized;
154                     clusterLength = 2;
155                 }
156             } else if (U16_IS_SURROGATE(c)) {
157                 if (!U16_IS_SURROGATE_LEAD(c))
158                     break;
159
160                 // Do we have a surrogate pair?  If so, determine the full Unicode (32 bit)
161                 // code point before glyph lookup.
162                 // Make sure we have another character and it's a low surrogate.
163                 if (currentCharacter + 1 >= m_run.length())
164                     break;
165                 UChar low = cp[1];
166                 if (!U16_IS_TRAIL(low))
167                     break;
168                 c = U16_GET_SUPPLEMENTARY(c, low);
169                 clusterLength = 2;
170             }
171         }
172
173         const GlyphData& glyphData = m_font->glyphDataForCharacter(c, cp, clusterLength, rtl, attemptFontSubstitution);
174         Glyph glyph = glyphData.glyph;
175         const FontData* fontData = glyphData.fontData;
176
177         ASSERT(fontData);
178
179         // Now that we have a glyph and font data, get its width.
180         float width;
181         if (c == '\t' && m_style.tabWidth())
182             width = m_style.tabWidth() - fmodf(m_style.xPos() + runWidthSoFar, m_style.tabWidth());
183         else {
184             width = fontData->widthForGlyph(glyph);
185             // We special case spaces in two ways when applying word rounding.
186             // First, we round spaces to an adjusted width in all fonts.
187             // Second, in fixed-pitch fonts we ensure that all characters that
188             // match the width of the space character have the same width as the space character.
189             if (width == fontData->m_spaceWidth && (fontData->m_treatAsFixedPitch || glyph == fontData->m_spaceGlyph) && m_style.applyWordRounding())
190                 width = fontData->m_adjustedSpaceWidth;
191         }
192
193         if (hasExtraSpacing) {
194             // Account for letter-spacing.
195             if (width && m_font->letterSpacing())
196                 width += m_font->letterSpacing();
197
198             if (Font::treatAsSpace(c)) {
199                 // Account for padding. WebCore uses space padding to justify text.
200                 // We distribute the specified padding over the available spaces in the run.
201                 if (m_padding) {
202                     // Use left over padding if not evenly divisible by number of spaces.
203                     if (m_padding < m_padPerSpace) {
204                         width += m_padding;
205                         m_padding = 0;
206                     } else {
207                         width += m_padPerSpace;
208                         m_padding -= m_padPerSpace;
209                     }
210                 }
211
212                 // Account for word spacing.
213                 // We apply additional space between "words" by adding width to the space character.
214                 if (currentCharacter != 0 && !Font::treatAsSpace(cp[-1]) && m_font->wordSpacing())
215                     width += m_font->wordSpacing();
216             }
217         }
218
219         // Advance past the character we just dealt with.
220         cp += clusterLength;
221         currentCharacter += clusterLength;
222
223         // Account for float/integer impedance mismatch between CG and KHTML. "Words" (characters 
224         // followed by a character defined by isRoundingHackCharacter()) are always an integer width.
225         // We adjust the width of the last character of a "word" to ensure an integer width.
226         // If we move KHTML to floats we can remove this (and related) hacks.
227
228         float oldWidth = width;
229
230         // Force characters that are used to determine word boundaries for the rounding hack
231         // to be integer width, so following words will start on an integer boundary.
232         if (m_style.applyWordRounding() && Font::isRoundingHackCharacter(c))
233             width = ceilf(width);
234
235         // Check to see if the next character is a "rounding hack character", if so, adjust
236         // width so that the total run width will be on an integer boundary.
237         if ((m_style.applyWordRounding() && currentCharacter < m_run.length() && Font::isRoundingHackCharacter(*cp))
238                 || (m_style.applyRunRounding() && currentCharacter >= m_end)) {
239             float totalWidth = m_widthToStart + runWidthSoFar + width;
240             width += ceilf(totalWidth) - totalWidth;
241         }
242
243         runWidthSoFar += width;
244
245         if (glyphBuffer)
246             glyphBuffer->add(glyph, fontData, (rtl ? oldWidth + lastRoundingWidth : width));
247
248         lastRoundingWidth = width - oldWidth;
249     }
250
251     m_currentCharacter = currentCharacter;
252     m_runWidthSoFar = runWidthSoFar;
253     m_finalRoundingWidth = lastRoundingWidth;
254 }
255
256 bool WidthIterator::advanceOneCharacter(float& width, GlyphBuffer* glyphBuffer)
257 {
258     glyphBuffer->clear();
259     advance(m_currentCharacter + 1, glyphBuffer);
260     float w = 0;
261     for (int i = 0; i < glyphBuffer->size(); ++i)
262         w += glyphBuffer->advanceAt(i);
263     width = w;
264     return !glyphBuffer->isEmpty();
265 }
266
267 UChar32 WidthIterator::normalizeVoicingMarks(int currentCharacter)
268 {
269     if (currentCharacter + 1 < m_end) {
270         if (combiningClass(m_run[currentCharacter + 1]) == hiraganaKatakanaVoicingMarksCombiningClass) {
271 #if USE(ICU_UNICODE)
272             // Normalize into composed form using 3.2 rules.
273             UChar normalizedCharacters[2] = { 0, 0 };
274             UErrorCode uStatus = U_ZERO_ERROR;  
275             int32_t resultLength = unorm_normalize(m_run.data(currentCharacter), 2,
276                 UNORM_NFC, UNORM_UNICODE_3_2, &normalizedCharacters[0], 2, &uStatus);
277             if (resultLength == 1 && uStatus == 0)
278                 return normalizedCharacters[0];
279 #elif USE(QT4_UNICODE)
280             QString tmp(reinterpret_cast<const QChar*>(m_run.data(currentCharacter)), 2);
281             QString res = tmp.normalized(QString::NormalizationForm_C, QChar::Unicode_3_2);
282             if (res.length() == 1)
283                 return res.at(0).unicode();
284 #endif
285         }
286     }
287     return 0;
288 }
289
290 // ============================================================================================
291 // Font Implementation (Cross-Platform Portion)
292 // ============================================================================================
293
294 Font::Font() :m_fontList(0), m_letterSpacing(0), m_wordSpacing(0)
295 {}
296
297 Font::Font(const FontDescription& fd, short letterSpacing, short wordSpacing) 
298 : m_fontDescription(fd),
299   m_fontList(0),
300   m_pageZero(0),
301   m_letterSpacing(letterSpacing),
302   m_wordSpacing(wordSpacing)
303 {}
304
305 Font::Font(const FontPlatformData& fontData, bool isPrinterFont)
306     : m_pageZero(0)
307     , m_letterSpacing(0)
308     , m_wordSpacing(0)
309 {
310     m_fontDescription.setUsePrinterFont(isPrinterFont);
311     m_fontList = new FontFallbackList();
312     m_fontList->setPlatformFont(fontData);
313 }
314
315 Font::Font(const Font& other)
316 {
317     m_fontDescription = other.m_fontDescription;
318     m_fontList = other.m_fontList;
319     m_letterSpacing = other.m_letterSpacing;
320     m_wordSpacing = other.m_wordSpacing;
321     m_pages = other.m_pages;
322     m_pageZero = other.m_pageZero;
323 }
324
325 Font& Font::operator=(const Font& other)
326 {
327     if (&other != this) {
328         m_fontDescription = other.m_fontDescription;
329         m_fontList = other.m_fontList;
330         m_pages = other.m_pages;
331         m_pageZero = other.m_pageZero;
332         m_letterSpacing = other.m_letterSpacing;
333         m_wordSpacing = other.m_wordSpacing;
334     }
335     return *this;
336 }
337
338 Font::~Font()
339 {
340 }
341
342 // FIXME: It is unfortunate that this function needs to be passed the original cluster.
343 // It is only required for the platform's FontCache::getFontDataForCharacters(), and it means
344 // that this function is not correct if it transforms the character to uppercase and calls
345 // FontCache::getFontDataForCharacters() afterwards.
346 const GlyphData& Font::glyphDataForCharacter(UChar32 c, const UChar* cluster, unsigned clusterLength, bool mirror, bool attemptFontSubstitution) const
347 {
348     bool smallCaps = false;
349
350     if (m_fontDescription.smallCaps() && !Unicode::isUpper(c)) {
351         // Convert lowercase to upper.
352         UChar32 upperC = Unicode::toUpper(c);
353         if (upperC != c) {
354             c = upperC;
355             smallCaps = true;
356         }
357     }
358
359     if (mirror)
360         c = mirroredChar(c);
361
362     unsigned pageNumber = (c / GlyphPage::size);
363
364     GlyphPageTreeNode* node = pageNumber ? m_pages.get(pageNumber) : m_pageZero;
365     if (!node) {
366         node = GlyphPageTreeNode::getRootChild(primaryFont(), pageNumber);
367         if (pageNumber)
368             m_pages.set(pageNumber, node);
369         else
370             m_pageZero = node;
371     }
372
373     if (!attemptFontSubstitution && node->level() != 1)
374         node = GlyphPageTreeNode::getRootChild(primaryFont(), pageNumber);
375
376     while (true) {
377         GlyphPage* page = node->page();
378
379         if (page) {
380             const GlyphData& data = page->glyphDataForCharacter(c);
381             if (data.glyph || !attemptFontSubstitution) {
382                 if (!smallCaps)
383                     return data;
384
385                 const FontData* smallCapsFontData = data.fontData->smallCapsFontData(m_fontDescription);
386
387                 if (!smallCapsFontData)
388                     // This should not happen, but if it does, we will return a big cap.
389                     return data;
390
391                 GlyphPageTreeNode* smallCapsNode = GlyphPageTreeNode::getRootChild(smallCapsFontData, pageNumber);
392                 GlyphPage* smallCapsPage = smallCapsNode->page();
393
394                 if (smallCapsPage) {
395                     const GlyphData& data = smallCapsPage->glyphDataForCharacter(c);
396                     if (data.glyph || !attemptFontSubstitution)
397                         return data;
398                 }
399                 // Not attempting system fallback off the smallCapsFontData. This is the very unlikely case that
400                 // a font has the lowercase character but not its uppercase version.
401                 return smallCapsFontData->missingGlyphData();
402             }
403         } else if (!attemptFontSubstitution) {
404             if (smallCaps) {
405                 if (const FontData* smallCapsFontData = primaryFont()->smallCapsFontData(m_fontDescription))
406                     return smallCapsFontData->missingGlyphData();
407             }
408             return primaryFont()->missingGlyphData();
409         }
410
411         if (node->isSystemFallback()) {
412             // System fallback is character-dependent.
413             // Convert characters that shouldn't render to zero width spaces when asking what font is
414             // appropriate.
415             const FontData* characterFontData;
416             if (clusterLength == 1 && Font::treatAsZeroWidthSpace(cluster[0]))
417                 characterFontData = FontCache::getFontDataForCharacters(*this, &zeroWidthSpace, 1);
418             else
419                 characterFontData = FontCache::getFontDataForCharacters(*this, cluster, clusterLength);
420             if (smallCaps)
421                 characterFontData = characterFontData->smallCapsFontData(m_fontDescription);
422             if (characterFontData) {
423                 GlyphPage* fallbackPage = GlyphPageTreeNode::getRootChild(characterFontData, pageNumber)->page();
424                 const GlyphData& data = fallbackPage ? fallbackPage->glyphDataForCharacter(c) : characterFontData->missingGlyphData();
425                 if (!smallCaps)
426                     page->setGlyphDataForCharacter(c, data.glyph, characterFontData);
427                 return data;
428             }
429             // Even system fallback can fail.
430             // FIXME: Should the last resort font be used?
431             const GlyphData& data = primaryFont()->missingGlyphData();
432             if (!smallCaps)
433                 page->setGlyphDataForCharacter(c, data.glyph, data.fontData);
434             return data;
435         }
436
437         // Proceed with the fallback list.
438         const FontData* fontData = fontDataAt(node->level());
439         node = node->getChild(fontData, pageNumber);
440
441         if (pageNumber)
442             m_pages.set(pageNumber, node);
443         else
444             m_pageZero = node;
445     }
446
447 }
448
449 const FontData* Font::primaryFont() const
450 {
451     ASSERT(m_fontList);
452     return m_fontList->primaryFont(this);
453 }
454
455 const FontData* Font::fontDataAt(unsigned index) const
456 {
457     ASSERT(m_fontList);
458     return m_fontList->fontDataAt(this, index);
459 }
460
461 const FontData* Font::fontDataForCharacters(const UChar* characters, int length) const
462 {
463     ASSERT(m_fontList);
464     return m_fontList->fontDataForCharacters(this, characters, length);
465 }
466
467 void Font::update() const
468 {
469     // FIXME: It is pretty crazy that we are willing to just poke into a RefPtr, but it ends up 
470     // being reasonably safe (because inherited fonts in the render tree pick up the new
471     // style anyway.  Other copies are transient, e.g., the state in the GraphicsContext, and
472     // won't stick around long enough to get you in trouble).  Still, this is pretty disgusting,
473     // and could eventually be rectified by using RefPtrs for Fonts themselves.
474     if (!m_fontList)
475         m_fontList = new FontFallbackList();
476     m_fontList->invalidate();
477     m_pageZero = 0;
478     m_pages.clear();
479 }
480
481 int Font::width(const TextRun& run) const
482 {
483     return width(run, TextStyle());
484 }
485
486 int Font::width(const TextRun& run, const TextStyle& style) const
487 {
488     return lroundf(floatWidth(run, style));
489 }
490
491 int Font::ascent() const
492 {
493     return primaryFont()->ascent();
494 }
495
496 int Font::descent() const
497 {
498     return primaryFont()->descent();
499 }
500
501 int Font::lineSpacing() const
502 {
503     return primaryFont()->lineSpacing();
504 }
505
506 float Font::xHeight() const
507 {
508     return primaryFont()->xHeight();
509 }
510
511 bool Font::isFixedPitch() const
512 {
513     ASSERT(m_fontList);
514     return m_fontList->isFixedPitch(this);
515 }
516
517 void Font::setCodePath(CodePath p)
518 {
519     codePath = p;
520 }
521
522 bool Font::canUseGlyphCache(const TextRun& run) const
523 {
524     switch (codePath) {
525         case Auto:
526             break;
527         case Simple:
528             return true;
529         case Complex:
530             return false;
531     }
532     
533     // Start from 0 since drawing and highlighting also measure the characters before run->from
534     for (int i = 0; i < run.to(); i++) {
535         const UChar c = run[i];
536         if (c < 0x300)      // U+0300 through U+036F Combining diacritical marks
537             continue;
538         if (c <= 0x36F)
539             return false;
540
541         if (c < 0x0591 || c == 0x05BE)     // U+0591 through U+05CF excluding U+05BE Hebrew combining marks, Hebrew punctuation Paseq, Sof Pasuq and Nun Hafukha
542             continue;
543         if (c <= 0x05CF)
544             return false;
545
546         if (c < 0x0600)     // U+0600 through U+1059 Arabic, Syriac, Thaana, Devanagari, Bengali, Gurmukhi, Gujarati, Oriya, Tamil, Telugu, Kannada, Malayalam, Sinhala, Thai, Lao, Tibetan, Myanmar
547             continue;
548         if (c <= 0x1059)
549             return false;
550
551         if (c < 0x1100)     // U+1100 through U+11FF Hangul Jamo (only Ancient Korean should be left here if you precompose; Modern Korean will be precomposed as a result of step A)
552             continue;
553         if (c <= 0x11FF)
554             return false;
555
556         if (c < 0x1780)     // U+1780 through U+18AF Khmer, Mongolian
557             continue;
558         if (c <= 0x18AF)
559             return false;
560
561         if (c < 0x1900)     // U+1900 through U+194F Limbu (Unicode 4.0)
562             continue;
563         if (c <= 0x194F)
564             return false;
565
566         if (c < 0x20D0)     // U+20D0 through U+20FF Combining marks for symbols
567             continue;
568         if (c <= 0x20FF)
569             return false;
570
571         if (c < 0xFE20)     // U+FE20 through U+FE2F Combining half marks
572             continue;
573         if (c <= 0xFE2F)
574             return false;
575     }
576
577     return true;
578
579 }
580
581 void Font::drawSimpleText(GraphicsContext* context, const TextRun& run, const TextStyle& style, const FloatPoint& point) const
582 {
583     // This glyph buffer holds our glyphs+advances+font data for each glyph.
584     GlyphBuffer glyphBuffer;
585
586     // Our measuring code will generate glyphs and advances for us.
587     float startX;
588     floatWidthForSimpleText(run, style, &startX, &glyphBuffer);
589     
590     // We couldn't generate any glyphs for the run.  Give up.
591     if (glyphBuffer.isEmpty())
592         return;
593
594     // Swap the order of the glyphs if right-to-left.
595     if (style.rtl())
596         for (int i = 0, end = glyphBuffer.size() - 1; i < glyphBuffer.size() / 2; ++i, --end)
597             glyphBuffer.swap(i, end);
598
599     // Calculate the starting point of the glyphs to be displayed by adding
600     // all the advances up to the first glyph.
601     startX += point.x();
602     FloatPoint startPoint(startX, point.y());
603     drawGlyphBuffer(context, glyphBuffer, run, style, startPoint);
604 }
605
606 void Font::drawGlyphBuffer(GraphicsContext* context, const GlyphBuffer& glyphBuffer, 
607                            const TextRun& run, const TextStyle& style, const FloatPoint& point) const
608 {   
609     // Draw each contiguous run of glyphs that use the same font data.
610     const FontData* fontData = glyphBuffer.fontDataAt(0);
611     FloatSize offset = glyphBuffer.offsetAt(0);
612     FloatPoint startPoint(point);
613     float nextX = startPoint.x();
614     int lastFrom = 0;
615     int nextGlyph = 0;
616     while (nextGlyph < glyphBuffer.size()) {
617         const FontData* nextFontData = glyphBuffer.fontDataAt(nextGlyph);
618         FloatSize nextOffset = glyphBuffer.offsetAt(nextGlyph);
619         if (nextFontData != fontData || nextOffset != offset) {
620             drawGlyphs(context, fontData, glyphBuffer, lastFrom, nextGlyph - lastFrom, startPoint);
621             lastFrom = nextGlyph;
622             fontData = nextFontData;
623             offset = nextOffset;
624             startPoint.setX(nextX);
625         }
626         nextX += glyphBuffer.advanceAt(nextGlyph);
627         nextGlyph++;
628     }
629     drawGlyphs(context, fontData, glyphBuffer, lastFrom, nextGlyph - lastFrom, startPoint);
630 }
631
632 void Font::drawText(GraphicsContext* context, const TextRun& run, const TextStyle& style, const FloatPoint& point) const
633 {
634     if (canUseGlyphCache(run))
635         drawSimpleText(context, run, style, point);
636     else
637         drawComplexText(context, run, style, point);
638 }
639
640 float Font::floatWidth(const TextRun& run, const TextStyle& style) const
641 {
642     if (canUseGlyphCache(run))
643         return floatWidthForSimpleText(run, style, 0, 0);
644     return floatWidthForComplexText(run, style);
645 }
646
647 float Font::floatWidthForSimpleText(const TextRun& run, const TextStyle& style, float* startPosition, GlyphBuffer* glyphBuffer) const
648 {
649     WidthIterator it(this, run, style);
650     it.advance(run.to(), glyphBuffer);
651     float runWidth = it.m_runWidthSoFar;
652     if (startPosition) {
653         if (style.ltr())
654             *startPosition = it.m_widthToStart;
655         else {
656             float finalRoundingWidth = it.m_finalRoundingWidth;
657             it.advance(run.length());
658             *startPosition = it.m_runWidthSoFar - runWidth + finalRoundingWidth;
659         }
660     }
661     return runWidth;
662 }
663
664 FloatRect Font::selectionRectForText(const TextRun& run, const TextStyle& style, const IntPoint& point, int h) const
665 {
666     if (canUseGlyphCache(run))
667         return selectionRectForSimpleText(run, style, point, h);
668     return selectionRectForComplexText(run, style, point, h);
669 }
670
671 FloatRect Font::selectionRectForSimpleText(const TextRun& run, const TextStyle& style, const IntPoint& point, int h) const
672 {
673     TextRun completeRun(run);
674     completeRun.makeComplete();
675
676     WidthIterator it(this, completeRun, style);
677     it.advance(run.from());
678     float beforeWidth = it.m_runWidthSoFar;
679     it.advance(run.to());
680     float afterWidth = it.m_runWidthSoFar;
681
682     // Using roundf() rather than ceilf() for the right edge as a compromise to ensure correct caret positioning
683     if (style.rtl()) {
684         it.advance(run.length());
685         float totalWidth = it.m_runWidthSoFar;
686         return FloatRect(point.x() + floorf(totalWidth - afterWidth), point.y(), roundf(totalWidth - beforeWidth) - floorf(totalWidth - afterWidth), h);
687     } else {
688         return FloatRect(point.x() + floorf(beforeWidth), point.y(), roundf(afterWidth) - floorf(beforeWidth), h);
689     }
690 }
691
692 int Font::offsetForPosition(const TextRun& run, const TextStyle& style, int x, bool includePartialGlyphs) const
693 {
694     if (canUseGlyphCache(run))
695         return offsetForPositionForSimpleText(run, style, x, includePartialGlyphs);
696     return offsetForPositionForComplexText(run, style, x, includePartialGlyphs);
697 }
698
699 int Font::offsetForPositionForSimpleText(const TextRun& run, const TextStyle& style, int x, bool includePartialGlyphs) const
700 {
701     float delta = (float)x;
702
703     WidthIterator it(this, run, style);
704     GlyphBuffer localGlyphBuffer;
705     unsigned offset;
706     if (style.rtl()) {
707         delta -= floatWidthForSimpleText(run, style, 0, 0);
708         while (1) {
709             offset = it.m_currentCharacter;
710             float w;
711             if (!it.advanceOneCharacter(w, &localGlyphBuffer))
712                 break;
713             delta += w;
714             if (includePartialGlyphs) {
715                 if (delta - w / 2 >= 0)
716                     break;
717             } else {
718                 if (delta >= 0)
719                     break;
720             }
721         }
722     } else {
723         while (1) {
724             offset = it.m_currentCharacter;
725             float w;
726             if (!it.advanceOneCharacter(w, &localGlyphBuffer))
727                 break;
728             delta -= w;
729             if (includePartialGlyphs) {
730                 if (delta + w / 2 <= 0)
731                     break;
732             } else {
733                 if (delta <= 0)
734                     break;
735             }
736         }
737     }
738
739     return offset - run.from();
740 }
741
742 }