| 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");
 | 
|  }
 | 
|  
 | 
| 
 |