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.
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.
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.
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.
26 #include "FloatRect.h"
27 #include "FontCache.h"
28 #include "FontFallbackList.h"
29 #include "GlyphBuffer.h"
30 #include "GlyphPageTreeNode.h"
31 #include "SimpleFontData.h"
33 #include "WidthIterator.h"
34 #include <wtf/MathExtras.h>
35 #include <wtf/unicode/CharacterNames.h>
36 #include <wtf/unicode/Unicode.h>
39 using namespace Unicode;
43 GlyphData Font::glyphDataForCharacter(UChar32 c, bool mirror, FontDataVariant variant) const
45 ASSERT(isMainThread());
47 if (variant == AutoVariant) {
48 if (m_fontDescription.smallCaps()) {
49 UChar32 upperC = toUpper(c);
52 variant = SmallCapsVariant;
54 variant = NormalVariant;
56 variant = NormalVariant;
62 unsigned pageNumber = (c / GlyphPage::size);
64 GlyphPageTreeNode* node = pageNumber ? m_fontList->m_pages.get(pageNumber) : m_fontList->m_pageZero;
66 node = GlyphPageTreeNode::getRootChild(fontDataAt(0), pageNumber);
68 m_fontList->m_pages.set(pageNumber, node);
70 m_fontList->m_pageZero = node;
74 if (variant == NormalVariant) {
75 // Fastest loop, for the common case (normal variant).
79 GlyphData data = page->glyphDataForCharacter(c);
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();
86 GlyphData data = ideographPage->glyphDataForCharacter(c);
91 // Shouldn't be possible to even reach this point.
97 if (node->isSystemFallback())
101 // Proceed with the fallback list.
102 node = node->getChild(fontDataAt(node->level()), pageNumber);
104 m_fontList->m_pages.set(pageNumber, node);
106 m_fontList->m_pageZero = node;
112 GlyphData data = page->glyphDataForCharacter(c);
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)
120 GlyphPageTreeNode* variantNode = GlyphPageTreeNode::getRootChild(variantFontData, pageNumber);
121 const GlyphPage* variantPage = variantNode->page();
123 GlyphData data = variantPage->glyphDataForCharacter(c);
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();
133 if (node->isSystemFallback())
137 // Proceed with the fallback list.
138 node = node->getChild(fontDataAt(node->level()), pageNumber);
140 m_fontList->m_pages.set(pageNumber, node);
142 m_fontList->m_pageZero = node;
147 ASSERT(node->isSystemFallback());
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.
155 codeUnits[0] = Font::normalizeSpaces(c);
158 codeUnits[0] = U16_LEAD(c);
159 codeUnits[1] = U16_TRAIL(c);
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) {
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);
179 page->setGlyphDataForCharacter(c, data.glyph, data.fontData);
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) {
190 // See comment about WINCE GDI handling near setGlyphDataForCharacter above.
191 page->setGlyphDataForCharacter(c, c, data.fontData);
192 return page->glyphDataForCharacter(c);
194 page->setGlyphDataForCharacter(c, data.glyph, data.fontData);
200 bool Font::primaryFontHasGlyphForCharacter(UChar32 character) const
202 unsigned pageNumber = (character / GlyphPage::size);
204 GlyphPageTreeNode* node = GlyphPageTreeNode::getRootChild(primaryFont(), pageNumber);
205 GlyphPage* page = node->page();
207 return page && page->fontDataForCharacter(character);
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
217 #if ENABLE(SVG_FONTS)
218 // FIXME: Implement for SVG fonts.
219 if (primaryFont()->isSVGFont())
223 UChar32 character = mark[0];
225 if (U16_IS_SURROGATE(character)) {
226 if (!U16_IS_SURROGATE_LEAD(character))
229 if (mark.length() < 2)
233 if (!U16_IS_TRAIL(low))
236 character = U16_GET_SUPPLEMENTARY(character, low);
239 glyphData = glyphDataForCharacter(character, false, EmphasisMarkVariant);
243 int Font::emphasisMarkAscent(const AtomicString& mark) const
245 GlyphData markGlyphData;
246 if (!getEmphasisMarkGlyphData(mark, markGlyphData))
249 const SimpleFontData* markFontData = markGlyphData.fontData;
250 ASSERT(markFontData);
254 return markFontData->fontMetrics().ascent();
257 int Font::emphasisMarkDescent(const AtomicString& mark) const
259 GlyphData markGlyphData;
260 if (!getEmphasisMarkGlyphData(mark, markGlyphData))
263 const SimpleFontData* markFontData = markGlyphData.fontData;
264 ASSERT(markFontData);
268 return markFontData->fontMetrics().descent();
271 int Font::emphasisMarkHeight(const AtomicString& mark) const
273 GlyphData markGlyphData;
274 if (!getEmphasisMarkGlyphData(mark, markGlyphData))
277 const SimpleFontData* markFontData = markGlyphData.fontData;
278 ASSERT(markFontData);
282 return markFontData->fontMetrics().height();
285 float Font::getGlyphsAndAdvancesForSimpleText(const TextRun& run, int from, int to, GlyphBuffer& glyphBuffer, ForTextEmphasisOrNot forTextEmphasis) const
287 float initialAdvance;
289 WidthIterator it(this, run, 0, false, forTextEmphasis);
291 float beforeWidth = it.m_runWidthSoFar;
292 it.advance(to, &glyphBuffer);
294 if (glyphBuffer.isEmpty())
297 float afterWidth = it.m_runWidthSoFar;
300 it.advance(run.length());
301 initialAdvance = it.m_runWidthSoFar - afterWidth;
303 initialAdvance = beforeWidth;
306 for (int i = 0, end = glyphBuffer.size() - 1; i < glyphBuffer.size() / 2; ++i, --end)
307 glyphBuffer.swap(i, end);
310 return initialAdvance;
313 void Font::drawSimpleText(GraphicsContext* context, const TextRun& run, const FloatPoint& point, int from, int to) const
315 // This glyph buffer holds our glyphs+advances+font data for each glyph.
316 GlyphBuffer glyphBuffer;
318 float startX = point.x() + getGlyphsAndAdvancesForSimpleText(run, from, to, glyphBuffer);
320 if (glyphBuffer.isEmpty())
323 FloatPoint startPoint(startX, point.y());
324 drawGlyphBuffer(context, glyphBuffer, startPoint);
327 void Font::drawEmphasisMarksForSimpleText(GraphicsContext* context, const TextRun& run, const AtomicString& mark, const FloatPoint& point, int from, int to) const
329 GlyphBuffer glyphBuffer;
330 float initialAdvance = getGlyphsAndAdvancesForSimpleText(run, from, to, glyphBuffer, ForTextEmphasis);
332 if (glyphBuffer.isEmpty())
335 drawEmphasisMarks(context, glyphBuffer, mark, FloatPoint(point.x() + initialAdvance, point.y()));
338 void Font::drawGlyphBuffer(GraphicsContext* context, const GlyphBuffer& glyphBuffer, const FloatPoint& point) const
340 // Draw each contiguous run of glyphs that use the same font data.
341 const SimpleFontData* fontData = glyphBuffer.fontDataAt(0);
342 FloatSize offset = glyphBuffer.offsetAt(0);
343 FloatPoint startPoint(point);
344 float nextX = startPoint.x();
347 while (nextGlyph < glyphBuffer.size()) {
348 const SimpleFontData* nextFontData = glyphBuffer.fontDataAt(nextGlyph);
349 FloatSize nextOffset = glyphBuffer.offsetAt(nextGlyph);
350 if (nextFontData != fontData || nextOffset != offset) {
351 drawGlyphs(context, fontData, glyphBuffer, lastFrom, nextGlyph - lastFrom, startPoint);
353 lastFrom = nextGlyph;
354 fontData = nextFontData;
356 startPoint.setX(nextX);
358 nextX += glyphBuffer.advanceAt(nextGlyph);
362 drawGlyphs(context, fontData, glyphBuffer, lastFrom, nextGlyph - lastFrom, startPoint);
365 inline static float offsetToMiddleOfGlyph(const SimpleFontData* fontData, Glyph glyph)
367 if (fontData->orientation() == Horizontal) {
368 FloatRect bounds = fontData->boundsForGlyph(glyph);
369 return bounds.x() + bounds.width() / 2;
371 // FIXME: Use glyph bounds once they make sense for vertical fonts.
372 return fontData->widthForGlyph(glyph) / 2;
375 inline static float offsetToMiddleOfGlyphAtIndex(const GlyphBuffer& glyphBuffer, size_t i)
377 return offsetToMiddleOfGlyph(glyphBuffer.fontDataAt(i), glyphBuffer.glyphAt(i));
380 void Font::drawEmphasisMarks(GraphicsContext* context, const GlyphBuffer& glyphBuffer, const AtomicString& mark, const FloatPoint& point) const
382 GlyphData markGlyphData;
383 if (!getEmphasisMarkGlyphData(mark, markGlyphData))
386 const SimpleFontData* markFontData = markGlyphData.fontData;
387 ASSERT(markFontData);
391 Glyph markGlyph = markGlyphData.glyph;
392 Glyph spaceGlyph = markFontData->spaceGlyph();
394 float middleOfLastGlyph = offsetToMiddleOfGlyphAtIndex(glyphBuffer, 0);
395 FloatPoint startPoint(point.x() + middleOfLastGlyph - offsetToMiddleOfGlyph(markFontData, markGlyph), point.y());
397 GlyphBuffer markBuffer;
398 for (int i = 0; i + 1 < glyphBuffer.size(); ++i) {
399 float middleOfNextGlyph = offsetToMiddleOfGlyphAtIndex(glyphBuffer, i + 1);
400 float advance = glyphBuffer.advanceAt(i) - middleOfLastGlyph + middleOfNextGlyph;
401 markBuffer.add(glyphBuffer.glyphAt(i) ? markGlyph : spaceGlyph, markFontData, advance);
402 middleOfLastGlyph = middleOfNextGlyph;
404 markBuffer.add(glyphBuffer.glyphAt(glyphBuffer.size() - 1) ? markGlyph : spaceGlyph, markFontData, 0);
406 drawGlyphBuffer(context, markBuffer, startPoint);
409 float Font::floatWidthForSimpleText(const TextRun& run, GlyphBuffer* glyphBuffer, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* glyphOverflow) const
411 WidthIterator it(this, run, fallbackFonts, glyphOverflow);
412 it.advance(run.length(), glyphBuffer);
415 glyphOverflow->top = max<int>(glyphOverflow->top, ceilf(-it.minGlyphBoundingBoxY()) - fontMetrics().ascent());
416 glyphOverflow->bottom = max<int>(glyphOverflow->bottom, ceilf(it.maxGlyphBoundingBoxY()) - fontMetrics().descent());
417 glyphOverflow->left = ceilf(it.firstGlyphOverflow());
418 glyphOverflow->right = ceilf(it.lastGlyphOverflow());
421 return it.m_runWidthSoFar;
424 FloatRect Font::selectionRectForSimpleText(const TextRun& run, const FloatPoint& point, int h, int from, int to) const
426 WidthIterator it(this, run);
428 float beforeWidth = it.m_runWidthSoFar;
430 float afterWidth = it.m_runWidthSoFar;
432 // Using roundf() rather than ceilf() for the right edge as a compromise to ensure correct caret positioning.
434 it.advance(run.length());
435 float totalWidth = it.m_runWidthSoFar;
436 return FloatRect(point.x() + floorf(totalWidth - afterWidth), point.y(), roundf(totalWidth - beforeWidth) - floorf(totalWidth - afterWidth), h);
439 return FloatRect(point.x() + floorf(beforeWidth), point.y(), roundf(afterWidth) - floorf(beforeWidth), h);
442 int Font::offsetForPositionForSimpleText(const TextRun& run, float x, bool includePartialGlyphs) const
446 WidthIterator it(this, run);
447 GlyphBuffer localGlyphBuffer;
450 delta -= floatWidthForSimpleText(run, 0);
452 offset = it.m_currentCharacter;
454 if (!it.advanceOneCharacter(w, &localGlyphBuffer))
457 if (includePartialGlyphs) {
458 if (delta - w / 2 >= 0)
467 offset = it.m_currentCharacter;
469 if (!it.advanceOneCharacter(w, &localGlyphBuffer))
472 if (includePartialGlyphs) {
473 if (delta + w / 2 <= 0)