blob: a75038c214077d3ffbfbbdf8039309b80f65223c [file] [log] [blame]
ctguil@chromium.orgf966fd32011-03-04 21:47:04 +00001/*
2 * Copyright (C) 2011 Google Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
reed@google.coma44ea512011-07-27 18:24:25 +000017#include "SkGeometry.h"
ctguil@chromium.orgf966fd32011-03-04 21:47:04 +000018#include "SkPaint.h"
19#include "SkPath.h"
20#include "SkPDFUtils.h"
vandebo@chromium.orgcae5fba2011-03-28 19:03:50 +000021#include "SkStream.h"
ctguil@chromium.orgf966fd32011-03-04 21:47:04 +000022#include "SkString.h"
23#include "SkPDFTypes.h"
24
25// static
26SkPDFArray* SkPDFUtils::MatrixToArray(const SkMatrix& matrix) {
27 SkScalar values[6];
bungeman@google.com1ddd7c32011-07-13 19:41:55 +000028 if (!matrix.asAffine(values)) {
29 SkMatrix::SetAffineIdentity(values);
30 }
ctguil@chromium.orgf966fd32011-03-04 21:47:04 +000031
32 SkPDFArray* result = new SkPDFArray;
33 result->reserve(6);
34 for (size_t i = 0; i < SK_ARRAY_COUNT(values); i++) {
reed@google.comc789cf12011-07-20 12:14:33 +000035 result->appendScalar(values[i]);
ctguil@chromium.orgf966fd32011-03-04 21:47:04 +000036 }
37 return result;
38}
39
40// static
vandebo@chromium.org75f97e42011-04-11 23:24:18 +000041void SkPDFUtils::AppendTransform(const SkMatrix& matrix, SkWStream* content) {
42 SkScalar values[6];
bungeman@google.com1ddd7c32011-07-13 19:41:55 +000043 if (!matrix.asAffine(values)) {
44 SkMatrix::SetAffineIdentity(values);
45 }
vandebo@chromium.org75f97e42011-04-11 23:24:18 +000046 for (size_t i = 0; i < SK_ARRAY_COUNT(values); i++) {
47 SkPDFScalar::Append(values[i], content);
48 content->writeText(" ");
49 }
50 content->writeText("cm\n");
51}
52
53// static
vandebo@chromium.orgcae5fba2011-03-28 19:03:50 +000054void SkPDFUtils::MoveTo(SkScalar x, SkScalar y, SkWStream* content) {
ctguil@chromium.orgf966fd32011-03-04 21:47:04 +000055 SkPDFScalar::Append(x, content);
vandebo@chromium.orgcae5fba2011-03-28 19:03:50 +000056 content->writeText(" ");
ctguil@chromium.orgf966fd32011-03-04 21:47:04 +000057 SkPDFScalar::Append(y, content);
vandebo@chromium.orgcae5fba2011-03-28 19:03:50 +000058 content->writeText(" m\n");
ctguil@chromium.orgf966fd32011-03-04 21:47:04 +000059}
60
61// static
vandebo@chromium.orgcae5fba2011-03-28 19:03:50 +000062void SkPDFUtils::AppendLine(SkScalar x, SkScalar y, SkWStream* content) {
ctguil@chromium.orgf966fd32011-03-04 21:47:04 +000063 SkPDFScalar::Append(x, content);
vandebo@chromium.orgcae5fba2011-03-28 19:03:50 +000064 content->writeText(" ");
ctguil@chromium.orgf966fd32011-03-04 21:47:04 +000065 SkPDFScalar::Append(y, content);
vandebo@chromium.orgcae5fba2011-03-28 19:03:50 +000066 content->writeText(" l\n");
ctguil@chromium.orgf966fd32011-03-04 21:47:04 +000067}
68
69// static
70void SkPDFUtils::AppendCubic(SkScalar ctl1X, SkScalar ctl1Y,
71 SkScalar ctl2X, SkScalar ctl2Y,
vandebo@chromium.orgcae5fba2011-03-28 19:03:50 +000072 SkScalar dstX, SkScalar dstY, SkWStream* content) {
ctguil@chromium.orgf966fd32011-03-04 21:47:04 +000073 SkString cmd("y\n");
74 SkPDFScalar::Append(ctl1X, content);
vandebo@chromium.orgcae5fba2011-03-28 19:03:50 +000075 content->writeText(" ");
ctguil@chromium.orgf966fd32011-03-04 21:47:04 +000076 SkPDFScalar::Append(ctl1Y, content);
vandebo@chromium.orgcae5fba2011-03-28 19:03:50 +000077 content->writeText(" ");
ctguil@chromium.orgf966fd32011-03-04 21:47:04 +000078 if (ctl2X != dstX || ctl2Y != dstY) {
79 cmd.set("c\n");
80 SkPDFScalar::Append(ctl2X, content);
vandebo@chromium.orgcae5fba2011-03-28 19:03:50 +000081 content->writeText(" ");
ctguil@chromium.orgf966fd32011-03-04 21:47:04 +000082 SkPDFScalar::Append(ctl2Y, content);
vandebo@chromium.orgcae5fba2011-03-28 19:03:50 +000083 content->writeText(" ");
ctguil@chromium.orgf966fd32011-03-04 21:47:04 +000084 }
85 SkPDFScalar::Append(dstX, content);
vandebo@chromium.orgcae5fba2011-03-28 19:03:50 +000086 content->writeText(" ");
ctguil@chromium.orgf966fd32011-03-04 21:47:04 +000087 SkPDFScalar::Append(dstY, content);
vandebo@chromium.orgcae5fba2011-03-28 19:03:50 +000088 content->writeText(" ");
89 content->writeText(cmd.c_str());
ctguil@chromium.orgf966fd32011-03-04 21:47:04 +000090}
91
92// static
vandebo@chromium.org9fbdf872011-05-09 07:55:58 +000093void SkPDFUtils::AppendRectangle(const SkRect& rect, SkWStream* content) {
94 // Skia has 0,0 at top left, pdf at bottom left. Do the right thing.
95 SkScalar bottom = SkMinScalar(rect.fBottom, rect.fTop);
96
97 SkPDFScalar::Append(rect.fLeft, content);
vandebo@chromium.orgcae5fba2011-03-28 19:03:50 +000098 content->writeText(" ");
vandebo@chromium.org9fbdf872011-05-09 07:55:58 +000099 SkPDFScalar::Append(bottom, content);
vandebo@chromium.orgcae5fba2011-03-28 19:03:50 +0000100 content->writeText(" ");
vandebo@chromium.org9fbdf872011-05-09 07:55:58 +0000101 SkPDFScalar::Append(rect.width(), content);
vandebo@chromium.orgcae5fba2011-03-28 19:03:50 +0000102 content->writeText(" ");
vandebo@chromium.org9fbdf872011-05-09 07:55:58 +0000103 SkPDFScalar::Append(rect.height(), content);
vandebo@chromium.orgcae5fba2011-03-28 19:03:50 +0000104 content->writeText(" re\n");
ctguil@chromium.orgf966fd32011-03-04 21:47:04 +0000105}
106
vandebo@chromium.orgcae5fba2011-03-28 19:03:50 +0000107// static
108void SkPDFUtils::EmitPath(const SkPath& path, SkWStream* content) {
ctguil@chromium.orgf966fd32011-03-04 21:47:04 +0000109 SkPoint args[4];
110 SkPath::Iter iter(path, false);
111 for (SkPath::Verb verb = iter.next(args);
112 verb != SkPath::kDone_Verb;
113 verb = iter.next(args)) {
114 // args gets all the points, even the implicit first point.
115 switch (verb) {
116 case SkPath::kMove_Verb:
117 MoveTo(args[0].fX, args[0].fY, content);
118 break;
119 case SkPath::kLine_Verb:
120 AppendLine(args[1].fX, args[1].fY, content);
121 break;
122 case SkPath::kQuad_Verb: {
reed@google.coma44ea512011-07-27 18:24:25 +0000123 SkPoint cubic[4];
124 SkConvertQuadToCubic(args, cubic);
125 AppendCubic(cubic[1].fX, cubic[1].fY, cubic[2].fX, cubic[2].fY,
126 cubic[3].fX, cubic[3].fY, content);
ctguil@chromium.orgf966fd32011-03-04 21:47:04 +0000127 break;
128 }
129 case SkPath::kCubic_Verb:
130 AppendCubic(args[1].fX, args[1].fY, args[2].fX, args[2].fY,
131 args[3].fX, args[3].fY, content);
132 break;
133 case SkPath::kClose_Verb:
134 ClosePath(content);
135 break;
ctguil@chromium.orgf966fd32011-03-04 21:47:04 +0000136 default:
137 SkASSERT(false);
138 break;
139 }
140 }
141}
142
143// static
vandebo@chromium.orgcae5fba2011-03-28 19:03:50 +0000144void SkPDFUtils::ClosePath(SkWStream* content) {
145 content->writeText("h\n");
ctguil@chromium.orgf966fd32011-03-04 21:47:04 +0000146}
147
148// static
149void SkPDFUtils::PaintPath(SkPaint::Style style, SkPath::FillType fill,
vandebo@chromium.orgcae5fba2011-03-28 19:03:50 +0000150 SkWStream* content) {
ctguil@chromium.orgf966fd32011-03-04 21:47:04 +0000151 if (style == SkPaint::kFill_Style)
vandebo@chromium.orgcae5fba2011-03-28 19:03:50 +0000152 content->writeText("f");
ctguil@chromium.orgf966fd32011-03-04 21:47:04 +0000153 else if (style == SkPaint::kStrokeAndFill_Style)
vandebo@chromium.orgcae5fba2011-03-28 19:03:50 +0000154 content->writeText("B");
ctguil@chromium.orgf966fd32011-03-04 21:47:04 +0000155 else if (style == SkPaint::kStroke_Style)
vandebo@chromium.orgcae5fba2011-03-28 19:03:50 +0000156 content->writeText("S");
ctguil@chromium.orgf966fd32011-03-04 21:47:04 +0000157
158 if (style != SkPaint::kStroke_Style) {
ctguil@chromium.orgf966fd32011-03-04 21:47:04 +0000159 NOT_IMPLEMENTED(fill == SkPath::kInverseEvenOdd_FillType, false);
160 NOT_IMPLEMENTED(fill == SkPath::kInverseWinding_FillType, false);
161 if (fill == SkPath::kEvenOdd_FillType)
vandebo@chromium.orgcae5fba2011-03-28 19:03:50 +0000162 content->writeText("*");
ctguil@chromium.orgf966fd32011-03-04 21:47:04 +0000163 }
vandebo@chromium.orgcae5fba2011-03-28 19:03:50 +0000164 content->writeText("\n");
ctguil@chromium.orgf966fd32011-03-04 21:47:04 +0000165}
166
167// static
vandebo@chromium.orgcae5fba2011-03-28 19:03:50 +0000168void SkPDFUtils::StrokePath(SkWStream* content) {
ctguil@chromium.orgf966fd32011-03-04 21:47:04 +0000169 SkPDFUtils::PaintPath(
170 SkPaint::kStroke_Style, SkPath::kWinding_FillType, content);
171}
vandebo@chromium.org6112c212011-05-13 03:50:38 +0000172
173// static
174void SkPDFUtils::DrawFormXObject(int objectIndex, SkWStream* content) {
175 content->writeText("/X");
176 content->writeDecAsText(objectIndex);
177 content->writeText(" Do\n");
178}
179
180// static
181void SkPDFUtils::ApplyGraphicState(int objectIndex, SkWStream* content) {
182 content->writeText("/G");
183 content->writeDecAsText(objectIndex);
184 content->writeText(" gs\n");
185}