summaryrefslogtreecommitdiffstats
path: root/Source
diff options
context:
space:
mode:
authorVictoria Lease <violets@google.com>2012-07-12 15:06:43 -0700
committerVictoria Lease <violets@google.com>2012-07-12 16:20:11 -0700
commit0dde4bb966a822beef3f067b7ad01941fd2c4d14 (patch)
tree72658eedb8e35785608f5345b2f8dc41ea5557ce /Source
parent675402ef4358583f64a2476927a548db4841c856 (diff)
downloadexternal_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')
-rw-r--r--Source/WebCore/platform/graphics/android/fonts/FontAndroid.cpp66
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));
}
}