Index: Source/platform/fonts/Font.cpp |
diff --git a/Source/platform/fonts/Font.cpp b/Source/platform/fonts/Font.cpp |
index 2a3f5d3a1fdf23b067c134bf2b964035291dcb20..5ee5e3bc2178439359efe0f6f685a9d759e1423a 100644 |
--- a/Source/platform/fonts/Font.cpp |
+++ b/Source/platform/fonts/Font.cpp |
@@ -35,6 +35,7 @@ |
#include "platform/fonts/GlyphBuffer.h" |
#include "platform/fonts/GlyphPageTreeNode.h" |
#include "platform/fonts/SimpleFontData.h" |
+#include "platform/fonts/shaping/HarfBuzzFace.h" |
#include "platform/fonts/shaping/HarfBuzzShaper.h" |
#include "platform/fonts/shaping/SimpleShaper.h" |
#include "platform/geometry/FloatRect.h" |
@@ -60,12 +61,16 @@ Font::Font() |
Font::Font(const FontDescription& fd) |
: m_fontDescription(fd) |
+ , m_canShapeWordByWord(0) |
+ , m_shapeWordByWordComputed(0) |
{ |
} |
Font::Font(const Font& other) |
: m_fontDescription(other.m_fontDescription) |
, m_fontFallbackList(other.m_fontFallbackList) |
+ , m_canShapeWordByWord(0) |
+ , m_shapeWordByWordComputed(0) |
{ |
} |
@@ -73,6 +78,8 @@ Font& Font::operator=(const Font& other) |
{ |
m_fontDescription = other.m_fontDescription; |
m_fontFallbackList = other.m_fontFallbackList; |
+ m_canShapeWordByWord = other.m_canShapeWordByWord; |
+ m_shapeWordByWordComputed = other.m_shapeWordByWordComputed; |
return *this; |
} |
@@ -103,10 +110,17 @@ float Font::buildGlyphBuffer(const TextRunPaintInfo& runInfo, GlyphBuffer& glyph |
const GlyphData* emphasisData) const |
{ |
if (codePath(runInfo) == ComplexPath) { |
- HarfBuzzShaper shaper(this, runInfo.run, emphasisData); |
- shaper.setDrawRange(runInfo.from, runInfo.to); |
- shaper.shape(&glyphBuffer); |
- return shaper.totalWidth(); |
+ float width; |
+ CachingWordShaper& shaper = m_fontFallbackList->cachingWordShaper(); |
+ if (emphasisData) { |
+ width = shaper.fillGlyphBufferForTextEmphasis(this, runInfo.run, |
+ emphasisData, &glyphBuffer, runInfo.from, runInfo.to); |
+ } else { |
+ width = shaper.fillGlyphBuffer(this, runInfo.run, nullptr, |
+ &glyphBuffer, runInfo.from, runInfo.to); |
+ } |
+ |
+ return width; |
} |
SimpleShaper shaper(this, runInfo.run, emphasisData, nullptr /* fallbackFonts */, nullptr); |
@@ -337,6 +351,25 @@ CodePath Font::codePath(const TextRunPaintInfo& runInfo) const |
return Character::characterRangeCodePath(run.characters16(), run.length()); |
} |
+bool Font::canShapeWordByWord() const |
+{ |
+ if (!m_shapeWordByWordComputed) { |
+ m_canShapeWordByWord = computeCanShapeWordByWord(); |
+ m_shapeWordByWordComputed = true; |
+ } |
+ return m_canShapeWordByWord; |
+}; |
+ |
+bool Font::computeCanShapeWordByWord() const |
+{ |
+ if (!fontDescription().typesettingFeatures()) |
+ return true; |
+ |
+ const FontPlatformData& platformData = primaryFont()->platformData(); |
+ TypesettingFeatures features = fontDescription().typesettingFeatures(); |
+ return !platformData.hasSpaceInLigaturesOrKerning(features); |
+}; |
+ |
void Font::willUseFontData(UChar32 character) const |
{ |
const FontFamily& family = fontDescription().family(); |
@@ -663,39 +696,11 @@ void Font::drawTextBlob(SkCanvas* canvas, const SkPaint& paint, const SkTextBlob |
canvas->drawTextBlob(blob, origin.x(), origin.y(), paint); |
} |
-float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts, FloatRect* outGlyphBounds) const |
+float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts, FloatRect* glyphBounds) const |
{ |
- bool hasWordSpacingOrLetterSpacing = fontDescription().wordSpacing() |
- || fontDescription().letterSpacing(); |
- // Word spacing and letter spacing can change the width of a word. |
- // If a tab occurs inside a word, the width of the word varies based on its |
- // position on the line. |
- bool isCacheable = !hasWordSpacingOrLetterSpacing && !run.allowTabs(); |
- |
- WidthCacheEntry* cacheEntry = isCacheable |
- ? m_fontFallbackList->widthCache().add(run, WidthCacheEntry()) |
- : 0; |
- if (cacheEntry && cacheEntry->isValid()) { |
- if (outGlyphBounds) |
- *outGlyphBounds = cacheEntry->glyphBounds; |
- return cacheEntry->width; |
- } |
- |
- FloatRect glyphBounds; |
- HarfBuzzShaper shaper(this, run, nullptr, fallbackFonts, &glyphBounds); |
- if (!shaper.shape()) |
- return 0; |
- |
- float result = shaper.totalWidth(); |
- |
- if (cacheEntry && (!fallbackFonts || fallbackFonts->isEmpty())) { |
- cacheEntry->glyphBounds = glyphBounds; |
- cacheEntry->width = result; |
- } |
- |
- if (outGlyphBounds) |
- *outGlyphBounds = glyphBounds; |
- return result; |
+ CachingWordShaper& shaper = m_fontFallbackList->cachingWordShaper(); |
+ float width = shaper.width(this, run, fallbackFonts, glyphBounds); |
+ return width; |
} |
// Return the code point index for the given |x| offset into the text run. |
@@ -703,19 +708,18 @@ int Font::offsetForPositionForComplexText(const TextRun& run, float xFloat, |
bool includePartialGlyphs) const |
{ |
HarfBuzzShaper shaper(this, run); |
- if (!shaper.shape()) |
+ RefPtr<ShapeResult> shapeResult = shaper.shapeResult(); |
+ if (!shapeResult) |
return 0; |
- return shaper.offsetForPosition(xFloat); |
+ return shapeResult->offsetForPosition(xFloat); |
} |
// Return the rectangle for selecting the given range of code-points in the TextRun. |
FloatRect Font::selectionRectForComplexText(const TextRun& run, |
const FloatPoint& point, int height, int from, int to) const |
{ |
- HarfBuzzShaper shaper(this, run); |
- if (!shaper.shape()) |
- return FloatRect(); |
- return shaper.selectionRect(point, height, from, to); |
+ CachingWordShaper& shaper = m_fontFallbackList->cachingWordShaper(); |
+ return shaper.selectionRect(this, run, point, height, from, to); |
} |
void Font::drawGlyphBuffer(SkCanvas* canvas, const SkPaint& paint, const TextRunPaintInfo& runInfo, const GlyphBuffer& glyphBuffer, const FloatPoint& point, float deviceScaleFactor) const |