5a2eb7af90a2735cd7de6d7f17f6980febdfdb6d
[WebKit-https.git] / WebCore / platform / graphics / 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., 51 Franklin Street, Fifth Floor,
22  * Boston, MA 02110-1301, 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 "FontStyle.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 FontStyle& 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 FontStyle& m_style;
76     
77     unsigned m_currentCharacter;
78     float m_runWidthSoFar;
79     float m_padding;
80     float m_padPerSpace;
81     float m_finalRoundingWidth;
82     
83 private:
84     UChar32 normalizeVoicingMarks(int currentCharacter);
85 };
86
87 WidthIterator::WidthIterator(const Font* font, const TextRun& run, const FontStyle& style)
88     : m_font(font)
89     , m_run(run)
90     , m_end(run.length())
91     , m_style(style)
92     , m_currentCharacter(0)
93     , m_runWidthSoFar(0)
94     , m_finalRoundingWidth(0)
95 {
96     // If the padding is non-zero, count the number of spaces in the run
97     // and divide that by the padding for per space addition.
98     m_padding = m_style.padding();
99     if (!m_padding)
100         m_padPerSpace = 0;
101     else {
102         float numSpaces = 0;
103         for (int i = 0; i < run.length(); i++)
104             if (Font::treatAsSpace(m_run[i]))
105                 numSpaces++;
106
107         if (numSpaces == 0)
108             m_padPerSpace = 0;
109         else
110             m_padPerSpace = ceilf(m_style.padding() / numSpaces);
111     }
112 }
113
114 void WidthIterator::advance(int offset, GlyphBuffer* glyphBuffer)
115 {
116     if (offset > m_end)
117         offset = m_end;
118
119     int currentCharacter = m_currentCharacter;
120     const UChar* cp = m_run.data(currentCharacter);
121
122     bool rtl = m_style.rtl();
123     bool hasExtraSpacing = m_font->letterSpacing() || m_font->wordSpacing() || m_padding;
124
125     float runWidthSoFar = m_runWidthSoFar;
126     float lastRoundingWidth = m_finalRoundingWidth;
127     
128     while (currentCharacter < offset) {
129         UChar32 c = *cp;
130         unsigned clusterLength = 1;
131         if (c >= 0x3041) {
132             if (c <= 0x30FE) {
133                 // Deal with Hiragana and Katakana voiced and semi-voiced syllables.
134                 // Normalize into composed form, and then look for glyph with base + combined mark.
135                 // Check above for character range to minimize performance impact.
136                 UChar32 normalized = normalizeVoicingMarks(currentCharacter);
137                 if (normalized) {
138                     c = normalized;
139                     clusterLength = 2;
140                 }
141             } else if (U16_IS_SURROGATE(c)) {
142                 if (!U16_IS_SURROGATE_LEAD(c))
143                     break;
144
145                 // Do we have a surrogate pair?  If so, determine the full Unicode (32 bit)
146                 // code point before glyph lookup.
147                 // Make sure we have another character and it's a low surrogate.
148                 if (currentCharacter + 1 >= m_run.length())
149                     break;
150                 UChar low = cp[1];
151                 if (!U16_IS_TRAIL(low))
152                     break;
153                 c = U16_GET_SUPPLEMENTARY(c, low);
154                 clusterLength = 2;
155             }
156         }
157
158         const GlyphData& glyphData = m_font->glyphDataForCharacter(c, rtl);
159         Glyph glyph = glyphData.glyph;
160         const FontData* fontData = glyphData.fontData;
161
162         ASSERT(fontData);
163
164         // Now that we have a glyph and font data, get its width.
165         float width;
166         if (c == '\t' && m_style.allowTabs()) {
167             float tabWidth = m_font->tabWidth();
168             width = tabWidth - fmodf(m_style.xPos() + runWidthSoFar, tabWidth);
169         } else {
170             width = fontData->widthForGlyph(glyph);
171             // We special case spaces in two ways when applying word rounding.
172             // First, we round spaces to an adjusted width in all fonts.
173             // Second, in fixed-pitch fonts we ensure that all characters that
174             // match the width of the space character have the same width as the space character.
175             if (width == fontData->m_spaceWidth && (fontData->m_treatAsFixedPitch || glyph == fontData->m_spaceGlyph) && m_style.applyWordRounding())
176                 width = fontData->m_adjustedSpaceWidth;
177         }
178
179         if (hasExtraSpacing && !m_style.spacingDisabled()) {
180             // Account for letter-spacing.
181             if (width && m_font->letterSpacing())
182                 width += m_font->letterSpacing();
183
184             if (Font::treatAsSpace(c)) {
185                 // Account for padding. WebCore uses space padding to justify text.
186                 // We distribute the specified padding over the available spaces in the run.
187                 if (m_padding) {
188                     // Use left over padding if not evenly divisible by number of spaces.
189                     if (m_padding < m_padPerSpace) {
190                         width += m_padding;
191                         m_padding = 0;
192                     } else {
193                         width += m_padPerSpace;
194                         m_padding -= m_padPerSpace;
195                     }
196                 }
197
198                 // Account for word spacing.
199                 // We apply additional space between "words" by adding width to the space character.
200                 if (currentCharacter != 0 && !Font::treatAsSpace(cp[-1]) && m_font->wordSpacing())
201                     width += m_font->wordSpacing();
202             }
203         }
204
205         // Advance past the character we just dealt with.
206         cp += clusterLength;
207         currentCharacter += clusterLength;
208
209         // Account for float/integer impedance mismatch between CG and KHTML. "Words" (characters 
210         // followed by a character defined by isRoundingHackCharacter()) are always an integer width.
211         // We adjust the width of the last character of a "word" to ensure an integer width.
212         // If we move KHTML to floats we can remove this (and related) hacks.
213
214         float oldWidth = width;
215
216         // Force characters that are used to determine word boundaries for the rounding hack
217         // to be integer width, so following words will start on an integer boundary.
218         if (m_style.applyWordRounding() && Font::isRoundingHackCharacter(c))
219             width = ceilf(width);
220
221         // Check to see if the next character is a "rounding hack character", if so, adjust
222         // width so that the total run width will be on an integer boundary.
223         if ((m_style.applyWordRounding() && currentCharacter < m_run.length() && Font::isRoundingHackCharacter(*cp))
224                 || (m_style.applyRunRounding() && currentCharacter >= m_end)) {
225             float totalWidth = runWidthSoFar + width;
226             width += ceilf(totalWidth) - totalWidth;
227         }
228
229         runWidthSoFar += width;
230
231         if (glyphBuffer)
232             glyphBuffer->add(glyph, fontData, (rtl ? oldWidth + lastRoundingWidth : width));
233
234         lastRoundingWidth = width - oldWidth;
235     }
236
237     m_currentCharacter = currentCharacter;
238     m_runWidthSoFar = runWidthSoFar;
239     m_finalRoundingWidth = lastRoundingWidth;
240 }
241
242 bool WidthIterator::advanceOneCharacter(float& width, GlyphBuffer* glyphBuffer)
243 {
244     glyphBuffer->clear();
245     advance(m_currentCharacter + 1, glyphBuffer);
246     float w = 0;
247     for (int i = 0; i < glyphBuffer->size(); ++i)
248         w += glyphBuffer->advanceAt(i);
249     width = w;
250     return !glyphBuffer->isEmpty();
251 }
252
253 UChar32 WidthIterator::normalizeVoicingMarks(int currentCharacter)
254 {
255     if (currentCharacter + 1 < m_end) {
256         if (combiningClass(m_run[currentCharacter + 1]) == hiraganaKatakanaVoicingMarksCombiningClass) {
257 #if USE(ICU_UNICODE)
258             // Normalize into composed form using 3.2 rules.
259             UChar normalizedCharacters[2] = { 0, 0 };
260             UErrorCode uStatus = U_ZERO_ERROR;  
261             int32_t resultLength = unorm_normalize(m_run.data(currentCharacter), 2,
262                 UNORM_NFC, UNORM_UNICODE_3_2, &normalizedCharacters[0], 2, &uStatus);
263             if (resultLength == 1 && uStatus == 0)
264                 return normalizedCharacters[0];
265 #elif USE(QT4_UNICODE)
266             QString tmp(reinterpret_cast<const QChar*>(m_run.data(currentCharacter)), 2);
267             QString res = tmp.normalized(QString::NormalizationForm_C, QChar::Unicode_3_2);
268             if (res.length() == 1)
269                 return res.at(0).unicode();
270 #endif
271         }
272     }
273     return 0;
274 }
275
276 // ============================================================================================
277 // Font Implementation (Cross-Platform Portion)
278 // ============================================================================================
279
280 Font::Font()
281     : m_pageZero(0)
282     , m_letterSpacing(0)
283     , m_wordSpacing(0)
284     , m_isPlatformFont(false)
285 {
286 }
287
288 Font::Font(const FontDescription& fd, short letterSpacing, short wordSpacing) 
289     : m_fontDescription(fd)
290     , m_pageZero(0)
291     , m_letterSpacing(letterSpacing)
292     , m_wordSpacing(wordSpacing)
293     , m_isPlatformFont(false)
294 {
295 }
296
297 Font::Font(const FontPlatformData& fontData, bool isPrinterFont)
298     : m_fontList(new FontFallbackList)
299     , m_pageZero(0)
300     , m_letterSpacing(0)
301     , m_wordSpacing(0)
302     , m_isPlatformFont(true)
303 {
304     m_fontDescription.setUsePrinterFont(isPrinterFont);
305     m_fontList->setPlatformFont(fontData);
306 }
307
308 Font::Font(const Font& other)
309     : m_fontDescription(other.m_fontDescription)
310     , m_fontList(other.m_fontList)
311     , m_pages(other.m_pages)
312     , m_pageZero(other.m_pageZero)
313     , m_letterSpacing(other.m_letterSpacing)
314     , m_wordSpacing(other.m_wordSpacing)
315     , m_isPlatformFont(other.m_isPlatformFont)
316 {
317 }
318
319 Font& Font::operator=(const Font& other)
320 {
321     m_fontDescription = other.m_fontDescription;
322     m_fontList = other.m_fontList;
323     m_pages = other.m_pages;
324     m_pageZero = other.m_pageZero;
325     m_letterSpacing = other.m_letterSpacing;
326     m_wordSpacing = other.m_wordSpacing;
327     m_isPlatformFont = other.m_isPlatformFont;
328     return *this;
329 }
330
331 Font::~Font()
332 {
333 }
334
335 bool Font::operator==(const Font& other) const
336 {
337     // Our FontData don't have to be checked, since checking the font description will be fine.
338     // FIXME: This does not work if the font was made with the FontPlatformData constructor.
339     if ((m_fontList && m_fontList->loadingCustomFonts()) ||
340         (other.m_fontList && other.m_fontList->loadingCustomFonts()))
341         return false;
342     
343     FontSelector* first = m_fontList ? m_fontList->fontSelector() : 0;
344     FontSelector* second = other.m_fontList ? other.m_fontList->fontSelector() : 0;
345     
346     return first == second
347            && m_fontDescription == other.m_fontDescription
348            && m_letterSpacing == other.m_letterSpacing
349            && m_wordSpacing == other.m_wordSpacing;
350 }
351     
352 // FIXME: It is unfortunate that this function needs to be passed the original cluster.
353 // It is only required for the platform's FontCache::getFontDataForCharacters(), and it means
354 // that this function is not correct if it transforms the character to uppercase and calls
355 // FontCache::getFontDataForCharacters() afterwards.
356 const GlyphData& Font::glyphDataForCharacter(UChar32 c, bool mirror) const
357 {
358     bool useSmallCapsFont = false;
359     if (m_fontDescription.smallCaps()) {
360         UChar32 upperC = Unicode::toUpper(c);
361         if (upperC != c) {
362             c = upperC;
363             useSmallCapsFont = true;
364         }
365     }
366
367     if (mirror)
368         c = mirroredChar(c);
369
370     unsigned pageNumber = (c / GlyphPage::size);
371
372     GlyphPageTreeNode* node = pageNumber ? m_pages.get(pageNumber) : m_pageZero;
373     if (!node) {
374         node = GlyphPageTreeNode::getRootChild(primaryFont(), pageNumber);
375         if (pageNumber)
376             m_pages.set(pageNumber, node);
377         else
378             m_pageZero = node;
379     }
380
381     GlyphPage* page;
382     if (!useSmallCapsFont) {
383         // Fastest loop, for the common case (not small caps).
384         while (true) {
385             page = node->page();
386             if (page) {
387                 const GlyphData& data = page->glyphDataForCharacter(c);
388                 if (data.fontData)
389                     return data;
390                 if (node->isSystemFallback())
391                     break;
392             }
393
394             // Proceed with the fallback list.
395             node = node->getChild(fontDataAt(node->level()), pageNumber);
396             if (pageNumber)
397                 m_pages.set(pageNumber, node);
398             else
399                 m_pageZero = node;
400         }
401     } else {
402         while (true) {
403             page = node->page();
404             if (page) {
405                 const GlyphData& data = page->glyphDataForCharacter(c);
406                 if (data.fontData) {
407                     // The smallCapsFontData function should not normally return 0.
408                     // But if it does, we will just render the capital letter big.
409                     const FontData* smallCapsFontData = data.fontData->smallCapsFontData(m_fontDescription);
410                     if (!smallCapsFontData)
411                         return data;
412
413                     GlyphPageTreeNode* smallCapsNode = GlyphPageTreeNode::getRootChild(smallCapsFontData, pageNumber);
414                     const GlyphData& data = smallCapsNode->page()->glyphDataForCharacter(c);
415                     if (data.fontData)
416                         return data;
417
418                     // Do not attempt system fallback off the smallCapsFontData. This is the very unlikely case that
419                     // a font has the lowercase character but the small caps font does not have its uppercase version.
420                     return smallCapsFontData->missingGlyphData();
421                 }
422
423                 if (node->isSystemFallback())
424                     break;
425             }
426
427             // Proceed with the fallback list.
428             node = node->getChild(fontDataAt(node->level()), pageNumber);
429             if (pageNumber)
430                 m_pages.set(pageNumber, node);
431             else
432                 m_pageZero = node;
433         }
434     }
435
436     ASSERT(page);
437     ASSERT(node->isSystemFallback());
438
439     // System fallback is character-dependent. When we get here, we
440     // know that the character in question isn't in the system fallback
441     // font's glyph page. Try to lazily create it here.
442     UChar codeUnits[2];
443     int codeUnitsLength;
444     if (c <= 0xFFFF) {
445         UChar c16 = c;
446         if (Font::treatAsSpace(c16))
447             codeUnits[0] = ' ';
448         else if (Font::treatAsZeroWidthSpace(c16))
449             codeUnits[0] = zeroWidthSpace;
450         else
451             codeUnits[0] = c16;
452         codeUnitsLength = 1;
453     } else {
454         codeUnits[0] = U16_LEAD(c);
455         codeUnits[1] = U16_TRAIL(c);
456         codeUnitsLength = 2;
457     }
458     const FontData* characterFontData = FontCache::getFontDataForCharacters(*this, codeUnits, codeUnitsLength);
459     if (useSmallCapsFont)
460         characterFontData = characterFontData->smallCapsFontData(m_fontDescription);
461     if (characterFontData) {
462         // Got the fallback glyph and font.
463         GlyphPage* fallbackPage = GlyphPageTreeNode::getRootChild(characterFontData, pageNumber)->page();
464         const GlyphData& data = fallbackPage && fallbackPage->glyphDataForCharacter(c).fontData ? fallbackPage->glyphDataForCharacter(c) : characterFontData->missingGlyphData();
465         // Cache it so we don't have to do system fallback again next time.
466         if (!useSmallCapsFont)
467             page->setGlyphDataForCharacter(c, data.glyph, data.fontData);
468         return data;
469     }
470
471     // Even system fallback can fail; use the missing glyph in that case.
472     // FIXME: It would be nicer to use the missing glyph from the last resort font instead.
473     const GlyphData& data = primaryFont()->missingGlyphData();
474     if (!useSmallCapsFont)
475         page->setGlyphDataForCharacter(c, data.glyph, data.fontData);
476     return data;
477 }
478
479 const FontData* Font::primaryFont() const
480 {
481     ASSERT(m_fontList);
482     return m_fontList->primaryFont(this);
483 }
484
485 const FontData* Font::fontDataAt(unsigned index) const
486 {
487     ASSERT(m_fontList);
488     return m_fontList->fontDataAt(this, index);
489 }
490
491 const FontData* Font::fontDataForCharacters(const UChar* characters, int length) const
492 {
493     ASSERT(m_fontList);
494     return m_fontList->fontDataForCharacters(this, characters, length);
495 }
496
497 void Font::update(PassRefPtr<FontSelector> fontSelector) const
498 {
499     // FIXME: It is pretty crazy that we are willing to just poke into a RefPtr, but it ends up 
500     // being reasonably safe (because inherited fonts in the render tree pick up the new
501     // style anyway. Other copies are transient, e.g., the state in the GraphicsContext, and
502     // won't stick around long enough to get you in trouble). Still, this is pretty disgusting,
503     // and could eventually be rectified by using RefPtrs for Fonts themselves.
504     if (!m_fontList)
505         m_fontList = new FontFallbackList();
506     m_fontList->invalidate(fontSelector);
507     m_pageZero = 0;
508     m_pages.clear();
509 }
510
511 int Font::width(const TextRun& run) const
512 {
513     return width(run, FontStyle());
514 }
515
516 int Font::width(const TextRun& run, const FontStyle& style) const
517 {
518     return lroundf(floatWidth(run, style));
519 }
520
521 int Font::ascent() const
522 {
523     return primaryFont()->ascent();
524 }
525
526 int Font::descent() const
527 {
528     return primaryFont()->descent();
529 }
530
531 int Font::lineSpacing() const
532 {
533     return primaryFont()->lineSpacing();
534 }
535
536 float Font::xHeight() const
537 {
538     return primaryFont()->xHeight();
539 }
540
541 unsigned Font::unitsPerEm() const
542 {
543     return primaryFont()->unitsPerEm();
544 }
545
546 int Font::spaceWidth() const
547 {
548     return (int)ceilf(primaryFont()->m_adjustedSpaceWidth + m_letterSpacing);
549 }
550
551 bool Font::isFixedPitch() const
552 {
553     ASSERT(m_fontList);
554     return m_fontList->isFixedPitch(this);
555 }
556
557 void Font::setCodePath(CodePath p)
558 {
559     codePath = p;
560 }
561
562 bool Font::canUseGlyphCache(const TextRun& run) const
563 {
564     switch (codePath) {
565         case Auto:
566             break;
567         case Simple:
568             return true;
569         case Complex:
570             return false;
571     }
572     
573     // Start from 0 since drawing and highlighting also measure the characters before run->from
574     for (int i = 0; i < run.length(); i++) {
575         const UChar c = run[i];
576         if (c < 0x300)      // U+0300 through U+036F Combining diacritical marks
577             continue;
578         if (c <= 0x36F)
579             return false;
580
581         if (c < 0x0591 || c == 0x05BE)     // U+0591 through U+05CF excluding U+05BE Hebrew combining marks, Hebrew punctuation Paseq, Sof Pasuq and Nun Hafukha
582             continue;
583         if (c <= 0x05CF)
584             return false;
585
586         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
587             continue;
588         if (c <= 0x1059)
589             return false;
590
591         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)
592             continue;
593         if (c <= 0x11FF)
594             return false;
595
596         if (c < 0x1780)     // U+1780 through U+18AF Khmer, Mongolian
597             continue;
598         if (c <= 0x18AF)
599             return false;
600
601         if (c < 0x1900)     // U+1900 through U+194F Limbu (Unicode 4.0)
602             continue;
603         if (c <= 0x194F)
604             return false;
605
606         if (c < 0x20D0)     // U+20D0 through U+20FF Combining marks for symbols
607             continue;
608         if (c <= 0x20FF)
609             return false;
610
611         if (c < 0xFE20)     // U+FE20 through U+FE2F Combining half marks
612             continue;
613         if (c <= 0xFE2F)
614             return false;
615     }
616
617     return true;
618
619 }
620
621 void Font::drawSimpleText(GraphicsContext* context, const TextRun& run, const FontStyle& style, const FloatPoint& point, int from, int to) const
622 {
623     // This glyph buffer holds our glyphs+advances+font data for each glyph.
624     GlyphBuffer glyphBuffer;
625
626     float startX = point.x();
627     WidthIterator it(this, run, style);
628     it.advance(from);
629     float beforeWidth = it.m_runWidthSoFar;
630     it.advance(to, &glyphBuffer);
631     
632     // We couldn't generate any glyphs for the run.  Give up.
633     if (glyphBuffer.isEmpty())
634         return;
635     
636     float afterWidth = it.m_runWidthSoFar;
637
638     if (style.rtl()) {
639         float finalRoundingWidth = it.m_finalRoundingWidth;
640         it.advance(run.length());
641         startX += finalRoundingWidth + it.m_runWidthSoFar - afterWidth;
642     } else
643         startX += beforeWidth;
644
645     // Swap the order of the glyphs if right-to-left.
646     if (style.rtl())
647         for (int i = 0, end = glyphBuffer.size() - 1; i < glyphBuffer.size() / 2; ++i, --end)
648             glyphBuffer.swap(i, end);
649
650     // Calculate the starting point of the glyphs to be displayed by adding
651     // all the advances up to the first glyph.
652     FloatPoint startPoint(startX, point.y());
653     drawGlyphBuffer(context, glyphBuffer, run, style, startPoint);
654 }
655
656 void Font::drawGlyphBuffer(GraphicsContext* context, const GlyphBuffer& glyphBuffer, 
657                            const TextRun& run, const FontStyle& style, const FloatPoint& point) const
658 {   
659     // Draw each contiguous run of glyphs that use the same font data.
660     const FontData* fontData = glyphBuffer.fontDataAt(0);
661     FloatSize offset = glyphBuffer.offsetAt(0);
662     FloatPoint startPoint(point);
663     float nextX = startPoint.x();
664     int lastFrom = 0;
665     int nextGlyph = 0;
666     while (nextGlyph < glyphBuffer.size()) {
667         const FontData* nextFontData = glyphBuffer.fontDataAt(nextGlyph);
668         FloatSize nextOffset = glyphBuffer.offsetAt(nextGlyph);
669         if (nextFontData != fontData || nextOffset != offset) {
670             drawGlyphs(context, fontData, glyphBuffer, lastFrom, nextGlyph - lastFrom, startPoint);
671             lastFrom = nextGlyph;
672             fontData = nextFontData;
673             offset = nextOffset;
674             startPoint.setX(nextX);
675         }
676         nextX += glyphBuffer.advanceAt(nextGlyph);
677         nextGlyph++;
678     }
679     drawGlyphs(context, fontData, glyphBuffer, lastFrom, nextGlyph - lastFrom, startPoint);
680 }
681
682 void Font::drawText(GraphicsContext* context, const TextRun& run, const FontStyle& style, const FloatPoint& point, int from, int to) const
683 {
684     // Don't draw anything while we are using custom fonts that are in the process of loading.
685     if (m_fontList && m_fontList->loadingCustomFonts())
686         return;
687     
688     to = (to == -1 ? run.length() : to);
689     if (canUseGlyphCache(run))
690         drawSimpleText(context, run, style, point, from, to);
691     else
692         drawComplexText(context, run, style, point, from, to);
693 }
694
695 float Font::floatWidth(const TextRun& run, const FontStyle& style) const
696 {
697     if (canUseGlyphCache(run))
698         return floatWidthForSimpleText(run, style, 0);
699     return floatWidthForComplexText(run, style);
700 }
701
702 float Font::floatWidthForSimpleText(const TextRun& run, const FontStyle& style, GlyphBuffer* glyphBuffer) const
703 {
704     WidthIterator it(this, run, style);
705     it.advance(run.length(), glyphBuffer);
706     return it.m_runWidthSoFar;
707 }
708
709 FloatRect Font::selectionRectForText(const TextRun& run, const FontStyle& style, const IntPoint& point, int h, int from, int to) const
710 {
711     to = (to == -1 ? run.length() : to);
712     if (canUseGlyphCache(run))
713         return selectionRectForSimpleText(run, style, point, h, from, to);
714     return selectionRectForComplexText(run, style, point, h, from, to);
715 }
716
717 FloatRect Font::selectionRectForSimpleText(const TextRun& run, const FontStyle& style, const IntPoint& point, int h, int from, int to) const
718 {
719     WidthIterator it(this, run, style);
720     it.advance(from);
721     float beforeWidth = it.m_runWidthSoFar;
722     it.advance(to);
723     float afterWidth = it.m_runWidthSoFar;
724
725     // Using roundf() rather than ceilf() for the right edge as a compromise to ensure correct caret positioning
726     if (style.rtl()) {
727         it.advance(run.length());
728         float totalWidth = it.m_runWidthSoFar;
729         return FloatRect(point.x() + floorf(totalWidth - afterWidth), point.y(), roundf(totalWidth - beforeWidth) - floorf(totalWidth - afterWidth), h);
730     } else {
731         return FloatRect(point.x() + floorf(beforeWidth), point.y(), roundf(afterWidth) - floorf(beforeWidth), h);
732     }
733 }
734
735 int Font::offsetForPosition(const TextRun& run, const FontStyle& style, int x, bool includePartialGlyphs) const
736 {
737     if (canUseGlyphCache(run))
738         return offsetForPositionForSimpleText(run, style, x, includePartialGlyphs);
739     return offsetForPositionForComplexText(run, style, x, includePartialGlyphs);
740 }
741
742 int Font::offsetForPositionForSimpleText(const TextRun& run, const FontStyle& style, int x, bool includePartialGlyphs) const
743 {
744     float delta = (float)x;
745
746     WidthIterator it(this, run, style);
747     GlyphBuffer localGlyphBuffer;
748     unsigned offset;
749     if (style.rtl()) {
750         delta -= floatWidthForSimpleText(run, style, 0);
751         while (1) {
752             offset = it.m_currentCharacter;
753             float w;
754             if (!it.advanceOneCharacter(w, &localGlyphBuffer))
755                 break;
756             delta += w;
757             if (includePartialGlyphs) {
758                 if (delta - w / 2 >= 0)
759                     break;
760             } else {
761                 if (delta >= 0)
762                     break;
763             }
764         }
765     } else {
766         while (1) {
767             offset = it.m_currentCharacter;
768             float w;
769             if (!it.advanceOneCharacter(w, &localGlyphBuffer))
770                 break;
771             delta -= w;
772             if (includePartialGlyphs) {
773                 if (delta + w / 2 <= 0)
774                     break;
775             } else {
776                 if (delta <= 0)
777                     break;
778             }
779         }
780     }
781
782     return offset;
783 }
784
785 }