11cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
20b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger/*
31cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Copyright 2011 Google Inc.
40b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger *
51cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Use of this source code is governed by a BSD-style license that can be
61cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * found in the LICENSE file.
70b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger */
80b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger
91cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
101cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#include "SkGeometry.h"
110b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger#include "SkPaint.h"
120b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger#include "SkPath.h"
130b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger#include "SkPDFUtils.h"
140b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger#include "SkStream.h"
150b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger#include "SkString.h"
160b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger#include "SkPDFTypes.h"
170b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger
180b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger// static
190b15698a8c76bb8abc1b555c1d91892669b4118fDerek SollenbergerSkPDFArray* SkPDFUtils::MatrixToArray(const SkMatrix& matrix) {
200b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    SkScalar values[6];
211cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (!matrix.asAffine(values)) {
221cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        SkMatrix::SetAffineIdentity(values);
231cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
240b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger
250b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    SkPDFArray* result = new SkPDFArray;
260b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    result->reserve(6);
270b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    for (size_t i = 0; i < SK_ARRAY_COUNT(values); i++) {
281cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        result->appendScalar(values[i]);
290b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    }
300b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    return result;
310b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger}
320b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger
330b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger// static
340b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenbergervoid SkPDFUtils::AppendTransform(const SkMatrix& matrix, SkWStream* content) {
350b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    SkScalar values[6];
361cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (!matrix.asAffine(values)) {
371cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        SkMatrix::SetAffineIdentity(values);
381cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
390b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    for (size_t i = 0; i < SK_ARRAY_COUNT(values); i++) {
400b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger        SkPDFScalar::Append(values[i], content);
410b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger        content->writeText(" ");
420b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    }
430b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    content->writeText("cm\n");
440b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger}
450b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger
460b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger// static
470b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenbergervoid SkPDFUtils::MoveTo(SkScalar x, SkScalar y, SkWStream* content) {
480b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    SkPDFScalar::Append(x, content);
490b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    content->writeText(" ");
500b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    SkPDFScalar::Append(y, content);
510b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    content->writeText(" m\n");
520b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger}
530b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger
540b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger// static
550b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenbergervoid SkPDFUtils::AppendLine(SkScalar x, SkScalar y, SkWStream* content) {
560b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    SkPDFScalar::Append(x, content);
570b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    content->writeText(" ");
580b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    SkPDFScalar::Append(y, content);
590b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    content->writeText(" l\n");
600b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger}
610b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger
620b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger// static
630b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenbergervoid SkPDFUtils::AppendCubic(SkScalar ctl1X, SkScalar ctl1Y,
640b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger                             SkScalar ctl2X, SkScalar ctl2Y,
650b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger                             SkScalar dstX, SkScalar dstY, SkWStream* content) {
660b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    SkString cmd("y\n");
670b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    SkPDFScalar::Append(ctl1X, content);
680b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    content->writeText(" ");
690b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    SkPDFScalar::Append(ctl1Y, content);
700b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    content->writeText(" ");
710b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    if (ctl2X != dstX || ctl2Y != dstY) {
720b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger        cmd.set("c\n");
730b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger        SkPDFScalar::Append(ctl2X, content);
740b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger        content->writeText(" ");
750b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger        SkPDFScalar::Append(ctl2Y, content);
760b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger        content->writeText(" ");
770b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    }
780b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    SkPDFScalar::Append(dstX, content);
790b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    content->writeText(" ");
800b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    SkPDFScalar::Append(dstY, content);
810b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    content->writeText(" ");
820b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    content->writeText(cmd.c_str());
830b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger}
840b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger
850b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger// static
860b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenbergervoid SkPDFUtils::AppendRectangle(const SkRect& rect, SkWStream* content) {
870b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    // Skia has 0,0 at top left, pdf at bottom left.  Do the right thing.
880b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    SkScalar bottom = SkMinScalar(rect.fBottom, rect.fTop);
890b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger
900b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    SkPDFScalar::Append(rect.fLeft, content);
910b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    content->writeText(" ");
920b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    SkPDFScalar::Append(bottom, content);
930b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    content->writeText(" ");
940b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    SkPDFScalar::Append(rect.width(), content);
950b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    content->writeText(" ");
960b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    SkPDFScalar::Append(rect.height(), content);
970b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    content->writeText(" re\n");
980b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger}
990b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger
1000b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger// static
1010b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenbergervoid SkPDFUtils::EmitPath(const SkPath& path, SkWStream* content) {
1020b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    SkPoint args[4];
1030b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    SkPath::Iter iter(path, false);
1040b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    for (SkPath::Verb verb = iter.next(args);
1050b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger         verb != SkPath::kDone_Verb;
1060b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger         verb = iter.next(args)) {
1070b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger        // args gets all the points, even the implicit first point.
1080b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger        switch (verb) {
1090b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger            case SkPath::kMove_Verb:
1100b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger                MoveTo(args[0].fX, args[0].fY, content);
1110b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger                break;
1120b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger            case SkPath::kLine_Verb:
1130b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger                AppendLine(args[1].fX, args[1].fY, content);
1140b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger                break;
1150b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger            case SkPath::kQuad_Verb: {
1161cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                SkPoint cubic[4];
1171cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                SkConvertQuadToCubic(args, cubic);
1181cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                AppendCubic(cubic[1].fX, cubic[1].fY, cubic[2].fX, cubic[2].fY,
1191cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                            cubic[3].fX, cubic[3].fY, content);
1200b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger                break;
1210b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger            }
1220b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger            case SkPath::kCubic_Verb:
1230b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger                AppendCubic(args[1].fX, args[1].fY, args[2].fX, args[2].fY,
1240b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger                            args[3].fX, args[3].fY, content);
1250b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger                break;
1260b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger            case SkPath::kClose_Verb:
1270b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger                ClosePath(content);
1280b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger                break;
1290b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger            default:
1300b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger                SkASSERT(false);
1310b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger                break;
1320b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger        }
1330b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    }
1340b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger}
1350b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger
1360b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger// static
1370b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenbergervoid SkPDFUtils::ClosePath(SkWStream* content) {
1380b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    content->writeText("h\n");
1390b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger}
1400b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger
1410b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger// static
1420b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenbergervoid SkPDFUtils::PaintPath(SkPaint::Style style, SkPath::FillType fill,
1430b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger                           SkWStream* content) {
1441cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (style == SkPaint::kFill_Style) {
1450b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger        content->writeText("f");
1461cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    } else if (style == SkPaint::kStrokeAndFill_Style) {
1470b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger        content->writeText("B");
1481cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    } else if (style == SkPaint::kStroke_Style) {
1490b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger        content->writeText("S");
1501cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
1510b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger
1520b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    if (style != SkPaint::kStroke_Style) {
1530b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger        NOT_IMPLEMENTED(fill == SkPath::kInverseEvenOdd_FillType, false);
1540b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger        NOT_IMPLEMENTED(fill == SkPath::kInverseWinding_FillType, false);
1551cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        if (fill == SkPath::kEvenOdd_FillType) {
1560b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger            content->writeText("*");
1571cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        }
1580b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    }
1590b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    content->writeText("\n");
1600b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger}
1610b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger
1620b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger// static
1630b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenbergervoid SkPDFUtils::StrokePath(SkWStream* content) {
1640b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    SkPDFUtils::PaintPath(
1650b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger        SkPaint::kStroke_Style, SkPath::kWinding_FillType, content);
1660b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger}
1670b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger
1680b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger// static
1690b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenbergervoid SkPDFUtils::DrawFormXObject(int objectIndex, SkWStream* content) {
1700b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    content->writeText("/X");
1710b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    content->writeDecAsText(objectIndex);
1720b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    content->writeText(" Do\n");
1730b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger}
1740b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger
1750b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger// static
1760b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenbergervoid SkPDFUtils::ApplyGraphicState(int objectIndex, SkWStream* content) {
1770b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    content->writeText("/G");
1780b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    content->writeDecAsText(objectIndex);
1790b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    content->writeText(" gs\n");
1800b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger}
181