tagging audio streams and changing audio sink to pulseaudio
[profile/ivi/webkit-efl.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/MainThread.h>
35 #include <wtf/MathExtras.h>
36 #include <wtf/unicode/CharacterNames.h>
37 #include <wtf/unicode/Unicode.h>
38
39 using namespace WTF;
40 using namespace Unicode;
41 using namespace std;
42
43 namespace WebCore {
44
45 GlyphData Font::glyphDataForCharacter(UChar32 c, bool mirror, FontDataVariant variant) const
46 {
47     return glyphDataAndPageForCharacter(c, mirror, variant).first;
48 }
49
50 std::pair<GlyphData, GlyphPage*> Font::glyphDataAndPageForCharacter(UChar32 c, bool mirror, FontDataVariant variant) const
51 {
52     ASSERT(isMainThread());
53
54     if (variant == AutoVariant) {
55         if (m_fontDescription.smallCaps() && !primaryFont()->isSVGFont()) {
56             UChar32 upperC = toUpper(c);
57             if (upperC != c) {
58                 c = upperC;
59                 variant = SmallCapsVariant;
60             } else
61                 variant = NormalVariant;
62         } else
63             variant = NormalVariant;
64     }
65
66     if (mirror)
67         c = mirroredChar(c);
68
69     unsigned pageNumber = (c / GlyphPage::size);
70
71     GlyphPageTreeNode* node = pageNumber ? m_fontList->m_pages.get(pageNumber) : m_fontList->m_pageZero;
72     if (!node) {
73         node = GlyphPageTreeNode::getRootChild(fontDataAt(0), pageNumber);
74         if (pageNumber)
75             m_fontList->m_pages.set(pageNumber, node);
76         else
77             m_fontList->m_pageZero = node;
78     }
79
80     GlyphPage* page = 0;
81     if (variant == NormalVariant) {
82         // Fastest loop, for the common case (normal variant).
83         while (true) {
84             page = node->page();
85             if (page) {
86                 GlyphData data = page->glyphDataForCharacter(c);
87                 if (data.fontData && (data.fontData->platformData().orientation() == Horizontal || data.fontData->isTextOrientationFallback()))
88                     return make_pair(data, page);
89
90                 if (data.fontData) {
91                     if (isCJKIdeographOrSymbol(c)) {
92                         if (!data.fontData->hasVerticalGlyphs()) {
93                             // Use the broken ideograph font data. The broken ideograph font will use the horizontal width of glyphs
94                             // to make sure you get a square (even for broken glyphs like symbols used for punctuation).
95                             variant = BrokenIdeographVariant;
96                             break;
97                         }
98                     } else {
99                         if (m_fontDescription.textOrientation() == TextOrientationVerticalRight) {
100                             const SimpleFontData* verticalRightFontData = data.fontData->verticalRightOrientationFontData();
101                             GlyphPageTreeNode* verticalRightNode = GlyphPageTreeNode::getRootChild(verticalRightFontData, pageNumber);
102                             GlyphPage* verticalRightPage = verticalRightNode->page();
103                             if (verticalRightPage) {
104                                 GlyphData verticalRightData = verticalRightPage->glyphDataForCharacter(c);
105                                 // If the glyphs are distinct, we will make the assumption that the font has a vertical-right glyph baked
106                                 // into it.
107                                 if (data.glyph != verticalRightData.glyph)
108                                     return make_pair(data, page);
109                                 // The glyphs are identical, meaning that we should just use the horizontal glyph.
110                                 if (verticalRightData.fontData)
111                                     return make_pair(verticalRightData, verticalRightPage);
112                             }
113                         } else if (m_fontDescription.textOrientation() == TextOrientationUpright) {
114                             const SimpleFontData* uprightFontData = data.fontData->uprightOrientationFontData();
115                             GlyphPageTreeNode* uprightNode = GlyphPageTreeNode::getRootChild(uprightFontData, pageNumber);
116                             GlyphPage* uprightPage = uprightNode->page();
117                             if (uprightPage) {
118                                 GlyphData uprightData = uprightPage->glyphDataForCharacter(c);
119                                 // If the glyphs are the same, then we know we can just use the horizontal glyph rotated vertically to be upright.
120                                 if (data.glyph == uprightData.glyph)
121                                     return make_pair(data, page);
122                                 // The glyphs are distinct, meaning that the font has a vertical-right glyph baked into it. We can't use that
123                                 // glyph, so we fall back to the upright data and use the horizontal glyph.
124                                 if (uprightData.fontData)
125                                     return make_pair(uprightData, uprightPage);
126                             }
127                         }
128
129                         // Shouldn't be possible to even reach this point.
130                         ASSERT_NOT_REACHED();
131                     }
132                     return make_pair(data, page);
133                 }
134
135                 if (node->isSystemFallback())
136                     break;
137             }
138
139             // Proceed with the fallback list.
140             node = node->getChild(fontDataAt(node->level()), pageNumber);
141             if (pageNumber)
142                 m_fontList->m_pages.set(pageNumber, node);
143             else
144                 m_fontList->m_pageZero = node;
145         }
146     }
147     if (variant != NormalVariant) {
148         while (true) {
149             page = node->page();
150             if (page) {
151                 GlyphData data = page->glyphDataForCharacter(c);
152                 if (data.fontData) {
153                     // The variantFontData function should not normally return 0.
154                     // But if it does, we will just render the capital letter big.
155                     const SimpleFontData* variantFontData = data.fontData->variantFontData(m_fontDescription, variant);
156                     if (!variantFontData)
157                         return make_pair(data, page);
158
159                     GlyphPageTreeNode* variantNode = GlyphPageTreeNode::getRootChild(variantFontData, pageNumber);
160                     GlyphPage* variantPage = variantNode->page();
161                     if (variantPage) {
162                         GlyphData data = variantPage->glyphDataForCharacter(c);
163                         if (data.fontData)
164                             return make_pair(data, variantPage);
165                     }
166
167                     // Do not attempt system fallback off the variantFontData. This is the very unlikely case that
168                     // a font has the lowercase character but the small caps font does not have its uppercase version.
169                     return make_pair(variantFontData->missingGlyphData(), page);
170                 }
171
172                 if (node->isSystemFallback())
173                     break;
174             }
175
176             // Proceed with the fallback list.
177             node = node->getChild(fontDataAt(node->level()), pageNumber);
178             if (pageNumber)
179                 m_fontList->m_pages.set(pageNumber, node);
180             else
181                 m_fontList->m_pageZero = node;
182         }
183     }
184
185     ASSERT(page);
186     ASSERT(node->isSystemFallback());
187
188     // System fallback is character-dependent. When we get here, we
189     // know that the character in question isn't in the system fallback
190     // font's glyph page. Try to lazily create it here.
191     UChar codeUnits[2];
192     int codeUnitsLength;
193     if (c <= 0xFFFF) {
194         codeUnits[0] = Font::normalizeSpaces(c);
195         codeUnitsLength = 1;
196     } else {
197         codeUnits[0] = U16_LEAD(c);
198         codeUnits[1] = U16_TRAIL(c);
199         codeUnitsLength = 2;
200     }
201     const SimpleFontData* characterFontData = fontCache()->getFontDataForCharacters(*this, codeUnits, codeUnitsLength);
202     if (characterFontData) {
203         if (characterFontData->platformData().orientation() == Vertical && !characterFontData->hasVerticalGlyphs() && isCJKIdeographOrSymbol(c))
204             variant = BrokenIdeographVariant;
205         if (variant != NormalVariant)
206             characterFontData = characterFontData->variantFontData(m_fontDescription, variant);
207     }
208     if (characterFontData) {
209         // Got the fallback glyph and font.
210         GlyphPage* fallbackPage = GlyphPageTreeNode::getRootChild(characterFontData, pageNumber)->page();
211         GlyphData data = fallbackPage && fallbackPage->fontDataForCharacter(c) ? fallbackPage->glyphDataForCharacter(c) : characterFontData->missingGlyphData();
212         // Cache it so we don't have to do system fallback again next time.
213         if (variant == NormalVariant) {
214 #if OS(WINCE)
215             // missingGlyphData returns a null character, which is not suitable for GDI to display.
216             // Also, sometimes we cannot map a font for the character on WINCE, but GDI can still
217             // display the character, probably because the font package is not installed correctly.
218             // So we just always set the glyph to be same as the character, and let GDI solve it.
219             page->setGlyphDataForCharacter(c, c, characterFontData);
220             characterFontData->setMaxGlyphPageTreeLevel(max(characterFontData->maxGlyphPageTreeLevel(), node->level()));
221             return make_pair(page->glyphDataForCharacter(c), page);
222 #else
223             page->setGlyphDataForCharacter(c, data.glyph, data.fontData);
224             data.fontData->setMaxGlyphPageTreeLevel(max(data.fontData->maxGlyphPageTreeLevel(), node->level()));
225 #endif
226         }
227         return make_pair(data, page);
228     }
229
230     // Even system fallback can fail; use the missing glyph in that case.
231     // FIXME: It would be nicer to use the missing glyph from the last resort font instead.
232     GlyphData data = primaryFont()->missingGlyphData();
233     if (variant == NormalVariant) {
234 #if OS(WINCE)
235         // See comment about WINCE GDI handling near setGlyphDataForCharacter above.
236         page->setGlyphDataForCharacter(c, c, data.fontData);
237         data.fontData->setMaxGlyphPageTreeLevel(max(data.fontData->maxGlyphPageTreeLevel(), node->level()));
238         return make_pair(page->glyphDataForCharacter(c), page);
239 #else
240         page->setGlyphDataForCharacter(c, data.glyph, data.fontData);
241         data.fontData->setMaxGlyphPageTreeLevel(max(data.fontData->maxGlyphPageTreeLevel(), node->level()));
242 #endif
243     }
244     return make_pair(data, page);
245 }
246
247 bool Font::primaryFontHasGlyphForCharacter(UChar32 character) const
248 {
249     unsigned pageNumber = (character / GlyphPage::size);
250
251     GlyphPageTreeNode* node = GlyphPageTreeNode::getRootChild(primaryFont(), pageNumber);
252     GlyphPage* page = node->page();
253
254     return page && page->fontDataForCharacter(character);
255 }
256
257 // FIXME: This function may not work if the emphasis mark uses a complex script, but none of the
258 // standard emphasis marks do so.
259 bool Font::getEmphasisMarkGlyphData(const AtomicString& mark, GlyphData& glyphData) const
260 {
261     if (mark.isEmpty())
262         return false;
263
264     UChar32 character = mark[0];
265
266     if (U16_IS_SURROGATE(character)) {
267         if (!U16_IS_SURROGATE_LEAD(character))
268             return false;
269
270         if (mark.length() < 2)
271             return false;
272
273         UChar low = mark[1];
274         if (!U16_IS_TRAIL(low))
275             return false;
276
277         character = U16_GET_SUPPLEMENTARY(character, low);
278     }
279
280     glyphData = glyphDataForCharacter(character, false, EmphasisMarkVariant);
281     return true;
282 }
283
284 int Font::emphasisMarkAscent(const AtomicString& mark) const
285 {
286     GlyphData markGlyphData;
287     if (!getEmphasisMarkGlyphData(mark, markGlyphData))
288         return 0;
289
290     const SimpleFontData* markFontData = markGlyphData.fontData;
291     ASSERT(markFontData);
292     if (!markFontData)
293         return 0;
294
295     return markFontData->fontMetrics().ascent();
296 }
297
298 int Font::emphasisMarkDescent(const AtomicString& mark) const
299 {
300     GlyphData markGlyphData;
301     if (!getEmphasisMarkGlyphData(mark, markGlyphData))
302         return 0;
303
304     const SimpleFontData* markFontData = markGlyphData.fontData;
305     ASSERT(markFontData);
306     if (!markFontData)
307         return 0;
308
309     return markFontData->fontMetrics().descent();
310 }
311
312 int Font::emphasisMarkHeight(const AtomicString& mark) const
313 {
314     GlyphData markGlyphData;
315     if (!getEmphasisMarkGlyphData(mark, markGlyphData))
316         return 0;
317
318     const SimpleFontData* markFontData = markGlyphData.fontData;
319     ASSERT(markFontData);
320     if (!markFontData)
321         return 0;
322
323     return markFontData->fontMetrics().height();
324 }
325
326 float Font::getGlyphsAndAdvancesForSimpleText(const TextRun& run, int from, int to, GlyphBuffer& glyphBuffer, ForTextEmphasisOrNot forTextEmphasis) const
327 {
328     float initialAdvance;
329
330     WidthIterator it(this, run, 0, false, forTextEmphasis);
331     it.advance(from);
332     float beforeWidth = it.m_runWidthSoFar;
333     it.advance(to, &glyphBuffer);
334
335     if (glyphBuffer.isEmpty())
336         return 0;
337
338     float afterWidth = it.m_runWidthSoFar;
339
340     if (run.rtl()) {
341         float finalRoundingWidth = it.m_finalRoundingWidth;
342         it.advance(run.length());
343         initialAdvance = finalRoundingWidth + it.m_runWidthSoFar - afterWidth;
344     } else
345         initialAdvance = beforeWidth;
346
347     if (run.rtl()) {
348         for (int i = 0, end = glyphBuffer.size() - 1; i < glyphBuffer.size() / 2; ++i, --end)
349             glyphBuffer.swap(i, end);
350     }
351
352     return initialAdvance;
353 }
354
355 void Font::drawSimpleText(GraphicsContext* context, const TextRun& run, const FloatPoint& point, int from, int to) const
356 {
357     // This glyph buffer holds our glyphs+advances+font data for each glyph.
358     GlyphBuffer glyphBuffer;
359
360     float startX = point.x() + getGlyphsAndAdvancesForSimpleText(run, from, to, glyphBuffer);
361
362     if (glyphBuffer.isEmpty())
363         return;
364
365     FloatPoint startPoint(startX, point.y());
366     drawGlyphBuffer(context, run, glyphBuffer, startPoint);
367 }
368
369 void Font::drawEmphasisMarksForSimpleText(GraphicsContext* context, const TextRun& run, const AtomicString& mark, const FloatPoint& point, int from, int to) const
370 {
371     GlyphBuffer glyphBuffer;
372     float initialAdvance = getGlyphsAndAdvancesForSimpleText(run, from, to, glyphBuffer, ForTextEmphasis);
373
374     if (glyphBuffer.isEmpty())
375         return;
376
377     drawEmphasisMarks(context, run, glyphBuffer, mark, FloatPoint(point.x() + initialAdvance, point.y()));
378 }
379
380 void Font::drawGlyphBuffer(GraphicsContext* context, const TextRun& run, const GlyphBuffer& glyphBuffer, const FloatPoint& point) const
381 {   
382 #if !ENABLE(SVG_FONTS)
383     UNUSED_PARAM(run);
384 #endif
385
386     // Draw each contiguous run of glyphs that use the same font data.
387     const SimpleFontData* fontData = glyphBuffer.fontDataAt(0);
388     FloatSize offset = glyphBuffer.offsetAt(0);
389     FloatPoint startPoint(point);
390     float nextX = startPoint.x() + glyphBuffer.advanceAt(0);
391     int lastFrom = 0;
392     int nextGlyph = 1;
393 #if ENABLE(SVG_FONTS)
394     TextRun::RenderingContext* renderingContext = run.renderingContext();
395 #endif
396     while (nextGlyph < glyphBuffer.size()) {
397         const SimpleFontData* nextFontData = glyphBuffer.fontDataAt(nextGlyph);
398         FloatSize nextOffset = glyphBuffer.offsetAt(nextGlyph);
399
400         if (nextFontData != fontData || nextOffset != offset) {
401 #if ENABLE(SVG_FONTS)
402             if (renderingContext && fontData->isSVGFont())
403                 renderingContext->drawSVGGlyphs(context, run, fontData, glyphBuffer, lastFrom, nextGlyph - lastFrom, startPoint);
404             else
405 #endif
406                 drawGlyphs(context, fontData, glyphBuffer, lastFrom, nextGlyph - lastFrom, startPoint);
407
408             lastFrom = nextGlyph;
409             fontData = nextFontData;
410             offset = nextOffset;
411             startPoint.setX(nextX);
412         }
413         nextX += glyphBuffer.advanceAt(nextGlyph);
414         nextGlyph++;
415     }
416
417 #if ENABLE(SVG_FONTS)
418     if (renderingContext && fontData->isSVGFont())
419         renderingContext->drawSVGGlyphs(context, run, fontData, glyphBuffer, lastFrom, nextGlyph - lastFrom, startPoint);
420     else
421 #endif
422         drawGlyphs(context, fontData, glyphBuffer, lastFrom, nextGlyph - lastFrom, startPoint);
423 }
424
425 inline static float offsetToMiddleOfGlyph(const SimpleFontData* fontData, Glyph glyph)
426 {
427     if (fontData->platformData().orientation() == Horizontal) {
428         FloatRect bounds = fontData->boundsForGlyph(glyph);
429         return bounds.x() + bounds.width() / 2;
430     }
431     // FIXME: Use glyph bounds once they make sense for vertical fonts.
432     return fontData->widthForGlyph(glyph) / 2;
433 }
434
435 inline static float offsetToMiddleOfGlyphAtIndex(const GlyphBuffer& glyphBuffer, size_t i)
436 {
437     return offsetToMiddleOfGlyph(glyphBuffer.fontDataAt(i), glyphBuffer.glyphAt(i));
438 }
439
440 void Font::drawEmphasisMarks(GraphicsContext* context, const TextRun& run, const GlyphBuffer& glyphBuffer, const AtomicString& mark, const FloatPoint& point) const
441 {
442     GlyphData markGlyphData;
443     if (!getEmphasisMarkGlyphData(mark, markGlyphData))
444         return;
445
446     const SimpleFontData* markFontData = markGlyphData.fontData;
447     ASSERT(markFontData);
448     if (!markFontData)
449         return;
450
451     Glyph markGlyph = markGlyphData.glyph;
452     Glyph spaceGlyph = markFontData->spaceGlyph();
453
454     float middleOfLastGlyph = offsetToMiddleOfGlyphAtIndex(glyphBuffer, 0);
455     FloatPoint startPoint(point.x() + middleOfLastGlyph - offsetToMiddleOfGlyph(markFontData, markGlyph), point.y());
456
457     GlyphBuffer markBuffer;
458     for (int i = 0; i + 1 < glyphBuffer.size(); ++i) {
459         float middleOfNextGlyph = offsetToMiddleOfGlyphAtIndex(glyphBuffer, i + 1);
460         float advance = glyphBuffer.advanceAt(i) - middleOfLastGlyph + middleOfNextGlyph;
461         markBuffer.add(glyphBuffer.glyphAt(i) ? markGlyph : spaceGlyph, markFontData, advance);
462         middleOfLastGlyph = middleOfNextGlyph;
463     }
464     markBuffer.add(glyphBuffer.glyphAt(glyphBuffer.size() - 1) ? markGlyph : spaceGlyph, markFontData, 0);
465
466     drawGlyphBuffer(context, run, markBuffer, startPoint);
467 }
468
469 float Font::floatWidthForSimpleText(const TextRun& run, GlyphBuffer* glyphBuffer, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* glyphOverflow) const
470 {
471     WidthIterator it(this, run, fallbackFonts, glyphOverflow);
472     it.advance(run.length(), glyphBuffer);
473
474     if (glyphOverflow) {
475         glyphOverflow->top = max<int>(glyphOverflow->top, ceilf(-it.minGlyphBoundingBoxY()) - (glyphOverflow->computeBounds ? 0 : fontMetrics().ascent()));
476         glyphOverflow->bottom = max<int>(glyphOverflow->bottom, ceilf(it.maxGlyphBoundingBoxY()) - (glyphOverflow->computeBounds ? 0 : fontMetrics().descent()));
477         glyphOverflow->left = ceilf(it.firstGlyphOverflow());
478         glyphOverflow->right = ceilf(it.lastGlyphOverflow());
479     }
480
481     return it.m_runWidthSoFar;
482 }
483
484 FloatRect Font::selectionRectForSimpleText(const TextRun& run, const FloatPoint& point, int h, int from, int to) const
485 {
486     WidthIterator it(this, run);
487     it.advance(from);
488     float beforeWidth = it.m_runWidthSoFar;
489     it.advance(to);
490     float afterWidth = it.m_runWidthSoFar;
491
492     // Using roundf() rather than ceilf() for the right edge as a compromise to ensure correct caret positioning.
493     if (run.rtl()) {
494         it.advance(run.length());
495         float totalWidth = it.m_runWidthSoFar;
496         return FloatRect(floorf(point.x() + totalWidth - afterWidth), point.y(), roundf(point.x() + totalWidth - beforeWidth) - floorf(point.x() + totalWidth - afterWidth), h);
497     }
498
499     return FloatRect(floorf(point.x() + beforeWidth), point.y(), roundf(point.x() + afterWidth) - floorf(point.x() + beforeWidth), h);
500 }
501
502 int Font::offsetForPositionForSimpleText(const TextRun& run, float x, bool includePartialGlyphs) const
503 {
504     float delta = x;
505
506     WidthIterator it(this, run);
507     GlyphBuffer localGlyphBuffer;
508     unsigned offset;
509     if (run.rtl()) {
510         delta -= floatWidthForSimpleText(run, 0);
511         while (1) {
512             offset = it.m_currentCharacter;
513             float w;
514             if (!it.advanceOneCharacter(w, &localGlyphBuffer))
515                 break;
516             delta += w;
517             if (includePartialGlyphs) {
518                 if (delta - w / 2 >= 0)
519                     break;
520             } else {
521                 if (delta >= 0)
522                     break;
523             }
524         }
525     } else {
526         while (1) {
527             offset = it.m_currentCharacter;
528             float w;
529             if (!it.advanceOneCharacter(w, &localGlyphBuffer))
530                 break;
531             delta -= w;
532             if (includePartialGlyphs) {
533                 if (delta + w / 2 <= 0)
534                     break;
535             } else {
536                 if (delta <= 0)
537                     break;
538             }
539         }
540     }
541
542     return offset;
543 }
544
545 }