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) {
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");
}
}
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;
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) {
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
}
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;
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,
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);
}
}
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';
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 {
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;
}
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();
}
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;
}
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();
}
}
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];
}
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,
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);
}
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;
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
// 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
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
}
#include "SkPaint.h"
#include "SkPath.h"
#include "SkPDFUtils.h"
+#include "SkStream.h"
#include "SkString.h"
#include "SkPDFTypes.h"
}
// 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);
}
// 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);
}