| Index: src/pdf/SkPDFDevice.cpp
|
| diff --git a/src/pdf/SkPDFDevice.cpp b/src/pdf/SkPDFDevice.cpp
|
| index 8e417b1f529dbf9e4b41909175a9cf7107aeb940..8e76c442befaabe89e492455c631285d141fdeab 100644
|
| --- a/src/pdf/SkPDFDevice.cpp
|
| +++ b/src/pdf/SkPDFDevice.cpp
|
| @@ -1079,6 +1079,72 @@ static void write_wide_string(SkDynamicMemoryWStream* wStream,
|
| }
|
| }
|
|
|
| +namespace {
|
| +class GlyphPositioner {
|
| +public:
|
| + GlyphPositioner(SkDynamicMemoryWStream* content,
|
| + SkScalar textSkewX,
|
| + bool wideChars)
|
| + : fContent(content)
|
| + , fCurrentMatrixX(0.0f)
|
| + , fCurrentMatrixY(0.0f)
|
| + , fXAdvance(0.0f)
|
| + , fWideChars(wideChars)
|
| + , fInText(false) {
|
| + set_text_transform(0.0f, 0.0f, textSkewX, fContent);
|
| + }
|
| + ~GlyphPositioner() { SkASSERT(!fInText); /* flush first */ }
|
| + void flush() {
|
| + if (fInText) {
|
| + fContent->writeText("> Tj\n");
|
| + fInText = false;
|
| + }
|
| + }
|
| + void setWideChars(bool wideChars) {
|
| + if (fWideChars != wideChars) {
|
| + SkASSERT(!fInText);
|
| + fWideChars = wideChars;
|
| + }
|
| + }
|
| + void writeGlyph(SkScalar x,
|
| + SkScalar y,
|
| + SkScalar advanceWidth,
|
| + uint16_t glyph) {
|
| + SkScalar xPosition = x - fCurrentMatrixX;
|
| + SkScalar yPosition = y - fCurrentMatrixY;
|
| + if (xPosition != fXAdvance || yPosition != 0) {
|
| + this->flush();
|
| + SkPDFUtils::AppendScalar(xPosition, fContent);
|
| + fContent->writeText(" ");
|
| + SkPDFUtils::AppendScalar(-yPosition, fContent);
|
| + fContent->writeText(" Td ");
|
| + fCurrentMatrixX = x;
|
| + fCurrentMatrixY = y;
|
| + fXAdvance = 0;
|
| + }
|
| + if (!fInText) {
|
| + fContent->writeText("<");
|
| + fInText = true;
|
| + }
|
| + if (fWideChars) {
|
| + SkPDFUtils::WriteUInt16BE(fContent, glyph);
|
| + } else {
|
| + SkASSERT(0 == glyph >> 8);
|
| + SkPDFUtils::WriteUInt8(fContent, static_cast<uint8_t>(glyph));
|
| + }
|
| + fXAdvance += advanceWidth;
|
| + }
|
| +
|
| +private:
|
| + SkDynamicMemoryWStream* fContent;
|
| + SkScalar fCurrentMatrixX;
|
| + SkScalar fCurrentMatrixY;
|
| + SkScalar fXAdvance;
|
| + bool fWideChars;
|
| + bool fInText;
|
| +};
|
| +} // namespace
|
| +
|
| static void draw_transparent_text(SkPDFDevice* device,
|
| const SkDraw& d,
|
| const void* text, size_t len,
|
| @@ -1230,6 +1296,9 @@ void SkPDFDevice::drawPosText(const SkDraw& d, const void* text, size_t len,
|
| SkPaint::GlyphCacheProc glyphCacheProc = textPaint.getGlyphCacheProc(true);
|
| content.entry()->fContent.writeText("BT\n");
|
| this->updateFont(textPaint, glyphIDs[0], content.entry());
|
| + GlyphPositioner glyphPositioner(&content.entry()->fContent,
|
| + textPaint.getTextSkewX(),
|
| + content.entry()->fState.fFont->multiByteGlyphs());
|
| SkPDFGlyphSetMap* fontGlyphUsage = fDocument->getGlyphUsage();
|
| for (size_t i = 0; i < numGlyphs; i++) {
|
| SkPDFFont* font = content.entry()->fState.fFont;
|
| @@ -1237,8 +1306,10 @@ void SkPDFDevice::drawPosText(const SkDraw& d, const void* text, size_t len,
|
| if (font->glyphsToPDFFontEncoding(&encodedValue, 1) != 1) {
|
| // The current pdf font cannot encode the current glyph.
|
| // Try to get a pdf font which can encode the current glyph.
|
| + glyphPositioner.flush();
|
| this->updateFont(textPaint, glyphIDs[i], content.entry());
|
| font = content.entry()->fState.fFont;
|
| + glyphPositioner.setWideChars(font->multiByteGlyphs());
|
| if (font->glyphsToPDFFontEncoding(&encodedValue, 1) != 1) {
|
| SkDEBUGFAIL("PDF could not encode glyph.");
|
| continue;
|
| @@ -1248,13 +1319,12 @@ void SkPDFDevice::drawPosText(const SkDraw& d, const void* text, size_t len,
|
| fontGlyphUsage->noteGlyphUsage(font, &encodedValue, 1);
|
| SkScalar x = offset.x() + pos[i * scalarsPerPos];
|
| SkScalar y = offset.y() + (2 == scalarsPerPos ? pos[i * scalarsPerPos + 1] : 0);
|
| -
|
| align_text(glyphCacheProc, textPaint, glyphIDs + i, 1, &x, &y);
|
| - set_text_transform(x, y, textPaint.getTextSkewX(), &content.entry()->fContent);
|
| - write_wide_string(&content.entry()->fContent, &encodedValue, 1,
|
| - font->multiByteGlyphs());
|
| - content.entry()->fContent.writeText(" Tj\n");
|
| +
|
| + SkScalar advanceWidth = textPaint.measureText(&encodedValue, sizeof(uint16_t));
|
| + glyphPositioner.writeGlyph(x, y, advanceWidth, encodedValue);
|
| }
|
| + glyphPositioner.flush(); // Must flush before ending text object.
|
| content.entry()->fContent.writeText("ET\n");
|
| }
|
|
|
|
|