blob: 874ee8f2d54e5965cac1d67e7d735dbf40dd7d02 [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"
20#include "SkString.h"
21#include "SkPDFTypes.h"
22
23// static
24SkPDFArray* SkPDFUtils::MatrixToArray(const SkMatrix& matrix) {
25 SkScalar values[6];
26 SkAssertResult(matrix.pdfTransform(values));
27
28 SkPDFArray* result = new SkPDFArray;
29 result->reserve(6);
30 for (size_t i = 0; i < SK_ARRAY_COUNT(values); i++) {
31 result->append(new SkPDFScalar(values[i]))->unref();
32 }
33 return result;
34}
35
36// static
37void SkPDFUtils::MoveTo(SkScalar x, SkScalar y, SkString* content) {
38 SkPDFScalar::Append(x, content);
39 content->append(" ");
40 SkPDFScalar::Append(y, content);
41 content->append(" m\n");
42}
43
44// static
45void SkPDFUtils::AppendLine(SkScalar x, SkScalar y, SkString* content) {
46 SkPDFScalar::Append(x, content);
47 content->append(" ");
48 SkPDFScalar::Append(y, content);
49 content->append(" l\n");
50}
51
52// static
53void SkPDFUtils::AppendCubic(SkScalar ctl1X, SkScalar ctl1Y,
54 SkScalar ctl2X, SkScalar ctl2Y,
55 SkScalar dstX, SkScalar dstY, SkString* content) {
56 SkString cmd("y\n");
57 SkPDFScalar::Append(ctl1X, content);
58 content->append(" ");
59 SkPDFScalar::Append(ctl1Y, content);
60 content->append(" ");
61 if (ctl2X != dstX || ctl2Y != dstY) {
62 cmd.set("c\n");
63 SkPDFScalar::Append(ctl2X, content);
64 content->append(" ");
65 SkPDFScalar::Append(ctl2Y, content);
66 content->append(" ");
67 }
68 SkPDFScalar::Append(dstX, content);
69 content->append(" ");
70 SkPDFScalar::Append(dstY, content);
71 content->append(" ");
72 content->append(cmd);
73}
74
75// static
76void SkPDFUtils::AppendRectangle(SkScalar x, SkScalar y,
77 SkScalar w, SkScalar h, SkString* content) {
78 SkPDFScalar::Append(x, content);
79 content->append(" ");
80 SkPDFScalar::Append(y, content);
81 content->append(" ");
82 SkPDFScalar::Append(w, content);
83 content->append(" ");
84 SkPDFScalar::Append(h, content);
85 content->append(" re\n");
86}
87
88// static
89void SkPDFUtils::EmitPath(const SkPath& path, SkString* content) {
90 SkPoint args[4];
91 SkPath::Iter iter(path, false);
92 for (SkPath::Verb verb = iter.next(args);
93 verb != SkPath::kDone_Verb;
94 verb = iter.next(args)) {
95 // args gets all the points, even the implicit first point.
96 switch (verb) {
97 case SkPath::kMove_Verb:
98 MoveTo(args[0].fX, args[0].fY, content);
99 break;
100 case SkPath::kLine_Verb:
101 AppendLine(args[1].fX, args[1].fY, content);
102 break;
103 case SkPath::kQuad_Verb: {
104 // Convert quad to cubic (degree elevation). http://goo.gl/vS4i
105 const SkScalar three = SkIntToScalar(3);
106 args[1].scale(SkIntToScalar(2));
107 SkScalar ctl1X = SkScalarDiv(args[0].fX + args[1].fX, three);
108 SkScalar ctl1Y = SkScalarDiv(args[0].fY + args[1].fY, three);
109 SkScalar ctl2X = SkScalarDiv(args[2].fX + args[1].fX, three);
110 SkScalar ctl2Y = SkScalarDiv(args[2].fY + args[1].fY, three);
111 AppendCubic(ctl1X, ctl1Y, ctl2X, ctl2Y, args[2].fX, args[2].fY,
112 content);
113 break;
114 }
115 case SkPath::kCubic_Verb:
116 AppendCubic(args[1].fX, args[1].fY, args[2].fX, args[2].fY,
117 args[3].fX, args[3].fY, content);
118 break;
119 case SkPath::kClose_Verb:
120 ClosePath(content);
121 break;
122 case SkPath::kDone_Verb:
123 break;
124 default:
125 SkASSERT(false);
126 break;
127 }
128 }
129}
130
131// static
132void SkPDFUtils::ClosePath(SkString* content) {
133 content->append("h\n");
134}
135
136// static
137void SkPDFUtils::PaintPath(SkPaint::Style style, SkPath::FillType fill,
138 SkString* content) {
139 if (style == SkPaint::kFill_Style)
140 content->append("f");
141 else if (style == SkPaint::kStrokeAndFill_Style)
142 content->append("B");
143 else if (style == SkPaint::kStroke_Style)
144 content->append("S");
145
146 if (style != SkPaint::kStroke_Style) {
147 // Not supported yet.
148 NOT_IMPLEMENTED(fill == SkPath::kInverseEvenOdd_FillType, false);
149 NOT_IMPLEMENTED(fill == SkPath::kInverseWinding_FillType, false);
150 if (fill == SkPath::kEvenOdd_FillType)
151 content->append("*");
152 }
153 content->append("\n");
154}
155
156// static
157void SkPDFUtils::StrokePath(SkString* content) {
158 SkPDFUtils::PaintPath(
159 SkPaint::kStroke_Style, SkPath::kWinding_FillType, content);
160}