blob: b596a27a72239d24331d42b5ca51bd1919d8834a [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001
ctguil@chromium.orgf966fd32011-03-04 21:47:04 +00002/*
epoger@google.comec3ed6a2011-07-28 14:26:00 +00003 * Copyright 2011 Google Inc.
ctguil@chromium.orgf966fd32011-03-04 21:47:04 +00004 *
epoger@google.comec3ed6a2011-07-28 14:26:00 +00005 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
ctguil@chromium.orgf966fd32011-03-04 21:47:04 +00007 */
8
epoger@google.comec3ed6a2011-07-28 14:26:00 +00009
reed@google.coma44ea512011-07-27 18:24:25 +000010#include "SkGeometry.h"
ctguil@chromium.orgf966fd32011-03-04 21:47:04 +000011#include "SkPaint.h"
12#include "SkPath.h"
13#include "SkPDFUtils.h"
vandebo@chromium.orgcae5fba2011-03-28 19:03:50 +000014#include "SkStream.h"
ctguil@chromium.orgf966fd32011-03-04 21:47:04 +000015#include "SkString.h"
16#include "SkPDFTypes.h"
17
18// static
19SkPDFArray* SkPDFUtils::MatrixToArray(const SkMatrix& matrix) {
20 SkScalar values[6];
bungeman@google.com1ddd7c32011-07-13 19:41:55 +000021 if (!matrix.asAffine(values)) {
22 SkMatrix::SetAffineIdentity(values);
23 }
ctguil@chromium.orgf966fd32011-03-04 21:47:04 +000024
25 SkPDFArray* result = new SkPDFArray;
26 result->reserve(6);
27 for (size_t i = 0; i < SK_ARRAY_COUNT(values); i++) {
reed@google.comc789cf12011-07-20 12:14:33 +000028 result->appendScalar(values[i]);
ctguil@chromium.orgf966fd32011-03-04 21:47:04 +000029 }
30 return result;
31}
32
33// static
vandebo@chromium.org75f97e42011-04-11 23:24:18 +000034void SkPDFUtils::AppendTransform(const SkMatrix& matrix, SkWStream* content) {
35 SkScalar values[6];
bungeman@google.com1ddd7c32011-07-13 19:41:55 +000036 if (!matrix.asAffine(values)) {
37 SkMatrix::SetAffineIdentity(values);
38 }
vandebo@chromium.org75f97e42011-04-11 23:24:18 +000039 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
vandebo@chromium.orgcae5fba2011-03-28 19:03:50 +000047void SkPDFUtils::MoveTo(SkScalar x, SkScalar y, SkWStream* content) {
ctguil@chromium.orgf966fd32011-03-04 21:47:04 +000048 SkPDFScalar::Append(x, content);
vandebo@chromium.orgcae5fba2011-03-28 19:03:50 +000049 content->writeText(" ");
ctguil@chromium.orgf966fd32011-03-04 21:47:04 +000050 SkPDFScalar::Append(y, content);
vandebo@chromium.orgcae5fba2011-03-28 19:03:50 +000051 content->writeText(" m\n");
ctguil@chromium.orgf966fd32011-03-04 21:47:04 +000052}
53
54// static
vandebo@chromium.orgcae5fba2011-03-28 19:03:50 +000055void SkPDFUtils::AppendLine(SkScalar x, SkScalar y, SkWStream* content) {
ctguil@chromium.orgf966fd32011-03-04 21:47:04 +000056 SkPDFScalar::Append(x, content);
vandebo@chromium.orgcae5fba2011-03-28 19:03:50 +000057 content->writeText(" ");
ctguil@chromium.orgf966fd32011-03-04 21:47:04 +000058 SkPDFScalar::Append(y, content);
vandebo@chromium.orgcae5fba2011-03-28 19:03:50 +000059 content->writeText(" l\n");
ctguil@chromium.orgf966fd32011-03-04 21:47:04 +000060}
61
62// static
63void SkPDFUtils::AppendCubic(SkScalar ctl1X, SkScalar ctl1Y,
64 SkScalar ctl2X, SkScalar ctl2Y,
vandebo@chromium.orgcae5fba2011-03-28 19:03:50 +000065 SkScalar dstX, SkScalar dstY, SkWStream* content) {
ctguil@chromium.orgf966fd32011-03-04 21:47:04 +000066 SkString cmd("y\n");
67 SkPDFScalar::Append(ctl1X, content);
vandebo@chromium.orgcae5fba2011-03-28 19:03:50 +000068 content->writeText(" ");
ctguil@chromium.orgf966fd32011-03-04 21:47:04 +000069 SkPDFScalar::Append(ctl1Y, content);
vandebo@chromium.orgcae5fba2011-03-28 19:03:50 +000070 content->writeText(" ");
ctguil@chromium.orgf966fd32011-03-04 21:47:04 +000071 if (ctl2X != dstX || ctl2Y != dstY) {
72 cmd.set("c\n");
73 SkPDFScalar::Append(ctl2X, content);
vandebo@chromium.orgcae5fba2011-03-28 19:03:50 +000074 content->writeText(" ");
ctguil@chromium.orgf966fd32011-03-04 21:47:04 +000075 SkPDFScalar::Append(ctl2Y, content);
vandebo@chromium.orgcae5fba2011-03-28 19:03:50 +000076 content->writeText(" ");
ctguil@chromium.orgf966fd32011-03-04 21:47:04 +000077 }
78 SkPDFScalar::Append(dstX, content);
vandebo@chromium.orgcae5fba2011-03-28 19:03:50 +000079 content->writeText(" ");
ctguil@chromium.orgf966fd32011-03-04 21:47:04 +000080 SkPDFScalar::Append(dstY, content);
vandebo@chromium.orgcae5fba2011-03-28 19:03:50 +000081 content->writeText(" ");
82 content->writeText(cmd.c_str());
ctguil@chromium.orgf966fd32011-03-04 21:47:04 +000083}
84
85// static
vandebo@chromium.org9fbdf872011-05-09 07:55:58 +000086void 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);
vandebo@chromium.orgcae5fba2011-03-28 19:03:50 +000091 content->writeText(" ");
vandebo@chromium.org9fbdf872011-05-09 07:55:58 +000092 SkPDFScalar::Append(bottom, content);
vandebo@chromium.orgcae5fba2011-03-28 19:03:50 +000093 content->writeText(" ");
vandebo@chromium.org9fbdf872011-05-09 07:55:58 +000094 SkPDFScalar::Append(rect.width(), content);
vandebo@chromium.orgcae5fba2011-03-28 19:03:50 +000095 content->writeText(" ");
vandebo@chromium.org9fbdf872011-05-09 07:55:58 +000096 SkPDFScalar::Append(rect.height(), 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: {
reed@google.coma44ea512011-07-27 18:24:25 +0000116 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);
ctguil@chromium.orgf966fd32011-03-04 21:47:04 +0000120 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;
ctguil@chromium.orgf966fd32011-03-04 21:47:04 +0000129 default:
130 SkASSERT(false);
131 break;
132 }
133 }
134}
135
136// static
vandebo@chromium.orgcae5fba2011-03-28 19:03:50 +0000137void SkPDFUtils::ClosePath(SkWStream* content) {
138 content->writeText("h\n");
ctguil@chromium.orgf966fd32011-03-04 21:47:04 +0000139}
140
141// static
142void SkPDFUtils::PaintPath(SkPaint::Style style, SkPath::FillType fill,
vandebo@chromium.orgcae5fba2011-03-28 19:03:50 +0000143 SkWStream* content) {
ctguil@chromium.org769fa6a2011-08-20 00:36:18 +0000144 if (style == SkPaint::kFill_Style) {
vandebo@chromium.orgcae5fba2011-03-28 19:03:50 +0000145 content->writeText("f");
ctguil@chromium.org769fa6a2011-08-20 00:36:18 +0000146 } else if (style == SkPaint::kStrokeAndFill_Style) {
vandebo@chromium.orgcae5fba2011-03-28 19:03:50 +0000147 content->writeText("B");
ctguil@chromium.org769fa6a2011-08-20 00:36:18 +0000148 } else if (style == SkPaint::kStroke_Style) {
vandebo@chromium.orgcae5fba2011-03-28 19:03:50 +0000149 content->writeText("S");
ctguil@chromium.org769fa6a2011-08-20 00:36:18 +0000150 }
ctguil@chromium.orgf966fd32011-03-04 21:47:04 +0000151
152 if (style != SkPaint::kStroke_Style) {
ctguil@chromium.orgf966fd32011-03-04 21:47:04 +0000153 NOT_IMPLEMENTED(fill == SkPath::kInverseEvenOdd_FillType, false);
154 NOT_IMPLEMENTED(fill == SkPath::kInverseWinding_FillType, false);
ctguil@chromium.org769fa6a2011-08-20 00:36:18 +0000155 if (fill == SkPath::kEvenOdd_FillType) {
vandebo@chromium.orgcae5fba2011-03-28 19:03:50 +0000156 content->writeText("*");
ctguil@chromium.org769fa6a2011-08-20 00:36:18 +0000157 }
ctguil@chromium.orgf966fd32011-03-04 21:47:04 +0000158 }
vandebo@chromium.orgcae5fba2011-03-28 19:03:50 +0000159 content->writeText("\n");
ctguil@chromium.orgf966fd32011-03-04 21:47:04 +0000160}
161
162// static
vandebo@chromium.orgcae5fba2011-03-28 19:03:50 +0000163void SkPDFUtils::StrokePath(SkWStream* content) {
ctguil@chromium.orgf966fd32011-03-04 21:47:04 +0000164 SkPDFUtils::PaintPath(
165 SkPaint::kStroke_Style, SkPath::kWinding_FillType, content);
166}
vandebo@chromium.org6112c212011-05-13 03:50:38 +0000167
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}