Store content streams in an SkStream instead of an SkString (64k size limit).

Review URL: http://codereview.appspot.com/4272070

git-svn-id: http://skia.googlecode.com/svn/trunk@1011 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/pdf/SkPDFDevice.cpp b/src/pdf/SkPDFDevice.cpp
index a0e1d28..3665dd8 100644
--- a/src/pdf/SkPDFDevice.cpp
+++ b/src/pdf/SkPDFDevice.cpp
@@ -38,20 +38,18 @@
 
 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 @@
     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 @@
             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 @@
 
     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 @@
         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 @@
     }
 
     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 @@
         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 @@
 
     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 @@
 }
 
 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 @@
                 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 @@
         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 @@
             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 @@
             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 @@
                               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 @@
             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 @@
 
 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 @@
     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 @@
     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;