aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/pdf/SkPDFDevice.cpp
diff options
context:
space:
mode:
authorGravatar Hal Canary <halcanary@google.com>2018-07-23 10:50:49 -0400
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2018-07-23 15:14:24 +0000
commit98caedd213775b61d93a320909e947735c626968 (patch)
tree89d5a6867a44c99d315e9063fc2ae19043485058 /src/pdf/SkPDFDevice.cpp
parent5e6cd2affe41af71399c247fcd144e8d28a3ec16 (diff)
SkPDF: only draw text with SkglyphRuns
Change-Id: I24e79c73a9c65a5d6a974bf52b0d0aee21be07db Reviewed-on: https://skia-review.googlesource.com/142695 Commit-Queue: Hal Canary <halcanary@google.com> Reviewed-by: Herb Derby <herb@google.com>
Diffstat (limited to 'src/pdf/SkPDFDevice.cpp')
-rw-r--r--src/pdf/SkPDFDevice.cpp182
1 files changed, 53 insertions, 129 deletions
diff --git a/src/pdf/SkPDFDevice.cpp b/src/pdf/SkPDFDevice.cpp
index d7a0f501c1..88955a1b9c 100644
--- a/src/pdf/SkPDFDevice.cpp
+++ b/src/pdf/SkPDFDevice.cpp
@@ -1033,13 +1033,11 @@ public:
GlyphPositioner(SkDynamicMemoryWStream* content,
SkScalar textSkewX,
bool wideChars,
- bool defaultPositioning,
SkPoint origin)
: fContent(content)
, fCurrentMatrixOrigin(origin)
, fTextSkewX(textSkewX)
- , fWideChars(wideChars)
- , fDefaultPositioning(defaultPositioning) {
+ , fWideChars(wideChars) {
}
~GlyphPositioner() { this->flush(); }
void flush() {
@@ -1064,19 +1062,17 @@ public:
fCurrentMatrixOrigin.set(0.0f, 0.0f);
fInitialized = true;
}
- if (!fDefaultPositioning) {
- SkPoint position = xy - fCurrentMatrixOrigin;
- if (position != SkPoint{fXAdvance, 0}) {
- this->flush();
- SkPDFUtils::AppendScalar(position.x() - position.y() * fTextSkewX, fContent);
- fContent->writeText(" ");
- SkPDFUtils::AppendScalar(-position.y(), fContent);
- fContent->writeText(" Td ");
- fCurrentMatrixOrigin = xy;
- fXAdvance = 0;
- }
- fXAdvance += advanceWidth;
+ SkPoint position = xy - fCurrentMatrixOrigin;
+ if (position != SkPoint{fXAdvance, 0}) {
+ this->flush();
+ SkPDFUtils::AppendScalar(position.x() - position.y() * fTextSkewX, fContent);
+ fContent->writeText(" ");
+ SkPDFUtils::AppendScalar(-position.y(), fContent);
+ fContent->writeText(" Td ");
+ fCurrentMatrixOrigin = xy;
+ fXAdvance = 0;
}
+ fXAdvance += advanceWidth;
if (!fInText) {
fContent->writeText("<");
fInText = true;
@@ -1097,7 +1093,6 @@ private:
bool fWideChars;
bool fInText = false;
bool fInitialized = false;
- const bool fDefaultPositioning;
};
} // namespace
@@ -1115,30 +1110,15 @@ static void update_font(SkWStream* wStream, int fontIndex, SkScalar textSize) {
wStream->writeText(" Tf\n");
}
-static SkPath draw_text_as_path(const void* sourceText, size_t sourceByteCount,
- const SkScalar pos[], SkTextBlob::GlyphPositioning positioning,
- SkPoint offset, const SkPaint& srcPaint) {
+static void draw_glyph_run_as_path(SkPDFDevice* dev, const SkGlyphRun& glyphRun, SkPoint offset) {
SkPath path;
- int glyphCount;
- SkAutoTMalloc<SkPoint> tmpPoints;
- switch (positioning) {
- case SkTextBlob::kDefault_Positioning:
- srcPaint.getTextPath(sourceText, sourceByteCount, offset.x(), offset.y(), &path);
- break;
- case SkTextBlob::kHorizontal_Positioning:
- glyphCount = srcPaint.countText(sourceText, sourceByteCount);
- tmpPoints.realloc(glyphCount);
- for (int i = 0; i < glyphCount; ++i) {
- tmpPoints[i] = {pos[i] + offset.x(), offset.y()};
- }
- srcPaint.getPosTextPath(sourceText, sourceByteCount, tmpPoints.get(), &path);
- break;
- case SkTextBlob::kFull_Positioning:
- srcPaint.getPosTextPath(sourceText, sourceByteCount, (const SkPoint*)pos, &path);
- path.offset(offset.x(), offset.y());
- break;
- }
- return path;
+ SkASSERT(glyphRun.paint().getTextEncoding() == SkPaint::kGlyphID_TextEncoding);
+ glyphRun.paint().getPosTextPath(glyphRun.shuntGlyphsIDs().data(),
+ glyphRun.shuntGlyphsIDs().size() * sizeof(SkGlyphID),
+ glyphRun.positions().data(),
+ &path);
+ path.offset(offset.x(), offset.y());
+ dev->drawPath(path, glyphRun.paint(), nullptr, true);
}
static bool has_outline_glyph(SkGlyphID gid, SkGlyphCache* cache) {
@@ -1205,36 +1185,25 @@ static sk_sp<SkImage> image_from_mask(const SkMask& mask) {
}
}
-void SkPDFDevice::internalDrawText(
- const void* sourceText, size_t sourceByteCount,
- const SkScalar pos[], SkTextBlob::GlyphPositioning positioning,
- SkPoint offset, const SkPaint& srcPaint, const uint32_t* clusters,
- uint32_t textByteLength, const char* utf8Text) {
- if (0 == sourceByteCount || !sourceText || srcPaint.getTextSize() <= 0) {
- return;
- }
- if (this->hasEmptyClip()) {
+void SkPDFDevice::internalDrawGlyphRun(const SkGlyphRun& glyphRun, SkPoint offset) {
+
+ const SkGlyphID* glyphs = glyphRun.shuntGlyphsIDs().data();
+ uint32_t glyphCount = SkToU32(glyphRun.shuntGlyphsIDs().size());
+ const SkPaint& srcPaint = glyphRun.paint();
+ if (!glyphCount || !glyphs || srcPaint.getTextSize() <= 0 || this->hasEmptyClip()) {
return;
}
- NOT_IMPLEMENTED(srcPaint.isVerticalText(), false);
- if (srcPaint.isVerticalText()) {
- // Don't pretend we support drawing vertical text. It is not
- // clear to me how to switch to "vertical writing" mode in PDF.
- // Currently neither Chromium or Android set this flag.
- // https://bug.skia.org/5665
- }
if (srcPaint.getPathEffect()
- || srcPaint.getMaskFilter()
- || SkPaint::kFill_Style != srcPaint.getStyle()) {
+ || srcPaint.getMaskFilter()
+ || srcPaint.isVerticalText()
+ || SkPaint::kFill_Style != srcPaint.getStyle()) {
// Stroked Text doesn't work well with Type3 fonts.
- SkPath path = draw_text_as_path(sourceText, sourceByteCount, pos,
- positioning, offset, srcPaint);
- this->drawPath(path, srcPaint, nullptr, true);
- return;
+ return draw_glyph_run_as_path(this, glyphRun, offset);
}
SkPaint paint = calculate_text_paint(srcPaint);
remove_color_filter(&paint);
replace_srcmode_on_opaque_paint(&paint);
+ paint.setHinting(SkPaint::kNo_Hinting);
if (!paint.getTypeface()) {
paint.setTypeface(SkTypeface::MakeDefault());
}
@@ -1243,25 +1212,14 @@ void SkPDFDevice::internalDrawText(
SkDebugf("SkPDF: SkTypeface::MakeDefault() returned nullptr.\n");
return;
}
-
- const SkAdvancedTypefaceMetrics* metrics =
- SkPDFFont::GetMetrics(typeface, fDocument->canon());
+ const SkAdvancedTypefaceMetrics* metrics = SkPDFFont::GetMetrics(typeface, fDocument->canon());
if (!metrics) {
return;
}
const std::vector<SkUnichar>& glyphToUnicode = SkPDFFont::GetUnicodeMap(
typeface, fDocument->canon());
- SkClusterator clusterator(sourceText, sourceByteCount, paint,
- clusters, textByteLength, utf8Text);
- const SkGlyphID* glyphs = clusterator.glyphs();
- uint32_t glyphCount = clusterator.glyphCount();
- if (glyphCount == 0) {
- return;
- }
-
- bool defaultPositioning = (positioning == SkTextBlob::kDefault_Positioning);
- paint.setHinting(SkPaint::kNo_Hinting);
+ SkClusterator clusterator(glyphRun);
int emSize;
auto glyphCache = SkPDFFont::MakeVectorCache(typeface, &emSize);
@@ -1273,23 +1231,13 @@ void SkPDFDevice::internalDrawText(
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 :
- /* SkPaint::kRight_Align */ -1.0f;
- if (defaultPositioning && alignment != SkPaint::kLeft_Align) {
- SkScalar advance = 0;
- for (uint32_t i = 0; i < glyphCount; ++i) {
- advance += advanceScale * glyphCache->getGlyphIDAdvance(glyphs[i]).fAdvanceX;
- }
- offset.offset(alignmentFactor * advance, 0);
- }
+ SkASSERT(paint.getTextAlign() == SkPaint::kLeft_Align);
SkRect clipStackBounds = this->cs().bounds(this->bounds());
struct PositionedGlyph {
SkPoint fPos;
SkGlyphID fGlyph;
};
- SkTArray<PositionedGlyph> fMissingGlyphs;
+ SkTArray<PositionedGlyph> missingGlyphs;
{
ScopedContentEntry content(this, paint, true);
if (!content.entry()) {
@@ -1310,7 +1258,6 @@ void SkPDFDevice::internalDrawText(
GlyphPositioner glyphPositioner(out,
paint.getTextSkewX(),
multiByteGlyphs,
- defaultPositioning,
offset);
SkPDFFont* font = nullptr;
@@ -1374,45 +1321,33 @@ void SkPDFDevice::internalDrawText(
}
SkASSERT(font->multiByteGlyphs() == multiByteGlyphs);
}
- SkPoint xy = {0, 0};
- 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 + offset, gid});
+ SkPoint xy = glyphRun.positions()[index];
+ // 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};
}
+ if (!has_outline_glyph(gid, glyphCache.get())) {
+ missingGlyphs.push_back({xy + offset, gid});
+ }
+
font->noteGlyphUsage(gid);
SkGlyphID encodedGlyph = multiByteGlyphs ? gid : font->glyphToPDFFontEncoding(gid);
+ SkScalar advance = advanceScale * glyphCache->getGlyphIDAdvance(gid).fAdvanceX;
glyphPositioner.writeGlyph(xy, advance, encodedGlyph);
}
}
}
- if (fMissingGlyphs.count() > 0) {
+ if (missingGlyphs.count() > 0) {
// Fall back on images.
SkPaint scaledGlyphCachePaint;
scaledGlyphCachePaint.setTextSize(paint.getTextSize());
@@ -1422,7 +1357,7 @@ void SkPDFDevice::internalDrawText(
auto scaledGlyphCache = SkStrikeCache::FindOrCreateStrikeExclusive(scaledGlyphCachePaint);
SkTHashMap<SkPDFCanon::BitmapGlyphKey, SkPDFCanon::BitmapGlyph>* map =
&this->getCanon()->fBitmapGlyphImages;
- for (PositionedGlyph positionedGlyph : fMissingGlyphs) {
+ for (PositionedGlyph positionedGlyph : missingGlyphs) {
SkPDFCanon::BitmapGlyphKey key = {typeface->uniqueID(),
paint.getTextSize(),
paint.getTextScaleX(),
@@ -1451,20 +1386,9 @@ void SkPDFDevice::internalDrawText(
}
}
-void SkPDFDevice::drawPosText(const void* text, size_t len,
- const SkScalar pos[], int scalarsPerPos,
- const SkPoint& offset, const SkPaint& paint) {
- this->internalDrawText(text, len, pos, (SkTextBlob::GlyphPositioning)scalarsPerPos,
- offset, paint, nullptr, 0, nullptr);
-}
-
void SkPDFDevice::drawGlyphRunList(SkGlyphRunList* glyphRunList) {
- for (SkGlyphRunListIterator it(glyphRunList); !it.done(); it.next()) {
- SkPaint runPaint;
- it.applyFontToPaint(&runPaint);
- this->internalDrawText(it.glyphs(), sizeof(SkGlyphID) * it.glyphCount(),
- it.pos(), it.positioning(), glyphRunList->origin(), runPaint,
- it.clusters(), it.textSize(), it.text());
+ for (const SkGlyphRun& glyphRun : *glyphRunList) {
+ this->internalDrawGlyphRun(glyphRun, glyphRunList->origin());
}
}