19b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org/*
2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2011 Google Inc.
39b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org *
4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
69b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org */
79b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org
89b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org#include "SkPDFDevice.h"
99b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org
10238be8c7e5de5a83517440a3db7f7965b47fb010vandebo@chromium.org#include "SkAnnotation.h"
119b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org#include "SkColor.h"
129fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org#include "SkClipStack.h"
138a85d0c4938173476d037d7af0ee3b9436a1234ereed@google.com#include "SkData.h"
14fb0b0edd86d71bb423fa921eaac1e2071602115cvandebo@chromium.org#include "SkDraw.h"
1528be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org#include "SkGlyphCache.h"
169b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org#include "SkPaint.h"
17a518086928494319b8968abc09808eff492c194fvandebo@chromium.org#include "SkPath.h"
1892ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org#include "SkPathOps.h"
19db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary#include "SkPDFBitmap.h"
2028be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org#include "SkPDFFont.h"
21eb6c7596af1a1fc7860e27ff2f678a33b2576c0fvandebo@chromium.org#include "SkPDFFormXObject.h"
2277bcaa324a574584331322d98768582d9232f7fcvandebo@chromium.org#include "SkPDFGraphicState.h"
2347401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org#include "SkPDFResourceDict.h"
24da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org#include "SkPDFShader.h"
259b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org#include "SkPDFStream.h"
2677bcaa324a574584331322d98768582d9232f7fcvandebo@chromium.org#include "SkPDFTypes.h"
279db86bb9cd1b77be0afc504ccc07026e4282d7e7ctguil@chromium.org#include "SkPDFUtils.h"
289b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org#include "SkRect.h"
29a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com#include "SkRRect.h"
309b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org#include "SkString.h"
3189443aba5bfa2b040dc9fd24938b7d0b3decd737reed#include "SkSurface.h"
3228be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org#include "SkTextFormatParams.h"
334e1cc6ac450903510b96c1b12f6ee6f420044a66vandebo@chromium.org#include "SkTemplates.h"
34fed86bdb8b9f037439bbfa7cdbd53a581dbc5985reed@google.com#include "SkTypefacePriv.h"
35c375b0b5c5c03d381111bf7bff12507d5ed24769senorblanco#include "SkXfermodeInterpretation.h"
369b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org
3773a7ea3ae0d37ee28f90d6b38c49fda052638253edisonn@google.com#define DPI_FOR_RASTER_SCALE_ONE 72
3873a7ea3ae0d37ee28f90d6b38c49fda052638253edisonn@google.com
399b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org// Utility functions
409b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org
41c375b0b5c5c03d381111bf7bff12507d5ed24769senorblanco// If the paint will definitely draw opaquely, replace kSrc_Mode with
42c375b0b5c5c03d381111bf7bff12507d5ed24769senorblanco// kSrcOver_Mode.  http://crbug.com/473572
43c375b0b5c5c03d381111bf7bff12507d5ed24769senorblancostatic void replace_srcmode_on_opaque_paint(SkPaint* paint) {
44c375b0b5c5c03d381111bf7bff12507d5ed24769senorblanco    if (kSrcOver_SkXfermodeInterpretation
45c375b0b5c5c03d381111bf7bff12507d5ed24769senorblanco        == SkInterpretXfermode(*paint, false)) {
46c375b0b5c5c03d381111bf7bff12507d5ed24769senorblanco        paint->setXfermode(NULL);
47c375b0b5c5c03d381111bf7bff12507d5ed24769senorblanco    }
48c375b0b5c5c03d381111bf7bff12507d5ed24769senorblanco}
49c375b0b5c5c03d381111bf7bff12507d5ed24769senorblanco
509fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.orgstatic void emit_pdf_color(SkColor color, SkWStream* result) {
519b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org    SkASSERT(SkColorGetA(color) == 0xFF);  // We handle alpha elsewhere.
5280ea19ca4bdd68c1493666a5fe7e4ce9d43ded8breed    SkScalar colorScale = SkScalarInvert(0xFF);
5380ea19ca4bdd68c1493666a5fe7e4ce9d43ded8breed    SkPDFUtils::AppendScalar(SkColorGetR(color) * colorScale, result);
54cae5fba82e687d674b076b10cdc8aba46e1ac3b3vandebo@chromium.org    result->writeText(" ");
5580ea19ca4bdd68c1493666a5fe7e4ce9d43ded8breed    SkPDFUtils::AppendScalar(SkColorGetG(color) * colorScale, result);
56cae5fba82e687d674b076b10cdc8aba46e1ac3b3vandebo@chromium.org    result->writeText(" ");
5780ea19ca4bdd68c1493666a5fe7e4ce9d43ded8breed    SkPDFUtils::AppendScalar(SkColorGetB(color) * colorScale, result);
58cae5fba82e687d674b076b10cdc8aba46e1ac3b3vandebo@chromium.org    result->writeText(" ");
599b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org}
609b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org
619fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.orgstatic SkPaint calculate_text_paint(const SkPaint& paint) {
6228be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org    SkPaint result = paint;
6328be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org    if (result.isFakeBoldText()) {
6428be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org        SkScalar fakeBoldScale = SkScalarInterpFunc(result.getTextSize(),
6528be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org                                                    kStdFakeBoldInterpKeys,
6628be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org                                                    kStdFakeBoldInterpValues,
6728be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org                                                    kStdFakeBoldInterpLength);
6828be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org        SkScalar width = SkScalarMul(result.getTextSize(), fakeBoldScale);
69769fa6a013baca6d7404e2bf096a34a7e3635fa5ctguil@chromium.org        if (result.getStyle() == SkPaint::kFill_Style) {
7028be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org            result.setStyle(SkPaint::kStrokeAndFill_Style);
71769fa6a013baca6d7404e2bf096a34a7e3635fa5ctguil@chromium.org        } else {
7228be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org            width += result.getStrokeWidth();
73769fa6a013baca6d7404e2bf096a34a7e3635fa5ctguil@chromium.org        }
7428be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org        result.setStrokeWidth(width);
7528be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org    }
7628be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org    return result;
7728be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org}
7828be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org
7928be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org// Stolen from measure_text in SkDraw.cpp and then tweaked.
809fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.orgstatic void align_text(SkDrawCacheProc glyphCacheProc, const SkPaint& paint,
819a87cee904e2d8f0ea6a0e7e3ca864262a8cb7c4bungeman@google.com                       const uint16_t* glyphs, size_t len,
829a87cee904e2d8f0ea6a0e7e3ca864262a8cb7c4bungeman@google.com                       SkScalar* x, SkScalar* y) {
839a87cee904e2d8f0ea6a0e7e3ca864262a8cb7c4bungeman@google.com    if (paint.getTextAlign() == SkPaint::kLeft_Align) {
8428be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org        return;
85769fa6a013baca6d7404e2bf096a34a7e3635fa5ctguil@chromium.org    }
8628be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org
8728be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org    SkMatrix ident;
8828be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org    ident.reset();
89532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com    SkAutoGlyphCache autoCache(paint, NULL, &ident);
9028be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org    SkGlyphCache* cache = autoCache.getCache();
9128be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org
929510ccc06bbfa5e888f66578042674be98d8ac60ctguil@chromium.org    const char* start = reinterpret_cast<const char*>(glyphs);
939510ccc06bbfa5e888f66578042674be98d8ac60ctguil@chromium.org    const char* stop = reinterpret_cast<const char*>(glyphs + len);
9428be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org    SkFixed xAdv = 0, yAdv = 0;
9528be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org
96769fa6a013baca6d7404e2bf096a34a7e3635fa5ctguil@chromium.org    // TODO(vandebo): This probably needs to take kerning into account.
9728be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org    while (start < stop) {
9828be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org        const SkGlyph& glyph = glyphCacheProc(cache, &start, 0, 0);
9928be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org        xAdv += glyph.fAdvanceX;
10028be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org        yAdv += glyph.fAdvanceY;
10128be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org    };
102769fa6a013baca6d7404e2bf096a34a7e3635fa5ctguil@chromium.org    if (paint.getTextAlign() == SkPaint::kLeft_Align) {
10328be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org        return;
104769fa6a013baca6d7404e2bf096a34a7e3635fa5ctguil@chromium.org    }
10528be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org
10628be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org    SkScalar xAdj = SkFixedToScalar(xAdv);
10728be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org    SkScalar yAdj = SkFixedToScalar(yAdv);
10828be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org    if (paint.getTextAlign() == SkPaint::kCenter_Align) {
10928be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org        xAdj = SkScalarHalf(xAdj);
11028be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org        yAdj = SkScalarHalf(yAdj);
11128be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org    }
11228be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org    *x = *x - xAdj;
11328be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org    *y = *y - yAdj;
11428be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org}
11528be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org
116a4662865e37a2ca95b5e3379072f6a274acc8ac8robertphillips@google.comstatic int max_glyphid_for_typeface(SkTypeface* typeface) {
117fed86bdb8b9f037439bbfa7cdbd53a581dbc5985reed@google.com    SkAutoResolveDefaultTypeface autoResolve(typeface);
118fed86bdb8b9f037439bbfa7cdbd53a581dbc5985reed@google.com    typeface = autoResolve.get();
1196a4ba5b20590e377d42d3488a32cd5dd94355107commit-bot@chromium.org    return typeface->countGlyphs() - 1;
1204e1cc6ac450903510b96c1b12f6ee6f420044a66vandebo@chromium.org}
1214e1cc6ac450903510b96c1b12f6ee6f420044a66vandebo@chromium.org
1224e1cc6ac450903510b96c1b12f6ee6f420044a66vandebo@chromium.orgtypedef SkAutoSTMalloc<128, uint16_t> SkGlyphStorage;
1234e1cc6ac450903510b96c1b12f6ee6f420044a66vandebo@chromium.org
124aec406650cbfa4ef65d83db5ff4f82572e8e098freed@google.comstatic int force_glyph_encoding(const SkPaint& paint, const void* text,
125aec406650cbfa4ef65d83db5ff4f82572e8e098freed@google.com                                size_t len, SkGlyphStorage* storage,
12622edc8310cd57ab02155bfa6b2ddaf830556bcafbungeman                                const uint16_t** glyphIDs) {
1274e1cc6ac450903510b96c1b12f6ee6f420044a66vandebo@chromium.org    // Make sure we have a glyph id encoding.
1284e1cc6ac450903510b96c1b12f6ee6f420044a66vandebo@chromium.org    if (paint.getTextEncoding() != SkPaint::kGlyphID_TextEncoding) {
129aec406650cbfa4ef65d83db5ff4f82572e8e098freed@google.com        int numGlyphs = paint.textToGlyphs(text, len, NULL);
1304e1cc6ac450903510b96c1b12f6ee6f420044a66vandebo@chromium.org        storage->reset(numGlyphs);
1314e1cc6ac450903510b96c1b12f6ee6f420044a66vandebo@chromium.org        paint.textToGlyphs(text, len, storage->get());
1324e1cc6ac450903510b96c1b12f6ee6f420044a66vandebo@chromium.org        *glyphIDs = storage->get();
1334e1cc6ac450903510b96c1b12f6ee6f420044a66vandebo@chromium.org        return numGlyphs;
1344e1cc6ac450903510b96c1b12f6ee6f420044a66vandebo@chromium.org    }
1354e1cc6ac450903510b96c1b12f6ee6f420044a66vandebo@chromium.org
1364e1cc6ac450903510b96c1b12f6ee6f420044a66vandebo@chromium.org    // For user supplied glyph ids we need to validate them.
1374e1cc6ac450903510b96c1b12f6ee6f420044a66vandebo@chromium.org    SkASSERT((len & 1) == 0);
138aec406650cbfa4ef65d83db5ff4f82572e8e098freed@google.com    int numGlyphs = SkToInt(len / 2);
13922edc8310cd57ab02155bfa6b2ddaf830556bcafbungeman    const uint16_t* input = static_cast<const uint16_t*>(text);
1404e1cc6ac450903510b96c1b12f6ee6f420044a66vandebo@chromium.org
1414e1cc6ac450903510b96c1b12f6ee6f420044a66vandebo@chromium.org    int maxGlyphID = max_glyphid_for_typeface(paint.getTypeface());
142aec406650cbfa4ef65d83db5ff4f82572e8e098freed@google.com    int validated;
1434e1cc6ac450903510b96c1b12f6ee6f420044a66vandebo@chromium.org    for (validated = 0; validated < numGlyphs; ++validated) {
1444e1cc6ac450903510b96c1b12f6ee6f420044a66vandebo@chromium.org        if (input[validated] > maxGlyphID) {
1454e1cc6ac450903510b96c1b12f6ee6f420044a66vandebo@chromium.org            break;
1464e1cc6ac450903510b96c1b12f6ee6f420044a66vandebo@chromium.org        }
1474e1cc6ac450903510b96c1b12f6ee6f420044a66vandebo@chromium.org    }
1484e1cc6ac450903510b96c1b12f6ee6f420044a66vandebo@chromium.org    if (validated >= numGlyphs) {
14922edc8310cd57ab02155bfa6b2ddaf830556bcafbungeman        *glyphIDs = static_cast<const uint16_t*>(text);
1504e1cc6ac450903510b96c1b12f6ee6f420044a66vandebo@chromium.org        return numGlyphs;
1514e1cc6ac450903510b96c1b12f6ee6f420044a66vandebo@chromium.org    }
1524e1cc6ac450903510b96c1b12f6ee6f420044a66vandebo@chromium.org
1534e1cc6ac450903510b96c1b12f6ee6f420044a66vandebo@chromium.org    // Silently drop anything out of range.
1544e1cc6ac450903510b96c1b12f6ee6f420044a66vandebo@chromium.org    storage->reset(numGlyphs);
1554e1cc6ac450903510b96c1b12f6ee6f420044a66vandebo@chromium.org    if (validated > 0) {
1564e1cc6ac450903510b96c1b12f6ee6f420044a66vandebo@chromium.org        memcpy(storage->get(), input, validated * sizeof(uint16_t));
1574e1cc6ac450903510b96c1b12f6ee6f420044a66vandebo@chromium.org    }
1584e1cc6ac450903510b96c1b12f6ee6f420044a66vandebo@chromium.org
159aec406650cbfa4ef65d83db5ff4f82572e8e098freed@google.com    for (int i = validated; i < numGlyphs; ++i) {
1604e1cc6ac450903510b96c1b12f6ee6f420044a66vandebo@chromium.org        storage->get()[i] = input[i];
1614e1cc6ac450903510b96c1b12f6ee6f420044a66vandebo@chromium.org        if (input[i] > maxGlyphID) {
1624e1cc6ac450903510b96c1b12f6ee6f420044a66vandebo@chromium.org            storage->get()[i] = 0;
1634e1cc6ac450903510b96c1b12f6ee6f420044a66vandebo@chromium.org        }
1644e1cc6ac450903510b96c1b12f6ee6f420044a66vandebo@chromium.org    }
1654e1cc6ac450903510b96c1b12f6ee6f420044a66vandebo@chromium.org    *glyphIDs = storage->get();
1664e1cc6ac450903510b96c1b12f6ee6f420044a66vandebo@chromium.org    return numGlyphs;
1674e1cc6ac450903510b96c1b12f6ee6f420044a66vandebo@chromium.org}
1684e1cc6ac450903510b96c1b12f6ee6f420044a66vandebo@chromium.org
169b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.orgstatic void set_text_transform(SkScalar x, SkScalar y, SkScalar textSkewX,
170b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org                               SkWStream* content) {
171b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org    // Flip the text about the x-axis to account for origin swap and include
172b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org    // the passed parameters.
173b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org    content->writeText("1 0 ");
174bc4696b9176e05940a7c2d6778276cdbc55ccd61halcanary    SkPDFUtils::AppendScalar(0 - textSkewX, content);
175b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org    content->writeText(" -1 ");
176bc4696b9176e05940a7c2d6778276cdbc55ccd61halcanary    SkPDFUtils::AppendScalar(x, content);
177b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org    content->writeText(" ");
178bc4696b9176e05940a7c2d6778276cdbc55ccd61halcanary    SkPDFUtils::AppendScalar(y, content);
179b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org    content->writeText(" Tm\n");
180b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org}
181b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org
1829fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org// It is important to not confuse GraphicStateEntry with SkPDFGraphicState, the
1839fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org// later being our representation of an object in the PDF file.
1849fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.orgstruct GraphicStateEntry {
1859fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    GraphicStateEntry();
1869fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org
1879fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    // Compare the fields we care about when setting up a new content entry.
1889fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    bool compareInitialState(const GraphicStateEntry& b);
1899fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org
1909fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    SkMatrix fMatrix;
1919fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    // We can't do set operations on Paths, though PDF natively supports
1929fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    // intersect.  If the clip stack does anything other than intersect,
1939fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    // we have to fall back to the region.  Treat fClipStack as authoritative.
1949fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    // See http://code.google.com/p/skia/issues/detail?id=221
1959fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    SkClipStack fClipStack;
1969fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    SkRegion fClipRegion;
1979fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org
1989fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    // When emitting the content entry, we will ensure the graphic state
1999fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    // is set to these values first.
2009fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    SkColor fColor;
2019fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    SkScalar fTextScaleX;  // Zero means we don't care what the value is.
2029fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    SkPaint::Style fTextFill;  // Only if TextScaleX is non-zero.
2039fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    int fShaderIndex;
2049fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    int fGraphicStateIndex;
2059fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org
2069fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    // We may change the font (i.e. for Type1 support) within a
2079fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    // ContentEntry.  This is the one currently in effect, or NULL if none.
2089fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    SkPDFFont* fFont;
2099fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    // In PDF, text size has no default value. It is only valid if fFont is
2109fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    // not NULL.
2119fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    SkScalar fTextSize;
2129fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org};
2139fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org
2149fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.orgGraphicStateEntry::GraphicStateEntry() : fColor(SK_ColorBLACK),
2159fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org                                         fTextScaleX(SK_Scalar1),
2169fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org                                         fTextFill(SkPaint::kFill_Style),
2179fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org                                         fShaderIndex(-1),
2189fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org                                         fGraphicStateIndex(-1),
2199fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org                                         fFont(NULL),
2209fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org                                         fTextSize(SK_ScalarNaN) {
2219fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    fMatrix.reset();
2229fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org}
2239fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org
224b000d76af4de735a233e64b7be68cee8a5a8f8dccommit-bot@chromium.orgbool GraphicStateEntry::compareInitialState(const GraphicStateEntry& cur) {
225b000d76af4de735a233e64b7be68cee8a5a8f8dccommit-bot@chromium.org    return fColor == cur.fColor &&
226b000d76af4de735a233e64b7be68cee8a5a8f8dccommit-bot@chromium.org           fShaderIndex == cur.fShaderIndex &&
227b000d76af4de735a233e64b7be68cee8a5a8f8dccommit-bot@chromium.org           fGraphicStateIndex == cur.fGraphicStateIndex &&
228b000d76af4de735a233e64b7be68cee8a5a8f8dccommit-bot@chromium.org           fMatrix == cur.fMatrix &&
229b000d76af4de735a233e64b7be68cee8a5a8f8dccommit-bot@chromium.org           fClipStack == cur.fClipStack &&
230b000d76af4de735a233e64b7be68cee8a5a8f8dccommit-bot@chromium.org           (fTextScaleX == 0 ||
231b000d76af4de735a233e64b7be68cee8a5a8f8dccommit-bot@chromium.org               (fTextScaleX == cur.fTextScaleX && fTextFill == cur.fTextFill));
2329fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org}
2339fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org
2349fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.orgclass GraphicStackState {
2359fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.orgpublic:
2369fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    GraphicStackState(const SkClipStack& existingClipStack,
2379fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org                      const SkRegion& existingClipRegion,
2389fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org                      SkWStream* contentStream)
2399fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org            : fStackDepth(0),
2409fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org              fContentStream(contentStream) {
2419fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org        fEntries[0].fClipStack = existingClipStack;
2429fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org        fEntries[0].fClipRegion = existingClipRegion;
2439fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    }
2449fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org
2459fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    void updateClip(const SkClipStack& clipStack, const SkRegion& clipRegion,
246663515bc59325092c4e47f5189782bd6fcd0586avandebo@chromium.org                    const SkPoint& translation);
2479fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    void updateMatrix(const SkMatrix& matrix);
2489fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    void updateDrawingState(const GraphicStateEntry& state);
2499fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org
2509fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    void drainStack();
2519fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org
2529fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.orgprivate:
2539fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    void push();
2549fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    void pop();
2559fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    GraphicStateEntry* currentEntry() { return &fEntries[fStackDepth]; }
2569fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org
2579fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    // Conservative limit on save depth, see impl. notes in PDF 1.4 spec.
2589fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    static const int kMaxStackDepth = 12;
2599fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    GraphicStateEntry fEntries[kMaxStackDepth + 1];
2609fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    int fStackDepth;
2619fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    SkWStream* fContentStream;
2629fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org};
2639fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org
2649fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.orgvoid GraphicStackState::drainStack() {
2659fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    while (fStackDepth) {
2669fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org        pop();
2679fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    }
2689fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org}
2699fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org
2709fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.orgvoid GraphicStackState::push() {
2719fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    SkASSERT(fStackDepth < kMaxStackDepth);
2729fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    fContentStream->writeText("q\n");
2739fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    fStackDepth++;
2749fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    fEntries[fStackDepth] = fEntries[fStackDepth - 1];
2759fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org}
2769fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org
2779fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.orgvoid GraphicStackState::pop() {
2789fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    SkASSERT(fStackDepth > 0);
2799fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    fContentStream->writeText("Q\n");
2809fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    fStackDepth--;
2819fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org}
2829fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org
28380214e26c57c5fea954006400852e8999e201923robertphillips@google.com// This function initializes iter to be an iterator on the "stack" argument
2849fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org// and then skips over the leading entries as specified in prefix.  It requires
2859fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org// and asserts that "prefix" will be a prefix to "stack."
2869fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.orgstatic void skip_clip_stack_prefix(const SkClipStack& prefix,
2879fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org                                   const SkClipStack& stack,
288c029062a0312fb747fb6c2677983aba51795c580robertphillips@google.com                                   SkClipStack::Iter* iter) {
28980214e26c57c5fea954006400852e8999e201923robertphillips@google.com    SkClipStack::B2TIter prefixIter(prefix);
29080214e26c57c5fea954006400852e8999e201923robertphillips@google.com    iter->reset(stack, SkClipStack::Iter::kBottom_IterStart);
2919fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org
2928182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com    const SkClipStack::Element* prefixEntry;
2938182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com    const SkClipStack::Element* iterEntry;
2949fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org
2959fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    for (prefixEntry = prefixIter.next(); prefixEntry;
296c029062a0312fb747fb6c2677983aba51795c580robertphillips@google.com            prefixEntry = prefixIter.next()) {
2979fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org        iterEntry = iter->next();
2989fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org        SkASSERT(iterEntry);
2998887ede82465687355c7a1c51e4553e99b2fb15avandebo@chromium.org        // Because of SkClipStack does internal intersection, the last clip
3008887ede82465687355c7a1c51e4553e99b2fb15avandebo@chromium.org        // entry may differ.
3019510ccc06bbfa5e888f66578042674be98d8ac60ctguil@chromium.org        if (*prefixEntry != *iterEntry) {
3028182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com            SkASSERT(prefixEntry->getOp() == SkRegion::kIntersect_Op);
3038182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com            SkASSERT(iterEntry->getOp() == SkRegion::kIntersect_Op);
3048182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com            SkASSERT(iterEntry->getType() == prefixEntry->getType());
305c029062a0312fb747fb6c2677983aba51795c580robertphillips@google.com            // back up the iterator by one
306c029062a0312fb747fb6c2677983aba51795c580robertphillips@google.com            iter->prev();
3078887ede82465687355c7a1c51e4553e99b2fb15avandebo@chromium.org            prefixEntry = prefixIter.next();
3088887ede82465687355c7a1c51e4553e99b2fb15avandebo@chromium.org            break;
3098887ede82465687355c7a1c51e4553e99b2fb15avandebo@chromium.org        }
3109fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    }
3119fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org
3129fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    SkASSERT(prefixEntry == NULL);
3139fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org}
3149fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org
3159fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.orgstatic void emit_clip(SkPath* clipPath, SkRect* clipRect,
3169fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org                      SkWStream* contentStream) {
3179fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    SkASSERT(clipPath || clipRect);
3189fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org
3199fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    SkPath::FillType clipFill;
3209fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    if (clipPath) {
321683001ce0de70c859ea5e5353245b18cadbefc45vandebo@chromium.org        SkPDFUtils::EmitPath(*clipPath, SkPaint::kFill_Style, contentStream);
3229fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org        clipFill = clipPath->getFillType();
3233e7b280b720ae202db6561f31d862990a7be32d9vandebo@chromium.org    } else {
3249fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org        SkPDFUtils::AppendRectangle(*clipRect, contentStream);
3259fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org        clipFill = SkPath::kWinding_FillType;
3269fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    }
3279fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org
3289fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    NOT_IMPLEMENTED(clipFill == SkPath::kInverseEvenOdd_FillType, false);
3299fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    NOT_IMPLEMENTED(clipFill == SkPath::kInverseWinding_FillType, false);
3309fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    if (clipFill == SkPath::kEvenOdd_FillType) {
3319fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org        contentStream->writeText("W* n\n");
3329fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    } else {
3339fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org        contentStream->writeText("W n\n");
3349fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    }
3359fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org}
3369fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org
337d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org/* Calculate an inverted path's equivalent non-inverted path, given the
338d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org * canvas bounds.
339d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org * outPath may alias with invPath (since this is supported by PathOps).
340d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org */
341d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.orgstatic bool calculate_inverse_path(const SkRect& bounds, const SkPath& invPath,
342d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org                                   SkPath* outPath) {
343d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org    SkASSERT(invPath.isInverseFillType());
344d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org
345d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org    SkPath clipPath;
346d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org    clipPath.addRect(bounds);
347d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org
348d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org    return Op(clipPath, invPath, kIntersect_PathOp, outPath);
349d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org}
350d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org
351632e92fc3fa99e6a78fcbc67d6da68d5bd8334c3fmalita#ifdef SK_PDF_USE_PATHOPS_CLIPPING
352d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org// Sanity check the numerical values of the SkRegion ops and PathOps ops
353d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org// enums so region_op_to_pathops_op can do a straight passthrough cast.
354d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org// If these are failing, it may be necessary to make region_op_to_pathops_op
355d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org// do more.
356d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.orgSK_COMPILE_ASSERT(SkRegion::kDifference_Op == (int)kDifference_PathOp,
357d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org                  region_pathop_mismatch);
358d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.orgSK_COMPILE_ASSERT(SkRegion::kIntersect_Op == (int)kIntersect_PathOp,
359d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org                  region_pathop_mismatch);
360d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.orgSK_COMPILE_ASSERT(SkRegion::kUnion_Op == (int)kUnion_PathOp,
361d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org                  region_pathop_mismatch);
362d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.orgSK_COMPILE_ASSERT(SkRegion::kXOR_Op == (int)kXOR_PathOp,
363d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org                  region_pathop_mismatch);
364d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.orgSK_COMPILE_ASSERT(SkRegion::kReverseDifference_Op ==
365d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org                  (int)kReverseDifference_PathOp,
366d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org                  region_pathop_mismatch);
367d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org
368d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.orgstatic SkPathOp region_op_to_pathops_op(SkRegion::Op op) {
369d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org    SkASSERT(op >= 0);
370d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org    SkASSERT(op <= SkRegion::kReverseDifference_Op);
371d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org    return (SkPathOp)op;
372d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org}
373d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org
374d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org/* Uses Path Ops to calculate a vector SkPath clip from a clip stack.
375d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org * Returns true if successful, or false if not successful.
376d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org * If successful, the resulting clip is stored in outClipPath.
377d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org * If not successful, outClipPath is undefined, and a fallback method
378d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org * should be used.
379d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org */
380d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.orgstatic bool get_clip_stack_path(const SkMatrix& transform,
381d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org                                const SkClipStack& clipStack,
382d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org                                const SkRegion& clipRegion,
383d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org                                SkPath* outClipPath) {
384d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org    outClipPath->reset();
385d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org    outClipPath->setFillType(SkPath::kInverseWinding_FillType);
386d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org
387d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org    const SkClipStack::Element* clipEntry;
388d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org    SkClipStack::Iter iter;
389d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org    iter.reset(clipStack, SkClipStack::Iter::kBottom_IterStart);
390d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org    for (clipEntry = iter.next(); clipEntry; clipEntry = iter.next()) {
391d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org        SkPath entryPath;
392d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org        if (SkClipStack::Element::kEmpty_Type == clipEntry->getType()) {
393d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org            outClipPath->reset();
394d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org            outClipPath->setFillType(SkPath::kInverseWinding_FillType);
395d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org            continue;
396e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org        } else {
397e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org            clipEntry->asPath(&entryPath);
398d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org        }
399d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org        entryPath.transform(transform);
400d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org
401d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org        if (SkRegion::kReplace_Op == clipEntry->getOp()) {
402d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org            *outClipPath = entryPath;
403d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org        } else {
404d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org            SkPathOp op = region_op_to_pathops_op(clipEntry->getOp());
405d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org            if (!Op(*outClipPath, entryPath, op, outClipPath)) {
406d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org                return false;
407d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org            }
408d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org        }
409d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org    }
410d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org
411d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org    if (outClipPath->isInverseFillType()) {
412d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org        // The bounds are slightly outset to ensure this is correct in the
413d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org        // face of floating-point accuracy and possible SkRegion bitmap
414d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org        // approximations.
415d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org        SkRect clipBounds = SkRect::Make(clipRegion.getBounds());
416d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org        clipBounds.outset(SK_Scalar1, SK_Scalar1);
417d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org        if (!calculate_inverse_path(clipBounds, *outClipPath, outClipPath)) {
418d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org            return false;
419d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org        }
420d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org    }
421d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org    return true;
422d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org}
423d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org#endif
424d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org
425769fa6a013baca6d7404e2bf096a34a7e3635fa5ctguil@chromium.org// TODO(vandebo): Take advantage of SkClipStack::getSaveCount(), the PDF
4269fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org// graphic state stack, and the fact that we can know all the clips used
4279fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org// on the page to optimize this.
4289fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.orgvoid GraphicStackState::updateClip(const SkClipStack& clipStack,
4299fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org                                   const SkRegion& clipRegion,
430663515bc59325092c4e47f5189782bd6fcd0586avandebo@chromium.org                                   const SkPoint& translation) {
4319fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    if (clipStack == currentEntry()->fClipStack) {
4329fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org        return;
4339fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    }
4349fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org
4359fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    while (fStackDepth > 0) {
4369fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org        pop();
4379fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org        if (clipStack == currentEntry()->fClipStack) {
4389fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org            return;
4399fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org        }
4409fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    }
4419fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    push();
4429fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org
443d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org    currentEntry()->fClipStack = clipStack;
444d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org    currentEntry()->fClipRegion = clipRegion;
445d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org
446d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org    SkMatrix transform;
447d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org    transform.setTranslate(translation.fX, translation.fY);
448d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org
449632e92fc3fa99e6a78fcbc67d6da68d5bd8334c3fmalita#ifdef SK_PDF_USE_PATHOPS_CLIPPING
450d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org    SkPath clipPath;
451d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org    if (get_clip_stack_path(transform, clipStack, clipRegion, &clipPath)) {
452d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org        emit_clip(&clipPath, NULL, fContentStream);
453d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org        return;
454d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org    }
455d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org#endif
4569fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    // gsState->initialEntry()->fClipStack/Region specifies the clip that has
4579fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    // already been applied.  (If this is a top level device, then it specifies
4589fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    // a clip to the content area.  If this is a layer, then it specifies
4599fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    // the clip in effect when the layer was created.)  There's no need to
4609fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    // reapply that clip; SKCanvas's SkDrawIter will draw anything outside the
4619fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    // initial clip on the parent layer.  (This means there's a bug if the user
4629fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    // expands the clip and then uses any xfer mode that uses dst:
4639fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    // http://code.google.com/p/skia/issues/detail?id=228 )
464c029062a0312fb747fb6c2677983aba51795c580robertphillips@google.com    SkClipStack::Iter iter;
4659fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    skip_clip_stack_prefix(fEntries[0].fClipStack, clipStack, &iter);
4669fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org
4679fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    // If the clip stack does anything other than intersect or if it uses
4689fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    // an inverse fill type, we have to fall back to the clip region.
4699fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    bool needRegion = false;
4708182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com    const SkClipStack::Element* clipEntry;
4719fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    for (clipEntry = iter.next(); clipEntry; clipEntry = iter.next()) {
4723b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org        if (clipEntry->getOp() != SkRegion::kIntersect_Op ||
4733b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org                clipEntry->isInverseFilled()) {
4749fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org            needRegion = true;
4759fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org            break;
4769fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org        }
4779fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    }
4789fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org
4799fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    if (needRegion) {
4809fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org        SkPath clipPath;
4819fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org        SkAssertResult(clipRegion.getBoundaryPath(&clipPath));
4829fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org        emit_clip(&clipPath, NULL, fContentStream);
4839fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    } else {
4849fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org        skip_clip_stack_prefix(fEntries[0].fClipStack, clipStack, &iter);
4858182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com        const SkClipStack::Element* clipEntry;
4869fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org        for (clipEntry = iter.next(); clipEntry; clipEntry = iter.next()) {
4878182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com            SkASSERT(clipEntry->getOp() == SkRegion::kIntersect_Op);
4888182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com            switch (clipEntry->getType()) {
4898182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com                case SkClipStack::Element::kRect_Type: {
4908182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com                    SkRect translatedClip;
4918182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com                    transform.mapRect(&translatedClip, clipEntry->getRect());
4928182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com                    emit_clip(NULL, &translatedClip, fContentStream);
4938182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com                    break;
4948182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com                }
4955a346a85027fc8aae5d836d951e455a22b3272d0commit-bot@chromium.org                default: {
4968182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com                    SkPath translatedPath;
4975a346a85027fc8aae5d836d951e455a22b3272d0commit-bot@chromium.org                    clipEntry->asPath(&translatedPath);
4985a346a85027fc8aae5d836d951e455a22b3272d0commit-bot@chromium.org                    translatedPath.transform(transform, &translatedPath);
4998182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com                    emit_clip(&translatedPath, NULL, fContentStream);
5008182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com                    break;
5018182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com                }
5029fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org            }
5039fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org        }
5049fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    }
5059fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org}
5069fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org
5079fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.orgvoid GraphicStackState::updateMatrix(const SkMatrix& matrix) {
5089fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    if (matrix == currentEntry()->fMatrix) {
5099fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org        return;
5109fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    }
5119fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org
5129fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    if (currentEntry()->fMatrix.getType() != SkMatrix::kIdentity_Mask) {
5139fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org        SkASSERT(fStackDepth > 0);
5149fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org        SkASSERT(fEntries[fStackDepth].fClipStack ==
5159fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org                 fEntries[fStackDepth -1].fClipStack);
5169fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org        pop();
5179fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org
5189fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org        SkASSERT(currentEntry()->fMatrix.getType() == SkMatrix::kIdentity_Mask);
5199fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    }
5209fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    if (matrix.getType() == SkMatrix::kIdentity_Mask) {
5219fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org        return;
5229fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    }
5239fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org
5249fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    push();
5259fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    SkPDFUtils::AppendTransform(matrix, fContentStream);
5269fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    currentEntry()->fMatrix = matrix;
5279fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org}
5289fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org
5299fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.orgvoid GraphicStackState::updateDrawingState(const GraphicStateEntry& state) {
5309fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    // PDF treats a shader as a color, so we only set one or the other.
5319fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    if (state.fShaderIndex >= 0) {
5329fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org        if (state.fShaderIndex != currentEntry()->fShaderIndex) {
53393a2e213441c75033b04365c7d68c8d3887288accommit-bot@chromium.org            SkPDFUtils::ApplyPattern(state.fShaderIndex, fContentStream);
5349fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org            currentEntry()->fShaderIndex = state.fShaderIndex;
5359fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org        }
5369fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    } else {
5379fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org        if (state.fColor != currentEntry()->fColor ||
5389fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org                currentEntry()->fShaderIndex >= 0) {
5399fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org            emit_pdf_color(state.fColor, fContentStream);
5409fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org            fContentStream->writeText("RG ");
5419fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org            emit_pdf_color(state.fColor, fContentStream);
5429fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org            fContentStream->writeText("rg\n");
5439fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org            currentEntry()->fColor = state.fColor;
5449fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org            currentEntry()->fShaderIndex = -1;
5459fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org        }
5469fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    }
5479fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org
5489fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    if (state.fGraphicStateIndex != currentEntry()->fGraphicStateIndex) {
5496112c215fbdd53388e64ece36e6c7bba0fe3a451vandebo@chromium.org        SkPDFUtils::ApplyGraphicState(state.fGraphicStateIndex, fContentStream);
5509fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org        currentEntry()->fGraphicStateIndex = state.fGraphicStateIndex;
5519fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    }
5529fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org
5539fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    if (state.fTextScaleX) {
5549fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org        if (state.fTextScaleX != currentEntry()->fTextScaleX) {
5559fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org            SkScalar pdfScale = SkScalarMul(state.fTextScaleX,
5569fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org                                            SkIntToScalar(100));
557bc4696b9176e05940a7c2d6778276cdbc55ccd61halcanary            SkPDFUtils::AppendScalar(pdfScale, fContentStream);
5589fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org            fContentStream->writeText(" Tz\n");
5599fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org            currentEntry()->fTextScaleX = state.fTextScaleX;
5609fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org        }
5619fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org        if (state.fTextFill != currentEntry()->fTextFill) {
5629fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org            SK_COMPILE_ASSERT(SkPaint::kFill_Style == 0, enum_must_match_value);
5639fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org            SK_COMPILE_ASSERT(SkPaint::kStroke_Style == 1,
5649fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org                              enum_must_match_value);
5659fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org            SK_COMPILE_ASSERT(SkPaint::kStrokeAndFill_Style == 2,
5669fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org                              enum_must_match_value);
5679fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org            fContentStream->writeDecAsText(state.fTextFill);
5689fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org            fContentStream->writeText(" Tr\n");
5699fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org            currentEntry()->fTextFill = state.fTextFill;
5709fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org        }
5719fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    }
5729fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org}
5739b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org
57476033be81b82c44fd5d4fdf2672eb22e505da1f0reedstatic bool not_supported_for_layers(const SkPaint& layerPaint) {
575b0e89dcc1d8c1c2f9f7ffb45e8609cdb4a68104bsenorblanco    // PDF does not support image filters, so render them on CPU.
576b0e89dcc1d8c1c2f9f7ffb45e8609cdb4a68104bsenorblanco    // Note that this rendering is done at "screen" resolution (100dpi), not
577b0e89dcc1d8c1c2f9f7ffb45e8609cdb4a68104bsenorblanco    // printer resolution.
578b0e89dcc1d8c1c2f9f7ffb45e8609cdb4a68104bsenorblanco    // FIXME: It may be possible to express some filters natively using PDF
579b0e89dcc1d8c1c2f9f7ffb45e8609cdb4a68104bsenorblanco    // to improve quality and file size (http://skbug.com/3043)
58076033be81b82c44fd5d4fdf2672eb22e505da1f0reed
58176033be81b82c44fd5d4fdf2672eb22e505da1f0reed    // TODO: should we return true if there is a colorfilter?
58276033be81b82c44fd5d4fdf2672eb22e505da1f0reed    return layerPaint.getImageFilter() != NULL;
58376033be81b82c44fd5d4fdf2672eb22e505da1f0reed}
58476033be81b82c44fd5d4fdf2672eb22e505da1f0reed
58576033be81b82c44fd5d4fdf2672eb22e505da1f0reedSkBaseDevice* SkPDFDevice::onCreateDevice(const CreateInfo& cinfo, const SkPaint* layerPaint) {
58600b7e5eb973a1b1e4d1affa74fc0341e8c41e3dahalcanary    if (cinfo.fForImageFilter ||
58700b7e5eb973a1b1e4d1affa74fc0341e8c41e3dahalcanary        (layerPaint && not_supported_for_layers(*layerPaint))) {
58861f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed        return NULL;
589b0e89dcc1d8c1c2f9f7ffb45e8609cdb4a68104bsenorblanco    }
5906987dcaf257dd7c2c8e0014cf7452fde82bcba5bfmalita    SkISize size = SkISize::Make(cinfo.fInfo.width(), cinfo.fInfo.height());
591a1f1ee98a1f6d0770f6243270ca2f0e6c92efabahalcanary    return SkPDFDevice::Create(size, fRasterDpi, fCanon);
592e97f0856a8044866b12527819d14cdfbcdfd96f2bsalomon@google.com}
593e97f0856a8044866b12527819d14cdfbcdfd96f2bsalomon@google.com
594e97f0856a8044866b12527819d14cdfbcdfd96f2bsalomon@google.com
595b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.orgstruct ContentEntry {
596b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org    GraphicStateEntry fState;
597b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org    SkDynamicMemoryWStream fContent;
598e02944075840d672bd1797f3d945ff82d302282fcommit-bot@chromium.org    SkAutoTDelete<ContentEntry> fNext;
5992e6a69b7a23e88e54d8b4a9ee3f4f9e4cc0695a7edisonn@google.com
6002e6a69b7a23e88e54d8b4a9ee3f4f9e4cc0695a7edisonn@google.com    // If the stack is too deep we could get Stack Overflow.
6012e6a69b7a23e88e54d8b4a9ee3f4f9e4cc0695a7edisonn@google.com    // So we manually destruct the object.
6022e6a69b7a23e88e54d8b4a9ee3f4f9e4cc0695a7edisonn@google.com    ~ContentEntry() {
603e02944075840d672bd1797f3d945ff82d302282fcommit-bot@chromium.org        ContentEntry* val = fNext.detach();
6042e6a69b7a23e88e54d8b4a9ee3f4f9e4cc0695a7edisonn@google.com        while (val != NULL) {
605e02944075840d672bd1797f3d945ff82d302282fcommit-bot@chromium.org            ContentEntry* valNext = val->fNext.detach();
6062e6a69b7a23e88e54d8b4a9ee3f4f9e4cc0695a7edisonn@google.com            // When the destructor is called, fNext is NULL and exits.
6072e6a69b7a23e88e54d8b4a9ee3f4f9e4cc0695a7edisonn@google.com            delete val;
6082e6a69b7a23e88e54d8b4a9ee3f4f9e4cc0695a7edisonn@google.com            val = valNext;
6092e6a69b7a23e88e54d8b4a9ee3f4f9e4cc0695a7edisonn@google.com        }
6102e6a69b7a23e88e54d8b4a9ee3f4f9e4cc0695a7edisonn@google.com    }
611b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org};
612b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org
613b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org// A helper class to automatically finish a ContentEntry at the end of a
614b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org// drawing method and maintain the state needed between set up and finish.
61513d14a9dbd2cf0a9654045cc967e92626690631avandebo@chromium.orgclass ScopedContentEntry {
616b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.orgpublic:
61713d14a9dbd2cf0a9654045cc967e92626690631avandebo@chromium.org    ScopedContentEntry(SkPDFDevice* device, const SkDraw& draw,
61813d14a9dbd2cf0a9654045cc967e92626690631avandebo@chromium.org                       const SkPaint& paint, bool hasText = false)
619b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org        : fDevice(device),
620b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org          fContentEntry(NULL),
6213b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org          fXfermode(SkXfermode::kSrcOver_Mode),
6223b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org          fDstFormXObject(NULL) {
623b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org        init(draw.fClipStack, *draw.fClip, *draw.fMatrix, paint, hasText);
624b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org    }
62513d14a9dbd2cf0a9654045cc967e92626690631avandebo@chromium.org    ScopedContentEntry(SkPDFDevice* device, const SkClipStack* clipStack,
62613d14a9dbd2cf0a9654045cc967e92626690631avandebo@chromium.org                       const SkRegion& clipRegion, const SkMatrix& matrix,
62713d14a9dbd2cf0a9654045cc967e92626690631avandebo@chromium.org                       const SkPaint& paint, bool hasText = false)
628b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org        : fDevice(device),
629b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org          fContentEntry(NULL),
6303b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org          fXfermode(SkXfermode::kSrcOver_Mode),
6313b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org          fDstFormXObject(NULL) {
632b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org        init(clipStack, clipRegion, matrix, paint, hasText);
633b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org    }
634b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org
63513d14a9dbd2cf0a9654045cc967e92626690631avandebo@chromium.org    ~ScopedContentEntry() {
636b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org        if (fContentEntry) {
6373b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org            SkPath* shape = &fShape;
6383b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org            if (shape->isEmpty()) {
6393b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org                shape = NULL;
6403b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org            }
6413b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org            fDevice->finishContentEntry(fXfermode, fDstFormXObject, shape);
642b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org        }
643fc641d09e5a1a9f7fae369ae06a8b96089faf57breed@google.com        SkSafeUnref(fDstFormXObject);
644b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org    }
645b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org
646b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org    ContentEntry* entry() { return fContentEntry; }
6473b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org
6483b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org    /* Returns true when we explicitly need the shape of the drawing. */
6493b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org    bool needShape() {
6503b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org        switch (fXfermode) {
6513b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org            case SkXfermode::kClear_Mode:
6523b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org            case SkXfermode::kSrc_Mode:
6533b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org            case SkXfermode::kSrcIn_Mode:
6543b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org            case SkXfermode::kSrcOut_Mode:
6553b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org            case SkXfermode::kDstIn_Mode:
6563b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org            case SkXfermode::kDstOut_Mode:
6573b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org            case SkXfermode::kSrcATop_Mode:
6583b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org            case SkXfermode::kDstATop_Mode:
6593b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org            case SkXfermode::kModulate_Mode:
6603b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org                return true;
6613b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org            default:
6623b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org                return false;
6633b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org        }
6643b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org    }
6653b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org
6663b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org    /* Returns true unless we only need the shape of the drawing. */
6673b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org    bool needSource() {
6683b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org        if (fXfermode == SkXfermode::kClear_Mode) {
6693b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org            return false;
6703b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org        }
6713b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org        return true;
6723b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org    }
6733b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org
6743b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org    /* If the shape is different than the alpha component of the content, then
6753b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org     * setShape should be called with the shape.  In particular, images and
6763b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org     * devices have rectangular shape.
6773b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org     */
6783b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org    void setShape(const SkPath& shape) {
6793b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org        fShape = shape;
6803b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org    }
6813b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org
682b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.orgprivate:
683b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org    SkPDFDevice* fDevice;
684b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org    ContentEntry* fContentEntry;
685b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org    SkXfermode::Mode fXfermode;
686fc641d09e5a1a9f7fae369ae06a8b96089faf57breed@google.com    SkPDFFormXObject* fDstFormXObject;
6873b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org    SkPath fShape;
688b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org
689b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org    void init(const SkClipStack* clipStack, const SkRegion& clipRegion,
690b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org              const SkMatrix& matrix, const SkPaint& paint, bool hasText) {
69183d8eda890def8c119794deeec6244c67da83ac8edisonn@google.com        // Shape has to be flatten before we get here.
69283d8eda890def8c119794deeec6244c67da83ac8edisonn@google.com        if (matrix.hasPerspective()) {
69383d8eda890def8c119794deeec6244c67da83ac8edisonn@google.com            NOT_IMPLEMENTED(!matrix.hasPerspective(), false);
694dc37e20647b92528ba9e6a4074cb0f8cc7fbe6b5vandebo@chromium.org            return;
695dc37e20647b92528ba9e6a4074cb0f8cc7fbe6b5vandebo@chromium.org        }
696b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org        if (paint.getXfermode()) {
697b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org            paint.getXfermode()->asMode(&fXfermode);
698b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org        }
699b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org        fContentEntry = fDevice->setUpContentEntry(clipStack, clipRegion,
700b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org                                                   matrix, paint, hasText,
701b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org                                                   &fDstFormXObject);
702b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org    }
703b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org};
704b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org
7059b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org////////////////////////////////////////////////////////////////////////////////
7069b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org
707a1f1ee98a1f6d0770f6243270ca2f0e6c92efabahalcanarySkPDFDevice::SkPDFDevice(SkISize pageSize,
708a1f1ee98a1f6d0770f6243270ca2f0e6c92efabahalcanary                         SkScalar rasterDpi,
709a1f1ee98a1f6d0770f6243270ca2f0e6c92efabahalcanary                         SkPDFCanon* canon,
710a1f1ee98a1f6d0770f6243270ca2f0e6c92efabahalcanary                         bool flip)
71189443aba5bfa2b040dc9fd24938b7d0b3decd737reed    : fPageSize(pageSize)
712a1f1ee98a1f6d0770f6243270ca2f0e6c92efabahalcanary    , fContentSize(pageSize)
713a1f1ee98a1f6d0770f6243270ca2f0e6c92efabahalcanary    , fExistingClipRegion(SkIRect::MakeSize(pageSize))
714a1f1ee98a1f6d0770f6243270ca2f0e6c92efabahalcanary    , fAnnotations(NULL)
71589443aba5bfa2b040dc9fd24938b7d0b3decd737reed    , fLastContentEntry(NULL)
71689443aba5bfa2b040dc9fd24938b7d0b3decd737reed    , fLastMarginContentEntry(NULL)
717a1f1ee98a1f6d0770f6243270ca2f0e6c92efabahalcanary    , fDrawingArea(kContent_DrawingArea)
71889443aba5bfa2b040dc9fd24938b7d0b3decd737reed    , fClipStack(NULL)
719a1f1ee98a1f6d0770f6243270ca2f0e6c92efabahalcanary    , fFontGlyphUsage(SkNEW(SkPDFGlyphSetMap))
720a1f1ee98a1f6d0770f6243270ca2f0e6c92efabahalcanary    , fRasterDpi(rasterDpi)
721a1f1ee98a1f6d0770f6243270ca2f0e6c92efabahalcanary    , fCanon(canon) {
722a1f1ee98a1f6d0770f6243270ca2f0e6c92efabahalcanary    SkASSERT(pageSize.width() > 0);
723a1f1ee98a1f6d0770f6243270ca2f0e6c92efabahalcanary    SkASSERT(pageSize.height() > 0);
724a1f1ee98a1f6d0770f6243270ca2f0e6c92efabahalcanary    fLegacyBitmap.setInfo(
725a1f1ee98a1f6d0770f6243270ca2f0e6c92efabahalcanary            SkImageInfo::MakeUnknown(pageSize.width(), pageSize.height()));
726a1f1ee98a1f6d0770f6243270ca2f0e6c92efabahalcanary    if (flip) {
727a1f1ee98a1f6d0770f6243270ca2f0e6c92efabahalcanary        // Skia generally uses the top left as the origin but PDF
728a1f1ee98a1f6d0770f6243270ca2f0e6c92efabahalcanary        // natively has the origin at the bottom left. This matrix
729a1f1ee98a1f6d0770f6243270ca2f0e6c92efabahalcanary        // corrects for that.  But that only needs to be done once, we
730a1f1ee98a1f6d0770f6243270ca2f0e6c92efabahalcanary        // don't do it when layering.
731a1f1ee98a1f6d0770f6243270ca2f0e6c92efabahalcanary        fInitialTransform.setTranslate(0, SkIntToScalar(pageSize.fHeight));
732a1f1ee98a1f6d0770f6243270ca2f0e6c92efabahalcanary        fInitialTransform.preScale(SK_Scalar1, -SK_Scalar1);
733a1f1ee98a1f6d0770f6243270ca2f0e6c92efabahalcanary    } else {
734a1f1ee98a1f6d0770f6243270ca2f0e6c92efabahalcanary        fInitialTransform.setIdentity();
735a1f1ee98a1f6d0770f6243270ca2f0e6c92efabahalcanary    }
73677bcaa324a574584331322d98768582d9232f7fcvandebo@chromium.org}
73777bcaa324a574584331322d98768582d9232f7fcvandebo@chromium.org
73877bcaa324a574584331322d98768582d9232f7fcvandebo@chromium.orgSkPDFDevice::~SkPDFDevice() {
7399859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org    this->cleanUp(true);
74077bcaa324a574584331322d98768582d9232f7fcvandebo@chromium.org}
74177bcaa324a574584331322d98768582d9232f7fcvandebo@chromium.org
74277bcaa324a574584331322d98768582d9232f7fcvandebo@chromium.orgvoid SkPDFDevice::init() {
7432a006c112743e07ce258ca223631fc19233f5ddcreed@google.com    fAnnotations = NULL;
744e02944075840d672bd1797f3d945ff82d302282fcommit-bot@chromium.org    fContentEntries.free();
745b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org    fLastContentEntry = NULL;
746e02944075840d672bd1797f3d945ff82d302282fcommit-bot@chromium.org    fMarginContentEntries.free();
7478dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org    fLastMarginContentEntry = NULL;
7489859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org    fDrawingArea = kContent_DrawingArea;
749e02944075840d672bd1797f3d945ff82d302282fcommit-bot@chromium.org    if (fFontGlyphUsage.get() == NULL) {
750792c80f5a7b66e75d42664ccb298f31962c6654chalcanary        fFontGlyphUsage.reset(SkNEW(SkPDFGlyphSetMap));
7519859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org    }
7529b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org}
7539b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org
7549859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.orgvoid SkPDFDevice::cleanUp(bool clearFontUsage) {
7559b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org    fGraphicStateResources.unrefAll();
7569b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org    fXObjectResources.unrefAll();
75728be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org    fFontResources.unrefAll();
758da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org    fShaderResources.unrefAll();
7592a006c112743e07ce258ca223631fc19233f5ddcreed@google.com    SkSafeUnref(fAnnotations);
760b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com    fNamedDestinations.deleteAll();
7612a006c112743e07ce258ca223631fc19233f5ddcreed@google.com
7629859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org    if (clearFontUsage) {
7639859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org        fFontGlyphUsage->reset();
7649859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org    }
7659b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org}
7669b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org
7679b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.orgvoid SkPDFDevice::drawPaint(const SkDraw& d, const SkPaint& paint) {
7689b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org    SkPaint newPaint = paint;
769c375b0b5c5c03d381111bf7bff12507d5ed24769senorblanco    replace_srcmode_on_opaque_paint(&newPaint);
770c375b0b5c5c03d381111bf7bff12507d5ed24769senorblanco
7719b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org    newPaint.setStyle(SkPaint::kFill_Style);
77213d14a9dbd2cf0a9654045cc967e92626690631avandebo@chromium.org    ScopedContentEntry content(this, d, newPaint);
773b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org    internalDrawPaint(newPaint, content.entry());
77477bcaa324a574584331322d98768582d9232f7fcvandebo@chromium.org}
77577bcaa324a574584331322d98768582d9232f7fcvandebo@chromium.org
776b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.orgvoid SkPDFDevice::internalDrawPaint(const SkPaint& paint,
777b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org                                    ContentEntry* contentEntry) {
778b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org    if (!contentEntry) {
779b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org        return;
780b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org    }
78177bcaa324a574584331322d98768582d9232f7fcvandebo@chromium.org    SkRect bbox = SkRect::MakeWH(SkIntToScalar(this->width()),
78277bcaa324a574584331322d98768582d9232f7fcvandebo@chromium.org                                 SkIntToScalar(this->height()));
78377bcaa324a574584331322d98768582d9232f7fcvandebo@chromium.org    SkMatrix inverse;
784d2cfa7422e2b0928970b3b0fa1abe1d73113fc1dcommit-bot@chromium.org    if (!contentEntry->fState.fMatrix.invert(&inverse)) {
785386dfc049baa400c13e4e98727d4c04d0242b7b8vandebo@chromium.org        return;
786b054990307b7338e599a12d9af10eb2058b94051vandebo@chromium.org    }
78777bcaa324a574584331322d98768582d9232f7fcvandebo@chromium.org    inverse.mapRect(&bbox);
78877bcaa324a574584331322d98768582d9232f7fcvandebo@chromium.org
789b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org    SkPDFUtils::AppendRectangle(bbox, &contentEntry->fContent);
7909fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    SkPDFUtils::PaintPath(paint.getStyle(), SkPath::kWinding_FillType,
791b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org                          &contentEntry->fContent);
7929b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org}
7939b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org
794c375b0b5c5c03d381111bf7bff12507d5ed24769senorblancovoid SkPDFDevice::drawPoints(const SkDraw& d,
795c375b0b5c5c03d381111bf7bff12507d5ed24769senorblanco                             SkCanvas::PointMode mode,
796c375b0b5c5c03d381111bf7bff12507d5ed24769senorblanco                             size_t count,
797c375b0b5c5c03d381111bf7bff12507d5ed24769senorblanco                             const SkPoint* points,
798c375b0b5c5c03d381111bf7bff12507d5ed24769senorblanco                             const SkPaint& srcPaint) {
799c375b0b5c5c03d381111bf7bff12507d5ed24769senorblanco    SkPaint passedPaint = srcPaint;
800c375b0b5c5c03d381111bf7bff12507d5ed24769senorblanco    replace_srcmode_on_opaque_paint(&passedPaint);
801c375b0b5c5c03d381111bf7bff12507d5ed24769senorblanco
80225adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org    if (count == 0) {
80325adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org        return;
80425adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org    }
80525adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org
806b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com    if (handlePointAnnotation(points, count, *d.fMatrix, passedPaint)) {
807b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com        return;
808b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com    }
809b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com
810ff3903202e5bce39016bac896ba6a417dc707d52vandebo@chromium.org    // SkDraw::drawPoints converts to multiple calls to fDevice->drawPath.
811ff3903202e5bce39016bac896ba6a417dc707d52vandebo@chromium.org    // We only use this when there's a path effect because of the overhead
812ff3903202e5bce39016bac896ba6a417dc707d52vandebo@chromium.org    // of multiple calls to setUpContentEntry it causes.
813ff3903202e5bce39016bac896ba6a417dc707d52vandebo@chromium.org    if (passedPaint.getPathEffect()) {
814ff3903202e5bce39016bac896ba6a417dc707d52vandebo@chromium.org        if (d.fClip->isEmpty()) {
815ff3903202e5bce39016bac896ba6a417dc707d52vandebo@chromium.org            return;
816ff3903202e5bce39016bac896ba6a417dc707d52vandebo@chromium.org        }
817ff3903202e5bce39016bac896ba6a417dc707d52vandebo@chromium.org        SkDraw pointDraw(d);
818ff3903202e5bce39016bac896ba6a417dc707d52vandebo@chromium.org        pointDraw.fDevice = this;
819ff3903202e5bce39016bac896ba6a417dc707d52vandebo@chromium.org        pointDraw.drawPoints(mode, count, points, passedPaint, true);
820ff3903202e5bce39016bac896ba6a417dc707d52vandebo@chromium.org        return;
821ff3903202e5bce39016bac896ba6a417dc707d52vandebo@chromium.org    }
822ff3903202e5bce39016bac896ba6a417dc707d52vandebo@chromium.org
82325adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org    const SkPaint* paint = &passedPaint;
82425adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org    SkPaint modifiedPaint;
82525adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org
82625adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org    if (mode == SkCanvas::kPoints_PointMode &&
82725adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org            paint->getStrokeCap() != SkPaint::kRound_Cap) {
82825adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org        modifiedPaint = *paint;
82925adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org        paint = &modifiedPaint;
83025adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org        if (paint->getStrokeWidth()) {
83125adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org            // PDF won't draw a single point with square/butt caps because the
83225adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org            // orientation is ambiguous.  Draw a rectangle instead.
83325adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org            modifiedPaint.setStyle(SkPaint::kFill_Style);
83425adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org            SkScalar strokeWidth = paint->getStrokeWidth();
83525adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org            SkScalar halfStroke = SkScalarHalf(strokeWidth);
83625adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org            for (size_t i = 0; i < count; i++) {
83725adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org                SkRect r = SkRect::MakeXYWH(points[i].fX, points[i].fY, 0, 0);
83825adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org                r.inset(-halfStroke, -halfStroke);
83925adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org                drawRect(d, r, modifiedPaint);
84025adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org            }
84125adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org            return;
84225adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org        } else {
84325adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org            modifiedPaint.setStrokeCap(SkPaint::kRound_Cap);
84425adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org        }
84525adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org    }
84625adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org
84713d14a9dbd2cf0a9654045cc967e92626690631avandebo@chromium.org    ScopedContentEntry content(this, d, *paint);
848b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org    if (!content.entry()) {
8499b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org        return;
850fb0b0edd86d71bb423fa921eaac1e2071602115cvandebo@chromium.org    }
8519b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org
8529b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org    switch (mode) {
8539b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org        case SkCanvas::kPolygon_PointMode:
8549fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org            SkPDFUtils::MoveTo(points[0].fX, points[0].fY,
855b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org                               &content.entry()->fContent);
8569db86bb9cd1b77be0afc504ccc07026e4282d7e7ctguil@chromium.org            for (size_t i = 1; i < count; i++) {
8579fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org                SkPDFUtils::AppendLine(points[i].fX, points[i].fY,
858b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org                                       &content.entry()->fContent);
8599db86bb9cd1b77be0afc504ccc07026e4282d7e7ctguil@chromium.org            }
860b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org            SkPDFUtils::StrokePath(&content.entry()->fContent);
8619b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org            break;
8629b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org        case SkCanvas::kLines_PointMode:
8639b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org            for (size_t i = 0; i < count/2; i++) {
8649db86bb9cd1b77be0afc504ccc07026e4282d7e7ctguil@chromium.org                SkPDFUtils::MoveTo(points[i * 2].fX, points[i * 2].fY,
865b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org                                   &content.entry()->fContent);
8669db86bb9cd1b77be0afc504ccc07026e4282d7e7ctguil@chromium.org                SkPDFUtils::AppendLine(points[i * 2 + 1].fX,
8679fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org                                       points[i * 2 + 1].fY,
868b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org                                       &content.entry()->fContent);
869b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org                SkPDFUtils::StrokePath(&content.entry()->fContent);
8709b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org            }
8719b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org            break;
8729b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org        case SkCanvas::kPoints_PointMode:
87325adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org            SkASSERT(paint->getStrokeCap() == SkPaint::kRound_Cap);
87425adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org            for (size_t i = 0; i < count; i++) {
87525adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org                SkPDFUtils::MoveTo(points[i].fX, points[i].fY,
876b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org                                   &content.entry()->fContent);
877b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org                SkPDFUtils::ClosePath(&content.entry()->fContent);
878b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org                SkPDFUtils::StrokePath(&content.entry()->fContent);
8799b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org            }
8809b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org            break;
8819b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org        default:
8829b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org            SkASSERT(false);
8839b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org    }
8849b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org}
8859b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org
886c375b0b5c5c03d381111bf7bff12507d5ed24769senorblancovoid SkPDFDevice::drawRect(const SkDraw& d,
887c375b0b5c5c03d381111bf7bff12507d5ed24769senorblanco                           const SkRect& rect,
888c375b0b5c5c03d381111bf7bff12507d5ed24769senorblanco                           const SkPaint& srcPaint) {
889c375b0b5c5c03d381111bf7bff12507d5ed24769senorblanco    SkPaint paint = srcPaint;
890c375b0b5c5c03d381111bf7bff12507d5ed24769senorblanco    replace_srcmode_on_opaque_paint(&paint);
891969fd6afc45df247377c35d9a273dce752af04aacommit-bot@chromium.org    SkRect r = rect;
892969fd6afc45df247377c35d9a273dce752af04aacommit-bot@chromium.org    r.sort();
893969fd6afc45df247377c35d9a273dce752af04aacommit-bot@chromium.org
8949b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org    if (paint.getPathEffect()) {
89525adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org        if (d.fClip->isEmpty()) {
89625adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org            return;
89725adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org        }
8989b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org        SkPath path;
8999b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org        path.addRect(r);
900ff3903202e5bce39016bac896ba6a417dc707d52vandebo@chromium.org        drawPath(d, path, paint, NULL, true);
9019b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org        return;
9029b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org    }
903b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org
904b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com    if (handleRectAnnotation(r, *d.fMatrix, paint)) {
905238be8c7e5de5a83517440a3db7f7965b47fb010vandebo@chromium.org        return;
906238be8c7e5de5a83517440a3db7f7965b47fb010vandebo@chromium.org    }
907238be8c7e5de5a83517440a3db7f7965b47fb010vandebo@chromium.org
90813d14a9dbd2cf0a9654045cc967e92626690631avandebo@chromium.org    ScopedContentEntry content(this, d, paint);
909b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org    if (!content.entry()) {
91025adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org        return;
91125adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org    }
912b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org    SkPDFUtils::AppendRectangle(r, &content.entry()->fContent);
9139db86bb9cd1b77be0afc504ccc07026e4282d7e7ctguil@chromium.org    SkPDFUtils::PaintPath(paint.getStyle(), SkPath::kWinding_FillType,
914b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org                          &content.entry()->fContent);
9159b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org}
9169b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org
917c375b0b5c5c03d381111bf7bff12507d5ed24769senorblancovoid SkPDFDevice::drawRRect(const SkDraw& draw,
918c375b0b5c5c03d381111bf7bff12507d5ed24769senorblanco                            const SkRRect& rrect,
919c375b0b5c5c03d381111bf7bff12507d5ed24769senorblanco                            const SkPaint& srcPaint) {
920c375b0b5c5c03d381111bf7bff12507d5ed24769senorblanco    SkPaint paint = srcPaint;
921c375b0b5c5c03d381111bf7bff12507d5ed24769senorblanco    replace_srcmode_on_opaque_paint(&paint);
922a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com    SkPath  path;
923a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com    path.addRRect(rrect);
924a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com    this->drawPath(draw, path, paint, NULL, true);
925a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com}
926a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com
927c375b0b5c5c03d381111bf7bff12507d5ed24769senorblancovoid SkPDFDevice::drawOval(const SkDraw& draw,
928c375b0b5c5c03d381111bf7bff12507d5ed24769senorblanco                           const SkRect& oval,
929c375b0b5c5c03d381111bf7bff12507d5ed24769senorblanco                           const SkPaint& srcPaint) {
930c375b0b5c5c03d381111bf7bff12507d5ed24769senorblanco    SkPaint paint = srcPaint;
931c375b0b5c5c03d381111bf7bff12507d5ed24769senorblanco    replace_srcmode_on_opaque_paint(&paint);
93289443aba5bfa2b040dc9fd24938b7d0b3decd737reed    SkPath  path;
93389443aba5bfa2b040dc9fd24938b7d0b3decd737reed    path.addOval(oval);
93489443aba5bfa2b040dc9fd24938b7d0b3decd737reed    this->drawPath(draw, path, paint, NULL, true);
93589443aba5bfa2b040dc9fd24938b7d0b3decd737reed}
93689443aba5bfa2b040dc9fd24938b7d0b3decd737reed
937c375b0b5c5c03d381111bf7bff12507d5ed24769senorblancovoid SkPDFDevice::drawPath(const SkDraw& d,
938c375b0b5c5c03d381111bf7bff12507d5ed24769senorblanco                           const SkPath& origPath,
939c375b0b5c5c03d381111bf7bff12507d5ed24769senorblanco                           const SkPaint& srcPaint,
940c375b0b5c5c03d381111bf7bff12507d5ed24769senorblanco                           const SkMatrix* prePathMatrix,
94102cc5aa736086320649d8a932515691ae18a0dd5vandebo@chromium.org                           bool pathIsMutable) {
942c375b0b5c5c03d381111bf7bff12507d5ed24769senorblanco    SkPaint paint = srcPaint;
943c375b0b5c5c03d381111bf7bff12507d5ed24769senorblanco    replace_srcmode_on_opaque_paint(&paint);
944ff3903202e5bce39016bac896ba6a417dc707d52vandebo@chromium.org    SkPath modifiedPath;
945ff3903202e5bce39016bac896ba6a417dc707d52vandebo@chromium.org    SkPath* pathPtr = const_cast<SkPath*>(&origPath);
946ff3903202e5bce39016bac896ba6a417dc707d52vandebo@chromium.org
947ff3903202e5bce39016bac896ba6a417dc707d52vandebo@chromium.org    SkMatrix matrix = *d.fMatrix;
948ff3903202e5bce39016bac896ba6a417dc707d52vandebo@chromium.org    if (prePathMatrix) {
949ff3903202e5bce39016bac896ba6a417dc707d52vandebo@chromium.org        if (paint.getPathEffect() || paint.getStyle() != SkPaint::kFill_Style) {
950ff3903202e5bce39016bac896ba6a417dc707d52vandebo@chromium.org            if (!pathIsMutable) {
951ff3903202e5bce39016bac896ba6a417dc707d52vandebo@chromium.org                pathPtr = &modifiedPath;
952ff3903202e5bce39016bac896ba6a417dc707d52vandebo@chromium.org                pathIsMutable = true;
953ff3903202e5bce39016bac896ba6a417dc707d52vandebo@chromium.org            }
954ff3903202e5bce39016bac896ba6a417dc707d52vandebo@chromium.org            origPath.transform(*prePathMatrix, pathPtr);
955ff3903202e5bce39016bac896ba6a417dc707d52vandebo@chromium.org        } else {
95692362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org            matrix.preConcat(*prePathMatrix);
957ff3903202e5bce39016bac896ba6a417dc707d52vandebo@chromium.org        }
958ff3903202e5bce39016bac896ba6a417dc707d52vandebo@chromium.org    }
95902cc5aa736086320649d8a932515691ae18a0dd5vandebo@chromium.org
9607d71f7f655cab6b6194f6c765ca33c1a6d512f5evandebo@chromium.org    if (paint.getPathEffect()) {
96125adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org        if (d.fClip->isEmpty()) {
96225adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org            return;
96325adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org        }
964ff3903202e5bce39016bac896ba6a417dc707d52vandebo@chromium.org        if (!pathIsMutable) {
965ff3903202e5bce39016bac896ba6a417dc707d52vandebo@chromium.org            pathPtr = &modifiedPath;
966ff3903202e5bce39016bac896ba6a417dc707d52vandebo@chromium.org            pathIsMutable = true;
967ff3903202e5bce39016bac896ba6a417dc707d52vandebo@chromium.org        }
968ff3903202e5bce39016bac896ba6a417dc707d52vandebo@chromium.org        bool fill = paint.getFillPath(origPath, pathPtr);
9697d71f7f655cab6b6194f6c765ca33c1a6d512f5evandebo@chromium.org
9707e2ff7cf7da604b29378978ef5d4655499485368vandebo@chromium.org        SkPaint noEffectPaint(paint);
971ff3903202e5bce39016bac896ba6a417dc707d52vandebo@chromium.org        noEffectPaint.setPathEffect(NULL);
972ff3903202e5bce39016bac896ba6a417dc707d52vandebo@chromium.org        if (fill) {
973ff3903202e5bce39016bac896ba6a417dc707d52vandebo@chromium.org            noEffectPaint.setStyle(SkPaint::kFill_Style);
974ff3903202e5bce39016bac896ba6a417dc707d52vandebo@chromium.org        } else {
975ff3903202e5bce39016bac896ba6a417dc707d52vandebo@chromium.org            noEffectPaint.setStyle(SkPaint::kStroke_Style);
976ff3903202e5bce39016bac896ba6a417dc707d52vandebo@chromium.org            noEffectPaint.setStrokeWidth(0);
977ff3903202e5bce39016bac896ba6a417dc707d52vandebo@chromium.org        }
978ff3903202e5bce39016bac896ba6a417dc707d52vandebo@chromium.org        drawPath(d, *pathPtr, noEffectPaint, NULL, true);
9797d71f7f655cab6b6194f6c765ca33c1a6d512f5evandebo@chromium.org        return;
9807d71f7f655cab6b6194f6c765ca33c1a6d512f5evandebo@chromium.org    }
981ff3903202e5bce39016bac896ba6a417dc707d52vandebo@chromium.org
982a9ebd161a7c08515f0c4bd885e61c4b52688ececedisonn@google.com    if (handleInversePath(d, origPath, paint, pathIsMutable, prePathMatrix)) {
98392ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org        return;
98492ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org    }
98592ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org
986a9ebd161a7c08515f0c4bd885e61c4b52688ececedisonn@google.com    if (handleRectAnnotation(pathPtr->getBounds(), matrix, paint)) {
987238be8c7e5de5a83517440a3db7f7965b47fb010vandebo@chromium.org        return;
988238be8c7e5de5a83517440a3db7f7965b47fb010vandebo@chromium.org    }
989238be8c7e5de5a83517440a3db7f7965b47fb010vandebo@chromium.org
990a9ebd161a7c08515f0c4bd885e61c4b52688ececedisonn@google.com    ScopedContentEntry content(this, d.fClipStack, *d.fClip, matrix, paint);
991b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org    if (!content.entry()) {
99225adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org        return;
99325adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org    }
994683001ce0de70c859ea5e5353245b18cadbefc45vandebo@chromium.org    SkPDFUtils::EmitPath(*pathPtr, paint.getStyle(),
995683001ce0de70c859ea5e5353245b18cadbefc45vandebo@chromium.org                         &content.entry()->fContent);
996ff3903202e5bce39016bac896ba6a417dc707d52vandebo@chromium.org    SkPDFUtils::PaintPath(paint.getStyle(), pathPtr->getFillType(),
997b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org                          &content.entry()->fContent);
9989b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org}
9999b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org
10002ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.comvoid SkPDFDevice::drawBitmapRect(const SkDraw& draw, const SkBitmap& bitmap,
10012ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com                                 const SkRect* src, const SkRect& dst,
1002c375b0b5c5c03d381111bf7bff12507d5ed24769senorblanco                                 const SkPaint& srcPaint,
1003eed779d866e1e239bfb9ebc6a225b7345a41adf9commit-bot@chromium.org                                 SkCanvas::DrawBitmapRectFlags flags) {
1004c375b0b5c5c03d381111bf7bff12507d5ed24769senorblanco    SkPaint paint = srcPaint;
1005c375b0b5c5c03d381111bf7bff12507d5ed24769senorblanco    if (bitmap.isOpaque()) {
1006c375b0b5c5c03d381111bf7bff12507d5ed24769senorblanco        replace_srcmode_on_opaque_paint(&paint);
1007c375b0b5c5c03d381111bf7bff12507d5ed24769senorblanco    }
1008c375b0b5c5c03d381111bf7bff12507d5ed24769senorblanco
1009eed779d866e1e239bfb9ebc6a225b7345a41adf9commit-bot@chromium.org    // TODO: this code path must be updated to respect the flags parameter
10102ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com    SkMatrix    matrix;
10112ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com    SkRect      bitmapBounds, tmpSrc, tmpDst;
10122ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com    SkBitmap    tmpBitmap;
10132ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com
10142ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com    bitmapBounds.isetWH(bitmap.width(), bitmap.height());
10152ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com
10162ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com    // Compute matrix from the two rectangles
10172ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com    if (src) {
10182ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com        tmpSrc = *src;
10192ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com    } else {
10202ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com        tmpSrc = bitmapBounds;
10212ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com    }
10222ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com    matrix.setRectToRect(tmpSrc, dst, SkMatrix::kFill_ScaleToFit);
10232ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com
10242ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com    const SkBitmap* bitmapPtr = &bitmap;
10252ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com
10262ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com    // clip the tmpSrc to the bounds of the bitmap, and recompute dstRect if
10272ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com    // needed (if the src was clipped). No check needed if src==null.
10282ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com    if (src) {
10292ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com        if (!bitmapBounds.contains(*src)) {
10302ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com            if (!tmpSrc.intersect(bitmapBounds)) {
10312ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com                return; // nothing to draw
10322ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com            }
10332ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com            // recompute dst, based on the smaller tmpSrc
10342ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com            matrix.mapRect(&tmpDst, tmpSrc);
10352ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com        }
10362ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com
10372ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com        // since we may need to clamp to the borders of the src rect within
10382ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com        // the bitmap, we extract a subset.
10392ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com        // TODO: make sure this is handled in drawBitmap and remove from here.
10402ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com        SkIRect srcIR;
10412ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com        tmpSrc.roundOut(&srcIR);
10422ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com        if (!bitmap.extractSubset(&tmpBitmap, srcIR)) {
10432ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com            return;
10442ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com        }
10452ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com        bitmapPtr = &tmpBitmap;
10462ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com
10472ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com        // Since we did an extract, we need to adjust the matrix accordingly
10482ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com        SkScalar dx = 0, dy = 0;
10492ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com        if (srcIR.fLeft > 0) {
10502ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com            dx = SkIntToScalar(srcIR.fLeft);
10512ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com        }
10522ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com        if (srcIR.fTop > 0) {
10532ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com            dy = SkIntToScalar(srcIR.fTop);
10542ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com        }
10552ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com        if (dx || dy) {
10562ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com            matrix.preTranslate(dx, dy);
10572ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com        }
10582ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com    }
10599bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com    this->drawBitmap(draw, *bitmapPtr, matrix, paint);
10602ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com}
10612ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com
1062fb0b0edd86d71bb423fa921eaac1e2071602115cvandebo@chromium.orgvoid SkPDFDevice::drawBitmap(const SkDraw& d, const SkBitmap& bitmap,
1063c375b0b5c5c03d381111bf7bff12507d5ed24769senorblanco                             const SkMatrix& matrix, const SkPaint& srcPaint) {
1064c375b0b5c5c03d381111bf7bff12507d5ed24769senorblanco    SkPaint paint = srcPaint;
1065c375b0b5c5c03d381111bf7bff12507d5ed24769senorblanco    if (bitmap.isOpaque()) {
1066c375b0b5c5c03d381111bf7bff12507d5ed24769senorblanco        replace_srcmode_on_opaque_paint(&paint);
1067c375b0b5c5c03d381111bf7bff12507d5ed24769senorblanco    }
1068c375b0b5c5c03d381111bf7bff12507d5ed24769senorblanco
1069fb0b0edd86d71bb423fa921eaac1e2071602115cvandebo@chromium.org    if (d.fClip->isEmpty()) {
1070fb0b0edd86d71bb423fa921eaac1e2071602115cvandebo@chromium.org        return;
1071fb0b0edd86d71bb423fa921eaac1e2071602115cvandebo@chromium.org    }
1072fb0b0edd86d71bb423fa921eaac1e2071602115cvandebo@chromium.org
10737e2ff7cf7da604b29378978ef5d4655499485368vandebo@chromium.org    SkMatrix transform = matrix;
10749fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    transform.postConcat(*d.fMatrix);
10753b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org    this->internalDrawBitmap(transform, d.fClipStack, *d.fClip, bitmap, NULL,
10763b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org                             paint);
10779b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org}
10789b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org
1079fb0b0edd86d71bb423fa921eaac1e2071602115cvandebo@chromium.orgvoid SkPDFDevice::drawSprite(const SkDraw& d, const SkBitmap& bitmap,
1080c375b0b5c5c03d381111bf7bff12507d5ed24769senorblanco                             int x, int y, const SkPaint& srcPaint) {
1081c375b0b5c5c03d381111bf7bff12507d5ed24769senorblanco    SkPaint paint = srcPaint;
1082c375b0b5c5c03d381111bf7bff12507d5ed24769senorblanco    if (bitmap.isOpaque()) {
1083c375b0b5c5c03d381111bf7bff12507d5ed24769senorblanco        replace_srcmode_on_opaque_paint(&paint);
1084c375b0b5c5c03d381111bf7bff12507d5ed24769senorblanco    }
1085c375b0b5c5c03d381111bf7bff12507d5ed24769senorblanco
1086fb0b0edd86d71bb423fa921eaac1e2071602115cvandebo@chromium.org    if (d.fClip->isEmpty()) {
1087fb0b0edd86d71bb423fa921eaac1e2071602115cvandebo@chromium.org        return;
1088fb0b0edd86d71bb423fa921eaac1e2071602115cvandebo@chromium.org    }
1089fb0b0edd86d71bb423fa921eaac1e2071602115cvandebo@chromium.org
10907e2ff7cf7da604b29378978ef5d4655499485368vandebo@chromium.org    SkMatrix matrix;
1091a6d59f60aab59fb6556841b063ead5d49b46ba8dreed@google.com    matrix.setTranslate(SkIntToScalar(x), SkIntToScalar(y));
10923b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org    this->internalDrawBitmap(matrix, d.fClipStack, *d.fClip, bitmap, NULL,
10933b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org                             paint);
10949b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org}
10959b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org
1096bb264b775004be3df72f0bb5ee613761a328a6c3halcanary//  Create a PDF string. Maximum length (in bytes) is 65,535.
1097bb264b775004be3df72f0bb5ee613761a328a6c3halcanary//  @param input     A string value.
1098bb264b775004be3df72f0bb5ee613761a328a6c3halcanary//  @param len       The length of the input array.
1099bb264b775004be3df72f0bb5ee613761a328a6c3halcanary//  @param wideChars True iff the upper byte in each uint16_t is
1100bb264b775004be3df72f0bb5ee613761a328a6c3halcanary//                   significant and should be encoded and not
1101bb264b775004be3df72f0bb5ee613761a328a6c3halcanary//                   discarded.  If true, the upper byte is encoded
1102bb264b775004be3df72f0bb5ee613761a328a6c3halcanary//                   first.  Otherwise, we assert the upper byte is
1103bb264b775004be3df72f0bb5ee613761a328a6c3halcanary//                   zero.
1104bb264b775004be3df72f0bb5ee613761a328a6c3halcanarystatic SkString format_wide_string(const uint16_t* input,
1105bb264b775004be3df72f0bb5ee613761a328a6c3halcanary                                   size_t len,
1106bb264b775004be3df72f0bb5ee613761a328a6c3halcanary                                   bool wideChars) {
1107bb264b775004be3df72f0bb5ee613761a328a6c3halcanary    if (wideChars) {
1108bb264b775004be3df72f0bb5ee613761a328a6c3halcanary        SkASSERT(2 * len < 65535);
1109bb264b775004be3df72f0bb5ee613761a328a6c3halcanary        static const char gHex[] = "0123456789ABCDEF";
1110bb264b775004be3df72f0bb5ee613761a328a6c3halcanary        SkString result(4 * len + 2);
1111bb264b775004be3df72f0bb5ee613761a328a6c3halcanary        result[0] = '<';
1112bb264b775004be3df72f0bb5ee613761a328a6c3halcanary        for (size_t i = 0; i < len; i++) {
1113bb264b775004be3df72f0bb5ee613761a328a6c3halcanary            result[4 * i + 1] = gHex[(input[i] >> 12) & 0xF];
1114bb264b775004be3df72f0bb5ee613761a328a6c3halcanary            result[4 * i + 2] = gHex[(input[i] >>  8) & 0xF];
1115bb264b775004be3df72f0bb5ee613761a328a6c3halcanary            result[4 * i + 3] = gHex[(input[i] >>  4) & 0xF];
1116bb264b775004be3df72f0bb5ee613761a328a6c3halcanary            result[4 * i + 4] = gHex[(input[i]      ) & 0xF];
1117bb264b775004be3df72f0bb5ee613761a328a6c3halcanary        }
1118bb264b775004be3df72f0bb5ee613761a328a6c3halcanary        result[4 * len + 1] = '>';
1119bb264b775004be3df72f0bb5ee613761a328a6c3halcanary        return result;
1120bb264b775004be3df72f0bb5ee613761a328a6c3halcanary    } else {
1121bb264b775004be3df72f0bb5ee613761a328a6c3halcanary        SkASSERT(len <= 65535);
1122bb264b775004be3df72f0bb5ee613761a328a6c3halcanary        SkString tmp(len);
1123bb264b775004be3df72f0bb5ee613761a328a6c3halcanary        for (size_t i = 0; i < len; i++) {
1124bb264b775004be3df72f0bb5ee613761a328a6c3halcanary            SkASSERT(0 == input[i] >> 8);
1125bb264b775004be3df72f0bb5ee613761a328a6c3halcanary            tmp[i] = static_cast<uint8_t>(input[i]);
1126bb264b775004be3df72f0bb5ee613761a328a6c3halcanary        }
1127bc4696b9176e05940a7c2d6778276cdbc55ccd61halcanary        return SkPDFUtils::FormatString(tmp.c_str(), tmp.size());
1128bb264b775004be3df72f0bb5ee613761a328a6c3halcanary    }
1129bb264b775004be3df72f0bb5ee613761a328a6c3halcanary}
1130bb264b775004be3df72f0bb5ee613761a328a6c3halcanary
113128be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.orgvoid SkPDFDevice::drawText(const SkDraw& d, const void* text, size_t len,
1132c375b0b5c5c03d381111bf7bff12507d5ed24769senorblanco                           SkScalar x, SkScalar y, const SkPaint& srcPaint) {
1133c375b0b5c5c03d381111bf7bff12507d5ed24769senorblanco    SkPaint paint = srcPaint;
1134c375b0b5c5c03d381111bf7bff12507d5ed24769senorblanco    replace_srcmode_on_opaque_paint(&paint);
1135c375b0b5c5c03d381111bf7bff12507d5ed24769senorblanco
1136b62f93fdbcdea16329847e30a351ee35a0552e83edisonn@google.com    NOT_IMPLEMENTED(paint.getMaskFilter() != NULL, false);
1137b62f93fdbcdea16329847e30a351ee35a0552e83edisonn@google.com    if (paint.getMaskFilter() != NULL) {
1138b62f93fdbcdea16329847e30a351ee35a0552e83edisonn@google.com        // Don't pretend we support drawing MaskFilters, it makes for artifacts
1139b62f93fdbcdea16329847e30a351ee35a0552e83edisonn@google.com        // making text unreadable (e.g. same text twice when using CSS shadows).
1140b62f93fdbcdea16329847e30a351ee35a0552e83edisonn@google.com        return;
1141b62f93fdbcdea16329847e30a351ee35a0552e83edisonn@google.com    }
114225adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org    SkPaint textPaint = calculate_text_paint(paint);
114313d14a9dbd2cf0a9654045cc967e92626690631avandebo@chromium.org    ScopedContentEntry content(this, d, textPaint, true);
1144b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org    if (!content.entry()) {
1145fb0b0edd86d71bb423fa921eaac1e2071602115cvandebo@chromium.org        return;
1146fb0b0edd86d71bb423fa921eaac1e2071602115cvandebo@chromium.org    }
1147fb0b0edd86d71bb423fa921eaac1e2071602115cvandebo@chromium.org
11484e1cc6ac450903510b96c1b12f6ee6f420044a66vandebo@chromium.org    SkGlyphStorage storage(0);
114922edc8310cd57ab02155bfa6b2ddaf830556bcafbungeman    const uint16_t* glyphIDs = NULL;
1150aec406650cbfa4ef65d83db5ff4f82572e8e098freed@google.com    int numGlyphs = force_glyph_encoding(paint, text, len, &storage, &glyphIDs);
11514e1cc6ac450903510b96c1b12f6ee6f420044a66vandebo@chromium.org    textPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
115228be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org
115328be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org    SkDrawCacheProc glyphCacheProc = textPaint.getDrawCacheProc();
11549a87cee904e2d8f0ea6a0e7e3ca864262a8cb7c4bungeman@google.com    align_text(glyphCacheProc, textPaint, glyphIDs, numGlyphs, &x, &y);
1155b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org    content.entry()->fContent.writeText("BT\n");
1156b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org    set_text_transform(x, y, textPaint.getTextSkewX(),
1157b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org                       &content.entry()->fContent);
1158aec406650cbfa4ef65d83db5ff4f82572e8e098freed@google.com    int consumedGlyphCount = 0;
11592f912f39b005b1725bd367c9dc5f1827cdde7be5halcanary
11602f912f39b005b1725bd367c9dc5f1827cdde7be5halcanary    SkTDArray<uint16_t> glyphIDsCopy(glyphIDs, numGlyphs);
11612f912f39b005b1725bd367c9dc5f1827cdde7be5halcanary
11622a22e10ab2946c5590cd2a258427ce3ccfca9bfavandebo@chromium.org    while (numGlyphs > consumedGlyphCount) {
1163b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org        updateFont(textPaint, glyphIDs[consumedGlyphCount], content.entry());
1164b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org        SkPDFFont* font = content.entry()->fState.fFont;
11652f912f39b005b1725bd367c9dc5f1827cdde7be5halcanary
11662f912f39b005b1725bd367c9dc5f1827cdde7be5halcanary        int availableGlyphs = font->glyphsToPDFFontEncoding(
11672f912f39b005b1725bd367c9dc5f1827cdde7be5halcanary                glyphIDsCopy.begin() + consumedGlyphCount,
11682f912f39b005b1725bd367c9dc5f1827cdde7be5halcanary                numGlyphs - consumedGlyphCount);
11692f912f39b005b1725bd367c9dc5f1827cdde7be5halcanary        fFontGlyphUsage->noteGlyphUsage(
11702f912f39b005b1725bd367c9dc5f1827cdde7be5halcanary                font,  glyphIDsCopy.begin() + consumedGlyphCount,
11712f912f39b005b1725bd367c9dc5f1827cdde7be5halcanary                availableGlyphs);
1172cae5fba82e687d674b076b10cdc8aba46e1ac3b3vandebo@chromium.org        SkString encodedString =
1173bb264b775004be3df72f0bb5ee613761a328a6c3halcanary                format_wide_string(glyphIDsCopy.begin() + consumedGlyphCount,
1174bb264b775004be3df72f0bb5ee613761a328a6c3halcanary                                   availableGlyphs, font->multiByteGlyphs());
1175b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org        content.entry()->fContent.writeText(encodedString.c_str());
11760129410fbe4b88a0632fb7aa5185610b30e69852vandebo@chromium.org        consumedGlyphCount += availableGlyphs;
1177b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org        content.entry()->fContent.writeText(" Tj\n");
11782a22e10ab2946c5590cd2a258427ce3ccfca9bfavandebo@chromium.org    }
1179b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org    content.entry()->fContent.writeText("ET\n");
11809b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org}
11819b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org
1182fb0b0edd86d71bb423fa921eaac1e2071602115cvandebo@chromium.orgvoid SkPDFDevice::drawPosText(const SkDraw& d, const void* text, size_t len,
118305c4a4322e7d4f3417b7df33825bab8603d52051fmalita                              const SkScalar pos[], int scalarsPerPos,
1184c375b0b5c5c03d381111bf7bff12507d5ed24769senorblanco                              const SkPoint& offset, const SkPaint& srcPaint) {
1185c375b0b5c5c03d381111bf7bff12507d5ed24769senorblanco    SkPaint paint = srcPaint;
1186c375b0b5c5c03d381111bf7bff12507d5ed24769senorblanco    replace_srcmode_on_opaque_paint(&paint);
1187c375b0b5c5c03d381111bf7bff12507d5ed24769senorblanco
1188b62f93fdbcdea16329847e30a351ee35a0552e83edisonn@google.com    NOT_IMPLEMENTED(paint.getMaskFilter() != NULL, false);
1189b62f93fdbcdea16329847e30a351ee35a0552e83edisonn@google.com    if (paint.getMaskFilter() != NULL) {
1190b62f93fdbcdea16329847e30a351ee35a0552e83edisonn@google.com        // Don't pretend we support drawing MaskFilters, it makes for artifacts
1191b62f93fdbcdea16329847e30a351ee35a0552e83edisonn@google.com        // making text unreadable (e.g. same text twice when using CSS shadows).
1192b62f93fdbcdea16329847e30a351ee35a0552e83edisonn@google.com        return;
1193b62f93fdbcdea16329847e30a351ee35a0552e83edisonn@google.com    }
119428be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org    SkASSERT(1 == scalarsPerPos || 2 == scalarsPerPos);
11959fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    SkPaint textPaint = calculate_text_paint(paint);
119613d14a9dbd2cf0a9654045cc967e92626690631avandebo@chromium.org    ScopedContentEntry content(this, d, textPaint, true);
1197b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org    if (!content.entry()) {
119825adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org        return;
119925adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org    }
120028be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org
12014e1cc6ac450903510b96c1b12f6ee6f420044a66vandebo@chromium.org    SkGlyphStorage storage(0);
120222edc8310cd57ab02155bfa6b2ddaf830556bcafbungeman    const uint16_t* glyphIDs = NULL;
120322edc8310cd57ab02155bfa6b2ddaf830556bcafbungeman    size_t numGlyphs = force_glyph_encoding(paint, text, len, &storage, &glyphIDs);
12044e1cc6ac450903510b96c1b12f6ee6f420044a66vandebo@chromium.org    textPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
120528be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org
120628be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org    SkDrawCacheProc glyphCacheProc = textPaint.getDrawCacheProc();
1207b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org    content.entry()->fContent.writeText("BT\n");
1208b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org    updateFont(textPaint, glyphIDs[0], content.entry());
12092a22e10ab2946c5590cd2a258427ce3ccfca9bfavandebo@chromium.org    for (size_t i = 0; i < numGlyphs; i++) {
1210b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org        SkPDFFont* font = content.entry()->fState.fFont;
12110129410fbe4b88a0632fb7aa5185610b30e69852vandebo@chromium.org        uint16_t encodedValue = glyphIDs[i];
12120129410fbe4b88a0632fb7aa5185610b30e69852vandebo@chromium.org        if (font->glyphsToPDFFontEncoding(&encodedValue, 1) != 1) {
121322edc8310cd57ab02155bfa6b2ddaf830556bcafbungeman            // The current pdf font cannot encode the current glyph.
121422edc8310cd57ab02155bfa6b2ddaf830556bcafbungeman            // Try to get a pdf font which can encode the current glyph.
1215b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org            updateFont(textPaint, glyphIDs[i], content.entry());
121622edc8310cd57ab02155bfa6b2ddaf830556bcafbungeman            font = content.entry()->fState.fFont;
121722edc8310cd57ab02155bfa6b2ddaf830556bcafbungeman            if (font->glyphsToPDFFontEncoding(&encodedValue, 1) != 1) {
121822edc8310cd57ab02155bfa6b2ddaf830556bcafbungeman                SkDEBUGFAIL("PDF could not encode glyph.");
121922edc8310cd57ab02155bfa6b2ddaf830556bcafbungeman                continue;
122022edc8310cd57ab02155bfa6b2ddaf830556bcafbungeman            }
12212a22e10ab2946c5590cd2a258427ce3ccfca9bfavandebo@chromium.org        }
122222edc8310cd57ab02155bfa6b2ddaf830556bcafbungeman
12239859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org        fFontGlyphUsage->noteGlyphUsage(font, &encodedValue, 1);
122405c4a4322e7d4f3417b7df33825bab8603d52051fmalita        SkScalar x = offset.x() + pos[i * scalarsPerPos];
122505c4a4322e7d4f3417b7df33825bab8603d52051fmalita        SkScalar y = offset.y() + (2 == scalarsPerPos ? pos[i * scalarsPerPos + 1] : 0);
122605c4a4322e7d4f3417b7df33825bab8603d52051fmalita
12279a87cee904e2d8f0ea6a0e7e3ca864262a8cb7c4bungeman@google.com        align_text(glyphCacheProc, textPaint, glyphIDs + i, 1, &x, &y);
122822edc8310cd57ab02155bfa6b2ddaf830556bcafbungeman        set_text_transform(x, y, textPaint.getTextSkewX(), &content.entry()->fContent);
1229cae5fba82e687d674b076b10cdc8aba46e1ac3b3vandebo@chromium.org        SkString encodedString =
1230bb264b775004be3df72f0bb5ee613761a328a6c3halcanary                format_wide_string(&encodedValue, 1, font->multiByteGlyphs());
1231b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org        content.entry()->fContent.writeText(encodedString.c_str());
1232b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org        content.entry()->fContent.writeText(" Tj\n");
123328be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org    }
1234b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org    content.entry()->fContent.writeText("ET\n");
12359b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org}
12369b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org
1237fb0b0edd86d71bb423fa921eaac1e2071602115cvandebo@chromium.orgvoid SkPDFDevice::drawVertices(const SkDraw& d, SkCanvas::VertexMode,
12389b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org                               int vertexCount, const SkPoint verts[],
12399b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org                               const SkPoint texs[], const SkColor colors[],
12409b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org                               SkXfermode* xmode, const uint16_t indices[],
12419b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org                               int indexCount, const SkPaint& paint) {
1242fb0b0edd86d71bb423fa921eaac1e2071602115cvandebo@chromium.org    if (d.fClip->isEmpty()) {
1243fb0b0edd86d71bb423fa921eaac1e2071602115cvandebo@chromium.org        return;
1244fb0b0edd86d71bb423fa921eaac1e2071602115cvandebo@chromium.org    }
124585e143c33c214e54187aa28146aa7666961a0d17reed@google.com    // TODO: implement drawVertices
12469b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org}
12479b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org
12483b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.orgvoid SkPDFDevice::drawDevice(const SkDraw& d, SkBaseDevice* device,
12493b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org                             int x, int y, const SkPaint& paint) {
12506987dcaf257dd7c2c8e0014cf7452fde82bcba5bfmalita    // our onCreateCompatibleDevice() always creates SkPDFDevice subclasses.
1251ee7a9569f2745b949dbafa15927d70a4e08c92aevandebo@chromium.org    SkPDFDevice* pdfDevice = static_cast<SkPDFDevice*>(device);
1252f4ff39ca4854d64fce9189745af615bb9bc37faactguil@chromium.org    if (pdfDevice->isContentEmpty()) {
1253ee7a9569f2745b949dbafa15927d70a4e08c92aevandebo@chromium.org        return;
1254ee7a9569f2745b949dbafa15927d70a4e08c92aevandebo@chromium.org    }
1255ee7a9569f2745b949dbafa15927d70a4e08c92aevandebo@chromium.org
1256eb6c7596af1a1fc7860e27ff2f678a33b2576c0fvandebo@chromium.org    SkMatrix matrix;
1257a6d59f60aab59fb6556841b063ead5d49b46ba8dreed@google.com    matrix.setTranslate(SkIntToScalar(x), SkIntToScalar(y));
125813d14a9dbd2cf0a9654045cc967e92626690631avandebo@chromium.org    ScopedContentEntry content(this, d.fClipStack, *d.fClip, matrix, paint);
1259b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org    if (!content.entry()) {
126025adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org        return;
126125adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org    }
12623b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org    if (content.needShape()) {
12633b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org        SkPath shape;
12643b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org        shape.addRect(SkRect::MakeXYWH(SkIntToScalar(x), SkIntToScalar(y),
1265fd3c8c243ab190604e134910a1d6c1326d21e374vandebo@chromium.org                                       SkIntToScalar(device->width()),
1266fd3c8c243ab190604e134910a1d6c1326d21e374vandebo@chromium.org                                       SkIntToScalar(device->height())));
12673b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org        content.setShape(shape);
12683b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org    }
12693b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org    if (!content.needSource()) {
12703b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org        return;
12713b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org    }
1272eb6c7596af1a1fc7860e27ff2f678a33b2576c0fvandebo@chromium.org
12733b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org    SkAutoTUnref<SkPDFFormXObject> xObject(new SkPDFFormXObject(pdfDevice));
12743b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org    SkPDFUtils::DrawFormXObject(this->addXObjectResource(xObject.get()),
1275b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org                                &content.entry()->fContent);
12769859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org
12779859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org    // Merge glyph sets from the drawn device.
12789859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org    fFontGlyphUsage->merge(pdfDevice->getFontGlyphUsage());
12799b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org}
12809b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org
128189443aba5bfa2b040dc9fd24938b7d0b3decd737reedSkImageInfo SkPDFDevice::imageInfo() const {
128289443aba5bfa2b040dc9fd24938b7d0b3decd737reed    return fLegacyBitmap.info();
128389443aba5bfa2b040dc9fd24938b7d0b3decd737reed}
128489443aba5bfa2b040dc9fd24938b7d0b3decd737reed
128540a1ae4df28810aa5aa5cf2627d8387b2dfb867arobertphillips@google.comvoid SkPDFDevice::onAttachToCanvas(SkCanvas* canvas) {
128640a1ae4df28810aa5aa5cf2627d8387b2dfb867arobertphillips@google.com    INHERITED::onAttachToCanvas(canvas);
128740a1ae4df28810aa5aa5cf2627d8387b2dfb867arobertphillips@google.com
128840a1ae4df28810aa5aa5cf2627d8387b2dfb867arobertphillips@google.com    // Canvas promises that this ptr is valid until onDetachFromCanvas is called
128940a1ae4df28810aa5aa5cf2627d8387b2dfb867arobertphillips@google.com    fClipStack = canvas->getClipStack();
129040a1ae4df28810aa5aa5cf2627d8387b2dfb867arobertphillips@google.com}
129140a1ae4df28810aa5aa5cf2627d8387b2dfb867arobertphillips@google.com
129240a1ae4df28810aa5aa5cf2627d8387b2dfb867arobertphillips@google.comvoid SkPDFDevice::onDetachFromCanvas() {
129340a1ae4df28810aa5aa5cf2627d8387b2dfb867arobertphillips@google.com    INHERITED::onDetachFromCanvas();
129440a1ae4df28810aa5aa5cf2627d8387b2dfb867arobertphillips@google.com
129540a1ae4df28810aa5aa5cf2627d8387b2dfb867arobertphillips@google.com    fClipStack = NULL;
129640a1ae4df28810aa5aa5cf2627d8387b2dfb867arobertphillips@google.com}
129740a1ae4df28810aa5aa5cf2627d8387b2dfb867arobertphillips@google.com
12984a8126e7f81384526629b1e21bf89b632ea13cd9reedSkSurface* SkPDFDevice::newSurface(const SkImageInfo& info, const SkSurfaceProps& props) {
12994a8126e7f81384526629b1e21bf89b632ea13cd9reed    return SkSurface::NewRaster(info, &props);
130089443aba5bfa2b040dc9fd24938b7d0b3decd737reed}
130189443aba5bfa2b040dc9fd24938b7d0b3decd737reed
13028dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.orgContentEntry* SkPDFDevice::getLastContentEntry() {
13038dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org    if (fDrawingArea == kContent_DrawingArea) {
13048dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org        return fLastContentEntry;
13058dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org    } else {
13068dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org        return fLastMarginContentEntry;
13078dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org    }
13088dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org}
13098dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org
1310e02944075840d672bd1797f3d945ff82d302282fcommit-bot@chromium.orgSkAutoTDelete<ContentEntry>* SkPDFDevice::getContentEntries() {
13118dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org    if (fDrawingArea == kContent_DrawingArea) {
13129510ccc06bbfa5e888f66578042674be98d8ac60ctguil@chromium.org        return &fContentEntries;
13138dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org    } else {
13149510ccc06bbfa5e888f66578042674be98d8ac60ctguil@chromium.org        return &fMarginContentEntries;
13158dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org    }
13168dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org}
13178dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org
13188dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.orgvoid SkPDFDevice::setLastContentEntry(ContentEntry* contentEntry) {
13198dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org    if (fDrawingArea == kContent_DrawingArea) {
13208dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org        fLastContentEntry = contentEntry;
13218dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org    } else {
13228dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org        fLastMarginContentEntry = contentEntry;
13238dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org    }
13248dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org}
13258dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org
13268dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.orgvoid SkPDFDevice::setDrawingArea(DrawingArea drawingArea) {
13279510ccc06bbfa5e888f66578042674be98d8ac60ctguil@chromium.org    // A ScopedContentEntry only exists during the course of a draw call, so
13289510ccc06bbfa5e888f66578042674be98d8ac60ctguil@chromium.org    // this can't be called while a ScopedContentEntry exists.
13298dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org    fDrawingArea = drawingArea;
13308dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org}
13318dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org
13322b86155b42c2493ff0c558ce105a464769962274halcanarySkPDFDict* SkPDFDevice::createResourceDict() const {
13332b86155b42c2493ff0c558ce105a464769962274halcanary    SkTDArray<SkPDFObject*> fonts;
13342b86155b42c2493ff0c558ce105a464769962274halcanary    fonts.setReserve(fFontResources.count());
13352b86155b42c2493ff0c558ce105a464769962274halcanary    for (SkPDFFont* font : fFontResources) {
13362b86155b42c2493ff0c558ce105a464769962274halcanary        fonts.push(font);
13372b86155b42c2493ff0c558ce105a464769962274halcanary    }
13382b86155b42c2493ff0c558ce105a464769962274halcanary    return SkPDFResourceDict::Create(
13392b86155b42c2493ff0c558ce105a464769962274halcanary            &fGraphicStateResources,
13402b86155b42c2493ff0c558ce105a464769962274halcanary            &fShaderResources,
13412b86155b42c2493ff0c558ce105a464769962274halcanary            &fXObjectResources,
13422b86155b42c2493ff0c558ce105a464769962274halcanary            &fonts);
13439b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org}
13449b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org
1345f0ec2666d9a3f0f1662f0d63b5147628c49648aavandebo@chromium.orgconst SkTDArray<SkPDFFont*>& SkPDFDevice::getFontResources() const {
1346f0ec2666d9a3f0f1662f0d63b5147628c49648aavandebo@chromium.org    return fFontResources;
1347f0ec2666d9a3f0f1662f0d63b5147628c49648aavandebo@chromium.org}
1348f0ec2666d9a3f0f1662f0d63b5147628c49648aavandebo@chromium.org
13492a006c112743e07ce258ca223631fc19233f5ddcreed@google.comSkPDFArray* SkPDFDevice::copyMediaBox() const {
13502a006c112743e07ce258ca223631fc19233f5ddcreed@google.com    // should this be a singleton?
1351f7c157610ff85f7323f5e213b62478dcc66edbecvandebo@chromium.org
1352130444fdaf737c5931a934018ab50b0c91a3499ehalcanary    SkAutoTUnref<SkPDFArray> mediaBox(SkNEW(SkPDFArray));
13539b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org    mediaBox->reserve(4);
1354130444fdaf737c5931a934018ab50b0c91a3499ehalcanary    mediaBox->appendInt(0);
1355130444fdaf737c5931a934018ab50b0c91a3499ehalcanary    mediaBox->appendInt(0);
1356c789cf1c6f3947283aeb34acb5a22e6204f8f6f5reed@google.com    mediaBox->appendInt(fPageSize.fWidth);
1357c789cf1c6f3947283aeb34acb5a22e6204f8f6f5reed@google.com    mediaBox->appendInt(fPageSize.fHeight);
1358130444fdaf737c5931a934018ab50b0c91a3499ehalcanary    return mediaBox.detach();
13599b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org}
13609b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org
1361334fcbc167237f02058cb508cb5f51b718141461halcanarySkStreamAsset* SkPDFDevice::content() const {
1362334fcbc167237f02058cb508cb5f51b718141461halcanary    SkDynamicMemoryWStream buffer;
1363334fcbc167237f02058cb508cb5f51b718141461halcanary    this->writeContent(&buffer);
1364334fcbc167237f02058cb508cb5f51b718141461halcanary    return buffer.detachAsStream();
13655667afc5cb4a8cd15a27667f222b6d9c94d61c38reed@google.com}
13665667afc5cb4a8cd15a27667f222b6d9c94d61c38reed@google.com
13678dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.orgvoid SkPDFDevice::copyContentEntriesToData(ContentEntry* entry,
13688dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org        SkWStream* data) const {
13699510ccc06bbfa5e888f66578042674be98d8ac60ctguil@chromium.org    // TODO(ctguil): For margins, I'm not sure fExistingClipStack/Region is the
13709510ccc06bbfa5e888f66578042674be98d8ac60ctguil@chromium.org    // right thing to pass here.
13718dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org    GraphicStackState gsState(fExistingClipStack, fExistingClipRegion, data);
13729510ccc06bbfa5e888f66578042674be98d8ac60ctguil@chromium.org    while (entry != NULL) {
1373663515bc59325092c4e47f5189782bd6fcd0586avandebo@chromium.org        SkPoint translation;
1374663515bc59325092c4e47f5189782bd6fcd0586avandebo@chromium.org        translation.iset(this->getOrigin());
13758dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org        translation.negate();
13768dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org        gsState.updateClip(entry->fState.fClipStack, entry->fState.fClipRegion,
13778dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org                           translation);
13788dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org        gsState.updateMatrix(entry->fState.fMatrix);
13798dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org        gsState.updateDrawingState(entry->fState);
13809510ccc06bbfa5e888f66578042674be98d8ac60ctguil@chromium.org
13817af21501a61886cac94f0bd5e1c14be2dce9ae63halcanary        entry->fContent.writeToStream(data);
13828dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org        entry = entry->fNext.get();
13838dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org    }
13848dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org    gsState.drainStack();
13858dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org}
13868dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org
1387334fcbc167237f02058cb508cb5f51b718141461halcanaryvoid SkPDFDevice::writeContent(SkWStream* out) const {
13889fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    if (fInitialTransform.getType() != SkMatrix::kIdentity_Mask) {
1389334fcbc167237f02058cb508cb5f51b718141461halcanary        SkPDFUtils::AppendTransform(fInitialTransform, out);
1390c2a9b7fe5640af8f0c371561f1ac71b045d6d8ecvandebo@chromium.org    }
13919510ccc06bbfa5e888f66578042674be98d8ac60ctguil@chromium.org
13928dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org    // TODO(aayushkumar): Apply clip along the margins.  Currently, webkit
13938dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org    // colors the contentArea white before it starts drawing into it and
13948dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org    // that currently acts as our clip.
13958dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org    // Also, think about adding a transform here (or assume that the values
13968dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org    // sent across account for that)
1397334fcbc167237f02058cb508cb5f51b718141461halcanary    SkPDFDevice::copyContentEntriesToData(fMarginContentEntries.get(), out);
13989510ccc06bbfa5e888f66578042674be98d8ac60ctguil@chromium.org
13999fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    // If the content area is the entire page, then we don't need to clip
14009fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    // the content area (PDF area clips to the page size).  Otherwise,
14019fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    // we have to clip to the content area; we've already applied the
14029fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    // initial transform, so just clip to the device size.
14039fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    if (fPageSize != fContentSize) {
14048637a365518a82901d313d61eecd83a0c5102fe9robertphillips@google.com        SkRect r = SkRect::MakeWH(SkIntToScalar(this->width()),
14058637a365518a82901d313d61eecd83a0c5102fe9robertphillips@google.com                                  SkIntToScalar(this->height()));
1406334fcbc167237f02058cb508cb5f51b718141461halcanary        emit_clip(NULL, &r, out);
14079fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    }
14089859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org
1409334fcbc167237f02058cb508cb5f51b718141461halcanary    SkPDFDevice::copyContentEntriesToData(fContentEntries.get(), out);
14109b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org}
14119b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org
141292ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org/* Draws an inverse filled path by using Path Ops to compute the positive
141392ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org * inverse using the current clip as the inverse bounds.
141492ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org * Return true if this was an inverse path and was properly handled,
141592ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org * otherwise returns false and the normal drawing routine should continue,
141692ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org * either as a (incorrect) fallback or because the path was not inverse
141792ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org * in the first place.
141892ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org */
141992ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.orgbool SkPDFDevice::handleInversePath(const SkDraw& d, const SkPath& origPath,
1420a9ebd161a7c08515f0c4bd885e61c4b52688ececedisonn@google.com                                    const SkPaint& paint, bool pathIsMutable,
1421a9ebd161a7c08515f0c4bd885e61c4b52688ececedisonn@google.com                                    const SkMatrix* prePathMatrix) {
142292ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org    if (!origPath.isInverseFillType()) {
142392ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org        return false;
142492ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org    }
142592ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org
142692ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org    if (d.fClip->isEmpty()) {
142792ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org        return false;
142892ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org    }
142992ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org
143092ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org    SkPath modifiedPath;
143192ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org    SkPath* pathPtr = const_cast<SkPath*>(&origPath);
143292ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org    SkPaint noInversePaint(paint);
143392ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org
143492ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org    // Merge stroking operations into final path.
143592ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org    if (SkPaint::kStroke_Style == paint.getStyle() ||
143692ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org        SkPaint::kStrokeAndFill_Style == paint.getStyle()) {
143792ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org        bool doFillPath = paint.getFillPath(origPath, &modifiedPath);
143892ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org        if (doFillPath) {
143992ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org            noInversePaint.setStyle(SkPaint::kFill_Style);
144092ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org            noInversePaint.setStrokeWidth(0);
144192ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org            pathPtr = &modifiedPath;
144292ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org        } else {
144392ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org            // To be consistent with the raster output, hairline strokes
144492ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org            // are rendered as non-inverted.
144592ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org            modifiedPath.toggleInverseFillType();
144692ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org            drawPath(d, modifiedPath, paint, NULL, true);
144792ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org            return true;
144892ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org        }
144992ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org    }
145092ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org
145192ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org    // Get bounds of clip in current transform space
145292ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org    // (clip bounds are given in device space).
145392ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org    SkRect bounds;
145492ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org    SkMatrix transformInverse;
1455a9ebd161a7c08515f0c4bd885e61c4b52688ececedisonn@google.com    SkMatrix totalMatrix = *d.fMatrix;
1456a9ebd161a7c08515f0c4bd885e61c4b52688ececedisonn@google.com    if (prePathMatrix) {
1457a9ebd161a7c08515f0c4bd885e61c4b52688ececedisonn@google.com        totalMatrix.preConcat(*prePathMatrix);
1458a9ebd161a7c08515f0c4bd885e61c4b52688ececedisonn@google.com    }
1459a9ebd161a7c08515f0c4bd885e61c4b52688ececedisonn@google.com    if (!totalMatrix.invert(&transformInverse)) {
146092ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org        return false;
146192ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org    }
146292ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org    bounds.set(d.fClip->getBounds());
146392ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org    transformInverse.mapRect(&bounds);
146492ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org
146592ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org    // Extend the bounds by the line width (plus some padding)
146692ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org    // so the edge doesn't cause a visible stroke.
146792ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org    bounds.outset(paint.getStrokeWidth() + SK_Scalar1,
146892ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org                  paint.getStrokeWidth() + SK_Scalar1);
146992ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org
147092ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org    if (!calculate_inverse_path(bounds, *pathPtr, &modifiedPath)) {
147192ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org        return false;
147292ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org    }
147392ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org
1474a9ebd161a7c08515f0c4bd885e61c4b52688ececedisonn@google.com    drawPath(d, modifiedPath, noInversePaint, prePathMatrix, true);
147592ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org    return true;
147692ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org}
147792ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org
1478b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.combool SkPDFDevice::handleRectAnnotation(const SkRect& r, const SkMatrix& matrix,
1479b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com                                       const SkPaint& p) {
1480238be8c7e5de5a83517440a3db7f7965b47fb010vandebo@chromium.org    SkAnnotation* annotationInfo = p.getAnnotation();
1481238be8c7e5de5a83517440a3db7f7965b47fb010vandebo@chromium.org    if (!annotationInfo) {
1482238be8c7e5de5a83517440a3db7f7965b47fb010vandebo@chromium.org        return false;
1483238be8c7e5de5a83517440a3db7f7965b47fb010vandebo@chromium.org    }
1484238be8c7e5de5a83517440a3db7f7965b47fb010vandebo@chromium.org    SkData* urlData = annotationInfo->find(SkAnnotationKeys::URL_Key());
1485b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com    if (urlData) {
1486b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com        handleLinkToURL(urlData, r, matrix);
14874469938e92d779dff05e745559e67907bbf21e78reed@google.com        return p.getAnnotation() != NULL;
1488b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com    }
14893b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org    SkData* linkToName = annotationInfo->find(
14903b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org            SkAnnotationKeys::Link_Named_Dest_Key());
1491b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com    if (linkToName) {
1492b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com        handleLinkToNamedDest(linkToName, r, matrix);
14934469938e92d779dff05e745559e67907bbf21e78reed@google.com        return p.getAnnotation() != NULL;
1494b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com    }
1495b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com    return false;
1496b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com}
1497b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com
1498b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.combool SkPDFDevice::handlePointAnnotation(const SkPoint* points, size_t count,
1499b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com                                        const SkMatrix& matrix,
1500b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com                                        const SkPaint& paint) {
1501b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com    SkAnnotation* annotationInfo = paint.getAnnotation();
1502b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com    if (!annotationInfo) {
1503238be8c7e5de5a83517440a3db7f7965b47fb010vandebo@chromium.org        return false;
1504238be8c7e5de5a83517440a3db7f7965b47fb010vandebo@chromium.org    }
15053b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org    SkData* nameData = annotationInfo->find(
15063b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org            SkAnnotationKeys::Define_Named_Dest_Key());
1507b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com    if (nameData) {
1508b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com        for (size_t i = 0; i < count; i++) {
1509b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com            defineNamedDestination(nameData, points[i], matrix);
1510b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com        }
15114469938e92d779dff05e745559e67907bbf21e78reed@google.com        return paint.getAnnotation() != NULL;
1512b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com    }
1513b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com    return false;
1514b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com}
1515238be8c7e5de5a83517440a3db7f7965b47fb010vandebo@chromium.org
1516438de49857cab98981b35d04dc49c2135124d18bhalcanaryvoid SkPDFDevice::addAnnotation(SkPDFDict* annotation) {
1517438de49857cab98981b35d04dc49c2135124d18bhalcanary    if (NULL == fAnnotations) {
1518438de49857cab98981b35d04dc49c2135124d18bhalcanary        fAnnotations = SkNEW(SkPDFArray);
1519438de49857cab98981b35d04dc49c2135124d18bhalcanary    }
1520438de49857cab98981b35d04dc49c2135124d18bhalcanary    fAnnotations->appendObject(annotation);
1521438de49857cab98981b35d04dc49c2135124d18bhalcanary}
1522438de49857cab98981b35d04dc49c2135124d18bhalcanary
1523438de49857cab98981b35d04dc49c2135124d18bhalcanarystatic SkPDFDict* create_link_annotation(const SkRect& r,
1524438de49857cab98981b35d04dc49c2135124d18bhalcanary                                         const SkMatrix& initialTransform,
1525438de49857cab98981b35d04dc49c2135124d18bhalcanary                                         const SkMatrix& matrix) {
1526238be8c7e5de5a83517440a3db7f7965b47fb010vandebo@chromium.org    SkMatrix transform = matrix;
1527438de49857cab98981b35d04dc49c2135124d18bhalcanary    transform.postConcat(initialTransform);
1528238be8c7e5de5a83517440a3db7f7965b47fb010vandebo@chromium.org    SkRect translatedRect;
1529238be8c7e5de5a83517440a3db7f7965b47fb010vandebo@chromium.org    transform.mapRect(&translatedRect, r);
1530238be8c7e5de5a83517440a3db7f7965b47fb010vandebo@chromium.org
1531438de49857cab98981b35d04dc49c2135124d18bhalcanary    SkAutoTUnref<SkPDFDict> annotation(SkNEW_ARGS(SkPDFDict, ("Annot")));
1532238be8c7e5de5a83517440a3db7f7965b47fb010vandebo@chromium.org    annotation->insertName("Subtype", "Link");
1533238be8c7e5de5a83517440a3db7f7965b47fb010vandebo@chromium.org
1534b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com    SkAutoTUnref<SkPDFArray> border(SkNEW(SkPDFArray));
1535238be8c7e5de5a83517440a3db7f7965b47fb010vandebo@chromium.org    border->reserve(3);
1536238be8c7e5de5a83517440a3db7f7965b47fb010vandebo@chromium.org    border->appendInt(0);  // Horizontal corner radius.
1537238be8c7e5de5a83517440a3db7f7965b47fb010vandebo@chromium.org    border->appendInt(0);  // Vertical corner radius.
1538238be8c7e5de5a83517440a3db7f7965b47fb010vandebo@chromium.org    border->appendInt(0);  // Width, 0 = no border.
1539438de49857cab98981b35d04dc49c2135124d18bhalcanary    annotation->insertObject("Border", border.detach());
1540238be8c7e5de5a83517440a3db7f7965b47fb010vandebo@chromium.org
1541b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com    SkAutoTUnref<SkPDFArray> rect(SkNEW(SkPDFArray));
1542238be8c7e5de5a83517440a3db7f7965b47fb010vandebo@chromium.org    rect->reserve(4);
1543238be8c7e5de5a83517440a3db7f7965b47fb010vandebo@chromium.org    rect->appendScalar(translatedRect.fLeft);
1544238be8c7e5de5a83517440a3db7f7965b47fb010vandebo@chromium.org    rect->appendScalar(translatedRect.fTop);
1545238be8c7e5de5a83517440a3db7f7965b47fb010vandebo@chromium.org    rect->appendScalar(translatedRect.fRight);
1546238be8c7e5de5a83517440a3db7f7965b47fb010vandebo@chromium.org    rect->appendScalar(translatedRect.fBottom);
1547438de49857cab98981b35d04dc49c2135124d18bhalcanary    annotation->insertObject("Rect", rect.detach());
1548238be8c7e5de5a83517440a3db7f7965b47fb010vandebo@chromium.org
1549438de49857cab98981b35d04dc49c2135124d18bhalcanary    return annotation.detach();
1550b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com}
1551b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com
1552b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.comvoid SkPDFDevice::handleLinkToURL(SkData* urlData, const SkRect& r,
1553b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com                                  const SkMatrix& matrix) {
1554438de49857cab98981b35d04dc49c2135124d18bhalcanary    SkAutoTUnref<SkPDFDict> annotation(
1555438de49857cab98981b35d04dc49c2135124d18bhalcanary            create_link_annotation(r, fInitialTransform, matrix));
1556b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com
1557b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com    SkString url(static_cast<const char *>(urlData->data()),
1558b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com                 urlData->size() - 1);
1559b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com    SkAutoTUnref<SkPDFDict> action(SkNEW_ARGS(SkPDFDict, ("Action")));
1560238be8c7e5de5a83517440a3db7f7965b47fb010vandebo@chromium.org    action->insertName("S", "URI");
1561130444fdaf737c5931a934018ab50b0c91a3499ehalcanary    action->insertString("URI", url);
1562438de49857cab98981b35d04dc49c2135124d18bhalcanary    annotation->insertObject("A", action.detach());
1563438de49857cab98981b35d04dc49c2135124d18bhalcanary    this->addAnnotation(annotation.detach());
1564b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com}
1565b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com
1566b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.comvoid SkPDFDevice::handleLinkToNamedDest(SkData* nameData, const SkRect& r,
1567b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com                                        const SkMatrix& matrix) {
1568438de49857cab98981b35d04dc49c2135124d18bhalcanary    SkAutoTUnref<SkPDFDict> annotation(
1569438de49857cab98981b35d04dc49c2135124d18bhalcanary            create_link_annotation(r, fInitialTransform, matrix));
1570b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com    SkString name(static_cast<const char *>(nameData->data()),
1571b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com                  nameData->size() - 1);
1572130444fdaf737c5931a934018ab50b0c91a3499ehalcanary    annotation->insertName("Dest", name);
1573438de49857cab98981b35d04dc49c2135124d18bhalcanary    this->addAnnotation(annotation.detach());
1574b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com}
1575b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com
1576b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.comstruct NamedDestination {
1577b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com    const SkData* nameData;
1578b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com    SkPoint point;
1579b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com
1580b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com    NamedDestination(const SkData* nameData, const SkPoint& point)
1581130444fdaf737c5931a934018ab50b0c91a3499ehalcanary        : nameData(SkRef(nameData)), point(point) {}
1582238be8c7e5de5a83517440a3db7f7965b47fb010vandebo@chromium.org
1583b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com    ~NamedDestination() {
1584b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com        nameData->unref();
1585b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com    }
1586b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com};
1587b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com
1588b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.comvoid SkPDFDevice::defineNamedDestination(SkData* nameData, const SkPoint& point,
1589b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com                                         const SkMatrix& matrix) {
1590b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com    SkMatrix transform = matrix;
1591b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com    transform.postConcat(fInitialTransform);
1592b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com    SkPoint translatedPoint;
1593b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com    transform.mapXY(point.x(), point.y(), &translatedPoint);
1594b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com    fNamedDestinations.push(
1595b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com        SkNEW_ARGS(NamedDestination, (nameData, translatedPoint)));
1596b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com}
1597b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com
15986d622703e578eddc64ab4e3340d0ab0033268799halcanaryvoid SkPDFDevice::appendDestinations(SkPDFDict* dict, SkPDFObject* page) const {
1599b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com    int nDest = fNamedDestinations.count();
1600b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com    for (int i = 0; i < nDest; i++) {
1601b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com        NamedDestination* dest = fNamedDestinations[i];
1602b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com        SkAutoTUnref<SkPDFArray> pdfDest(SkNEW(SkPDFArray));
1603b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com        pdfDest->reserve(5);
1604130444fdaf737c5931a934018ab50b0c91a3499ehalcanary        pdfDest->appendObjRef(SkRef(page));
1605b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com        pdfDest->appendName("XYZ");
1606b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com        pdfDest->appendScalar(dest->point.x());
1607b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com        pdfDest->appendScalar(dest->point.y());
1608b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com        pdfDest->appendInt(0);  // Leave zoom unchanged
1609130444fdaf737c5931a934018ab50b0c91a3499ehalcanary        SkString name(static_cast<const char*>(dest->nameData->data()));
1610130444fdaf737c5931a934018ab50b0c91a3499ehalcanary        dict->insertObject(name, pdfDest.detach());
1611b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com    }
1612238be8c7e5de5a83517440a3db7f7965b47fb010vandebo@chromium.org}
1613238be8c7e5de5a83517440a3db7f7965b47fb010vandebo@chromium.org
1614fc641d09e5a1a9f7fae369ae06a8b96089faf57breed@google.comSkPDFFormXObject* SkPDFDevice::createFormXObjectFromDevice() {
1615fc641d09e5a1a9f7fae369ae06a8b96089faf57breed@google.com    SkPDFFormXObject* xobject = SkNEW_ARGS(SkPDFFormXObject, (this));
16169859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org    // We always draw the form xobjects that we create back into the device, so
16179859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org    // we simply preserve the font usage instead of pulling it out and merging
16189859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org    // it back in later.
16199859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org    cleanUp(false);  // Reset this device to have no content.
16206112c215fbdd53388e64ece36e6c7bba0fe3a451vandebo@chromium.org    init();
1621fc641d09e5a1a9f7fae369ae06a8b96089faf57breed@google.com    return xobject;
16226112c215fbdd53388e64ece36e6c7bba0fe3a451vandebo@chromium.org}
16236112c215fbdd53388e64ece36e6c7bba0fe3a451vandebo@chromium.org
16243b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.orgvoid SkPDFDevice::drawFormXObjectWithMask(int xObjectIndex,
16253b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org                                          SkPDFFormXObject* mask,
1626481aef68333e01c19badda456d8e60bd1f1bee2avandebo@chromium.org                                          const SkClipStack* clipStack,
1627481aef68333e01c19badda456d8e60bd1f1bee2avandebo@chromium.org                                          const SkRegion& clipRegion,
16283b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org                                          SkXfermode::Mode mode,
1629481aef68333e01c19badda456d8e60bd1f1bee2avandebo@chromium.org                                          bool invertClip) {
1630481aef68333e01c19badda456d8e60bd1f1bee2avandebo@chromium.org    if (clipRegion.isEmpty() && !invertClip) {
1631481aef68333e01c19badda456d8e60bd1f1bee2avandebo@chromium.org        return;
1632481aef68333e01c19badda456d8e60bd1f1bee2avandebo@chromium.org    }
1633481aef68333e01c19badda456d8e60bd1f1bee2avandebo@chromium.org
1634be27a118c277af23377d38e9b3bfd3fcc276114fhalcanary    SkAutoTUnref<SkPDFObject> sMaskGS(SkPDFGraphicState::GetSMaskGraphicState(
16353b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org            mask, invertClip, SkPDFGraphicState::kAlpha_SMaskMode));
1636466f3d66f09285d2d988315bacde573a5359ce54vandebo@chromium.org
16373b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org    SkMatrix identity;
16383b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org    identity.reset();
16393b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org    SkPaint paint;
16403b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org    paint.setXfermodeMode(mode);
16413b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org    ScopedContentEntry content(this, clipStack, clipRegion, identity, paint);
1642b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org    if (!content.entry()) {
1643b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org        return;
1644b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org    }
1645466f3d66f09285d2d988315bacde573a5359ce54vandebo@chromium.org    SkPDFUtils::ApplyGraphicState(addGraphicStateResource(sMaskGS.get()),
1646b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org                                  &content.entry()->fContent);
16473b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org    SkPDFUtils::DrawFormXObject(xObjectIndex, &content.entry()->fContent);
1648466f3d66f09285d2d988315bacde573a5359ce54vandebo@chromium.org
1649d96d17b9c113ac694138224249ff2ce643e961ddvandebo@chromium.org    sMaskGS.reset(SkPDFGraphicState::GetNoSMaskGraphicState());
1650466f3d66f09285d2d988315bacde573a5359ce54vandebo@chromium.org    SkPDFUtils::ApplyGraphicState(addGraphicStateResource(sMaskGS.get()),
1651b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org                                  &content.entry()->fContent);
1652466f3d66f09285d2d988315bacde573a5359ce54vandebo@chromium.org}
1653466f3d66f09285d2d988315bacde573a5359ce54vandebo@chromium.org
1654b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.orgContentEntry* SkPDFDevice::setUpContentEntry(const SkClipStack* clipStack,
1655b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org                                             const SkRegion& clipRegion,
1656b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org                                             const SkMatrix& matrix,
1657b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org                                             const SkPaint& paint,
1658b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org                                             bool hasText,
1659fc641d09e5a1a9f7fae369ae06a8b96089faf57breed@google.com                                             SkPDFFormXObject** dst) {
1660fc641d09e5a1a9f7fae369ae06a8b96089faf57breed@google.com    *dst = NULL;
166125adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org    if (clipRegion.isEmpty()) {
1662b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org        return NULL;
166325adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org    }
166425adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org
166578dad54080ad806be89adb5cc0e3c530b031cdafvandebo@chromium.org    // The clip stack can come from an SkDraw where it is technically optional.
166678dad54080ad806be89adb5cc0e3c530b031cdafvandebo@chromium.org    SkClipStack synthesizedClipStack;
166778dad54080ad806be89adb5cc0e3c530b031cdafvandebo@chromium.org    if (clipStack == NULL) {
166878dad54080ad806be89adb5cc0e3c530b031cdafvandebo@chromium.org        if (clipRegion == fExistingClipRegion) {
166978dad54080ad806be89adb5cc0e3c530b031cdafvandebo@chromium.org            clipStack = &fExistingClipStack;
167078dad54080ad806be89adb5cc0e3c530b031cdafvandebo@chromium.org        } else {
167178dad54080ad806be89adb5cc0e3c530b031cdafvandebo@chromium.org            // GraphicStackState::updateClip expects the clip stack to have
167278dad54080ad806be89adb5cc0e3c530b031cdafvandebo@chromium.org            // fExistingClip as a prefix, so start there, then set the clip
167378dad54080ad806be89adb5cc0e3c530b031cdafvandebo@chromium.org            // to the passed region.
167478dad54080ad806be89adb5cc0e3c530b031cdafvandebo@chromium.org            synthesizedClipStack = fExistingClipStack;
167578dad54080ad806be89adb5cc0e3c530b031cdafvandebo@chromium.org            SkPath clipPath;
167678dad54080ad806be89adb5cc0e3c530b031cdafvandebo@chromium.org            clipRegion.getBoundaryPath(&clipPath);
16770017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com            synthesizedClipStack.clipDevPath(clipPath, SkRegion::kReplace_Op,
16780017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com                                             false);
167978dad54080ad806be89adb5cc0e3c530b031cdafvandebo@chromium.org            clipStack = &synthesizedClipStack;
168078dad54080ad806be89adb5cc0e3c530b031cdafvandebo@chromium.org        }
168178dad54080ad806be89adb5cc0e3c530b031cdafvandebo@chromium.org    }
168278dad54080ad806be89adb5cc0e3c530b031cdafvandebo@chromium.org
168325adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org    SkXfermode::Mode xfermode = SkXfermode::kSrcOver_Mode;
168425adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org    if (paint.getXfermode()) {
168525adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org        paint.getXfermode()->asMode(&xfermode);
168625adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org    }
168725adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org
16883b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org    // For the following modes, we want to handle source and destination
16893b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org    // separately, so make an object of what's already there.
16903b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org    if (xfermode == SkXfermode::kClear_Mode       ||
16913b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org            xfermode == SkXfermode::kSrc_Mode     ||
16923b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org            xfermode == SkXfermode::kSrcIn_Mode   ||
16933b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org            xfermode == SkXfermode::kDstIn_Mode   ||
16943b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org            xfermode == SkXfermode::kSrcOut_Mode  ||
16953b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org            xfermode == SkXfermode::kDstOut_Mode  ||
16963b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org            xfermode == SkXfermode::kSrcATop_Mode ||
16973b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org            xfermode == SkXfermode::kDstATop_Mode ||
16983b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org            xfermode == SkXfermode::kModulate_Mode) {
16993b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org        if (!isContentEmpty()) {
1700fc641d09e5a1a9f7fae369ae06a8b96089faf57breed@google.com            *dst = createFormXObjectFromDevice();
17013b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org            SkASSERT(isContentEmpty());
17023b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org        } else if (xfermode != SkXfermode::kSrc_Mode &&
17033b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org                   xfermode != SkXfermode::kSrcOut_Mode) {
17043b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org            // Except for Src and SrcOut, if there isn't anything already there,
17053b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org            // then we're done.
17063b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org            return NULL;
1707481aef68333e01c19badda456d8e60bd1f1bee2avandebo@chromium.org        }
17086112c215fbdd53388e64ece36e6c7bba0fe3a451vandebo@chromium.org    }
1709769fa6a013baca6d7404e2bf096a34a7e3635fa5ctguil@chromium.org    // TODO(vandebo): Figure out how/if we can handle the following modes:
17103b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org    // Xor, Plus.
171125adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org
17123b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org    // Dst xfer mode doesn't draw source at all.
17133b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org    if (xfermode == SkXfermode::kDst_Mode) {
1714b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org        return NULL;
171525adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org    }
171625adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org
17179fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    ContentEntry* entry;
1718e02944075840d672bd1797f3d945ff82d302282fcommit-bot@chromium.org    SkAutoTDelete<ContentEntry> newEntry;
17198dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org
17208dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org    ContentEntry* lastContentEntry = getLastContentEntry();
17218dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org    if (lastContentEntry && lastContentEntry->fContent.getOffset() == 0) {
17228dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org        entry = lastContentEntry;
17239fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    } else {
17249fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org        newEntry.reset(new ContentEntry);
17259fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org        entry = newEntry.get();
17269fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    }
17279fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org
172878dad54080ad806be89adb5cc0e3c530b031cdafvandebo@chromium.org    populateGraphicStateEntryFromPaint(matrix, *clipStack, clipRegion, paint,
17299fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org                                       hasText, &entry->fState);
17308dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org    if (lastContentEntry && xfermode != SkXfermode::kDstOver_Mode &&
17318dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org            entry->fState.compareInitialState(lastContentEntry->fState)) {
17328dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org        return lastContentEntry;
17339fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    }
17349fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org
1735e02944075840d672bd1797f3d945ff82d302282fcommit-bot@chromium.org    SkAutoTDelete<ContentEntry>* contentEntries = getContentEntries();
17368dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org    if (!lastContentEntry) {
17379510ccc06bbfa5e888f66578042674be98d8ac60ctguil@chromium.org        contentEntries->reset(entry);
17388dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org        setLastContentEntry(entry);
173925adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org    } else if (xfermode == SkXfermode::kDstOver_Mode) {
1740e02944075840d672bd1797f3d945ff82d302282fcommit-bot@chromium.org        entry->fNext.reset(contentEntries->detach());
17419510ccc06bbfa5e888f66578042674be98d8ac60ctguil@chromium.org        contentEntries->reset(entry);
17429fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    } else {
17438dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org        lastContentEntry->fNext.reset(entry);
17448dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org        setLastContentEntry(entry);
17459fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    }
1746e02944075840d672bd1797f3d945ff82d302282fcommit-bot@chromium.org    newEntry.detach();
1747b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org    return entry;
17489fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org}
17499fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org
17507542dc8897d151afc0eca7dd73d72ea05f92baadcommit-bot@chromium.orgvoid SkPDFDevice::finishContentEntry(SkXfermode::Mode xfermode,
17513b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org                                     SkPDFFormXObject* dst,
17523b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org                                     SkPath* shape) {
17533b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org    if (xfermode != SkXfermode::kClear_Mode       &&
17543b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org            xfermode != SkXfermode::kSrc_Mode     &&
17557542dc8897d151afc0eca7dd73d72ea05f92baadcommit-bot@chromium.org            xfermode != SkXfermode::kDstOver_Mode &&
17563b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org            xfermode != SkXfermode::kSrcIn_Mode   &&
17573b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org            xfermode != SkXfermode::kDstIn_Mode   &&
17583b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org            xfermode != SkXfermode::kSrcOut_Mode  &&
17593b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org            xfermode != SkXfermode::kDstOut_Mode  &&
17603b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org            xfermode != SkXfermode::kSrcATop_Mode &&
17613b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org            xfermode != SkXfermode::kDstATop_Mode &&
17623b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org            xfermode != SkXfermode::kModulate_Mode) {
1763b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org        SkASSERT(!dst);
17646112c215fbdd53388e64ece36e6c7bba0fe3a451vandebo@chromium.org        return;
17656112c215fbdd53388e64ece36e6c7bba0fe3a451vandebo@chromium.org    }
17667542dc8897d151afc0eca7dd73d72ea05f92baadcommit-bot@chromium.org    if (xfermode == SkXfermode::kDstOver_Mode) {
17677542dc8897d151afc0eca7dd73d72ea05f92baadcommit-bot@chromium.org        SkASSERT(!dst);
17687542dc8897d151afc0eca7dd73d72ea05f92baadcommit-bot@chromium.org        ContentEntry* firstContentEntry = getContentEntries()->get();
17697542dc8897d151afc0eca7dd73d72ea05f92baadcommit-bot@chromium.org        if (firstContentEntry->fContent.getOffset() == 0) {
17707542dc8897d151afc0eca7dd73d72ea05f92baadcommit-bot@chromium.org            // For DstOver, an empty content entry was inserted before the rest
17717542dc8897d151afc0eca7dd73d72ea05f92baadcommit-bot@chromium.org            // of the content entries. If nothing was drawn, it needs to be
17727542dc8897d151afc0eca7dd73d72ea05f92baadcommit-bot@chromium.org            // removed.
17737542dc8897d151afc0eca7dd73d72ea05f92baadcommit-bot@chromium.org            SkAutoTDelete<ContentEntry>* contentEntries = getContentEntries();
17747542dc8897d151afc0eca7dd73d72ea05f92baadcommit-bot@chromium.org            contentEntries->reset(firstContentEntry->fNext.detach());
17757542dc8897d151afc0eca7dd73d72ea05f92baadcommit-bot@chromium.org        }
17767542dc8897d151afc0eca7dd73d72ea05f92baadcommit-bot@chromium.org        return;
17777542dc8897d151afc0eca7dd73d72ea05f92baadcommit-bot@chromium.org    }
17783b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org    if (!dst) {
17793b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org        SkASSERT(xfermode == SkXfermode::kSrc_Mode ||
17803b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org                 xfermode == SkXfermode::kSrcOut_Mode);
17813b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org        return;
17823b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org    }
17839510ccc06bbfa5e888f66578042674be98d8ac60ctguil@chromium.org
17849510ccc06bbfa5e888f66578042674be98d8ac60ctguil@chromium.org    ContentEntry* contentEntries = getContentEntries()->get();
1785b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org    SkASSERT(dst);
17868dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org    SkASSERT(!contentEntries->fNext.get());
17874e8f1e56b17c3663d1892f44a4c1893b568ce67fcommit-bot@chromium.org    // Changing the current content into a form-xobject will destroy the clip
17884e8f1e56b17c3663d1892f44a4c1893b568ce67fcommit-bot@chromium.org    // objects which is fine since the xobject will already be clipped. However
17894e8f1e56b17c3663d1892f44a4c1893b568ce67fcommit-bot@chromium.org    // if source has shape, we need to clip it too, so a copy of the clip is
17904e8f1e56b17c3663d1892f44a4c1893b568ce67fcommit-bot@chromium.org    // saved.
17918dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org    SkClipStack clipStack = contentEntries->fState.fClipStack;
17928dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org    SkRegion clipRegion = contentEntries->fState.fClipRegion;
1793481aef68333e01c19badda456d8e60bd1f1bee2avandebo@chromium.org
17947542dc8897d151afc0eca7dd73d72ea05f92baadcommit-bot@chromium.org    SkMatrix identity;
17957542dc8897d151afc0eca7dd73d72ea05f92baadcommit-bot@chromium.org    identity.reset();
17967542dc8897d151afc0eca7dd73d72ea05f92baadcommit-bot@chromium.org    SkPaint stockPaint;
17977542dc8897d151afc0eca7dd73d72ea05f92baadcommit-bot@chromium.org
1798fc641d09e5a1a9f7fae369ae06a8b96089faf57breed@google.com    SkAutoTUnref<SkPDFFormXObject> srcFormXObject;
17993b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org    if (isContentEmpty()) {
18007542dc8897d151afc0eca7dd73d72ea05f92baadcommit-bot@chromium.org        // If nothing was drawn and there's no shape, then the draw was a
18017542dc8897d151afc0eca7dd73d72ea05f92baadcommit-bot@chromium.org        // no-op, but dst needs to be restored for that to be true.
18027542dc8897d151afc0eca7dd73d72ea05f92baadcommit-bot@chromium.org        // If there is shape, then an empty source with Src, SrcIn, SrcOut,
18037542dc8897d151afc0eca7dd73d72ea05f92baadcommit-bot@chromium.org        // DstIn, DstAtop or Modulate reduces to Clear and DstOut or SrcAtop
18047542dc8897d151afc0eca7dd73d72ea05f92baadcommit-bot@chromium.org        // reduces to Dst.
18057542dc8897d151afc0eca7dd73d72ea05f92baadcommit-bot@chromium.org        if (shape == NULL || xfermode == SkXfermode::kDstOut_Mode ||
18067542dc8897d151afc0eca7dd73d72ea05f92baadcommit-bot@chromium.org                xfermode == SkXfermode::kSrcATop_Mode) {
18074e8f1e56b17c3663d1892f44a4c1893b568ce67fcommit-bot@chromium.org            ScopedContentEntry content(this, &fExistingClipStack,
18084e8f1e56b17c3663d1892f44a4c1893b568ce67fcommit-bot@chromium.org                                       fExistingClipRegion, identity,
18097542dc8897d151afc0eca7dd73d72ea05f92baadcommit-bot@chromium.org                                       stockPaint);
18107542dc8897d151afc0eca7dd73d72ea05f92baadcommit-bot@chromium.org            SkPDFUtils::DrawFormXObject(this->addXObjectResource(dst),
18117542dc8897d151afc0eca7dd73d72ea05f92baadcommit-bot@chromium.org                                        &content.entry()->fContent);
18127542dc8897d151afc0eca7dd73d72ea05f92baadcommit-bot@chromium.org            return;
18137542dc8897d151afc0eca7dd73d72ea05f92baadcommit-bot@chromium.org        } else {
18147542dc8897d151afc0eca7dd73d72ea05f92baadcommit-bot@chromium.org            xfermode = SkXfermode::kClear_Mode;
18157542dc8897d151afc0eca7dd73d72ea05f92baadcommit-bot@chromium.org        }
18163b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org    } else {
18173b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org        SkASSERT(!fContentEntries->fNext.get());
1818fc641d09e5a1a9f7fae369ae06a8b96089faf57breed@google.com        srcFormXObject.reset(createFormXObjectFromDevice());
1819481aef68333e01c19badda456d8e60bd1f1bee2avandebo@chromium.org    }
1820481aef68333e01c19badda456d8e60bd1f1bee2avandebo@chromium.org
18213b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org    // TODO(vandebo) srcFormXObject may contain alpha, but here we want it
18223b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org    // without alpha.
18233b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org    if (xfermode == SkXfermode::kSrcATop_Mode) {
18243b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org        // TODO(vandebo): In order to properly support SrcATop we have to track
18253b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org        // the shape of what's been drawn at all times. It's the intersection of
18263b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org        // the non-transparent parts of the device and the outlines (shape) of
18273b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org        // all images and devices drawn.
18283b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org        drawFormXObjectWithMask(addXObjectResource(srcFormXObject.get()), dst,
18294e8f1e56b17c3663d1892f44a4c1893b568ce67fcommit-bot@chromium.org                                &fExistingClipStack, fExistingClipRegion,
18303b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org                                SkXfermode::kSrcOver_Mode, true);
18313b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org    } else {
18323b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org        SkAutoTUnref<SkPDFFormXObject> dstMaskStorage;
18333b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org        SkPDFFormXObject* dstMask = srcFormXObject.get();
18343b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org        if (shape != NULL) {
18353b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org            // Draw shape into a form-xobject.
18363b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org            SkDraw d;
18373b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org            d.fMatrix = &identity;
18383b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org            d.fClip = &clipRegion;
18393b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org            d.fClipStack = &clipStack;
18403b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org            SkPaint filledPaint;
18413b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org            filledPaint.setColor(SK_ColorBLACK);
18423b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org            filledPaint.setStyle(SkPaint::kFill_Style);
18433b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org            this->drawPath(d, *shape, filledPaint, NULL, true);
18443b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org
18453b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org            dstMaskStorage.reset(createFormXObjectFromDevice());
18463b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org            dstMask = dstMaskStorage.get();
18473b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org        }
18484e8f1e56b17c3663d1892f44a4c1893b568ce67fcommit-bot@chromium.org        drawFormXObjectWithMask(addXObjectResource(dst), dstMask,
18494e8f1e56b17c3663d1892f44a4c1893b568ce67fcommit-bot@chromium.org                                &fExistingClipStack, fExistingClipRegion,
18504e8f1e56b17c3663d1892f44a4c1893b568ce67fcommit-bot@chromium.org                                SkXfermode::kSrcOver_Mode, true);
1851481aef68333e01c19badda456d8e60bd1f1bee2avandebo@chromium.org    }
18526112c215fbdd53388e64ece36e6c7bba0fe3a451vandebo@chromium.org
18537542dc8897d151afc0eca7dd73d72ea05f92baadcommit-bot@chromium.org    if (xfermode == SkXfermode::kClear_Mode) {
18543b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org        return;
18553b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org    } else if (xfermode == SkXfermode::kSrc_Mode ||
18563b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org            xfermode == SkXfermode::kDstATop_Mode) {
18574e8f1e56b17c3663d1892f44a4c1893b568ce67fcommit-bot@chromium.org        ScopedContentEntry content(this, &fExistingClipStack,
18584e8f1e56b17c3663d1892f44a4c1893b568ce67fcommit-bot@chromium.org                                   fExistingClipRegion, identity, stockPaint);
18593b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org        if (content.entry()) {
18603b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org            SkPDFUtils::DrawFormXObject(
18613b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org                    this->addXObjectResource(srcFormXObject.get()),
18623b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org                    &content.entry()->fContent);
18633b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org        }
18643b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org        if (xfermode == SkXfermode::kSrc_Mode) {
18653b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org            return;
18663b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org        }
18677542dc8897d151afc0eca7dd73d72ea05f92baadcommit-bot@chromium.org    } else if (xfermode == SkXfermode::kSrcATop_Mode) {
18684e8f1e56b17c3663d1892f44a4c1893b568ce67fcommit-bot@chromium.org        ScopedContentEntry content(this, &fExistingClipStack,
18694e8f1e56b17c3663d1892f44a4c1893b568ce67fcommit-bot@chromium.org                                   fExistingClipRegion, identity, stockPaint);
18707542dc8897d151afc0eca7dd73d72ea05f92baadcommit-bot@chromium.org        if (content.entry()) {
18717542dc8897d151afc0eca7dd73d72ea05f92baadcommit-bot@chromium.org            SkPDFUtils::DrawFormXObject(this->addXObjectResource(dst),
18727542dc8897d151afc0eca7dd73d72ea05f92baadcommit-bot@chromium.org                                        &content.entry()->fContent);
18737542dc8897d151afc0eca7dd73d72ea05f92baadcommit-bot@chromium.org        }
18743b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org    }
18753b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org
18763b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org    SkASSERT(xfermode == SkXfermode::kSrcIn_Mode   ||
18773b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org             xfermode == SkXfermode::kDstIn_Mode   ||
18783b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org             xfermode == SkXfermode::kSrcOut_Mode  ||
18793b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org             xfermode == SkXfermode::kDstOut_Mode  ||
18803b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org             xfermode == SkXfermode::kSrcATop_Mode ||
18813b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org             xfermode == SkXfermode::kDstATop_Mode ||
18823b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org             xfermode == SkXfermode::kModulate_Mode);
18833b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org
18846112c215fbdd53388e64ece36e6c7bba0fe3a451vandebo@chromium.org    if (xfermode == SkXfermode::kSrcIn_Mode ||
18853b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org            xfermode == SkXfermode::kSrcOut_Mode ||
18863b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org            xfermode == SkXfermode::kSrcATop_Mode) {
18873b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org        drawFormXObjectWithMask(addXObjectResource(srcFormXObject.get()), dst,
18884e8f1e56b17c3663d1892f44a4c1893b568ce67fcommit-bot@chromium.org                                &fExistingClipStack, fExistingClipRegion,
18893b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org                                SkXfermode::kSrcOver_Mode,
18903b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org                                xfermode == SkXfermode::kSrcOut_Mode);
18916112c215fbdd53388e64ece36e6c7bba0fe3a451vandebo@chromium.org    } else {
18923b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org        SkXfermode::Mode mode = SkXfermode::kSrcOver_Mode;
18933b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org        if (xfermode == SkXfermode::kModulate_Mode) {
18943b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org            drawFormXObjectWithMask(addXObjectResource(srcFormXObject.get()),
18954e8f1e56b17c3663d1892f44a4c1893b568ce67fcommit-bot@chromium.org                                    dst, &fExistingClipStack,
18964e8f1e56b17c3663d1892f44a4c1893b568ce67fcommit-bot@chromium.org                                    fExistingClipRegion,
18973b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org                                    SkXfermode::kSrcOver_Mode, false);
18983b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org            mode = SkXfermode::kMultiply_Mode;
18993b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org        }
19003b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org        drawFormXObjectWithMask(addXObjectResource(dst), srcFormXObject.get(),
19014e8f1e56b17c3663d1892f44a4c1893b568ce67fcommit-bot@chromium.org                                &fExistingClipStack, fExistingClipRegion, mode,
19023b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org                                xfermode == SkXfermode::kDstOut_Mode);
19036112c215fbdd53388e64ece36e6c7bba0fe3a451vandebo@chromium.org    }
19046112c215fbdd53388e64ece36e6c7bba0fe3a451vandebo@chromium.org}
19056112c215fbdd53388e64ece36e6c7bba0fe3a451vandebo@chromium.org
1906481aef68333e01c19badda456d8e60bd1f1bee2avandebo@chromium.orgbool SkPDFDevice::isContentEmpty() {
19079510ccc06bbfa5e888f66578042674be98d8ac60ctguil@chromium.org    ContentEntry* contentEntries = getContentEntries()->get();
19089510ccc06bbfa5e888f66578042674be98d8ac60ctguil@chromium.org    if (!contentEntries || contentEntries->fContent.getOffset() == 0) {
19099510ccc06bbfa5e888f66578042674be98d8ac60ctguil@chromium.org        SkASSERT(!contentEntries || !contentEntries->fNext.get());
1910481aef68333e01c19badda456d8e60bd1f1bee2avandebo@chromium.org        return true;
1911481aef68333e01c19badda456d8e60bd1f1bee2avandebo@chromium.org    }
1912481aef68333e01c19badda456d8e60bd1f1bee2avandebo@chromium.org    return false;
1913481aef68333e01c19badda456d8e60bd1f1bee2avandebo@chromium.org}
1914481aef68333e01c19badda456d8e60bd1f1bee2avandebo@chromium.org
19159fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.orgvoid SkPDFDevice::populateGraphicStateEntryFromPaint(
19169fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org        const SkMatrix& matrix,
19179fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org        const SkClipStack& clipStack,
19189fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org        const SkRegion& clipRegion,
19199fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org        const SkPaint& paint,
19209fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org        bool hasText,
19219fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org        GraphicStateEntry* entry) {
19226f4e473676ff5c32c06151f4f8451d62715d65d2reed@google.com    NOT_IMPLEMENTED(paint.getPathEffect() != NULL, false);
1923da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org    NOT_IMPLEMENTED(paint.getMaskFilter() != NULL, false);
1924da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org    NOT_IMPLEMENTED(paint.getColorFilter() != NULL, false);
19259b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org
19269fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    entry->fMatrix = matrix;
19279fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    entry->fClipStack = clipStack;
19289fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    entry->fClipRegion = clipRegion;
1929da6c569334b5971e55dc95cb9bf85853d068e999vandebo@chromium.org    entry->fColor = SkColorSetA(paint.getColor(), 0xFF);
1930da6c569334b5971e55dc95cb9bf85853d068e999vandebo@chromium.org    entry->fShaderIndex = -1;
193148543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org
1932da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org    // PDF treats a shader as a color, so we only set one or the other.
1933d96d17b9c113ac694138224249ff2ce643e961ddvandebo@chromium.org    SkAutoTUnref<SkPDFObject> pdfShader;
19349fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    const SkShader* shader = paint.getShader();
19359fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    SkColor color = paint.getColor();
1936da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org    if (shader) {
1937da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org        // PDF positions patterns relative to the initial transform, so
1938da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org        // we need to apply the current transform to the shader parameters.
19399fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org        SkMatrix transform = matrix;
194075f97e452e8f2ee55cd2b283df7d7734f48bc2bfvandebo@chromium.org        transform.postConcat(fInitialTransform);
1941da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org
1942da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org        // PDF doesn't support kClamp_TileMode, so we simulate it by making
19439fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org        // a pattern the size of the current clip.
1944b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org        SkIRect bounds = clipRegion.getBounds();
1945293a758929222b6003678c6a49bfbb2f2f806e8evandebo@chromium.org
1946293a758929222b6003678c6a49bfbb2f2f806e8evandebo@chromium.org        // We need to apply the initial transform to bounds in order to get
1947293a758929222b6003678c6a49bfbb2f2f806e8evandebo@chromium.org        // bounds in a consistent coordinate system.
1948293a758929222b6003678c6a49bfbb2f2f806e8evandebo@chromium.org        SkRect boundsTemp;
1949293a758929222b6003678c6a49bfbb2f2f806e8evandebo@chromium.org        boundsTemp.set(bounds);
1950293a758929222b6003678c6a49bfbb2f2f806e8evandebo@chromium.org        fInitialTransform.mapRect(&boundsTemp);
1951293a758929222b6003678c6a49bfbb2f2f806e8evandebo@chromium.org        boundsTemp.roundOut(&bounds);
1952293a758929222b6003678c6a49bfbb2f2f806e8evandebo@chromium.org
1953792c80f5a7b66e75d42664ccb298f31962c6654chalcanary        SkScalar rasterScale =
1954792c80f5a7b66e75d42664ccb298f31962c6654chalcanary                SkIntToScalar(fRasterDpi) / DPI_FOR_RASTER_SCALE_ONE;
1955792c80f5a7b66e75d42664ccb298f31962c6654chalcanary        pdfShader.reset(SkPDFShader::GetPDFShader(
1956792c80f5a7b66e75d42664ccb298f31962c6654chalcanary                fCanon, fRasterDpi, *shader, transform, bounds, rasterScale));
1957da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org
1958b88cfe58e117ffe781e4ce2cba73cc4f7a795de7vandebo@chromium.org        if (pdfShader.get()) {
1959b88cfe58e117ffe781e4ce2cba73cc4f7a795de7vandebo@chromium.org            // pdfShader has been canonicalized so we can directly compare
1960b88cfe58e117ffe781e4ce2cba73cc4f7a795de7vandebo@chromium.org            // pointers.
1961b88cfe58e117ffe781e4ce2cba73cc4f7a795de7vandebo@chromium.org            int resourceIndex = fShaderResources.find(pdfShader.get());
1962b88cfe58e117ffe781e4ce2cba73cc4f7a795de7vandebo@chromium.org            if (resourceIndex < 0) {
1963b88cfe58e117ffe781e4ce2cba73cc4f7a795de7vandebo@chromium.org                resourceIndex = fShaderResources.count();
1964b88cfe58e117ffe781e4ce2cba73cc4f7a795de7vandebo@chromium.org                fShaderResources.push(pdfShader.get());
1965d96d17b9c113ac694138224249ff2ce643e961ddvandebo@chromium.org                pdfShader.get()->ref();
1966b88cfe58e117ffe781e4ce2cba73cc4f7a795de7vandebo@chromium.org            }
1967b88cfe58e117ffe781e4ce2cba73cc4f7a795de7vandebo@chromium.org            entry->fShaderIndex = resourceIndex;
1968b88cfe58e117ffe781e4ce2cba73cc4f7a795de7vandebo@chromium.org        } else {
1969b88cfe58e117ffe781e4ce2cba73cc4f7a795de7vandebo@chromium.org            // A color shader is treated as an invalid shader so we don't have
1970b88cfe58e117ffe781e4ce2cba73cc4f7a795de7vandebo@chromium.org            // to set a shader just for a color.
1971da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org            SkShader::GradientInfo gradientInfo;
1972da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org            SkColor gradientColor;
1973da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org            gradientInfo.fColors = &gradientColor;
1974da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org            gradientInfo.fColorOffsets = NULL;
1975da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org            gradientInfo.fColorCount = 1;
1976da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org            if (shader->asAGradient(&gradientInfo) ==
1977da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org                    SkShader::kColor_GradientType) {
19789fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org                entry->fColor = SkColorSetA(gradientColor, 0xFF);
19799fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org                color = gradientColor;
1980da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org            }
1981da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org        }
1982da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org    }
19839b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org
1984d96d17b9c113ac694138224249ff2ce643e961ddvandebo@chromium.org    SkAutoTUnref<SkPDFGraphicState> newGraphicState;
19859fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    if (color == paint.getColor()) {
1986d96d17b9c113ac694138224249ff2ce643e961ddvandebo@chromium.org        newGraphicState.reset(
1987792c80f5a7b66e75d42664ccb298f31962c6654chalcanary                SkPDFGraphicState::GetGraphicStateForPaint(fCanon, paint));
19889fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    } else {
19899fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org        SkPaint newPaint = paint;
19909fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org        newPaint.setColor(color);
1991d96d17b9c113ac694138224249ff2ce643e961ddvandebo@chromium.org        newGraphicState.reset(
1992792c80f5a7b66e75d42664ccb298f31962c6654chalcanary                SkPDFGraphicState::GetGraphicStateForPaint(fCanon, newPaint));
19939fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    }
19946112c215fbdd53388e64ece36e6c7bba0fe3a451vandebo@chromium.org    int resourceIndex = addGraphicStateResource(newGraphicState.get());
19959fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    entry->fGraphicStateIndex = resourceIndex;
199628be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org
19979fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    if (hasText) {
19989fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org        entry->fTextScaleX = paint.getTextScaleX();
19999fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org        entry->fTextFill = paint.getStyle();
20009fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    } else {
20019fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org        entry->fTextScaleX = 0;
20029b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org    }
20039b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org}
20049b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org
2005be27a118c277af23377d38e9b3bfd3fcc276114fhalcanaryint SkPDFDevice::addGraphicStateResource(SkPDFObject* gs) {
20066112c215fbdd53388e64ece36e6c7bba0fe3a451vandebo@chromium.org    // Assumes that gs has been canonicalized (so we can directly compare
20076112c215fbdd53388e64ece36e6c7bba0fe3a451vandebo@chromium.org    // pointers).
20086112c215fbdd53388e64ece36e6c7bba0fe3a451vandebo@chromium.org    int result = fGraphicStateResources.find(gs);
20096112c215fbdd53388e64ece36e6c7bba0fe3a451vandebo@chromium.org    if (result < 0) {
20106112c215fbdd53388e64ece36e6c7bba0fe3a451vandebo@chromium.org        result = fGraphicStateResources.count();
20116112c215fbdd53388e64ece36e6c7bba0fe3a451vandebo@chromium.org        fGraphicStateResources.push(gs);
20126112c215fbdd53388e64ece36e6c7bba0fe3a451vandebo@chromium.org        gs->ref();
20136112c215fbdd53388e64ece36e6c7bba0fe3a451vandebo@chromium.org    }
20146112c215fbdd53388e64ece36e6c7bba0fe3a451vandebo@chromium.org    return result;
20156112c215fbdd53388e64ece36e6c7bba0fe3a451vandebo@chromium.org}
20166112c215fbdd53388e64ece36e6c7bba0fe3a451vandebo@chromium.org
20173b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.orgint SkPDFDevice::addXObjectResource(SkPDFObject* xObject) {
20183b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org    // Assumes that xobject has been canonicalized (so we can directly compare
20193b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org    // pointers).
20203b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org    int result = fXObjectResources.find(xObject);
20213b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org    if (result < 0) {
20223b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org        result = fXObjectResources.count();
20233b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org        fXObjectResources.push(xObject);
20243b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org        xObject->ref();
20253b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org    }
20263b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org    return result;
20273b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org}
20283b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org
2029b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.orgvoid SkPDFDevice::updateFont(const SkPaint& paint, uint16_t glyphID,
2030b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org                             ContentEntry* contentEntry) {
20319db86bb9cd1b77be0afc504ccc07026e4282d7e7ctguil@chromium.org    SkTypeface* typeface = paint.getTypeface();
2032b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org    if (contentEntry->fState.fFont == NULL ||
2033b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org            contentEntry->fState.fTextSize != paint.getTextSize() ||
2034b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org            !contentEntry->fState.fFont->hasGlyph(glyphID)) {
20359db86bb9cd1b77be0afc504ccc07026e4282d7e7ctguil@chromium.org        int fontIndex = getFontResourceIndex(typeface, glyphID);
203647401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org        contentEntry->fContent.writeText("/");
203747401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org        contentEntry->fContent.writeText(SkPDFResourceDict::getResourceName(
203847401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org                SkPDFResourceDict::kFont_ResourceType,
203947401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org                fontIndex).c_str());
2040b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org        contentEntry->fContent.writeText(" ");
2041bc4696b9176e05940a7c2d6778276cdbc55ccd61halcanary        SkPDFUtils::AppendScalar(paint.getTextSize(), &contentEntry->fContent);
2042b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org        contentEntry->fContent.writeText(" Tf\n");
2043b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org        contentEntry->fState.fFont = fFontResources[fontIndex];
20442a22e10ab2946c5590cd2a258427ce3ccfca9bfavandebo@chromium.org    }
20452a22e10ab2946c5590cd2a258427ce3ccfca9bfavandebo@chromium.org}
20462a22e10ab2946c5590cd2a258427ce3ccfca9bfavandebo@chromium.org
20479db86bb9cd1b77be0afc504ccc07026e4282d7e7ctguil@chromium.orgint SkPDFDevice::getFontResourceIndex(SkTypeface* typeface, uint16_t glyphID) {
2048792c80f5a7b66e75d42664ccb298f31962c6654chalcanary    SkAutoTUnref<SkPDFFont> newFont(
2049792c80f5a7b66e75d42664ccb298f31962c6654chalcanary            SkPDFFont::GetFontResource(fCanon, typeface, glyphID));
205028be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org    int resourceIndex = fFontResources.find(newFont.get());
205128be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org    if (resourceIndex < 0) {
205228be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org        resourceIndex = fFontResources.count();
205328be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org        fFontResources.push(newFont.get());
2054d96d17b9c113ac694138224249ff2ce643e961ddvandebo@chromium.org        newFont.get()->ref();
205528be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org    }
205628be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org    return resourceIndex;
205728be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org}
205828be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org
20599cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.comvoid SkPDFDevice::internalDrawBitmap(const SkMatrix& origMatrix,
206078dad54080ad806be89adb5cc0e3c530b031cdafvandebo@chromium.org                                     const SkClipStack* clipStack,
20619cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com                                     const SkRegion& origClipRegion,
20629cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com                                     const SkBitmap& origBitmap,
2063befebb8a8437ce69e3a416b417cb27b66273128dvandebo@chromium.org                                     const SkIRect* srcRect,
20649b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org                                     const SkPaint& paint) {
20659cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com    SkMatrix matrix = origMatrix;
20669cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com    SkRegion perspectiveBounds;
20679cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com    const SkRegion* clipRegion = &origClipRegion;
20689cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com    SkBitmap perspectiveBitmap;
20699cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com    const SkBitmap* bitmap = &origBitmap;
20709cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com    SkBitmap tmpSubsetBitmap;
20719cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com
20729cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com    // Rasterize the bitmap using perspective in a new bitmap.
20739cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com    if (origMatrix.hasPerspective()) {
207473a7ea3ae0d37ee28f90d6b38c49fda052638253edisonn@google.com        if (fRasterDpi == 0) {
207573a7ea3ae0d37ee28f90d6b38c49fda052638253edisonn@google.com            return;
207673a7ea3ae0d37ee28f90d6b38c49fda052638253edisonn@google.com        }
20779cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com        SkBitmap* subsetBitmap;
20789cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com        if (srcRect) {
20799cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com            if (!origBitmap.extractSubset(&tmpSubsetBitmap, *srcRect)) {
20809cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com               return;
20819cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com            }
20829cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com            subsetBitmap = &tmpSubsetBitmap;
20839cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com        } else {
20849cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com            subsetBitmap = &tmpSubsetBitmap;
20859cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com            *subsetBitmap = origBitmap;
20869cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com        }
20879cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com        srcRect = NULL;
20889cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com
208973a7ea3ae0d37ee28f90d6b38c49fda052638253edisonn@google.com        // Transform the bitmap in the new space, without taking into
209073a7ea3ae0d37ee28f90d6b38c49fda052638253edisonn@google.com        // account the initial transform.
20919cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com        SkPath perspectiveOutline;
20929cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com        perspectiveOutline.addRect(
20939cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com                SkRect::MakeWH(SkIntToScalar(subsetBitmap->width()),
20949cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com                               SkIntToScalar(subsetBitmap->height())));
20959cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com        perspectiveOutline.transform(origMatrix);
20969cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com
20979cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com        // TODO(edisonn): perf - use current clip too.
20989cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com        // Retrieve the bounds of the new shape.
20999cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com        SkRect bounds = perspectiveOutline.getBounds();
21009cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com
210173a7ea3ae0d37ee28f90d6b38c49fda052638253edisonn@google.com        // Transform the bitmap in the new space, taking into
210273a7ea3ae0d37ee28f90d6b38c49fda052638253edisonn@google.com        // account the initial transform.
210373a7ea3ae0d37ee28f90d6b38c49fda052638253edisonn@google.com        SkMatrix total = origMatrix;
210473a7ea3ae0d37ee28f90d6b38c49fda052638253edisonn@google.com        total.postConcat(fInitialTransform);
210573a7ea3ae0d37ee28f90d6b38c49fda052638253edisonn@google.com        total.postScale(SkIntToScalar(fRasterDpi) /
210673a7ea3ae0d37ee28f90d6b38c49fda052638253edisonn@google.com                            SkIntToScalar(DPI_FOR_RASTER_SCALE_ONE),
210773a7ea3ae0d37ee28f90d6b38c49fda052638253edisonn@google.com                        SkIntToScalar(fRasterDpi) /
210873a7ea3ae0d37ee28f90d6b38c49fda052638253edisonn@google.com                            SkIntToScalar(DPI_FOR_RASTER_SCALE_ONE));
210973a7ea3ae0d37ee28f90d6b38c49fda052638253edisonn@google.com        SkPath physicalPerspectiveOutline;
211073a7ea3ae0d37ee28f90d6b38c49fda052638253edisonn@google.com        physicalPerspectiveOutline.addRect(
211173a7ea3ae0d37ee28f90d6b38c49fda052638253edisonn@google.com                SkRect::MakeWH(SkIntToScalar(subsetBitmap->width()),
211273a7ea3ae0d37ee28f90d6b38c49fda052638253edisonn@google.com                               SkIntToScalar(subsetBitmap->height())));
211373a7ea3ae0d37ee28f90d6b38c49fda052638253edisonn@google.com        physicalPerspectiveOutline.transform(total);
211473a7ea3ae0d37ee28f90d6b38c49fda052638253edisonn@google.com
211573a7ea3ae0d37ee28f90d6b38c49fda052638253edisonn@google.com        SkScalar scaleX = physicalPerspectiveOutline.getBounds().width() /
211673a7ea3ae0d37ee28f90d6b38c49fda052638253edisonn@google.com                              bounds.width();
211773a7ea3ae0d37ee28f90d6b38c49fda052638253edisonn@google.com        SkScalar scaleY = physicalPerspectiveOutline.getBounds().height() /
211873a7ea3ae0d37ee28f90d6b38c49fda052638253edisonn@google.com                              bounds.height();
21199cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com
21209cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com        // TODO(edisonn): A better approach would be to use a bitmap shader
21219cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com        // (in clamp mode) and draw a rect over the entire bounding box. Then
21229cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com        // intersect perspectiveOutline to the clip. That will avoid introducing
21239cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com        // alpha to the image while still giving good behavior at the edge of
21249cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com        // the image.  Avoiding alpha will reduce the pdf size and generation
21259cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com        // CPU time some.
21269cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com
21279ebcac54635cde63110d73ad7c43d70772e7872freed@google.com        const int w = SkScalarCeilToInt(physicalPerspectiveOutline.getBounds().width());
21289ebcac54635cde63110d73ad7c43d70772e7872freed@google.com        const int h = SkScalarCeilToInt(physicalPerspectiveOutline.getBounds().height());
2129848250415eddc54075f7eb8795e8db79e749c6abreed        if (!perspectiveBitmap.tryAllocN32Pixels(w, h)) {
21309ebcac54635cde63110d73ad7c43d70772e7872freed@google.com            return;
21319ebcac54635cde63110d73ad7c43d70772e7872freed@google.com        }
21329cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com        perspectiveBitmap.eraseColor(SK_ColorTRANSPARENT);
21339cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com
213489443aba5bfa2b040dc9fd24938b7d0b3decd737reed        SkCanvas canvas(perspectiveBitmap);
21359cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com
21369cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com        SkScalar deltaX = bounds.left();
21379cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com        SkScalar deltaY = bounds.top();
21389cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com
21399cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com        SkMatrix offsetMatrix = origMatrix;
21409cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com        offsetMatrix.postTranslate(-deltaX, -deltaY);
214173a7ea3ae0d37ee28f90d6b38c49fda052638253edisonn@google.com        offsetMatrix.postScale(scaleX, scaleY);
21429cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com
21439cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com        // Translate the draw in the new canvas, so we perfectly fit the
21449cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com        // shape in the bitmap.
21459cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com        canvas.setMatrix(offsetMatrix);
21469cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com
21479cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com        canvas.drawBitmap(*subsetBitmap, SkIntToScalar(0), SkIntToScalar(0));
21489cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com
21499cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com        // Make sure the final bits are in the bitmap.
21509cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com        canvas.flush();
21519cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com
215273a7ea3ae0d37ee28f90d6b38c49fda052638253edisonn@google.com        // In the new space, we use the identity matrix translated
215373a7ea3ae0d37ee28f90d6b38c49fda052638253edisonn@google.com        // and scaled to reflect DPI.
215473a7ea3ae0d37ee28f90d6b38c49fda052638253edisonn@google.com        matrix.setScale(1 / scaleX, 1 / scaleY);
215573a7ea3ae0d37ee28f90d6b38c49fda052638253edisonn@google.com        matrix.postTranslate(deltaX, deltaY);
215673a7ea3ae0d37ee28f90d6b38c49fda052638253edisonn@google.com
21579cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com        perspectiveBounds.setRect(
21589cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com                SkIRect::MakeXYWH(SkScalarFloorToInt(bounds.x()),
21599cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com                                  SkScalarFloorToInt(bounds.y()),
21609cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com                                  SkScalarCeilToInt(bounds.width()),
21619cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com                                  SkScalarCeilToInt(bounds.height())));
21629cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com        clipRegion = &perspectiveBounds;
21639cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com        srcRect = NULL;
21649cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com        bitmap = &perspectiveBitmap;
21659cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com    }
21669cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com
21677e2ff7cf7da604b29378978ef5d4655499485368vandebo@chromium.org    SkMatrix scaled;
21687e2ff7cf7da604b29378978ef5d4655499485368vandebo@chromium.org    // Adjust for origin flip.
2169663515bc59325092c4e47f5189782bd6fcd0586avandebo@chromium.org    scaled.setScale(SK_Scalar1, -SK_Scalar1);
2170663515bc59325092c4e47f5189782bd6fcd0586avandebo@chromium.org    scaled.postTranslate(0, SK_Scalar1);
21717e2ff7cf7da604b29378978ef5d4655499485368vandebo@chromium.org    // Scale the image up from 1x1 to WxH.
2172f622a6c8fd176acf9944de8df00d7f0bb56b67d3halcanary    SkIRect subset = bitmap->bounds();
2173a6d59f60aab59fb6556841b063ead5d49b46ba8dreed@google.com    scaled.postScale(SkIntToScalar(subset.width()),
2174a6d59f60aab59fb6556841b063ead5d49b46ba8dreed@google.com                     SkIntToScalar(subset.height()));
21757e2ff7cf7da604b29378978ef5d4655499485368vandebo@chromium.org    scaled.postConcat(matrix);
21769cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com    ScopedContentEntry content(this, clipStack, *clipRegion, scaled, paint);
21773b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org    if (!content.entry() || (srcRect && !subset.intersect(*srcRect))) {
217825adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org        return;
217925adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org    }
21803b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org    if (content.needShape()) {
21813b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org        SkPath shape;
2182fd3c8c243ab190604e134910a1d6c1326d21e374vandebo@chromium.org        shape.addRect(SkRect::MakeWH(SkIntToScalar(subset.width()),
2183db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary                                     SkIntToScalar(subset.height())));
21843b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org        shape.transform(matrix);
21853b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org        content.setShape(shape);
21863b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org    }
21873b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org    if (!content.needSource()) {
218825adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org        return;
218925adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org    }
219025adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org
2191db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary    SkBitmap subsetBitmap;
2192db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary    // Should extractSubset be done by the SkPDFDevice?
2193db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary    if (!bitmap->extractSubset(&subsetBitmap, subset)) {
2194db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary        return;
2195db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary    }
2196db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary    SkAutoTUnref<SkPDFObject> image(SkPDFBitmap::Create(fCanon, subsetBitmap));
219725adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org    if (!image) {
219825adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org        return;
219925adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org    }
22007e2ff7cf7da604b29378978ef5d4655499485368vandebo@chromium.org
22013b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org    SkPDFUtils::DrawFormXObject(this->addXObjectResource(image.get()),
2202b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org                                &content.entry()->fContent);
22039b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org}
2204