Store content streams in an SkStream instead of an SkString (64k size limit).
authorvandebo@chromium.org <vandebo@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>
Mon, 28 Mar 2011 19:03:50 +0000 (19:03 +0000)
committervandebo@chromium.org <vandebo@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>
Mon, 28 Mar 2011 19:03:50 +0000 (19:03 +0000)
Review URL: http://codereview.appspot.com/4272070

git-svn-id: http://skia.googlecode.com/svn/trunk@1011 2bbb7eff-a529-9590-31e7-b0007b416f81

include/pdf/SkPDFDevice.h
include/pdf/SkPDFTypes.h
include/pdf/SkPDFUtils.h
src/pdf/SkPDFDevice.cpp
src/pdf/SkPDFFont.cpp
src/pdf/SkPDFTypes.cpp
src/pdf/SkPDFUtils.cpp

index 0efaafd..9292227 100644 (file)
@@ -19,7 +19,7 @@
 
 #include "SkRefCnt.h"
 #include "SkDevice.h"
-#include "SkString.h"
+#include "SkStream.h"
 #include "SkPaint.h"
 #include "SkPath.h"
 
@@ -175,7 +175,7 @@ private:
     struct GraphicStackEntry fGraphicStack[3];
     int fGraphicStackIndex;
 
-    SkString fContent;
+    SkDynamicMemoryWStream fContent;
 
     void updateGSFromPaint(const SkPaint& newPaint, bool forText);
     void updateFont(const SkPaint& paint, uint16_t glyphID);
index efa03c3..6b5146a 100644 (file)
@@ -151,7 +151,7 @@ public:
     explicit SkPDFScalar(SkScalar value);
     virtual ~SkPDFScalar();
 
-    static void Append(SkScalar value, SkString* string);
+    static void Append(SkScalar value, SkWStream* stream);
 
     // The SkPDFObject interface.
     virtual void emitObject(SkWStream* stream, SkPDFCatalog* catalog,
index 1f279c2..8c7d0c0 100644 (file)
@@ -32,19 +32,19 @@ class SkPDFArray;
 class SkPDFUtils {
 public:
     static SkPDFArray* MatrixToArray(const SkMatrix& matrix);
-    
-    static void MoveTo(SkScalar x, SkScalar y, SkString* content);
-    static void AppendLine(SkScalar x, SkScalar y, SkString* content);
+
+    static void MoveTo(SkScalar x, SkScalar y, SkWStream* content);
+    static void AppendLine(SkScalar x, SkScalar y, SkWStream* content);
     static void AppendCubic(SkScalar ctl1X, SkScalar ctl1Y,
                             SkScalar ctl2X, SkScalar ctl2Y,
-                            SkScalar dstX, SkScalar dstY, SkString* content);
+                            SkScalar dstX, SkScalar dstY, SkWStream* content);
     static void AppendRectangle(SkScalar x, SkScalar y, SkScalar w, SkScalar h,
-                                SkString* content);
-    static void EmitPath(const SkPath& path, SkString* content);
-    static void ClosePath(SkString* content);
+                                SkWStream* content);
+    static void EmitPath(const SkPath& path, SkWStream* content);
+    static void ClosePath(SkWStream* content);
     static void PaintPath(SkPaint::Style style, SkPath::FillType fill,
-                          SkString* content);
-    static void StrokePath(SkString* content);
+                          SkWStream* content);
+    static void StrokePath(SkWStream* content);
 };
 
 #endif
