blob: 57e0cb72447d1ac2b1c660bbfb84740f3ee09ad4 [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
17#include "SkPaint.h"
18#include "SkPath.h"
19#include "SkPDFUtils.h"
vandebo@chromium.orgcae5fba2011-03-28 19:03:50 +000020#include "SkStream.h"
ctguil@chromium.orgf966fd32011-03-04 21:47:04 +000021#include "SkString.h"
22#include "SkPDFTypes.h"
23
24// static
25SkPDFArray* SkPDFUtils::MatrixToArray(const SkMatrix& matrix) {
26 SkScalar values[6];
27 SkAssertResult(matrix.pdfTransform(values));
28
29 SkPDFArray* result = new SkPDFArray;
30 result->reserve(6);
31 for (size_t i = 0; i < SK_ARRAY_COUNT(values); i++) {
32 result->append(new SkPDFScalar(values[i]))->unref();
33 }
34 return result;
35}
36
37// static
vandebo@chromium.org75f97e42011-04-11 23:24:18 +000038void SkPDFUtils::AppendTransform(const SkMatrix& matrix, SkWStream* content) {
39 SkScalar values[6];
40 SkAssertResult(matrix.pdfTransform(values));
41 for (size_t i = 0; i < SK_ARRAY_COUNT(values); i++) {
42 SkPDFScalar::Append(values[i], content);
43 content->writeText(" ");
44 }
45 content->writeText("cm\n");
46}
47
48// static
vandebo@chromium.orgcae5fba2011-03-28 19:03:50 +000049void SkPDFUtils::MoveTo(SkScalar x, SkScalar y, SkWStream* content) {
ctguil@chromium.orgf966fd32011-03-04 21:47:04 +000050 SkPDFScalar::Append(x, content);
vandebo@chromium.orgcae5fba2011-03-28 19:03:50 +000051 content->writeText(" ");
ctguil@chromium.orgf966fd32011-03-04 21:47:04 +000052 SkPDFScalar::Append(y, content);
vandebo@chromium.orgcae5fba2011-03-28 19:03:50 +000053 content->writeText(" m\n");
ctguil@chromium.orgf966fd32011-03-04 21:47:04 +000054}
55
56// static
vandebo@chromium.orgcae5fba2011-03-28 19:03:50 +000057void SkPDFUtils::AppendLine(SkScalar x, SkScalar y, SkWStream* content) {
ctguil@chromium.orgf966fd32011-03-04 21:47:04 +000058 SkPDFScalar::Append(x, content);
vandebo@chromium.orgcae5fba2011-03-28 19:03:50 +000059 content->writeText(" ");
ctguil@chromium.orgf966fd32011-03-04 21:47:04 +000060 SkPDFScalar::Append(y, content);
vandebo@chromium.orgcae5fba2011-03-28 19:03:50 +000061 content->writeText(" l\n");
ctguil@chromium.orgf966fd32011-03-04 21:47:04 +000062}
63
64// static
65void SkPDFUtils::AppendCubic(SkScalar ctl1X, SkScalar ctl1Y,
66 SkScalar ctl2X, SkScalar ctl2Y,
vandebo@chromium.orgcae5fba2011-03-28 19:03:50 +000067 SkScalar dstX, SkScalar dstY, SkWStream* content) {
ctguil@chromium.orgf966fd32011-03-04 21:47:04 +000068 SkString cmd("y\n");
69 SkPDFScalar::Append(ctl1X, content);
vandebo@chromium.orgcae5fba2011-03-28 19:03:50 +000070 content->writeText(" ");
ctguil@chromium.orgf966fd32011-03-04 21:47:04 +000071 SkPDFScalar::Append(ctl1Y, content);
vandebo@chromium.orgcae5fba2011-03-28 19:03:50 +000072 content->writeText(" ");
ctguil@chromium.orgf966fd32011-03-04 21:47:04 +000073 if (ctl2X != dstX || ctl2Y != dstY) {
74 cmd.set("c\n");
75 SkPDFScalar::Append(ctl2X, content);
vandebo@chromium.orgcae5fba2011-03-28 19:03:50 +000076 content->writeText(" ");
ctguil@chromium.orgf966fd32011-03-04 21:47:04 +000077 SkPDFScalar::Append(ctl2Y, content);
vandebo@chromium.orgcae5fba2011-03-28 19:03:50 +000078 content->writeText(" ");
ctguil@chromium.orgf966fd32011-03-04 21:47:04 +000079 }
80 SkPDFScalar::Append(dstX, content);
vandebo@chromium.orgcae5fba2011-03-28 19:03:50 +000081 content->writeText(" ");
ctguil@chromium.orgf966fd32011-03-04 21:47:04 +000082 SkPDFScalar::Append(dstY, content);
vandebo@chromium.orgcae5fba2011-03-28 19:03:50 +000083 content->writeText(" ");
84 content->writeText(cmd.c_str());
ctguil@chromium.orgf966fd32011-03-04 21:47:04 +000085}
86
87// static
88void SkPDFUtils::AppendRectangle(SkScalar x, SkScalar y,
vandebo@chromium.orgcae5fba2011-03-28 19:03:50 +000089 SkScalar w, SkScalar h, SkWStream* content) {
ctguil@chromium.orgf966fd32011-03-04 21:47:04 +000090 SkPDFScalar::Append(x, content);
vandebo@chromium.orgcae5fba2011-03-28 19:03:50 +000091 content->writeText(" ");
ctguil@chromium.orgf966fd32011-03-04 21:47:04 +000092 SkPDFScalar::Append(y, content);
vandebo@chromium.orgcae5fba2011-03-28 19:03:50 +000093 content->writeText(" ");
ctguil@chromium.orgf966fd32011-03-04 21:47:04 +000094 SkPDFScalar::Append(w, content);
vandebo@chromium.orgcae5fba2011-03-28 19:03:50 +000095 content->writeText(" ");
ctguil@chromium.orgf966fd32011-03-04 21:47:04 +000096 SkPDFScalar::Append(h, content);
vandebo@chromium.orgcae5fba2011-03-28 19:03:50 +000097 content->writeText(" re\n");
ctguil@chromium.orgf966fd32011-03-04 21:47:04 +000098}
99
vandebo@chromium.orgcae5fba2011-03-28 19:03:50 +0000100// static
101void SkPDFUtils::EmitPath(const SkPath& path, SkWStream* content) {
ctguil@chromium.orgf966fd32011-03-04 21:47:04 +0000102 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 // Convert quad to cubic (degree elevation). http://goo.gl/vS4i
117 const SkScalar three = SkIntToScalar(3);
118 args[1].scale(SkIntToScalar(2));
119 SkScalar ctl1X = SkScalarDiv(args[0].fX + args[1].fX, three);
120 SkScalar ctl1Y = SkScalarDiv(args[0].fY + args[1].fY, three);
121 SkScalar ctl2X = SkScalarDiv(args[2].fX + args[1].fX, three);
122 SkScalar ctl2Y = SkScalarDiv(args[2].fY + args[1].fY, three);
123 AppendCubic(ctl1X, ctl1Y, ctl2X, ctl2Y, args[2].fX, args[2].fY,
124 content);
125 break;
126 }
127 case SkPath::kCubic_Verb:
128 AppendCubic(args[1].fX, args[1].fY, args[2].fX, args[2].fY,
129 args[3].fX, args[3].fY, content);
130 break;
131 case SkPath::kClose_Verb:
132 ClosePath(content);
133 break;
134 case SkPath::kDone_Verb:
135 break;
136 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}