2011-01-29 Patrick Gansterer <paroga@webkit.org>
[WebKit-https.git] / Source / WebCore / platform / graphics / FontFastPath.cpp
1 /**
2  * Copyright (C) 2003, 2006, 2010 Apple Inc. All rights reserved.
3  * Copyright (C) 2008 Holger Hans Peter Freyther
4  * Copyright (C) 2009 Torch Mobile, Inc.
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public License
17  * along with this library; see the file COPYING.LIB.  If not, write to
18  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19  * Boston, MA 02110-1301, USA.
20  *
21  */
22
23 #include "config.h"
24 #include "Font.h"
25
26 #include "FloatRect.h"
27 #include "FontCache.h"
28 #include "FontFallbackList.h"
29 #include "GlyphBuffer.h"
30 #include "GlyphPageTreeNode.h"
31 #include "SimpleFontData.h"
32 #include "TextRun.h"
33 #include "WidthIterator.h"
34 #include <wtf/MathExtras.h>
35 #include <wtf/unicode/CharacterNames.h>
36 #include <wtf/unicode/Unicode.h>
37
38 using namespace WTF;
39 using namespace Unicode;
40
41 namespace WebCore {
42
43 GlyphData Font::glyphDataForCharacter(UChar32 c, bool mirror, FontDataVariant variant) const
44 {
45     ASSERT(isMainThread());
46
47     if (variant == AutoVariant) {
48         if (m_fontDescription.smallCaps()) {
49             UChar32 upperC = toUpper(c);
50             if (upperC != c) {
51                 c = upperC;
52                 variant = SmallCapsVariant;
53             } else
54                 variant = NormalVariant;
55         } else
56             variant = NormalVariant;
57     }
58
59     if (mirror)
60         c = mirroredChar(c);
61
62     unsigned pageNumber = (c / GlyphPage::size);
63
64     GlyphPageTreeNode* node = pageNumber ? m_fontList->m_pages.get(pageNumber) : m_fontList->m_pageZero;
65     if (!node) {
66         node = GlyphPageTreeNode::getRootChild(fontDataAt(0), pageNumber);
67         if (pageNumber)
68             m_fontList->m_pages.set(pageNumber, node);
69         else
70             m_fontList->m_pageZero = node;
71     }
72
73     GlyphPage* page;
74     if (variant == NormalVariant) {
75         // Fastest loop, for the common case (normal variant).
76         while (true) {
77             page = node->page();
78             if (page) {
79                 GlyphData data = page->glyphDataForCharacter(c);
80                 if (data.fontData) {
81                     if (data.fontData->platformData().orientation() == Vertical && data.fontData->orientation() == Horizontal && Font::isCJKIdeographOrSymbol(c)) {
82                         const SimpleFontData* ideographFontData = data.fontData->brokenIdeographFontData();
83                         GlyphPageTreeNode* ideographNode = GlyphPageTreeNode::getRootChild(ideographFontData, pageNumber);
84                         const GlyphPage* ideographPage = ideographNode->page();
85                         if (ideographPage) {
86                             GlyphData data = ideographPage->glyphDataForCharacter(c);
87                             if (data.fontData)
88                                 return data;
89                         }
90                         
91                         // Shouldn't be possible to even reach this point.
92                         ASSERT_NOT_REACHED();
93                     }
94                     return data;
95                 }
96
97                 if (node->isSystemFallback())
98                     break;
99             }
100
101             // Proceed with the fallback list.
102             node = node->getChild(fontDataAt(node->level()), pageNumber);
103             if (pageNumber)
104                 m_fontList->m_pages.set(pageNumber, node);
105             else
106                 m_fontList->m_pageZero = node;
107         }
108     } else {
109         while (true) {
110             page = node->page();
111             if (page) {
112                 GlyphData data = page->glyphDataForCharacter(c);
113                 if (data.fontData) {
114                     // The variantFontData function should not normally return 0.
115                     // But if it does, we will just render the capital letter big.
116                     const SimpleFontData* variantFontData = data.fontData->variantFontData(m_fontDescription, variant);
117                     if (!variantFontData)
118                         return data;
119
120                     GlyphPageTreeNode* variantNode = GlyphPageTreeNode::getRootChild(variantFontData, pageNumber);
121                     const GlyphPage* variantPage = variantNode->page();
122                     if (variantPage) {
123                         GlyphData data = variantPage->glyphDataForCharacter(c);
124                         if (data.fontData)
125                             return data;
126                     }
127
128                     // Do not attempt system fallback off the variantFontData. This is the very unlikely case that
129                     // a font has the lowercase character but the small caps font does not have its uppercase version.
130                     return variantFontData->missingGlyphData();
131                 }
132
133                 if (node->isSystemFallback())
134                     break;
135             }
136
137             // Proceed with the fallback list.
138             node = node->getChild(fontDataAt(node->level()), pageNumber);
139             if (pageNumber)
140                 m_fontList->m_pages.set(pageNumber, node);
141             else
142                 m_fontList->m_pageZero = node;
143         }
144     }
145
146     ASSERT(page);
147     ASSERT(node->isSystemFallback());
148
149     // System fallback is character-dependent. When we get here, we
150     // know that the character in question isn't in the system fallback
151     // font's glyph page. Try to lazily create it here.
152     UChar codeUnits[2];
153     int codeUnitsLength;
154     if (c <= 0xFFFF) {
155         codeUnits[0] = Font::normalizeSpaces(c);
156         codeUnitsLength = 1;
157     } else {
158         codeUnits[0] = U16_LEAD(c);
159         codeUnits[1] = U16_TRAIL(c);
160         codeUnitsLength = 2;
161     }
162     const SimpleFontData* characterFontData = fontCache()->getFontDataForCharacters(*this, codeUnits, codeUnitsLength);
163     if (variant != NormalVariant && characterFontData)
164         characterFontData = characterFontData->variantFontData(m_fontDescription, variant);
165     if (characterFontData) {
166         // Got the fallback glyph and font.
167         GlyphPage* fallbackPage = GlyphPageTreeNode::getRootChild(characterFontData, pageNumber)->page();
168         GlyphData data = fallbackPage && fallbackPage->fontDataForCharacter(c) ? fallbackPage->glyphDataForCharacter(c) : characterFontData->missingGlyphData();
169         // Cache it so we don't have to do system fallback again next time.
170         if (variant == NormalVariant) {
171 #if OS(WINCE)
172             // missingGlyphData returns a null character, which is not suitable for GDI to display.
173             // Also, sometimes we cannot map a font for the character on WINCE, but GDI can still
174             // display the character, probably because the font package is not installed correctly.
175             // So we just always set the glyph to be same as the character, and let GDI solve it.
176             page->setGlyphDataForCharacter(c, c, characterFontData);
177             return page->glyphDataForCharacter(c);
178 #else
179             page->setGlyphDataForCharacter(c, data.glyph, data.fontData);
180 #endif
181         }
182         return data;
183     }
184
185     // Even system fallback can fail; use the missing glyph in that case.
186     // FIXME: It would be nicer to use the missing glyph from the last resort font instead.
187     GlyphData data = primaryFont()->missingGlyphData();
188     if (variant == NormalVariant) {
189 #if OS(WINCE)
190         // See comment about WINCE GDI handling near setGlyphDataForCharacter above.
191         page->setGlyphDataForCharacter(c, c, data.fontData);
192         return page->glyphDataForCharacter(c);
193 #else
194         page->setGlyphDataForCharacter(c, data.glyph, data.fontData);
195 #endif
196     }
197     return data;
198 }
199
200 bool Font::primaryFontHasGlyphForCharacter(UChar32 character) const
201 {
202     unsigned pageNumber = (character / GlyphPage::size);
203
204     GlyphPageTreeNode* node = GlyphPageTreeNode::getRootChild(primaryFont(), pageNumber);
205     GlyphPage* page = node->page();
206
207     return page && page->fontDataForCharacter(character);
208 }
209
210 // FIXME: This function may not work if the emphasis mark uses a complex script, but none of the
211 // standard emphasis marks do so.
212 bool Font::getEmphasisMarkGlyphData(const AtomicString& mark, GlyphData& glyphData) const
213 {
214     if (mark.isEmpty())
215         return false;
216
217 #if ENABLE(SVG_FONTS)
218     // FIXME: Implement for SVG fonts.
219     if (primaryFont()->isSVGFont())
220         return false;
221 #endif
222
223     UChar32 character = mark[0];
224
225     if (U16_IS_SURROGATE(character)) {
226         if (!U16_IS_SURROGATE_LEAD(character))
227             return false;
228
229         if (mark.length() < 2)
230             return false;
231
232         UChar low = mark[1];
233         if (!U16_IS_TRAIL(low))
234             return false;
235
236         character = U16_GET_SUPPLEMENTARY(character, low);
237     }
238
239     glyphData = glyphDataForCharacter(character, false, EmphasisMarkVariant);
240     return true;
241 }
242
243 int Font::emphasisMarkAscent(const AtomicString& mark) const
244 {
245     GlyphData markGlyphData;
246     if (!getEmphasisMarkGlyphData(mark, markGlyphData))
247         return 0;
248
249     const SimpleFontData* markFontData = markGlyphData.fontData;
250     ASSERT(markFontData);
251     if (!markFontData)
252         return 0;
253
254     return markFontData->fontMetrics().ascent();
255 }
256
257 int Font::emphasisMarkDescent(const AtomicString& mark) const
258 {
259     GlyphData markGlyphData;
260     if (!getEmphasisMarkGlyphData(mark, markGlyphData))
261         return 0;
262
263     const SimpleFontData* markFontData = markGlyphData.fontData;
264     ASSERT(markFontData);
265     if (!markFontData)
266         return 0;
267
268     return markFontData->fontMetrics().descent();
269 }
270
271 int Font::emphasisMarkHeight(const AtomicString& mark) const
272 {
273     GlyphData markGlyphData;
274     if (!getEmphasisMarkGlyphData(mark, markGlyphData))
275         return 0;
276
277     const SimpleFontData* markFontData = markGlyphData.fontData;
278     ASSERT(markFontData);
279     if (!markFontData)
280         return 0;
281
282     return markFontData->fontMetrics().height();
283 }
284
285 float Font::getGlyphsAndAdvancesForSimpleText(const TextRun& run, int from, int to, GlyphBuffer& glyphBuffer, ForTextEmphasisOrNot forTextEmphasis) const
286 {
287     float initialAdvance;
288
289     WidthIterator it(this, run, 0, false, forTextEmphasis);
290     it.advance(from);
291     float beforeWidth = it.m_runWidthSoFar;
292     it.advance(to, &glyphBuffer);
293
294     if (glyphBuffer.isEmpty())
295         return 0;
296
297     float afterWidth = it.m_runWidthSoFar;
298
299     if (run.rtl()) {
300         float finalRoundingWidth = it.m_finalRoundingWidth;
301         it.advance(run.length());
302         initialAdvance = finalRoundingWidth + it.m_runWidthSoFar - afterWidth;
303     } else
304         initialAdvance = beforeWidth;
305
306     if (run.rtl()) {
307         for (int i = 0, end = glyphBuffer.size() - 1; i < glyphBuffer.size() / 2; ++i, --end)
308             glyphBuffer.swap(i, end);
309     }
310
311     return initialAdvance;
312 }
313
314 void Font::drawSimpleText(GraphicsContext* context, const TextRun& run, const FloatPoint& point, int from, int to) const
315 {
316     // This glyph buffer holds our glyphs+advances+font data for each glyph.
317     GlyphBuffer glyphBuffer;
318
319     float startX = point.x() + getGlyphsAndAdvancesForSimpleText(run, from, to, glyphBuffer);
320
321     if (glyphBuffer.isEmpty())
322         return;
323
324     FloatPoint startPoint(startX, point.y());
325     drawGlyphBuffer(context, glyphBuffer, startPoint);
326 }
327
328 void Font::drawEmphasisMarksForSimpleText(GraphicsContext* context, const TextRun& run, const AtomicString& mark, const FloatPoint& point, int from, int to) const
329 {
330     GlyphBuffer glyphBuffer;
331     float initialAdvance = getGlyphsAndAdvancesForSimpleText(run, from, to, glyphBuffer, ForTextEmphasis);
332
333     if (glyphBuffer.isEmpty())
334         return;
335
336     drawEmphasisMarks(context, glyphBuffer, mark, FloatPoint(point.x() + initialAdvance, point.y()));
337 }
338
339 void Font::drawGlyphBuffer(GraphicsContext* context, const GlyphBuffer& glyphBuffer, const FloatPoint& point) const
340 {   
341     // Draw each contiguous run of glyphs that use the same font data.
342     const SimpleFontData* fontData = glyphBuffer.fontDataAt(0);
343     FloatSize offset = glyphBuffer.offsetAt(0);
344     FloatPoint startPoint(point);
345     float nextX = startPoint.x();
346     int lastFrom = 0;
347     int nextGlyph = 0;
348     while (nextGlyph < glyphBuffer.size()) {
349         const SimpleFontData* nextFontData = glyphBuffer.fontDataAt(nextGlyph);
350         FloatSize nextOffset = glyphBuffer.offsetAt(nextGlyph);
351         if (nextFontData != fontData || nextOffset != offset) {
352             drawGlyphs(context, fontData, glyphBuffer, lastFrom, nextGlyph - lastFrom, startPoint);
353
354             lastFrom = nextGlyph;
355             fontData = nextFontData;
356             offset = nextOffset;
357             startPoint.setX(nextX);
358         }
359         nextX += glyphBuffer.advanceAt(nextGlyph);
360         nextGlyph++;
361     }
362
363     drawGlyphs(context, fontData, glyphBuffer, lastFrom, nextGlyph - lastFrom, startPoint);
364 }
365
366 inline static float offsetToMiddleOfGlyph(const SimpleFontData* fontData, Glyph glyph)
367 {
368     if (fontData->orientation() == Horizontal) {
369         FloatRect bounds = fontData->boundsForGlyph(glyph);
370         return bounds.x() + bounds.width() / 2;
371     }
372     // FIXME: Use glyph bounds once they make sense for vertical fonts.
373     return fontData->widthForGlyph(glyph) / 2;
374 }
375
376 inline static float offsetToMiddleOfGlyphAtIndex(const GlyphBuffer& glyphBuffer, size_t i)
377 {
378     return offsetToMiddleOfGlyph(glyphBuffer.fontDataAt(i), glyphBuffer.glyphAt(i));
379 }
380
381 void Font::drawEmphasisMarks(GraphicsContext* context, const GlyphBuffer& glyphBuffer, const AtomicString& mark, const FloatPoint& point) const
382 {
383     GlyphData markGlyphData;
384     if (!getEmphasisMarkGlyphData(mark, markGlyphData))
385         return;
386
387     const SimpleFontData* markFontData = markGlyphData.fontData;
388     ASSERT(markFontData);
389     if (!markFontData)
390         return;
391
392     Glyph markGlyph = markGlyphData.glyph;
393     Glyph spaceGlyph = markFontData->spaceGlyph();
394
395     float middleOfLastGlyph = offsetToMiddleOfGlyphAtIndex(glyphBuffer, 0);
396     FloatPoint startPoint(point.x() + middleOfLastGlyph - offsetToMiddleOfGlyph(markFontData, markGlyph), point.y());
397
398     GlyphBuffer markBuffer;
399     for (int i = 0; i + 1 < glyphBuffer.size(); ++i) {
400         float middleOfNextGlyph = offsetToMiddleOfGlyphAtIndex(glyphBuffer, i + 1);
401         float advance = glyphBuffer.advanceAt(i) - middleOfLastGlyph + middleOfNextGlyph;
402         markBuffer.add(glyphBuffer.glyphAt(i) ? markGlyph : spaceGlyph, markFontData, advance);
403         middleOfLastGlyph = middleOfNextGlyph;
404     }
405     markBuffer.add(glyphBuffer.glyphAt(glyphBuffer.size() - 1) ? markGlyph : spaceGlyph, markFontData, 0);
406
407     drawGlyphBuffer(context, markBuffer, startPoint);
408 }
409
410 float Font::floatWidthForSimpleText(const TextRun& run, GlyphBuffer* glyphBuffer, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* glyphOverflow) const
411 {
412     WidthIterator it(this, run, fallbackFonts, glyphOverflow);
413     it.advance(run.length(), glyphBuffer);
414
415     if (glyphOverflow) {
416         glyphOverflow->top = max<int>(glyphOverflow->top, ceilf(-it.minGlyphBoundingBoxY()) - fontMetrics().ascent());
417         glyphOverflow->bottom = max<int>(glyphOverflow->bottom, ceilf(it.maxGlyphBoundingBoxY()) - fontMetrics().descent());
418         glyphOverflow->left = ceilf(it.firstGlyphOverflow());
419         glyphOverflow->right = ceilf(it.lastGlyphOverflow());
420     }
421
422     return it.m_runWidthSoFar;
423 }
424
425 FloatRect Font::selectionRectForSimpleText(const TextRun& run, const FloatPoint& point, int h, int from, int to) const
426 {
427     WidthIterator it(this, run);
428     it.advance(from);
429     float beforeWidth = it.m_runWidthSoFar;
430     it.advance(to);
431     float afterWidth = it.m_runWidthSoFar;
432
433     // Using roundf() rather than ceilf() for the right edge as a compromise to ensure correct caret positioning.
434     if (run.rtl()) {
435         it.advance(run.length());
436         float totalWidth = it.m_runWidthSoFar;
437         return FloatRect(point.x() + floorf(totalWidth - afterWidth), point.y(), roundf(totalWidth - beforeWidth) - floorf(totalWidth - afterWidth), h);
438     }
439
440     return FloatRect(point.x() + floorf(beforeWidth), point.y(), roundf(afterWidth) - floorf(beforeWidth), h);
441 }
442
443 int Font::offsetForPositionForSimpleText(const TextRun& run, float x, bool includePartialGlyphs) const
444 {
445     float delta = x;
446
447     WidthIterator it(this, run);
448     GlyphBuffer localGlyphBuffer;
449     unsigned offset;
450     if (run.rtl()) {
451         delta -= floatWidthForSimpleText(run, 0);
452         while (1) {
453             offset = it.m_currentCharacter;
454             float w;
455             if (!it.advanceOneCharacter(w, &localGlyphBuffer))
456                 break;
457             delta += w;
458             if (includePartialGlyphs) {
459                 if (delta - w / 2 >= 0)
460                     break;
461             } else {
462                 if (delta >= 0)
463                     break;
464             }
465         }
466     } else {
467         while (1) {
468             offset = it.m_currentCharacter;
469             float w;
470             if (!it.advanceOneCharacter(w, &localGlyphBuffer))
471                 break;
472             delta -= w;
473             if (includePartialGlyphs) {
474                 if (delta + w / 2 <= 0)
475                     break;
476             } else {
477                 if (delta <= 0)
478                     break;
479             }
480         }
481     }
482
483     return offset;
484 }
485
486 }