SkPDFUtils.cpp revision 769fa6a013baca6d7404e2bf096a34a7e3635fa5
1 2/* 3 * Copyright 2011 Google Inc. 4 * 5 * Use of this source code is governed by a BSD-style license that can be 6 * found in the LICENSE file. 7 */ 8 9 10#include "SkGeometry.h" 11#include "SkPaint.h" 12#include "SkPath.h" 13#include "SkPDFUtils.h" 14#include "SkStream.h" 15#include "SkString.h" 16#include "SkPDFTypes.h" 17 18// static 19SkPDFArray* SkPDFUtils::MatrixToArray(const SkMatrix& matrix) { 20 SkScalar values[6]; 21 if (!matrix.asAffine(values)) { 22 SkMatrix::SetAffineIdentity(values); 23 } 24 25 SkPDFArray* result = new SkPDFArray; 26 result->reserve(6); 27 for (size_t i = 0; i < SK_ARRAY_COUNT(values); i++) { 28 result->appendScalar(values[i]); 29 } 30 return result; 31} 32 33// static 34void SkPDFUtils::AppendTransform(const SkMatrix& matrix, SkWStream* content) { 35 SkScalar values[6]; 36 if (!matrix.asAffine(values)) { 37 SkMatrix::SetAffineIdentity(values); 38 } 39 for (size_t i = 0; i < SK_ARRAY_COUNT(values); i++) { 40 SkPDFScalar::Append(values[i], content); 41 content->writeText(" "); 42 } 43 content->writeText("cm\n"); 44} 45 46// static 47void SkPDFUtils::MoveTo(SkScalar x, SkScalar y, SkWStream* content) { 48 SkPDFScalar::Append(x, content); 49 content->writeText(" "); 50 SkPDFScalar::Append(y, content); 51 content->writeText(" m\n"); 52} 53 54// static 55void SkPDFUtils::AppendLine(SkScalar x, SkScalar y, SkWStream* content) { 56 SkPDFScalar::Append(x, content); 57 content->writeText(" "); 58 SkPDFScalar::Append(y, content); 59 content->writeText(" l\n"); 60} 61 62// static 63void SkPDFUtils::AppendCubic(SkScalar ctl1X, SkScalar ctl1Y, 64 SkScalar ctl2X, SkScalar ctl2Y, 65 SkScalar dstX, SkScalar dstY, SkWStream* content) { 66 SkString cmd("y\n"); 67 SkPDFScalar::Append(ctl1X, content); 68 content->writeText(" "); 69 SkPDFScalar::Append(ctl1Y, content); 70 content->writeText(" "); 71 if (ctl2X != dstX || ctl2Y != dstY) { 72 cmd.set("c\n"); 73 SkPDFScalar::Append(ctl2X, content); 74 content->writeText(" "); 75 SkPDFScalar::Append(ctl2Y, content); 76 content->writeText(" "); 77 } 78 SkPDFScalar::Append(dstX, content); 79 content->writeText(" "); 80 SkPDFScalar::Append(dstY, content); 81 content->writeText(" "); 82 content->writeText(cmd.c_str()); 83} 84 85// static 86void SkPDFUtils::AppendRectangle(const SkRect& rect, SkWStream* content) { 87 // Skia has 0,0 at top left, pdf at bottom left. Do the right thing. 88 SkScalar bottom = SkMinScalar(rect.fBottom, rect.fTop); 89 90 SkPDFScalar::Append(rect.fLeft, content); 91 content->writeText(" "); 92 SkPDFScalar::Append(bottom, content); 93 content->writeText(" "); 94 SkPDFScalar::Append(rect.width(), content); 95 content->writeText(" "); 96 SkPDFScalar::Append(rect.height(), content); 97 content->writeText(" re\n"); 98} 99 100// static 101void SkPDFUtils::EmitPath(const SkPath& path, SkWStream* content) { 102 SkPoint args[4]; 103 SkPath::Iter iter(path, false); 104 for (SkPath::Verb verb = iter.next(args); 105 verb != SkPath::kDone_Verb; 106 verb = iter.next(args)) { 107 // args gets all the points, even the implicit first point. 108 switch (verb) { 109 case SkPath::kMove_Verb: 110 MoveTo(args[0].fX, args[0].fY, content); 111 break; 112 case SkPath::kLine_Verb: 113 AppendLine(args[1].fX, args[1].fY, content); 114 break; 115 case SkPath::kQuad_Verb: { 116 SkPoint cubic[4]; 117 SkConvertQuadToCubic(args, cubic); 118 AppendCubic(cubic[1].fX, cubic[1].fY, cubic[2].fX, cubic[2].fY, 119 cubic[3].fX, cubic[3].fY, content); 120 break; 121 } 122 case SkPath::kCubic_Verb: 123 AppendCubic(args[1].fX, args[1].fY, args[2].fX, args[2].fY, 124 args[3].fX, args[3].fY, content); 125 break; 126 case SkPath::kClose_Verb: 127 ClosePath(content); 128 break; 129 default: 130 SkASSERT(false); 131 break; 132 } 133 } 134} 135 136// static 137void SkPDFUtils::ClosePath(SkWStream* content) { 138 content->writeText("h\n"); 139} 140 141// static 142void SkPDFUtils::PaintPath(SkPaint::Style style, SkPath::FillType fill, 143 SkWStream* content) { 144 if (style == SkPaint::kFill_Style) { 145 content->writeText("f"); 146 } else if (style == SkPaint::kStrokeAndFill_Style) { 147 content->writeText("B"); 148 } else if (style == SkPaint::kStroke_Style) { 149 content->writeText("S"); 150 } 151 152 if (style != SkPaint::kStroke_Style) { 153 NOT_IMPLEMENTED(fill == SkPath::kInverseEvenOdd_FillType, false); 154 NOT_IMPLEMENTED(fill == SkPath::kInverseWinding_FillType, false); 155 if (fill == SkPath::kEvenOdd_FillType) { 156 content->writeText("*"); 157 } 158 } 159 content->writeText("\n"); 160} 161 162// static 163void SkPDFUtils::StrokePath(SkWStream* content) { 164 SkPDFUtils::PaintPath( 165 SkPaint::kStroke_Style, SkPath::kWinding_FillType, content); 166} 167 168// static 169void SkPDFUtils::DrawFormXObject(int objectIndex, SkWStream* content) { 170 content->writeText("/X"); 171 content->writeDecAsText(objectIndex); 172 content->writeText(" Do\n"); 173} 174 175// static 176void SkPDFUtils::ApplyGraphicState(int objectIndex, SkWStream* content) { 177 content->writeText("/G"); 178 content->writeDecAsText(objectIndex); 179 content->writeText(" gs\n"); 180} 181