diff options
author | Victoria Lease <violets@google.com> | 2012-07-12 15:06:43 -0700 |
---|---|---|
committer | Victoria Lease <violets@google.com> | 2012-07-12 16:20:11 -0700 |
commit | 0dde4bb966a822beef3f067b7ad01941fd2c4d14 (patch) | |
tree | 72658eedb8e35785608f5345b2f8dc41ea5557ce /Source/WebCore/platform/graphics/android/fonts | |
parent | 675402ef4358583f64a2476927a548db4841c856 (diff) | |
download | external_webkit-0dde4bb966a822beef3f067b7ad01941fd2c4d14.zip external_webkit-0dde4bb966a822beef3f067b7ad01941fd2c4d14.tar.gz external_webkit-0dde4bb966a822beef3f067b7ad01941fd2c4d14.tar.bz2 |
approximate text bounds for recording context
Currently, SkPaint::measureText() is very, very slow. Fortunately, we
do not need precise text bounds and can live with approximated bounds
so long as the approximation is not smaller than the glyphs. We err
very much on the side of safety so as to play nicely with calligraphic
fonts and scripts that make heavy use of modifiers.
Change-Id: Id08f0856c0d902386089560fc3cfcdd853a06177
Diffstat (limited to 'Source/WebCore/platform/graphics/android/fonts')
-rw-r--r-- | Source/WebCore/platform/graphics/android/fonts/FontAndroid.cpp | 66 |
1 files changed, 53 insertions, 13 deletions
diff --git a/Source/WebCore/platform/graphics/android/fonts/FontAndroid.cpp b/Source/WebCore/platform/graphics/android/fonts/FontAndroid.cpp index 2bd77ee..132d5a4 100644 --- a/Source/WebCore/platform/graphics/android/fonts/FontAndroid.cpp +++ b/Source/WebCore/platform/graphics/android/fonts/FontAndroid.cpp @@ -178,13 +178,49 @@ static bool setupForText(SkPaint* paint, GraphicsContext* gc, return true; } -static FloatRect drawPosText(SkCanvas* canvas, const void* text, size_t byteLength, - const SkPoint pos[], const SkPaint& paint) +static void approximateTextBounds(FloatRect& rect, size_t numGlyphs, + const SkPoint pos[], float lineSpacing, bool isVertical) +{ + if (!numGlyphs || !pos) { + return; + } + + // get glyph position bounds + float minX = SkScalarToFloat(pos[0].x()); + float maxX = minX; + float minY = SkScalarToFloat(pos[0].y()); + float maxY = minY; + for (size_t i = 1; i < numGlyphs; ++i) { + float x = SkScalarToFloat(pos[i].x()); + float y = SkScalarToFloat(pos[i].y()); + minX = std::min(minX, x); + maxX = std::max(maxX, x); + minY = std::min(minY, y); + maxY = std::max(maxY, y); + } + + // set final rect + rect.setX(minX); + rect.setY(minY); + rect.setWidth(maxX - minX); + rect.setHeight(maxY - minY); + if (!isVertical) { + rect.inflateX(rect.width() * 2); + rect.inflateY(2 * lineSpacing); + } else { + rect.inflateX(2 * lineSpacing); + rect.inflateY(rect.height() * 2); + } +} + +static FloatRect drawPosText(SkCanvas* canvas, const void* text, + size_t byteLength, const SkPoint pos[], const SkPaint& paint, + float lineSpacing) { - SkRect textBounds; - paint.measureText(text, byteLength, &textBounds); - textBounds.offset(pos[0].x(), pos[0].y()); canvas->drawPosText(text, byteLength, pos, paint); + FloatRect textBounds; + approximateTextBounds(textBounds, byteLength / sizeof(uint16_t), pos, + lineSpacing, paint.isVerticalText()); return textBounds; } @@ -232,6 +268,7 @@ void Font::drawGlyphs(GraphicsContext* gc, const SimpleFontData* font, if (font->platformData().orientation() == Vertical) y += SkFloatToScalar(font->fontMetrics().floatAscent(IdeographicBaseline) - font->fontMetrics().floatAscent()); + float lineSpacing = font->fontMetrics().lineSpacing(); FloatRect textBounds; if (EmojiFont::IsAvailable()) { // set filtering, to make scaled images look nice(r) @@ -244,7 +281,7 @@ void Font::drawGlyphs(GraphicsContext* gc, const SimpleFontData* font, if (localCount) { textBounds.unite(drawPosText(canvas, &glyphs[localIndex], localCount * sizeof(uint16_t), - &pos[localIndex], paint)); + &pos[localIndex], paint, lineSpacing)); } EmojiFont::Draw(canvas, glyphs[i], x, y, paint); float size = paint.getTextSize(); @@ -264,7 +301,7 @@ void Font::drawGlyphs(GraphicsContext* gc, const SimpleFontData* font, if (localCount) { textBounds.unite(drawPosText(canvas, &glyphs[localIndex], localCount * sizeof(uint16_t), - &pos[localIndex], paint)); + &pos[localIndex], paint, lineSpacing)); } } else { for (int i = 0; i < numGlyphs; i++) { @@ -281,8 +318,8 @@ void Font::drawGlyphs(GraphicsContext* gc, const SimpleFontData* font, rotator.setRotate(90); rotator.mapPoints(pos, numGlyphs); } - textBounds.unite(drawPosText(canvas, glyphs, numGlyphs * sizeof(uint16_t), - pos, paint)); + textBounds.unite(drawPosText(canvas, glyphs, + numGlyphs * sizeof(uint16_t), pos, paint, lineSpacing)); if (font->platformData().orientation() == Vertical) canvas->restore(); @@ -1052,18 +1089,21 @@ void Font::drawComplexText(GraphicsContext* gc, TextRun const& run, walker.setPadding(run.expansion()); FloatRect textBounds; + SkScalar lineSpacing = fontMetrics().lineSpacing(); while (walker.nextScriptRun()) { if (fill) { walker.fontPlatformDataForScriptRun()->setupPaint(&fillPaint); adjustTextRenderMode(&fillPaint, haveMultipleLayers); - textBounds.unite(drawPosText(canvas, walker.glyphs(), walker.length() << 1, - walker.positions(), fillPaint)); + textBounds.unite(drawPosText(canvas, walker.glyphs(), + walker.length() << 1, walker.positions(), fillPaint, + lineSpacing)); } if (stroke) { walker.fontPlatformDataForScriptRun()->setupPaint(&strokePaint); adjustTextRenderMode(&strokePaint, haveMultipleLayers); - textBounds.unite(drawPosText(canvas, walker.glyphs(), walker.length() << 1, - walker.positions(), strokePaint)); + textBounds.unite(drawPosText(canvas, walker.glyphs(), + walker.length() << 1, walker.positions(), strokePaint, + lineSpacing)); } } |