index a0e1d28..3665dd8 100644 (file)
 
 namespace {
 
-SkString toPDFColor(SkColor color) {
+void emitPDFColor(SkColor color, SkWStream* result) {
     SkASSERT(SkColorGetA(color) == 0xFF);  // We handle alpha elsewhere.
     SkScalar colorMax = SkIntToScalar(0xFF);
-    SkString result;
     SkPDFScalar::Append(
-            SkScalarDiv(SkIntToScalar(SkColorGetR(color)), colorMax), &result);
-    result.append(" ");
+            SkScalarDiv(SkIntToScalar(SkColorGetR(color)), colorMax), result);
+    result->writeText(" ");
     SkPDFScalar::Append(
-            SkScalarDiv(SkIntToScalar(SkColorGetG(color)), colorMax), &result);
-    result.append(" ");
+            SkScalarDiv(SkIntToScalar(SkColorGetG(color)), colorMax), result);
+    result->writeText(" ");
     SkPDFScalar::Append(
-            SkScalarDiv(SkIntToScalar(SkColorGetB(color)), colorMax), &result);
-    result.append(" ");
-    return result;
+            SkScalarDiv(SkIntToScalar(SkColorGetB(color)), colorMax), result);
+    result->writeText(" ");
 }
 
 SkPaint calculateTextPaint(const SkPaint& paint) {
@@ -145,7 +143,9 @@ SkPDFDevice::SkPDFDevice(int width, int height, OriginTransform flipOrigin)
     fGraphicStack[0].fTransform.reset();
 
     if (flipOrigin == kFlip_OriginTransform) {
-        fContent.printf("1 0 0 -1 0 %d cm\n", fHeight);
+        fContent.writeText("1 0 0 -1 0 ");
+        fContent.writeDecAsText(fHeight);
+        fContent.writeText(" cm\n");
     }
 }
 
@@ -175,9 +175,9 @@ void SkPDFDevice::setMatrixClip(const SkMatrix& matrix,
             NOT_IMPLEMENTED(clipFill == SkPath::kInverseWinding_FillType,
                             false);
             if (clipFill == SkPath::kEvenOdd_FillType)
-                fContent.append("W* n ");
+                fContent.writeText("W* n ");
             else
-                fContent.append("W n ");
+                fContent.writeText("W n ");
         }
 
         fGraphicStack[fGraphicStackIndex].fClip = region;
