Add SkPDFUtils.cpp to build.


git-svn-id: http://skia.googlecode.com/svn/trunk@893 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/pdf/SkPDFUtils.cpp b/src/pdf/SkPDFUtils.cpp
new file mode 100644
index 0000000..874ee8f
--- /dev/null
+++ b/src/pdf/SkPDFUtils.cpp
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2011 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "SkPaint.h"
+#include "SkPath.h"
+#include "SkPDFUtils.h"
+#include "SkString.h"
+#include "SkPDFTypes.h"
+
+// static
+SkPDFArray* SkPDFUtils::MatrixToArray(const SkMatrix& matrix) {
+    SkScalar values[6];
+    SkAssertResult(matrix.pdfTransform(values));
+
+    SkPDFArray* result = new SkPDFArray;
+    result->reserve(6);
+    for (size_t i = 0; i < SK_ARRAY_COUNT(values); i++) {
+        result->append(new SkPDFScalar(values[i]))->unref();
+    }
+    return result;
+}
+
+// static
+void SkPDFUtils::MoveTo(SkScalar x, SkScalar y, SkString* content) {
+    SkPDFScalar::Append(x, content);
+    content->append(" ");
+    SkPDFScalar::Append(y, content);
+    content->append(" m\n");
+}
+
+// static
+void SkPDFUtils::AppendLine(SkScalar x, SkScalar y, SkString* content) {
+    SkPDFScalar::Append(x, content);
+    content->append(" ");
+    SkPDFScalar::Append(y, content);
+    content->append(" l\n");
+}
+
+// static
+void SkPDFUtils::AppendCubic(SkScalar ctl1X, SkScalar ctl1Y,
+                             SkScalar ctl2X, SkScalar ctl2Y,
+                             SkScalar dstX, SkScalar dstY, SkString* content) {
+    SkString cmd("y\n");
+    SkPDFScalar::Append(ctl1X, content);
+    content->append(" ");
+    SkPDFScalar::Append(ctl1Y, content);
+    content->append(" ");
+    if (ctl2X != dstX || ctl2Y != dstY) {
+        cmd.set("c\n");
+        SkPDFScalar::Append(ctl2X, content);
+        content->append(" ");
+        SkPDFScalar::Append(ctl2Y, content);
+        content->append(" ");
+    }
+    SkPDFScalar::Append(dstX, content);
+    content->append(" ");
+    SkPDFScalar::Append(dstY, content);
+    content->append(" ");
+    content->append(cmd);
+}
+
+// static
+void SkPDFUtils::AppendRectangle(SkScalar x, SkScalar y,
+                                 SkScalar w, SkScalar h, SkString* content) {
+    SkPDFScalar::Append(x, content);
+    content->append(" ");
+    SkPDFScalar::Append(y, content);
+    content->append(" ");
+    SkPDFScalar::Append(w, content);
+    content->append(" ");
+    SkPDFScalar::Append(h, content);
+    content->append(" re\n");
+}
+
+// static 
+void SkPDFUtils::EmitPath(const SkPath& path, SkString* content) {
+    SkPoint args[4];
+    SkPath::Iter iter(path, false);
+    for (SkPath::Verb verb = iter.next(args);
+         verb != SkPath::kDone_Verb;
+         verb = iter.next(args)) {
+        // args gets all the points, even the implicit first point.
+        switch (verb) {
+            case SkPath::kMove_Verb:
+                MoveTo(args[0].fX, args[0].fY, content);
+                break;
+            case SkPath::kLine_Verb:
+                AppendLine(args[1].fX, args[1].fY, content);
+                break;
+            case SkPath::kQuad_Verb: {
+                // Convert quad to cubic (degree elevation). http://goo.gl/vS4i
+                const SkScalar three = SkIntToScalar(3);
+                args[1].scale(SkIntToScalar(2));
+                SkScalar ctl1X = SkScalarDiv(args[0].fX + args[1].fX, three);
+                SkScalar ctl1Y = SkScalarDiv(args[0].fY + args[1].fY, three);
+                SkScalar ctl2X = SkScalarDiv(args[2].fX + args[1].fX, three);
+                SkScalar ctl2Y = SkScalarDiv(args[2].fY + args[1].fY, three);
+                AppendCubic(ctl1X, ctl1Y, ctl2X, ctl2Y, args[2].fX, args[2].fY,
+                            content);
+                break;
+            }
+            case SkPath::kCubic_Verb:
+                AppendCubic(args[1].fX, args[1].fY, args[2].fX, args[2].fY,
+                            args[3].fX, args[3].fY, content);
+                break;
+            case SkPath::kClose_Verb:
+                ClosePath(content);
+                break;
+            case SkPath::kDone_Verb:
+                break;
+            default:
+                SkASSERT(false);
+                break;
+        }
+    }
+}
+
+// static
+void SkPDFUtils::ClosePath(SkString* content) {
+    content->append("h\n");
+}
+
+// static
+void SkPDFUtils::PaintPath(SkPaint::Style style, SkPath::FillType fill,
+                           SkString* content) {
+    if (style == SkPaint::kFill_Style)
+        content->append("f");
+    else if (style == SkPaint::kStrokeAndFill_Style)
+        content->append("B");
+    else if (style == SkPaint::kStroke_Style)
+        content->append("S");
+
+    if (style != SkPaint::kStroke_Style) {
+        // Not supported yet.
+        NOT_IMPLEMENTED(fill == SkPath::kInverseEvenOdd_FillType, false);
+        NOT_IMPLEMENTED(fill == SkPath::kInverseWinding_FillType, false);
+        if (fill == SkPath::kEvenOdd_FillType)
+            content->append("*");
+    }
+    content->append("\n");
+}
+
+// static
+void SkPDFUtils::StrokePath(SkString* content) {
+    SkPDFUtils::PaintPath(
+        SkPaint::kStroke_Style, SkPath::kWinding_FillType, content);
+}