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