@@ -339,7 +339,7 @@ void SkPDFDevice::drawText(const SkDraw& d, const void* text, size_t len,
 
     SkDrawCacheProc glyphCacheProc = textPaint.getDrawCacheProc();
     alignText(glyphCacheProc, textPaint, glyphIDs, numGlyphs, &x, &y, widthPtr);
-    fContent.append("BT\n");
+    fContent.writeText("BT\n");
     setTextTransform(x, y, textPaint.getTextSkewX());
     size_t consumedGlyphCount = 0;
     while (numGlyphs > consumedGlyphCount) {
@@ -348,13 +348,14 @@ void SkPDFDevice::drawText(const SkDraw& d, const void* text, size_t len,
         size_t availableGlyphs =
             font->glyphsToPDFFontEncoding(glyphIDs + consumedGlyphCount,
                                           numGlyphs - consumedGlyphCount);
-        fContent.append(SkPDFString::formatString(glyphIDs + consumedGlyphCount,
-                                                  availableGlyphs,
-                                                  font->multiByteGlyphs()));
+        SkString encodedString =
+            SkPDFString::formatString(glyphIDs + consumedGlyphCount,
+                                      availableGlyphs, font->multiByteGlyphs());
+        fContent.writeText(encodedString.c_str());
         consumedGlyphCount += availableGlyphs;
-        fContent.append(" Tj\n");
+        fContent.writeText(" Tj\n");
     }
-    fContent.append("ET\n");
+    fContent.writeText("ET\n");
 
     // Draw underline and/or strikethrough if the paint has them.
     // drawPosText() and drawTextOnPath() don't draw underline or strikethrough
@@ -402,7 +403,7 @@ void SkPDFDevice::drawPosText(const SkDraw&, const void* text, size_t len,
     }
 
     SkDrawCacheProc glyphCacheProc = textPaint.getDrawCacheProc();
-    fContent.append("BT\n");
+    fContent.writeText("BT\n");
     updateFont(textPaint, glyphIDs[0]);
     for (size_t i = 0; i < numGlyphs; i++) {
         SkPDFFont* font = fGraphicStack[fGraphicStackIndex].fFont;
@@ -416,11 +417,13 @@ void SkPDFDevice::drawPosText(const SkDraw&, const void* text, size_t len,
         SkScalar y = scalarsPerPos == 1 ? constY : pos[i * scalarsPerPos + 1];
         alignText(glyphCacheProc, textPaint, glyphIDs + i, 1, &x, &y, NULL);
         setTextTransform(x, y, textPaint.getTextSkewX());
-        fContent.append(SkPDFString::formatString(&encodedValue, 1,
-                                                  font->multiByteGlyphs()));
-        fContent.append(" Tj\n");
+        SkString encodedString =
+            SkPDFString::formatString(&encodedValue, 1,
+                                      font->multiByteGlyphs());
+        fContent.writeText(encodedString.c_str());
+        fContent.writeText(" Tj\n");
     }
-    fContent.append("ET\n");
+    fContent.writeText("ET\n");
 }
 
 void SkPDFDevice::drawTextOnPath(const SkDraw&, const void* text, size_t len,
@@ -454,9 +457,9 @@ void SkPDFDevice::drawDevice(const SkDraw& d, SkDevice* device, int x, int y,
 
     SkPDFFormXObject* xobject = new SkPDFFormXObject(pdfDevice);
     fXObjectResources.push(xobject);  // Transfer reference.
-    fContent.append("/X");
-    fContent.appendS32(fXObjectResources.count() - 1);
-    fContent.append(" Do\n");
+    fContent.writeText("/X");
+    fContent.writeDecAsText(fXObjectResources.count() - 1);
+    fContent.writeText(" Do\n");
     setTransform(curTransform);
 }
 
@@ -571,9 +574,9 @@ SkRefPtr<SkPDFArray> SkPDFDevice::getMediaBox() const {
 }
 
 SkStream* SkPDFDevice::content() const {
-    size_t offset = fContent.size();
+    size_t offset = fContent.getOffset();
     char* data = (char*)sk_malloc_throw(offset + fGraphicStackIndex * 2);
-    memcpy(data, fContent.c_str(), offset);
+    fContent.copyTo(data);
     for (int i = 0; i < fGraphicStackIndex; i++) {
         data[offset++] = 'Q';
         data[offset++] = '\n';
@@ -637,8 +640,11 @@ void SkPDFDevice::updateGSFromPaint(const SkPaint& paint, bool forText) {
                 fShaderResources.push(pdfShader.get());
                 pdfShader->ref();
             }
-            fContent.appendf("/Pattern CS /Pattern cs /P%d SCN /P%d scn\n",
-                             resourceIndex, resourceIndex);
+            fContent.writeText("/Pattern CS /Pattern cs /P");
+            fContent.writeDecAsText(resourceIndex);
+            fContent.writeText(" SCN /P");
+            fContent.writeDecAsText(resourceIndex);
+            fContent.writeText(" scn\n");
             fGraphicStack[fGraphicStackIndex].fShader = pdfShader.get();
         }
     } else {
@@ -646,11 +652,10 @@ void SkPDFDevice::updateGSFromPaint(const SkPaint& paint, bool forText) {
         newColor = SkColorSetA(newColor, 0xFF);
         if (fGraphicStack[fGraphicStackIndex].fShader ||
                 fGraphicStack[fGraphicStackIndex].fColor != newColor) {
-            SkString colorString = toPDFColor(newColor);
-            fContent.append(colorString);
-            fContent.append("RG ");
-            fContent.append(colorString);
-            fContent.append("rg\n");
+            emitPDFColor(newColor, &fContent);
+            fContent.writeText("RG ");
+            emitPDFColor(newColor, &fContent);
+            fContent.writeText("rg\n");
             fGraphicStack[fGraphicStackIndex].fColor = newColor;
             fGraphicStack[fGraphicStackIndex].fShader = NULL;
         }
@@ -669,9 +674,9 @@ void SkPDFDevice::updateGSFromPaint(const SkPaint& paint, bool forText) {
             fGraphicStateResources.push(newGraphicState.get());
             newGraphicState->ref();
         }
-        fContent.append("/G");
-        fContent.appendS32(resourceIndex);
-        fContent.append(" gs\n");
+        fContent.writeText("/G");
+        fContent.writeDecAsText(resourceIndex);
+        fContent.writeText(" gs\n");
         fGraphicStack[fGraphicStackIndex].fGraphicState = newGraphicState.get();
     }
 
@@ -681,7 +686,7 @@ void SkPDFDevice::updateGSFromPaint(const SkPaint& paint, bool forText) {
             SkScalar scale = newPaint.getTextScaleX();
             SkScalar pdfScale = SkScalarMul(scale, SkIntToScalar(100));
             SkPDFScalar::Append(pdfScale, &fContent);
-            fContent.append(" Tz\n");
+            fContent.writeText(" Tz\n");
             fGraphicStack[fGraphicStackIndex].fTextScaleX = scale;
         }
 
@@ -692,8 +697,8 @@ void SkPDFDevice::updateGSFromPaint(const SkPaint& paint, bool forText) {
                               enum_must_match_value);
             SK_COMPILE_ASSERT(SkPaint::kStrokeAndFill_Style == 2,
                               enum_must_match_value);
-            fContent.appendS32(newPaint.getStyle());
-            fContent.append(" Tr\n");
+            fContent.writeDecAsText(newPaint.getStyle());
+            fContent.writeText(" Tr\n");
             fGraphicStack[fGraphicStackIndex].fTextFill = newPaint.getStyle();
         }
     }
@@ -706,11 +711,11 @@ void SkPDFDevice::updateFont(const SkPaint& paint, uint16_t glyphID) {
             fGraphicStack[fGraphicStackIndex].fFont->typeface() != typeface ||
             !fGraphicStack[fGraphicStackIndex].fFont->hasGlyph(glyphID)) {
         int fontIndex = getFontResourceIndex(typeface, glyphID);
-        fContent.append("/F");
-        fContent.appendS32(fontIndex);
-        fContent.append(" ");
+        fContent.writeText("/F");
+        fContent.writeDecAsText(fontIndex);
+        fContent.writeText(" ");
         SkPDFScalar::Append(paint.getTextSize(), &fContent);
-        fContent.append(" Tf\n");
+        fContent.writeText(" Tf\n");
         fGraphicStack[fGraphicStackIndex].fTextSize = paint.getTextSize();
         fGraphicStack[fGraphicStackIndex].fFont = fFontResources[fontIndex];
     }
@@ -730,27 +735,27 @@ int SkPDFDevice::getFontResourceIndex(SkTypeface* typeface, uint16_t glyphID) {
 
 void SkPDFDevice::pushGS() {
     SkASSERT(fGraphicStackIndex < 2);
-    fContent.append("q\n");
+    fContent.writeText("q\n");
     fGraphicStackIndex++;
     fGraphicStack[fGraphicStackIndex] = fGraphicStack[fGraphicStackIndex - 1];
 }
 
 void SkPDFDevice::popGS() {
     SkASSERT(fGraphicStackIndex > 0);
-    fContent.append("Q\n");
+    fContent.writeText("Q\n");
     fGraphicStackIndex--;
 }
 
 void SkPDFDevice::setTextTransform(SkScalar x, SkScalar y, SkScalar textSkewX) {
     // Flip the text about the x-axis to account for origin swap and include
     // the passed parameters.
-    fContent.append("1 0 ");
+    fContent.writeText("1 0 ");
     SkPDFScalar::Append(0 - textSkewX, &fContent);
-    fContent.append(" -1 ");
+    fContent.writeText(" -1 ");
     SkPDFScalar::Append(x, &fContent);
-    fContent.append(" ");
+    fContent.writeText(" ");
     SkPDFScalar::Append(y, &fContent);
-    fContent.append(" Tm\n");
+    fContent.writeText(" Tm\n");
 }
 
 void SkPDFDevice::internalDrawBitmap(const SkMatrix& matrix,
@@ -777,9 +782,9 @@ void SkPDFDevice::internalDrawBitmap(const SkMatrix& matrix,
     updateGSFromPaint(paint, false);
 
     fXObjectResources.push(image);  // Transfer reference.
-    fContent.append("/X");
-    fContent.appendS32(fXObjectResources.count() - 1);
-    fContent.append(" Do\n");
+    fContent.writeText("/X");
+    fContent.writeDecAsText(fXObjectResources.count() - 1);
+    fContent.writeText(" Do\n");
     setTransform(curTransform);
 }
 
@@ -807,9 +812,9 @@ SkMatrix SkPDFDevice::setTransform(const SkMatrix& m) {
     SkAssertResult(m.pdfTransform(transform));
     for (size_t i = 0; i < SK_ARRAY_COUNT(transform); i++) {
         SkPDFScalar::Append(transform[i], &fContent);
-        fContent.append(" ");
+        fContent.writeText(" ");
     }
-    fContent.append("cm\n");
+    fContent.writeText("cm\n");
     fGraphicStack[fGraphicStackIndex].fTransform = m;
 
     return old;
index e0da5af..83caea5 100644 (file)
@@ -236,11 +236,18 @@ SkScalar scaleFromFontUnits(int16_t val, uint16_t emSize) {
 }
 
 void setGlyphWidthAndBoundingBox(SkScalar width, SkIRect box,
-                                 SkString* content) {
+                                 SkWStream* content) {
     // Specify width and bounding box for the glyph.
     SkPDFScalar::Append(width, content);
-    content->appendf(" 0 %d %d %d %d d1\n", box.fLeft, box.fTop,
-                                            box.fRight, box.fBottom);
+    content->writeText(" 0 ");
+    content->writeDecAsText(box.fLeft);
+    content->writeText(" ");
+    content->writeDecAsText(box.fTop);
+    content->writeText(" ");
+    content->writeDecAsText(box.fRight);
+    content->writeText(" ");
+    content->writeDecAsText(box.fBottom);
+    content->writeText(" d1\n");
 }
 
 SkPDFArray* makeFontBBox(
@@ -670,7 +677,7 @@ void SkPDFFont::populateType3Font(int16_t glyphID) {
                                               glyph.fWidth, glyph.fHeight);
         bbox.join(glyphBBox);
 
-        SkString content;
+        SkDynamicMemoryWStream content;
         setGlyphWidthAndBoundingBox(SkFixedToScalar(glyph.fAdvanceX), glyphBBox,
                                     &content);
         const SkPath* path = cache->findPath(glyph);
@@ -679,9 +686,10 @@ void SkPDFFont::populateType3Font(int16_t glyphID) {
             SkPDFUtils::PaintPath(paint.getStyle(), path->getFillType(),
                                   &content);
         }
-        SkRefPtr<SkStream> glyphStream =
-            new SkMemoryStream(content.c_str(), content.size(), true);
+        SkRefPtr<SkMemoryStream> glyphStream = new SkMemoryStream();
         glyphStream->unref();  // SkRefPtr and new both took a ref.
+        glyphStream->setMemoryOwned(content.detach(), content.getOffset());
+
         SkRefPtr<SkPDFStream> glyphDescription =
             new SkPDFStream(glyphStream.get());
         // SkRefPtr and new both ref()'d charProcs, pass one.
index bbeeeeb..cb1c178 100644 (file)
@@ -100,32 +100,31 @@ void SkPDFScalar::emitObject(SkWStream* stream, SkPDFCatalog* catalog,
     if (indirect)
         return emitIndirectObject(stream, catalog);
 
-    SkString tmp;
-    Append(fValue, &tmp);
-    stream->write(tmp.c_str(), tmp.size());
+    Append(fValue, stream);
 }
 
 // static
-void SkPDFScalar::Append(SkScalar value, SkString* string) {
+void SkPDFScalar::Append(SkScalar value, SkWStream* stream) {
     // The range of reals in PDF/A is the same as SkFixed: +/- 32,767 and
     // +/- 1/65,536 (though integers can range from 2^31 - 1 to -2^31).
     // When using floats that are outside the whole value range, we can use
     // integers instead.
 
+
 #if defined(SK_SCALAR_IS_FIXED)
-    string->appendScalar(value);
+    stream->wrieScalarAsText(value);
     return;
 #endif  // SK_SCALAR_IS_FIXED
 
 #if !defined(SK_ALLOW_LARGE_PDF_SCALARS)
     if (value > 32767 || value < -32767) {
-        string->appendS32(SkScalarRound(value));
+        stream->writeDecAsText(SkScalarRound(value));
         return;
     }
 
     char buffer[SkStrAppendScalar_MaxSize];
     char* end = SkStrAppendFixed(buffer, SkScalarToFixed(value));
-    string->append(buffer, end - buffer);
+    stream->write(buffer, end - buffer);
     return;
 #endif  // !SK_ALLOW_LARGE_PDF_SCALARS
 
@@ -134,12 +133,12 @@ void SkPDFScalar::Append(SkScalar value, SkString* string) {
     // no more precise than an int. (Plus PDF doesn't support scientific
     // notation, so this clamps to SK_Max/MinS32).
     if (value > (1 << 24) || value < -(1 << 24)) {
-        string->appendS32(value);
+        stream->writeDecAsText(value);
         return;
     }
     // Continue to enforce the PDF limits for small floats.
     if (value < 1.0f/65536 && value > -1.0f/65536) {
-        string->appendS32(0);
+        stream->writeDecAsText(0);
         return;
     }
     // SkStrAppendFloat might still use scientific notation, so use snprintf
@@ -154,7 +153,7 @@ void SkPDFScalar::Append(SkScalar value, SkString* string) {
     if (buffer[len - 1] == '.') {
         buffer[len - 1] = '\0';
     }
-    string->append(buffer);
+    stream->writeText(buffer);
     return;
 #endif  // SK_SCALAR_IS_FLOAT && SK_ALLOW_LARGE_PDF_SCALARS
 }
index 874ee8f..8bd9c8f 100644 (file)
@@ -17,6 +17,7 @@
 #include "SkPaint.h"
 #include "SkPath.h"
 #include "SkPDFUtils.h"
+#include "SkStream.h"
 #include "SkString.h"
 #include "SkPDFTypes.h"
 
@@ -34,59 +35,59 @@ SkPDFArray* SkPDFUtils::MatrixToArray(const SkMatrix& matrix) {
 }
 
 // static
-void SkPDFUtils::MoveTo(SkScalar x, SkScalar y, SkString* content) {
+void SkPDFUtils::MoveTo(SkScalar x, SkScalar y, SkWStream* content) {
     SkPDFScalar::Append(x, content);
-    content->append(" ");
+    content->writeText(" ");
     SkPDFScalar::Append(y, content);
-    content->append(" m\n");
+    content->writeText(" m\n");
 }
 
 // static
-void SkPDFUtils::AppendLine(SkScalar x, SkScalar y, SkString* content) {
+void SkPDFUtils::AppendLine(SkScalar x, SkScalar y, SkWStream* content) {
     SkPDFScalar::Append(x, content);
-    content->append(" ");
+    content->writeText(" ");
     SkPDFScalar::Append(y, content);
-    content->append(" l\n");
+    content->writeText(" l\n");
 }
 
 // static
 void SkPDFUtils::AppendCubic(SkScalar ctl1X, SkScalar ctl1Y,
                              SkScalar ctl2X, SkScalar ctl2Y,
-                             SkScalar dstX, SkScalar dstY, SkString* content) {
+                             SkScalar dstX, SkScalar dstY, SkWStream* content) {
     SkString cmd("y\n");
     SkPDFScalar::Append(ctl1X, content);
-    content->append(" ");
+    content->writeText(" ");
     SkPDFScalar::Append(ctl1Y, content);
-    content->append(" ");
+    content->writeText(" ");
     if (ctl2X != dstX || ctl2Y != dstY) {
         cmd.set("c\n");
         SkPDFScalar::Append(ctl2X, content);
-        content->append(" ");
+        content->writeText(" ");
         SkPDFScalar::Append(ctl2Y, content);
-        content->append(" ");
+        content->writeText(" ");
     }
     SkPDFScalar::Append(dstX, content);
-    content->append(" ");
+    content->writeText(" ");
     SkPDFScalar::Append(dstY, content);
-    content->append(" ");
-    content->append(cmd);
+    content->writeText(" ");
+    content->writeText(cmd.c_str());
 }
 
 // static
 void SkPDFUtils::AppendRectangle(SkScalar x, SkScalar y,
-                                 SkScalar w, SkScalar h, SkString* content) {
+                                 SkScalar w, SkScalar h, SkWStream* content) {
     SkPDFScalar::Append(x, content);
-    content->append(" ");
+    content->writeText(" ");
     SkPDFScalar::Append(y, content);
-    content->append(" ");
+    content->writeText(" ");
     SkPDFScalar::Append(w, content);
-    content->append(" ");
+    content->writeText(" ");
     SkPDFScalar::Append(h, content);
-    content->append(" re\n");
+    content->writeText(" re\n");
 }
 
-// static 
-void SkPDFUtils::EmitPath(const SkPath& path, SkString* content) {
+// static
+void SkPDFUtils::EmitPath(const SkPath& path, SkWStream* content) {
     SkPoint args[4];
     SkPath::Iter iter(path, false);
     for (SkPath::Verb verb = iter.next(args);
@@ -129,32 +130,31 @@ void SkPDFUtils::EmitPath(const SkPath& path, SkString* content) {
 }
 
 // static
-void SkPDFUtils::ClosePath(SkString* content) {
-    content->append("h\n");
+void SkPDFUtils::ClosePath(SkWStream* content) {
+    content->writeText("h\n");
 }
 
 // static
 void SkPDFUtils::PaintPath(SkPaint::Style style, SkPath::FillType fill,
-                           SkString* content) {
+                           SkWStream* content) {
     if (style == SkPaint::kFill_Style)
-        content->append("f");
+        content->writeText("f");
     else if (style == SkPaint::kStrokeAndFill_Style)
-        content->append("B");
+        content->writeText("B");
     else if (style == SkPaint::kStroke_Style)
-        content->append("S");
+        content->writeText("S");
 
     if (style != SkPaint::kStroke_Style) {
-        // Not supported yet.
         NOT_IMPLEMENTED(fill == SkPath::kInverseEvenOdd_FillType, false);
         NOT_IMPLEMENTED(fill == SkPath::kInverseWinding_FillType, false);
         if (fill == SkPath::kEvenOdd_FillType)
-            content->append("*");
+            content->writeText("*");
     }
-    content->append("\n");
+    content->writeText("\n");
 }
 
 // static
-void SkPDFUtils::StrokePath(SkString* content) {
+void SkPDFUtils::StrokePath(SkWStream* content) {
     SkPDFUtils::PaintPath(
         SkPaint::kStroke_Style, SkPath::kWinding_FillType, content);
 }