10b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger/* 20b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger * Copyright (C) 2011 Google Inc. 30b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger * 40b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger * Licensed under the Apache License, Version 2.0 (the "License"); 50b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger * you may not use this file except in compliance with the License. 60b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger * You may obtain a copy of the License at 70b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger * 80b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger * http://www.apache.org/licenses/LICENSE-2.0 90b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger * 100b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger * Unless required by applicable law or agreed to in writing, software 110b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger * distributed under the License is distributed on an "AS IS" BASIS, 120b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 130b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger * See the License for the specific language governing permissions and 140b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger * limitations under the License. 150b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger */ 160b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 170b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger#include "SkPDFDevice.h" 180b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 190b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger#include "SkColor.h" 200b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger#include "SkClipStack.h" 210b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger#include "SkDraw.h" 220b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger#include "SkGlyphCache.h" 230b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger#include "SkPaint.h" 240b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger#include "SkPath.h" 250b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger#include "SkPDFFont.h" 260b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger#include "SkPDFFormXObject.h" 270b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger#include "SkPDFGraphicState.h" 280b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger#include "SkPDFImage.h" 290b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger#include "SkPDFShader.h" 300b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger#include "SkPDFStream.h" 310b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger#include "SkPDFTypes.h" 320b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger#include "SkPDFUtils.h" 330b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger#include "SkRect.h" 340b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger#include "SkString.h" 350b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger#include "SkTextFormatParams.h" 360b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger#include "SkTypeface.h" 370b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger#include "SkTypes.h" 380b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 390b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger// Utility functions 400b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 410b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenbergerstatic void emit_pdf_color(SkColor color, SkWStream* result) { 420b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkASSERT(SkColorGetA(color) == 0xFF); // We handle alpha elsewhere. 430b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkScalar colorMax = SkIntToScalar(0xFF); 440b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkPDFScalar::Append( 450b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkScalarDiv(SkIntToScalar(SkColorGetR(color)), colorMax), result); 460b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger result->writeText(" "); 470b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkPDFScalar::Append( 480b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkScalarDiv(SkIntToScalar(SkColorGetG(color)), colorMax), result); 490b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger result->writeText(" "); 500b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkPDFScalar::Append( 510b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkScalarDiv(SkIntToScalar(SkColorGetB(color)), colorMax), result); 520b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger result->writeText(" "); 530b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger} 540b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 550b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenbergerstatic SkPaint calculate_text_paint(const SkPaint& paint) { 560b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkPaint result = paint; 570b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (result.isFakeBoldText()) { 580b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkScalar fakeBoldScale = SkScalarInterpFunc(result.getTextSize(), 590b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger kStdFakeBoldInterpKeys, 600b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger kStdFakeBoldInterpValues, 610b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger kStdFakeBoldInterpLength); 620b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkScalar width = SkScalarMul(result.getTextSize(), fakeBoldScale); 630b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (result.getStyle() == SkPaint::kFill_Style) 640b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger result.setStyle(SkPaint::kStrokeAndFill_Style); 650b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger else 660b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger width += result.getStrokeWidth(); 670b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger result.setStrokeWidth(width); 680b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 690b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger return result; 700b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger} 710b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 720b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger// Stolen from measure_text in SkDraw.cpp and then tweaked. 730b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenbergerstatic void align_text(SkDrawCacheProc glyphCacheProc, const SkPaint& paint, 740b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger const uint16_t* glyphs, size_t len, SkScalar* x, 750b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkScalar* y, SkScalar* width) { 760b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (paint.getTextAlign() == SkPaint::kLeft_Align && width == NULL) 770b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger return; 780b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 790b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkMatrix ident; 800b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger ident.reset(); 810b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkAutoGlyphCache autoCache(paint, &ident); 820b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkGlyphCache* cache = autoCache.getCache(); 830b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 840b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger const char* start = (char*)glyphs; 850b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger const char* stop = (char*)(glyphs + len); 860b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkFixed xAdv = 0, yAdv = 0; 870b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 880b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // TODO(vandebo) This probably needs to take kerning into account. 890b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger while (start < stop) { 900b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger const SkGlyph& glyph = glyphCacheProc(cache, &start, 0, 0); 910b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger xAdv += glyph.fAdvanceX; 920b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger yAdv += glyph.fAdvanceY; 930b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger }; 940b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (width) 950b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger *width = SkFixedToScalar(xAdv); 960b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (paint.getTextAlign() == SkPaint::kLeft_Align) 970b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger return; 980b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 990b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkScalar xAdj = SkFixedToScalar(xAdv); 1000b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkScalar yAdj = SkFixedToScalar(yAdv); 1010b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (paint.getTextAlign() == SkPaint::kCenter_Align) { 1020b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger xAdj = SkScalarHalf(xAdj); 1030b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger yAdj = SkScalarHalf(yAdj); 1040b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 1050b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger *x = *x - xAdj; 1060b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger *y = *y - yAdj; 1070b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger} 1080b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 1090b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenbergerstatic void set_text_transform(SkScalar x, SkScalar y, SkScalar textSkewX, 1100b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkWStream* content) { 1110b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // Flip the text about the x-axis to account for origin swap and include 1120b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // the passed parameters. 1130b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger content->writeText("1 0 "); 1140b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkPDFScalar::Append(0 - textSkewX, content); 1150b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger content->writeText(" -1 "); 1160b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkPDFScalar::Append(x, content); 1170b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger content->writeText(" "); 1180b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkPDFScalar::Append(y, content); 1190b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger content->writeText(" Tm\n"); 1200b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger} 1210b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 1220b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger// It is important to not confuse GraphicStateEntry with SkPDFGraphicState, the 1230b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger// later being our representation of an object in the PDF file. 1240b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenbergerstruct GraphicStateEntry { 1250b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger GraphicStateEntry(); 1260b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 1270b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // Compare the fields we care about when setting up a new content entry. 1280b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger bool compareInitialState(const GraphicStateEntry& b); 1290b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 1300b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkMatrix fMatrix; 1310b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // We can't do set operations on Paths, though PDF natively supports 1320b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // intersect. If the clip stack does anything other than intersect, 1330b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // we have to fall back to the region. Treat fClipStack as authoritative. 1340b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // See http://code.google.com/p/skia/issues/detail?id=221 1350b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkClipStack fClipStack; 1360b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkRegion fClipRegion; 1370b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 1380b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // When emitting the content entry, we will ensure the graphic state 1390b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // is set to these values first. 1400b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkColor fColor; 1410b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkScalar fTextScaleX; // Zero means we don't care what the value is. 1420b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkPaint::Style fTextFill; // Only if TextScaleX is non-zero. 1430b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger int fShaderIndex; 1440b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger int fGraphicStateIndex; 1450b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 1460b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // We may change the font (i.e. for Type1 support) within a 1470b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // ContentEntry. This is the one currently in effect, or NULL if none. 1480b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkPDFFont* fFont; 1490b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // In PDF, text size has no default value. It is only valid if fFont is 1500b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // not NULL. 1510b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkScalar fTextSize; 1520b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger}; 1530b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 1540b15698a8c76bb8abc1b555c1d91892669b4118fDerek SollenbergerGraphicStateEntry::GraphicStateEntry() : fColor(SK_ColorBLACK), 1550b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fTextScaleX(SK_Scalar1), 1560b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fTextFill(SkPaint::kFill_Style), 1570b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fShaderIndex(-1), 1580b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fGraphicStateIndex(-1), 1590b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fFont(NULL), 1600b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fTextSize(SK_ScalarNaN) { 1610b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fMatrix.reset(); 1620b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger} 1630b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 1640b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenbergerbool GraphicStateEntry::compareInitialState(const GraphicStateEntry& b) { 1650b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger return fColor == b.fColor && 1660b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fShaderIndex == b.fShaderIndex && 1670b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fGraphicStateIndex == b.fGraphicStateIndex && 1680b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fMatrix == b.fMatrix && 1690b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fClipStack == b.fClipStack && 1700b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger (fTextScaleX == 0 || 1710b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger b.fTextScaleX == 0 || 1720b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger (fTextScaleX == b.fTextScaleX && fTextFill == b.fTextFill)); 1730b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger} 1740b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 1750b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenbergerclass GraphicStackState { 1760b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenbergerpublic: 1770b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger GraphicStackState(const SkClipStack& existingClipStack, 1780b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger const SkRegion& existingClipRegion, 1790b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkWStream* contentStream) 1800b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger : fStackDepth(0), 1810b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fContentStream(contentStream) { 1820b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fEntries[0].fClipStack = existingClipStack; 1830b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fEntries[0].fClipRegion = existingClipRegion; 1840b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 1850b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 1860b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger void updateClip(const SkClipStack& clipStack, const SkRegion& clipRegion, 1870b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger const SkIPoint& translation); 1880b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger void updateMatrix(const SkMatrix& matrix); 1890b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger void updateDrawingState(const GraphicStateEntry& state); 1900b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 1910b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger void drainStack(); 1920b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 1930b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenbergerprivate: 1940b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger void push(); 1950b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger void pop(); 1960b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger GraphicStateEntry* currentEntry() { return &fEntries[fStackDepth]; } 1970b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 1980b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // Conservative limit on save depth, see impl. notes in PDF 1.4 spec. 1990b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger static const int kMaxStackDepth = 12; 2000b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger GraphicStateEntry fEntries[kMaxStackDepth + 1]; 2010b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger int fStackDepth; 2020b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkWStream* fContentStream; 2030b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger}; 2040b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 2050b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenbergervoid GraphicStackState::drainStack() { 2060b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger while (fStackDepth) { 2070b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger pop(); 2080b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 2090b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger} 2100b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 2110b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenbergervoid GraphicStackState::push() { 2120b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkASSERT(fStackDepth < kMaxStackDepth); 2130b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fContentStream->writeText("q\n"); 2140b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fStackDepth++; 2150b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fEntries[fStackDepth] = fEntries[fStackDepth - 1]; 2160b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger} 2170b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 2180b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenbergervoid GraphicStackState::pop() { 2190b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkASSERT(fStackDepth > 0); 2200b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fContentStream->writeText("Q\n"); 2210b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fStackDepth--; 2220b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger} 2230b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 2240b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger// This function initializes iter to be an interator on the "stack" argument 2250b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger// and then skips over the leading entries as specified in prefix. It requires 2260b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger// and asserts that "prefix" will be a prefix to "stack." 2270b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenbergerstatic void skip_clip_stack_prefix(const SkClipStack& prefix, 2280b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger const SkClipStack& stack, 2290b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkClipStack::B2FIter* iter) { 2300b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkClipStack::B2FIter prefixIter(prefix); 2310b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger iter->reset(stack); 2320b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 2330b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger const SkClipStack::B2FIter::Clip* prefixEntry; 2340b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger const SkClipStack::B2FIter::Clip* iterEntry; 2350b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 2360b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger int count = 0; 2370b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger for (prefixEntry = prefixIter.next(); prefixEntry; 2380b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger prefixEntry = prefixIter.next(), count++) { 2390b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger iterEntry = iter->next(); 2400b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkASSERT(iterEntry); 2410b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // Because of SkClipStack does internal intersection, the last clip 2420b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // entry may differ. 2430b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if(*prefixEntry != *iterEntry) { 2440b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkASSERT(prefixEntry->fOp == SkRegion::kIntersect_Op); 2450b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkASSERT(iterEntry->fOp == SkRegion::kIntersect_Op); 2460b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkASSERT((iterEntry->fRect == NULL) == 2470b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger (prefixEntry->fRect == NULL)); 2480b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkASSERT((iterEntry->fPath == NULL) == 2490b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger (prefixEntry->fPath == NULL)); 2500b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // We need to back up the iterator by one but don't have that 2510b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // function, so reset and go forward by one less. 2520b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger iter->reset(stack); 2530b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger for (int i = 0; i < count; i++) { 2540b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger iter->next(); 2550b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 2560b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger prefixEntry = prefixIter.next(); 2570b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger break; 2580b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 2590b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 2600b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 2610b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkASSERT(prefixEntry == NULL); 2620b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger} 2630b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 2640b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenbergerstatic void emit_clip(SkPath* clipPath, SkRect* clipRect, 2650b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkWStream* contentStream) { 2660b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkASSERT(clipPath || clipRect); 2670b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 2680b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkPath::FillType clipFill; 2690b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (clipPath) { 2700b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkPDFUtils::EmitPath(*clipPath, contentStream); 2710b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger clipFill = clipPath->getFillType(); 2720b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } else if (clipRect) { 2730b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkPDFUtils::AppendRectangle(*clipRect, contentStream); 2740b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger clipFill = SkPath::kWinding_FillType; 2750b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 2760b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 2770b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger NOT_IMPLEMENTED(clipFill == SkPath::kInverseEvenOdd_FillType, false); 2780b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger NOT_IMPLEMENTED(clipFill == SkPath::kInverseWinding_FillType, false); 2790b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (clipFill == SkPath::kEvenOdd_FillType) { 2800b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger contentStream->writeText("W* n\n"); 2810b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } else { 2820b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger contentStream->writeText("W n\n"); 2830b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 2840b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger} 2850b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 2860b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger// TODO(vandebo) Take advantage of SkClipStack::getSaveCount(), the PDF 2870b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger// graphic state stack, and the fact that we can know all the clips used 2880b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger// on the page to optimize this. 2890b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenbergervoid GraphicStackState::updateClip(const SkClipStack& clipStack, 2900b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger const SkRegion& clipRegion, 2910b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger const SkIPoint& translation) { 2920b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (clipStack == currentEntry()->fClipStack) { 2930b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger return; 2940b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 2950b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 2960b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger while (fStackDepth > 0) { 2970b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger pop(); 2980b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (clipStack == currentEntry()->fClipStack) { 2990b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger return; 3000b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 3010b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 3020b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger push(); 3030b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 3040b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // gsState->initialEntry()->fClipStack/Region specifies the clip that has 3050b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // already been applied. (If this is a top level device, then it specifies 3060b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // a clip to the content area. If this is a layer, then it specifies 3070b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // the clip in effect when the layer was created.) There's no need to 3080b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // reapply that clip; SKCanvas's SkDrawIter will draw anything outside the 3090b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // initial clip on the parent layer. (This means there's a bug if the user 3100b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // expands the clip and then uses any xfer mode that uses dst: 3110b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // http://code.google.com/p/skia/issues/detail?id=228 ) 3120b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkClipStack::B2FIter iter; 3130b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger skip_clip_stack_prefix(fEntries[0].fClipStack, clipStack, &iter); 3140b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 3150b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // If the clip stack does anything other than intersect or if it uses 3160b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // an inverse fill type, we have to fall back to the clip region. 3170b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger bool needRegion = false; 3180b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger const SkClipStack::B2FIter::Clip* clipEntry; 3190b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger for (clipEntry = iter.next(); clipEntry; clipEntry = iter.next()) { 3200b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (clipEntry->fOp != SkRegion::kIntersect_Op || 3210b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger (clipEntry->fPath && clipEntry->fPath->isInverseFillType())) { 3220b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger needRegion = true; 3230b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger break; 3240b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 3250b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 3260b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 3270b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (needRegion) { 3280b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkPath clipPath; 3290b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkAssertResult(clipRegion.getBoundaryPath(&clipPath)); 3300b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger emit_clip(&clipPath, NULL, fContentStream); 3310b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } else { 3320b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger skip_clip_stack_prefix(fEntries[0].fClipStack, clipStack, &iter); 3330b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkMatrix transform; 3340b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger transform.setTranslate(translation.fX, translation.fY); 3350b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger const SkClipStack::B2FIter::Clip* clipEntry; 3360b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger for (clipEntry = iter.next(); clipEntry; clipEntry = iter.next()) { 3370b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkASSERT(clipEntry->fOp == SkRegion::kIntersect_Op); 3380b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (clipEntry->fRect) { 3390b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkRect translatedClip; 3400b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger transform.mapRect(&translatedClip, *clipEntry->fRect); 3410b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger emit_clip(NULL, &translatedClip, fContentStream); 3420b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } else if (clipEntry->fPath) { 3430b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkPath translatedPath; 3440b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger clipEntry->fPath->transform(transform, &translatedPath); 3450b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger emit_clip(&translatedPath, NULL, fContentStream); 3460b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } else { 3470b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkASSERT(false); 3480b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 3490b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 3500b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 3510b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger currentEntry()->fClipStack = clipStack; 3520b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger currentEntry()->fClipRegion = clipRegion; 3530b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger} 3540b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 3550b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenbergervoid GraphicStackState::updateMatrix(const SkMatrix& matrix) { 3560b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (matrix == currentEntry()->fMatrix) { 3570b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger return; 3580b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 3590b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 3600b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (currentEntry()->fMatrix.getType() != SkMatrix::kIdentity_Mask) { 3610b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkASSERT(fStackDepth > 0); 3620b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkASSERT(fEntries[fStackDepth].fClipStack == 3630b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fEntries[fStackDepth -1].fClipStack); 3640b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger pop(); 3650b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 3660b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkASSERT(currentEntry()->fMatrix.getType() == SkMatrix::kIdentity_Mask); 3670b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 3680b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (matrix.getType() == SkMatrix::kIdentity_Mask) { 3690b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger return; 3700b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 3710b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 3720b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger push(); 3730b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkPDFUtils::AppendTransform(matrix, fContentStream); 3740b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger currentEntry()->fMatrix = matrix; 3750b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger} 3760b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 3770b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenbergervoid GraphicStackState::updateDrawingState(const GraphicStateEntry& state) { 3780b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // PDF treats a shader as a color, so we only set one or the other. 3790b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (state.fShaderIndex >= 0) { 3800b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (state.fShaderIndex != currentEntry()->fShaderIndex) { 3810b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fContentStream->writeText("/Pattern CS /Pattern cs /P"); 3820b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fContentStream->writeDecAsText(state.fShaderIndex); 3830b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fContentStream->writeText(" SCN /P"); 3840b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fContentStream->writeDecAsText(state.fShaderIndex); 3850b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fContentStream->writeText(" scn\n"); 3860b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger currentEntry()->fShaderIndex = state.fShaderIndex; 3870b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 3880b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } else { 3890b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (state.fColor != currentEntry()->fColor || 3900b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger currentEntry()->fShaderIndex >= 0) { 3910b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger emit_pdf_color(state.fColor, fContentStream); 3920b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fContentStream->writeText("RG "); 3930b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger emit_pdf_color(state.fColor, fContentStream); 3940b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fContentStream->writeText("rg\n"); 3950b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger currentEntry()->fColor = state.fColor; 3960b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger currentEntry()->fShaderIndex = -1; 3970b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 3980b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 3990b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 4000b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (state.fGraphicStateIndex != currentEntry()->fGraphicStateIndex) { 4010b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkPDFUtils::ApplyGraphicState(state.fGraphicStateIndex, fContentStream); 4020b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger currentEntry()->fGraphicStateIndex = state.fGraphicStateIndex; 4030b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 4040b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 4050b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (state.fTextScaleX) { 4060b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (state.fTextScaleX != currentEntry()->fTextScaleX) { 4070b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkScalar pdfScale = SkScalarMul(state.fTextScaleX, 4080b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkIntToScalar(100)); 4090b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkPDFScalar::Append(pdfScale, fContentStream); 4100b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fContentStream->writeText(" Tz\n"); 4110b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger currentEntry()->fTextScaleX = state.fTextScaleX; 4120b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 4130b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (state.fTextFill != currentEntry()->fTextFill) { 4140b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SK_COMPILE_ASSERT(SkPaint::kFill_Style == 0, enum_must_match_value); 4150b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SK_COMPILE_ASSERT(SkPaint::kStroke_Style == 1, 4160b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger enum_must_match_value); 4170b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SK_COMPILE_ASSERT(SkPaint::kStrokeAndFill_Style == 2, 4180b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger enum_must_match_value); 4190b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fContentStream->writeDecAsText(state.fTextFill); 4200b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fContentStream->writeText(" Tr\n"); 4210b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger currentEntry()->fTextFill = state.fTextFill; 4220b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 4230b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 4240b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger} 4250b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 4260b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenbergerstruct ContentEntry { 4270b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger GraphicStateEntry fState; 4280b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkDynamicMemoryWStream fContent; 4290b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkTScopedPtr<ContentEntry> fNext; 4300b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger}; 4310b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 4320b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger// A helper class to automatically finish a ContentEntry at the end of a 4330b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger// drawing method and maintain the state needed between set up and finish. 4340b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenbergerclass ScopedContentEntry { 4350b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenbergerpublic: 4360b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger ScopedContentEntry(SkPDFDevice* device, const SkDraw& draw, 4370b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger const SkPaint& paint, bool hasText = false) 4380b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger : fDevice(device), 4390b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fContentEntry(NULL), 4400b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fXfermode(SkXfermode::kSrcOver_Mode) { 4410b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger init(draw.fClipStack, *draw.fClip, *draw.fMatrix, paint, hasText); 4420b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 4430b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger ScopedContentEntry(SkPDFDevice* device, const SkClipStack* clipStack, 4440b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger const SkRegion& clipRegion, const SkMatrix& matrix, 4450b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger const SkPaint& paint, bool hasText = false) 4460b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger : fDevice(device), 4470b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fContentEntry(NULL), 4480b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fXfermode(SkXfermode::kSrcOver_Mode) { 4490b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger init(clipStack, clipRegion, matrix, paint, hasText); 4500b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 4510b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 4520b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger ~ScopedContentEntry() { 4530b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (fContentEntry) { 4540b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fDevice->finishContentEntry(fXfermode, fDstFormXObject.get()); 4550b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 4560b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 4570b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 4580b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger ContentEntry* entry() { return fContentEntry; } 4590b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenbergerprivate: 4600b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkPDFDevice* fDevice; 4610b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger ContentEntry* fContentEntry; 4620b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkXfermode::Mode fXfermode; 4630b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkRefPtr<SkPDFFormXObject> fDstFormXObject; 4640b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 4650b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger void init(const SkClipStack* clipStack, const SkRegion& clipRegion, 4660b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger const SkMatrix& matrix, const SkPaint& paint, bool hasText) { 4670b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (paint.getXfermode()) { 4680b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger paint.getXfermode()->asMode(&fXfermode); 4690b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 4700b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fContentEntry = fDevice->setUpContentEntry(clipStack, clipRegion, 4710b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger matrix, paint, hasText, 4720b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger &fDstFormXObject); 4730b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 4740b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger}; 4750b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 4760b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger//////////////////////////////////////////////////////////////////////////////// 4770b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 4780b15698a8c76bb8abc1b555c1d91892669b4118fDerek SollenbergerSkDevice* SkPDFDeviceFactory::newDevice(SkCanvas* c, SkBitmap::Config config, 4790b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger int width, int height, bool isOpaque, 4800b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger bool isForLayer) { 4810b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkMatrix initialTransform; 4820b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger initialTransform.reset(); 4830b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkISize size = SkISize::Make(width, height); 4840b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (isForLayer) { 4850b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger return SkNEW_ARGS(SkPDFDevice, (size, c->getTotalClipStack(), 4860b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger c->getTotalClip())); 4870b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } else { 4880b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger return SkNEW_ARGS(SkPDFDevice, (size, size, initialTransform)); 4890b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 4900b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger} 4910b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 4920b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenbergerstatic inline SkBitmap makeContentBitmap(const SkISize& contentSize, 4930b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger const SkMatrix* initialTransform) { 4940b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkBitmap bitmap; 4950b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (initialTransform) { 4960b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // Compute the size of the drawing area. 4970b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkVector drawingSize; 4980b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkMatrix inverse; 4990b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger drawingSize.set(contentSize.fWidth, contentSize.fHeight); 5000b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger initialTransform->invert(&inverse); 5010b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger inverse.mapVectors(&drawingSize, 1); 5020b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkISize size = SkSize::Make(drawingSize.fX, drawingSize.fY).toRound(); 5030b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger bitmap.setConfig(SkBitmap::kNo_Config, abs(size.fWidth), 5040b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger abs(size.fHeight)); 5050b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } else { 5060b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger bitmap.setConfig(SkBitmap::kNo_Config, abs(contentSize.fWidth), 5070b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger abs(contentSize.fHeight)); 5080b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 5090b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 5100b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger return bitmap; 5110b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger} 5120b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 5130b15698a8c76bb8abc1b555c1d91892669b4118fDerek SollenbergerSkPDFDevice::SkPDFDevice(const SkISize& pageSize, const SkISize& contentSize, 5140b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger const SkMatrix& initialTransform) 5150b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger : SkDevice(NULL, makeContentBitmap(contentSize, &initialTransform), false), 5160b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fPageSize(pageSize), 5170b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fContentSize(contentSize), 5180b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fLastContentEntry(NULL) { 5190b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // Skia generally uses the top left as the origin but PDF natively has the 5200b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // origin at the bottom left. This matrix corrects for that. But that only 5210b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // needs to be done once, we don't do it when layering. 5220b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fInitialTransform.setTranslate(0, pageSize.fHeight); 5230b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fInitialTransform.preScale(1, -1); 5240b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fInitialTransform.preConcat(initialTransform); 5250b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 5260b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkIRect existingClip = SkIRect::MakeWH(this->width(), this->height()); 5270b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fExistingClipStack.clipDevRect(existingClip); 5280b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fExistingClipRegion.setRect(existingClip); 5290b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 5300b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger this->init(); 5310b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger} 5320b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 5330b15698a8c76bb8abc1b555c1d91892669b4118fDerek SollenbergerSkPDFDevice::SkPDFDevice(const SkISize& layerSize, 5340b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger const SkClipStack& existingClipStack, 5350b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger const SkRegion& existingClipRegion) 5360b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger : SkDevice(NULL, makeContentBitmap(layerSize, NULL), false), 5370b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fPageSize(layerSize), 5380b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fContentSize(layerSize), 5390b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fExistingClipStack(existingClipStack), 5400b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fExistingClipRegion(existingClipRegion), 5410b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fLastContentEntry(NULL) { 5420b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fInitialTransform.reset(); 5430b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger this->init(); 5440b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger} 5450b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 5460b15698a8c76bb8abc1b555c1d91892669b4118fDerek SollenbergerSkPDFDevice::~SkPDFDevice() { 5470b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger this->cleanUp(); 5480b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger} 5490b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 5500b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenbergervoid SkPDFDevice::init() { 5510b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fResourceDict = NULL; 5520b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fContentEntries.reset(); 5530b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fLastContentEntry = NULL; 5540b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger} 5550b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 5560b15698a8c76bb8abc1b555c1d91892669b4118fDerek SollenbergerSkDeviceFactory* SkPDFDevice::onNewDeviceFactory() { 5570b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger return SkNEW(SkPDFDeviceFactory); 5580b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger} 5590b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 5600b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenbergervoid SkPDFDevice::cleanUp() { 5610b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fGraphicStateResources.unrefAll(); 5620b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fXObjectResources.unrefAll(); 5630b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fFontResources.unrefAll(); 5640b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fShaderResources.unrefAll(); 5650b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger} 5660b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 5670b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenbergervoid SkPDFDevice::clear(SkColor color) { 5680b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger this->cleanUp(); 5690b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger this->init(); 5700b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 5710b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkPaint paint; 5720b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger paint.setColor(color); 5730b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger paint.setStyle(SkPaint::kFill_Style); 5740b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkMatrix identity; 5750b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger identity.reset(); 5760b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger ScopedContentEntry content(this, &fExistingClipStack, fExistingClipRegion, 5770b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger identity, paint); 5780b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger internalDrawPaint(paint, content.entry()); 5790b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger} 5800b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 5810b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenbergervoid SkPDFDevice::drawPaint(const SkDraw& d, const SkPaint& paint) { 5820b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkPaint newPaint = paint; 5830b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger newPaint.setStyle(SkPaint::kFill_Style); 5840b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger ScopedContentEntry content(this, d, newPaint); 5850b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger internalDrawPaint(newPaint, content.entry()); 5860b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger} 5870b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 5880b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenbergervoid SkPDFDevice::internalDrawPaint(const SkPaint& paint, 5890b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger ContentEntry* contentEntry) { 5900b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (!contentEntry) { 5910b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger return; 5920b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 5930b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkRect bbox = SkRect::MakeWH(SkIntToScalar(this->width()), 5940b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkIntToScalar(this->height())); 5950b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkMatrix totalTransform = fInitialTransform; 5960b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger totalTransform.preConcat(contentEntry->fState.fMatrix); 5970b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkMatrix inverse; 5980b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger inverse.reset(); 5990b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger totalTransform.invert(&inverse); 6000b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger inverse.mapRect(&bbox); 6010b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 6020b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkPDFUtils::AppendRectangle(bbox, &contentEntry->fContent); 6030b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkPDFUtils::PaintPath(paint.getStyle(), SkPath::kWinding_FillType, 6040b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger &contentEntry->fContent); 6050b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger} 6060b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 6070b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenbergervoid SkPDFDevice::drawPoints(const SkDraw& d, SkCanvas::PointMode mode, 6080b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger size_t count, const SkPoint* points, 6090b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger const SkPaint& passedPaint) { 6100b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (count == 0) { 6110b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger return; 6120b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 6130b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 6140b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // SkDraw::drawPoints converts to multiple calls to fDevice->drawPath. 6150b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // We only use this when there's a path effect because of the overhead 6160b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // of multiple calls to setUpContentEntry it causes. 6170b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (passedPaint.getPathEffect()) { 6180b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (d.fClip->isEmpty()) { 6190b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger return; 6200b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 6210b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkDraw pointDraw(d); 6220b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger pointDraw.fDevice = this; 6230b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger pointDraw.drawPoints(mode, count, points, passedPaint, true); 6240b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger return; 6250b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 6260b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 6270b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger const SkPaint* paint = &passedPaint; 6280b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkPaint modifiedPaint; 6290b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 6300b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (mode == SkCanvas::kPoints_PointMode && 6310b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger paint->getStrokeCap() != SkPaint::kRound_Cap) { 6320b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger modifiedPaint = *paint; 6330b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger paint = &modifiedPaint; 6340b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (paint->getStrokeWidth()) { 6350b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // PDF won't draw a single point with square/butt caps because the 6360b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // orientation is ambiguous. Draw a rectangle instead. 6370b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger modifiedPaint.setStyle(SkPaint::kFill_Style); 6380b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkScalar strokeWidth = paint->getStrokeWidth(); 6390b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkScalar halfStroke = SkScalarHalf(strokeWidth); 6400b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger for (size_t i = 0; i < count; i++) { 6410b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkRect r = SkRect::MakeXYWH(points[i].fX, points[i].fY, 0, 0); 6420b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger r.inset(-halfStroke, -halfStroke); 6430b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger drawRect(d, r, modifiedPaint); 6440b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 6450b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger return; 6460b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } else { 6470b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger modifiedPaint.setStrokeCap(SkPaint::kRound_Cap); 6480b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 6490b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 6500b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 6510b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger ScopedContentEntry content(this, d, *paint); 6520b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (!content.entry()) { 6530b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger return; 6540b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 6550b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 6560b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger switch (mode) { 6570b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger case SkCanvas::kPolygon_PointMode: 6580b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkPDFUtils::MoveTo(points[0].fX, points[0].fY, 6590b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger &content.entry()->fContent); 6600b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger for (size_t i = 1; i < count; i++) { 6610b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkPDFUtils::AppendLine(points[i].fX, points[i].fY, 6620b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger &content.entry()->fContent); 6630b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 6640b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkPDFUtils::StrokePath(&content.entry()->fContent); 6650b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger break; 6660b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger case SkCanvas::kLines_PointMode: 6670b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger for (size_t i = 0; i < count/2; i++) { 6680b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkPDFUtils::MoveTo(points[i * 2].fX, points[i * 2].fY, 6690b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger &content.entry()->fContent); 6700b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkPDFUtils::AppendLine(points[i * 2 + 1].fX, 6710b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger points[i * 2 + 1].fY, 6720b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger &content.entry()->fContent); 6730b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkPDFUtils::StrokePath(&content.entry()->fContent); 6740b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 6750b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger break; 6760b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger case SkCanvas::kPoints_PointMode: 6770b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkASSERT(paint->getStrokeCap() == SkPaint::kRound_Cap); 6780b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger for (size_t i = 0; i < count; i++) { 6790b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkPDFUtils::MoveTo(points[i].fX, points[i].fY, 6800b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger &content.entry()->fContent); 6810b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkPDFUtils::ClosePath(&content.entry()->fContent); 6820b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkPDFUtils::StrokePath(&content.entry()->fContent); 6830b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 6840b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger break; 6850b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger default: 6860b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkASSERT(false); 6870b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 6880b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger} 6890b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 6900b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenbergervoid SkPDFDevice::drawRect(const SkDraw& d, const SkRect& r, 6910b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger const SkPaint& paint) { 6920b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (paint.getPathEffect()) { 6930b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (d.fClip->isEmpty()) { 6940b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger return; 6950b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 6960b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkPath path; 6970b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger path.addRect(r); 6980b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger drawPath(d, path, paint, NULL, true); 6990b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger return; 7000b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 7010b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 7020b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger ScopedContentEntry content(this, d, paint); 7030b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (!content.entry()) { 7040b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger return; 7050b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 7060b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkPDFUtils::AppendRectangle(r, &content.entry()->fContent); 7070b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkPDFUtils::PaintPath(paint.getStyle(), SkPath::kWinding_FillType, 7080b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger &content.entry()->fContent); 7090b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger} 7100b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 7110b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenbergervoid SkPDFDevice::drawPath(const SkDraw& d, const SkPath& origPath, 7120b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger const SkPaint& paint, const SkMatrix* prePathMatrix, 7130b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger bool pathIsMutable) { 7140b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkPath modifiedPath; 7150b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkPath* pathPtr = const_cast<SkPath*>(&origPath); 7160b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 7170b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkMatrix matrix = *d.fMatrix; 7180b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (prePathMatrix) { 7190b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (paint.getPathEffect() || paint.getStyle() != SkPaint::kFill_Style) { 7200b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (!pathIsMutable) { 7210b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger pathPtr = &modifiedPath; 7220b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger pathIsMutable = true; 7230b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 7240b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger origPath.transform(*prePathMatrix, pathPtr); 7250b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } else { 7260b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (!matrix.preConcat(*prePathMatrix)) { 7270b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger return; 7280b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 7290b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 7300b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 7310b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 7320b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (paint.getPathEffect()) { 7330b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (d.fClip->isEmpty()) { 7340b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger return; 7350b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 7360b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (!pathIsMutable) { 7370b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger pathPtr = &modifiedPath; 7380b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger pathIsMutable = true; 7390b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 7400b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger bool fill = paint.getFillPath(origPath, pathPtr); 7410b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 7420b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkPaint noEffectPaint(paint); 7430b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger noEffectPaint.setPathEffect(NULL); 7440b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (fill) { 7450b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger noEffectPaint.setStyle(SkPaint::kFill_Style); 7460b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } else { 7470b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger noEffectPaint.setStyle(SkPaint::kStroke_Style); 7480b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger noEffectPaint.setStrokeWidth(0); 7490b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 7500b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger drawPath(d, *pathPtr, noEffectPaint, NULL, true); 7510b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger return; 7520b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 7530b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 7540b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger ScopedContentEntry content(this, d, paint); 7550b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (!content.entry()) { 7560b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger return; 7570b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 7580b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkPDFUtils::EmitPath(*pathPtr, &content.entry()->fContent); 7590b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkPDFUtils::PaintPath(paint.getStyle(), pathPtr->getFillType(), 7600b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger &content.entry()->fContent); 7610b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger} 7620b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 7630b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenbergervoid SkPDFDevice::drawBitmap(const SkDraw& d, const SkBitmap& bitmap, 7640b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger const SkIRect* srcRect, const SkMatrix& matrix, 7650b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger const SkPaint& paint) { 7660b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (d.fClip->isEmpty()) { 7670b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger return; 7680b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 7690b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 7700b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkMatrix transform = matrix; 7710b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger transform.postConcat(*d.fMatrix); 7720b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger internalDrawBitmap(transform, d.fClipStack, *d.fClip, bitmap, srcRect, 7730b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger paint); 7740b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger} 7750b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 7760b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenbergervoid SkPDFDevice::drawSprite(const SkDraw& d, const SkBitmap& bitmap, 7770b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger int x, int y, const SkPaint& paint) { 7780b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (d.fClip->isEmpty()) { 7790b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger return; 7800b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 7810b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 7820b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkMatrix matrix; 7830b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger matrix.setTranslate(SkIntToScalar(x), SkIntToScalar(y)); 7840b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger internalDrawBitmap(matrix, d.fClipStack, *d.fClip, bitmap, NULL, paint); 7850b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger} 7860b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 7870b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenbergervoid SkPDFDevice::drawText(const SkDraw& d, const void* text, size_t len, 7880b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkScalar x, SkScalar y, const SkPaint& paint) { 7890b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkPaint textPaint = calculate_text_paint(paint); 7900b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger ScopedContentEntry content(this, d, textPaint, true); 7910b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (!content.entry()) { 7920b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger return; 7930b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 7940b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 7950b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // We want the text in glyph id encoding and a writable buffer, so we end 7960b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // up making a copy either way. 7970b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger size_t numGlyphs = paint.textToGlyphs(text, len, NULL); 7980b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger uint16_t* glyphIDs = 7990b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger (uint16_t*)sk_malloc_flags(numGlyphs * 2, 8000b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SK_MALLOC_TEMP | SK_MALLOC_THROW); 8010b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkAutoFree autoFreeGlyphIDs(glyphIDs); 8020b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (paint.getTextEncoding() != SkPaint::kGlyphID_TextEncoding) { 8030b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger paint.textToGlyphs(text, len, glyphIDs); 8040b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger textPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); 8050b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } else { 8060b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkASSERT((len & 1) == 0); 8070b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkASSERT(len / 2 == numGlyphs); 8080b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger memcpy(glyphIDs, text, len); 8090b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 8100b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 8110b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkScalar width; 8120b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkScalar* widthPtr = NULL; 8130b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (textPaint.isUnderlineText() || textPaint.isStrikeThruText()) 8140b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger widthPtr = &width; 8150b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 8160b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkDrawCacheProc glyphCacheProc = textPaint.getDrawCacheProc(); 8170b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger align_text(glyphCacheProc, textPaint, glyphIDs, numGlyphs, &x, &y, 8180b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger widthPtr); 8190b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger content.entry()->fContent.writeText("BT\n"); 8200b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger set_text_transform(x, y, textPaint.getTextSkewX(), 8210b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger &content.entry()->fContent); 8220b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger size_t consumedGlyphCount = 0; 8230b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger while (numGlyphs > consumedGlyphCount) { 8240b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger updateFont(textPaint, glyphIDs[consumedGlyphCount], content.entry()); 8250b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkPDFFont* font = content.entry()->fState.fFont; 8260b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger size_t availableGlyphs = 8270b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger font->glyphsToPDFFontEncoding(glyphIDs + consumedGlyphCount, 8280b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger numGlyphs - consumedGlyphCount); 8290b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkString encodedString = 8300b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkPDFString::formatString(glyphIDs + consumedGlyphCount, 8310b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger availableGlyphs, font->multiByteGlyphs()); 8320b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger content.entry()->fContent.writeText(encodedString.c_str()); 8330b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger consumedGlyphCount += availableGlyphs; 8340b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger content.entry()->fContent.writeText(" Tj\n"); 8350b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 8360b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger content.entry()->fContent.writeText("ET\n"); 8370b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 8380b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // Draw underline and/or strikethrough if the paint has them. 8390b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // drawPosText() and drawTextOnPath() don't draw underline or strikethrough 8400b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // because the raster versions don't. Use paint instead of textPaint 8410b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // because we may have changed strokeWidth to do fakeBold text. 8420b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (paint.isUnderlineText() || paint.isStrikeThruText()) { 8430b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkScalar textSize = paint.getTextSize(); 8440b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkScalar height = SkScalarMul(textSize, kStdUnderline_Thickness); 8450b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 8460b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (paint.isUnderlineText()) { 8470b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkScalar top = SkScalarMulAdd(textSize, kStdUnderline_Offset, y); 8480b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkRect r = SkRect::MakeXYWH(x, top - height, width, height); 8490b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger drawRect(d, r, paint); 8500b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 8510b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (paint.isStrikeThruText()) { 8520b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkScalar top = SkScalarMulAdd(textSize, kStdStrikeThru_Offset, y); 8530b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkRect r = SkRect::MakeXYWH(x, top - height, width, height); 8540b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger drawRect(d, r, paint); 8550b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 8560b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 8570b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger} 8580b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 8590b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenbergervoid SkPDFDevice::drawPosText(const SkDraw& d, const void* text, size_t len, 8600b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger const SkScalar pos[], SkScalar constY, 8610b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger int scalarsPerPos, const SkPaint& paint) { 8620b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkASSERT(1 == scalarsPerPos || 2 == scalarsPerPos); 8630b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkPaint textPaint = calculate_text_paint(paint); 8640b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger ScopedContentEntry content(this, d, textPaint, true); 8650b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (!content.entry()) { 8660b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger return; 8670b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 8680b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 8690b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // Make sure we have a glyph id encoding. 8700b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkAutoFree glyphStorage; 8710b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger uint16_t* glyphIDs; 8720b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger size_t numGlyphs; 8730b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (paint.getTextEncoding() != SkPaint::kGlyphID_TextEncoding) { 8740b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger numGlyphs = paint.textToGlyphs(text, len, NULL); 8750b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger glyphIDs = (uint16_t*)sk_malloc_flags(numGlyphs * 2, 8760b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SK_MALLOC_TEMP | SK_MALLOC_THROW); 8770b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger glyphStorage.set(glyphIDs); 8780b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger paint.textToGlyphs(text, len, glyphIDs); 8790b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger textPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); 8800b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } else { 8810b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkASSERT((len & 1) == 0); 8820b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger numGlyphs = len / 2; 8830b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger glyphIDs = (uint16_t*)text; 8840b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 8850b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 8860b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkDrawCacheProc glyphCacheProc = textPaint.getDrawCacheProc(); 8870b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger content.entry()->fContent.writeText("BT\n"); 8880b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger updateFont(textPaint, glyphIDs[0], content.entry()); 8890b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger for (size_t i = 0; i < numGlyphs; i++) { 8900b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkPDFFont* font = content.entry()->fState.fFont; 8910b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger uint16_t encodedValue = glyphIDs[i]; 8920b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (font->glyphsToPDFFontEncoding(&encodedValue, 1) != 1) { 8930b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger updateFont(textPaint, glyphIDs[i], content.entry()); 8940b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger i--; 8950b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger continue; 8960b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 8970b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkScalar x = pos[i * scalarsPerPos]; 8980b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkScalar y = scalarsPerPos == 1 ? constY : pos[i * scalarsPerPos + 1]; 8990b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger align_text(glyphCacheProc, textPaint, glyphIDs + i, 1, &x, &y, NULL); 9000b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger set_text_transform(x, y, textPaint.getTextSkewX(), 9010b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger &content.entry()->fContent); 9020b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkString encodedString = 9030b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkPDFString::formatString(&encodedValue, 1, 9040b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger font->multiByteGlyphs()); 9050b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger content.entry()->fContent.writeText(encodedString.c_str()); 9060b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger content.entry()->fContent.writeText(" Tj\n"); 9070b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 9080b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger content.entry()->fContent.writeText("ET\n"); 9090b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger} 9100b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 9110b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenbergervoid SkPDFDevice::drawTextOnPath(const SkDraw& d, const void* text, size_t len, 9120b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger const SkPath& path, const SkMatrix* matrix, 9130b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger const SkPaint& paint) { 9140b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (d.fClip->isEmpty()) { 9150b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger return; 9160b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 9170b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger NOT_IMPLEMENTED("drawTextOnPath", true); 9180b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger} 9190b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 9200b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenbergervoid SkPDFDevice::drawVertices(const SkDraw& d, SkCanvas::VertexMode, 9210b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger int vertexCount, const SkPoint verts[], 9220b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger const SkPoint texs[], const SkColor colors[], 9230b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkXfermode* xmode, const uint16_t indices[], 9240b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger int indexCount, const SkPaint& paint) { 9250b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (d.fClip->isEmpty()) { 9260b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger return; 9270b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 9280b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger NOT_IMPLEMENTED("drawVerticies", true); 9290b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger} 9300b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 9310b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenbergervoid SkPDFDevice::drawDevice(const SkDraw& d, SkDevice* device, int x, int y, 9320b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger const SkPaint& paint) { 9330b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if ((device->getDeviceCapabilities() & kVector_Capability) == 0) { 9340b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // If we somehow get a raster device, do what our parent would do. 9350b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkDevice::drawDevice(d, device, x, y, paint); 9360b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger return; 9370b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 9380b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 9390b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // Assume that a vector capable device means that it's a PDF Device. 9400b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkPDFDevice* pdfDevice = static_cast<SkPDFDevice*>(device); 9410b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (pdfDevice->isContentEmpty()) { 9420b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger return; 9430b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 9440b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 9450b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkMatrix matrix; 9460b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger matrix.setTranslate(SkIntToScalar(x), SkIntToScalar(y)); 9470b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger ScopedContentEntry content(this, d.fClipStack, *d.fClip, matrix, paint); 9480b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (!content.entry()) { 9490b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger return; 9500b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 9510b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 9520b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkPDFFormXObject* xobject = new SkPDFFormXObject(pdfDevice); 9530b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fXObjectResources.push(xobject); // Transfer reference. 9540b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkPDFUtils::DrawFormXObject(fXObjectResources.count() - 1, 9550b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger &content.entry()->fContent); 9560b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger} 9570b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 9580b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenbergerconst SkRefPtr<SkPDFDict>& SkPDFDevice::getResourceDict() { 9590b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (fResourceDict.get() == NULL) { 9600b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fResourceDict = new SkPDFDict; 9610b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fResourceDict->unref(); // SkRefPtr and new both took a reference. 9620b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 9630b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (fGraphicStateResources.count()) { 9640b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkRefPtr<SkPDFDict> extGState = new SkPDFDict(); 9650b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger extGState->unref(); // SkRefPtr and new both took a reference. 9660b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger for (int i = 0; i < fGraphicStateResources.count(); i++) { 9670b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkString nameString("G"); 9680b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger nameString.appendS32(i); 9690b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger extGState->insert( 9700b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger nameString.c_str(), 9710b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger new SkPDFObjRef(fGraphicStateResources[i]))->unref(); 9720b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 9730b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fResourceDict->insert("ExtGState", extGState.get()); 9740b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 9750b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 9760b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (fXObjectResources.count()) { 9770b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkRefPtr<SkPDFDict> xObjects = new SkPDFDict(); 9780b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger xObjects->unref(); // SkRefPtr and new both took a reference. 9790b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger for (int i = 0; i < fXObjectResources.count(); i++) { 9800b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkString nameString("X"); 9810b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger nameString.appendS32(i); 9820b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger xObjects->insert( 9830b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger nameString.c_str(), 9840b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger new SkPDFObjRef(fXObjectResources[i]))->unref(); 9850b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 9860b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fResourceDict->insert("XObject", xObjects.get()); 9870b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 9880b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 9890b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (fFontResources.count()) { 9900b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkRefPtr<SkPDFDict> fonts = new SkPDFDict(); 9910b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fonts->unref(); // SkRefPtr and new both took a reference. 9920b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger for (int i = 0; i < fFontResources.count(); i++) { 9930b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkString nameString("F"); 9940b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger nameString.appendS32(i); 9950b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fonts->insert(nameString.c_str(), 9960b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger new SkPDFObjRef(fFontResources[i]))->unref(); 9970b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 9980b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fResourceDict->insert("Font", fonts.get()); 9990b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 10000b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 10010b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (fShaderResources.count()) { 10020b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkRefPtr<SkPDFDict> patterns = new SkPDFDict(); 10030b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger patterns->unref(); // SkRefPtr and new both took a reference. 10040b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger for (int i = 0; i < fShaderResources.count(); i++) { 10050b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkString nameString("P"); 10060b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger nameString.appendS32(i); 10070b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger patterns->insert(nameString.c_str(), 10080b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger new SkPDFObjRef(fShaderResources[i]))->unref(); 10090b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 10100b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fResourceDict->insert("Pattern", patterns.get()); 10110b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 10120b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 10130b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // For compatibility, add all proc sets (only used for output to PS 10140b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // devices). 10150b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger const char procs[][7] = {"PDF", "Text", "ImageB", "ImageC", "ImageI"}; 10160b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkRefPtr<SkPDFArray> procSets = new SkPDFArray(); 10170b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger procSets->unref(); // SkRefPtr and new both took a reference. 10180b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger procSets->reserve(SK_ARRAY_COUNT(procs)); 10190b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger for (size_t i = 0; i < SK_ARRAY_COUNT(procs); i++) 10200b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger procSets->append(new SkPDFName(procs[i]))->unref(); 10210b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fResourceDict->insert("ProcSet", procSets.get()); 10220b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 10230b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger return fResourceDict; 10240b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger} 10250b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 10260b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenbergervoid SkPDFDevice::getResources(SkTDArray<SkPDFObject*>* resourceList) const { 10270b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger resourceList->setReserve(resourceList->count() + 10280b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fGraphicStateResources.count() + 10290b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fXObjectResources.count() + 10300b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fFontResources.count() + 10310b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fShaderResources.count()); 10320b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger for (int i = 0; i < fGraphicStateResources.count(); i++) { 10330b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger resourceList->push(fGraphicStateResources[i]); 10340b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fGraphicStateResources[i]->ref(); 10350b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fGraphicStateResources[i]->getResources(resourceList); 10360b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 10370b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger for (int i = 0; i < fXObjectResources.count(); i++) { 10380b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger resourceList->push(fXObjectResources[i]); 10390b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fXObjectResources[i]->ref(); 10400b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fXObjectResources[i]->getResources(resourceList); 10410b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 10420b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger for (int i = 0; i < fFontResources.count(); i++) { 10430b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger resourceList->push(fFontResources[i]); 10440b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fFontResources[i]->ref(); 10450b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fFontResources[i]->getResources(resourceList); 10460b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 10470b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger for (int i = 0; i < fShaderResources.count(); i++) { 10480b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger resourceList->push(fShaderResources[i]); 10490b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fShaderResources[i]->ref(); 10500b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fShaderResources[i]->getResources(resourceList); 10510b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 10520b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger} 10530b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 10540b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenbergerconst SkTDArray<SkPDFFont*>& SkPDFDevice::getFontResources() const { 10550b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger return fFontResources; 10560b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger} 10570b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 10580b15698a8c76bb8abc1b555c1d91892669b4118fDerek SollenbergerSkRefPtr<SkPDFArray> SkPDFDevice::getMediaBox() const { 10590b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkRefPtr<SkPDFInt> zero = new SkPDFInt(0); 10600b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger zero->unref(); // SkRefPtr and new both took a reference. 10610b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 10620b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkRefPtr<SkPDFArray> mediaBox = new SkPDFArray(); 10630b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger mediaBox->unref(); // SkRefPtr and new both took a reference. 10640b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger mediaBox->reserve(4); 10650b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger mediaBox->append(zero.get()); 10660b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger mediaBox->append(zero.get()); 10670b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger mediaBox->append(new SkPDFInt(fPageSize.fWidth))->unref(); 10680b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger mediaBox->append(new SkPDFInt(fPageSize.fHeight))->unref(); 10690b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger return mediaBox; 10700b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger} 10710b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 10720b15698a8c76bb8abc1b555c1d91892669b4118fDerek SollenbergerSkStream* SkPDFDevice::content() const { 10730b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkDynamicMemoryWStream data; 10740b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (fInitialTransform.getType() != SkMatrix::kIdentity_Mask) { 10750b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkPDFUtils::AppendTransform(fInitialTransform, &data); 10760b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 10770b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // If the content area is the entire page, then we don't need to clip 10780b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // the content area (PDF area clips to the page size). Otherwise, 10790b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // we have to clip to the content area; we've already applied the 10800b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // initial transform, so just clip to the device size. 10810b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (fPageSize != fContentSize) { 10820b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkRect r = SkRect::MakeWH(this->width(), this->height()); 10830b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger emit_clip(NULL, &r, &data); 10840b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 10850b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 10860b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger GraphicStackState gsState(fExistingClipStack, fExistingClipRegion, &data); 10870b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger for (ContentEntry* entry = fContentEntries.get(); 10880b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger entry != NULL; 10890b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger entry = entry->fNext.get()) { 10900b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkIPoint translation = this->getOrigin(); 10910b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger translation.negate(); 10920b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger gsState.updateClip(entry->fState.fClipStack, entry->fState.fClipRegion, 10930b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger translation); 10940b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger gsState.updateMatrix(entry->fState.fMatrix); 10950b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger gsState.updateDrawingState(entry->fState); 10960b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger data.write(entry->fContent.getStream(), entry->fContent.getOffset()); 10970b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 10980b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger gsState.drainStack(); 10990b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 11000b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkMemoryStream* result = new SkMemoryStream; 11010b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger result->setMemoryOwned(data.detach(), data.getOffset()); 11020b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger return result; 11030b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger} 11040b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 11050b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenbergervoid SkPDFDevice::createFormXObjectFromDevice( 11060b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkRefPtr<SkPDFFormXObject>* xobject) { 11070b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger *xobject = new SkPDFFormXObject(this); 11080b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger (*xobject)->unref(); // SkRefPtr and new both took a reference. 11090b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger cleanUp(); // Reset this device to have no content. 11100b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger init(); 11110b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger} 11120b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 11130b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenbergervoid SkPDFDevice::clearClipFromContent(const SkClipStack* clipStack, 11140b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger const SkRegion& clipRegion) { 11150b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (clipRegion.isEmpty() || isContentEmpty()) { 11160b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger return; 11170b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 11180b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkRefPtr<SkPDFFormXObject> curContent; 11190b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger createFormXObjectFromDevice(&curContent); 11200b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 11210b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // Redraw what we already had, but with the clip as a mask. 11220b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger drawFormXObjectWithClip(curContent.get(), clipStack, clipRegion, true); 11230b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger} 11240b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 11250b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenbergervoid SkPDFDevice::drawFormXObjectWithClip(SkPDFFormXObject* xobject, 11260b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger const SkClipStack* clipStack, 11270b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger const SkRegion& clipRegion, 11280b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger bool invertClip) { 11290b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (clipRegion.isEmpty() && !invertClip) { 11300b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger return; 11310b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 11320b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 11330b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // Create the mask. 11340b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkMatrix identity; 11350b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger identity.reset(); 11360b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkDraw draw; 11370b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger draw.fMatrix = &identity; 11380b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger draw.fClip = &clipRegion; 11390b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger draw.fClipStack = clipStack; 11400b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkPaint stockPaint; 11410b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger this->drawPaint(draw, stockPaint); 11420b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkRefPtr<SkPDFFormXObject> maskFormXObject; 11430b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger createFormXObjectFromDevice(&maskFormXObject); 11440b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkRefPtr<SkPDFGraphicState> sMaskGS = 11450b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkPDFGraphicState::getSMaskGraphicState(maskFormXObject.get(), 11460b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger invertClip); 11470b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger sMaskGS->unref(); // SkRefPtr and getSMaskGraphicState both took a ref. 11480b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 11490b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // Draw the xobject with the clip as a mask. 11500b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger ScopedContentEntry content(this, &fExistingClipStack, fExistingClipRegion, 11510b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger identity, stockPaint); 11520b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (!content.entry()) { 11530b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger return; 11540b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 11550b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkPDFUtils::ApplyGraphicState(addGraphicStateResource(sMaskGS.get()), 11560b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger &content.entry()->fContent); 11570b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkPDFUtils::DrawFormXObject(fXObjectResources.count(), 11580b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger &content.entry()->fContent); 11590b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fXObjectResources.push(xobject); 11600b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger xobject->ref(); 11610b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 11620b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger sMaskGS = SkPDFGraphicState::getNoSMaskGraphicState(); 11630b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger sMaskGS->unref(); // SkRefPtr and getSMaskGraphicState both took a ref. 11640b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkPDFUtils::ApplyGraphicState(addGraphicStateResource(sMaskGS.get()), 11650b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger &content.entry()->fContent); 11660b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger} 11670b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 11680b15698a8c76bb8abc1b555c1d91892669b4118fDerek SollenbergerContentEntry* SkPDFDevice::setUpContentEntry(const SkClipStack* clipStack, 11690b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger const SkRegion& clipRegion, 11700b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger const SkMatrix& matrix, 11710b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger const SkPaint& paint, 11720b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger bool hasText, 11730b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkRefPtr<SkPDFFormXObject>* dst) { 11740b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (clipRegion.isEmpty()) { 11750b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger return NULL; 11760b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 11770b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 11780b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // The clip stack can come from an SkDraw where it is technically optional. 11790b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkClipStack synthesizedClipStack; 11800b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (clipStack == NULL) { 11810b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (clipRegion == fExistingClipRegion) { 11820b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger clipStack = &fExistingClipStack; 11830b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } else { 11840b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // GraphicStackState::updateClip expects the clip stack to have 11850b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // fExistingClip as a prefix, so start there, then set the clip 11860b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // to the passed region. 11870b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger synthesizedClipStack = fExistingClipStack; 11880b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkPath clipPath; 11890b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger clipRegion.getBoundaryPath(&clipPath); 11900b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger synthesizedClipStack.clipDevPath(clipPath, SkRegion::kReplace_Op); 11910b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger clipStack = &synthesizedClipStack; 11920b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 11930b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 11940b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 11950b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkXfermode::Mode xfermode = SkXfermode::kSrcOver_Mode; 11960b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (paint.getXfermode()) { 11970b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger paint.getXfermode()->asMode(&xfermode); 11980b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 11990b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 12000b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (xfermode == SkXfermode::kClear_Mode || 12010b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger xfermode == SkXfermode::kSrc_Mode) { 12020b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger this->clearClipFromContent(clipStack, clipRegion); 12030b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } else if (xfermode == SkXfermode::kSrcIn_Mode || 12040b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger xfermode == SkXfermode::kDstIn_Mode || 12050b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger xfermode == SkXfermode::kSrcOut_Mode || 12060b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger xfermode == SkXfermode::kDstOut_Mode) { 12070b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // For the following modes, we use both source and destination, but 12080b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // we use one as a smask for the other, so we have to make form xobjects 12090b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // out of both of them: SrcIn, DstIn, SrcOut, DstOut. 12100b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (isContentEmpty()) { 12110b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger return NULL; 12120b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } else { 12130b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger createFormXObjectFromDevice(dst); 12140b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 12150b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 12160b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // TODO(vandebo) Figure out how/if we can handle the following modes: 12170b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // SrcAtop, DestAtop, Xor, Plus. 12180b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 12190b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // These xfer modes don't draw source at all. 12200b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (xfermode == SkXfermode::kClear_Mode || 12210b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger xfermode == SkXfermode::kDst_Mode) { 12220b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger return NULL; 12230b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 12240b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 12250b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger ContentEntry* entry; 12260b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkTScopedPtr<ContentEntry> newEntry; 12270b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (fLastContentEntry && fLastContentEntry->fContent.getOffset() == 0) { 12280b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger entry = fLastContentEntry; 12290b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } else { 12300b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger newEntry.reset(new ContentEntry); 12310b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger entry = newEntry.get(); 12320b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 12330b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 12340b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger populateGraphicStateEntryFromPaint(matrix, *clipStack, clipRegion, paint, 12350b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger hasText, &entry->fState); 12360b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (fLastContentEntry && xfermode != SkXfermode::kDstOver_Mode && 12370b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger entry->fState.compareInitialState(fLastContentEntry->fState)) { 12380b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger return fLastContentEntry; 12390b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 12400b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 12410b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (!fLastContentEntry) { 12420b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fContentEntries.reset(entry); 12430b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fLastContentEntry = entry; 12440b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } else if (xfermode == SkXfermode::kDstOver_Mode) { 12450b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger entry->fNext.reset(fContentEntries.release()); 12460b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fContentEntries.reset(entry); 12470b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } else { 12480b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fLastContentEntry->fNext.reset(entry); 12490b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fLastContentEntry = entry; 12500b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 12510b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger newEntry.release(); 12520b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger return entry; 12530b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger} 12540b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 12550b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenbergervoid SkPDFDevice::finishContentEntry(const SkXfermode::Mode xfermode, 12560b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkPDFFormXObject* dst) { 12570b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (xfermode != SkXfermode::kSrcIn_Mode && 12580b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger xfermode != SkXfermode::kDstIn_Mode && 12590b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger xfermode != SkXfermode::kSrcOut_Mode && 12600b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger xfermode != SkXfermode::kDstOut_Mode) { 12610b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkASSERT(!dst); 12620b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger return; 12630b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 12640b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkASSERT(dst); 12650b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkASSERT(!fContentEntries->fNext.get()); 12660b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 12670b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // We have to make a copy of these here because changing the current 12680b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // content into a form xobject will destroy them. 12690b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkClipStack clipStack = fContentEntries->fState.fClipStack; 12700b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkRegion clipRegion = fContentEntries->fState.fClipRegion; 12710b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 12720b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkRefPtr<SkPDFFormXObject> srcFormXObject; 12730b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (!isContentEmpty()) { 12740b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger createFormXObjectFromDevice(&srcFormXObject); 12750b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 12760b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 12770b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger drawFormXObjectWithClip(dst, &clipStack, clipRegion, true); 12780b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 12790b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // We've redrawn dst minus the clip area, if there's no src, we're done. 12800b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (!srcFormXObject.get()) { 12810b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger return; 12820b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 12830b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 12840b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkMatrix identity; 12850b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger identity.reset(); 12860b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkPaint stockPaint; 12870b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger ScopedContentEntry inClipContentEntry(this, &fExistingClipStack, 12880b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fExistingClipRegion, identity, 12890b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger stockPaint); 12900b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (!inClipContentEntry.entry()) { 12910b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger return; 12920b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 12930b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 12940b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkRefPtr<SkPDFGraphicState> sMaskGS; 12950b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (xfermode == SkXfermode::kSrcIn_Mode || 12960b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger xfermode == SkXfermode::kSrcOut_Mode) { 12970b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger sMaskGS = SkPDFGraphicState::getSMaskGraphicState( 12980b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger dst, xfermode == SkXfermode::kSrcOut_Mode); 12990b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fXObjectResources.push(srcFormXObject.get()); 13000b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger srcFormXObject->ref(); 13010b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } else { 13020b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger sMaskGS = SkPDFGraphicState::getSMaskGraphicState( 13030b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger srcFormXObject.get(), xfermode == SkXfermode::kDstOut_Mode); 13040b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // dst already added to fXObjectResources in drawFormXObjectWithClip. 13050b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 13060b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger sMaskGS->unref(); // SkRefPtr and getSMaskGraphicState both took a ref. 13070b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkPDFUtils::ApplyGraphicState(addGraphicStateResource(sMaskGS.get()), 13080b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger &inClipContentEntry.entry()->fContent); 13090b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 13100b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkPDFUtils::DrawFormXObject(fXObjectResources.count() - 1, 13110b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger &inClipContentEntry.entry()->fContent); 13120b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 13130b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger sMaskGS = SkPDFGraphicState::getNoSMaskGraphicState(); 13140b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger sMaskGS->unref(); // SkRefPtr and getSMaskGraphicState both took a ref. 13150b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkPDFUtils::ApplyGraphicState(addGraphicStateResource(sMaskGS.get()), 13160b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger &inClipContentEntry.entry()->fContent); 13170b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger} 13180b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 13190b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenbergerbool SkPDFDevice::isContentEmpty() { 13200b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (!fContentEntries.get() || fContentEntries->fContent.getOffset() == 0) { 13210b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkASSERT(!fContentEntries.get() || !fContentEntries->fNext.get()); 13220b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger return true; 13230b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 13240b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger return false; 13250b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger} 13260b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 13270b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 13280b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenbergervoid SkPDFDevice::populateGraphicStateEntryFromPaint( 13290b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger const SkMatrix& matrix, 13300b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger const SkClipStack& clipStack, 13310b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger const SkRegion& clipRegion, 13320b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger const SkPaint& paint, 13330b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger bool hasText, 13340b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger GraphicStateEntry* entry) { 13350b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkASSERT(paint.getPathEffect() == NULL); 13360b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 13370b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger NOT_IMPLEMENTED(paint.getMaskFilter() != NULL, false); 13380b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger NOT_IMPLEMENTED(paint.getColorFilter() != NULL, false); 13390b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 13400b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger entry->fMatrix = matrix; 13410b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger entry->fClipStack = clipStack; 13420b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger entry->fClipRegion = clipRegion; 13430b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 13440b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // PDF treats a shader as a color, so we only set one or the other. 13450b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkRefPtr<SkPDFShader> pdfShader; 13460b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger const SkShader* shader = paint.getShader(); 13470b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkColor color = paint.getColor(); 13480b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (shader) { 13490b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // PDF positions patterns relative to the initial transform, so 13500b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // we need to apply the current transform to the shader parameters. 13510b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkMatrix transform = matrix; 13520b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger transform.postConcat(fInitialTransform); 13530b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 13540b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // PDF doesn't support kClamp_TileMode, so we simulate it by making 13550b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // a pattern the size of the current clip. 13560b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkIRect bounds = clipRegion.getBounds(); 13570b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger pdfShader = SkPDFShader::getPDFShader(*shader, transform, bounds); 13580b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkSafeUnref(pdfShader.get()); // getShader and SkRefPtr both took a ref 13590b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 13600b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // A color shader is treated as an invalid shader so we don't have 13610b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // to set a shader just for a color. 13620b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (pdfShader.get() == NULL) { 13630b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger entry->fColor = 0; 13640b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger color = 0; 13650b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 13660b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // Check for a color shader. 13670b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkShader::GradientInfo gradientInfo; 13680b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkColor gradientColor; 13690b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger gradientInfo.fColors = &gradientColor; 13700b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger gradientInfo.fColorOffsets = NULL; 13710b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger gradientInfo.fColorCount = 1; 13720b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (shader->asAGradient(&gradientInfo) == 13730b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkShader::kColor_GradientType) { 13740b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger entry->fColor = SkColorSetA(gradientColor, 0xFF); 13750b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger color = gradientColor; 13760b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 13770b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 13780b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 13790b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 13800b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (pdfShader) { 13810b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // pdfShader has been canonicalized so we can directly compare 13820b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // pointers. 13830b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger int resourceIndex = fShaderResources.find(pdfShader.get()); 13840b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (resourceIndex < 0) { 13850b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger resourceIndex = fShaderResources.count(); 13860b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fShaderResources.push(pdfShader.get()); 13870b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger pdfShader->ref(); 13880b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 13890b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger entry->fShaderIndex = resourceIndex; 13900b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } else { 13910b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger entry->fShaderIndex = -1; 13920b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger entry->fColor = SkColorSetA(paint.getColor(), 0xFF); 13930b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger color = paint.getColor(); 13940b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 13950b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 13960b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkRefPtr<SkPDFGraphicState> newGraphicState; 13970b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (color == paint.getColor()) { 13980b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger newGraphicState = SkPDFGraphicState::getGraphicStateForPaint(paint); 13990b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } else { 14000b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkPaint newPaint = paint; 14010b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger newPaint.setColor(color); 14020b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger newGraphicState = SkPDFGraphicState::getGraphicStateForPaint(newPaint); 14030b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 14040b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger newGraphicState->unref(); // getGraphicState and SkRefPtr both took a ref. 14050b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger int resourceIndex = addGraphicStateResource(newGraphicState.get()); 14060b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger entry->fGraphicStateIndex = resourceIndex; 14070b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 14080b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (hasText) { 14090b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger entry->fTextScaleX = paint.getTextScaleX(); 14100b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger entry->fTextFill = paint.getStyle(); 14110b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } else { 14120b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger entry->fTextScaleX = 0; 14130b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 14140b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger} 14150b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 14160b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenbergerint SkPDFDevice::addGraphicStateResource(SkPDFGraphicState* gs) { 14170b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // Assumes that gs has been canonicalized (so we can directly compare 14180b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // pointers). 14190b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger int result = fGraphicStateResources.find(gs); 14200b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (result < 0) { 14210b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger result = fGraphicStateResources.count(); 14220b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fGraphicStateResources.push(gs); 14230b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger gs->ref(); 14240b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 14250b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger return result; 14260b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger} 14270b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 14280b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenbergervoid SkPDFDevice::updateFont(const SkPaint& paint, uint16_t glyphID, 14290b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger ContentEntry* contentEntry) { 14300b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkTypeface* typeface = paint.getTypeface(); 14310b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (contentEntry->fState.fFont == NULL || 14320b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger contentEntry->fState.fTextSize != paint.getTextSize() || 14330b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger !contentEntry->fState.fFont->hasGlyph(glyphID)) { 14340b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger int fontIndex = getFontResourceIndex(typeface, glyphID); 14350b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger contentEntry->fContent.writeText("/F"); 14360b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger contentEntry->fContent.writeDecAsText(fontIndex); 14370b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger contentEntry->fContent.writeText(" "); 14380b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkPDFScalar::Append(paint.getTextSize(), &contentEntry->fContent); 14390b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger contentEntry->fContent.writeText(" Tf\n"); 14400b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger contentEntry->fState.fFont = fFontResources[fontIndex]; 14410b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 14420b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger} 14430b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 14440b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenbergerint SkPDFDevice::getFontResourceIndex(SkTypeface* typeface, uint16_t glyphID) { 14450b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkRefPtr<SkPDFFont> newFont = SkPDFFont::getFontResource(typeface, glyphID); 14460b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger newFont->unref(); // getFontResource and SkRefPtr both took a ref. 14470b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger int resourceIndex = fFontResources.find(newFont.get()); 14480b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (resourceIndex < 0) { 14490b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger resourceIndex = fFontResources.count(); 14500b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fFontResources.push(newFont.get()); 14510b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger newFont->ref(); 14520b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 14530b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger return resourceIndex; 14540b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger} 14550b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 14560b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenbergervoid SkPDFDevice::internalDrawBitmap(const SkMatrix& matrix, 14570b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger const SkClipStack* clipStack, 14580b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger const SkRegion& clipRegion, 14590b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger const SkBitmap& bitmap, 14600b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger const SkIRect* srcRect, 14610b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger const SkPaint& paint) { 14620b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkMatrix scaled; 14630b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // Adjust for origin flip. 14640b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger scaled.setScale(1, -1); 14650b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger scaled.postTranslate(0, 1); 14660b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // Scale the image up from 1x1 to WxH. 14670b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkIRect subset = SkIRect::MakeWH(bitmap.width(), bitmap.height()); 14680b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger scaled.postScale(SkIntToScalar(subset.width()), 14690b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkIntToScalar(subset.height())); 14700b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger scaled.postConcat(matrix); 14710b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger ScopedContentEntry content(this, clipStack, clipRegion, scaled, paint); 14720b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (!content.entry()) { 14730b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger return; 14740b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 14750b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 14760b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (srcRect && !subset.intersect(*srcRect)) { 14770b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger return; 14780b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 14790b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 14800b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkPDFImage* image = SkPDFImage::CreateImage(bitmap, subset, paint); 14810b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (!image) { 14820b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger return; 14830b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 14840b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 14850b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fXObjectResources.push(image); // Transfer reference. 14860b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkPDFUtils::DrawFormXObject(fXObjectResources.count() - 1, 14870b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger &content.entry()->fContent); 14880b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger} 1489