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" 11c38dee4f2c4cac24fa926a51069f04df272b1516Stephen White#include "SkBitmapDevice.h" 129b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org#include "SkColor.h" 139fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org#include "SkClipStack.h" 148a85d0c4938173476d037d7af0ee3b9436a1234ereed@google.com#include "SkData.h" 15fb0b0edd86d71bb423fa921eaac1e2071602115cvandebo@chromium.org#include "SkDraw.h" 164e1cc6ac450903510b96c1b12f6ee6f420044a66vandebo@chromium.org#include "SkFontHost.h" 1728be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org#include "SkGlyphCache.h" 189b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org#include "SkPaint.h" 19a518086928494319b8968abc09808eff492c194fvandebo@chromium.org#include "SkPath.h" 2092ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org#include "SkPathOps.h" 2128be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org#include "SkPDFFont.h" 22eb6c7596af1a1fc7860e27ff2f678a33b2576c0fvandebo@chromium.org#include "SkPDFFormXObject.h" 2377bcaa324a574584331322d98768582d9232f7fcvandebo@chromium.org#include "SkPDFGraphicState.h" 2477bcaa324a574584331322d98768582d9232f7fcvandebo@chromium.org#include "SkPDFImage.h" 2547401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org#include "SkPDFResourceDict.h" 26da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org#include "SkPDFShader.h" 279b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org#include "SkPDFStream.h" 2877bcaa324a574584331322d98768582d9232f7fcvandebo@chromium.org#include "SkPDFTypes.h" 299db86bb9cd1b77be0afc504ccc07026e4282d7e7ctguil@chromium.org#include "SkPDFUtils.h" 309b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org#include "SkRect.h" 31a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com#include "SkRRect.h" 329b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org#include "SkString.h" 3389443aba5bfa2b040dc9fd24938b7d0b3decd737reed#include "SkSurface.h" 3428be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org#include "SkTextFormatParams.h" 354e1cc6ac450903510b96c1b12f6ee6f420044a66vandebo@chromium.org#include "SkTemplates.h" 36fed86bdb8b9f037439bbfa7cdbd53a581dbc5985reed@google.com#include "SkTypefacePriv.h" 376addb1930013ebb2f984045141650fd7afcfa90fedisonn@google.com#include "SkTSet.h" 389b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org 3973a7ea3ae0d37ee28f90d6b38c49fda052638253edisonn@google.com#define DPI_FOR_RASTER_SCALE_ONE 72 4073a7ea3ae0d37ee28f90d6b38c49fda052638253edisonn@google.com 419b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org// Utility functions 429b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org 439fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.orgstatic void emit_pdf_color(SkColor color, SkWStream* result) { 449b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org SkASSERT(SkColorGetA(color) == 0xFF); // We handle alpha elsewhere. 459b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org SkScalar colorMax = SkIntToScalar(0xFF); 46094316bd284372c2a3d8ef02eec589901e503c59vandebo@chromium.org SkPDFScalar::Append( 47cae5fba82e687d674b076b10cdc8aba46e1ac3b3vandebo@chromium.org SkScalarDiv(SkIntToScalar(SkColorGetR(color)), colorMax), result); 48cae5fba82e687d674b076b10cdc8aba46e1ac3b3vandebo@chromium.org result->writeText(" "); 49094316bd284372c2a3d8ef02eec589901e503c59vandebo@chromium.org SkPDFScalar::Append( 50cae5fba82e687d674b076b10cdc8aba46e1ac3b3vandebo@chromium.org SkScalarDiv(SkIntToScalar(SkColorGetG(color)), colorMax), result); 51cae5fba82e687d674b076b10cdc8aba46e1ac3b3vandebo@chromium.org result->writeText(" "); 52094316bd284372c2a3d8ef02eec589901e503c59vandebo@chromium.org SkPDFScalar::Append( 53cae5fba82e687d674b076b10cdc8aba46e1ac3b3vandebo@chromium.org SkScalarDiv(SkIntToScalar(SkColorGetB(color)), colorMax), result); 54cae5fba82e687d674b076b10cdc8aba46e1ac3b3vandebo@chromium.org result->writeText(" "); 559b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org} 569b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org 579fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.orgstatic SkPaint calculate_text_paint(const SkPaint& paint) { 5828be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org SkPaint result = paint; 5928be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org if (result.isFakeBoldText()) { 6028be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org SkScalar fakeBoldScale = SkScalarInterpFunc(result.getTextSize(), 6128be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org kStdFakeBoldInterpKeys, 6228be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org kStdFakeBoldInterpValues, 6328be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org kStdFakeBoldInterpLength); 6428be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org SkScalar width = SkScalarMul(result.getTextSize(), fakeBoldScale); 65769fa6a013baca6d7404e2bf096a34a7e3635fa5ctguil@chromium.org if (result.getStyle() == SkPaint::kFill_Style) { 6628be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org result.setStyle(SkPaint::kStrokeAndFill_Style); 67769fa6a013baca6d7404e2bf096a34a7e3635fa5ctguil@chromium.org } else { 6828be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org width += result.getStrokeWidth(); 69769fa6a013baca6d7404e2bf096a34a7e3635fa5ctguil@chromium.org } 7028be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org result.setStrokeWidth(width); 7128be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org } 7228be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org return result; 7328be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org} 7428be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org 7528be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org// Stolen from measure_text in SkDraw.cpp and then tweaked. 769fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.orgstatic void align_text(SkDrawCacheProc glyphCacheProc, const SkPaint& paint, 779a87cee904e2d8f0ea6a0e7e3ca864262a8cb7c4bungeman@google.com const uint16_t* glyphs, size_t len, 789a87cee904e2d8f0ea6a0e7e3ca864262a8cb7c4bungeman@google.com SkScalar* x, SkScalar* y) { 799a87cee904e2d8f0ea6a0e7e3ca864262a8cb7c4bungeman@google.com if (paint.getTextAlign() == SkPaint::kLeft_Align) { 8028be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org return; 81769fa6a013baca6d7404e2bf096a34a7e3635fa5ctguil@chromium.org } 8228be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org 8328be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org SkMatrix ident; 8428be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org ident.reset(); 85532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com SkAutoGlyphCache autoCache(paint, NULL, &ident); 8628be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org SkGlyphCache* cache = autoCache.getCache(); 8728be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org 889510ccc06bbfa5e888f66578042674be98d8ac60ctguil@chromium.org const char* start = reinterpret_cast<const char*>(glyphs); 899510ccc06bbfa5e888f66578042674be98d8ac60ctguil@chromium.org const char* stop = reinterpret_cast<const char*>(glyphs + len); 9028be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org SkFixed xAdv = 0, yAdv = 0; 9128be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org 92769fa6a013baca6d7404e2bf096a34a7e3635fa5ctguil@chromium.org // TODO(vandebo): This probably needs to take kerning into account. 9328be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org while (start < stop) { 9428be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org const SkGlyph& glyph = glyphCacheProc(cache, &start, 0, 0); 9528be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org xAdv += glyph.fAdvanceX; 9628be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org yAdv += glyph.fAdvanceY; 9728be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org }; 98769fa6a013baca6d7404e2bf096a34a7e3635fa5ctguil@chromium.org if (paint.getTextAlign() == SkPaint::kLeft_Align) { 9928be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org return; 100769fa6a013baca6d7404e2bf096a34a7e3635fa5ctguil@chromium.org } 10128be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org 10228be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org SkScalar xAdj = SkFixedToScalar(xAdv); 10328be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org SkScalar yAdj = SkFixedToScalar(yAdv); 10428be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org if (paint.getTextAlign() == SkPaint::kCenter_Align) { 10528be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org xAdj = SkScalarHalf(xAdj); 10628be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org yAdj = SkScalarHalf(yAdj); 10728be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org } 10828be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org *x = *x - xAdj; 10928be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org *y = *y - yAdj; 11028be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org} 11128be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org 112a4662865e37a2ca95b5e3379072f6a274acc8ac8robertphillips@google.comstatic int max_glyphid_for_typeface(SkTypeface* typeface) { 113fed86bdb8b9f037439bbfa7cdbd53a581dbc5985reed@google.com SkAutoResolveDefaultTypeface autoResolve(typeface); 114fed86bdb8b9f037439bbfa7cdbd53a581dbc5985reed@google.com typeface = autoResolve.get(); 1156a4ba5b20590e377d42d3488a32cd5dd94355107commit-bot@chromium.org return typeface->countGlyphs() - 1; 1164e1cc6ac450903510b96c1b12f6ee6f420044a66vandebo@chromium.org} 1174e1cc6ac450903510b96c1b12f6ee6f420044a66vandebo@chromium.org 1184e1cc6ac450903510b96c1b12f6ee6f420044a66vandebo@chromium.orgtypedef SkAutoSTMalloc<128, uint16_t> SkGlyphStorage; 1194e1cc6ac450903510b96c1b12f6ee6f420044a66vandebo@chromium.org 120aec406650cbfa4ef65d83db5ff4f82572e8e098freed@google.comstatic int force_glyph_encoding(const SkPaint& paint, const void* text, 121aec406650cbfa4ef65d83db5ff4f82572e8e098freed@google.com size_t len, SkGlyphStorage* storage, 122139c136944f3af0cba3a25ac65c642c05fe46ac8bungeman const uint16_t** glyphIDs) { 1234e1cc6ac450903510b96c1b12f6ee6f420044a66vandebo@chromium.org // Make sure we have a glyph id encoding. 1244e1cc6ac450903510b96c1b12f6ee6f420044a66vandebo@chromium.org if (paint.getTextEncoding() != SkPaint::kGlyphID_TextEncoding) { 125aec406650cbfa4ef65d83db5ff4f82572e8e098freed@google.com int numGlyphs = paint.textToGlyphs(text, len, NULL); 1264e1cc6ac450903510b96c1b12f6ee6f420044a66vandebo@chromium.org storage->reset(numGlyphs); 1274e1cc6ac450903510b96c1b12f6ee6f420044a66vandebo@chromium.org paint.textToGlyphs(text, len, storage->get()); 1284e1cc6ac450903510b96c1b12f6ee6f420044a66vandebo@chromium.org *glyphIDs = storage->get(); 1294e1cc6ac450903510b96c1b12f6ee6f420044a66vandebo@chromium.org return numGlyphs; 1304e1cc6ac450903510b96c1b12f6ee6f420044a66vandebo@chromium.org } 1314e1cc6ac450903510b96c1b12f6ee6f420044a66vandebo@chromium.org 1324e1cc6ac450903510b96c1b12f6ee6f420044a66vandebo@chromium.org // For user supplied glyph ids we need to validate them. 1334e1cc6ac450903510b96c1b12f6ee6f420044a66vandebo@chromium.org SkASSERT((len & 1) == 0); 134aec406650cbfa4ef65d83db5ff4f82572e8e098freed@google.com int numGlyphs = SkToInt(len / 2); 135139c136944f3af0cba3a25ac65c642c05fe46ac8bungeman const uint16_t* input = static_cast<const uint16_t*>(text); 1364e1cc6ac450903510b96c1b12f6ee6f420044a66vandebo@chromium.org 1374e1cc6ac450903510b96c1b12f6ee6f420044a66vandebo@chromium.org int maxGlyphID = max_glyphid_for_typeface(paint.getTypeface()); 138aec406650cbfa4ef65d83db5ff4f82572e8e098freed@google.com int validated; 1394e1cc6ac450903510b96c1b12f6ee6f420044a66vandebo@chromium.org for (validated = 0; validated < numGlyphs; ++validated) { 1404e1cc6ac450903510b96c1b12f6ee6f420044a66vandebo@chromium.org if (input[validated] > maxGlyphID) { 1414e1cc6ac450903510b96c1b12f6ee6f420044a66vandebo@chromium.org break; 1424e1cc6ac450903510b96c1b12f6ee6f420044a66vandebo@chromium.org } 1434e1cc6ac450903510b96c1b12f6ee6f420044a66vandebo@chromium.org } 1444e1cc6ac450903510b96c1b12f6ee6f420044a66vandebo@chromium.org if (validated >= numGlyphs) { 145139c136944f3af0cba3a25ac65c642c05fe46ac8bungeman *glyphIDs = static_cast<const uint16_t*>(text); 1464e1cc6ac450903510b96c1b12f6ee6f420044a66vandebo@chromium.org return numGlyphs; 1474e1cc6ac450903510b96c1b12f6ee6f420044a66vandebo@chromium.org } 1484e1cc6ac450903510b96c1b12f6ee6f420044a66vandebo@chromium.org 1494e1cc6ac450903510b96c1b12f6ee6f420044a66vandebo@chromium.org // Silently drop anything out of range. 1504e1cc6ac450903510b96c1b12f6ee6f420044a66vandebo@chromium.org storage->reset(numGlyphs); 1514e1cc6ac450903510b96c1b12f6ee6f420044a66vandebo@chromium.org if (validated > 0) { 1524e1cc6ac450903510b96c1b12f6ee6f420044a66vandebo@chromium.org memcpy(storage->get(), input, validated * sizeof(uint16_t)); 1534e1cc6ac450903510b96c1b12f6ee6f420044a66vandebo@chromium.org } 1544e1cc6ac450903510b96c1b12f6ee6f420044a66vandebo@chromium.org 155aec406650cbfa4ef65d83db5ff4f82572e8e098freed@google.com for (int i = validated; i < numGlyphs; ++i) { 1564e1cc6ac450903510b96c1b12f6ee6f420044a66vandebo@chromium.org storage->get()[i] = input[i]; 1574e1cc6ac450903510b96c1b12f6ee6f420044a66vandebo@chromium.org if (input[i] > maxGlyphID) { 1584e1cc6ac450903510b96c1b12f6ee6f420044a66vandebo@chromium.org storage->get()[i] = 0; 1594e1cc6ac450903510b96c1b12f6ee6f420044a66vandebo@chromium.org } 1604e1cc6ac450903510b96c1b12f6ee6f420044a66vandebo@chromium.org } 1614e1cc6ac450903510b96c1b12f6ee6f420044a66vandebo@chromium.org *glyphIDs = storage->get(); 1624e1cc6ac450903510b96c1b12f6ee6f420044a66vandebo@chromium.org return numGlyphs; 1634e1cc6ac450903510b96c1b12f6ee6f420044a66vandebo@chromium.org} 1644e1cc6ac450903510b96c1b12f6ee6f420044a66vandebo@chromium.org 165b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.orgstatic void set_text_transform(SkScalar x, SkScalar y, SkScalar textSkewX, 166b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org SkWStream* content) { 167b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org // Flip the text about the x-axis to account for origin swap and include 168b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org // the passed parameters. 169b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org content->writeText("1 0 "); 170b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org SkPDFScalar::Append(0 - textSkewX, content); 171b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org content->writeText(" -1 "); 172b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org SkPDFScalar::Append(x, content); 173b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org content->writeText(" "); 174b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org SkPDFScalar::Append(y, content); 175b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org content->writeText(" Tm\n"); 176b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org} 177b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org 1789fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org// It is important to not confuse GraphicStateEntry with SkPDFGraphicState, the 1799fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org// later being our representation of an object in the PDF file. 1809fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.orgstruct GraphicStateEntry { 1819fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org GraphicStateEntry(); 1829fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org 1839fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org // Compare the fields we care about when setting up a new content entry. 1849fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org bool compareInitialState(const GraphicStateEntry& b); 1859fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org 1869fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org SkMatrix fMatrix; 1879fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org // We can't do set operations on Paths, though PDF natively supports 1889fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org // intersect. If the clip stack does anything other than intersect, 1899fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org // we have to fall back to the region. Treat fClipStack as authoritative. 1909fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org // See http://code.google.com/p/skia/issues/detail?id=221 1919fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org SkClipStack fClipStack; 1929fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org SkRegion fClipRegion; 1939fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org 1949fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org // When emitting the content entry, we will ensure the graphic state 1959fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org // is set to these values first. 1969fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org SkColor fColor; 1979fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org SkScalar fTextScaleX; // Zero means we don't care what the value is. 1989fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org SkPaint::Style fTextFill; // Only if TextScaleX is non-zero. 1999fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org int fShaderIndex; 2009fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org int fGraphicStateIndex; 2019fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org 2029fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org // We may change the font (i.e. for Type1 support) within a 2039fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org // ContentEntry. This is the one currently in effect, or NULL if none. 2049fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org SkPDFFont* fFont; 2059fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org // In PDF, text size has no default value. It is only valid if fFont is 2069fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org // not NULL. 2079fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org SkScalar fTextSize; 2089fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org}; 2099fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org 2109fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.orgGraphicStateEntry::GraphicStateEntry() : fColor(SK_ColorBLACK), 2119fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org fTextScaleX(SK_Scalar1), 2129fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org fTextFill(SkPaint::kFill_Style), 2139fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org fShaderIndex(-1), 2149fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org fGraphicStateIndex(-1), 2159fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org fFont(NULL), 2169fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org fTextSize(SK_ScalarNaN) { 2179fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org fMatrix.reset(); 2189fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org} 2199fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org 220b000d76af4de735a233e64b7be68cee8a5a8f8dccommit-bot@chromium.orgbool GraphicStateEntry::compareInitialState(const GraphicStateEntry& cur) { 221b000d76af4de735a233e64b7be68cee8a5a8f8dccommit-bot@chromium.org return fColor == cur.fColor && 222b000d76af4de735a233e64b7be68cee8a5a8f8dccommit-bot@chromium.org fShaderIndex == cur.fShaderIndex && 223b000d76af4de735a233e64b7be68cee8a5a8f8dccommit-bot@chromium.org fGraphicStateIndex == cur.fGraphicStateIndex && 224b000d76af4de735a233e64b7be68cee8a5a8f8dccommit-bot@chromium.org fMatrix == cur.fMatrix && 225b000d76af4de735a233e64b7be68cee8a5a8f8dccommit-bot@chromium.org fClipStack == cur.fClipStack && 226b000d76af4de735a233e64b7be68cee8a5a8f8dccommit-bot@chromium.org (fTextScaleX == 0 || 227b000d76af4de735a233e64b7be68cee8a5a8f8dccommit-bot@chromium.org (fTextScaleX == cur.fTextScaleX && fTextFill == cur.fTextFill)); 2289fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org} 2299fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org 2309fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.orgclass GraphicStackState { 2319fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.orgpublic: 2329fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org GraphicStackState(const SkClipStack& existingClipStack, 2339fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org const SkRegion& existingClipRegion, 2349fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org SkWStream* contentStream) 2359fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org : fStackDepth(0), 2369fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org fContentStream(contentStream) { 2379fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org fEntries[0].fClipStack = existingClipStack; 2389fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org fEntries[0].fClipRegion = existingClipRegion; 2399fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org } 2409fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org 2419fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org void updateClip(const SkClipStack& clipStack, const SkRegion& clipRegion, 242663515bc59325092c4e47f5189782bd6fcd0586avandebo@chromium.org const SkPoint& translation); 2439fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org void updateMatrix(const SkMatrix& matrix); 2449fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org void updateDrawingState(const GraphicStateEntry& state); 2459fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org 2469fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org void drainStack(); 2479fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org 2489fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.orgprivate: 2499fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org void push(); 2509fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org void pop(); 2519fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org GraphicStateEntry* currentEntry() { return &fEntries[fStackDepth]; } 2529fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org 2539fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org // Conservative limit on save depth, see impl. notes in PDF 1.4 spec. 2549fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org static const int kMaxStackDepth = 12; 2559fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org GraphicStateEntry fEntries[kMaxStackDepth + 1]; 2569fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org int fStackDepth; 2579fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org SkWStream* fContentStream; 2589fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org}; 2599fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org 2609fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.orgvoid GraphicStackState::drainStack() { 2619fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org while (fStackDepth) { 2629fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org pop(); 2639fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org } 2649fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org} 2659fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org 2669fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.orgvoid GraphicStackState::push() { 2679fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org SkASSERT(fStackDepth < kMaxStackDepth); 2689fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org fContentStream->writeText("q\n"); 2699fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org fStackDepth++; 2709fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org fEntries[fStackDepth] = fEntries[fStackDepth - 1]; 2719fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org} 2729fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org 2739fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.orgvoid GraphicStackState::pop() { 2749fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org SkASSERT(fStackDepth > 0); 2759fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org fContentStream->writeText("Q\n"); 2769fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org fStackDepth--; 2779fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org} 2789fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org 27980214e26c57c5fea954006400852e8999e201923robertphillips@google.com// This function initializes iter to be an iterator on the "stack" argument 2809fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org// and then skips over the leading entries as specified in prefix. It requires 2819fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org// and asserts that "prefix" will be a prefix to "stack." 2829fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.orgstatic void skip_clip_stack_prefix(const SkClipStack& prefix, 2839fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org const SkClipStack& stack, 284c029062a0312fb747fb6c2677983aba51795c580robertphillips@google.com SkClipStack::Iter* iter) { 28580214e26c57c5fea954006400852e8999e201923robertphillips@google.com SkClipStack::B2TIter prefixIter(prefix); 28680214e26c57c5fea954006400852e8999e201923robertphillips@google.com iter->reset(stack, SkClipStack::Iter::kBottom_IterStart); 2879fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org 2888182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com const SkClipStack::Element* prefixEntry; 2898182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com const SkClipStack::Element* iterEntry; 2909fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org 2919fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org for (prefixEntry = prefixIter.next(); prefixEntry; 292c029062a0312fb747fb6c2677983aba51795c580robertphillips@google.com prefixEntry = prefixIter.next()) { 2939fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org iterEntry = iter->next(); 2949fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org SkASSERT(iterEntry); 2958887ede82465687355c7a1c51e4553e99b2fb15avandebo@chromium.org // Because of SkClipStack does internal intersection, the last clip 2968887ede82465687355c7a1c51e4553e99b2fb15avandebo@chromium.org // entry may differ. 2979510ccc06bbfa5e888f66578042674be98d8ac60ctguil@chromium.org if (*prefixEntry != *iterEntry) { 2988182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com SkASSERT(prefixEntry->getOp() == SkRegion::kIntersect_Op); 2998182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com SkASSERT(iterEntry->getOp() == SkRegion::kIntersect_Op); 3008182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com SkASSERT(iterEntry->getType() == prefixEntry->getType()); 301c029062a0312fb747fb6c2677983aba51795c580robertphillips@google.com // back up the iterator by one 302c029062a0312fb747fb6c2677983aba51795c580robertphillips@google.com iter->prev(); 3038887ede82465687355c7a1c51e4553e99b2fb15avandebo@chromium.org prefixEntry = prefixIter.next(); 3048887ede82465687355c7a1c51e4553e99b2fb15avandebo@chromium.org break; 3058887ede82465687355c7a1c51e4553e99b2fb15avandebo@chromium.org } 3069fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org } 3079fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org 3089fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org SkASSERT(prefixEntry == NULL); 3099fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org} 3109fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org 3119fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.orgstatic void emit_clip(SkPath* clipPath, SkRect* clipRect, 3129fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org SkWStream* contentStream) { 3139fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org SkASSERT(clipPath || clipRect); 3149fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org 3159fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org SkPath::FillType clipFill; 3169fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org if (clipPath) { 317683001ce0de70c859ea5e5353245b18cadbefc45vandebo@chromium.org SkPDFUtils::EmitPath(*clipPath, SkPaint::kFill_Style, contentStream); 3189fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org clipFill = clipPath->getFillType(); 3193e7b280b720ae202db6561f31d862990a7be32d9vandebo@chromium.org } else { 3209fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org SkPDFUtils::AppendRectangle(*clipRect, contentStream); 3219fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org clipFill = SkPath::kWinding_FillType; 3229fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org } 3239fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org 3249fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org NOT_IMPLEMENTED(clipFill == SkPath::kInverseEvenOdd_FillType, false); 3259fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org NOT_IMPLEMENTED(clipFill == SkPath::kInverseWinding_FillType, false); 3269fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org if (clipFill == SkPath::kEvenOdd_FillType) { 3279fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org contentStream->writeText("W* n\n"); 3289fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org } else { 3299fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org contentStream->writeText("W n\n"); 3309fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org } 3319fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org} 3329fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org 333d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org#ifdef SK_PDF_USE_PATHOPS 334d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org/* Calculate an inverted path's equivalent non-inverted path, given the 335d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org * canvas bounds. 336d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org * outPath may alias with invPath (since this is supported by PathOps). 337d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org */ 338d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.orgstatic bool calculate_inverse_path(const SkRect& bounds, const SkPath& invPath, 339d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org SkPath* outPath) { 340d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org SkASSERT(invPath.isInverseFillType()); 341d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org 342d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org SkPath clipPath; 343d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org clipPath.addRect(bounds); 344d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org 345d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org return Op(clipPath, invPath, kIntersect_PathOp, outPath); 346d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org} 347d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org 348d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org// Sanity check the numerical values of the SkRegion ops and PathOps ops 349d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org// enums so region_op_to_pathops_op can do a straight passthrough cast. 350d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org// If these are failing, it may be necessary to make region_op_to_pathops_op 351d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org// do more. 352d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.orgSK_COMPILE_ASSERT(SkRegion::kDifference_Op == (int)kDifference_PathOp, 353d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org region_pathop_mismatch); 354d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.orgSK_COMPILE_ASSERT(SkRegion::kIntersect_Op == (int)kIntersect_PathOp, 355d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org region_pathop_mismatch); 356d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.orgSK_COMPILE_ASSERT(SkRegion::kUnion_Op == (int)kUnion_PathOp, 357d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org region_pathop_mismatch); 358d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.orgSK_COMPILE_ASSERT(SkRegion::kXOR_Op == (int)kXOR_PathOp, 359d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org region_pathop_mismatch); 360d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.orgSK_COMPILE_ASSERT(SkRegion::kReverseDifference_Op == 361d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org (int)kReverseDifference_PathOp, 362d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org region_pathop_mismatch); 363d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org 364d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.orgstatic SkPathOp region_op_to_pathops_op(SkRegion::Op op) { 365d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org SkASSERT(op >= 0); 366d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org SkASSERT(op <= SkRegion::kReverseDifference_Op); 367d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org return (SkPathOp)op; 368d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org} 369d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org 370d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org/* Uses Path Ops to calculate a vector SkPath clip from a clip stack. 371d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org * Returns true if successful, or false if not successful. 372d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org * If successful, the resulting clip is stored in outClipPath. 373d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org * If not successful, outClipPath is undefined, and a fallback method 374d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org * should be used. 375d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org */ 376d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.orgstatic bool get_clip_stack_path(const SkMatrix& transform, 377d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org const SkClipStack& clipStack, 378d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org const SkRegion& clipRegion, 379d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org SkPath* outClipPath) { 380d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org outClipPath->reset(); 381d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org outClipPath->setFillType(SkPath::kInverseWinding_FillType); 382d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org 383d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org const SkClipStack::Element* clipEntry; 384d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org SkClipStack::Iter iter; 385d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org iter.reset(clipStack, SkClipStack::Iter::kBottom_IterStart); 386d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org for (clipEntry = iter.next(); clipEntry; clipEntry = iter.next()) { 387d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org SkPath entryPath; 388d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org if (SkClipStack::Element::kEmpty_Type == clipEntry->getType()) { 389d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org outClipPath->reset(); 390d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org outClipPath->setFillType(SkPath::kInverseWinding_FillType); 391d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org continue; 392e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org } else { 393e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org clipEntry->asPath(&entryPath); 394d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org } 395d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org entryPath.transform(transform); 396d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org 397d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org if (SkRegion::kReplace_Op == clipEntry->getOp()) { 398d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org *outClipPath = entryPath; 399d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org } else { 400d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org SkPathOp op = region_op_to_pathops_op(clipEntry->getOp()); 401d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org if (!Op(*outClipPath, entryPath, op, outClipPath)) { 402d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org return false; 403d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org } 404d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org } 405d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org } 406d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org 407d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org if (outClipPath->isInverseFillType()) { 408d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org // The bounds are slightly outset to ensure this is correct in the 409d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org // face of floating-point accuracy and possible SkRegion bitmap 410d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org // approximations. 411d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org SkRect clipBounds = SkRect::Make(clipRegion.getBounds()); 412d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org clipBounds.outset(SK_Scalar1, SK_Scalar1); 413d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org if (!calculate_inverse_path(clipBounds, *outClipPath, outClipPath)) { 414d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org return false; 415d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org } 416d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org } 417d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org return true; 418d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org} 419d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org#endif 420d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org 421769fa6a013baca6d7404e2bf096a34a7e3635fa5ctguil@chromium.org// TODO(vandebo): Take advantage of SkClipStack::getSaveCount(), the PDF 4229fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org// graphic state stack, and the fact that we can know all the clips used 4239fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org// on the page to optimize this. 4249fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.orgvoid GraphicStackState::updateClip(const SkClipStack& clipStack, 4259fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org const SkRegion& clipRegion, 426663515bc59325092c4e47f5189782bd6fcd0586avandebo@chromium.org const SkPoint& translation) { 4279fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org if (clipStack == currentEntry()->fClipStack) { 4289fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org return; 4299fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org } 4309fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org 4319fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org while (fStackDepth > 0) { 4329fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org pop(); 4339fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org if (clipStack == currentEntry()->fClipStack) { 4349fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org return; 4359fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org } 4369fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org } 4379fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org push(); 4389fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org 439d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org currentEntry()->fClipStack = clipStack; 440d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org currentEntry()->fClipRegion = clipRegion; 441d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org 442d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org SkMatrix transform; 443d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org transform.setTranslate(translation.fX, translation.fY); 444d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org 445d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org#ifdef SK_PDF_USE_PATHOPS 446d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org SkPath clipPath; 447d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org if (get_clip_stack_path(transform, clipStack, clipRegion, &clipPath)) { 448d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org emit_clip(&clipPath, NULL, fContentStream); 449d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org return; 450d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org } 451d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org#endif 4529fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org // gsState->initialEntry()->fClipStack/Region specifies the clip that has 4539fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org // already been applied. (If this is a top level device, then it specifies 4549fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org // a clip to the content area. If this is a layer, then it specifies 4559fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org // the clip in effect when the layer was created.) There's no need to 4569fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org // reapply that clip; SKCanvas's SkDrawIter will draw anything outside the 4579fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org // initial clip on the parent layer. (This means there's a bug if the user 4589fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org // expands the clip and then uses any xfer mode that uses dst: 4599fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org // http://code.google.com/p/skia/issues/detail?id=228 ) 460c029062a0312fb747fb6c2677983aba51795c580robertphillips@google.com SkClipStack::Iter iter; 4619fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org skip_clip_stack_prefix(fEntries[0].fClipStack, clipStack, &iter); 4629fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org 4639fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org // If the clip stack does anything other than intersect or if it uses 4649fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org // an inverse fill type, we have to fall back to the clip region. 4659fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org bool needRegion = false; 4668182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com const SkClipStack::Element* clipEntry; 4679fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org for (clipEntry = iter.next(); clipEntry; clipEntry = iter.next()) { 4683b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org if (clipEntry->getOp() != SkRegion::kIntersect_Op || 4693b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org clipEntry->isInverseFilled()) { 4709fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org needRegion = true; 4719fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org break; 4729fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org } 4739fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org } 4749fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org 4759fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org if (needRegion) { 4769fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org SkPath clipPath; 4779fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org SkAssertResult(clipRegion.getBoundaryPath(&clipPath)); 4789fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org emit_clip(&clipPath, NULL, fContentStream); 4799fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org } else { 4809fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org skip_clip_stack_prefix(fEntries[0].fClipStack, clipStack, &iter); 4818182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com const SkClipStack::Element* clipEntry; 4829fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org for (clipEntry = iter.next(); clipEntry; clipEntry = iter.next()) { 4838182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com SkASSERT(clipEntry->getOp() == SkRegion::kIntersect_Op); 4848182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com switch (clipEntry->getType()) { 4858182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com case SkClipStack::Element::kRect_Type: { 4868182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com SkRect translatedClip; 4878182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com transform.mapRect(&translatedClip, clipEntry->getRect()); 4888182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com emit_clip(NULL, &translatedClip, fContentStream); 4898182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com break; 4908182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com } 4915a346a85027fc8aae5d836d951e455a22b3272d0commit-bot@chromium.org default: { 4928182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com SkPath translatedPath; 4935a346a85027fc8aae5d836d951e455a22b3272d0commit-bot@chromium.org clipEntry->asPath(&translatedPath); 4945a346a85027fc8aae5d836d951e455a22b3272d0commit-bot@chromium.org translatedPath.transform(transform, &translatedPath); 4958182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com emit_clip(&translatedPath, NULL, fContentStream); 4968182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com break; 4978182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com } 4989fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org } 4999fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org } 5009fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org } 5019fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org} 5029fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org 5039fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.orgvoid GraphicStackState::updateMatrix(const SkMatrix& matrix) { 5049fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org if (matrix == currentEntry()->fMatrix) { 5059fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org return; 5069fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org } 5079fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org 5089fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org if (currentEntry()->fMatrix.getType() != SkMatrix::kIdentity_Mask) { 5099fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org SkASSERT(fStackDepth > 0); 5109fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org SkASSERT(fEntries[fStackDepth].fClipStack == 5119fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org fEntries[fStackDepth -1].fClipStack); 5129fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org pop(); 5139fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org 5149fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org SkASSERT(currentEntry()->fMatrix.getType() == SkMatrix::kIdentity_Mask); 5159fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org } 5169fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org if (matrix.getType() == SkMatrix::kIdentity_Mask) { 5179fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org return; 5189fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org } 5199fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org 5209fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org push(); 5219fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org SkPDFUtils::AppendTransform(matrix, fContentStream); 5229fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org currentEntry()->fMatrix = matrix; 5239fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org} 5249fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org 5259fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.orgvoid GraphicStackState::updateDrawingState(const GraphicStateEntry& state) { 5269fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org // PDF treats a shader as a color, so we only set one or the other. 5279fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org if (state.fShaderIndex >= 0) { 5289fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org if (state.fShaderIndex != currentEntry()->fShaderIndex) { 52993a2e213441c75033b04365c7d68c8d3887288accommit-bot@chromium.org SkPDFUtils::ApplyPattern(state.fShaderIndex, fContentStream); 5309fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org currentEntry()->fShaderIndex = state.fShaderIndex; 5319fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org } 5329fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org } else { 5339fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org if (state.fColor != currentEntry()->fColor || 5349fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org currentEntry()->fShaderIndex >= 0) { 5359fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org emit_pdf_color(state.fColor, fContentStream); 5369fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org fContentStream->writeText("RG "); 5379fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org emit_pdf_color(state.fColor, fContentStream); 5389fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org fContentStream->writeText("rg\n"); 5399fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org currentEntry()->fColor = state.fColor; 5409fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org currentEntry()->fShaderIndex = -1; 5419fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org } 5429fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org } 5439fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org 5449fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org if (state.fGraphicStateIndex != currentEntry()->fGraphicStateIndex) { 5456112c215fbdd53388e64ece36e6c7bba0fe3a451vandebo@chromium.org SkPDFUtils::ApplyGraphicState(state.fGraphicStateIndex, fContentStream); 5469fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org currentEntry()->fGraphicStateIndex = state.fGraphicStateIndex; 5479fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org } 5489fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org 5499fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org if (state.fTextScaleX) { 5509fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org if (state.fTextScaleX != currentEntry()->fTextScaleX) { 5519fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org SkScalar pdfScale = SkScalarMul(state.fTextScaleX, 5529fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org SkIntToScalar(100)); 5539fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org SkPDFScalar::Append(pdfScale, fContentStream); 5549fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org fContentStream->writeText(" Tz\n"); 5559fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org currentEntry()->fTextScaleX = state.fTextScaleX; 5569fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org } 5579fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org if (state.fTextFill != currentEntry()->fTextFill) { 5589fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org SK_COMPILE_ASSERT(SkPaint::kFill_Style == 0, enum_must_match_value); 5599fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org SK_COMPILE_ASSERT(SkPaint::kStroke_Style == 1, 5609fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org enum_must_match_value); 5619fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org SK_COMPILE_ASSERT(SkPaint::kStrokeAndFill_Style == 2, 5629fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org enum_must_match_value); 5639fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org fContentStream->writeDecAsText(state.fTextFill); 5649fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org fContentStream->writeText(" Tr\n"); 5659fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org currentEntry()->fTextFill = state.fTextFill; 5669fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org } 5679fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org } 5689fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org} 5699b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org 57015a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.orgSkBaseDevice* SkPDFDevice::onCreateDevice(const SkImageInfo& info, Usage usage) { 571c38dee4f2c4cac24fa926a51069f04df272b1516Stephen White // PDF does not support image filters, so render them on CPU. 572c38dee4f2c4cac24fa926a51069f04df272b1516Stephen White // Note that this rendering is done at "screen" resolution (100dpi), not 573c38dee4f2c4cac24fa926a51069f04df272b1516Stephen White // printer resolution. 574c38dee4f2c4cac24fa926a51069f04df272b1516Stephen White // FIXME: It may be possible to express some filters natively using PDF 575c38dee4f2c4cac24fa926a51069f04df272b1516Stephen White // to improve quality and file size (http://skbug.com/3043) 576c38dee4f2c4cac24fa926a51069f04df272b1516Stephen White if (kImageFilter_Usage == usage) { 577c38dee4f2c4cac24fa926a51069f04df272b1516Stephen White return SkBitmapDevice::Create(info); 578c38dee4f2c4cac24fa926a51069f04df272b1516Stephen White } 579c38dee4f2c4cac24fa926a51069f04df272b1516Stephen White 580e97f0856a8044866b12527819d14cdfbcdfd96f2bsalomon@google.com SkMatrix initialTransform; 581e97f0856a8044866b12527819d14cdfbcdfd96f2bsalomon@google.com initialTransform.reset(); 58215a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org SkISize size = SkISize::Make(info.width(), info.height()); 583e97f0856a8044866b12527819d14cdfbcdfd96f2bsalomon@google.com return SkNEW_ARGS(SkPDFDevice, (size, size, initialTransform)); 584e97f0856a8044866b12527819d14cdfbcdfd96f2bsalomon@google.com} 585e97f0856a8044866b12527819d14cdfbcdfd96f2bsalomon@google.com 586e97f0856a8044866b12527819d14cdfbcdfd96f2bsalomon@google.com 587b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.orgstruct ContentEntry { 588b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org GraphicStateEntry fState; 589b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org SkDynamicMemoryWStream fContent; 590e02944075840d672bd1797f3d945ff82d302282fcommit-bot@chromium.org SkAutoTDelete<ContentEntry> fNext; 5912e6a69b7a23e88e54d8b4a9ee3f4f9e4cc0695a7edisonn@google.com 5922e6a69b7a23e88e54d8b4a9ee3f4f9e4cc0695a7edisonn@google.com // If the stack is too deep we could get Stack Overflow. 5932e6a69b7a23e88e54d8b4a9ee3f4f9e4cc0695a7edisonn@google.com // So we manually destruct the object. 5942e6a69b7a23e88e54d8b4a9ee3f4f9e4cc0695a7edisonn@google.com ~ContentEntry() { 595e02944075840d672bd1797f3d945ff82d302282fcommit-bot@chromium.org ContentEntry* val = fNext.detach(); 5962e6a69b7a23e88e54d8b4a9ee3f4f9e4cc0695a7edisonn@google.com while (val != NULL) { 597e02944075840d672bd1797f3d945ff82d302282fcommit-bot@chromium.org ContentEntry* valNext = val->fNext.detach(); 5982e6a69b7a23e88e54d8b4a9ee3f4f9e4cc0695a7edisonn@google.com // When the destructor is called, fNext is NULL and exits. 5992e6a69b7a23e88e54d8b4a9ee3f4f9e4cc0695a7edisonn@google.com delete val; 6002e6a69b7a23e88e54d8b4a9ee3f4f9e4cc0695a7edisonn@google.com val = valNext; 6012e6a69b7a23e88e54d8b4a9ee3f4f9e4cc0695a7edisonn@google.com } 6022e6a69b7a23e88e54d8b4a9ee3f4f9e4cc0695a7edisonn@google.com } 603b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org}; 604b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org 605b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org// A helper class to automatically finish a ContentEntry at the end of a 606b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org// drawing method and maintain the state needed between set up and finish. 60713d14a9dbd2cf0a9654045cc967e92626690631avandebo@chromium.orgclass ScopedContentEntry { 608b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.orgpublic: 60913d14a9dbd2cf0a9654045cc967e92626690631avandebo@chromium.org ScopedContentEntry(SkPDFDevice* device, const SkDraw& draw, 61013d14a9dbd2cf0a9654045cc967e92626690631avandebo@chromium.org const SkPaint& paint, bool hasText = false) 611b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org : fDevice(device), 612b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org fContentEntry(NULL), 6133b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org fXfermode(SkXfermode::kSrcOver_Mode), 6143b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org fDstFormXObject(NULL) { 615b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org init(draw.fClipStack, *draw.fClip, *draw.fMatrix, paint, hasText); 616b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org } 61713d14a9dbd2cf0a9654045cc967e92626690631avandebo@chromium.org ScopedContentEntry(SkPDFDevice* device, const SkClipStack* clipStack, 61813d14a9dbd2cf0a9654045cc967e92626690631avandebo@chromium.org const SkRegion& clipRegion, const SkMatrix& matrix, 61913d14a9dbd2cf0a9654045cc967e92626690631avandebo@chromium.org const SkPaint& paint, bool hasText = false) 620b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org : fDevice(device), 621b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org fContentEntry(NULL), 6223b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org fXfermode(SkXfermode::kSrcOver_Mode), 6233b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org fDstFormXObject(NULL) { 624b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org init(clipStack, clipRegion, matrix, paint, hasText); 625b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org } 626b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org 62713d14a9dbd2cf0a9654045cc967e92626690631avandebo@chromium.org ~ScopedContentEntry() { 628b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org if (fContentEntry) { 6293b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org SkPath* shape = &fShape; 6303b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org if (shape->isEmpty()) { 6313b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org shape = NULL; 6323b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org } 6333b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org fDevice->finishContentEntry(fXfermode, fDstFormXObject, shape); 634b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org } 635fc641d09e5a1a9f7fae369ae06a8b96089faf57breed@google.com SkSafeUnref(fDstFormXObject); 636b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org } 637b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org 638b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org ContentEntry* entry() { return fContentEntry; } 6393b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org 6403b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org /* Returns true when we explicitly need the shape of the drawing. */ 6413b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org bool needShape() { 6423b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org switch (fXfermode) { 6433b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org case SkXfermode::kClear_Mode: 6443b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org case SkXfermode::kSrc_Mode: 6453b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org case SkXfermode::kSrcIn_Mode: 6463b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org case SkXfermode::kSrcOut_Mode: 6473b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org case SkXfermode::kDstIn_Mode: 6483b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org case SkXfermode::kDstOut_Mode: 6493b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org case SkXfermode::kSrcATop_Mode: 6503b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org case SkXfermode::kDstATop_Mode: 6513b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org case SkXfermode::kModulate_Mode: 6523b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org return true; 6533b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org default: 6543b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org return false; 6553b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org } 6563b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org } 6573b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org 6583b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org /* Returns true unless we only need the shape of the drawing. */ 6593b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org bool needSource() { 6603b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org if (fXfermode == SkXfermode::kClear_Mode) { 6613b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org return false; 6623b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org } 6633b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org return true; 6643b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org } 6653b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org 6663b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org /* If the shape is different than the alpha component of the content, then 6673b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org * setShape should be called with the shape. In particular, images and 6683b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org * devices have rectangular shape. 6693b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org */ 6703b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org void setShape(const SkPath& shape) { 6713b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org fShape = shape; 6723b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org } 6733b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org 674b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.orgprivate: 675b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org SkPDFDevice* fDevice; 676b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org ContentEntry* fContentEntry; 677b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org SkXfermode::Mode fXfermode; 678fc641d09e5a1a9f7fae369ae06a8b96089faf57breed@google.com SkPDFFormXObject* fDstFormXObject; 6793b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org SkPath fShape; 680b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org 681b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org void init(const SkClipStack* clipStack, const SkRegion& clipRegion, 682b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org const SkMatrix& matrix, const SkPaint& paint, bool hasText) { 68383d8eda890def8c119794deeec6244c67da83ac8edisonn@google.com // Shape has to be flatten before we get here. 68483d8eda890def8c119794deeec6244c67da83ac8edisonn@google.com if (matrix.hasPerspective()) { 68583d8eda890def8c119794deeec6244c67da83ac8edisonn@google.com NOT_IMPLEMENTED(!matrix.hasPerspective(), false); 686dc37e20647b92528ba9e6a4074cb0f8cc7fbe6b5vandebo@chromium.org return; 687dc37e20647b92528ba9e6a4074cb0f8cc7fbe6b5vandebo@chromium.org } 688b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org if (paint.getXfermode()) { 689b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org paint.getXfermode()->asMode(&fXfermode); 690b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org } 691b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org fContentEntry = fDevice->setUpContentEntry(clipStack, clipRegion, 692b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org matrix, paint, hasText, 693b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org &fDstFormXObject); 694b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org } 695b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org}; 696b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org 6979b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org//////////////////////////////////////////////////////////////////////////////// 6989b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org 69989443aba5bfa2b040dc9fd24938b7d0b3decd737reedstatic inline SkImageInfo make_content_info(const SkISize& contentSize, 70089443aba5bfa2b040dc9fd24938b7d0b3decd737reed const SkMatrix* initialTransform) { 701900ecf2f1579d42c9d2959831787af0346320f86reed@google.com SkImageInfo info; 702a0c7edbb0804144ab320951db5c741eea247fc0fvandebo@chromium.org if (initialTransform) { 703a0c7edbb0804144ab320951db5c741eea247fc0fvandebo@chromium.org // Compute the size of the drawing area. 704a0c7edbb0804144ab320951db5c741eea247fc0fvandebo@chromium.org SkVector drawingSize; 705a0c7edbb0804144ab320951db5c741eea247fc0fvandebo@chromium.org SkMatrix inverse; 706663515bc59325092c4e47f5189782bd6fcd0586avandebo@chromium.org drawingSize.set(SkIntToScalar(contentSize.fWidth), 707663515bc59325092c4e47f5189782bd6fcd0586avandebo@chromium.org SkIntToScalar(contentSize.fHeight)); 708b054990307b7338e599a12d9af10eb2058b94051vandebo@chromium.org if (!initialTransform->invert(&inverse)) { 709386dfc049baa400c13e4e98727d4c04d0242b7b8vandebo@chromium.org // This shouldn't happen, initial transform should be invertible. 710386dfc049baa400c13e4e98727d4c04d0242b7b8vandebo@chromium.org SkASSERT(false); 711b054990307b7338e599a12d9af10eb2058b94051vandebo@chromium.org inverse.reset(); 712b054990307b7338e599a12d9af10eb2058b94051vandebo@chromium.org } 713a0c7edbb0804144ab320951db5c741eea247fc0fvandebo@chromium.org inverse.mapVectors(&drawingSize, 1); 714a0c7edbb0804144ab320951db5c741eea247fc0fvandebo@chromium.org SkISize size = SkSize::Make(drawingSize.fX, drawingSize.fY).toRound(); 715900ecf2f1579d42c9d2959831787af0346320f86reed@google.com info = SkImageInfo::MakeUnknown(abs(size.fWidth), abs(size.fHeight)); 716a0c7edbb0804144ab320951db5c741eea247fc0fvandebo@chromium.org } else { 717900ecf2f1579d42c9d2959831787af0346320f86reed@google.com info = SkImageInfo::MakeUnknown(abs(contentSize.fWidth), 718900ecf2f1579d42c9d2959831787af0346320f86reed@google.com abs(contentSize.fHeight)); 719a0c7edbb0804144ab320951db5c741eea247fc0fvandebo@chromium.org } 72089443aba5bfa2b040dc9fd24938b7d0b3decd737reed return info; 721f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com} 722f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com 723663515bc59325092c4e47f5189782bd6fcd0586avandebo@chromium.org// TODO(vandebo) change pageSize to SkSize. 724152612938020fa46999f33668027d5bc0f7afd18ctguil@chromium.orgSkPDFDevice::SkPDFDevice(const SkISize& pageSize, const SkISize& contentSize, 72575f97e452e8f2ee55cd2b283df7d7734f48bc2bfvandebo@chromium.org const SkMatrix& initialTransform) 72689443aba5bfa2b040dc9fd24938b7d0b3decd737reed : fPageSize(pageSize) 72789443aba5bfa2b040dc9fd24938b7d0b3decd737reed , fContentSize(contentSize) 72889443aba5bfa2b040dc9fd24938b7d0b3decd737reed , fLastContentEntry(NULL) 72989443aba5bfa2b040dc9fd24938b7d0b3decd737reed , fLastMarginContentEntry(NULL) 73089443aba5bfa2b040dc9fd24938b7d0b3decd737reed , fClipStack(NULL) 73189443aba5bfa2b040dc9fd24938b7d0b3decd737reed , fEncoder(NULL) 73289443aba5bfa2b040dc9fd24938b7d0b3decd737reed , fRasterDpi(72.0f) 73389443aba5bfa2b040dc9fd24938b7d0b3decd737reed{ 73489443aba5bfa2b040dc9fd24938b7d0b3decd737reed const SkImageInfo info = make_content_info(contentSize, &initialTransform); 73589443aba5bfa2b040dc9fd24938b7d0b3decd737reed 73683d8eda890def8c119794deeec6244c67da83ac8edisonn@google.com // Just report that PDF does not supports perspective in the 73783d8eda890def8c119794deeec6244c67da83ac8edisonn@google.com // initial transform. 738aa6c4d2587cf155eb8d74ac29225c9bcac13cd9bedisonn@google.com NOT_IMPLEMENTED(initialTransform.hasPerspective(), true); 739aa6c4d2587cf155eb8d74ac29225c9bcac13cd9bedisonn@google.com 74077bcaa324a574584331322d98768582d9232f7fcvandebo@chromium.org // Skia generally uses the top left as the origin but PDF natively has the 741a0c7edbb0804144ab320951db5c741eea247fc0fvandebo@chromium.org // origin at the bottom left. This matrix corrects for that. But that only 742a0c7edbb0804144ab320951db5c741eea247fc0fvandebo@chromium.org // needs to be done once, we don't do it when layering. 743663515bc59325092c4e47f5189782bd6fcd0586avandebo@chromium.org fInitialTransform.setTranslate(0, SkIntToScalar(pageSize.fHeight)); 744663515bc59325092c4e47f5189782bd6fcd0586avandebo@chromium.org fInitialTransform.preScale(SK_Scalar1, -SK_Scalar1); 74577bcaa324a574584331322d98768582d9232f7fcvandebo@chromium.org fInitialTransform.preConcat(initialTransform); 74689443aba5bfa2b040dc9fd24938b7d0b3decd737reed fLegacyBitmap.setInfo(info); 74777bcaa324a574584331322d98768582d9232f7fcvandebo@chromium.org 74889443aba5bfa2b040dc9fd24938b7d0b3decd737reed SkIRect existingClip = SkIRect::MakeWH(info.width(), info.height()); 749a0c7edbb0804144ab320951db5c741eea247fc0fvandebo@chromium.org fExistingClipRegion.setRect(existingClip); 750a0c7edbb0804144ab320951db5c741eea247fc0fvandebo@chromium.org this->init(); 751a0c7edbb0804144ab320951db5c741eea247fc0fvandebo@chromium.org} 752a0c7edbb0804144ab320951db5c741eea247fc0fvandebo@chromium.org 753663515bc59325092c4e47f5189782bd6fcd0586avandebo@chromium.org// TODO(vandebo) change layerSize to SkSize. 754a0c7edbb0804144ab320951db5c741eea247fc0fvandebo@chromium.orgSkPDFDevice::SkPDFDevice(const SkISize& layerSize, 755a0c7edbb0804144ab320951db5c741eea247fc0fvandebo@chromium.org const SkClipStack& existingClipStack, 756a0c7edbb0804144ab320951db5c741eea247fc0fvandebo@chromium.org const SkRegion& existingClipRegion) 75789443aba5bfa2b040dc9fd24938b7d0b3decd737reed : fPageSize(layerSize) 75889443aba5bfa2b040dc9fd24938b7d0b3decd737reed , fContentSize(layerSize) 75989443aba5bfa2b040dc9fd24938b7d0b3decd737reed , fExistingClipStack(existingClipStack) 76089443aba5bfa2b040dc9fd24938b7d0b3decd737reed , fExistingClipRegion(existingClipRegion) 76189443aba5bfa2b040dc9fd24938b7d0b3decd737reed , fLastContentEntry(NULL) 76289443aba5bfa2b040dc9fd24938b7d0b3decd737reed , fLastMarginContentEntry(NULL) 76389443aba5bfa2b040dc9fd24938b7d0b3decd737reed , fClipStack(NULL) 76489443aba5bfa2b040dc9fd24938b7d0b3decd737reed , fEncoder(NULL) 76589443aba5bfa2b040dc9fd24938b7d0b3decd737reed , fRasterDpi(72.0f) 76689443aba5bfa2b040dc9fd24938b7d0b3decd737reed{ 767a0c7edbb0804144ab320951db5c741eea247fc0fvandebo@chromium.org fInitialTransform.reset(); 76889443aba5bfa2b040dc9fd24938b7d0b3decd737reed fLegacyBitmap.setInfo(make_content_info(layerSize, NULL)); 76989443aba5bfa2b040dc9fd24938b7d0b3decd737reed 77077bcaa324a574584331322d98768582d9232f7fcvandebo@chromium.org this->init(); 77177bcaa324a574584331322d98768582d9232f7fcvandebo@chromium.org} 77277bcaa324a574584331322d98768582d9232f7fcvandebo@chromium.org 77377bcaa324a574584331322d98768582d9232f7fcvandebo@chromium.orgSkPDFDevice::~SkPDFDevice() { 7749859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org this->cleanUp(true); 77577bcaa324a574584331322d98768582d9232f7fcvandebo@chromium.org} 77677bcaa324a574584331322d98768582d9232f7fcvandebo@chromium.org 77777bcaa324a574584331322d98768582d9232f7fcvandebo@chromium.orgvoid SkPDFDevice::init() { 7782a006c112743e07ce258ca223631fc19233f5ddcreed@google.com fAnnotations = NULL; 77977bcaa324a574584331322d98768582d9232f7fcvandebo@chromium.org fResourceDict = NULL; 780e02944075840d672bd1797f3d945ff82d302282fcommit-bot@chromium.org fContentEntries.free(); 781b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org fLastContentEntry = NULL; 782e02944075840d672bd1797f3d945ff82d302282fcommit-bot@chromium.org fMarginContentEntries.free(); 7838dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org fLastMarginContentEntry = NULL; 7849859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org fDrawingArea = kContent_DrawingArea; 785e02944075840d672bd1797f3d945ff82d302282fcommit-bot@chromium.org if (fFontGlyphUsage.get() == NULL) { 7869859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org fFontGlyphUsage.reset(new SkPDFGlyphSetMap()); 7879859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org } 7889b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org} 7899b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org 7909859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.orgvoid SkPDFDevice::cleanUp(bool clearFontUsage) { 7919b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org fGraphicStateResources.unrefAll(); 7929b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org fXObjectResources.unrefAll(); 79328be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org fFontResources.unrefAll(); 794da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org fShaderResources.unrefAll(); 7952a006c112743e07ce258ca223631fc19233f5ddcreed@google.com SkSafeUnref(fAnnotations); 796fc641d09e5a1a9f7fae369ae06a8b96089faf57breed@google.com SkSafeUnref(fResourceDict); 797b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com fNamedDestinations.deleteAll(); 7982a006c112743e07ce258ca223631fc19233f5ddcreed@google.com 7999859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org if (clearFontUsage) { 8009859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org fFontGlyphUsage->reset(); 8019859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org } 8029b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org} 8039b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org 8049fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.orgvoid SkPDFDevice::clear(SkColor color) { 8059859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org this->cleanUp(true); 80677bcaa324a574584331322d98768582d9232f7fcvandebo@chromium.org this->init(); 80777bcaa324a574584331322d98768582d9232f7fcvandebo@chromium.org 80877bcaa324a574584331322d98768582d9232f7fcvandebo@chromium.org SkPaint paint; 80977bcaa324a574584331322d98768582d9232f7fcvandebo@chromium.org paint.setColor(color); 81077bcaa324a574584331322d98768582d9232f7fcvandebo@chromium.org paint.setStyle(SkPaint::kFill_Style); 8119fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org SkMatrix identity; 8129fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org identity.reset(); 81313d14a9dbd2cf0a9654045cc967e92626690631avandebo@chromium.org ScopedContentEntry content(this, &fExistingClipStack, fExistingClipRegion, 81413d14a9dbd2cf0a9654045cc967e92626690631avandebo@chromium.org identity, paint); 815b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org internalDrawPaint(paint, content.entry()); 8169b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org} 8179b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org 8189b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.orgvoid SkPDFDevice::drawPaint(const SkDraw& d, const SkPaint& paint) { 8199b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org SkPaint newPaint = paint; 8209b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org newPaint.setStyle(SkPaint::kFill_Style); 82113d14a9dbd2cf0a9654045cc967e92626690631avandebo@chromium.org ScopedContentEntry content(this, d, newPaint); 822b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org internalDrawPaint(newPaint, content.entry()); 82377bcaa324a574584331322d98768582d9232f7fcvandebo@chromium.org} 82477bcaa324a574584331322d98768582d9232f7fcvandebo@chromium.org 825b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.orgvoid SkPDFDevice::internalDrawPaint(const SkPaint& paint, 826b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org ContentEntry* contentEntry) { 827b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org if (!contentEntry) { 828b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org return; 829b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org } 83077bcaa324a574584331322d98768582d9232f7fcvandebo@chromium.org SkRect bbox = SkRect::MakeWH(SkIntToScalar(this->width()), 83177bcaa324a574584331322d98768582d9232f7fcvandebo@chromium.org SkIntToScalar(this->height())); 83277bcaa324a574584331322d98768582d9232f7fcvandebo@chromium.org SkMatrix inverse; 833d2cfa7422e2b0928970b3b0fa1abe1d73113fc1dcommit-bot@chromium.org if (!contentEntry->fState.fMatrix.invert(&inverse)) { 834386dfc049baa400c13e4e98727d4c04d0242b7b8vandebo@chromium.org return; 835b054990307b7338e599a12d9af10eb2058b94051vandebo@chromium.org } 83677bcaa324a574584331322d98768582d9232f7fcvandebo@chromium.org inverse.mapRect(&bbox); 83777bcaa324a574584331322d98768582d9232f7fcvandebo@chromium.org 838b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org SkPDFUtils::AppendRectangle(bbox, &contentEntry->fContent); 8399fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org SkPDFUtils::PaintPath(paint.getStyle(), SkPath::kWinding_FillType, 840b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org &contentEntry->fContent); 8419b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org} 8429b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org 8439b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.orgvoid SkPDFDevice::drawPoints(const SkDraw& d, SkCanvas::PointMode mode, 8449b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org size_t count, const SkPoint* points, 84525adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org const SkPaint& passedPaint) { 84625adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org if (count == 0) { 84725adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org return; 84825adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org } 84925adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org 850b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com if (handlePointAnnotation(points, count, *d.fMatrix, passedPaint)) { 851b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com return; 852b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com } 853b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com 854ff3903202e5bce39016bac896ba6a417dc707d52vandebo@chromium.org // SkDraw::drawPoints converts to multiple calls to fDevice->drawPath. 855ff3903202e5bce39016bac896ba6a417dc707d52vandebo@chromium.org // We only use this when there's a path effect because of the overhead 856ff3903202e5bce39016bac896ba6a417dc707d52vandebo@chromium.org // of multiple calls to setUpContentEntry it causes. 857ff3903202e5bce39016bac896ba6a417dc707d52vandebo@chromium.org if (passedPaint.getPathEffect()) { 858ff3903202e5bce39016bac896ba6a417dc707d52vandebo@chromium.org if (d.fClip->isEmpty()) { 859ff3903202e5bce39016bac896ba6a417dc707d52vandebo@chromium.org return; 860ff3903202e5bce39016bac896ba6a417dc707d52vandebo@chromium.org } 861ff3903202e5bce39016bac896ba6a417dc707d52vandebo@chromium.org SkDraw pointDraw(d); 862ff3903202e5bce39016bac896ba6a417dc707d52vandebo@chromium.org pointDraw.fDevice = this; 863ff3903202e5bce39016bac896ba6a417dc707d52vandebo@chromium.org pointDraw.drawPoints(mode, count, points, passedPaint, true); 864ff3903202e5bce39016bac896ba6a417dc707d52vandebo@chromium.org return; 865ff3903202e5bce39016bac896ba6a417dc707d52vandebo@chromium.org } 866ff3903202e5bce39016bac896ba6a417dc707d52vandebo@chromium.org 86725adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org const SkPaint* paint = &passedPaint; 86825adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org SkPaint modifiedPaint; 86925adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org 87025adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org if (mode == SkCanvas::kPoints_PointMode && 87125adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org paint->getStrokeCap() != SkPaint::kRound_Cap) { 87225adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org modifiedPaint = *paint; 87325adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org paint = &modifiedPaint; 87425adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org if (paint->getStrokeWidth()) { 87525adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org // PDF won't draw a single point with square/butt caps because the 87625adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org // orientation is ambiguous. Draw a rectangle instead. 87725adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org modifiedPaint.setStyle(SkPaint::kFill_Style); 87825adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org SkScalar strokeWidth = paint->getStrokeWidth(); 87925adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org SkScalar halfStroke = SkScalarHalf(strokeWidth); 88025adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org for (size_t i = 0; i < count; i++) { 88125adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org SkRect r = SkRect::MakeXYWH(points[i].fX, points[i].fY, 0, 0); 88225adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org r.inset(-halfStroke, -halfStroke); 88325adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org drawRect(d, r, modifiedPaint); 88425adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org } 88525adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org return; 88625adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org } else { 88725adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org modifiedPaint.setStrokeCap(SkPaint::kRound_Cap); 88825adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org } 88925adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org } 89025adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org 89113d14a9dbd2cf0a9654045cc967e92626690631avandebo@chromium.org ScopedContentEntry content(this, d, *paint); 892b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org if (!content.entry()) { 8939b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org return; 894fb0b0edd86d71bb423fa921eaac1e2071602115cvandebo@chromium.org } 8959b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org 8969b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org switch (mode) { 8979b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org case SkCanvas::kPolygon_PointMode: 8989fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org SkPDFUtils::MoveTo(points[0].fX, points[0].fY, 899b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org &content.entry()->fContent); 9009db86bb9cd1b77be0afc504ccc07026e4282d7e7ctguil@chromium.org for (size_t i = 1; i < count; i++) { 9019fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org SkPDFUtils::AppendLine(points[i].fX, points[i].fY, 902b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org &content.entry()->fContent); 9039db86bb9cd1b77be0afc504ccc07026e4282d7e7ctguil@chromium.org } 904b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org SkPDFUtils::StrokePath(&content.entry()->fContent); 9059b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org break; 9069b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org case SkCanvas::kLines_PointMode: 9079b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org for (size_t i = 0; i < count/2; i++) { 9089db86bb9cd1b77be0afc504ccc07026e4282d7e7ctguil@chromium.org SkPDFUtils::MoveTo(points[i * 2].fX, points[i * 2].fY, 909b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org &content.entry()->fContent); 9109db86bb9cd1b77be0afc504ccc07026e4282d7e7ctguil@chromium.org SkPDFUtils::AppendLine(points[i * 2 + 1].fX, 9119fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org points[i * 2 + 1].fY, 912b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org &content.entry()->fContent); 913b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org SkPDFUtils::StrokePath(&content.entry()->fContent); 9149b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org } 9159b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org break; 9169b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org case SkCanvas::kPoints_PointMode: 91725adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org SkASSERT(paint->getStrokeCap() == SkPaint::kRound_Cap); 91825adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org for (size_t i = 0; i < count; i++) { 91925adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org SkPDFUtils::MoveTo(points[i].fX, points[i].fY, 920b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org &content.entry()->fContent); 921b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org SkPDFUtils::ClosePath(&content.entry()->fContent); 922b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org SkPDFUtils::StrokePath(&content.entry()->fContent); 9239b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org } 9249b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org break; 9259b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org default: 9269b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org SkASSERT(false); 9279b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org } 9289b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org} 9299b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org 930969fd6afc45df247377c35d9a273dce752af04aacommit-bot@chromium.orgvoid SkPDFDevice::drawRect(const SkDraw& d, const SkRect& rect, 9319b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org const SkPaint& paint) { 932969fd6afc45df247377c35d9a273dce752af04aacommit-bot@chromium.org SkRect r = rect; 933969fd6afc45df247377c35d9a273dce752af04aacommit-bot@chromium.org r.sort(); 934969fd6afc45df247377c35d9a273dce752af04aacommit-bot@chromium.org 9359b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org if (paint.getPathEffect()) { 93625adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org if (d.fClip->isEmpty()) { 93725adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org return; 93825adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org } 9399b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org SkPath path; 9409b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org path.addRect(r); 941ff3903202e5bce39016bac896ba6a417dc707d52vandebo@chromium.org drawPath(d, path, paint, NULL, true); 9429b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org return; 9439b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org } 944b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org 945b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com if (handleRectAnnotation(r, *d.fMatrix, paint)) { 946238be8c7e5de5a83517440a3db7f7965b47fb010vandebo@chromium.org return; 947238be8c7e5de5a83517440a3db7f7965b47fb010vandebo@chromium.org } 948238be8c7e5de5a83517440a3db7f7965b47fb010vandebo@chromium.org 94913d14a9dbd2cf0a9654045cc967e92626690631avandebo@chromium.org ScopedContentEntry content(this, d, paint); 950b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org if (!content.entry()) { 95125adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org return; 95225adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org } 953b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org SkPDFUtils::AppendRectangle(r, &content.entry()->fContent); 9549db86bb9cd1b77be0afc504ccc07026e4282d7e7ctguil@chromium.org SkPDFUtils::PaintPath(paint.getStyle(), SkPath::kWinding_FillType, 955b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org &content.entry()->fContent); 9569b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org} 9579b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org 95889443aba5bfa2b040dc9fd24938b7d0b3decd737reedvoid SkPDFDevice::drawRRect(const SkDraw& draw, const SkRRect& rrect, const SkPaint& paint) { 959a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com SkPath path; 960a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com path.addRRect(rrect); 961a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com this->drawPath(draw, path, paint, NULL, true); 962a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com} 963a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com 96489443aba5bfa2b040dc9fd24938b7d0b3decd737reedvoid SkPDFDevice::drawOval(const SkDraw& draw, const SkRect& oval, const SkPaint& paint) { 96589443aba5bfa2b040dc9fd24938b7d0b3decd737reed SkPath path; 96689443aba5bfa2b040dc9fd24938b7d0b3decd737reed path.addOval(oval); 96789443aba5bfa2b040dc9fd24938b7d0b3decd737reed this->drawPath(draw, path, paint, NULL, true); 96889443aba5bfa2b040dc9fd24938b7d0b3decd737reed} 96989443aba5bfa2b040dc9fd24938b7d0b3decd737reed 970ff3903202e5bce39016bac896ba6a417dc707d52vandebo@chromium.orgvoid SkPDFDevice::drawPath(const SkDraw& d, const SkPath& origPath, 97102cc5aa736086320649d8a932515691ae18a0dd5vandebo@chromium.org const SkPaint& paint, const SkMatrix* prePathMatrix, 97202cc5aa736086320649d8a932515691ae18a0dd5vandebo@chromium.org bool pathIsMutable) { 973ff3903202e5bce39016bac896ba6a417dc707d52vandebo@chromium.org SkPath modifiedPath; 974ff3903202e5bce39016bac896ba6a417dc707d52vandebo@chromium.org SkPath* pathPtr = const_cast<SkPath*>(&origPath); 975ff3903202e5bce39016bac896ba6a417dc707d52vandebo@chromium.org 976ff3903202e5bce39016bac896ba6a417dc707d52vandebo@chromium.org SkMatrix matrix = *d.fMatrix; 977ff3903202e5bce39016bac896ba6a417dc707d52vandebo@chromium.org if (prePathMatrix) { 978ff3903202e5bce39016bac896ba6a417dc707d52vandebo@chromium.org if (paint.getPathEffect() || paint.getStyle() != SkPaint::kFill_Style) { 979ff3903202e5bce39016bac896ba6a417dc707d52vandebo@chromium.org if (!pathIsMutable) { 980ff3903202e5bce39016bac896ba6a417dc707d52vandebo@chromium.org pathPtr = &modifiedPath; 981ff3903202e5bce39016bac896ba6a417dc707d52vandebo@chromium.org pathIsMutable = true; 982ff3903202e5bce39016bac896ba6a417dc707d52vandebo@chromium.org } 983ff3903202e5bce39016bac896ba6a417dc707d52vandebo@chromium.org origPath.transform(*prePathMatrix, pathPtr); 984ff3903202e5bce39016bac896ba6a417dc707d52vandebo@chromium.org } else { 98592362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org matrix.preConcat(*prePathMatrix); 986ff3903202e5bce39016bac896ba6a417dc707d52vandebo@chromium.org } 987ff3903202e5bce39016bac896ba6a417dc707d52vandebo@chromium.org } 98802cc5aa736086320649d8a932515691ae18a0dd5vandebo@chromium.org 9897d71f7f655cab6b6194f6c765ca33c1a6d512f5evandebo@chromium.org if (paint.getPathEffect()) { 99025adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org if (d.fClip->isEmpty()) { 99125adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org return; 99225adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org } 993ff3903202e5bce39016bac896ba6a417dc707d52vandebo@chromium.org if (!pathIsMutable) { 994ff3903202e5bce39016bac896ba6a417dc707d52vandebo@chromium.org pathPtr = &modifiedPath; 995ff3903202e5bce39016bac896ba6a417dc707d52vandebo@chromium.org pathIsMutable = true; 996ff3903202e5bce39016bac896ba6a417dc707d52vandebo@chromium.org } 997ff3903202e5bce39016bac896ba6a417dc707d52vandebo@chromium.org bool fill = paint.getFillPath(origPath, pathPtr); 9987d71f7f655cab6b6194f6c765ca33c1a6d512f5evandebo@chromium.org 9997e2ff7cf7da604b29378978ef5d4655499485368vandebo@chromium.org SkPaint noEffectPaint(paint); 1000ff3903202e5bce39016bac896ba6a417dc707d52vandebo@chromium.org noEffectPaint.setPathEffect(NULL); 1001ff3903202e5bce39016bac896ba6a417dc707d52vandebo@chromium.org if (fill) { 1002ff3903202e5bce39016bac896ba6a417dc707d52vandebo@chromium.org noEffectPaint.setStyle(SkPaint::kFill_Style); 1003ff3903202e5bce39016bac896ba6a417dc707d52vandebo@chromium.org } else { 1004ff3903202e5bce39016bac896ba6a417dc707d52vandebo@chromium.org noEffectPaint.setStyle(SkPaint::kStroke_Style); 1005ff3903202e5bce39016bac896ba6a417dc707d52vandebo@chromium.org noEffectPaint.setStrokeWidth(0); 1006ff3903202e5bce39016bac896ba6a417dc707d52vandebo@chromium.org } 1007ff3903202e5bce39016bac896ba6a417dc707d52vandebo@chromium.org drawPath(d, *pathPtr, noEffectPaint, NULL, true); 10087d71f7f655cab6b6194f6c765ca33c1a6d512f5evandebo@chromium.org return; 10097d71f7f655cab6b6194f6c765ca33c1a6d512f5evandebo@chromium.org } 1010ff3903202e5bce39016bac896ba6a417dc707d52vandebo@chromium.org 101192ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org#ifdef SK_PDF_USE_PATHOPS 1012a9ebd161a7c08515f0c4bd885e61c4b52688ececedisonn@google.com if (handleInversePath(d, origPath, paint, pathIsMutable, prePathMatrix)) { 101392ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org return; 101492ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org } 101592ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org#endif 101692ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org 1017a9ebd161a7c08515f0c4bd885e61c4b52688ececedisonn@google.com if (handleRectAnnotation(pathPtr->getBounds(), matrix, paint)) { 1018238be8c7e5de5a83517440a3db7f7965b47fb010vandebo@chromium.org return; 1019238be8c7e5de5a83517440a3db7f7965b47fb010vandebo@chromium.org } 1020238be8c7e5de5a83517440a3db7f7965b47fb010vandebo@chromium.org 1021a9ebd161a7c08515f0c4bd885e61c4b52688ececedisonn@google.com ScopedContentEntry content(this, d.fClipStack, *d.fClip, matrix, paint); 1022b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org if (!content.entry()) { 102325adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org return; 102425adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org } 1025683001ce0de70c859ea5e5353245b18cadbefc45vandebo@chromium.org SkPDFUtils::EmitPath(*pathPtr, paint.getStyle(), 1026683001ce0de70c859ea5e5353245b18cadbefc45vandebo@chromium.org &content.entry()->fContent); 1027ff3903202e5bce39016bac896ba6a417dc707d52vandebo@chromium.org SkPDFUtils::PaintPath(paint.getStyle(), pathPtr->getFillType(), 1028b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org &content.entry()->fContent); 10299b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org} 10309b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org 10312ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.comvoid SkPDFDevice::drawBitmapRect(const SkDraw& draw, const SkBitmap& bitmap, 10322ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com const SkRect* src, const SkRect& dst, 1033eed779d866e1e239bfb9ebc6a225b7345a41adf9commit-bot@chromium.org const SkPaint& paint, 1034eed779d866e1e239bfb9ebc6a225b7345a41adf9commit-bot@chromium.org SkCanvas::DrawBitmapRectFlags flags) { 1035eed779d866e1e239bfb9ebc6a225b7345a41adf9commit-bot@chromium.org // TODO: this code path must be updated to respect the flags parameter 10362ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com SkMatrix matrix; 10372ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com SkRect bitmapBounds, tmpSrc, tmpDst; 10382ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com SkBitmap tmpBitmap; 10392ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com 10402ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com bitmapBounds.isetWH(bitmap.width(), bitmap.height()); 10412ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com 10422ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com // Compute matrix from the two rectangles 10432ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com if (src) { 10442ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com tmpSrc = *src; 10452ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com } else { 10462ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com tmpSrc = bitmapBounds; 10472ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com } 10482ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com matrix.setRectToRect(tmpSrc, dst, SkMatrix::kFill_ScaleToFit); 10492ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com 10502ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com const SkBitmap* bitmapPtr = &bitmap; 10512ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com 10522ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com // clip the tmpSrc to the bounds of the bitmap, and recompute dstRect if 10532ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com // needed (if the src was clipped). No check needed if src==null. 10542ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com if (src) { 10552ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com if (!bitmapBounds.contains(*src)) { 10562ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com if (!tmpSrc.intersect(bitmapBounds)) { 10572ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com return; // nothing to draw 10582ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com } 10592ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com // recompute dst, based on the smaller tmpSrc 10602ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com matrix.mapRect(&tmpDst, tmpSrc); 10612ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com } 10622ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com 10632ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com // since we may need to clamp to the borders of the src rect within 10642ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com // the bitmap, we extract a subset. 10652ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com // TODO: make sure this is handled in drawBitmap and remove from here. 10662ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com SkIRect srcIR; 10672ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com tmpSrc.roundOut(&srcIR); 10682ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com if (!bitmap.extractSubset(&tmpBitmap, srcIR)) { 10692ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com return; 10702ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com } 10712ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com bitmapPtr = &tmpBitmap; 10722ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com 10732ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com // Since we did an extract, we need to adjust the matrix accordingly 10742ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com SkScalar dx = 0, dy = 0; 10752ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com if (srcIR.fLeft > 0) { 10762ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com dx = SkIntToScalar(srcIR.fLeft); 10772ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com } 10782ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com if (srcIR.fTop > 0) { 10792ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com dy = SkIntToScalar(srcIR.fTop); 10802ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com } 10812ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com if (dx || dy) { 10822ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com matrix.preTranslate(dx, dy); 10832ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com } 10842ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com } 10859bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com this->drawBitmap(draw, *bitmapPtr, matrix, paint); 10862ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com} 10872ae67e70cd06be3f64c6290be7724af8ce6bc853edisonn@google.com 1088fb0b0edd86d71bb423fa921eaac1e2071602115cvandebo@chromium.orgvoid SkPDFDevice::drawBitmap(const SkDraw& d, const SkBitmap& bitmap, 10899bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com const SkMatrix& matrix, const SkPaint& paint) { 1090fb0b0edd86d71bb423fa921eaac1e2071602115cvandebo@chromium.org if (d.fClip->isEmpty()) { 1091fb0b0edd86d71bb423fa921eaac1e2071602115cvandebo@chromium.org return; 1092fb0b0edd86d71bb423fa921eaac1e2071602115cvandebo@chromium.org } 1093fb0b0edd86d71bb423fa921eaac1e2071602115cvandebo@chromium.org 10947e2ff7cf7da604b29378978ef5d4655499485368vandebo@chromium.org SkMatrix transform = matrix; 10959fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org transform.postConcat(*d.fMatrix); 10963b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org this->internalDrawBitmap(transform, d.fClipStack, *d.fClip, bitmap, NULL, 10973b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org paint); 10989b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org} 10999b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org 1100fb0b0edd86d71bb423fa921eaac1e2071602115cvandebo@chromium.orgvoid SkPDFDevice::drawSprite(const SkDraw& d, const SkBitmap& bitmap, 11019b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org int x, int y, const SkPaint& paint) { 1102fb0b0edd86d71bb423fa921eaac1e2071602115cvandebo@chromium.org if (d.fClip->isEmpty()) { 1103fb0b0edd86d71bb423fa921eaac1e2071602115cvandebo@chromium.org return; 1104fb0b0edd86d71bb423fa921eaac1e2071602115cvandebo@chromium.org } 1105fb0b0edd86d71bb423fa921eaac1e2071602115cvandebo@chromium.org 11067e2ff7cf7da604b29378978ef5d4655499485368vandebo@chromium.org SkMatrix matrix; 1107a6d59f60aab59fb6556841b063ead5d49b46ba8dreed@google.com matrix.setTranslate(SkIntToScalar(x), SkIntToScalar(y)); 11083b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org this->internalDrawBitmap(matrix, d.fClipStack, *d.fClip, bitmap, NULL, 11093b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org paint); 11109b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org} 11119b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org 111228be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.orgvoid SkPDFDevice::drawText(const SkDraw& d, const void* text, size_t len, 11139b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org SkScalar x, SkScalar y, const SkPaint& paint) { 1114b62f93fdbcdea16329847e30a351ee35a0552e83edisonn@google.com NOT_IMPLEMENTED(paint.getMaskFilter() != NULL, false); 1115b62f93fdbcdea16329847e30a351ee35a0552e83edisonn@google.com if (paint.getMaskFilter() != NULL) { 1116b62f93fdbcdea16329847e30a351ee35a0552e83edisonn@google.com // Don't pretend we support drawing MaskFilters, it makes for artifacts 1117b62f93fdbcdea16329847e30a351ee35a0552e83edisonn@google.com // making text unreadable (e.g. same text twice when using CSS shadows). 1118b62f93fdbcdea16329847e30a351ee35a0552e83edisonn@google.com return; 1119b62f93fdbcdea16329847e30a351ee35a0552e83edisonn@google.com } 112025adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org SkPaint textPaint = calculate_text_paint(paint); 112113d14a9dbd2cf0a9654045cc967e92626690631avandebo@chromium.org ScopedContentEntry content(this, d, textPaint, true); 1122b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org if (!content.entry()) { 1123fb0b0edd86d71bb423fa921eaac1e2071602115cvandebo@chromium.org return; 1124fb0b0edd86d71bb423fa921eaac1e2071602115cvandebo@chromium.org } 1125fb0b0edd86d71bb423fa921eaac1e2071602115cvandebo@chromium.org 11264e1cc6ac450903510b96c1b12f6ee6f420044a66vandebo@chromium.org SkGlyphStorage storage(0); 1127139c136944f3af0cba3a25ac65c642c05fe46ac8bungeman const uint16_t* glyphIDs = NULL; 1128aec406650cbfa4ef65d83db5ff4f82572e8e098freed@google.com int numGlyphs = force_glyph_encoding(paint, text, len, &storage, &glyphIDs); 11294e1cc6ac450903510b96c1b12f6ee6f420044a66vandebo@chromium.org textPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); 113028be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org 113128be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org SkDrawCacheProc glyphCacheProc = textPaint.getDrawCacheProc(); 11329a87cee904e2d8f0ea6a0e7e3ca864262a8cb7c4bungeman@google.com align_text(glyphCacheProc, textPaint, glyphIDs, numGlyphs, &x, &y); 1133b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org content.entry()->fContent.writeText("BT\n"); 1134b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org set_text_transform(x, y, textPaint.getTextSkewX(), 1135b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org &content.entry()->fContent); 1136aec406650cbfa4ef65d83db5ff4f82572e8e098freed@google.com int consumedGlyphCount = 0; 11372a22e10ab2946c5590cd2a258427ce3ccfca9bfavandebo@chromium.org while (numGlyphs > consumedGlyphCount) { 1138b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org updateFont(textPaint, glyphIDs[consumedGlyphCount], content.entry()); 1139b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org SkPDFFont* font = content.entry()->fState.fFont; 1140139c136944f3af0cba3a25ac65c642c05fe46ac8bungeman //TODO: the const_cast here is a bug if the encoding started out as glyph encoding. 1141aec406650cbfa4ef65d83db5ff4f82572e8e098freed@google.com int availableGlyphs = 1142139c136944f3af0cba3a25ac65c642c05fe46ac8bungeman font->glyphsToPDFFontEncoding(const_cast<uint16_t*>(glyphIDs) + consumedGlyphCount, 11430129410fbe4b88a0632fb7aa5185610b30e69852vandebo@chromium.org numGlyphs - consumedGlyphCount); 11449859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org fFontGlyphUsage->noteGlyphUsage(font, glyphIDs + consumedGlyphCount, 11459859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org availableGlyphs); 1146cae5fba82e687d674b076b10cdc8aba46e1ac3b3vandebo@chromium.org SkString encodedString = 1147f6c3ebdeb135dcdb9af225bd7af77f1fe1f92787reed@google.com SkPDFString::FormatString(glyphIDs + consumedGlyphCount, 1148cae5fba82e687d674b076b10cdc8aba46e1ac3b3vandebo@chromium.org availableGlyphs, font->multiByteGlyphs()); 1149b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org content.entry()->fContent.writeText(encodedString.c_str()); 11500129410fbe4b88a0632fb7aa5185610b30e69852vandebo@chromium.org consumedGlyphCount += availableGlyphs; 1151b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org content.entry()->fContent.writeText(" Tj\n"); 11522a22e10ab2946c5590cd2a258427ce3ccfca9bfavandebo@chromium.org } 1153b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org content.entry()->fContent.writeText("ET\n"); 11549b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org} 11559b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org 1156fb0b0edd86d71bb423fa921eaac1e2071602115cvandebo@chromium.orgvoid SkPDFDevice::drawPosText(const SkDraw& d, const void* text, size_t len, 11579b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org const SkScalar pos[], SkScalar constY, 11589b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org int scalarsPerPos, const SkPaint& paint) { 1159b62f93fdbcdea16329847e30a351ee35a0552e83edisonn@google.com NOT_IMPLEMENTED(paint.getMaskFilter() != NULL, false); 1160b62f93fdbcdea16329847e30a351ee35a0552e83edisonn@google.com if (paint.getMaskFilter() != NULL) { 1161b62f93fdbcdea16329847e30a351ee35a0552e83edisonn@google.com // Don't pretend we support drawing MaskFilters, it makes for artifacts 1162b62f93fdbcdea16329847e30a351ee35a0552e83edisonn@google.com // making text unreadable (e.g. same text twice when using CSS shadows). 1163b62f93fdbcdea16329847e30a351ee35a0552e83edisonn@google.com return; 1164b62f93fdbcdea16329847e30a351ee35a0552e83edisonn@google.com } 116528be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org SkASSERT(1 == scalarsPerPos || 2 == scalarsPerPos); 11669fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org SkPaint textPaint = calculate_text_paint(paint); 116713d14a9dbd2cf0a9654045cc967e92626690631avandebo@chromium.org ScopedContentEntry content(this, d, textPaint, true); 1168b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org if (!content.entry()) { 116925adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org return; 117025adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org } 117128be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org 11724e1cc6ac450903510b96c1b12f6ee6f420044a66vandebo@chromium.org SkGlyphStorage storage(0); 1173139c136944f3af0cba3a25ac65c642c05fe46ac8bungeman const uint16_t* glyphIDs = NULL; 1174139c136944f3af0cba3a25ac65c642c05fe46ac8bungeman size_t numGlyphs = force_glyph_encoding(paint, text, len, &storage, &glyphIDs); 11754e1cc6ac450903510b96c1b12f6ee6f420044a66vandebo@chromium.org textPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); 117628be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org 117728be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org SkDrawCacheProc glyphCacheProc = textPaint.getDrawCacheProc(); 1178b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org content.entry()->fContent.writeText("BT\n"); 1179b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org updateFont(textPaint, glyphIDs[0], content.entry()); 11802a22e10ab2946c5590cd2a258427ce3ccfca9bfavandebo@chromium.org for (size_t i = 0; i < numGlyphs; i++) { 1181b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org SkPDFFont* font = content.entry()->fState.fFont; 11820129410fbe4b88a0632fb7aa5185610b30e69852vandebo@chromium.org uint16_t encodedValue = glyphIDs[i]; 11830129410fbe4b88a0632fb7aa5185610b30e69852vandebo@chromium.org if (font->glyphsToPDFFontEncoding(&encodedValue, 1) != 1) { 1184139c136944f3af0cba3a25ac65c642c05fe46ac8bungeman // The current pdf font cannot encode the current glyph. 1185139c136944f3af0cba3a25ac65c642c05fe46ac8bungeman // Try to get a pdf font which can encode the current glyph. 1186b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org updateFont(textPaint, glyphIDs[i], content.entry()); 1187139c136944f3af0cba3a25ac65c642c05fe46ac8bungeman font = content.entry()->fState.fFont; 1188139c136944f3af0cba3a25ac65c642c05fe46ac8bungeman if (font->glyphsToPDFFontEncoding(&encodedValue, 1) != 1) { 1189139c136944f3af0cba3a25ac65c642c05fe46ac8bungeman SkDEBUGFAIL("PDF could not encode glyph."); 1190139c136944f3af0cba3a25ac65c642c05fe46ac8bungeman continue; 1191139c136944f3af0cba3a25ac65c642c05fe46ac8bungeman } 11922a22e10ab2946c5590cd2a258427ce3ccfca9bfavandebo@chromium.org } 1193139c136944f3af0cba3a25ac65c642c05fe46ac8bungeman 11949859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org fFontGlyphUsage->noteGlyphUsage(font, &encodedValue, 1); 119528be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org SkScalar x = pos[i * scalarsPerPos]; 119628be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org SkScalar y = scalarsPerPos == 1 ? constY : pos[i * scalarsPerPos + 1]; 11979a87cee904e2d8f0ea6a0e7e3ca864262a8cb7c4bungeman@google.com align_text(glyphCacheProc, textPaint, glyphIDs + i, 1, &x, &y); 1198139c136944f3af0cba3a25ac65c642c05fe46ac8bungeman set_text_transform(x, y, textPaint.getTextSkewX(), &content.entry()->fContent); 1199cae5fba82e687d674b076b10cdc8aba46e1ac3b3vandebo@chromium.org SkString encodedString = 1200139c136944f3af0cba3a25ac65c642c05fe46ac8bungeman SkPDFString::FormatString(&encodedValue, 1, font->multiByteGlyphs()); 1201b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org content.entry()->fContent.writeText(encodedString.c_str()); 1202b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org content.entry()->fContent.writeText(" Tj\n"); 120328be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org } 1204b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org content.entry()->fContent.writeText("ET\n"); 12059b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org} 12069b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org 1207fb0b0edd86d71bb423fa921eaac1e2071602115cvandebo@chromium.orgvoid SkPDFDevice::drawTextOnPath(const SkDraw& d, const void* text, size_t len, 12089b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org const SkPath& path, const SkMatrix* matrix, 12099b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org const SkPaint& paint) { 1210fb0b0edd86d71bb423fa921eaac1e2071602115cvandebo@chromium.org if (d.fClip->isEmpty()) { 1211fb0b0edd86d71bb423fa921eaac1e2071602115cvandebo@chromium.org return; 1212fb0b0edd86d71bb423fa921eaac1e2071602115cvandebo@chromium.org } 1213290e3bbcf4c8b33c161d7b6a3edb12168e0e6910vandebo@chromium.org d.drawTextOnPath((const char*)text, len, path, matrix, paint); 12149b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org} 12159b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org 1216fb0b0edd86d71bb423fa921eaac1e2071602115cvandebo@chromium.orgvoid SkPDFDevice::drawVertices(const SkDraw& d, SkCanvas::VertexMode, 12179b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org int vertexCount, const SkPoint verts[], 12189b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org const SkPoint texs[], const SkColor colors[], 12199b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org SkXfermode* xmode, const uint16_t indices[], 12209b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org int indexCount, const SkPaint& paint) { 1221fb0b0edd86d71bb423fa921eaac1e2071602115cvandebo@chromium.org if (d.fClip->isEmpty()) { 1222fb0b0edd86d71bb423fa921eaac1e2071602115cvandebo@chromium.org return; 1223fb0b0edd86d71bb423fa921eaac1e2071602115cvandebo@chromium.org } 122485e143c33c214e54187aa28146aa7666961a0d17reed@google.com // TODO: implement drawVertices 12259b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org} 12269b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org 12273b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.orgvoid SkPDFDevice::drawDevice(const SkDraw& d, SkBaseDevice* device, 12283b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org int x, int y, const SkPaint& paint) { 12293da3b621c34810514a6d415a1dc782bd21648c3ccommit-bot@chromium.org // our onCreateDevice() always creates SkPDFDevice subclasses. 1230ee7a9569f2745b949dbafa15927d70a4e08c92aevandebo@chromium.org SkPDFDevice* pdfDevice = static_cast<SkPDFDevice*>(device); 1231f4ff39ca4854d64fce9189745af615bb9bc37faactguil@chromium.org if (pdfDevice->isContentEmpty()) { 1232ee7a9569f2745b949dbafa15927d70a4e08c92aevandebo@chromium.org return; 1233ee7a9569f2745b949dbafa15927d70a4e08c92aevandebo@chromium.org } 1234ee7a9569f2745b949dbafa15927d70a4e08c92aevandebo@chromium.org 1235eb6c7596af1a1fc7860e27ff2f678a33b2576c0fvandebo@chromium.org SkMatrix matrix; 1236a6d59f60aab59fb6556841b063ead5d49b46ba8dreed@google.com matrix.setTranslate(SkIntToScalar(x), SkIntToScalar(y)); 123713d14a9dbd2cf0a9654045cc967e92626690631avandebo@chromium.org ScopedContentEntry content(this, d.fClipStack, *d.fClip, matrix, paint); 1238b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org if (!content.entry()) { 123925adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org return; 124025adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org } 12413b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org if (content.needShape()) { 12423b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org SkPath shape; 12433b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org shape.addRect(SkRect::MakeXYWH(SkIntToScalar(x), SkIntToScalar(y), 1244fd3c8c243ab190604e134910a1d6c1326d21e374vandebo@chromium.org SkIntToScalar(device->width()), 1245fd3c8c243ab190604e134910a1d6c1326d21e374vandebo@chromium.org SkIntToScalar(device->height()))); 12463b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org content.setShape(shape); 12473b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org } 12483b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org if (!content.needSource()) { 12493b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org return; 12503b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org } 1251eb6c7596af1a1fc7860e27ff2f678a33b2576c0fvandebo@chromium.org 12523b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org SkAutoTUnref<SkPDFFormXObject> xObject(new SkPDFFormXObject(pdfDevice)); 12533b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org SkPDFUtils::DrawFormXObject(this->addXObjectResource(xObject.get()), 1254b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org &content.entry()->fContent); 12559859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org 12569859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org // Merge glyph sets from the drawn device. 12579859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org fFontGlyphUsage->merge(pdfDevice->getFontGlyphUsage()); 12589b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org} 12599b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org 126089443aba5bfa2b040dc9fd24938b7d0b3decd737reedSkImageInfo SkPDFDevice::imageInfo() const { 126189443aba5bfa2b040dc9fd24938b7d0b3decd737reed return fLegacyBitmap.info(); 126289443aba5bfa2b040dc9fd24938b7d0b3decd737reed} 126389443aba5bfa2b040dc9fd24938b7d0b3decd737reed 126440a1ae4df28810aa5aa5cf2627d8387b2dfb867arobertphillips@google.comvoid SkPDFDevice::onAttachToCanvas(SkCanvas* canvas) { 126540a1ae4df28810aa5aa5cf2627d8387b2dfb867arobertphillips@google.com INHERITED::onAttachToCanvas(canvas); 126640a1ae4df28810aa5aa5cf2627d8387b2dfb867arobertphillips@google.com 126740a1ae4df28810aa5aa5cf2627d8387b2dfb867arobertphillips@google.com // Canvas promises that this ptr is valid until onDetachFromCanvas is called 126840a1ae4df28810aa5aa5cf2627d8387b2dfb867arobertphillips@google.com fClipStack = canvas->getClipStack(); 126940a1ae4df28810aa5aa5cf2627d8387b2dfb867arobertphillips@google.com} 127040a1ae4df28810aa5aa5cf2627d8387b2dfb867arobertphillips@google.com 127140a1ae4df28810aa5aa5cf2627d8387b2dfb867arobertphillips@google.comvoid SkPDFDevice::onDetachFromCanvas() { 127240a1ae4df28810aa5aa5cf2627d8387b2dfb867arobertphillips@google.com INHERITED::onDetachFromCanvas(); 127340a1ae4df28810aa5aa5cf2627d8387b2dfb867arobertphillips@google.com 127440a1ae4df28810aa5aa5cf2627d8387b2dfb867arobertphillips@google.com fClipStack = NULL; 127540a1ae4df28810aa5aa5cf2627d8387b2dfb867arobertphillips@google.com} 127640a1ae4df28810aa5aa5cf2627d8387b2dfb867arobertphillips@google.com 12774a8126e7f81384526629b1e21bf89b632ea13cd9reedSkSurface* SkPDFDevice::newSurface(const SkImageInfo& info, const SkSurfaceProps& props) { 12784a8126e7f81384526629b1e21bf89b632ea13cd9reed return SkSurface::NewRaster(info, &props); 127989443aba5bfa2b040dc9fd24938b7d0b3decd737reed} 128089443aba5bfa2b040dc9fd24938b7d0b3decd737reed 12818dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.orgContentEntry* SkPDFDevice::getLastContentEntry() { 12828dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org if (fDrawingArea == kContent_DrawingArea) { 12838dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org return fLastContentEntry; 12848dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org } else { 12858dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org return fLastMarginContentEntry; 12868dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org } 12878dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org} 12888dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org 1289e02944075840d672bd1797f3d945ff82d302282fcommit-bot@chromium.orgSkAutoTDelete<ContentEntry>* SkPDFDevice::getContentEntries() { 12908dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org if (fDrawingArea == kContent_DrawingArea) { 12919510ccc06bbfa5e888f66578042674be98d8ac60ctguil@chromium.org return &fContentEntries; 12928dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org } else { 12939510ccc06bbfa5e888f66578042674be98d8ac60ctguil@chromium.org return &fMarginContentEntries; 12948dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org } 12958dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org} 12968dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org 12978dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.orgvoid SkPDFDevice::setLastContentEntry(ContentEntry* contentEntry) { 12988dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org if (fDrawingArea == kContent_DrawingArea) { 12998dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org fLastContentEntry = contentEntry; 13008dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org } else { 13018dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org fLastMarginContentEntry = contentEntry; 13028dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org } 13038dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org} 13048dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org 13058dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.orgvoid SkPDFDevice::setDrawingArea(DrawingArea drawingArea) { 13069510ccc06bbfa5e888f66578042674be98d8ac60ctguil@chromium.org // A ScopedContentEntry only exists during the course of a draw call, so 13079510ccc06bbfa5e888f66578042674be98d8ac60ctguil@chromium.org // this can't be called while a ScopedContentEntry exists. 13088dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org fDrawingArea = drawingArea; 13098dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org} 13108dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org 131147401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.orgSkPDFResourceDict* SkPDFDevice::getResourceDict() { 1312fc641d09e5a1a9f7fae369ae06a8b96089faf57breed@google.com if (NULL == fResourceDict) { 131347401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org fResourceDict = SkNEW(SkPDFResourceDict); 13149b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org 13159b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org if (fGraphicStateResources.count()) { 13169b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org for (int i = 0; i < fGraphicStateResources.count(); i++) { 131747401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org fResourceDict->insertResourceAsReference( 131847401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org SkPDFResourceDict::kExtGState_ResourceType, 131947401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org i, fGraphicStateResources[i]); 13209b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org } 13219b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org } 13229b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org 13239b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org if (fXObjectResources.count()) { 13249b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org for (int i = 0; i < fXObjectResources.count(); i++) { 132547401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org fResourceDict->insertResourceAsReference( 132647401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org SkPDFResourceDict::kXObject_ResourceType, 132747401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org i, fXObjectResources[i]); 13289b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org } 13299b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org } 133028be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org 133128be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org if (fFontResources.count()) { 133228be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org for (int i = 0; i < fFontResources.count(); i++) { 133347401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org fResourceDict->insertResourceAsReference( 133447401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org SkPDFResourceDict::kFont_ResourceType, 133547401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org i, fFontResources[i]); 133628be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org } 133728be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org } 133828be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org 1339da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org if (fShaderResources.count()) { 1340d96d17b9c113ac694138224249ff2ce643e961ddvandebo@chromium.org SkAutoTUnref<SkPDFDict> patterns(new SkPDFDict()); 1341da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org for (int i = 0; i < fShaderResources.count(); i++) { 134247401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org fResourceDict->insertResourceAsReference( 134347401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org SkPDFResourceDict::kPattern_ResourceType, 134447401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org i, fShaderResources[i]); 1345da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 1346da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 13479b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org } 1348fc641d09e5a1a9f7fae369ae06a8b96089faf57breed@google.com return fResourceDict; 13499b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org} 13509b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org 1351f0ec2666d9a3f0f1662f0d63b5147628c49648aavandebo@chromium.orgconst SkTDArray<SkPDFFont*>& SkPDFDevice::getFontResources() const { 1352f0ec2666d9a3f0f1662f0d63b5147628c49648aavandebo@chromium.org return fFontResources; 1353f0ec2666d9a3f0f1662f0d63b5147628c49648aavandebo@chromium.org} 1354f0ec2666d9a3f0f1662f0d63b5147628c49648aavandebo@chromium.org 13552a006c112743e07ce258ca223631fc19233f5ddcreed@google.comSkPDFArray* SkPDFDevice::copyMediaBox() const { 13562a006c112743e07ce258ca223631fc19233f5ddcreed@google.com // should this be a singleton? 13572a006c112743e07ce258ca223631fc19233f5ddcreed@google.com SkAutoTUnref<SkPDFInt> zero(SkNEW_ARGS(SkPDFInt, (0))); 1358f7c157610ff85f7323f5e213b62478dcc66edbecvandebo@chromium.org 13592a006c112743e07ce258ca223631fc19233f5ddcreed@google.com SkPDFArray* mediaBox = SkNEW(SkPDFArray); 13609b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org mediaBox->reserve(4); 13619b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org mediaBox->append(zero.get()); 13629b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org mediaBox->append(zero.get()); 1363c789cf1c6f3947283aeb34acb5a22e6204f8f6f5reed@google.com mediaBox->appendInt(fPageSize.fWidth); 1364c789cf1c6f3947283aeb34acb5a22e6204f8f6f5reed@google.com mediaBox->appendInt(fPageSize.fHeight); 13659b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org return mediaBox; 13669b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org} 13679b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org 1368c2a9b7fe5640af8f0c371561f1ac71b045d6d8ecvandebo@chromium.orgSkStream* SkPDFDevice::content() const { 13695667afc5cb4a8cd15a27667f222b6d9c94d61c38reed@google.com SkMemoryStream* result = new SkMemoryStream; 13705667afc5cb4a8cd15a27667f222b6d9c94d61c38reed@google.com result->setData(this->copyContentToData())->unref(); 13715667afc5cb4a8cd15a27667f222b6d9c94d61c38reed@google.com return result; 13725667afc5cb4a8cd15a27667f222b6d9c94d61c38reed@google.com} 13735667afc5cb4a8cd15a27667f222b6d9c94d61c38reed@google.com 13748dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.orgvoid SkPDFDevice::copyContentEntriesToData(ContentEntry* entry, 13758dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org SkWStream* data) const { 13769510ccc06bbfa5e888f66578042674be98d8ac60ctguil@chromium.org // TODO(ctguil): For margins, I'm not sure fExistingClipStack/Region is the 13779510ccc06bbfa5e888f66578042674be98d8ac60ctguil@chromium.org // right thing to pass here. 13788dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org GraphicStackState gsState(fExistingClipStack, fExistingClipRegion, data); 13799510ccc06bbfa5e888f66578042674be98d8ac60ctguil@chromium.org while (entry != NULL) { 1380663515bc59325092c4e47f5189782bd6fcd0586avandebo@chromium.org SkPoint translation; 1381663515bc59325092c4e47f5189782bd6fcd0586avandebo@chromium.org translation.iset(this->getOrigin()); 13828dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org translation.negate(); 13838dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org gsState.updateClip(entry->fState.fClipStack, entry->fState.fClipRegion, 13848dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org translation); 13858dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org gsState.updateMatrix(entry->fState.fMatrix); 13868dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org gsState.updateDrawingState(entry->fState); 13879510ccc06bbfa5e888f66578042674be98d8ac60ctguil@chromium.org 13888dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org SkAutoDataUnref copy(entry->fContent.copyToData()); 138959f46b81f8bdd1b524f5cc43bc27603f9604c71arobertphillips@google.com data->write(copy->data(), copy->size()); 13908dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org entry = entry->fNext.get(); 13918dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org } 13928dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org gsState.drainStack(); 13938dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org} 13948dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org 13955667afc5cb4a8cd15a27667f222b6d9c94d61c38reed@google.comSkData* SkPDFDevice::copyContentToData() const { 13969fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org SkDynamicMemoryWStream data; 13979fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org if (fInitialTransform.getType() != SkMatrix::kIdentity_Mask) { 13989fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org SkPDFUtils::AppendTransform(fInitialTransform, &data); 1399c2a9b7fe5640af8f0c371561f1ac71b045d6d8ecvandebo@chromium.org } 14009510ccc06bbfa5e888f66578042674be98d8ac60ctguil@chromium.org 14018dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org // TODO(aayushkumar): Apply clip along the margins. Currently, webkit 14028dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org // colors the contentArea white before it starts drawing into it and 14038dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org // that currently acts as our clip. 14048dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org // Also, think about adding a transform here (or assume that the values 14058dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org // sent across account for that) 14068dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org SkPDFDevice::copyContentEntriesToData(fMarginContentEntries.get(), &data); 14079510ccc06bbfa5e888f66578042674be98d8ac60ctguil@chromium.org 14089fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org // If the content area is the entire page, then we don't need to clip 14099fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org // the content area (PDF area clips to the page size). Otherwise, 14109fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org // we have to clip to the content area; we've already applied the 14119fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org // initial transform, so just clip to the device size. 14129fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org if (fPageSize != fContentSize) { 14138637a365518a82901d313d61eecd83a0c5102fe9robertphillips@google.com SkRect r = SkRect::MakeWH(SkIntToScalar(this->width()), 14148637a365518a82901d313d61eecd83a0c5102fe9robertphillips@google.com SkIntToScalar(this->height())); 14159fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org emit_clip(NULL, &r, &data); 14169fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org } 14179859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org 14188dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org SkPDFDevice::copyContentEntriesToData(fContentEntries.get(), &data); 14199fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org 14205667afc5cb4a8cd15a27667f222b6d9c94d61c38reed@google.com // potentially we could cache this SkData, and only rebuild it if we 14215667afc5cb4a8cd15a27667f222b6d9c94d61c38reed@google.com // see that our state has changed. 14225667afc5cb4a8cd15a27667f222b6d9c94d61c38reed@google.com return data.copyToData(); 14239b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org} 14249b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org 1425d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org#ifdef SK_PDF_USE_PATHOPS 142692ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org/* Draws an inverse filled path by using Path Ops to compute the positive 142792ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org * inverse using the current clip as the inverse bounds. 142892ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org * Return true if this was an inverse path and was properly handled, 142992ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org * otherwise returns false and the normal drawing routine should continue, 143092ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org * either as a (incorrect) fallback or because the path was not inverse 143192ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org * in the first place. 143292ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org */ 143392ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.orgbool SkPDFDevice::handleInversePath(const SkDraw& d, const SkPath& origPath, 1434a9ebd161a7c08515f0c4bd885e61c4b52688ececedisonn@google.com const SkPaint& paint, bool pathIsMutable, 1435a9ebd161a7c08515f0c4bd885e61c4b52688ececedisonn@google.com const SkMatrix* prePathMatrix) { 143692ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org if (!origPath.isInverseFillType()) { 143792ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org return false; 143892ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org } 143992ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org 144092ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org if (d.fClip->isEmpty()) { 144192ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org return false; 144292ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org } 144392ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org 144492ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org SkPath modifiedPath; 144592ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org SkPath* pathPtr = const_cast<SkPath*>(&origPath); 144692ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org SkPaint noInversePaint(paint); 144792ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org 144892ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org // Merge stroking operations into final path. 144992ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org if (SkPaint::kStroke_Style == paint.getStyle() || 145092ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org SkPaint::kStrokeAndFill_Style == paint.getStyle()) { 145192ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org bool doFillPath = paint.getFillPath(origPath, &modifiedPath); 145292ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org if (doFillPath) { 145392ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org noInversePaint.setStyle(SkPaint::kFill_Style); 145492ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org noInversePaint.setStrokeWidth(0); 145592ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org pathPtr = &modifiedPath; 145692ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org } else { 145792ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org // To be consistent with the raster output, hairline strokes 145892ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org // are rendered as non-inverted. 145992ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org modifiedPath.toggleInverseFillType(); 146092ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org drawPath(d, modifiedPath, paint, NULL, true); 146192ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org return true; 146292ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org } 146392ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org } 146492ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org 146592ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org // Get bounds of clip in current transform space 146692ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org // (clip bounds are given in device space). 146792ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org SkRect bounds; 146892ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org SkMatrix transformInverse; 1469a9ebd161a7c08515f0c4bd885e61c4b52688ececedisonn@google.com SkMatrix totalMatrix = *d.fMatrix; 1470a9ebd161a7c08515f0c4bd885e61c4b52688ececedisonn@google.com if (prePathMatrix) { 1471a9ebd161a7c08515f0c4bd885e61c4b52688ececedisonn@google.com totalMatrix.preConcat(*prePathMatrix); 1472a9ebd161a7c08515f0c4bd885e61c4b52688ececedisonn@google.com } 1473a9ebd161a7c08515f0c4bd885e61c4b52688ececedisonn@google.com if (!totalMatrix.invert(&transformInverse)) { 147492ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org return false; 147592ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org } 147692ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org bounds.set(d.fClip->getBounds()); 147792ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org transformInverse.mapRect(&bounds); 147892ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org 147992ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org // Extend the bounds by the line width (plus some padding) 148092ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org // so the edge doesn't cause a visible stroke. 148192ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org bounds.outset(paint.getStrokeWidth() + SK_Scalar1, 148292ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org paint.getStrokeWidth() + SK_Scalar1); 148392ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org 148492ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org if (!calculate_inverse_path(bounds, *pathPtr, &modifiedPath)) { 148592ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org return false; 148692ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org } 148792ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org 1488a9ebd161a7c08515f0c4bd885e61c4b52688ececedisonn@google.com drawPath(d, modifiedPath, noInversePaint, prePathMatrix, true); 148992ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org return true; 149092ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org} 1491d2623a1a0bcd23801c86a7d3f352b5e1f1c2e195commit-bot@chromium.org#endif 149292ffe7d10ef5db05f1f4ffef0cfe898169ba13bfcommit-bot@chromium.org 1493b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.combool SkPDFDevice::handleRectAnnotation(const SkRect& r, const SkMatrix& matrix, 1494b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com const SkPaint& p) { 1495238be8c7e5de5a83517440a3db7f7965b47fb010vandebo@chromium.org SkAnnotation* annotationInfo = p.getAnnotation(); 1496238be8c7e5de5a83517440a3db7f7965b47fb010vandebo@chromium.org if (!annotationInfo) { 1497238be8c7e5de5a83517440a3db7f7965b47fb010vandebo@chromium.org return false; 1498238be8c7e5de5a83517440a3db7f7965b47fb010vandebo@chromium.org } 1499238be8c7e5de5a83517440a3db7f7965b47fb010vandebo@chromium.org SkData* urlData = annotationInfo->find(SkAnnotationKeys::URL_Key()); 1500b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com if (urlData) { 1501b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com handleLinkToURL(urlData, r, matrix); 15024469938e92d779dff05e745559e67907bbf21e78reed@google.com return p.getAnnotation() != NULL; 1503b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com } 15043b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org SkData* linkToName = annotationInfo->find( 15053b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org SkAnnotationKeys::Link_Named_Dest_Key()); 1506b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com if (linkToName) { 1507b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com handleLinkToNamedDest(linkToName, r, matrix); 15084469938e92d779dff05e745559e67907bbf21e78reed@google.com return p.getAnnotation() != NULL; 1509b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com } 1510b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com return false; 1511b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com} 1512b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com 1513b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.combool SkPDFDevice::handlePointAnnotation(const SkPoint* points, size_t count, 1514b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com const SkMatrix& matrix, 1515b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com const SkPaint& paint) { 1516b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com SkAnnotation* annotationInfo = paint.getAnnotation(); 1517b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com if (!annotationInfo) { 1518238be8c7e5de5a83517440a3db7f7965b47fb010vandebo@chromium.org return false; 1519238be8c7e5de5a83517440a3db7f7965b47fb010vandebo@chromium.org } 15203b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org SkData* nameData = annotationInfo->find( 15213b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org SkAnnotationKeys::Define_Named_Dest_Key()); 1522b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com if (nameData) { 1523b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com for (size_t i = 0; i < count; i++) { 1524b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com defineNamedDestination(nameData, points[i], matrix); 1525b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com } 15264469938e92d779dff05e745559e67907bbf21e78reed@google.com return paint.getAnnotation() != NULL; 1527b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com } 1528b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com return false; 1529b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com} 1530238be8c7e5de5a83517440a3db7f7965b47fb010vandebo@chromium.org 15313b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.orgSkPDFDict* SkPDFDevice::createLinkAnnotation(const SkRect& r, 15323b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org const SkMatrix& matrix) { 1533238be8c7e5de5a83517440a3db7f7965b47fb010vandebo@chromium.org SkMatrix transform = matrix; 1534238be8c7e5de5a83517440a3db7f7965b47fb010vandebo@chromium.org transform.postConcat(fInitialTransform); 1535238be8c7e5de5a83517440a3db7f7965b47fb010vandebo@chromium.org SkRect translatedRect; 1536238be8c7e5de5a83517440a3db7f7965b47fb010vandebo@chromium.org transform.mapRect(&translatedRect, r); 1537238be8c7e5de5a83517440a3db7f7965b47fb010vandebo@chromium.org 15382a006c112743e07ce258ca223631fc19233f5ddcreed@google.com if (NULL == fAnnotations) { 15392a006c112743e07ce258ca223631fc19233f5ddcreed@google.com fAnnotations = SkNEW(SkPDFArray); 1540238be8c7e5de5a83517440a3db7f7965b47fb010vandebo@chromium.org } 1541b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com SkPDFDict* annotation(SkNEW_ARGS(SkPDFDict, ("Annot"))); 1542238be8c7e5de5a83517440a3db7f7965b47fb010vandebo@chromium.org annotation->insertName("Subtype", "Link"); 1543b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com fAnnotations->append(annotation); 1544238be8c7e5de5a83517440a3db7f7965b47fb010vandebo@chromium.org 1545b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com SkAutoTUnref<SkPDFArray> border(SkNEW(SkPDFArray)); 1546238be8c7e5de5a83517440a3db7f7965b47fb010vandebo@chromium.org border->reserve(3); 1547238be8c7e5de5a83517440a3db7f7965b47fb010vandebo@chromium.org border->appendInt(0); // Horizontal corner radius. 1548238be8c7e5de5a83517440a3db7f7965b47fb010vandebo@chromium.org border->appendInt(0); // Vertical corner radius. 1549238be8c7e5de5a83517440a3db7f7965b47fb010vandebo@chromium.org border->appendInt(0); // Width, 0 = no border. 1550238be8c7e5de5a83517440a3db7f7965b47fb010vandebo@chromium.org annotation->insert("Border", border.get()); 1551238be8c7e5de5a83517440a3db7f7965b47fb010vandebo@chromium.org 1552b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com SkAutoTUnref<SkPDFArray> rect(SkNEW(SkPDFArray)); 1553238be8c7e5de5a83517440a3db7f7965b47fb010vandebo@chromium.org rect->reserve(4); 1554238be8c7e5de5a83517440a3db7f7965b47fb010vandebo@chromium.org rect->appendScalar(translatedRect.fLeft); 1555238be8c7e5de5a83517440a3db7f7965b47fb010vandebo@chromium.org rect->appendScalar(translatedRect.fTop); 1556238be8c7e5de5a83517440a3db7f7965b47fb010vandebo@chromium.org rect->appendScalar(translatedRect.fRight); 1557238be8c7e5de5a83517440a3db7f7965b47fb010vandebo@chromium.org rect->appendScalar(translatedRect.fBottom); 1558238be8c7e5de5a83517440a3db7f7965b47fb010vandebo@chromium.org annotation->insert("Rect", rect.get()); 1559238be8c7e5de5a83517440a3db7f7965b47fb010vandebo@chromium.org 1560b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com return annotation; 1561b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com} 1562b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com 1563b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.comvoid SkPDFDevice::handleLinkToURL(SkData* urlData, const SkRect& r, 1564b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com const SkMatrix& matrix) { 1565b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com SkAutoTUnref<SkPDFDict> annotation(createLinkAnnotation(r, matrix)); 1566b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com 1567b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com SkString url(static_cast<const char *>(urlData->data()), 1568b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com urlData->size() - 1); 1569b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com SkAutoTUnref<SkPDFDict> action(SkNEW_ARGS(SkPDFDict, ("Action"))); 1570238be8c7e5de5a83517440a3db7f7965b47fb010vandebo@chromium.org action->insertName("S", "URI"); 1571b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com action->insert("URI", SkNEW_ARGS(SkPDFString, (url)))->unref(); 1572238be8c7e5de5a83517440a3db7f7965b47fb010vandebo@chromium.org annotation->insert("A", action.get()); 1573b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com} 1574b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com 1575b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.comvoid SkPDFDevice::handleLinkToNamedDest(SkData* nameData, const SkRect& r, 1576b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com const SkMatrix& matrix) { 1577b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com SkAutoTUnref<SkPDFDict> annotation(createLinkAnnotation(r, matrix)); 1578b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com SkString name(static_cast<const char *>(nameData->data()), 1579b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com nameData->size() - 1); 1580b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com annotation->insert("Dest", SkNEW_ARGS(SkPDFName, (name)))->unref(); 1581b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com} 1582b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com 1583b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.comstruct NamedDestination { 1584b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com const SkData* nameData; 1585b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com SkPoint point; 1586b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com 1587b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com NamedDestination(const SkData* nameData, const SkPoint& point) 1588b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com : nameData(nameData), point(point) { 1589b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com nameData->ref(); 1590b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com } 1591238be8c7e5de5a83517440a3db7f7965b47fb010vandebo@chromium.org 1592b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com ~NamedDestination() { 1593b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com nameData->unref(); 1594b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com } 1595b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com}; 1596b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com 1597b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.comvoid SkPDFDevice::defineNamedDestination(SkData* nameData, const SkPoint& point, 1598b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com const SkMatrix& matrix) { 1599b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com SkMatrix transform = matrix; 1600b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com transform.postConcat(fInitialTransform); 1601b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com SkPoint translatedPoint; 1602b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com transform.mapXY(point.x(), point.y(), &translatedPoint); 1603b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com fNamedDestinations.push( 1604b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com SkNEW_ARGS(NamedDestination, (nameData, translatedPoint))); 1605b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com} 1606b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com 1607b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.comvoid SkPDFDevice::appendDestinations(SkPDFDict* dict, SkPDFObject* page) { 1608b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com int nDest = fNamedDestinations.count(); 1609b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com for (int i = 0; i < nDest; i++) { 1610b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com NamedDestination* dest = fNamedDestinations[i]; 1611b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com SkAutoTUnref<SkPDFArray> pdfDest(SkNEW(SkPDFArray)); 1612b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com pdfDest->reserve(5); 1613b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com pdfDest->append(SkNEW_ARGS(SkPDFObjRef, (page)))->unref(); 1614b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com pdfDest->appendName("XYZ"); 1615b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com pdfDest->appendScalar(dest->point.x()); 1616b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com pdfDest->appendScalar(dest->point.y()); 1617b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com pdfDest->appendInt(0); // Leave zoom unchanged 16183b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org dict->insert(static_cast<const char *>(dest->nameData->data()), 16193b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org pdfDest); 1620b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com } 1621238be8c7e5de5a83517440a3db7f7965b47fb010vandebo@chromium.org} 1622238be8c7e5de5a83517440a3db7f7965b47fb010vandebo@chromium.org 1623fc641d09e5a1a9f7fae369ae06a8b96089faf57breed@google.comSkPDFFormXObject* SkPDFDevice::createFormXObjectFromDevice() { 1624fc641d09e5a1a9f7fae369ae06a8b96089faf57breed@google.com SkPDFFormXObject* xobject = SkNEW_ARGS(SkPDFFormXObject, (this)); 16259859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org // We always draw the form xobjects that we create back into the device, so 16269859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org // we simply preserve the font usage instead of pulling it out and merging 16279859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org // it back in later. 16289859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org cleanUp(false); // Reset this device to have no content. 16296112c215fbdd53388e64ece36e6c7bba0fe3a451vandebo@chromium.org init(); 1630fc641d09e5a1a9f7fae369ae06a8b96089faf57breed@google.com return xobject; 16316112c215fbdd53388e64ece36e6c7bba0fe3a451vandebo@chromium.org} 16326112c215fbdd53388e64ece36e6c7bba0fe3a451vandebo@chromium.org 16333b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.orgvoid SkPDFDevice::drawFormXObjectWithMask(int xObjectIndex, 16343b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org SkPDFFormXObject* mask, 1635481aef68333e01c19badda456d8e60bd1f1bee2avandebo@chromium.org const SkClipStack* clipStack, 1636481aef68333e01c19badda456d8e60bd1f1bee2avandebo@chromium.org const SkRegion& clipRegion, 16373b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org SkXfermode::Mode mode, 1638481aef68333e01c19badda456d8e60bd1f1bee2avandebo@chromium.org bool invertClip) { 1639481aef68333e01c19badda456d8e60bd1f1bee2avandebo@chromium.org if (clipRegion.isEmpty() && !invertClip) { 1640481aef68333e01c19badda456d8e60bd1f1bee2avandebo@chromium.org return; 1641481aef68333e01c19badda456d8e60bd1f1bee2avandebo@chromium.org } 1642481aef68333e01c19badda456d8e60bd1f1bee2avandebo@chromium.org 1643d96d17b9c113ac694138224249ff2ce643e961ddvandebo@chromium.org SkAutoTUnref<SkPDFGraphicState> sMaskGS( 16443b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org SkPDFGraphicState::GetSMaskGraphicState( 16453b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org mask, invertClip, SkPDFGraphicState::kAlpha_SMaskMode)); 1646466f3d66f09285d2d988315bacde573a5359ce54vandebo@chromium.org 16473b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org SkMatrix identity; 16483b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org identity.reset(); 16493b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org SkPaint paint; 16503b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org paint.setXfermodeMode(mode); 16513b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org ScopedContentEntry content(this, clipStack, clipRegion, identity, paint); 1652b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org if (!content.entry()) { 1653b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org return; 1654b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org } 1655466f3d66f09285d2d988315bacde573a5359ce54vandebo@chromium.org SkPDFUtils::ApplyGraphicState(addGraphicStateResource(sMaskGS.get()), 1656b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org &content.entry()->fContent); 16573b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org SkPDFUtils::DrawFormXObject(xObjectIndex, &content.entry()->fContent); 1658466f3d66f09285d2d988315bacde573a5359ce54vandebo@chromium.org 1659d96d17b9c113ac694138224249ff2ce643e961ddvandebo@chromium.org sMaskGS.reset(SkPDFGraphicState::GetNoSMaskGraphicState()); 1660466f3d66f09285d2d988315bacde573a5359ce54vandebo@chromium.org SkPDFUtils::ApplyGraphicState(addGraphicStateResource(sMaskGS.get()), 1661b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org &content.entry()->fContent); 1662466f3d66f09285d2d988315bacde573a5359ce54vandebo@chromium.org} 1663466f3d66f09285d2d988315bacde573a5359ce54vandebo@chromium.org 1664b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.orgContentEntry* SkPDFDevice::setUpContentEntry(const SkClipStack* clipStack, 1665b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org const SkRegion& clipRegion, 1666b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org const SkMatrix& matrix, 1667b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org const SkPaint& paint, 1668b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org bool hasText, 1669fc641d09e5a1a9f7fae369ae06a8b96089faf57breed@google.com SkPDFFormXObject** dst) { 1670fc641d09e5a1a9f7fae369ae06a8b96089faf57breed@google.com *dst = NULL; 167125adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org if (clipRegion.isEmpty()) { 1672b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org return NULL; 167325adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org } 167425adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org 167578dad54080ad806be89adb5cc0e3c530b031cdafvandebo@chromium.org // The clip stack can come from an SkDraw where it is technically optional. 167678dad54080ad806be89adb5cc0e3c530b031cdafvandebo@chromium.org SkClipStack synthesizedClipStack; 167778dad54080ad806be89adb5cc0e3c530b031cdafvandebo@chromium.org if (clipStack == NULL) { 167878dad54080ad806be89adb5cc0e3c530b031cdafvandebo@chromium.org if (clipRegion == fExistingClipRegion) { 167978dad54080ad806be89adb5cc0e3c530b031cdafvandebo@chromium.org clipStack = &fExistingClipStack; 168078dad54080ad806be89adb5cc0e3c530b031cdafvandebo@chromium.org } else { 168178dad54080ad806be89adb5cc0e3c530b031cdafvandebo@chromium.org // GraphicStackState::updateClip expects the clip stack to have 168278dad54080ad806be89adb5cc0e3c530b031cdafvandebo@chromium.org // fExistingClip as a prefix, so start there, then set the clip 168378dad54080ad806be89adb5cc0e3c530b031cdafvandebo@chromium.org // to the passed region. 168478dad54080ad806be89adb5cc0e3c530b031cdafvandebo@chromium.org synthesizedClipStack = fExistingClipStack; 168578dad54080ad806be89adb5cc0e3c530b031cdafvandebo@chromium.org SkPath clipPath; 168678dad54080ad806be89adb5cc0e3c530b031cdafvandebo@chromium.org clipRegion.getBoundaryPath(&clipPath); 16870017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com synthesizedClipStack.clipDevPath(clipPath, SkRegion::kReplace_Op, 16880017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com false); 168978dad54080ad806be89adb5cc0e3c530b031cdafvandebo@chromium.org clipStack = &synthesizedClipStack; 169078dad54080ad806be89adb5cc0e3c530b031cdafvandebo@chromium.org } 169178dad54080ad806be89adb5cc0e3c530b031cdafvandebo@chromium.org } 169278dad54080ad806be89adb5cc0e3c530b031cdafvandebo@chromium.org 169325adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org SkXfermode::Mode xfermode = SkXfermode::kSrcOver_Mode; 169425adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org if (paint.getXfermode()) { 169525adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org paint.getXfermode()->asMode(&xfermode); 169625adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org } 169725adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org 16983b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org // For the following modes, we want to handle source and destination 16993b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org // separately, so make an object of what's already there. 17003b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org if (xfermode == SkXfermode::kClear_Mode || 17013b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org xfermode == SkXfermode::kSrc_Mode || 17023b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org xfermode == SkXfermode::kSrcIn_Mode || 17033b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org xfermode == SkXfermode::kDstIn_Mode || 17043b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org xfermode == SkXfermode::kSrcOut_Mode || 17053b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org xfermode == SkXfermode::kDstOut_Mode || 17063b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org xfermode == SkXfermode::kSrcATop_Mode || 17073b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org xfermode == SkXfermode::kDstATop_Mode || 17083b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org xfermode == SkXfermode::kModulate_Mode) { 17093b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org if (!isContentEmpty()) { 1710fc641d09e5a1a9f7fae369ae06a8b96089faf57breed@google.com *dst = createFormXObjectFromDevice(); 17113b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org SkASSERT(isContentEmpty()); 17123b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org } else if (xfermode != SkXfermode::kSrc_Mode && 17133b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org xfermode != SkXfermode::kSrcOut_Mode) { 17143b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org // Except for Src and SrcOut, if there isn't anything already there, 17153b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org // then we're done. 17163b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org return NULL; 1717481aef68333e01c19badda456d8e60bd1f1bee2avandebo@chromium.org } 17186112c215fbdd53388e64ece36e6c7bba0fe3a451vandebo@chromium.org } 1719769fa6a013baca6d7404e2bf096a34a7e3635fa5ctguil@chromium.org // TODO(vandebo): Figure out how/if we can handle the following modes: 17203b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org // Xor, Plus. 172125adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org 17223b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org // Dst xfer mode doesn't draw source at all. 17233b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org if (xfermode == SkXfermode::kDst_Mode) { 1724b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org return NULL; 172525adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org } 172625adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org 17279fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org ContentEntry* entry; 1728e02944075840d672bd1797f3d945ff82d302282fcommit-bot@chromium.org SkAutoTDelete<ContentEntry> newEntry; 17298dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org 17308dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org ContentEntry* lastContentEntry = getLastContentEntry(); 17318dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org if (lastContentEntry && lastContentEntry->fContent.getOffset() == 0) { 17328dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org entry = lastContentEntry; 17339fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org } else { 17349fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org newEntry.reset(new ContentEntry); 17359fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org entry = newEntry.get(); 17369fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org } 17379fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org 173878dad54080ad806be89adb5cc0e3c530b031cdafvandebo@chromium.org populateGraphicStateEntryFromPaint(matrix, *clipStack, clipRegion, paint, 17399fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org hasText, &entry->fState); 17408dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org if (lastContentEntry && xfermode != SkXfermode::kDstOver_Mode && 17418dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org entry->fState.compareInitialState(lastContentEntry->fState)) { 17428dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org return lastContentEntry; 17439fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org } 17449fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org 1745e02944075840d672bd1797f3d945ff82d302282fcommit-bot@chromium.org SkAutoTDelete<ContentEntry>* contentEntries = getContentEntries(); 17468dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org if (!lastContentEntry) { 17479510ccc06bbfa5e888f66578042674be98d8ac60ctguil@chromium.org contentEntries->reset(entry); 17488dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org setLastContentEntry(entry); 174925adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org } else if (xfermode == SkXfermode::kDstOver_Mode) { 1750e02944075840d672bd1797f3d945ff82d302282fcommit-bot@chromium.org entry->fNext.reset(contentEntries->detach()); 17519510ccc06bbfa5e888f66578042674be98d8ac60ctguil@chromium.org contentEntries->reset(entry); 17529fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org } else { 17538dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org lastContentEntry->fNext.reset(entry); 17548dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org setLastContentEntry(entry); 17559fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org } 1756e02944075840d672bd1797f3d945ff82d302282fcommit-bot@chromium.org newEntry.detach(); 1757b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org return entry; 17589fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org} 17599fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org 17607542dc8897d151afc0eca7dd73d72ea05f92baadcommit-bot@chromium.orgvoid SkPDFDevice::finishContentEntry(SkXfermode::Mode xfermode, 17613b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org SkPDFFormXObject* dst, 17623b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org SkPath* shape) { 17633b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org if (xfermode != SkXfermode::kClear_Mode && 17643b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org xfermode != SkXfermode::kSrc_Mode && 17657542dc8897d151afc0eca7dd73d72ea05f92baadcommit-bot@chromium.org xfermode != SkXfermode::kDstOver_Mode && 17663b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org xfermode != SkXfermode::kSrcIn_Mode && 17673b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org xfermode != SkXfermode::kDstIn_Mode && 17683b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org xfermode != SkXfermode::kSrcOut_Mode && 17693b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org xfermode != SkXfermode::kDstOut_Mode && 17703b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org xfermode != SkXfermode::kSrcATop_Mode && 17713b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org xfermode != SkXfermode::kDstATop_Mode && 17723b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org xfermode != SkXfermode::kModulate_Mode) { 1773b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org SkASSERT(!dst); 17746112c215fbdd53388e64ece36e6c7bba0fe3a451vandebo@chromium.org return; 17756112c215fbdd53388e64ece36e6c7bba0fe3a451vandebo@chromium.org } 17767542dc8897d151afc0eca7dd73d72ea05f92baadcommit-bot@chromium.org if (xfermode == SkXfermode::kDstOver_Mode) { 17777542dc8897d151afc0eca7dd73d72ea05f92baadcommit-bot@chromium.org SkASSERT(!dst); 17787542dc8897d151afc0eca7dd73d72ea05f92baadcommit-bot@chromium.org ContentEntry* firstContentEntry = getContentEntries()->get(); 17797542dc8897d151afc0eca7dd73d72ea05f92baadcommit-bot@chromium.org if (firstContentEntry->fContent.getOffset() == 0) { 17807542dc8897d151afc0eca7dd73d72ea05f92baadcommit-bot@chromium.org // For DstOver, an empty content entry was inserted before the rest 17817542dc8897d151afc0eca7dd73d72ea05f92baadcommit-bot@chromium.org // of the content entries. If nothing was drawn, it needs to be 17827542dc8897d151afc0eca7dd73d72ea05f92baadcommit-bot@chromium.org // removed. 17837542dc8897d151afc0eca7dd73d72ea05f92baadcommit-bot@chromium.org SkAutoTDelete<ContentEntry>* contentEntries = getContentEntries(); 17847542dc8897d151afc0eca7dd73d72ea05f92baadcommit-bot@chromium.org contentEntries->reset(firstContentEntry->fNext.detach()); 17857542dc8897d151afc0eca7dd73d72ea05f92baadcommit-bot@chromium.org } 17867542dc8897d151afc0eca7dd73d72ea05f92baadcommit-bot@chromium.org return; 17877542dc8897d151afc0eca7dd73d72ea05f92baadcommit-bot@chromium.org } 17883b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org if (!dst) { 17893b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org SkASSERT(xfermode == SkXfermode::kSrc_Mode || 17903b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org xfermode == SkXfermode::kSrcOut_Mode); 17913b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org return; 17923b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org } 17939510ccc06bbfa5e888f66578042674be98d8ac60ctguil@chromium.org 17949510ccc06bbfa5e888f66578042674be98d8ac60ctguil@chromium.org ContentEntry* contentEntries = getContentEntries()->get(); 1795b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org SkASSERT(dst); 17968dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org SkASSERT(!contentEntries->fNext.get()); 17974e8f1e56b17c3663d1892f44a4c1893b568ce67fcommit-bot@chromium.org // Changing the current content into a form-xobject will destroy the clip 17984e8f1e56b17c3663d1892f44a4c1893b568ce67fcommit-bot@chromium.org // objects which is fine since the xobject will already be clipped. However 17994e8f1e56b17c3663d1892f44a4c1893b568ce67fcommit-bot@chromium.org // if source has shape, we need to clip it too, so a copy of the clip is 18004e8f1e56b17c3663d1892f44a4c1893b568ce67fcommit-bot@chromium.org // saved. 18018dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org SkClipStack clipStack = contentEntries->fState.fClipStack; 18028dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org SkRegion clipRegion = contentEntries->fState.fClipRegion; 1803481aef68333e01c19badda456d8e60bd1f1bee2avandebo@chromium.org 18047542dc8897d151afc0eca7dd73d72ea05f92baadcommit-bot@chromium.org SkMatrix identity; 18057542dc8897d151afc0eca7dd73d72ea05f92baadcommit-bot@chromium.org identity.reset(); 18067542dc8897d151afc0eca7dd73d72ea05f92baadcommit-bot@chromium.org SkPaint stockPaint; 18077542dc8897d151afc0eca7dd73d72ea05f92baadcommit-bot@chromium.org 1808fc641d09e5a1a9f7fae369ae06a8b96089faf57breed@google.com SkAutoTUnref<SkPDFFormXObject> srcFormXObject; 18093b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org if (isContentEmpty()) { 18107542dc8897d151afc0eca7dd73d72ea05f92baadcommit-bot@chromium.org // If nothing was drawn and there's no shape, then the draw was a 18117542dc8897d151afc0eca7dd73d72ea05f92baadcommit-bot@chromium.org // no-op, but dst needs to be restored for that to be true. 18127542dc8897d151afc0eca7dd73d72ea05f92baadcommit-bot@chromium.org // If there is shape, then an empty source with Src, SrcIn, SrcOut, 18137542dc8897d151afc0eca7dd73d72ea05f92baadcommit-bot@chromium.org // DstIn, DstAtop or Modulate reduces to Clear and DstOut or SrcAtop 18147542dc8897d151afc0eca7dd73d72ea05f92baadcommit-bot@chromium.org // reduces to Dst. 18157542dc8897d151afc0eca7dd73d72ea05f92baadcommit-bot@chromium.org if (shape == NULL || xfermode == SkXfermode::kDstOut_Mode || 18167542dc8897d151afc0eca7dd73d72ea05f92baadcommit-bot@chromium.org xfermode == SkXfermode::kSrcATop_Mode) { 18174e8f1e56b17c3663d1892f44a4c1893b568ce67fcommit-bot@chromium.org ScopedContentEntry content(this, &fExistingClipStack, 18184e8f1e56b17c3663d1892f44a4c1893b568ce67fcommit-bot@chromium.org fExistingClipRegion, identity, 18197542dc8897d151afc0eca7dd73d72ea05f92baadcommit-bot@chromium.org stockPaint); 18207542dc8897d151afc0eca7dd73d72ea05f92baadcommit-bot@chromium.org SkPDFUtils::DrawFormXObject(this->addXObjectResource(dst), 18217542dc8897d151afc0eca7dd73d72ea05f92baadcommit-bot@chromium.org &content.entry()->fContent); 18227542dc8897d151afc0eca7dd73d72ea05f92baadcommit-bot@chromium.org return; 18237542dc8897d151afc0eca7dd73d72ea05f92baadcommit-bot@chromium.org } else { 18247542dc8897d151afc0eca7dd73d72ea05f92baadcommit-bot@chromium.org xfermode = SkXfermode::kClear_Mode; 18257542dc8897d151afc0eca7dd73d72ea05f92baadcommit-bot@chromium.org } 18263b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org } else { 18273b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org SkASSERT(!fContentEntries->fNext.get()); 1828fc641d09e5a1a9f7fae369ae06a8b96089faf57breed@google.com srcFormXObject.reset(createFormXObjectFromDevice()); 1829481aef68333e01c19badda456d8e60bd1f1bee2avandebo@chromium.org } 1830481aef68333e01c19badda456d8e60bd1f1bee2avandebo@chromium.org 18313b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org // TODO(vandebo) srcFormXObject may contain alpha, but here we want it 18323b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org // without alpha. 18333b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org if (xfermode == SkXfermode::kSrcATop_Mode) { 18343b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org // TODO(vandebo): In order to properly support SrcATop we have to track 18353b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org // the shape of what's been drawn at all times. It's the intersection of 18363b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org // the non-transparent parts of the device and the outlines (shape) of 18373b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org // all images and devices drawn. 18383b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org drawFormXObjectWithMask(addXObjectResource(srcFormXObject.get()), dst, 18394e8f1e56b17c3663d1892f44a4c1893b568ce67fcommit-bot@chromium.org &fExistingClipStack, fExistingClipRegion, 18403b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org SkXfermode::kSrcOver_Mode, true); 18413b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org } else { 18423b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org SkAutoTUnref<SkPDFFormXObject> dstMaskStorage; 18433b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org SkPDFFormXObject* dstMask = srcFormXObject.get(); 18443b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org if (shape != NULL) { 18453b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org // Draw shape into a form-xobject. 18463b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org SkDraw d; 18473b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org d.fMatrix = &identity; 18483b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org d.fClip = &clipRegion; 18493b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org d.fClipStack = &clipStack; 18503b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org SkPaint filledPaint; 18513b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org filledPaint.setColor(SK_ColorBLACK); 18523b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org filledPaint.setStyle(SkPaint::kFill_Style); 18533b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org this->drawPath(d, *shape, filledPaint, NULL, true); 18543b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org 18553b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org dstMaskStorage.reset(createFormXObjectFromDevice()); 18563b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org dstMask = dstMaskStorage.get(); 18573b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org } 18584e8f1e56b17c3663d1892f44a4c1893b568ce67fcommit-bot@chromium.org drawFormXObjectWithMask(addXObjectResource(dst), dstMask, 18594e8f1e56b17c3663d1892f44a4c1893b568ce67fcommit-bot@chromium.org &fExistingClipStack, fExistingClipRegion, 18604e8f1e56b17c3663d1892f44a4c1893b568ce67fcommit-bot@chromium.org SkXfermode::kSrcOver_Mode, true); 1861481aef68333e01c19badda456d8e60bd1f1bee2avandebo@chromium.org } 18626112c215fbdd53388e64ece36e6c7bba0fe3a451vandebo@chromium.org 18637542dc8897d151afc0eca7dd73d72ea05f92baadcommit-bot@chromium.org if (xfermode == SkXfermode::kClear_Mode) { 18643b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org return; 18653b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org } else if (xfermode == SkXfermode::kSrc_Mode || 18663b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org xfermode == SkXfermode::kDstATop_Mode) { 18674e8f1e56b17c3663d1892f44a4c1893b568ce67fcommit-bot@chromium.org ScopedContentEntry content(this, &fExistingClipStack, 18684e8f1e56b17c3663d1892f44a4c1893b568ce67fcommit-bot@chromium.org fExistingClipRegion, identity, stockPaint); 18693b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org if (content.entry()) { 18703b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org SkPDFUtils::DrawFormXObject( 18713b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org this->addXObjectResource(srcFormXObject.get()), 18723b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org &content.entry()->fContent); 18733b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org } 18743b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org if (xfermode == SkXfermode::kSrc_Mode) { 18753b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org return; 18763b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org } 18777542dc8897d151afc0eca7dd73d72ea05f92baadcommit-bot@chromium.org } else if (xfermode == SkXfermode::kSrcATop_Mode) { 18784e8f1e56b17c3663d1892f44a4c1893b568ce67fcommit-bot@chromium.org ScopedContentEntry content(this, &fExistingClipStack, 18794e8f1e56b17c3663d1892f44a4c1893b568ce67fcommit-bot@chromium.org fExistingClipRegion, identity, stockPaint); 18807542dc8897d151afc0eca7dd73d72ea05f92baadcommit-bot@chromium.org if (content.entry()) { 18817542dc8897d151afc0eca7dd73d72ea05f92baadcommit-bot@chromium.org SkPDFUtils::DrawFormXObject(this->addXObjectResource(dst), 18827542dc8897d151afc0eca7dd73d72ea05f92baadcommit-bot@chromium.org &content.entry()->fContent); 18837542dc8897d151afc0eca7dd73d72ea05f92baadcommit-bot@chromium.org } 18843b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org } 18853b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org 18863b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org SkASSERT(xfermode == SkXfermode::kSrcIn_Mode || 18873b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org xfermode == SkXfermode::kDstIn_Mode || 18883b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org xfermode == SkXfermode::kSrcOut_Mode || 18893b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org xfermode == SkXfermode::kDstOut_Mode || 18903b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org xfermode == SkXfermode::kSrcATop_Mode || 18913b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org xfermode == SkXfermode::kDstATop_Mode || 18923b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org xfermode == SkXfermode::kModulate_Mode); 18933b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org 18946112c215fbdd53388e64ece36e6c7bba0fe3a451vandebo@chromium.org if (xfermode == SkXfermode::kSrcIn_Mode || 18953b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org xfermode == SkXfermode::kSrcOut_Mode || 18963b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org xfermode == SkXfermode::kSrcATop_Mode) { 18973b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org drawFormXObjectWithMask(addXObjectResource(srcFormXObject.get()), dst, 18984e8f1e56b17c3663d1892f44a4c1893b568ce67fcommit-bot@chromium.org &fExistingClipStack, fExistingClipRegion, 18993b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org SkXfermode::kSrcOver_Mode, 19003b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org xfermode == SkXfermode::kSrcOut_Mode); 19016112c215fbdd53388e64ece36e6c7bba0fe3a451vandebo@chromium.org } else { 19023b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org SkXfermode::Mode mode = SkXfermode::kSrcOver_Mode; 19033b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org if (xfermode == SkXfermode::kModulate_Mode) { 19043b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org drawFormXObjectWithMask(addXObjectResource(srcFormXObject.get()), 19054e8f1e56b17c3663d1892f44a4c1893b568ce67fcommit-bot@chromium.org dst, &fExistingClipStack, 19064e8f1e56b17c3663d1892f44a4c1893b568ce67fcommit-bot@chromium.org fExistingClipRegion, 19073b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org SkXfermode::kSrcOver_Mode, false); 19083b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org mode = SkXfermode::kMultiply_Mode; 19093b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org } 19103b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org drawFormXObjectWithMask(addXObjectResource(dst), srcFormXObject.get(), 19114e8f1e56b17c3663d1892f44a4c1893b568ce67fcommit-bot@chromium.org &fExistingClipStack, fExistingClipRegion, mode, 19123b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org xfermode == SkXfermode::kDstOut_Mode); 19136112c215fbdd53388e64ece36e6c7bba0fe3a451vandebo@chromium.org } 19146112c215fbdd53388e64ece36e6c7bba0fe3a451vandebo@chromium.org} 19156112c215fbdd53388e64ece36e6c7bba0fe3a451vandebo@chromium.org 1916481aef68333e01c19badda456d8e60bd1f1bee2avandebo@chromium.orgbool SkPDFDevice::isContentEmpty() { 19179510ccc06bbfa5e888f66578042674be98d8ac60ctguil@chromium.org ContentEntry* contentEntries = getContentEntries()->get(); 19189510ccc06bbfa5e888f66578042674be98d8ac60ctguil@chromium.org if (!contentEntries || contentEntries->fContent.getOffset() == 0) { 19199510ccc06bbfa5e888f66578042674be98d8ac60ctguil@chromium.org SkASSERT(!contentEntries || !contentEntries->fNext.get()); 1920481aef68333e01c19badda456d8e60bd1f1bee2avandebo@chromium.org return true; 1921481aef68333e01c19badda456d8e60bd1f1bee2avandebo@chromium.org } 1922481aef68333e01c19badda456d8e60bd1f1bee2avandebo@chromium.org return false; 1923481aef68333e01c19badda456d8e60bd1f1bee2avandebo@chromium.org} 1924481aef68333e01c19badda456d8e60bd1f1bee2avandebo@chromium.org 19259fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.orgvoid SkPDFDevice::populateGraphicStateEntryFromPaint( 19269fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org const SkMatrix& matrix, 19279fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org const SkClipStack& clipStack, 19289fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org const SkRegion& clipRegion, 19299fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org const SkPaint& paint, 19309fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org bool hasText, 19319fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org GraphicStateEntry* entry) { 19326f4e473676ff5c32c06151f4f8451d62715d65d2reed@google.com NOT_IMPLEMENTED(paint.getPathEffect() != NULL, false); 1933da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org NOT_IMPLEMENTED(paint.getMaskFilter() != NULL, false); 1934da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org NOT_IMPLEMENTED(paint.getColorFilter() != NULL, false); 19359b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org 19369fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org entry->fMatrix = matrix; 19379fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org entry->fClipStack = clipStack; 19389fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org entry->fClipRegion = clipRegion; 1939da6c569334b5971e55dc95cb9bf85853d068e999vandebo@chromium.org entry->fColor = SkColorSetA(paint.getColor(), 0xFF); 1940da6c569334b5971e55dc95cb9bf85853d068e999vandebo@chromium.org entry->fShaderIndex = -1; 194148543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org 1942da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org // PDF treats a shader as a color, so we only set one or the other. 1943d96d17b9c113ac694138224249ff2ce643e961ddvandebo@chromium.org SkAutoTUnref<SkPDFObject> pdfShader; 19449fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org const SkShader* shader = paint.getShader(); 19459fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org SkColor color = paint.getColor(); 1946da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org if (shader) { 1947da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org // PDF positions patterns relative to the initial transform, so 1948da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org // we need to apply the current transform to the shader parameters. 19499fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org SkMatrix transform = matrix; 195075f97e452e8f2ee55cd2b283df7d7734f48bc2bfvandebo@chromium.org transform.postConcat(fInitialTransform); 1951da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 1952da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org // PDF doesn't support kClamp_TileMode, so we simulate it by making 19539fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org // a pattern the size of the current clip. 1954b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org SkIRect bounds = clipRegion.getBounds(); 1955293a758929222b6003678c6a49bfbb2f2f806e8evandebo@chromium.org 1956293a758929222b6003678c6a49bfbb2f2f806e8evandebo@chromium.org // We need to apply the initial transform to bounds in order to get 1957293a758929222b6003678c6a49bfbb2f2f806e8evandebo@chromium.org // bounds in a consistent coordinate system. 1958293a758929222b6003678c6a49bfbb2f2f806e8evandebo@chromium.org SkRect boundsTemp; 1959293a758929222b6003678c6a49bfbb2f2f806e8evandebo@chromium.org boundsTemp.set(bounds); 1960293a758929222b6003678c6a49bfbb2f2f806e8evandebo@chromium.org fInitialTransform.mapRect(&boundsTemp); 1961293a758929222b6003678c6a49bfbb2f2f806e8evandebo@chromium.org boundsTemp.roundOut(&bounds); 1962293a758929222b6003678c6a49bfbb2f2f806e8evandebo@chromium.org 1963d96d17b9c113ac694138224249ff2ce643e961ddvandebo@chromium.org pdfShader.reset(SkPDFShader::GetPDFShader(*shader, transform, bounds)); 1964da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org 1965b88cfe58e117ffe781e4ce2cba73cc4f7a795de7vandebo@chromium.org if (pdfShader.get()) { 1966b88cfe58e117ffe781e4ce2cba73cc4f7a795de7vandebo@chromium.org // pdfShader has been canonicalized so we can directly compare 1967b88cfe58e117ffe781e4ce2cba73cc4f7a795de7vandebo@chromium.org // pointers. 1968b88cfe58e117ffe781e4ce2cba73cc4f7a795de7vandebo@chromium.org int resourceIndex = fShaderResources.find(pdfShader.get()); 1969b88cfe58e117ffe781e4ce2cba73cc4f7a795de7vandebo@chromium.org if (resourceIndex < 0) { 1970b88cfe58e117ffe781e4ce2cba73cc4f7a795de7vandebo@chromium.org resourceIndex = fShaderResources.count(); 1971b88cfe58e117ffe781e4ce2cba73cc4f7a795de7vandebo@chromium.org fShaderResources.push(pdfShader.get()); 1972d96d17b9c113ac694138224249ff2ce643e961ddvandebo@chromium.org pdfShader.get()->ref(); 1973b88cfe58e117ffe781e4ce2cba73cc4f7a795de7vandebo@chromium.org } 1974b88cfe58e117ffe781e4ce2cba73cc4f7a795de7vandebo@chromium.org entry->fShaderIndex = resourceIndex; 1975b88cfe58e117ffe781e4ce2cba73cc4f7a795de7vandebo@chromium.org } else { 1976b88cfe58e117ffe781e4ce2cba73cc4f7a795de7vandebo@chromium.org // A color shader is treated as an invalid shader so we don't have 1977b88cfe58e117ffe781e4ce2cba73cc4f7a795de7vandebo@chromium.org // to set a shader just for a color. 1978da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkShader::GradientInfo gradientInfo; 1979da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkColor gradientColor; 1980da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org gradientInfo.fColors = &gradientColor; 1981da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org gradientInfo.fColorOffsets = NULL; 1982da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org gradientInfo.fColorCount = 1; 1983da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org if (shader->asAGradient(&gradientInfo) == 1984da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org SkShader::kColor_GradientType) { 19859fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org entry->fColor = SkColorSetA(gradientColor, 0xFF); 19869fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org color = gradientColor; 1987da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 1988da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 1989da912d61ede86dd3dfa8f645c6f3977f2183812bvandebo@chromium.org } 19909b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org 1991d96d17b9c113ac694138224249ff2ce643e961ddvandebo@chromium.org SkAutoTUnref<SkPDFGraphicState> newGraphicState; 19929fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org if (color == paint.getColor()) { 1993d96d17b9c113ac694138224249ff2ce643e961ddvandebo@chromium.org newGraphicState.reset( 1994d96d17b9c113ac694138224249ff2ce643e961ddvandebo@chromium.org SkPDFGraphicState::GetGraphicStateForPaint(paint)); 19959fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org } else { 19969fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org SkPaint newPaint = paint; 19979fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org newPaint.setColor(color); 1998d96d17b9c113ac694138224249ff2ce643e961ddvandebo@chromium.org newGraphicState.reset( 1999d96d17b9c113ac694138224249ff2ce643e961ddvandebo@chromium.org SkPDFGraphicState::GetGraphicStateForPaint(newPaint)); 20009fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org } 20016112c215fbdd53388e64ece36e6c7bba0fe3a451vandebo@chromium.org int resourceIndex = addGraphicStateResource(newGraphicState.get()); 20029fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org entry->fGraphicStateIndex = resourceIndex; 200328be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org 20049fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org if (hasText) { 20059fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org entry->fTextScaleX = paint.getTextScaleX(); 20069fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org entry->fTextFill = paint.getStyle(); 20079fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org } else { 20089fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org entry->fTextScaleX = 0; 20099b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org } 20109b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org} 20119b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org 20126112c215fbdd53388e64ece36e6c7bba0fe3a451vandebo@chromium.orgint SkPDFDevice::addGraphicStateResource(SkPDFGraphicState* gs) { 20136112c215fbdd53388e64ece36e6c7bba0fe3a451vandebo@chromium.org // Assumes that gs has been canonicalized (so we can directly compare 20146112c215fbdd53388e64ece36e6c7bba0fe3a451vandebo@chromium.org // pointers). 20156112c215fbdd53388e64ece36e6c7bba0fe3a451vandebo@chromium.org int result = fGraphicStateResources.find(gs); 20166112c215fbdd53388e64ece36e6c7bba0fe3a451vandebo@chromium.org if (result < 0) { 20176112c215fbdd53388e64ece36e6c7bba0fe3a451vandebo@chromium.org result = fGraphicStateResources.count(); 20186112c215fbdd53388e64ece36e6c7bba0fe3a451vandebo@chromium.org fGraphicStateResources.push(gs); 20196112c215fbdd53388e64ece36e6c7bba0fe3a451vandebo@chromium.org gs->ref(); 20206112c215fbdd53388e64ece36e6c7bba0fe3a451vandebo@chromium.org } 20216112c215fbdd53388e64ece36e6c7bba0fe3a451vandebo@chromium.org return result; 20226112c215fbdd53388e64ece36e6c7bba0fe3a451vandebo@chromium.org} 20236112c215fbdd53388e64ece36e6c7bba0fe3a451vandebo@chromium.org 20243b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.orgint SkPDFDevice::addXObjectResource(SkPDFObject* xObject) { 20253b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org // Assumes that xobject has been canonicalized (so we can directly compare 20263b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org // pointers). 20273b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org int result = fXObjectResources.find(xObject); 20283b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org if (result < 0) { 20293b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org result = fXObjectResources.count(); 20303b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org fXObjectResources.push(xObject); 20313b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org xObject->ref(); 20323b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org } 20333b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org return result; 20343b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org} 20353b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org 2036b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.orgvoid SkPDFDevice::updateFont(const SkPaint& paint, uint16_t glyphID, 2037b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org ContentEntry* contentEntry) { 20389db86bb9cd1b77be0afc504ccc07026e4282d7e7ctguil@chromium.org SkTypeface* typeface = paint.getTypeface(); 2039b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org if (contentEntry->fState.fFont == NULL || 2040b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org contentEntry->fState.fTextSize != paint.getTextSize() || 2041b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org !contentEntry->fState.fFont->hasGlyph(glyphID)) { 20429db86bb9cd1b77be0afc504ccc07026e4282d7e7ctguil@chromium.org int fontIndex = getFontResourceIndex(typeface, glyphID); 204347401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org contentEntry->fContent.writeText("/"); 204447401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org contentEntry->fContent.writeText(SkPDFResourceDict::getResourceName( 204547401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org SkPDFResourceDict::kFont_ResourceType, 204647401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org fontIndex).c_str()); 2047b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org contentEntry->fContent.writeText(" "); 2048b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org SkPDFScalar::Append(paint.getTextSize(), &contentEntry->fContent); 2049b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org contentEntry->fContent.writeText(" Tf\n"); 2050b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org contentEntry->fState.fFont = fFontResources[fontIndex]; 20512a22e10ab2946c5590cd2a258427ce3ccfca9bfavandebo@chromium.org } 20522a22e10ab2946c5590cd2a258427ce3ccfca9bfavandebo@chromium.org} 20532a22e10ab2946c5590cd2a258427ce3ccfca9bfavandebo@chromium.org 20549db86bb9cd1b77be0afc504ccc07026e4282d7e7ctguil@chromium.orgint SkPDFDevice::getFontResourceIndex(SkTypeface* typeface, uint16_t glyphID) { 20553b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org SkAutoTUnref<SkPDFFont> newFont(SkPDFFont::GetFontResource(typeface, 20563b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org glyphID)); 205728be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org int resourceIndex = fFontResources.find(newFont.get()); 205828be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org if (resourceIndex < 0) { 205928be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org resourceIndex = fFontResources.count(); 206028be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org fFontResources.push(newFont.get()); 2061d96d17b9c113ac694138224249ff2ce643e961ddvandebo@chromium.org newFont.get()->ref(); 206228be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org } 206328be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org return resourceIndex; 206428be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org} 206528be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org 20669cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.comvoid SkPDFDevice::internalDrawBitmap(const SkMatrix& origMatrix, 206778dad54080ad806be89adb5cc0e3c530b031cdafvandebo@chromium.org const SkClipStack* clipStack, 20689cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com const SkRegion& origClipRegion, 20699cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com const SkBitmap& origBitmap, 2070befebb8a8437ce69e3a416b417cb27b66273128dvandebo@chromium.org const SkIRect* srcRect, 20719b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org const SkPaint& paint) { 20729cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com SkMatrix matrix = origMatrix; 20739cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com SkRegion perspectiveBounds; 20749cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com const SkRegion* clipRegion = &origClipRegion; 20759cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com SkBitmap perspectiveBitmap; 20769cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com const SkBitmap* bitmap = &origBitmap; 20779cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com SkBitmap tmpSubsetBitmap; 20789cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com 20799cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com // Rasterize the bitmap using perspective in a new bitmap. 20809cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com if (origMatrix.hasPerspective()) { 208173a7ea3ae0d37ee28f90d6b38c49fda052638253edisonn@google.com if (fRasterDpi == 0) { 208273a7ea3ae0d37ee28f90d6b38c49fda052638253edisonn@google.com return; 208373a7ea3ae0d37ee28f90d6b38c49fda052638253edisonn@google.com } 20849cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com SkBitmap* subsetBitmap; 20859cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com if (srcRect) { 20869cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com if (!origBitmap.extractSubset(&tmpSubsetBitmap, *srcRect)) { 20879cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com return; 20889cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com } 20899cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com subsetBitmap = &tmpSubsetBitmap; 20909cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com } else { 20919cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com subsetBitmap = &tmpSubsetBitmap; 20929cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com *subsetBitmap = origBitmap; 20939cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com } 20949cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com srcRect = NULL; 20959cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com 209673a7ea3ae0d37ee28f90d6b38c49fda052638253edisonn@google.com // Transform the bitmap in the new space, without taking into 209773a7ea3ae0d37ee28f90d6b38c49fda052638253edisonn@google.com // account the initial transform. 20989cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com SkPath perspectiveOutline; 20999cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com perspectiveOutline.addRect( 21009cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com SkRect::MakeWH(SkIntToScalar(subsetBitmap->width()), 21019cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com SkIntToScalar(subsetBitmap->height()))); 21029cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com perspectiveOutline.transform(origMatrix); 21039cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com 21049cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com // TODO(edisonn): perf - use current clip too. 21059cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com // Retrieve the bounds of the new shape. 21069cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com SkRect bounds = perspectiveOutline.getBounds(); 21079cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com 210873a7ea3ae0d37ee28f90d6b38c49fda052638253edisonn@google.com // Transform the bitmap in the new space, taking into 210973a7ea3ae0d37ee28f90d6b38c49fda052638253edisonn@google.com // account the initial transform. 211073a7ea3ae0d37ee28f90d6b38c49fda052638253edisonn@google.com SkMatrix total = origMatrix; 211173a7ea3ae0d37ee28f90d6b38c49fda052638253edisonn@google.com total.postConcat(fInitialTransform); 211273a7ea3ae0d37ee28f90d6b38c49fda052638253edisonn@google.com total.postScale(SkIntToScalar(fRasterDpi) / 211373a7ea3ae0d37ee28f90d6b38c49fda052638253edisonn@google.com SkIntToScalar(DPI_FOR_RASTER_SCALE_ONE), 211473a7ea3ae0d37ee28f90d6b38c49fda052638253edisonn@google.com SkIntToScalar(fRasterDpi) / 211573a7ea3ae0d37ee28f90d6b38c49fda052638253edisonn@google.com SkIntToScalar(DPI_FOR_RASTER_SCALE_ONE)); 211673a7ea3ae0d37ee28f90d6b38c49fda052638253edisonn@google.com SkPath physicalPerspectiveOutline; 211773a7ea3ae0d37ee28f90d6b38c49fda052638253edisonn@google.com physicalPerspectiveOutline.addRect( 211873a7ea3ae0d37ee28f90d6b38c49fda052638253edisonn@google.com SkRect::MakeWH(SkIntToScalar(subsetBitmap->width()), 211973a7ea3ae0d37ee28f90d6b38c49fda052638253edisonn@google.com SkIntToScalar(subsetBitmap->height()))); 212073a7ea3ae0d37ee28f90d6b38c49fda052638253edisonn@google.com physicalPerspectiveOutline.transform(total); 212173a7ea3ae0d37ee28f90d6b38c49fda052638253edisonn@google.com 212273a7ea3ae0d37ee28f90d6b38c49fda052638253edisonn@google.com SkScalar scaleX = physicalPerspectiveOutline.getBounds().width() / 212373a7ea3ae0d37ee28f90d6b38c49fda052638253edisonn@google.com bounds.width(); 212473a7ea3ae0d37ee28f90d6b38c49fda052638253edisonn@google.com SkScalar scaleY = physicalPerspectiveOutline.getBounds().height() / 212573a7ea3ae0d37ee28f90d6b38c49fda052638253edisonn@google.com bounds.height(); 21269cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com 21279cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com // TODO(edisonn): A better approach would be to use a bitmap shader 21289cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com // (in clamp mode) and draw a rect over the entire bounding box. Then 21299cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com // intersect perspectiveOutline to the clip. That will avoid introducing 21309cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com // alpha to the image while still giving good behavior at the edge of 21319cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com // the image. Avoiding alpha will reduce the pdf size and generation 21329cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com // CPU time some. 21339cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com 21349ebcac54635cde63110d73ad7c43d70772e7872freed@google.com const int w = SkScalarCeilToInt(physicalPerspectiveOutline.getBounds().width()); 21359ebcac54635cde63110d73ad7c43d70772e7872freed@google.com const int h = SkScalarCeilToInt(physicalPerspectiveOutline.getBounds().height()); 2136848250415eddc54075f7eb8795e8db79e749c6abreed if (!perspectiveBitmap.tryAllocN32Pixels(w, h)) { 21379ebcac54635cde63110d73ad7c43d70772e7872freed@google.com return; 21389ebcac54635cde63110d73ad7c43d70772e7872freed@google.com } 21399cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com perspectiveBitmap.eraseColor(SK_ColorTRANSPARENT); 21409cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com 214189443aba5bfa2b040dc9fd24938b7d0b3decd737reed SkCanvas canvas(perspectiveBitmap); 21429cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com 21439cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com SkScalar deltaX = bounds.left(); 21449cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com SkScalar deltaY = bounds.top(); 21459cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com 21469cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com SkMatrix offsetMatrix = origMatrix; 21479cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com offsetMatrix.postTranslate(-deltaX, -deltaY); 214873a7ea3ae0d37ee28f90d6b38c49fda052638253edisonn@google.com offsetMatrix.postScale(scaleX, scaleY); 21499cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com 21509cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com // Translate the draw in the new canvas, so we perfectly fit the 21519cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com // shape in the bitmap. 21529cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com canvas.setMatrix(offsetMatrix); 21539cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com 21549cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com canvas.drawBitmap(*subsetBitmap, SkIntToScalar(0), SkIntToScalar(0)); 21559cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com 21569cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com // Make sure the final bits are in the bitmap. 21579cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com canvas.flush(); 21589cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com 215973a7ea3ae0d37ee28f90d6b38c49fda052638253edisonn@google.com // In the new space, we use the identity matrix translated 216073a7ea3ae0d37ee28f90d6b38c49fda052638253edisonn@google.com // and scaled to reflect DPI. 216173a7ea3ae0d37ee28f90d6b38c49fda052638253edisonn@google.com matrix.setScale(1 / scaleX, 1 / scaleY); 216273a7ea3ae0d37ee28f90d6b38c49fda052638253edisonn@google.com matrix.postTranslate(deltaX, deltaY); 216373a7ea3ae0d37ee28f90d6b38c49fda052638253edisonn@google.com 21649cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com perspectiveBounds.setRect( 21659cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com SkIRect::MakeXYWH(SkScalarFloorToInt(bounds.x()), 21669cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com SkScalarFloorToInt(bounds.y()), 21679cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com SkScalarCeilToInt(bounds.width()), 21689cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com SkScalarCeilToInt(bounds.height()))); 21699cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com clipRegion = &perspectiveBounds; 21709cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com srcRect = NULL; 21719cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com bitmap = &perspectiveBitmap; 21729cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com } 21739cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com 21747e2ff7cf7da604b29378978ef5d4655499485368vandebo@chromium.org SkMatrix scaled; 21757e2ff7cf7da604b29378978ef5d4655499485368vandebo@chromium.org // Adjust for origin flip. 2176663515bc59325092c4e47f5189782bd6fcd0586avandebo@chromium.org scaled.setScale(SK_Scalar1, -SK_Scalar1); 2177663515bc59325092c4e47f5189782bd6fcd0586avandebo@chromium.org scaled.postTranslate(0, SK_Scalar1); 21787e2ff7cf7da604b29378978ef5d4655499485368vandebo@chromium.org // Scale the image up from 1x1 to WxH. 21799cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com SkIRect subset = SkIRect::MakeWH(bitmap->width(), bitmap->height()); 2180a6d59f60aab59fb6556841b063ead5d49b46ba8dreed@google.com scaled.postScale(SkIntToScalar(subset.width()), 2181a6d59f60aab59fb6556841b063ead5d49b46ba8dreed@google.com SkIntToScalar(subset.height())); 21827e2ff7cf7da604b29378978ef5d4655499485368vandebo@chromium.org scaled.postConcat(matrix); 21839cf0cb169bda63ad50f4c394739deb6c67003647edisonn@google.com ScopedContentEntry content(this, clipStack, *clipRegion, scaled, paint); 21843b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org if (!content.entry() || (srcRect && !subset.intersect(*srcRect))) { 218525adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org return; 218625adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org } 21873b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org if (content.needShape()) { 21883b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org SkPath shape; 2189fd3c8c243ab190604e134910a1d6c1326d21e374vandebo@chromium.org shape.addRect(SkRect::MakeWH(SkIntToScalar(subset.width()), 2190fd3c8c243ab190604e134910a1d6c1326d21e374vandebo@chromium.org SkIntToScalar( subset.height()))); 21913b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org shape.transform(matrix); 21923b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org content.setShape(shape); 21933b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org } 21943b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org if (!content.needSource()) { 219525adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org return; 219625adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org } 219725adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org 2198daefa5b340d7aa36fe31865a3646f6fce321bb38halcanary SkAutoTUnref<SkPDFObject> image( 2199daefa5b340d7aa36fe31865a3646f6fce321bb38halcanary SkPDFCreateImageObject(*bitmap, subset, fEncoder)); 220025adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org if (!image) { 220125adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org return; 220225adce81ce24702174ede33445c414a8d21d8a23vandebo@chromium.org } 22037e2ff7cf7da604b29378978ef5d4655499485368vandebo@chromium.org 22043b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org SkPDFUtils::DrawFormXObject(this->addXObjectResource(image.get()), 2205b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org &content.entry()->fContent); 22069b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org} 2207982cb875f01e247843b9a79082f680cdcf234c2creed@google.com 2208