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