summaryrefslogtreecommitdiffstats
path: root/Source/WebCore/platform/graphics/FontFastPath.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebCore/platform/graphics/FontFastPath.cpp')
-rw-r--r--Source/WebCore/platform/graphics/FontFastPath.cpp125
1 files changed, 64 insertions, 61 deletions
diff --git a/Source/WebCore/platform/graphics/FontFastPath.cpp b/Source/WebCore/platform/graphics/FontFastPath.cpp
index 3ae0ad581..7ed7a9703 100644
--- a/Source/WebCore/platform/graphics/FontFastPath.cpp
+++ b/Source/WebCore/platform/graphics/FontFastPath.cpp
@@ -42,9 +42,38 @@ using namespace std;
namespace WebCore {
-GlyphData Font::glyphDataForCharacter(UChar32 c, bool mirror, FontDataVariant variant) const
+static inline std::pair<GlyphData, GlyphPage*> glyphDataAndPageForCharacterWithTextOrientation(UChar32 character, TextOrientation orientation, GlyphData& data, GlyphPage* page, unsigned pageNumber)
{
- return glyphDataAndPageForCharacter(c, mirror, variant).first;
+ if (orientation == TextOrientationVerticalRight) {
+ RefPtr<SimpleFontData> verticalRightFontData = data.fontData->verticalRightOrientationFontData();
+ GlyphPageTreeNode* verticalRightNode = GlyphPageTreeNode::getRootChild(verticalRightFontData.get(), pageNumber);
+ GlyphPage* verticalRightPage = verticalRightNode->page();
+ if (verticalRightPage) {
+ GlyphData verticalRightData = verticalRightPage->glyphDataForCharacter(character);
+ // If the glyphs are distinct, we will make the assumption that the font has a vertical-right glyph baked
+ // into it.
+ if (data.glyph != verticalRightData.glyph)
+ return make_pair(data, page);
+ // The glyphs are identical, meaning that we should just use the horizontal glyph.
+ if (verticalRightData.fontData)
+ return make_pair(verticalRightData, verticalRightPage);
+ }
+ } else if (orientation == TextOrientationUpright) {
+ RefPtr<SimpleFontData> uprightFontData = data.fontData->uprightOrientationFontData();
+ GlyphPageTreeNode* uprightNode = GlyphPageTreeNode::getRootChild(uprightFontData.get(), pageNumber);
+ GlyphPage* uprightPage = uprightNode->page();
+ if (uprightPage) {
+ GlyphData uprightData = uprightPage->glyphDataForCharacter(character);
+ // If the glyphs are the same, then we know we can just use the horizontal glyph rotated vertically to be upright.
+ if (data.glyph == uprightData.glyph)
+ return make_pair(data, page);
+ // The glyphs are distinct, meaning that the font has a vertical-right glyph baked into it. We can't use that
+ // glyph, so we fall back to the upright data and use the horizontal glyph.
+ if (uprightData.fontData)
+ return make_pair(uprightData, uprightPage);
+ }
+ }
+ return make_pair(data, page);
}
std::pair<GlyphData, GlyphPage*> Font::glyphDataAndPageForCharacter(UChar32 c, bool mirror, FontDataVariant variant) const
@@ -68,13 +97,13 @@ std::pair<GlyphData, GlyphPage*> Font::glyphDataAndPageForCharacter(UChar32 c, b
unsigned pageNumber = (c / GlyphPage::size);
- GlyphPageTreeNode* node = pageNumber ? m_fontList->m_pages.get(pageNumber) : m_fontList->m_pageZero;
+ GlyphPageTreeNode* node = pageNumber ? m_fontFallbackList->m_pages.get(pageNumber) : m_fontFallbackList->m_pageZero;
if (!node) {
node = GlyphPageTreeNode::getRootChild(fontDataAt(0), pageNumber);
if (pageNumber)
- m_fontList->m_pages.set(pageNumber, node);
+ m_fontFallbackList->m_pages.set(pageNumber, node);
else
- m_fontList->m_pageZero = node;
+ m_fontFallbackList->m_pageZero = node;
}
GlyphPage* page = 0;
@@ -95,40 +124,9 @@ std::pair<GlyphData, GlyphPage*> Font::glyphDataAndPageForCharacter(UChar32 c, b
variant = BrokenIdeographVariant;
break;
}
- } else {
- if (m_fontDescription.textOrientation() == TextOrientationVerticalRight) {
- const SimpleFontData* verticalRightFontData = data.fontData->verticalRightOrientationFontData();
- GlyphPageTreeNode* verticalRightNode = GlyphPageTreeNode::getRootChild(verticalRightFontData, pageNumber);
- GlyphPage* verticalRightPage = verticalRightNode->page();
- if (verticalRightPage) {
- GlyphData verticalRightData = verticalRightPage->glyphDataForCharacter(c);
- // If the glyphs are distinct, we will make the assumption that the font has a vertical-right glyph baked
- // into it.
- if (data.glyph != verticalRightData.glyph)
- return make_pair(data, page);
- // The glyphs are identical, meaning that we should just use the horizontal glyph.
- if (verticalRightData.fontData)
- return make_pair(verticalRightData, verticalRightPage);
- }
- } else if (m_fontDescription.textOrientation() == TextOrientationUpright) {
- const SimpleFontData* uprightFontData = data.fontData->uprightOrientationFontData();
- GlyphPageTreeNode* uprightNode = GlyphPageTreeNode::getRootChild(uprightFontData, pageNumber);
- GlyphPage* uprightPage = uprightNode->page();
- if (uprightPage) {
- GlyphData uprightData = uprightPage->glyphDataForCharacter(c);
- // If the glyphs are the same, then we know we can just use the horizontal glyph rotated vertically to be upright.
- if (data.glyph == uprightData.glyph)
- return make_pair(data, page);
- // The glyphs are distinct, meaning that the font has a vertical-right glyph baked into it. We can't use that
- // glyph, so we fall back to the upright data and use the horizontal glyph.
- if (uprightData.fontData)
- return make_pair(uprightData, uprightPage);
- }
- }
+ } else
+ return glyphDataAndPageForCharacterWithTextOrientation(c, m_fontDescription.textOrientation(), data, page, pageNumber);
- // Shouldn't be possible to even reach this point.
- ASSERT_NOT_REACHED();
- }
return make_pair(data, page);
}
@@ -139,9 +137,9 @@ std::pair<GlyphData, GlyphPage*> Font::glyphDataAndPageForCharacter(UChar32 c, b
// Proceed with the fallback list.
node = node->getChild(fontDataAt(node->level()), pageNumber);
if (pageNumber)
- m_fontList->m_pages.set(pageNumber, node);
+ m_fontFallbackList->m_pages.set(pageNumber, node);
else
- m_fontList->m_pageZero = node;
+ m_fontFallbackList->m_pageZero = node;
}
}
if (variant != NormalVariant) {
@@ -152,11 +150,11 @@ std::pair<GlyphData, GlyphPage*> Font::glyphDataAndPageForCharacter(UChar32 c, b
if (data.fontData) {
// The variantFontData function should not normally return 0.
// But if it does, we will just render the capital letter big.
- const SimpleFontData* variantFontData = data.fontData->variantFontData(m_fontDescription, variant);
+ RefPtr<SimpleFontData> variantFontData = data.fontData->variantFontData(m_fontDescription, variant);
if (!variantFontData)
return make_pair(data, page);
- GlyphPageTreeNode* variantNode = GlyphPageTreeNode::getRootChild(variantFontData, pageNumber);
+ GlyphPageTreeNode* variantNode = GlyphPageTreeNode::getRootChild(variantFontData.get(), pageNumber);
GlyphPage* variantPage = variantNode->page();
if (variantPage) {
GlyphData data = variantPage->glyphDataForCharacter(c);
@@ -176,9 +174,9 @@ std::pair<GlyphData, GlyphPage*> Font::glyphDataAndPageForCharacter(UChar32 c, b
// Proceed with the fallback list.
node = node->getChild(fontDataAt(node->level()), pageNumber);
if (pageNumber)
- m_fontList->m_pages.set(pageNumber, node);
+ m_fontFallbackList->m_pages.set(pageNumber, node);
else
- m_fontList->m_pageZero = node;
+ m_fontFallbackList->m_pageZero = node;
}
}
@@ -198,7 +196,7 @@ std::pair<GlyphData, GlyphPage*> Font::glyphDataAndPageForCharacter(UChar32 c, b
codeUnits[1] = U16_TRAIL(c);
codeUnitsLength = 2;
}
- const SimpleFontData* characterFontData = fontCache()->getFontDataForCharacters(*this, codeUnits, codeUnitsLength);
+ RefPtr<SimpleFontData> characterFontData = fontCache()->getFontDataForCharacters(*this, codeUnits, codeUnitsLength);
if (characterFontData) {
if (characterFontData->platformData().orientation() == Vertical && !characterFontData->hasVerticalGlyphs() && isCJKIdeographOrSymbol(c))
variant = BrokenIdeographVariant;
@@ -207,7 +205,7 @@ std::pair<GlyphData, GlyphPage*> Font::glyphDataAndPageForCharacter(UChar32 c, b
}
if (characterFontData) {
// Got the fallback glyph and font.
- GlyphPage* fallbackPage = GlyphPageTreeNode::getRootChild(characterFontData, pageNumber)->page();
+ GlyphPage* fallbackPage = GlyphPageTreeNode::getRootChild(characterFontData.get(), pageNumber)->page();
GlyphData data = fallbackPage && fallbackPage->fontDataForCharacter(c) ? fallbackPage->glyphDataForCharacter(c) : characterFontData->missingGlyphData();
// Cache it so we don't have to do system fallback again next time.
if (variant == NormalVariant) {
@@ -216,12 +214,14 @@ std::pair<GlyphData, GlyphPage*> Font::glyphDataAndPageForCharacter(UChar32 c, b
// Also, sometimes we cannot map a font for the character on WINCE, but GDI can still
// display the character, probably because the font package is not installed correctly.
// So we just always set the glyph to be same as the character, and let GDI solve it.
- page->setGlyphDataForCharacter(c, c, characterFontData);
+ page->setGlyphDataForCharacter(c, c, characterFontData.get());
characterFontData->setMaxGlyphPageTreeLevel(max(characterFontData->maxGlyphPageTreeLevel(), node->level()));
return make_pair(page->glyphDataForCharacter(c), page);
#else
page->setGlyphDataForCharacter(c, data.glyph, data.fontData);
data.fontData->setMaxGlyphPageTreeLevel(max(data.fontData->maxGlyphPageTreeLevel(), node->level()));
+ if (!isCJKIdeographOrSymbol(c) && data.fontData->platformData().orientation() != Horizontal && !data.fontData->isTextOrientationFallback())
+ return glyphDataAndPageForCharacterWithTextOrientation(c, m_fontDescription.textOrientation(), data, fallbackPage, pageNumber);
#endif
}
return make_pair(data, page);
@@ -328,7 +328,10 @@ float Font::getGlyphsAndAdvancesForSimpleText(const TextRun& run, int from, int
float initialAdvance;
WidthIterator it(this, run, 0, false, forTextEmphasis);
- it.advance(from);
+ // FIXME: Using separate glyph buffers for the prefix and the suffix is incorrect when kerning or
+ // ligatures are enabled.
+ GlyphBuffer localGlyphBuffer;
+ it.advance(from, &localGlyphBuffer);
float beforeWidth = it.m_runWidthSoFar;
it.advance(to, &glyphBuffer);
@@ -339,15 +342,13 @@ float Font::getGlyphsAndAdvancesForSimpleText(const TextRun& run, int from, int
if (run.rtl()) {
float finalRoundingWidth = it.m_finalRoundingWidth;
- it.advance(run.length());
+ it.advance(run.length(), &localGlyphBuffer);
initialAdvance = finalRoundingWidth + it.m_runWidthSoFar - afterWidth;
} else
initialAdvance = beforeWidth;
- if (run.rtl()) {
- for (int i = 0, end = glyphBuffer.size() - 1; i < glyphBuffer.size() / 2; ++i, --end)
- glyphBuffer.swap(i, end);
- }
+ if (run.rtl())
+ glyphBuffer.reverse(0, glyphBuffer.size());
return initialAdvance;
}
@@ -466,10 +467,11 @@ void Font::drawEmphasisMarks(GraphicsContext* context, const TextRun& run, const
drawGlyphBuffer(context, run, markBuffer, startPoint);
}
-float Font::floatWidthForSimpleText(const TextRun& run, GlyphBuffer* glyphBuffer, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* glyphOverflow) const
+float Font::floatWidthForSimpleText(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* glyphOverflow) const
{
WidthIterator it(this, run, fallbackFonts, glyphOverflow);
- it.advance(run.length(), glyphBuffer);
+ GlyphBuffer glyphBuffer;
+ it.advance(run.length(), (typesettingFeatures() & (Kerning | Ligatures)) ? &glyphBuffer : 0);
if (glyphOverflow) {
glyphOverflow->top = max<int>(glyphOverflow->top, ceilf(-it.minGlyphBoundingBoxY()) - (glyphOverflow->computeBounds ? 0 : fontMetrics().ascent()));
@@ -483,15 +485,16 @@ float Font::floatWidthForSimpleText(const TextRun& run, GlyphBuffer* glyphBuffer
FloatRect Font::selectionRectForSimpleText(const TextRun& run, const FloatPoint& point, int h, int from, int to) const
{
+ GlyphBuffer glyphBuffer;
WidthIterator it(this, run);
- it.advance(from);
+ it.advance(from, &glyphBuffer);
float beforeWidth = it.m_runWidthSoFar;
- it.advance(to);
+ it.advance(to, &glyphBuffer);
float afterWidth = it.m_runWidthSoFar;
// Using roundf() rather than ceilf() for the right edge as a compromise to ensure correct caret positioning.
if (run.rtl()) {
- it.advance(run.length());
+ it.advance(run.length(), &glyphBuffer);
float totalWidth = it.m_runWidthSoFar;
return FloatRect(floorf(point.x() + totalWidth - afterWidth), point.y(), roundf(point.x() + totalWidth - beforeWidth) - floorf(point.x() + totalWidth - afterWidth), h);
}
@@ -507,11 +510,11 @@ int Font::offsetForPositionForSimpleText(const TextRun& run, float x, bool inclu
GlyphBuffer localGlyphBuffer;
unsigned offset;
if (run.rtl()) {
- delta -= floatWidthForSimpleText(run, 0);
+ delta -= floatWidthForSimpleText(run);
while (1) {
offset = it.m_currentCharacter;
float w;
- if (!it.advanceOneCharacter(w, &localGlyphBuffer))
+ if (!it.advanceOneCharacter(w, localGlyphBuffer))
break;
delta += w;
if (includePartialGlyphs) {
@@ -526,7 +529,7 @@ int Font::offsetForPositionForSimpleText(const TextRun& run, float x, bool inclu
while (1) {
offset = it.m_currentCharacter;
float w;
- if (!it.advanceOneCharacter(w, &localGlyphBuffer))
+ if (!it.advanceOneCharacter(w, localGlyphBuffer))
break;
delta -= w;
if (includePartialGlyphs) {