SkPDFUtils.cpp revision 1cab2921ab279367f8206cdadc9259d12e603548
11cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 20b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger/* 31cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Copyright 2011 Google Inc. 40b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger * 51cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Use of this source code is governed by a BSD-style license that can be 61cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * found in the LICENSE file. 70b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger */ 80b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 91cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 101cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#include "SkGeometry.h" 110b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger#include "SkPaint.h" 120b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger#include "SkPath.h" 130b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger#include "SkPDFUtils.h" 140b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger#include "SkStream.h" 150b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger#include "SkString.h" 160b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger#include "SkPDFTypes.h" 170b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 180b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger// static 190b15698a8c76bb8abc1b555c1d91892669b4118fDerek SollenbergerSkPDFArray* SkPDFUtils::MatrixToArray(const SkMatrix& matrix) { 200b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkScalar values[6]; 211cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (!matrix.asAffine(values)) { 221cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkMatrix::SetAffineIdentity(values); 231cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 240b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 250b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkPDFArray* result = new SkPDFArray; 260b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger result->reserve(6); 270b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger for (size_t i = 0; i < SK_ARRAY_COUNT(values); i++) { 281cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger result->appendScalar(values[i]); 290b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 300b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger return result; 310b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger} 320b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 330b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger// static 340b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenbergervoid SkPDFUtils::AppendTransform(const SkMatrix& matrix, SkWStream* content) { 350b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkScalar values[6]; 361cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (!matrix.asAffine(values)) { 371cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkMatrix::SetAffineIdentity(values); 381cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 390b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger for (size_t i = 0; i < SK_ARRAY_COUNT(values); i++) { 400b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkPDFScalar::Append(values[i], content); 410b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger content->writeText(" "); 420b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 430b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger content->writeText("cm\n"); 440b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger} 450b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 460b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger// static 470b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenbergervoid SkPDFUtils::MoveTo(SkScalar x, SkScalar y, SkWStream* content) { 480b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkPDFScalar::Append(x, content); 490b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger content->writeText(" "); 500b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkPDFScalar::Append(y, content); 510b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger content->writeText(" m\n"); 520b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger} 530b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 540b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger// static 550b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenbergervoid SkPDFUtils::AppendLine(SkScalar x, SkScalar y, SkWStream* content) { 560b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkPDFScalar::Append(x, content); 570b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger content->writeText(" "); 580b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkPDFScalar::Append(y, content); 590b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger content->writeText(" l\n"); 600b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger} 610b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 620b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger// static 630b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenbergervoid SkPDFUtils::AppendCubic(SkScalar ctl1X, SkScalar ctl1Y, 640b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkScalar ctl2X, SkScalar ctl2Y, 650b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkScalar dstX, SkScalar dstY, SkWStream* content) { 660b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkString cmd("y\n"); 670b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkPDFScalar::Append(ctl1X, content); 680b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger content->writeText(" "); 690b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkPDFScalar::Append(ctl1Y, content); 700b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger content->writeText(" "); 710b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (ctl2X != dstX || ctl2Y != dstY) { 720b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger cmd.set("c\n"); 730b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkPDFScalar::Append(ctl2X, content); 740b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger content->writeText(" "); 750b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkPDFScalar::Append(ctl2Y, content); 760b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger content->writeText(" "); 770b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 780b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkPDFScalar::Append(dstX, content); 790b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger content->writeText(" "); 800b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkPDFScalar::Append(dstY, content); 810b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger content->writeText(" "); 820b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger content->writeText(cmd.c_str()); 830b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger} 840b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 850b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger// static 860b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenbergervoid SkPDFUtils::AppendRectangle(const SkRect& rect, SkWStream* content) { 870b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // Skia has 0,0 at top left, pdf at bottom left. Do the right thing. 880b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkScalar bottom = SkMinScalar(rect.fBottom, rect.fTop); 890b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 900b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkPDFScalar::Append(rect.fLeft, content); 910b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger content->writeText(" "); 920b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkPDFScalar::Append(bottom, content); 930b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger content->writeText(" "); 940b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkPDFScalar::Append(rect.width(), content); 950b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger content->writeText(" "); 960b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkPDFScalar::Append(rect.height(), content); 970b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger content->writeText(" re\n"); 980b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger} 990b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 1000b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger// static 1010b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenbergervoid SkPDFUtils::EmitPath(const SkPath& path, SkWStream* content) { 1020b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkPoint args[4]; 1030b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkPath::Iter iter(path, false); 1040b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger for (SkPath::Verb verb = iter.next(args); 1050b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger verb != SkPath::kDone_Verb; 1060b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger verb = iter.next(args)) { 1070b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // args gets all the points, even the implicit first point. 1080b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger switch (verb) { 1090b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger case SkPath::kMove_Verb: 1100b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger MoveTo(args[0].fX, args[0].fY, content); 1110b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger break; 1120b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger case SkPath::kLine_Verb: 1130b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger AppendLine(args[1].fX, args[1].fY, content); 1140b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger break; 1150b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger case SkPath::kQuad_Verb: { 1161cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkPoint cubic[4]; 1171cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkConvertQuadToCubic(args, cubic); 1181cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger AppendCubic(cubic[1].fX, cubic[1].fY, cubic[2].fX, cubic[2].fY, 1191cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger cubic[3].fX, cubic[3].fY, content); 1200b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger break; 1210b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 1220b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger case SkPath::kCubic_Verb: 1230b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger AppendCubic(args[1].fX, args[1].fY, args[2].fX, args[2].fY, 1240b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger args[3].fX, args[3].fY, content); 1250b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger break; 1260b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger case SkPath::kClose_Verb: 1270b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger ClosePath(content); 1280b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger break; 1290b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger default: 1300b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkASSERT(false); 1310b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger break; 1320b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 1330b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 1340b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger} 1350b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 1360b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger// static 1370b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenbergervoid SkPDFUtils::ClosePath(SkWStream* content) { 1380b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger content->writeText("h\n"); 1390b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger} 1400b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 1410b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger// static 1420b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenbergervoid SkPDFUtils::PaintPath(SkPaint::Style style, SkPath::FillType fill, 1430b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkWStream* content) { 1441cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (style == SkPaint::kFill_Style) { 1450b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger content->writeText("f"); 1461cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } else if (style == SkPaint::kStrokeAndFill_Style) { 1470b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger content->writeText("B"); 1481cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } else if (style == SkPaint::kStroke_Style) { 1490b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger content->writeText("S"); 1501cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 1510b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 1520b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (style != SkPaint::kStroke_Style) { 1530b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger NOT_IMPLEMENTED(fill == SkPath::kInverseEvenOdd_FillType, false); 1540b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger NOT_IMPLEMENTED(fill == SkPath::kInverseWinding_FillType, false); 1551cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (fill == SkPath::kEvenOdd_FillType) { 1560b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger content->writeText("*"); 1571cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 1580b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 1590b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger content->writeText("\n"); 1600b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger} 1610b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 1620b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger// static 1630b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenbergervoid SkPDFUtils::StrokePath(SkWStream* content) { 1640b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkPDFUtils::PaintPath( 1650b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkPaint::kStroke_Style, SkPath::kWinding_FillType, content); 1660b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger} 1670b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 1680b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger// static 1690b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenbergervoid SkPDFUtils::DrawFormXObject(int objectIndex, SkWStream* content) { 1700b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger content->writeText("/X"); 1710b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger content->writeDecAsText(objectIndex); 1720b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger content->writeText(" Do\n"); 1730b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger} 1740b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 1750b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger// static 1760b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenbergervoid SkPDFUtils::ApplyGraphicState(int objectIndex, SkWStream* content) { 1770b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger content->writeText("/G"); 1780b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger content->writeDecAsText(objectIndex); 1790b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger content->writeText(" gs\n"); 1800b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger} 181