aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/pdf/SkPDFDevice.cpp
diff options
context:
space:
mode:
authorGravatar Mike Reed <reed@google.com>2017-07-17 21:12:19 +0000
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-07-17 21:12:30 +0000
commit63b6f8b93209e593f60b235577f5b3d660396d5f (patch)
tree4864da686054d19002996f539b699e499018533a /src/pdf/SkPDFDevice.cpp
parent0983268dd52150fb968fb10bed2e8541095f12a1 (diff)
Revert "SkPDF: Non-outline glyphs as images"
This reverts commit 3cf6b79e50f148cae7ed8c6ec0cd79f1ede71c95. Reason for revert: breaking build ../../../../../work/skia/src/pdf/SkPDFDevice.cpp: In member function 'void SkPDFDevice::internalDrawText(const void*, size_t, const SkScalar*, SkTextBlob::GlyphPositioning, SkPoint, const SkPaint&, const uint32_t*, uint32_t, const char*)': ../../../../../work/skia/src/pdf/SkPDFDevice.cpp:1578:31: error: missing initializer for member 'SkPoint::fX' [-Werror=missing-field-initializers] SkPoint xy = {}; ^ Original change's description: > SkPDF: Non-outline glyphs as images > > - Cache images in PDF Canon for de-duping > - For now, rasterize at text scale. in the future, look at CTM and > fRasterScale. > - add a test that works on MacOS > > BUG=chromium:705480 > BUG=skia:3489 > Change-Id: I4fbc42f218e5b81ea15ea6cdccc61c91e532f6d0 > Reviewed-on: https://skia-review.googlesource.com/24080 > Commit-Queue: Hal Canary <halcanary@google.com> > Reviewed-by: Ben Wagner <bungeman@google.com> TBR=halcanary@google.com,bungeman@google.com Change-Id: I3d8800fcb33817c6065da0860a534eb14350d132 No-Presubmit: true No-Tree-Checks: true No-Try: true Bug: chromium:705480, skia:3489 Reviewed-on: https://skia-review.googlesource.com/24160 Reviewed-by: Mike Reed <reed@google.com> Commit-Queue: Mike Reed <reed@google.com>
Diffstat (limited to 'src/pdf/SkPDFDevice.cpp')
-rw-r--r--src/pdf/SkPDFDevice.cpp294
1 files changed, 96 insertions, 198 deletions
diff --git a/src/pdf/SkPDFDevice.cpp b/src/pdf/SkPDFDevice.cpp
index 7a2d51c848..bbc09f7ed6 100644
--- a/src/pdf/SkPDFDevice.cpp
+++ b/src/pdf/SkPDFDevice.cpp
@@ -1320,12 +1320,6 @@ static SkPath draw_text_as_path(const void* sourceText, size_t sourceByteCount,
return path;
}
-static bool has_outline_glyph(SkGlyphID gid, SkGlyphCache* cache) {
- const SkGlyph& glyph = cache->getGlyphIDMetrics(gid);
- const SkPath* path = cache->findPath(glyph);
- return (path && !path->isEmpty()) || (glyph.fWidth == 0 && glyph.fHeight == 0);
-}
-
static SkRect get_glyph_bounds_device_space(SkGlyphID gid, SkGlyphCache* cache,
SkScalar xScale, SkScalar yScale,
SkPoint xy, const SkMatrix& ctm) {
@@ -1344,46 +1338,6 @@ static bool contains(const SkRect& r, SkPoint p) {
r.top() <= p.y() && p.y() <= r.bottom();
}
-static sk_sp<SkImage> image_from_mask(const SkMask& mask) {
- if (!mask.fImage) {
- return nullptr;
- }
- SkIRect bounds = mask.fBounds;
- SkBitmap bm;
- switch (mask.fFormat) {
- case SkMask::kBW_Format:
- bm.allocPixels(SkImageInfo::MakeA8(bounds.width(), bounds.height()));
- for (int y = 0; y < bm.height(); ++y) {
- for (int x8 = 0; x8 < bm.width(); x8 += 8) {
- uint8_t v = *mask.getAddr1(x8 + bounds.x(), y + bounds.y());
- int e = SkTMin(x8 + 8, bm.width());
- for (int x = x8; x < e; ++x) {
- *bm.getAddr8(x, y) = (v >> (x & 0x7)) & 0x1 ? 0xFF : 0x00;
- }
- }
- }
- bm.setImmutable();
- return SkImage::MakeFromBitmap(bm);
- case SkMask::kA8_Format:
- bm.installPixels(SkImageInfo::MakeA8(bounds.width(), bounds.height()),
- mask.fImage, mask.fRowBytes);
- return SkMakeImageFromRasterBitmap(bm, kAlways_SkCopyPixelsMode);
- case SkMask::kARGB32_Format:
- bm.installPixels(SkImageInfo::MakeN32Premul(bounds.width(), bounds.height()),
- mask.fImage, mask.fRowBytes);
- return SkMakeImageFromRasterBitmap(bm, kAlways_SkCopyPixelsMode);
- case SkMask::k3D_Format:
- SkASSERT(false);
- return nullptr;
- case SkMask::kLCD16_Format:
- SkASSERT(false);
- return nullptr;
- default:
- SkASSERT(false);
- return nullptr;
- }
-}
-
void SkPDFDevice::internalDrawText(
const void* sourceText, size_t sourceByteCount,
const SkScalar pos[], SkTextBlob::GlyphPositioning positioning,
@@ -1485,169 +1439,113 @@ void SkPDFDevice::internalDrawText(
offset.offset(alignmentFactor * advance, 0);
}
SkRect clipStackBounds = this->cs().bounds(size(*this));
- struct PositionedGlyph {
- SkPoint fPos;
- SkGlyphID fGlyph;
- };
- SkTArray<PositionedGlyph> fMissingGlyphs;
- {
- ScopedContentEntry content(this, paint, true);
- if (!content.entry()) {
- return;
+ ScopedContentEntry content(this, paint, true);
+ if (!content.entry()) {
+ return;
+ }
+ SkDynamicMemoryWStream* out = content.stream();
+ const SkTDArray<SkUnichar>& glyphToUnicode = metrics->fGlyphToUnicode;
+
+ out->writeText("BT\n");
+ SK_AT_SCOPE_EXIT(out->writeText("ET\n"));
+
+ const SkGlyphID maxGlyphID = SkToU16(typeface->countGlyphs() - 1);
+
+ bool multiByteGlyphs = SkPDFFont::IsMultiByte(SkPDFFont::FontType(*metrics));
+ if (clusterator.reversedChars()) {
+ out->writeText("/ReversedChars BMC\n");
+ }
+ SK_AT_SCOPE_EXIT(if (clusterator.reversedChars()) { out->writeText("EMC\n"); } );
+ GlyphPositioner glyphPositioner(out,
+ paint.getTextSkewX(),
+ multiByteGlyphs,
+ defaultPositioning,
+ offset);
+ SkPDFFont* font = nullptr;
+
+ while (Clusterator::Cluster c = clusterator.next()) {
+ int index = c.fGlyphIndex;
+ int glyphLimit = index + c.fGlyphCount;
+
+ bool actualText = false;
+ SK_AT_SCOPE_EXIT(if (actualText) { glyphPositioner.flush(); out->writeText("EMC\n"); } );
+ if (c.fUtf8Text) { // real cluster
+ // Check if `/ActualText` needed.
+ const char* textPtr = c.fUtf8Text;
+ const char* textEnd = c.fUtf8Text + c.fTextByteLength;
+ SkUnichar unichar = SkUTF8_NextUnicharWithError(&textPtr, textEnd);
+ if (unichar < 0) {
+ return;
+ }
+ if (textPtr < textEnd || // more characters left
+ glyphLimit > index + 1 || // toUnicode wouldn't work
+ unichar != map_glyph(glyphToUnicode, glyphs[index])) // test single Unichar map
+ {
+ glyphPositioner.flush();
+ out->writeText("/Span<</ActualText <");
+ SkPDFUtils::WriteUTF16beHex(out, 0xFEFF); // U+FEFF = BYTE ORDER MARK
+ // the BOM marks this text as UTF-16BE, not PDFDocEncoding.
+ SkPDFUtils::WriteUTF16beHex(out, unichar); // first char
+ while (textPtr < textEnd) {
+ unichar = SkUTF8_NextUnicharWithError(&textPtr, textEnd);
+ if (unichar < 0) {
+ break;
+ }
+ SkPDFUtils::WriteUTF16beHex(out, unichar);
+ }
+ out->writeText("> >> BDC\n"); // begin marked-content sequence
+ // with an associated property list.
+ actualText = true;
+ }
}
- SkDynamicMemoryWStream* out = content.stream();
- const SkTDArray<SkUnichar>& glyphToUnicode = metrics->fGlyphToUnicode;
-
- out->writeText("BT\n");
- SK_AT_SCOPE_EXIT(out->writeText("ET\n"));
-
- const SkGlyphID maxGlyphID = SkToU16(typeface->countGlyphs() - 1);
-
- bool multiByteGlyphs = SkPDFFont::IsMultiByte(SkPDFFont::FontType(*metrics));
- if (clusterator.reversedChars()) {
- out->writeText("/ReversedChars BMC\n");
- }
- SK_AT_SCOPE_EXIT(if (clusterator.reversedChars()) { out->writeText("EMC\n"); } );
- GlyphPositioner glyphPositioner(out,
- paint.getTextSkewX(),
- multiByteGlyphs,
- defaultPositioning,
- offset);
- SkPDFFont* font = nullptr;
-
- while (Clusterator::Cluster c = clusterator.next()) {
- int index = c.fGlyphIndex;
- int glyphLimit = index + c.fGlyphCount;
-
- bool actualText = false;
- SK_AT_SCOPE_EXIT(if (actualText) {
- glyphPositioner.flush();
- out->writeText("EMC\n");
- });
- if (c.fUtf8Text) { // real cluster
- // Check if `/ActualText` needed.
- const char* textPtr = c.fUtf8Text;
- const char* textEnd = c.fUtf8Text + c.fTextByteLength;
- SkUnichar unichar = SkUTF8_NextUnicharWithError(&textPtr, textEnd);
- if (unichar < 0) {
+ for (; index < glyphLimit; ++index) {
+ SkGlyphID gid = glyphs[index];
+ if (gid > maxGlyphID) {
+ continue;
+ }
+ if (!font || !font->hasGlyph(gid)) {
+ // Not yet specified font or need to switch font.
+ int fontIndex = this->getFontResourceIndex(typeface, gid);
+ // All preconditions for SkPDFFont::GetFontResource are met.
+ SkASSERT(fontIndex >= 0);
+ if (fontIndex < 0) {
return;
}
- if (textPtr < textEnd || // more characters left
- glyphLimit > index + 1 || // toUnicode wouldn't work
- unichar != map_glyph(glyphToUnicode, glyphs[index])) // test single Unichar map
- {
- glyphPositioner.flush();
- out->writeText("/Span<</ActualText <");
- SkPDFUtils::WriteUTF16beHex(out, 0xFEFF); // U+FEFF = BYTE ORDER MARK
- // the BOM marks this text as UTF-16BE, not PDFDocEncoding.
- SkPDFUtils::WriteUTF16beHex(out, unichar); // first char
- while (textPtr < textEnd) {
- unichar = SkUTF8_NextUnicharWithError(&textPtr, textEnd);
- if (unichar < 0) {
- break;
- }
- SkPDFUtils::WriteUTF16beHex(out, unichar);
- }
- out->writeText("> >> BDC\n"); // begin marked-content sequence
- // with an associated property list.
- actualText = true;
+ glyphPositioner.flush();
+ update_font(out, fontIndex, textSize);
+ font = fFontResources[fontIndex];
+ SkASSERT(font); // All preconditions for SkPDFFont::GetFontResource are met.
+ if (!font) {
+ return;
}
+ SkASSERT(font->multiByteGlyphs() == multiByteGlyphs);
}
- for (; index < glyphLimit; ++index) {
- SkGlyphID gid = glyphs[index];
- if (gid > maxGlyphID) {
- continue;
+ SkPoint xy{0, 0};
+ SkScalar advance{0};
+ if (!defaultPositioning) {
+ advance = advanceScale * glyphCache->getGlyphIDAdvance(gid).fAdvanceX;
+ xy = SkTextBlob::kFull_Positioning == positioning
+ ? SkPoint{pos[2 * index], pos[2 * index + 1]}
+ : SkPoint{pos[index], 0};
+ if (alignment != SkPaint::kLeft_Align) {
+ xy.offset(alignmentFactor * advance, 0);
}
- if (!font || !font->hasGlyph(gid)) {
- // Not yet specified font or need to switch font.
- int fontIndex = this->getFontResourceIndex(typeface, gid);
- // All preconditions for SkPDFFont::GetFontResource are met.
- SkASSERT(fontIndex >= 0);
- if (fontIndex < 0) {
- return;
- }
- glyphPositioner.flush();
- update_font(out, fontIndex, textSize);
- font = fFontResources[fontIndex];
- SkASSERT(font); // All preconditions for SkPDFFont::GetFontResource are met.
- if (!font) {
- return;
- }
- SkASSERT(font->multiByteGlyphs() == multiByteGlyphs);
- }
- SkPoint xy = {};
- SkScalar advance = advanceScale * glyphCache->getGlyphIDAdvance(gid).fAdvanceX;
- if (!defaultPositioning) {
- xy = SkTextBlob::kFull_Positioning == positioning
- ? SkPoint{pos[2 * index], pos[2 * index + 1]}
- : SkPoint{pos[index], 0};
- 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
- }
- }
- if (!has_outline_glyph(gid, glyphCache.get())) {
- fMissingGlyphs.push_back({xy, gid});
+ // 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 (!has_outline_glyph(gid, glyphCache.get())) {
- fMissingGlyphs.push_back({offset, gid});
+ if (!clipStackBounds.intersects(glyphBounds)) {
+ continue; // reject glyphs as out of bounds
}
- offset += SkPoint{advance, 0};
}
- font->noteGlyphUsage(gid);
-
- SkGlyphID encodedGlyph = multiByteGlyphs ? gid : font->glyphToPDFFontEncoding(gid);
- glyphPositioner.writeGlyph(xy, advance, encodedGlyph);
- }
- }
- }
- if (fMissingGlyphs.count() > 0) {
- // Fall back on images.
- SkPaint scaledGlyphCachePaint;
- scaledGlyphCachePaint.setTextSize(paint.getTextSize());
- scaledGlyphCachePaint.setTextScaleX(paint.getTextScaleX());
- scaledGlyphCachePaint.setTextSkewX(paint.getTextSkewX());
- scaledGlyphCachePaint.setTypeface(sk_ref_sp(typeface));
- SkAutoGlyphCache scaledGlyphCache(scaledGlyphCachePaint, nullptr, nullptr);
- SkTHashMap<SkPDFCanon::BitmapGlyphKey, SkPDFCanon::BitmapGlyph>* map =
- &this->getCanon()->fBitmapGlyphImages;
- for (PositionedGlyph positionedGlyph : fMissingGlyphs) {
- SkPDFCanon::BitmapGlyphKey key = {typeface->uniqueID(),
- paint.getTextSize(),
- paint.getTextScaleX(),
- paint.getTextSkewX(),
- positionedGlyph.fGlyph,
- 0};
- SkImage* img = nullptr;
- SkIPoint imgOffset = {0, 0};
- if (SkPDFCanon::BitmapGlyph* ptr = map->find(key)) {
- img = ptr->fImage.get();
- imgOffset = ptr->fOffset;
- } else {
- (void)scaledGlyphCache->findImage(
- scaledGlyphCache->getGlyphIDMetrics(positionedGlyph.fGlyph));
- SkMask mask;
- scaledGlyphCache->getGlyphIDMetrics(positionedGlyph.fGlyph).toMask(&mask);
- imgOffset = {mask.fBounds.x(), mask.fBounds.y()};
- img = map->set(key, {image_from_mask(mask), imgOffset})->fImage.get();
- }
- if (img) {
- SkPoint pt = positionedGlyph.fPos +
- SkPoint{(SkScalar)imgOffset.x(), (SkScalar)imgOffset.y()};
- this->drawImage(img, pt.x(), pt.y(), srcPaint);
}
+ font->noteGlyphUsage(gid);
+ SkGlyphID encodedGlyph = multiByteGlyphs ? gid : font->glyphToPDFFontEncoding(gid);
+ glyphPositioner.writeGlyph(xy, advance, encodedGlyph);
}
}
}