aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar Hal Canary <halcanary@google.com>2017-06-13 12:13:29 -0400
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-06-14 21:51:36 +0000
commit699b8732bf7b1ea3fbcce0b77a60f96fc4f8446c (patch)
tree017e29e88aac43b435c322290128f95d8214ca51 /src
parent89c1c2552ec5b9ad8949988f7c9532a298b55987 (diff)
SkPDF: Glyph-by-glyph bounds-reject.
BUG=chromium:682644 Change-Id: I9d20dd81886d4de4e74ba043349d456230c89cb1 Reviewed-on: https://skia-review.googlesource.com/19706 Commit-Queue: Hal Canary <halcanary@google.com> Reviewed-by: Ben Wagner <bungeman@google.com>
Diffstat (limited to 'src')
-rw-r--r--src/pdf/SkPDFDevice.cpp35
1 files changed, 35 insertions, 0 deletions
diff --git a/src/pdf/SkPDFDevice.cpp b/src/pdf/SkPDFDevice.cpp
index cf3bf0d662..56bb616d40 100644
--- a/src/pdf/SkPDFDevice.cpp
+++ b/src/pdf/SkPDFDevice.cpp
@@ -1413,6 +1413,24 @@ static SkPath draw_text_as_path(const void* sourceText, size_t sourceByteCount,
return path;
}
+static SkRect get_glyph_bounds_device_space(SkGlyphID gid, SkGlyphCache* cache,
+ SkScalar xScale, SkScalar yScale,
+ SkPoint xy, const SkMatrix& ctm) {
+ const SkGlyph& glyph = cache->getGlyphIDMetrics(gid);
+ SkRect glyphBounds = {glyph.fLeft * xScale,
+ glyph.fTop * yScale,
+ (glyph.fLeft + glyph.fWidth) * xScale,
+ (glyph.fTop + glyph.fHeight) * yScale};
+ glyphBounds.offset(xy);
+ ctm.mapRect(&glyphBounds); // now in dev space.
+ return glyphBounds;
+}
+
+static bool contains(const SkRect& r, SkPoint p) {
+ return r.left() <= p.x() && p.x() <= r.right() &&
+ r.top() <= p.y() && p.y() <= r.bottom();
+}
+
void SkPDFDevice::internalDrawText(
const void* sourceText, size_t sourceByteCount,
const SkScalar pos[], SkTextBlob::GlyphPositioning positioning,
@@ -1498,6 +1516,10 @@ void SkPDFDevice::internalDrawText(
SkScalar textSize = paint.getTextSize();
SkScalar advanceScale = textSize * paint.getTextScaleX() / emSize;
+ // textScaleX and textScaleY are used to get a conservative bounding box for glyphs.
+ SkScalar textScaleY = textSize / emSize;
+ SkScalar textScaleX = advanceScale + paint.getTextSkewX() * textScaleY;
+
SkPaint::Align alignment = paint.getTextAlign();
float alignmentFactor = SkPaint::kLeft_Align == alignment ? 0.0f :
SkPaint::kCenter_Align == alignment ? -0.5f :
@@ -1509,6 +1531,7 @@ void SkPDFDevice::internalDrawText(
}
offset.offset(alignmentFactor * advance, 0);
}
+ SkRect clipStackBounds = this->cs().bounds(size(*this));
ScopedContentEntry content(this, paint, true);
if (!content.entry()) {
return;
@@ -1600,6 +1623,18 @@ void SkPDFDevice::internalDrawText(
if (alignment != SkPaint::kLeft_Align) {
xy.offset(alignmentFactor * advance, 0);
}
+ // Do a glyph-by-glyph bounds-reject if positions are absolute.
+ SkRect glyphBounds = get_glyph_bounds_device_space(
+ gid, glyphCache.get(), textScaleX, textScaleY, xy + offset, this->ctm());
+ if (glyphBounds.isEmpty()) {
+ if (!contains(clipStackBounds, {glyphBounds.x(), glyphBounds.y()})) {
+ continue;
+ }
+ } else {
+ if (!clipStackBounds.intersects(glyphBounds)) {
+ continue; // reject glyphs as out of bounds
+ }
+ }
}
font->noteGlyphUsage(gid);
SkGlyphID encodedGlyph = multiByteGlyphs ? gid : font->glyphToPDFFontEncoding(gid);