Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / platform / fonts / Font.cpp
1 /*
2  * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3  *           (C) 1999 Antti Koivisto (koivisto@kde.org)
4  *           (C) 2000 Dirk Mueller (mueller@kde.org)
5  * Copyright (C) 2003, 2006, 2010, 2011 Apple Inc. All rights reserved.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public License
18  * along with this library; see the file COPYING.LIB.  If not, write to
19  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20  * Boston, MA 02110-1301, USA.
21  *
22  */
23
24 #include "config.h"
25 #include "platform/fonts/Font.h"
26
27 #include "platform/LayoutUnit.h"
28 #include "platform/fonts/Character.h"
29 #include "platform/fonts/FontCache.h"
30 #include "platform/fonts/FontFallbackList.h"
31 #include "platform/fonts/FontPlatformFeatures.h"
32 #include "platform/fonts/GlyphBuffer.h"
33 #include "platform/fonts/GlyphPageTreeNode.h"
34 #include "platform/fonts/SimpleFontData.h"
35 #include "platform/fonts/WidthIterator.h"
36 #include "platform/geometry/FloatRect.h"
37 #include "platform/text/TextRun.h"
38 #include "wtf/MainThread.h"
39 #include "wtf/StdLibExtras.h"
40 #include "wtf/unicode/CharacterNames.h"
41 #include "wtf/unicode/Unicode.h"
42
43 using namespace WTF;
44 using namespace Unicode;
45 using namespace std;
46
47 namespace WebCore {
48
49 CodePath Font::s_codePath = AutoPath;
50
51 // ============================================================================================
52 // Font Implementation (Cross-Platform Portion)
53 // ============================================================================================
54
55 Font::Font()
56 {
57 }
58
59 Font::Font(const FontDescription& fd)
60     : m_fontDescription(fd)
61 {
62 }
63
64 Font::Font(const Font& other)
65     : m_fontDescription(other.m_fontDescription)
66     , m_fontFallbackList(other.m_fontFallbackList)
67 {
68 }
69
70 Font& Font::operator=(const Font& other)
71 {
72     m_fontDescription = other.m_fontDescription;
73     m_fontFallbackList = other.m_fontFallbackList;
74     return *this;
75 }
76
77 bool Font::operator==(const Font& other) const
78 {
79     // Our FontData don't have to be checked, since checking the font description will be fine.
80     // FIXME: This does not work if the font was made with the FontPlatformData constructor.
81     if (loadingCustomFonts() || other.loadingCustomFonts())
82         return false;
83
84     FontSelector* first = m_fontFallbackList ? m_fontFallbackList->fontSelector() : 0;
85     FontSelector* second = other.m_fontFallbackList ? other.m_fontFallbackList->fontSelector() : 0;
86
87     return first == second
88         && m_fontDescription == other.m_fontDescription
89         && (m_fontFallbackList ? m_fontFallbackList->fontSelectorVersion() : 0) == (other.m_fontFallbackList ? other.m_fontFallbackList->fontSelectorVersion() : 0)
90         && (m_fontFallbackList ? m_fontFallbackList->generation() : 0) == (other.m_fontFallbackList ? other.m_fontFallbackList->generation() : 0);
91 }
92
93 void Font::update(PassRefPtr<FontSelector> fontSelector) const
94 {
95     // FIXME: It is pretty crazy that we are willing to just poke into a RefPtr, but it ends up
96     // being reasonably safe (because inherited fonts in the render tree pick up the new
97     // style anyway. Other copies are transient, e.g., the state in the GraphicsContext, and
98     // won't stick around long enough to get you in trouble). Still, this is pretty disgusting,
99     // and could eventually be rectified by using RefPtrs for Fonts themselves.
100     if (!m_fontFallbackList)
101         m_fontFallbackList = FontFallbackList::create();
102     m_fontFallbackList->invalidate(fontSelector);
103 }
104
105 void Font::drawText(GraphicsContext* context, const TextRunPaintInfo& runInfo, const FloatPoint& point, CustomFontNotReadyAction customFontNotReadyAction) const
106 {
107     // Don't draw anything while we are using custom fonts that are in the process of loading,
108     // except if the 'force' argument is set to true (in which case it will use a fallback
109     // font).
110     if (loadingCustomFonts() && customFontNotReadyAction == DoNotPaintIfFontNotReady)
111         return;
112
113     CodePath codePathToUse = codePath(runInfo.run);
114     // FIXME: Use the fast code path once it handles partial runs with kerning and ligatures. See http://webkit.org/b/100050
115     if (codePathToUse != ComplexPath && fontDescription().typesettingFeatures() && (runInfo.from || runInfo.to != runInfo.run.length()))
116         codePathToUse = ComplexPath;
117
118     if (codePathToUse != ComplexPath)
119         return drawSimpleText(context, runInfo, point);
120
121     return drawComplexText(context, runInfo, point);
122 }
123
124 void Font::drawEmphasisMarks(GraphicsContext* context, const TextRunPaintInfo& runInfo, const AtomicString& mark, const FloatPoint& point) const
125 {
126     if (loadingCustomFonts())
127         return;
128
129     CodePath codePathToUse = codePath(runInfo.run);
130     // FIXME: Use the fast code path once it handles partial runs with kerning and ligatures. See http://webkit.org/b/100050
131     if (codePathToUse != ComplexPath && fontDescription().typesettingFeatures() && (runInfo.from || runInfo.to != runInfo.run.length()))
132         codePathToUse = ComplexPath;
133
134     if (codePathToUse != ComplexPath)
135         drawEmphasisMarksForSimpleText(context, runInfo, mark, point);
136     else
137         drawEmphasisMarksForComplexText(context, runInfo, mark, point);
138 }
139
140 float Font::width(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* glyphOverflow) const
141 {
142     CodePath codePathToUse = codePath(run);
143     if (codePathToUse != ComplexPath) {
144         // The complex path is more restrictive about returning fallback fonts than the simple path, so we need an explicit test to make their behaviors match.
145         if (!FontPlatformFeatures::canReturnFallbackFontsForComplexText())
146             fallbackFonts = 0;
147         // The simple path can optimize the case where glyph overflow is not observable.
148         if (codePathToUse != SimpleWithGlyphOverflowPath && (glyphOverflow && !glyphOverflow->computeBounds))
149             glyphOverflow = 0;
150     }
151
152     bool hasKerningOrLigatures = fontDescription().typesettingFeatures() & (Kerning | Ligatures);
153     bool hasWordSpacingOrLetterSpacing = fontDescription().wordSpacing() || fontDescription().letterSpacing();
154     float* cacheEntry = m_fontFallbackList->widthCache().add(run, std::numeric_limits<float>::quiet_NaN(), hasKerningOrLigatures, hasWordSpacingOrLetterSpacing, glyphOverflow);
155     if (cacheEntry && !std::isnan(*cacheEntry))
156         return *cacheEntry;
157
158     float result;
159     if (codePathToUse == ComplexPath)
160         result = floatWidthForComplexText(run, fallbackFonts, glyphOverflow);
161     else
162         result = floatWidthForSimpleText(run, fallbackFonts, glyphOverflow);
163
164     if (cacheEntry && (!fallbackFonts || fallbackFonts->isEmpty()))
165         *cacheEntry = result;
166     return result;
167 }
168
169 float Font::width(const TextRun& run, int& charsConsumed, String& glyphName) const
170 {
171 #if ENABLE(SVG_FONTS)
172     if (TextRun::RenderingContext* renderingContext = run.renderingContext())
173         return renderingContext->floatWidthUsingSVGFont(*this, run, charsConsumed, glyphName);
174 #endif
175
176     charsConsumed = run.length();
177     glyphName = "";
178     return width(run);
179 }
180
181 FloatRect Font::selectionRectForText(const TextRun& run, const FloatPoint& point, int h, int from, int to) const
182 {
183     to = (to == -1 ? run.length() : to);
184
185     CodePath codePathToUse = codePath(run);
186     // FIXME: Use the fast code path once it handles partial runs with kerning and ligatures. See http://webkit.org/b/100050
187     if (codePathToUse != ComplexPath && fontDescription().typesettingFeatures() && (from || to != run.length()))
188         codePathToUse = ComplexPath;
189
190     if (codePathToUse != ComplexPath)
191         return selectionRectForSimpleText(run, point, h, from, to);
192
193     return selectionRectForComplexText(run, point, h, from, to);
194 }
195
196 int Font::offsetForPosition(const TextRun& run, float x, bool includePartialGlyphs) const
197 {
198     // FIXME: Use the fast code path once it handles partial runs with kerning and ligatures. See http://webkit.org/b/100050
199     if (codePath(run) != ComplexPath && !fontDescription().typesettingFeatures())
200         return offsetForPositionForSimpleText(run, x, includePartialGlyphs);
201
202     return offsetForPositionForComplexText(run, x, includePartialGlyphs);
203 }
204
205 void Font::setCodePath(CodePath p)
206 {
207     s_codePath = p;
208 }
209
210 CodePath Font::codePath()
211 {
212     return s_codePath;
213 }
214
215 CodePath Font::codePath(const TextRun& run) const
216 {
217     if (s_codePath != AutoPath)
218         return s_codePath;
219
220 #if ENABLE(SVG_FONTS)
221     if (run.renderingContext())
222         return SimplePath;
223 #endif
224
225     if (m_fontDescription.featureSettings() && m_fontDescription.featureSettings()->size() > 0)
226         return ComplexPath;
227
228     if (run.length() > 1 && !WidthIterator::supportsTypesettingFeatures(*this))
229         return ComplexPath;
230
231     if (!run.characterScanForCodePath())
232         return SimplePath;
233
234     if (run.is8Bit())
235         return SimplePath;
236
237     // Start from 0 since drawing and highlighting also measure the characters before run->from.
238     return Character::characterRangeCodePath(run.characters16(), run.length());
239 }
240
241 void Font::willUseFontData() const
242 {
243     const FontFamily& family = fontDescription().family();
244     if (m_fontFallbackList && m_fontFallbackList->fontSelector() && !family.familyIsEmpty())
245         m_fontFallbackList->fontSelector()->willUseFontData(fontDescription(), family.family());
246 }
247
248 static inline bool isInRange(UChar32 character, UChar32 lowerBound, UChar32 upperBound)
249 {
250     return character >= lowerBound && character <= upperBound;
251 }
252
253 static bool shouldIgnoreRotation(UChar32 character)
254 {
255     if (character == 0x000A7 || character == 0x000A9 || character == 0x000AE)
256         return true;
257
258     if (character == 0x000B6 || character == 0x000BC || character == 0x000BD || character == 0x000BE)
259         return true;
260
261     if (isInRange(character, 0x002E5, 0x002EB))
262         return true;
263
264     if (isInRange(character, 0x01100, 0x011FF) || isInRange(character, 0x01401, 0x0167F) || isInRange(character, 0x01800, 0x018FF))
265         return true;
266
267     if (character == 0x02016 || character == 0x02018 || character == 0x02019 || character == 0x02020 || character == 0x02021
268         || character == 0x2030 || character == 0x02031)
269         return true;
270
271     if (isInRange(character, 0x0203B, 0x0203D) || character == 0x02042 || character == 0x02044 || character == 0x02047
272         || character == 0x02048 || character == 0x02049 || character == 0x2051)
273         return true;
274
275     if (isInRange(character, 0x02065, 0x02069) || isInRange(character, 0x020DD, 0x020E0)
276         || isInRange(character, 0x020E2, 0x020E4) || isInRange(character, 0x02100, 0x02117)
277         || isInRange(character, 0x02119, 0x02131) || isInRange(character, 0x02133, 0x0213F))
278         return true;
279
280     if (isInRange(character, 0x02145, 0x0214A) || character == 0x0214C || character == 0x0214D
281         || isInRange(character, 0x0214F, 0x0218F))
282         return true;
283
284     if (isInRange(character, 0x02300, 0x02307) || isInRange(character, 0x0230C, 0x0231F)
285         || isInRange(character, 0x02322, 0x0232B) || isInRange(character, 0x0237D, 0x0239A)
286         || isInRange(character, 0x023B4, 0x023B6) || isInRange(character, 0x023BA, 0x023CF)
287         || isInRange(character, 0x023D1, 0x023DB) || isInRange(character, 0x023E2, 0x024FF))
288         return true;
289
290     if (isInRange(character, 0x025A0, 0x02619) || isInRange(character, 0x02620, 0x02767)
291         || isInRange(character, 0x02776, 0x02793) || isInRange(character, 0x02B12, 0x02B2F)
292         || isInRange(character, 0x02B4D, 0x02BFF) || isInRange(character, 0x02E80, 0x03007))
293         return true;
294
295     if (character == 0x03012 || character == 0x03013 || isInRange(character, 0x03020, 0x0302F)
296         || isInRange(character, 0x03031, 0x0309F) || isInRange(character, 0x030A1, 0x030FB)
297         || isInRange(character, 0x030FD, 0x0A4CF))
298         return true;
299
300     if (isInRange(character, 0x0A840, 0x0A87F) || isInRange(character, 0x0A960, 0x0A97F)
301         || isInRange(character, 0x0AC00, 0x0D7FF) || isInRange(character, 0x0E000, 0x0FAFF))
302         return true;
303
304     if (isInRange(character, 0x0FE10, 0x0FE1F) || isInRange(character, 0x0FE30, 0x0FE48)
305         || isInRange(character, 0x0FE50, 0x0FE57) || isInRange(character, 0x0FE5F, 0x0FE62)
306         || isInRange(character, 0x0FE67, 0x0FE6F))
307         return true;
308
309     if (isInRange(character, 0x0FF01, 0x0FF07) || isInRange(character, 0x0FF0A, 0x0FF0C)
310         || isInRange(character, 0x0FF0E, 0x0FF19) || isInRange(character, 0x0FF1F, 0x0FF3A))
311         return true;
312
313     if (character == 0x0FF3C || character == 0x0FF3E)
314         return true;
315
316     if (isInRange(character, 0x0FF40, 0x0FF5A) || isInRange(character, 0x0FFE0, 0x0FFE2)
317         || isInRange(character, 0x0FFE4, 0x0FFE7) || isInRange(character, 0x0FFF0, 0x0FFF8)
318         || character == 0x0FFFD)
319         return true;
320
321     if (isInRange(character, 0x13000, 0x1342F) || isInRange(character, 0x1B000, 0x1B0FF)
322         || isInRange(character, 0x1D000, 0x1D1FF) || isInRange(character, 0x1D300, 0x1D37F)
323         || isInRange(character, 0x1F000, 0x1F64F) || isInRange(character, 0x1F680, 0x1F77F))
324         return true;
325
326     if (isInRange(character, 0x20000, 0x2FFFD) || isInRange(character, 0x30000, 0x3FFFD))
327         return true;
328
329     return false;
330 }
331
332 static inline std::pair<GlyphData, GlyphPage*> glyphDataAndPageForNonCJKCharacterWithGlyphOrientation(UChar32 character, NonCJKGlyphOrientation orientation, GlyphData& data, GlyphPage* page, unsigned pageNumber)
333 {
334     if (orientation == NonCJKGlyphOrientationUpright || shouldIgnoreRotation(character)) {
335         RefPtr<SimpleFontData> uprightFontData = data.fontData->uprightOrientationFontData();
336         GlyphPageTreeNode* uprightNode = GlyphPageTreeNode::getRootChild(uprightFontData.get(), pageNumber);
337         GlyphPage* uprightPage = uprightNode->page();
338         if (uprightPage) {
339             GlyphData uprightData = uprightPage->glyphDataForCharacter(character);
340             // If the glyphs are the same, then we know we can just use the horizontal glyph rotated vertically to be upright.
341             if (data.glyph == uprightData.glyph)
342                 return make_pair(data, page);
343             // The glyphs are distinct, meaning that the font has a vertical-right glyph baked into it. We can't use that
344             // glyph, so we fall back to the upright data and use the horizontal glyph.
345             if (uprightData.fontData)
346                 return make_pair(uprightData, uprightPage);
347         }
348     } else if (orientation == NonCJKGlyphOrientationVerticalRight) {
349         RefPtr<SimpleFontData> verticalRightFontData = data.fontData->verticalRightOrientationFontData();
350         GlyphPageTreeNode* verticalRightNode = GlyphPageTreeNode::getRootChild(verticalRightFontData.get(), pageNumber);
351         GlyphPage* verticalRightPage = verticalRightNode->page();
352         if (verticalRightPage) {
353             GlyphData verticalRightData = verticalRightPage->glyphDataForCharacter(character);
354             // If the glyphs are distinct, we will make the assumption that the font has a vertical-right glyph baked
355             // into it.
356             if (data.glyph != verticalRightData.glyph)
357                 return make_pair(data, page);
358             // The glyphs are identical, meaning that we should just use the horizontal glyph.
359             if (verticalRightData.fontData)
360                 return make_pair(verticalRightData, verticalRightPage);
361         }
362     }
363     return make_pair(data, page);
364 }
365
366 std::pair<GlyphData, GlyphPage*> Font::glyphDataAndPageForCharacter(UChar32 c, bool mirror, FontDataVariant variant) const
367 {
368     ASSERT(isMainThread());
369
370     if (variant == AutoVariant) {
371         if (m_fontDescription.smallCaps() && !primaryFont()->isSVGFont()) {
372             UChar32 upperC = toUpper(c);
373             if (upperC != c) {
374                 c = upperC;
375                 variant = SmallCapsVariant;
376             } else {
377                 variant = NormalVariant;
378             }
379         } else {
380             variant = NormalVariant;
381         }
382     }
383
384     if (mirror)
385         c = mirroredChar(c);
386
387     unsigned pageNumber = (c / GlyphPage::size);
388
389     GlyphPageTreeNode* node = pageNumber ? m_fontFallbackList->m_pages.get(pageNumber) : m_fontFallbackList->m_pageZero;
390     if (!node) {
391         node = GlyphPageTreeNode::getRootChild(fontDataAt(0), pageNumber);
392         if (pageNumber)
393             m_fontFallbackList->m_pages.set(pageNumber, node);
394         else
395             m_fontFallbackList->m_pageZero = node;
396     }
397
398     GlyphPage* page = 0;
399     if (variant == NormalVariant) {
400         // Fastest loop, for the common case (normal variant).
401         while (true) {
402             page = node->page();
403             if (page) {
404                 GlyphData data = page->glyphDataForCharacter(c);
405                 if (data.fontData && (data.fontData->platformData().orientation() == Horizontal || data.fontData->isTextOrientationFallback()))
406                     return make_pair(data, page);
407
408                 if (data.fontData) {
409                     if (Character::isCJKIdeographOrSymbol(c)) {
410                         if (!data.fontData->hasVerticalGlyphs()) {
411                             // Use the broken ideograph font data. The broken ideograph font will use the horizontal width of glyphs
412                             // to make sure you get a square (even for broken glyphs like symbols used for punctuation).
413                             variant = BrokenIdeographVariant;
414                             break;
415                         }
416                     } else {
417                         return glyphDataAndPageForNonCJKCharacterWithGlyphOrientation(c, m_fontDescription.nonCJKGlyphOrientation(), data, page, pageNumber);
418                     }
419
420                     return make_pair(data, page);
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_fontFallbackList->m_pages.set(pageNumber, node);
431             else
432                 m_fontFallbackList->m_pageZero = node;
433         }
434     }
435     if (variant != NormalVariant) {
436         while (true) {
437             page = node->page();
438             if (page) {
439                 GlyphData data = page->glyphDataForCharacter(c);
440                 if (data.fontData) {
441                     // The variantFontData function should not normally return 0.
442                     // But if it does, we will just render the capital letter big.
443                     RefPtr<SimpleFontData> variantFontData = data.fontData->variantFontData(m_fontDescription, variant);
444                     if (!variantFontData)
445                         return make_pair(data, page);
446
447                     GlyphPageTreeNode* variantNode = GlyphPageTreeNode::getRootChild(variantFontData.get(), pageNumber);
448                     GlyphPage* variantPage = variantNode->page();
449                     if (variantPage) {
450                         GlyphData data = variantPage->glyphDataForCharacter(c);
451                         if (data.fontData)
452                             return make_pair(data, variantPage);
453                     }
454
455                     // Do not attempt system fallback off the variantFontData. This is the very unlikely case that
456                     // a font has the lowercase character but the small caps font does not have its uppercase version.
457                     return make_pair(variantFontData->missingGlyphData(), page);
458                 }
459
460                 if (node->isSystemFallback())
461                     break;
462             }
463
464             // Proceed with the fallback list.
465             node = node->getChild(fontDataAt(node->level()), pageNumber);
466             if (pageNumber)
467                 m_fontFallbackList->m_pages.set(pageNumber, node);
468             else
469                 m_fontFallbackList->m_pageZero = node;
470         }
471     }
472
473     ASSERT(page);
474     ASSERT(node->isSystemFallback());
475
476     // System fallback is character-dependent. When we get here, we
477     // know that the character in question isn't in the system fallback
478     // font's glyph page. Try to lazily create it here.
479
480     // FIXME: Unclear if this should normalizeSpaces above 0xFFFF.
481     // Doing so changes fast/text/international/plane2-diffs.html
482     UChar32 characterToRender = c;
483     if (characterToRender <=  0xFFFF)
484         characterToRender = Character::normalizeSpaces(characterToRender);
485     const SimpleFontData* fontDataToSubstitute = fontDataAt(0)->fontDataForCharacter(characterToRender);
486     RefPtr<SimpleFontData> characterFontData = FontCache::fontCache()->platformFallbackForCharacter(m_fontDescription, characterToRender, fontDataToSubstitute);
487     if (characterFontData) {
488         if (characterFontData->platformData().orientation() == Vertical && !characterFontData->hasVerticalGlyphs() && Character::isCJKIdeographOrSymbol(c))
489             variant = BrokenIdeographVariant;
490         if (variant != NormalVariant)
491             characterFontData = characterFontData->variantFontData(m_fontDescription, variant);
492     }
493     if (characterFontData) {
494         // Got the fallback glyph and font.
495         GlyphPage* fallbackPage = GlyphPageTreeNode::getRootChild(characterFontData.get(), pageNumber)->page();
496         GlyphData data = fallbackPage && fallbackPage->fontDataForCharacter(c) ? fallbackPage->glyphDataForCharacter(c) : characterFontData->missingGlyphData();
497         // Cache it so we don't have to do system fallback again next time.
498         if (variant == NormalVariant) {
499             page->setGlyphDataForCharacter(c, data.glyph, data.fontData);
500             data.fontData->setMaxGlyphPageTreeLevel(max(data.fontData->maxGlyphPageTreeLevel(), node->level()));
501             if (!Character::isCJKIdeographOrSymbol(c) && data.fontData->platformData().orientation() != Horizontal && !data.fontData->isTextOrientationFallback())
502                 return glyphDataAndPageForNonCJKCharacterWithGlyphOrientation(c, m_fontDescription.nonCJKGlyphOrientation(), data, fallbackPage, pageNumber);
503         }
504         return make_pair(data, page);
505     }
506
507     // Even system fallback can fail; use the missing glyph in that case.
508     // FIXME: It would be nicer to use the missing glyph from the last resort font instead.
509     GlyphData data = primaryFont()->missingGlyphData();
510     if (variant == NormalVariant) {
511         page->setGlyphDataForCharacter(c, data.glyph, data.fontData);
512         data.fontData->setMaxGlyphPageTreeLevel(max(data.fontData->maxGlyphPageTreeLevel(), node->level()));
513     }
514     return make_pair(data, page);
515 }
516
517 bool Font::primaryFontHasGlyphForCharacter(UChar32 character) const
518 {
519     unsigned pageNumber = (character / GlyphPage::size);
520
521     GlyphPageTreeNode* node = GlyphPageTreeNode::getRootChild(primaryFont(), pageNumber);
522     GlyphPage* page = node->page();
523
524     return page && page->fontDataForCharacter(character);
525 }
526
527 // FIXME: This function may not work if the emphasis mark uses a complex script, but none of the
528 // standard emphasis marks do so.
529 bool Font::getEmphasisMarkGlyphData(const AtomicString& mark, GlyphData& glyphData) const
530 {
531     if (mark.isEmpty())
532         return false;
533
534     UChar32 character = mark[0];
535
536     if (U16_IS_SURROGATE(character)) {
537         if (!U16_IS_SURROGATE_LEAD(character))
538             return false;
539
540         if (mark.length() < 2)
541             return false;
542
543         UChar low = mark[1];
544         if (!U16_IS_TRAIL(low))
545             return false;
546
547         character = U16_GET_SUPPLEMENTARY(character, low);
548     }
549
550     glyphData = glyphDataForCharacter(character, false, EmphasisMarkVariant);
551     return true;
552 }
553
554 int Font::emphasisMarkAscent(const AtomicString& mark) const
555 {
556     FontCachePurgePreventer purgePreventer;
557
558     GlyphData markGlyphData;
559     if (!getEmphasisMarkGlyphData(mark, markGlyphData))
560         return 0;
561
562     const SimpleFontData* markFontData = markGlyphData.fontData;
563     ASSERT(markFontData);
564     if (!markFontData)
565         return 0;
566
567     return markFontData->fontMetrics().ascent();
568 }
569
570 int Font::emphasisMarkDescent(const AtomicString& mark) const
571 {
572     FontCachePurgePreventer purgePreventer;
573
574     GlyphData markGlyphData;
575     if (!getEmphasisMarkGlyphData(mark, markGlyphData))
576         return 0;
577
578     const SimpleFontData* markFontData = markGlyphData.fontData;
579     ASSERT(markFontData);
580     if (!markFontData)
581         return 0;
582
583     return markFontData->fontMetrics().descent();
584 }
585
586 int Font::emphasisMarkHeight(const AtomicString& mark) const
587 {
588     FontCachePurgePreventer purgePreventer;
589
590     GlyphData markGlyphData;
591     if (!getEmphasisMarkGlyphData(mark, markGlyphData))
592         return 0;
593
594     const SimpleFontData* markFontData = markGlyphData.fontData;
595     ASSERT(markFontData);
596     if (!markFontData)
597         return 0;
598
599     return markFontData->fontMetrics().height();
600 }
601
602 float Font::getGlyphsAndAdvancesForSimpleText(const TextRun& run, int from, int to, GlyphBuffer& glyphBuffer, ForTextEmphasisOrNot forTextEmphasis) const
603 {
604     float initialAdvance;
605
606     WidthIterator it(this, run, 0, false, forTextEmphasis);
607     // FIXME: Using separate glyph buffers for the prefix and the suffix is incorrect when kerning or
608     // ligatures are enabled.
609     GlyphBuffer localGlyphBuffer;
610     it.advance(from, &localGlyphBuffer);
611     float beforeWidth = it.m_runWidthSoFar;
612     it.advance(to, &glyphBuffer);
613
614     if (glyphBuffer.isEmpty())
615         return 0;
616
617     float afterWidth = it.m_runWidthSoFar;
618
619     if (run.rtl()) {
620         float finalRoundingWidth = it.m_finalRoundingWidth;
621         it.advance(run.length(), &localGlyphBuffer);
622         initialAdvance = finalRoundingWidth + it.m_runWidthSoFar - afterWidth;
623     } else {
624         initialAdvance = beforeWidth;
625     }
626
627     if (run.rtl())
628         glyphBuffer.reverse(0, glyphBuffer.size());
629
630     return initialAdvance;
631 }
632
633 void Font::drawSimpleText(GraphicsContext* context, const TextRunPaintInfo& runInfo, const FloatPoint& point) const
634 {
635     // This glyph buffer holds our glyphs+advances+font data for each glyph.
636     GlyphBuffer glyphBuffer;
637
638     float startX = point.x() + getGlyphsAndAdvancesForSimpleText(runInfo.run, runInfo.from, runInfo.to, glyphBuffer);
639
640     if (glyphBuffer.isEmpty())
641         return;
642
643     FloatPoint startPoint(startX, point.y());
644     drawGlyphBuffer(context, runInfo, glyphBuffer, startPoint);
645 }
646
647 void Font::drawEmphasisMarksForSimpleText(GraphicsContext* context, const TextRunPaintInfo& runInfo, const AtomicString& mark, const FloatPoint& point) const
648 {
649     GlyphBuffer glyphBuffer;
650     float initialAdvance = getGlyphsAndAdvancesForSimpleText(runInfo.run, runInfo.from, runInfo.to, glyphBuffer, ForTextEmphasis);
651
652     if (glyphBuffer.isEmpty())
653         return;
654
655     drawEmphasisMarks(context, runInfo, glyphBuffer, mark, FloatPoint(point.x() + initialAdvance, point.y()));
656 }
657
658 void Font::drawGlyphBuffer(GraphicsContext* context, const TextRunPaintInfo& runInfo, const GlyphBuffer& glyphBuffer, const FloatPoint& point) const
659 {
660     // Draw each contiguous run of glyphs that use the same font data.
661     const SimpleFontData* fontData = glyphBuffer.fontDataAt(0);
662     FloatPoint startPoint(point);
663     float nextX = startPoint.x() + glyphBuffer.advanceAt(0);
664     unsigned lastFrom = 0;
665     unsigned nextGlyph = 1;
666 #if ENABLE(SVG_FONTS)
667     TextRun::RenderingContext* renderingContext = runInfo.run.renderingContext();
668 #endif
669     while (nextGlyph < glyphBuffer.size()) {
670         const SimpleFontData* nextFontData = glyphBuffer.fontDataAt(nextGlyph);
671
672         if (nextFontData != fontData) {
673 #if ENABLE(SVG_FONTS)
674             if (renderingContext && fontData->isSVGFont())
675                 renderingContext->drawSVGGlyphs(context, runInfo.run, fontData, glyphBuffer, lastFrom, nextGlyph - lastFrom, startPoint);
676             else
677 #endif
678                 drawGlyphs(context, fontData, glyphBuffer, lastFrom, nextGlyph - lastFrom, startPoint, runInfo.bounds);
679
680             lastFrom = nextGlyph;
681             fontData = nextFontData;
682             startPoint.setX(nextX);
683         }
684         nextX += glyphBuffer.advanceAt(nextGlyph);
685         nextGlyph++;
686     }
687
688 #if ENABLE(SVG_FONTS)
689     if (renderingContext && fontData->isSVGFont())
690         renderingContext->drawSVGGlyphs(context, runInfo.run, fontData, glyphBuffer, lastFrom, nextGlyph - lastFrom, startPoint);
691     else
692 #endif
693         drawGlyphs(context, fontData, glyphBuffer, lastFrom, nextGlyph - lastFrom, startPoint, runInfo.bounds);
694 }
695
696 inline static float offsetToMiddleOfGlyph(const SimpleFontData* fontData, Glyph glyph)
697 {
698     if (fontData->platformData().orientation() == Horizontal) {
699         FloatRect bounds = fontData->boundsForGlyph(glyph);
700         return bounds.x() + bounds.width() / 2;
701     }
702     // FIXME: Use glyph bounds once they make sense for vertical fonts.
703     return fontData->widthForGlyph(glyph) / 2;
704 }
705
706 inline static float offsetToMiddleOfAdvanceAtIndex(const GlyphBuffer& glyphBuffer, size_t i)
707 {
708     return glyphBuffer.advanceAt(i) / 2;
709 }
710
711 void Font::drawEmphasisMarks(GraphicsContext* context, const TextRunPaintInfo& runInfo, const GlyphBuffer& glyphBuffer, const AtomicString& mark, const FloatPoint& point) const
712 {
713     FontCachePurgePreventer purgePreventer;
714
715     GlyphData markGlyphData;
716     if (!getEmphasisMarkGlyphData(mark, markGlyphData))
717         return;
718
719     const SimpleFontData* markFontData = markGlyphData.fontData;
720     ASSERT(markFontData);
721     if (!markFontData)
722         return;
723
724     Glyph markGlyph = markGlyphData.glyph;
725     Glyph spaceGlyph = markFontData->spaceGlyph();
726
727     float middleOfLastGlyph = offsetToMiddleOfAdvanceAtIndex(glyphBuffer, 0);
728     FloatPoint startPoint(point.x() + middleOfLastGlyph - offsetToMiddleOfGlyph(markFontData, markGlyph), point.y());
729
730     GlyphBuffer markBuffer;
731     for (unsigned i = 0; i + 1 < glyphBuffer.size(); ++i) {
732         float middleOfNextGlyph = offsetToMiddleOfAdvanceAtIndex(glyphBuffer, i + 1);
733         float advance = glyphBuffer.advanceAt(i) - middleOfLastGlyph + middleOfNextGlyph;
734         markBuffer.add(glyphBuffer.glyphAt(i) ? markGlyph : spaceGlyph, markFontData, advance);
735         middleOfLastGlyph = middleOfNextGlyph;
736     }
737     markBuffer.add(glyphBuffer.glyphAt(glyphBuffer.size() - 1) ? markGlyph : spaceGlyph, markFontData, 0);
738
739     drawGlyphBuffer(context, runInfo, markBuffer, startPoint);
740 }
741
742 float Font::floatWidthForSimpleText(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* glyphOverflow) const
743 {
744     WidthIterator it(this, run, fallbackFonts, glyphOverflow);
745     GlyphBuffer glyphBuffer;
746     it.advance(run.length(), (fontDescription().typesettingFeatures() & (Kerning | Ligatures)) ? &glyphBuffer : 0);
747
748     if (glyphOverflow) {
749         glyphOverflow->top = max<int>(glyphOverflow->top, ceilf(-it.minGlyphBoundingBoxY()) - (glyphOverflow->computeBounds ? 0 : fontMetrics().ascent()));
750         glyphOverflow->bottom = max<int>(glyphOverflow->bottom, ceilf(it.maxGlyphBoundingBoxY()) - (glyphOverflow->computeBounds ? 0 : fontMetrics().descent()));
751         glyphOverflow->left = ceilf(it.firstGlyphOverflow());
752         glyphOverflow->right = ceilf(it.lastGlyphOverflow());
753     }
754
755     return it.m_runWidthSoFar;
756 }
757
758 FloatRect Font::selectionRectForSimpleText(const TextRun& run, const FloatPoint& point, int h, int from, int to) const
759 {
760     GlyphBuffer glyphBuffer;
761     WidthIterator it(this, run);
762     it.advance(from, &glyphBuffer);
763     float beforeWidth = it.m_runWidthSoFar;
764     it.advance(to, &glyphBuffer);
765     float afterWidth = it.m_runWidthSoFar;
766
767     // Using roundf() rather than ceilf() for the right edge as a compromise to
768     // ensure correct caret positioning.
769     // Use LayoutUnit::epsilon() to ensure that values that cannot be stored as
770     // an integer are floored to n and not n-1 due to floating point imprecision.
771     if (run.rtl()) {
772         it.advance(run.length(), &glyphBuffer);
773         float totalWidth = it.m_runWidthSoFar;
774         float pixelAlignedX = floorf(point.x() + totalWidth - afterWidth + LayoutUnit::epsilon());
775         return FloatRect(pixelAlignedX, point.y(),
776             roundf(point.x() + totalWidth - beforeWidth) - pixelAlignedX, h);
777     }
778
779     float pixelAlignedX = floorf(point.x() + beforeWidth + LayoutUnit::epsilon());
780     return FloatRect(pixelAlignedX, point.y(),
781         roundf(point.x() + afterWidth) - pixelAlignedX, h);
782 }
783
784 int Font::offsetForPositionForSimpleText(const TextRun& run, float x, bool includePartialGlyphs) const
785 {
786     float delta = x;
787
788     WidthIterator it(this, run);
789     GlyphBuffer localGlyphBuffer;
790     unsigned offset;
791     if (run.rtl()) {
792         delta -= floatWidthForSimpleText(run);
793         while (1) {
794             offset = it.m_currentCharacter;
795             float w;
796             if (!it.advanceOneCharacter(w, localGlyphBuffer))
797                 break;
798             delta += w;
799             if (includePartialGlyphs) {
800                 if (delta - w / 2 >= 0)
801                     break;
802             } else {
803                 if (delta >= 0)
804                     break;
805             }
806         }
807     } else {
808         while (1) {
809             offset = it.m_currentCharacter;
810             float w;
811             if (!it.advanceOneCharacter(w, localGlyphBuffer))
812                 break;
813             delta -= w;
814             if (includePartialGlyphs) {
815                 if (delta + w / 2 <= 0)
816                     break;
817             } else {
818                 if (delta <= 0)
819                     break;
820             }
821         }
822     }
823
824     return offset;
825 }
826
827 }