Home | History | Annotate | Download | only in pdf
      1 
      2 /*
      3  * Copyright 2011 Google Inc.
      4  *
      5  * Use of this source code is governed by a BSD-style license that can be
      6  * found in the LICENSE file.
      7  */
      8 
      9 
     10 #include "SkPDFDevice.h"
     11 
     12 #include "SkColor.h"
     13 #include "SkClipStack.h"
     14 #include "SkData.h"
     15 #include "SkDraw.h"
     16 #include "SkGlyphCache.h"
     17 #include "SkPaint.h"
     18 #include "SkPath.h"
     19 #include "SkPDFFont.h"
     20 #include "SkPDFFormXObject.h"
     21 #include "SkPDFGraphicState.h"
     22 #include "SkPDFImage.h"
     23 #include "SkPDFShader.h"
     24 #include "SkPDFStream.h"
     25 #include "SkPDFTypes.h"
     26 #include "SkPDFUtils.h"
     27 #include "SkRect.h"
     28 #include "SkString.h"
     29 #include "SkTextFormatParams.h"
     30 #include "SkTypeface.h"
     31 #include "SkTypes.h"
     32 
     33 // Utility functions
     34 
     35 static void emit_pdf_color(SkColor color, SkWStream* result) {
     36     SkASSERT(SkColorGetA(color) == 0xFF);  // We handle alpha elsewhere.
     37     SkScalar colorMax = SkIntToScalar(0xFF);
     38     SkPDFScalar::Append(
     39             SkScalarDiv(SkIntToScalar(SkColorGetR(color)), colorMax), result);
     40     result->writeText(" ");
     41     SkPDFScalar::Append(
     42             SkScalarDiv(SkIntToScalar(SkColorGetG(color)), colorMax), result);
     43     result->writeText(" ");
     44     SkPDFScalar::Append(
     45             SkScalarDiv(SkIntToScalar(SkColorGetB(color)), colorMax), result);
     46     result->writeText(" ");
     47 }
     48 
     49 static SkPaint calculate_text_paint(const SkPaint& paint) {
     50     SkPaint result = paint;
     51     if (result.isFakeBoldText()) {
     52         SkScalar fakeBoldScale = SkScalarInterpFunc(result.getTextSize(),
     53                                                     kStdFakeBoldInterpKeys,
     54                                                     kStdFakeBoldInterpValues,
     55                                                     kStdFakeBoldInterpLength);
     56         SkScalar width = SkScalarMul(result.getTextSize(), fakeBoldScale);
     57         if (result.getStyle() == SkPaint::kFill_Style) {
     58             result.setStyle(SkPaint::kStrokeAndFill_Style);
     59         } else {
     60             width += result.getStrokeWidth();
     61         }
     62         result.setStrokeWidth(width);
     63     }
     64     return result;
     65 }
     66 
     67 // Stolen from measure_text in SkDraw.cpp and then tweaked.
     68 static void align_text(SkDrawCacheProc glyphCacheProc, const SkPaint& paint,
     69                        const uint16_t* glyphs, size_t len,
     70                        SkScalar* x, SkScalar* y) {
     71     if (paint.getTextAlign() == SkPaint::kLeft_Align) {
     72         return;
     73     }
     74 
     75     SkMatrix ident;
     76     ident.reset();
     77     SkAutoGlyphCache autoCache(paint, &ident);
     78     SkGlyphCache* cache = autoCache.getCache();
     79 
     80     const char* start = reinterpret_cast<const char*>(glyphs);
     81     const char* stop = reinterpret_cast<const char*>(glyphs + len);
     82     SkFixed xAdv = 0, yAdv = 0;
     83 
     84     // TODO(vandebo): This probably needs to take kerning into account.
     85     while (start < stop) {
     86         const SkGlyph& glyph = glyphCacheProc(cache, &start, 0, 0);
     87         xAdv += glyph.fAdvanceX;
     88         yAdv += glyph.fAdvanceY;
     89     };
     90     if (paint.getTextAlign() == SkPaint::kLeft_Align) {
     91         return;
     92     }
     93 
     94     SkScalar xAdj = SkFixedToScalar(xAdv);
     95     SkScalar yAdj = SkFixedToScalar(yAdv);
     96     if (paint.getTextAlign() == SkPaint::kCenter_Align) {
     97         xAdj = SkScalarHalf(xAdj);
     98         yAdj = SkScalarHalf(yAdj);
     99     }
    100     *x = *x - xAdj;
    101     *y = *y - yAdj;
    102 }
    103 
    104 static void set_text_transform(SkScalar x, SkScalar y, SkScalar textSkewX,
    105                                SkWStream* content) {
    106     // Flip the text about the x-axis to account for origin swap and include
    107     // the passed parameters.
    108     content->writeText("1 0 ");
    109     SkPDFScalar::Append(0 - textSkewX, content);
    110     content->writeText(" -1 ");
    111     SkPDFScalar::Append(x, content);
    112     content->writeText(" ");
    113     SkPDFScalar::Append(y, content);
    114     content->writeText(" Tm\n");
    115 }
    116 
    117 // It is important to not confuse GraphicStateEntry with SkPDFGraphicState, the
    118 // later being our representation of an object in the PDF file.
    119 struct GraphicStateEntry {
    120     GraphicStateEntry();
    121 
    122     // Compare the fields we care about when setting up a new content entry.
    123     bool compareInitialState(const GraphicStateEntry& b);
    124 
    125     SkMatrix fMatrix;
    126     // We can't do set operations on Paths, though PDF natively supports
    127     // intersect.  If the clip stack does anything other than intersect,
    128     // we have to fall back to the region.  Treat fClipStack as authoritative.
    129     // See http://code.google.com/p/skia/issues/detail?id=221
    130     SkClipStack fClipStack;
    131     SkRegion fClipRegion;
    132 
    133     // When emitting the content entry, we will ensure the graphic state
    134     // is set to these values first.
    135     SkColor fColor;
    136     SkScalar fTextScaleX;  // Zero means we don't care what the value is.
    137     SkPaint::Style fTextFill;  // Only if TextScaleX is non-zero.
    138     int fShaderIndex;
    139     int fGraphicStateIndex;
    140 
    141     // We may change the font (i.e. for Type1 support) within a
    142     // ContentEntry.  This is the one currently in effect, or NULL if none.
    143     SkPDFFont* fFont;
    144     // In PDF, text size has no default value. It is only valid if fFont is
    145     // not NULL.
    146     SkScalar fTextSize;
    147 };
    148 
    149 GraphicStateEntry::GraphicStateEntry() : fColor(SK_ColorBLACK),
    150                                          fTextScaleX(SK_Scalar1),
    151                                          fTextFill(SkPaint::kFill_Style),
    152                                          fShaderIndex(-1),
    153                                          fGraphicStateIndex(-1),
    154                                          fFont(NULL),
    155                                          fTextSize(SK_ScalarNaN) {
    156     fMatrix.reset();
    157 }
    158 
    159 bool GraphicStateEntry::compareInitialState(const GraphicStateEntry& b) {
    160     return fColor == b.fColor &&
    161            fShaderIndex == b.fShaderIndex &&
    162            fGraphicStateIndex == b.fGraphicStateIndex &&
    163            fMatrix == b.fMatrix &&
    164            fClipStack == b.fClipStack &&
    165                (fTextScaleX == 0 ||
    166                 b.fTextScaleX == 0 ||
    167                 (fTextScaleX == b.fTextScaleX && fTextFill == b.fTextFill));
    168 }
    169 
    170 class GraphicStackState {
    171 public:
    172     GraphicStackState(const SkClipStack& existingClipStack,
    173                       const SkRegion& existingClipRegion,
    174                       SkWStream* contentStream)
    175             : fStackDepth(0),
    176               fContentStream(contentStream) {
    177         fEntries[0].fClipStack = existingClipStack;
    178         fEntries[0].fClipRegion = existingClipRegion;
    179     }
    180 
    181     void updateClip(const SkClipStack& clipStack, const SkRegion& clipRegion,
    182                     const SkPoint& translation);
    183     void updateMatrix(const SkMatrix& matrix);
    184     void updateDrawingState(const GraphicStateEntry& state);
    185 
    186     void drainStack();
    187 
    188 private:
    189     void push();
    190     void pop();
    191     GraphicStateEntry* currentEntry() { return &fEntries[fStackDepth]; }
    192 
    193     // Conservative limit on save depth, see impl. notes in PDF 1.4 spec.
    194     static const int kMaxStackDepth = 12;
    195     GraphicStateEntry fEntries[kMaxStackDepth + 1];
    196     int fStackDepth;
    197     SkWStream* fContentStream;
    198 };
    199 
    200 void GraphicStackState::drainStack() {
    201     while (fStackDepth) {
    202         pop();
    203     }
    204 }
    205 
    206 void GraphicStackState::push() {
    207     SkASSERT(fStackDepth < kMaxStackDepth);
    208     fContentStream->writeText("q\n");
    209     fStackDepth++;
    210     fEntries[fStackDepth] = fEntries[fStackDepth - 1];
    211 }
    212 
    213 void GraphicStackState::pop() {
    214     SkASSERT(fStackDepth > 0);
    215     fContentStream->writeText("Q\n");
    216     fStackDepth--;
    217 }
    218 
    219 // This function initializes iter to be an interator on the "stack" argument
    220 // and then skips over the leading entries as specified in prefix.  It requires
    221 // and asserts that "prefix" will be a prefix to "stack."
    222 static void skip_clip_stack_prefix(const SkClipStack& prefix,
    223                                    const SkClipStack& stack,
    224                                    SkClipStack::B2FIter* iter) {
    225     SkClipStack::B2FIter prefixIter(prefix);
    226     iter->reset(stack);
    227 
    228     const SkClipStack::B2FIter::Clip* prefixEntry;
    229     const SkClipStack::B2FIter::Clip* iterEntry;
    230 
    231     int count = 0;
    232     for (prefixEntry = prefixIter.next(); prefixEntry;
    233             prefixEntry = prefixIter.next(), count++) {
    234         iterEntry = iter->next();
    235         SkASSERT(iterEntry);
    236         // Because of SkClipStack does internal intersection, the last clip
    237         // entry may differ.
    238         if (*prefixEntry != *iterEntry) {
    239             SkASSERT(prefixEntry->fOp == SkRegion::kIntersect_Op);
    240             SkASSERT(iterEntry->fOp == SkRegion::kIntersect_Op);
    241             SkASSERT((iterEntry->fRect == NULL) ==
    242                     (prefixEntry->fRect == NULL));
    243             SkASSERT((iterEntry->fPath == NULL) ==
    244                     (prefixEntry->fPath == NULL));
    245             // We need to back up the iterator by one but don't have that
    246             // function, so reset and go forward by one less.
    247             iter->reset(stack);
    248             for (int i = 0; i < count; i++) {
    249                 iter->next();
    250             }
    251             prefixEntry = prefixIter.next();
    252             break;
    253         }
    254     }
    255 
    256     SkASSERT(prefixEntry == NULL);
    257 }
    258 
    259 static void emit_clip(SkPath* clipPath, SkRect* clipRect,
    260                       SkWStream* contentStream) {
    261     SkASSERT(clipPath || clipRect);
    262 
    263     SkPath::FillType clipFill;
    264     if (clipPath) {
    265         SkPDFUtils::EmitPath(*clipPath, contentStream);
    266         clipFill = clipPath->getFillType();
    267     } else {
    268         SkPDFUtils::AppendRectangle(*clipRect, contentStream);
    269         clipFill = SkPath::kWinding_FillType;
    270     }
    271 
    272     NOT_IMPLEMENTED(clipFill == SkPath::kInverseEvenOdd_FillType, false);
    273     NOT_IMPLEMENTED(clipFill == SkPath::kInverseWinding_FillType, false);
    274     if (clipFill == SkPath::kEvenOdd_FillType) {
    275         contentStream->writeText("W* n\n");
    276     } else {
    277         contentStream->writeText("W n\n");
    278     }
    279 }
    280 
    281 // TODO(vandebo): Take advantage of SkClipStack::getSaveCount(), the PDF
    282 // graphic state stack, and the fact that we can know all the clips used
    283 // on the page to optimize this.
    284 void GraphicStackState::updateClip(const SkClipStack& clipStack,
    285                                    const SkRegion& clipRegion,
    286                                    const SkPoint& translation) {
    287     if (clipStack == currentEntry()->fClipStack) {
    288         return;
    289     }
    290 
    291     while (fStackDepth > 0) {
    292         pop();
    293         if (clipStack == currentEntry()->fClipStack) {
    294             return;
    295         }
    296     }
    297     push();
    298 
    299     // gsState->initialEntry()->fClipStack/Region specifies the clip that has
    300     // already been applied.  (If this is a top level device, then it specifies
    301     // a clip to the content area.  If this is a layer, then it specifies
    302     // the clip in effect when the layer was created.)  There's no need to
    303     // reapply that clip; SKCanvas's SkDrawIter will draw anything outside the
    304     // initial clip on the parent layer.  (This means there's a bug if the user
    305     // expands the clip and then uses any xfer mode that uses dst:
    306     // http://code.google.com/p/skia/issues/detail?id=228 )
    307     SkClipStack::B2FIter iter;
    308     skip_clip_stack_prefix(fEntries[0].fClipStack, clipStack, &iter);
    309 
    310     // If the clip stack does anything other than intersect or if it uses
    311     // an inverse fill type, we have to fall back to the clip region.
    312     bool needRegion = false;
    313     const SkClipStack::B2FIter::Clip* clipEntry;
    314     for (clipEntry = iter.next(); clipEntry; clipEntry = iter.next()) {
    315         if (clipEntry->fOp != SkRegion::kIntersect_Op ||
    316                 (clipEntry->fPath && clipEntry->fPath->isInverseFillType())) {
    317             needRegion = true;
    318             break;
    319         }
    320     }
    321 
    322     if (needRegion) {
    323         SkPath clipPath;
    324         SkAssertResult(clipRegion.getBoundaryPath(&clipPath));
    325         emit_clip(&clipPath, NULL, fContentStream);
    326     } else {
    327         skip_clip_stack_prefix(fEntries[0].fClipStack, clipStack, &iter);
    328         SkMatrix transform;
    329         transform.setTranslate(translation.fX, translation.fY);
    330         const SkClipStack::B2FIter::Clip* clipEntry;
    331         for (clipEntry = iter.next(); clipEntry; clipEntry = iter.next()) {
    332             SkASSERT(clipEntry->fOp == SkRegion::kIntersect_Op);
    333             if (clipEntry->fRect) {
    334                 SkRect translatedClip;
    335                 transform.mapRect(&translatedClip, *clipEntry->fRect);
    336                 emit_clip(NULL, &translatedClip, fContentStream);
    337             } else if (clipEntry->fPath) {
    338                 SkPath translatedPath;
    339                 clipEntry->fPath->transform(transform, &translatedPath);
    340                 emit_clip(&translatedPath, NULL, fContentStream);
    341             } else {
    342                 SkASSERT(false);
    343             }
    344         }
    345     }
    346     currentEntry()->fClipStack = clipStack;
    347     currentEntry()->fClipRegion = clipRegion;
    348 }
    349 
    350 void GraphicStackState::updateMatrix(const SkMatrix& matrix) {
    351     if (matrix == currentEntry()->fMatrix) {
    352         return;
    353     }
    354 
    355     if (currentEntry()->fMatrix.getType() != SkMatrix::kIdentity_Mask) {
    356         SkASSERT(fStackDepth > 0);
    357         SkASSERT(fEntries[fStackDepth].fClipStack ==
    358                  fEntries[fStackDepth -1].fClipStack);
    359         pop();
    360 
    361         SkASSERT(currentEntry()->fMatrix.getType() == SkMatrix::kIdentity_Mask);
    362     }
    363     if (matrix.getType() == SkMatrix::kIdentity_Mask) {
    364         return;
    365     }
    366 
    367     push();
    368     SkPDFUtils::AppendTransform(matrix, fContentStream);
    369     currentEntry()->fMatrix = matrix;
    370 }
    371 
    372 void GraphicStackState::updateDrawingState(const GraphicStateEntry& state) {
    373     // PDF treats a shader as a color, so we only set one or the other.
    374     if (state.fShaderIndex >= 0) {
    375         if (state.fShaderIndex != currentEntry()->fShaderIndex) {
    376             fContentStream->writeText("/Pattern CS /Pattern cs /P");
    377             fContentStream->writeDecAsText(state.fShaderIndex);
    378             fContentStream->writeText(" SCN /P");
    379             fContentStream->writeDecAsText(state.fShaderIndex);
    380             fContentStream->writeText(" scn\n");
    381             currentEntry()->fShaderIndex = state.fShaderIndex;
    382         }
    383     } else {
    384         if (state.fColor != currentEntry()->fColor ||
    385                 currentEntry()->fShaderIndex >= 0) {
    386             emit_pdf_color(state.fColor, fContentStream);
    387             fContentStream->writeText("RG ");
    388             emit_pdf_color(state.fColor, fContentStream);
    389             fContentStream->writeText("rg\n");
    390             currentEntry()->fColor = state.fColor;
    391             currentEntry()->fShaderIndex = -1;
    392         }
    393     }
    394 
    395     if (state.fGraphicStateIndex != currentEntry()->fGraphicStateIndex) {
    396         SkPDFUtils::ApplyGraphicState(state.fGraphicStateIndex, fContentStream);
    397         currentEntry()->fGraphicStateIndex = state.fGraphicStateIndex;
    398     }
    399 
    400     if (state.fTextScaleX) {
    401         if (state.fTextScaleX != currentEntry()->fTextScaleX) {
    402             SkScalar pdfScale = SkScalarMul(state.fTextScaleX,
    403                                             SkIntToScalar(100));
    404             SkPDFScalar::Append(pdfScale, fContentStream);
    405             fContentStream->writeText(" Tz\n");
    406             currentEntry()->fTextScaleX = state.fTextScaleX;
    407         }
    408         if (state.fTextFill != currentEntry()->fTextFill) {
    409             SK_COMPILE_ASSERT(SkPaint::kFill_Style == 0, enum_must_match_value);
    410             SK_COMPILE_ASSERT(SkPaint::kStroke_Style == 1,
    411                               enum_must_match_value);
    412             SK_COMPILE_ASSERT(SkPaint::kStrokeAndFill_Style == 2,
    413                               enum_must_match_value);
    414             fContentStream->writeDecAsText(state.fTextFill);
    415             fContentStream->writeText(" Tr\n");
    416             currentEntry()->fTextFill = state.fTextFill;
    417         }
    418     }
    419 }
    420 
    421 SkDevice* SkPDFDevice::onCreateCompatibleDevice(SkBitmap::Config config,
    422                                                 int width, int height,
    423                                                 bool isOpaque,
    424                                                 Usage usage) {
    425     SkMatrix initialTransform;
    426     initialTransform.reset();
    427     SkISize size = SkISize::Make(width, height);
    428     return SkNEW_ARGS(SkPDFDevice, (size, size, initialTransform));
    429 }
    430 
    431 
    432 struct ContentEntry {
    433     GraphicStateEntry fState;
    434     SkDynamicMemoryWStream fContent;
    435     SkTScopedPtr<ContentEntry> fNext;
    436 };
    437 
    438 // A helper class to automatically finish a ContentEntry at the end of a
    439 // drawing method and maintain the state needed between set up and finish.
    440 class ScopedContentEntry {
    441 public:
    442     ScopedContentEntry(SkPDFDevice* device, const SkDraw& draw,
    443                        const SkPaint& paint, bool hasText = false)
    444         : fDevice(device),
    445           fContentEntry(NULL),
    446           fXfermode(SkXfermode::kSrcOver_Mode) {
    447         init(draw.fClipStack, *draw.fClip, *draw.fMatrix, paint, hasText);
    448     }
    449     ScopedContentEntry(SkPDFDevice* device, const SkClipStack* clipStack,
    450                        const SkRegion& clipRegion, const SkMatrix& matrix,
    451                        const SkPaint& paint, bool hasText = false)
    452         : fDevice(device),
    453           fContentEntry(NULL),
    454           fXfermode(SkXfermode::kSrcOver_Mode) {
    455         init(clipStack, clipRegion, matrix, paint, hasText);
    456     }
    457 
    458     ~ScopedContentEntry() {
    459         if (fContentEntry) {
    460             fDevice->finishContentEntry(fXfermode, fDstFormXObject.get());
    461         }
    462     }
    463 
    464     ContentEntry* entry() { return fContentEntry; }
    465 private:
    466     SkPDFDevice* fDevice;
    467     ContentEntry* fContentEntry;
    468     SkXfermode::Mode fXfermode;
    469     SkRefPtr<SkPDFFormXObject> fDstFormXObject;
    470 
    471     void init(const SkClipStack* clipStack, const SkRegion& clipRegion,
    472               const SkMatrix& matrix, const SkPaint& paint, bool hasText) {
    473         if (paint.getXfermode()) {
    474             paint.getXfermode()->asMode(&fXfermode);
    475         }
    476         fContentEntry = fDevice->setUpContentEntry(clipStack, clipRegion,
    477                                                    matrix, paint, hasText,
    478                                                    &fDstFormXObject);
    479     }
    480 };
    481 
    482 ////////////////////////////////////////////////////////////////////////////////
    483 
    484 static inline SkBitmap makeContentBitmap(const SkISize& contentSize,
    485                                          const SkMatrix* initialTransform) {
    486     SkBitmap bitmap;
    487     if (initialTransform) {
    488         // Compute the size of the drawing area.
    489         SkVector drawingSize;
    490         SkMatrix inverse;
    491         drawingSize.set(SkIntToScalar(contentSize.fWidth),
    492                         SkIntToScalar(contentSize.fHeight));
    493         initialTransform->invert(&inverse);
    494         inverse.mapVectors(&drawingSize, 1);
    495         SkISize size = SkSize::Make(drawingSize.fX, drawingSize.fY).toRound();
    496         bitmap.setConfig(SkBitmap::kNo_Config, abs(size.fWidth),
    497                          abs(size.fHeight));
    498     } else {
    499         bitmap.setConfig(SkBitmap::kNo_Config, abs(contentSize.fWidth),
    500                          abs(contentSize.fHeight));
    501     }
    502 
    503     return bitmap;
    504 }
    505 
    506 // TODO(vandebo) change pageSize to SkSize.
    507 SkPDFDevice::SkPDFDevice(const SkISize& pageSize, const SkISize& contentSize,
    508                          const SkMatrix& initialTransform)
    509     : SkDevice(makeContentBitmap(contentSize, &initialTransform)),
    510       fPageSize(pageSize),
    511       fContentSize(contentSize),
    512       fLastContentEntry(NULL),
    513       fLastMarginContentEntry(NULL) {
    514     // Skia generally uses the top left as the origin but PDF natively has the
    515     // origin at the bottom left. This matrix corrects for that.  But that only
    516     // needs to be done once, we don't do it when layering.
    517     fInitialTransform.setTranslate(0, SkIntToScalar(pageSize.fHeight));
    518     fInitialTransform.preScale(SK_Scalar1, -SK_Scalar1);
    519     fInitialTransform.preConcat(initialTransform);
    520 
    521     SkIRect existingClip = SkIRect::MakeWH(this->width(), this->height());
    522     fExistingClipRegion.setRect(existingClip);
    523 
    524     this->init();
    525 }
    526 
    527 // TODO(vandebo) change layerSize to SkSize.
    528 SkPDFDevice::SkPDFDevice(const SkISize& layerSize,
    529                          const SkClipStack& existingClipStack,
    530                          const SkRegion& existingClipRegion)
    531     : SkDevice(makeContentBitmap(layerSize, NULL)),
    532       fPageSize(layerSize),
    533       fContentSize(layerSize),
    534       fExistingClipStack(existingClipStack),
    535       fExistingClipRegion(existingClipRegion),
    536       fLastContentEntry(NULL),
    537       fLastMarginContentEntry(NULL) {
    538     fInitialTransform.reset();
    539     this->init();
    540 }
    541 
    542 SkPDFDevice::~SkPDFDevice() {
    543     this->cleanUp(true);
    544 }
    545 
    546 void SkPDFDevice::init() {
    547     fResourceDict = NULL;
    548     fContentEntries.reset();
    549     fLastContentEntry = NULL;
    550     fMarginContentEntries.reset();
    551     fLastMarginContentEntry = NULL;
    552     fDrawingArea = kContent_DrawingArea;
    553     if (fFontGlyphUsage == NULL) {
    554         fFontGlyphUsage.reset(new SkPDFGlyphSetMap());
    555     }
    556 }
    557 
    558 void SkPDFDevice::cleanUp(bool clearFontUsage) {
    559     fGraphicStateResources.unrefAll();
    560     fXObjectResources.unrefAll();
    561     fFontResources.unrefAll();
    562     fShaderResources.unrefAll();
    563     if (clearFontUsage) {
    564         fFontGlyphUsage->reset();
    565     }
    566 }
    567 
    568 uint32_t SkPDFDevice::getDeviceCapabilities() {
    569     return kVector_Capability;
    570 }
    571 
    572 void SkPDFDevice::clear(SkColor color) {
    573     this->cleanUp(true);
    574     this->init();
    575 
    576     SkPaint paint;
    577     paint.setColor(color);
    578     paint.setStyle(SkPaint::kFill_Style);
    579     SkMatrix identity;
    580     identity.reset();
    581     ScopedContentEntry content(this, &fExistingClipStack, fExistingClipRegion,
    582                                identity, paint);
    583     internalDrawPaint(paint, content.entry());
    584 }
    585 
    586 void SkPDFDevice::drawPaint(const SkDraw& d, const SkPaint& paint) {
    587     SkPaint newPaint = paint;
    588     newPaint.setStyle(SkPaint::kFill_Style);
    589     ScopedContentEntry content(this, d, newPaint);
    590     internalDrawPaint(newPaint, content.entry());
    591 }
    592 
    593 void SkPDFDevice::internalDrawPaint(const SkPaint& paint,
    594                                     ContentEntry* contentEntry) {
    595     if (!contentEntry) {
    596         return;
    597     }
    598     SkRect bbox = SkRect::MakeWH(SkIntToScalar(this->width()),
    599                                  SkIntToScalar(this->height()));
    600     SkMatrix totalTransform = fInitialTransform;
    601     totalTransform.preConcat(contentEntry->fState.fMatrix);
    602     SkMatrix inverse;
    603     inverse.reset();
    604     totalTransform.invert(&inverse);
    605     inverse.mapRect(&bbox);
    606 
    607     SkPDFUtils::AppendRectangle(bbox, &contentEntry->fContent);
    608     SkPDFUtils::PaintPath(paint.getStyle(), SkPath::kWinding_FillType,
    609                           &contentEntry->fContent);
    610 }
    611 
    612 void SkPDFDevice::drawPoints(const SkDraw& d, SkCanvas::PointMode mode,
    613                              size_t count, const SkPoint* points,
    614                              const SkPaint& passedPaint) {
    615     if (count == 0) {
    616         return;
    617     }
    618 
    619     // SkDraw::drawPoints converts to multiple calls to fDevice->drawPath.
    620     // We only use this when there's a path effect because of the overhead
    621     // of multiple calls to setUpContentEntry it causes.
    622     if (passedPaint.getPathEffect()) {
    623         if (d.fClip->isEmpty()) {
    624             return;
    625         }
    626         SkDraw pointDraw(d);
    627         pointDraw.fDevice = this;
    628         pointDraw.drawPoints(mode, count, points, passedPaint, true);
    629         return;
    630     }
    631 
    632     const SkPaint* paint = &passedPaint;
    633     SkPaint modifiedPaint;
    634 
    635     if (mode == SkCanvas::kPoints_PointMode &&
    636             paint->getStrokeCap() != SkPaint::kRound_Cap) {
    637         modifiedPaint = *paint;
    638         paint = &modifiedPaint;
    639         if (paint->getStrokeWidth()) {
    640             // PDF won't draw a single point with square/butt caps because the
    641             // orientation is ambiguous.  Draw a rectangle instead.
    642             modifiedPaint.setStyle(SkPaint::kFill_Style);
    643             SkScalar strokeWidth = paint->getStrokeWidth();
    644             SkScalar halfStroke = SkScalarHalf(strokeWidth);
    645             for (size_t i = 0; i < count; i++) {
    646                 SkRect r = SkRect::MakeXYWH(points[i].fX, points[i].fY, 0, 0);
    647                 r.inset(-halfStroke, -halfStroke);
    648                 drawRect(d, r, modifiedPaint);
    649             }
    650             return;
    651         } else {
    652             modifiedPaint.setStrokeCap(SkPaint::kRound_Cap);
    653         }
    654     }
    655 
    656     ScopedContentEntry content(this, d, *paint);
    657     if (!content.entry()) {
    658         return;
    659     }
    660 
    661     switch (mode) {
    662         case SkCanvas::kPolygon_PointMode:
    663             SkPDFUtils::MoveTo(points[0].fX, points[0].fY,
    664                                &content.entry()->fContent);
    665             for (size_t i = 1; i < count; i++) {
    666                 SkPDFUtils::AppendLine(points[i].fX, points[i].fY,
    667                                        &content.entry()->fContent);
    668             }
    669             SkPDFUtils::StrokePath(&content.entry()->fContent);
    670             break;
    671         case SkCanvas::kLines_PointMode:
    672             for (size_t i = 0; i < count/2; i++) {
    673                 SkPDFUtils::MoveTo(points[i * 2].fX, points[i * 2].fY,
    674                                    &content.entry()->fContent);
    675                 SkPDFUtils::AppendLine(points[i * 2 + 1].fX,
    676                                        points[i * 2 + 1].fY,
    677                                        &content.entry()->fContent);
    678                 SkPDFUtils::StrokePath(&content.entry()->fContent);
    679             }
    680             break;
    681         case SkCanvas::kPoints_PointMode:
    682             SkASSERT(paint->getStrokeCap() == SkPaint::kRound_Cap);
    683             for (size_t i = 0; i < count; i++) {
    684                 SkPDFUtils::MoveTo(points[i].fX, points[i].fY,
    685                                    &content.entry()->fContent);
    686                 SkPDFUtils::ClosePath(&content.entry()->fContent);
    687                 SkPDFUtils::StrokePath(&content.entry()->fContent);
    688             }
    689             break;
    690         default:
    691             SkASSERT(false);
    692     }
    693 }
    694 
    695 void SkPDFDevice::drawRect(const SkDraw& d, const SkRect& r,
    696                            const SkPaint& paint) {
    697     if (paint.getPathEffect()) {
    698         if (d.fClip->isEmpty()) {
    699             return;
    700         }
    701         SkPath path;
    702         path.addRect(r);
    703         drawPath(d, path, paint, NULL, true);
    704         return;
    705     }
    706 
    707     ScopedContentEntry content(this, d, paint);
    708     if (!content.entry()) {
    709         return;
    710     }
    711     SkPDFUtils::AppendRectangle(r, &content.entry()->fContent);
    712     SkPDFUtils::PaintPath(paint.getStyle(), SkPath::kWinding_FillType,
    713                           &content.entry()->fContent);
    714 }
    715 
    716 void SkPDFDevice::drawPath(const SkDraw& d, const SkPath& origPath,
    717                            const SkPaint& paint, const SkMatrix* prePathMatrix,
    718                            bool pathIsMutable) {
    719     SkPath modifiedPath;
    720     SkPath* pathPtr = const_cast<SkPath*>(&origPath);
    721 
    722     SkMatrix matrix = *d.fMatrix;
    723     if (prePathMatrix) {
    724         if (paint.getPathEffect() || paint.getStyle() != SkPaint::kFill_Style) {
    725             if (!pathIsMutable) {
    726                 pathPtr = &modifiedPath;
    727                 pathIsMutable = true;
    728             }
    729             origPath.transform(*prePathMatrix, pathPtr);
    730         } else {
    731             if (!matrix.preConcat(*prePathMatrix)) {
    732                 return;
    733             }
    734         }
    735     }
    736 
    737     if (paint.getPathEffect()) {
    738         if (d.fClip->isEmpty()) {
    739             return;
    740         }
    741         if (!pathIsMutable) {
    742             pathPtr = &modifiedPath;
    743             pathIsMutable = true;
    744         }
    745         bool fill = paint.getFillPath(origPath, pathPtr);
    746 
    747         SkPaint noEffectPaint(paint);
    748         noEffectPaint.setPathEffect(NULL);
    749         if (fill) {
    750             noEffectPaint.setStyle(SkPaint::kFill_Style);
    751         } else {
    752             noEffectPaint.setStyle(SkPaint::kStroke_Style);
    753             noEffectPaint.setStrokeWidth(0);
    754         }
    755         drawPath(d, *pathPtr, noEffectPaint, NULL, true);
    756         return;
    757     }
    758 
    759     ScopedContentEntry content(this, d, paint);
    760     if (!content.entry()) {
    761         return;
    762     }
    763     SkPDFUtils::EmitPath(*pathPtr, &content.entry()->fContent);
    764     SkPDFUtils::PaintPath(paint.getStyle(), pathPtr->getFillType(),
    765                           &content.entry()->fContent);
    766 }
    767 
    768 void SkPDFDevice::drawBitmap(const SkDraw& d, const SkBitmap& bitmap,
    769                              const SkIRect* srcRect, const SkMatrix& matrix,
    770                              const SkPaint& paint) {
    771     if (d.fClip->isEmpty()) {
    772         return;
    773     }
    774 
    775     SkMatrix transform = matrix;
    776     transform.postConcat(*d.fMatrix);
    777     internalDrawBitmap(transform, d.fClipStack, *d.fClip, bitmap, srcRect,
    778                        paint);
    779 }
    780 
    781 void SkPDFDevice::drawSprite(const SkDraw& d, const SkBitmap& bitmap,
    782                              int x, int y, const SkPaint& paint) {
    783     if (d.fClip->isEmpty()) {
    784         return;
    785     }
    786 
    787     SkMatrix matrix;
    788     matrix.setTranslate(SkIntToScalar(x), SkIntToScalar(y));
    789     internalDrawBitmap(matrix, d.fClipStack, *d.fClip, bitmap, NULL, paint);
    790 }
    791 
    792 void SkPDFDevice::drawText(const SkDraw& d, const void* text, size_t len,
    793                            SkScalar x, SkScalar y, const SkPaint& paint) {
    794     SkPaint textPaint = calculate_text_paint(paint);
    795     ScopedContentEntry content(this, d, textPaint, true);
    796     if (!content.entry()) {
    797         return;
    798     }
    799 
    800     // We want the text in glyph id encoding and a writable buffer, so we end
    801     // up making a copy either way.
    802     size_t numGlyphs = paint.textToGlyphs(text, len, NULL);
    803     uint16_t* glyphIDs = reinterpret_cast<uint16_t*>(
    804             sk_malloc_flags(numGlyphs * 2, SK_MALLOC_TEMP | SK_MALLOC_THROW));
    805     SkAutoFree autoFreeGlyphIDs(glyphIDs);
    806     if (paint.getTextEncoding() != SkPaint::kGlyphID_TextEncoding) {
    807         paint.textToGlyphs(text, len, glyphIDs);
    808         textPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
    809     } else {
    810         SkASSERT((len & 1) == 0);
    811         SkASSERT(len / 2 == numGlyphs);
    812         memcpy(glyphIDs, text, len);
    813     }
    814 
    815     SkDrawCacheProc glyphCacheProc = textPaint.getDrawCacheProc();
    816     align_text(glyphCacheProc, textPaint, glyphIDs, numGlyphs, &x, &y);
    817     content.entry()->fContent.writeText("BT\n");
    818     set_text_transform(x, y, textPaint.getTextSkewX(),
    819                        &content.entry()->fContent);
    820     size_t consumedGlyphCount = 0;
    821     while (numGlyphs > consumedGlyphCount) {
    822         updateFont(textPaint, glyphIDs[consumedGlyphCount], content.entry());
    823         SkPDFFont* font = content.entry()->fState.fFont;
    824         size_t availableGlyphs =
    825             font->glyphsToPDFFontEncoding(glyphIDs + consumedGlyphCount,
    826                                           numGlyphs - consumedGlyphCount);
    827         fFontGlyphUsage->noteGlyphUsage(font, glyphIDs + consumedGlyphCount,
    828                                         availableGlyphs);
    829         SkString encodedString =
    830             SkPDFString::FormatString(glyphIDs + consumedGlyphCount,
    831                                       availableGlyphs, font->multiByteGlyphs());
    832         content.entry()->fContent.writeText(encodedString.c_str());
    833         consumedGlyphCount += availableGlyphs;
    834         content.entry()->fContent.writeText(" Tj\n");
    835     }
    836     content.entry()->fContent.writeText("ET\n");
    837 }
    838 
    839 void SkPDFDevice::drawPosText(const SkDraw& d, const void* text, size_t len,
    840                               const SkScalar pos[], SkScalar constY,
    841                               int scalarsPerPos, const SkPaint& paint) {
    842     SkASSERT(1 == scalarsPerPos || 2 == scalarsPerPos);
    843     SkPaint textPaint = calculate_text_paint(paint);
    844     ScopedContentEntry content(this, d, textPaint, true);
    845     if (!content.entry()) {
    846         return;
    847     }
    848 
    849     // Make sure we have a glyph id encoding.
    850     SkAutoFree glyphStorage;
    851     uint16_t* glyphIDs;
    852     size_t numGlyphs;
    853     if (paint.getTextEncoding() != SkPaint::kGlyphID_TextEncoding) {
    854         numGlyphs = paint.textToGlyphs(text, len, NULL);
    855         glyphIDs = reinterpret_cast<uint16_t*>(sk_malloc_flags(
    856                 numGlyphs * 2, SK_MALLOC_TEMP | SK_MALLOC_THROW));
    857         glyphStorage.set(glyphIDs);
    858         paint.textToGlyphs(text, len, glyphIDs);
    859         textPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
    860     } else {
    861         SkASSERT((len & 1) == 0);
    862         numGlyphs = len / 2;
    863         glyphIDs = reinterpret_cast<uint16_t*>(const_cast<void*>((text)));
    864     }
    865 
    866     SkDrawCacheProc glyphCacheProc = textPaint.getDrawCacheProc();
    867     content.entry()->fContent.writeText("BT\n");
    868     updateFont(textPaint, glyphIDs[0], content.entry());
    869     for (size_t i = 0; i < numGlyphs; i++) {
    870         SkPDFFont* font = content.entry()->fState.fFont;
    871         uint16_t encodedValue = glyphIDs[i];
    872         if (font->glyphsToPDFFontEncoding(&encodedValue, 1) != 1) {
    873             updateFont(textPaint, glyphIDs[i], content.entry());
    874             i--;
    875             continue;
    876         }
    877         fFontGlyphUsage->noteGlyphUsage(font, &encodedValue, 1);
    878         SkScalar x = pos[i * scalarsPerPos];
    879         SkScalar y = scalarsPerPos == 1 ? constY : pos[i * scalarsPerPos + 1];
    880         align_text(glyphCacheProc, textPaint, glyphIDs + i, 1, &x, &y);
    881         set_text_transform(x, y, textPaint.getTextSkewX(),
    882                            &content.entry()->fContent);
    883         SkString encodedString =
    884             SkPDFString::FormatString(&encodedValue, 1,
    885                                       font->multiByteGlyphs());
    886         content.entry()->fContent.writeText(encodedString.c_str());
    887         content.entry()->fContent.writeText(" Tj\n");
    888     }
    889     content.entry()->fContent.writeText("ET\n");
    890 }
    891 
    892 void SkPDFDevice::drawTextOnPath(const SkDraw& d, const void* text, size_t len,
    893                                  const SkPath& path, const SkMatrix* matrix,
    894                                  const SkPaint& paint) {
    895     if (d.fClip->isEmpty()) {
    896         return;
    897     }
    898     d.drawTextOnPath((const char*)text, len, path, matrix, paint);
    899 }
    900 
    901 void SkPDFDevice::drawVertices(const SkDraw& d, SkCanvas::VertexMode,
    902                                int vertexCount, const SkPoint verts[],
    903                                const SkPoint texs[], const SkColor colors[],
    904                                SkXfermode* xmode, const uint16_t indices[],
    905                                int indexCount, const SkPaint& paint) {
    906     if (d.fClip->isEmpty()) {
    907         return;
    908     }
    909     NOT_IMPLEMENTED("drawVerticies", true);
    910 }
    911 
    912 void SkPDFDevice::drawDevice(const SkDraw& d, SkDevice* device, int x, int y,
    913                              const SkPaint& paint) {
    914     if ((device->getDeviceCapabilities() & kVector_Capability) == 0) {
    915         // If we somehow get a raster device, do what our parent would do.
    916         SkDevice::drawDevice(d, device, x, y, paint);
    917         return;
    918     }
    919 
    920     // Assume that a vector capable device means that it's a PDF Device.
    921     SkPDFDevice* pdfDevice = static_cast<SkPDFDevice*>(device);
    922     if (pdfDevice->isContentEmpty()) {
    923         return;
    924     }
    925 
    926     SkMatrix matrix;
    927     matrix.setTranslate(SkIntToScalar(x), SkIntToScalar(y));
    928     ScopedContentEntry content(this, d.fClipStack, *d.fClip, matrix, paint);
    929     if (!content.entry()) {
    930         return;
    931     }
    932 
    933     SkPDFFormXObject* xobject = new SkPDFFormXObject(pdfDevice);
    934     fXObjectResources.push(xobject);  // Transfer reference.
    935     SkPDFUtils::DrawFormXObject(fXObjectResources.count() - 1,
    936                                 &content.entry()->fContent);
    937 
    938     // Merge glyph sets from the drawn device.
    939     fFontGlyphUsage->merge(pdfDevice->getFontGlyphUsage());
    940 }
    941 
    942 ContentEntry* SkPDFDevice::getLastContentEntry() {
    943     if (fDrawingArea == kContent_DrawingArea) {
    944         return fLastContentEntry;
    945     } else {
    946         return fLastMarginContentEntry;
    947     }
    948 }
    949 
    950 SkTScopedPtr<ContentEntry>* SkPDFDevice::getContentEntries() {
    951     if (fDrawingArea == kContent_DrawingArea) {
    952         return &fContentEntries;
    953     } else {
    954         return &fMarginContentEntries;
    955     }
    956 }
    957 
    958 void SkPDFDevice::setLastContentEntry(ContentEntry* contentEntry) {
    959     if (fDrawingArea == kContent_DrawingArea) {
    960         fLastContentEntry = contentEntry;
    961     } else {
    962         fLastMarginContentEntry = contentEntry;
    963     }
    964 }
    965 
    966 void SkPDFDevice::setDrawingArea(DrawingArea drawingArea) {
    967     // A ScopedContentEntry only exists during the course of a draw call, so
    968     // this can't be called while a ScopedContentEntry exists.
    969     fDrawingArea = drawingArea;
    970 }
    971 
    972 SkPDFDict* SkPDFDevice::getResourceDict() {
    973     if (fResourceDict.get() == NULL) {
    974         fResourceDict = new SkPDFDict;
    975         fResourceDict->unref();  // SkRefPtr and new both took a reference.
    976 
    977         if (fGraphicStateResources.count()) {
    978             SkRefPtr<SkPDFDict> extGState = new SkPDFDict();
    979             extGState->unref();  // SkRefPtr and new both took a reference.
    980             for (int i = 0; i < fGraphicStateResources.count(); i++) {
    981                 SkString nameString("G");
    982                 nameString.appendS32(i);
    983                 extGState->insert(
    984                         nameString.c_str(),
    985                         new SkPDFObjRef(fGraphicStateResources[i]))->unref();
    986             }
    987             fResourceDict->insert("ExtGState", extGState.get());
    988         }
    989 
    990         if (fXObjectResources.count()) {
    991             SkRefPtr<SkPDFDict> xObjects = new SkPDFDict();
    992             xObjects->unref();  // SkRefPtr and new both took a reference.
    993             for (int i = 0; i < fXObjectResources.count(); i++) {
    994                 SkString nameString("X");
    995                 nameString.appendS32(i);
    996                 xObjects->insert(
    997                         nameString.c_str(),
    998                         new SkPDFObjRef(fXObjectResources[i]))->unref();
    999             }
   1000             fResourceDict->insert("XObject", xObjects.get());
   1001         }
   1002 
   1003         if (fFontResources.count()) {
   1004             SkRefPtr<SkPDFDict> fonts = new SkPDFDict();
   1005             fonts->unref();  // SkRefPtr and new both took a reference.
   1006             for (int i = 0; i < fFontResources.count(); i++) {
   1007                 SkString nameString("F");
   1008                 nameString.appendS32(i);
   1009                 fonts->insert(nameString.c_str(),
   1010                               new SkPDFObjRef(fFontResources[i]))->unref();
   1011             }
   1012             fResourceDict->insert("Font", fonts.get());
   1013         }
   1014 
   1015         if (fShaderResources.count()) {
   1016             SkRefPtr<SkPDFDict> patterns = new SkPDFDict();
   1017             patterns->unref();  // SkRefPtr and new both took a reference.
   1018             for (int i = 0; i < fShaderResources.count(); i++) {
   1019                 SkString nameString("P");
   1020                 nameString.appendS32(i);
   1021                 patterns->insert(nameString.c_str(),
   1022                                  new SkPDFObjRef(fShaderResources[i]))->unref();
   1023             }
   1024             fResourceDict->insert("Pattern", patterns.get());
   1025         }
   1026 
   1027         // For compatibility, add all proc sets (only used for output to PS
   1028         // devices).
   1029         const char procs[][7] = {"PDF", "Text", "ImageB", "ImageC", "ImageI"};
   1030         SkRefPtr<SkPDFArray> procSets = new SkPDFArray();
   1031         procSets->unref();  // SkRefPtr and new both took a reference.
   1032         procSets->reserve(SK_ARRAY_COUNT(procs));
   1033         for (size_t i = 0; i < SK_ARRAY_COUNT(procs); i++)
   1034             procSets->appendName(procs[i]);
   1035         fResourceDict->insert("ProcSet", procSets.get());
   1036     }
   1037     return fResourceDict.get();
   1038 }
   1039 
   1040 void SkPDFDevice::getResources(SkTDArray<SkPDFObject*>* resourceList) const {
   1041     resourceList->setReserve(resourceList->count() +
   1042                              fGraphicStateResources.count() +
   1043                              fXObjectResources.count() +
   1044                              fFontResources.count() +
   1045                              fShaderResources.count());
   1046     for (int i = 0; i < fGraphicStateResources.count(); i++) {
   1047         resourceList->push(fGraphicStateResources[i]);
   1048         fGraphicStateResources[i]->ref();
   1049         fGraphicStateResources[i]->getResources(resourceList);
   1050     }
   1051     for (int i = 0; i < fXObjectResources.count(); i++) {
   1052         resourceList->push(fXObjectResources[i]);
   1053         fXObjectResources[i]->ref();
   1054         fXObjectResources[i]->getResources(resourceList);
   1055     }
   1056     for (int i = 0; i < fFontResources.count(); i++) {
   1057         resourceList->push(fFontResources[i]);
   1058         fFontResources[i]->ref();
   1059         fFontResources[i]->getResources(resourceList);
   1060     }
   1061     for (int i = 0; i < fShaderResources.count(); i++) {
   1062         resourceList->push(fShaderResources[i]);
   1063         fShaderResources[i]->ref();
   1064         fShaderResources[i]->getResources(resourceList);
   1065     }
   1066 }
   1067 
   1068 const SkTDArray<SkPDFFont*>& SkPDFDevice::getFontResources() const {
   1069     return fFontResources;
   1070 }
   1071 
   1072 SkRefPtr<SkPDFArray> SkPDFDevice::getMediaBox() const {
   1073     SkRefPtr<SkPDFInt> zero = new SkPDFInt(0);
   1074     zero->unref();  // SkRefPtr and new both took a reference.
   1075 
   1076     SkRefPtr<SkPDFArray> mediaBox = new SkPDFArray();
   1077     mediaBox->unref();  // SkRefPtr and new both took a reference.
   1078     mediaBox->reserve(4);
   1079     mediaBox->append(zero.get());
   1080     mediaBox->append(zero.get());
   1081     mediaBox->appendInt(fPageSize.fWidth);
   1082     mediaBox->appendInt(fPageSize.fHeight);
   1083     return mediaBox;
   1084 }
   1085 
   1086 SkStream* SkPDFDevice::content() const {
   1087     SkMemoryStream* result = new SkMemoryStream;
   1088     result->setData(this->copyContentToData())->unref();
   1089     return result;
   1090 }
   1091 
   1092 void SkPDFDevice::copyContentEntriesToData(ContentEntry* entry,
   1093         SkWStream* data) const {
   1094     // TODO(ctguil): For margins, I'm not sure fExistingClipStack/Region is the
   1095     // right thing to pass here.
   1096     GraphicStackState gsState(fExistingClipStack, fExistingClipRegion, data);
   1097     while (entry != NULL) {
   1098         SkPoint translation;
   1099         translation.iset(this->getOrigin());
   1100         translation.negate();
   1101         gsState.updateClip(entry->fState.fClipStack, entry->fState.fClipRegion,
   1102                            translation);
   1103         gsState.updateMatrix(entry->fState.fMatrix);
   1104         gsState.updateDrawingState(entry->fState);
   1105 
   1106         SkAutoDataUnref copy(entry->fContent.copyToData());
   1107         data->write(copy.data(), copy.size());
   1108         entry = entry->fNext.get();
   1109     }
   1110     gsState.drainStack();
   1111 }
   1112 
   1113 SkData* SkPDFDevice::copyContentToData() const {
   1114     SkDynamicMemoryWStream data;
   1115     if (fInitialTransform.getType() != SkMatrix::kIdentity_Mask) {
   1116         SkPDFUtils::AppendTransform(fInitialTransform, &data);
   1117     }
   1118 
   1119     // TODO(aayushkumar): Apply clip along the margins.  Currently, webkit
   1120     // colors the contentArea white before it starts drawing into it and
   1121     // that currently acts as our clip.
   1122     // Also, think about adding a transform here (or assume that the values
   1123     // sent across account for that)
   1124     SkPDFDevice::copyContentEntriesToData(fMarginContentEntries.get(), &data);
   1125 
   1126     // If the content area is the entire page, then we don't need to clip
   1127     // the content area (PDF area clips to the page size).  Otherwise,
   1128     // we have to clip to the content area; we've already applied the
   1129     // initial transform, so just clip to the device size.
   1130     if (fPageSize != fContentSize) {
   1131         SkRect r = SkRect::MakeWH(this->width(), this->height());
   1132         emit_clip(NULL, &r, &data);
   1133     }
   1134 
   1135     SkPDFDevice::copyContentEntriesToData(fContentEntries.get(), &data);
   1136 
   1137     // potentially we could cache this SkData, and only rebuild it if we
   1138     // see that our state has changed.
   1139     return data.copyToData();
   1140 }
   1141 
   1142 void SkPDFDevice::createFormXObjectFromDevice(
   1143         SkRefPtr<SkPDFFormXObject>* xobject) {
   1144     *xobject = new SkPDFFormXObject(this);
   1145     (*xobject)->unref();  // SkRefPtr and new both took a reference.
   1146     // We always draw the form xobjects that we create back into the device, so
   1147     // we simply preserve the font usage instead of pulling it out and merging
   1148     // it back in later.
   1149     cleanUp(false);  // Reset this device to have no content.
   1150     init();
   1151 }
   1152 
   1153 void SkPDFDevice::clearClipFromContent(const SkClipStack* clipStack,
   1154                                        const SkRegion& clipRegion) {
   1155     if (clipRegion.isEmpty() || isContentEmpty()) {
   1156         return;
   1157     }
   1158     SkRefPtr<SkPDFFormXObject> curContent;
   1159     createFormXObjectFromDevice(&curContent);
   1160 
   1161     // Redraw what we already had, but with the clip as a mask.
   1162     drawFormXObjectWithClip(curContent.get(), clipStack, clipRegion, true);
   1163 }
   1164 
   1165 void SkPDFDevice::drawFormXObjectWithClip(SkPDFFormXObject* xobject,
   1166                                           const SkClipStack* clipStack,
   1167                                           const SkRegion& clipRegion,
   1168                                           bool invertClip) {
   1169     if (clipRegion.isEmpty() && !invertClip) {
   1170         return;
   1171     }
   1172 
   1173     // Create the mask.
   1174     SkMatrix identity;
   1175     identity.reset();
   1176     SkDraw draw;
   1177     draw.fMatrix = &identity;
   1178     draw.fClip = &clipRegion;
   1179     draw.fClipStack = clipStack;
   1180     SkPaint stockPaint;
   1181     this->drawPaint(draw, stockPaint);
   1182     SkRefPtr<SkPDFFormXObject> maskFormXObject;
   1183     createFormXObjectFromDevice(&maskFormXObject);
   1184     SkRefPtr<SkPDFGraphicState> sMaskGS =
   1185         SkPDFGraphicState::GetSMaskGraphicState(maskFormXObject.get(),
   1186                                                 invertClip);
   1187     sMaskGS->unref();  // SkRefPtr and getSMaskGraphicState both took a ref.
   1188 
   1189     // Draw the xobject with the clip as a mask.
   1190     ScopedContentEntry content(this, &fExistingClipStack, fExistingClipRegion,
   1191                                  identity, stockPaint);
   1192     if (!content.entry()) {
   1193         return;
   1194     }
   1195     SkPDFUtils::ApplyGraphicState(addGraphicStateResource(sMaskGS.get()),
   1196                                   &content.entry()->fContent);
   1197     SkPDFUtils::DrawFormXObject(fXObjectResources.count(),
   1198                                 &content.entry()->fContent);
   1199     fXObjectResources.push(xobject);
   1200     xobject->ref();
   1201 
   1202     sMaskGS = SkPDFGraphicState::GetNoSMaskGraphicState();
   1203     sMaskGS->unref();  // SkRefPtr and getSMaskGraphicState both took a ref.
   1204     SkPDFUtils::ApplyGraphicState(addGraphicStateResource(sMaskGS.get()),
   1205                                   &content.entry()->fContent);
   1206 }
   1207 
   1208 ContentEntry* SkPDFDevice::setUpContentEntry(const SkClipStack* clipStack,
   1209                                              const SkRegion& clipRegion,
   1210                                              const SkMatrix& matrix,
   1211                                              const SkPaint& paint,
   1212                                              bool hasText,
   1213                                              SkRefPtr<SkPDFFormXObject>* dst) {
   1214     if (clipRegion.isEmpty()) {
   1215         return NULL;
   1216     }
   1217 
   1218     // The clip stack can come from an SkDraw where it is technically optional.
   1219     SkClipStack synthesizedClipStack;
   1220     if (clipStack == NULL) {
   1221         if (clipRegion == fExistingClipRegion) {
   1222             clipStack = &fExistingClipStack;
   1223         } else {
   1224             // GraphicStackState::updateClip expects the clip stack to have
   1225             // fExistingClip as a prefix, so start there, then set the clip
   1226             // to the passed region.
   1227             synthesizedClipStack = fExistingClipStack;
   1228             SkPath clipPath;
   1229             clipRegion.getBoundaryPath(&clipPath);
   1230             synthesizedClipStack.clipDevPath(clipPath, SkRegion::kReplace_Op,
   1231                                              false);
   1232             clipStack = &synthesizedClipStack;
   1233         }
   1234     }
   1235 
   1236     SkXfermode::Mode xfermode = SkXfermode::kSrcOver_Mode;
   1237     if (paint.getXfermode()) {
   1238         paint.getXfermode()->asMode(&xfermode);
   1239     }
   1240 
   1241     if (xfermode == SkXfermode::kClear_Mode ||
   1242             xfermode == SkXfermode::kSrc_Mode) {
   1243         this->clearClipFromContent(clipStack, clipRegion);
   1244     } else if (xfermode == SkXfermode::kSrcIn_Mode ||
   1245                xfermode == SkXfermode::kDstIn_Mode ||
   1246                xfermode == SkXfermode::kSrcOut_Mode ||
   1247                xfermode == SkXfermode::kDstOut_Mode) {
   1248         // For the following modes, we use both source and destination, but
   1249         // we use one as a smask for the other, so we have to make form xobjects
   1250         // out of both of them: SrcIn, DstIn, SrcOut, DstOut.
   1251         if (isContentEmpty()) {
   1252             return NULL;
   1253         } else {
   1254             createFormXObjectFromDevice(dst);
   1255         }
   1256     }
   1257     // TODO(vandebo): Figure out how/if we can handle the following modes:
   1258     // SrcAtop, DestAtop, Xor, Plus.
   1259 
   1260     // These xfer modes don't draw source at all.
   1261     if (xfermode == SkXfermode::kClear_Mode ||
   1262             xfermode == SkXfermode::kDst_Mode) {
   1263         return NULL;
   1264     }
   1265 
   1266     ContentEntry* entry;
   1267     SkTScopedPtr<ContentEntry> newEntry;
   1268 
   1269     ContentEntry* lastContentEntry = getLastContentEntry();
   1270     if (lastContentEntry && lastContentEntry->fContent.getOffset() == 0) {
   1271         entry = lastContentEntry;
   1272     } else {
   1273         newEntry.reset(new ContentEntry);
   1274         entry = newEntry.get();
   1275     }
   1276 
   1277     populateGraphicStateEntryFromPaint(matrix, *clipStack, clipRegion, paint,
   1278                                        hasText, &entry->fState);
   1279     if (lastContentEntry && xfermode != SkXfermode::kDstOver_Mode &&
   1280             entry->fState.compareInitialState(lastContentEntry->fState)) {
   1281         return lastContentEntry;
   1282     }
   1283 
   1284     SkTScopedPtr<ContentEntry>* contentEntries = getContentEntries();
   1285     if (!lastContentEntry) {
   1286         contentEntries->reset(entry);
   1287         setLastContentEntry(entry);
   1288     } else if (xfermode == SkXfermode::kDstOver_Mode) {
   1289         entry->fNext.reset(contentEntries->release());
   1290         contentEntries->reset(entry);
   1291     } else {
   1292         lastContentEntry->fNext.reset(entry);
   1293         setLastContentEntry(entry);
   1294     }
   1295     newEntry.release();
   1296     return entry;
   1297 }
   1298 
   1299 void SkPDFDevice::finishContentEntry(const SkXfermode::Mode xfermode,
   1300                                      SkPDFFormXObject* dst) {
   1301     if (xfermode != SkXfermode::kSrcIn_Mode &&
   1302             xfermode != SkXfermode::kDstIn_Mode &&
   1303             xfermode != SkXfermode::kSrcOut_Mode &&
   1304             xfermode != SkXfermode::kDstOut_Mode) {
   1305         SkASSERT(!dst);
   1306         return;
   1307     }
   1308 
   1309     ContentEntry* contentEntries = getContentEntries()->get();
   1310     SkASSERT(dst);
   1311     SkASSERT(!contentEntries->fNext.get());
   1312     // We have to make a copy of these here because changing the current
   1313     // content into a form xobject will destroy them.
   1314     SkClipStack clipStack = contentEntries->fState.fClipStack;
   1315     SkRegion clipRegion = contentEntries->fState.fClipRegion;
   1316 
   1317     SkRefPtr<SkPDFFormXObject> srcFormXObject;
   1318     if (!isContentEmpty()) {
   1319         createFormXObjectFromDevice(&srcFormXObject);
   1320     }
   1321 
   1322     drawFormXObjectWithClip(dst, &clipStack, clipRegion, true);
   1323 
   1324     // We've redrawn dst minus the clip area, if there's no src, we're done.
   1325     if (!srcFormXObject.get()) {
   1326         return;
   1327     }
   1328 
   1329     SkMatrix identity;
   1330     identity.reset();
   1331     SkPaint stockPaint;
   1332     ScopedContentEntry inClipContentEntry(this, &fExistingClipStack,
   1333                                           fExistingClipRegion, identity,
   1334                                           stockPaint);
   1335     if (!inClipContentEntry.entry()) {
   1336         return;
   1337     }
   1338 
   1339     SkRefPtr<SkPDFGraphicState> sMaskGS;
   1340     if (xfermode == SkXfermode::kSrcIn_Mode ||
   1341             xfermode == SkXfermode::kSrcOut_Mode) {
   1342         sMaskGS = SkPDFGraphicState::GetSMaskGraphicState(
   1343                 dst, xfermode == SkXfermode::kSrcOut_Mode);
   1344         fXObjectResources.push(srcFormXObject.get());
   1345         srcFormXObject->ref();
   1346     } else {
   1347         sMaskGS = SkPDFGraphicState::GetSMaskGraphicState(
   1348                 srcFormXObject.get(), xfermode == SkXfermode::kDstOut_Mode);
   1349         // dst already added to fXObjectResources in drawFormXObjectWithClip.
   1350     }
   1351     sMaskGS->unref();  // SkRefPtr and getSMaskGraphicState both took a ref.
   1352     SkPDFUtils::ApplyGraphicState(addGraphicStateResource(sMaskGS.get()),
   1353                                   &inClipContentEntry.entry()->fContent);
   1354 
   1355     SkPDFUtils::DrawFormXObject(fXObjectResources.count() - 1,
   1356                                 &inClipContentEntry.entry()->fContent);
   1357 
   1358     sMaskGS = SkPDFGraphicState::GetNoSMaskGraphicState();
   1359     sMaskGS->unref();  // SkRefPtr and getSMaskGraphicState both took a ref.
   1360     SkPDFUtils::ApplyGraphicState(addGraphicStateResource(sMaskGS.get()),
   1361                                   &inClipContentEntry.entry()->fContent);
   1362 }
   1363 
   1364 bool SkPDFDevice::isContentEmpty() {
   1365     ContentEntry* contentEntries = getContentEntries()->get();
   1366     if (!contentEntries || contentEntries->fContent.getOffset() == 0) {
   1367         SkASSERT(!contentEntries || !contentEntries->fNext.get());
   1368         return true;
   1369     }
   1370     return false;
   1371 }
   1372 
   1373 void SkPDFDevice::populateGraphicStateEntryFromPaint(
   1374         const SkMatrix& matrix,
   1375         const SkClipStack& clipStack,
   1376         const SkRegion& clipRegion,
   1377         const SkPaint& paint,
   1378         bool hasText,
   1379         GraphicStateEntry* entry) {
   1380     SkASSERT(paint.getPathEffect() == NULL);
   1381 
   1382     NOT_IMPLEMENTED(paint.getMaskFilter() != NULL, false);
   1383     NOT_IMPLEMENTED(paint.getColorFilter() != NULL, false);
   1384 
   1385     entry->fMatrix = matrix;
   1386     entry->fClipStack = clipStack;
   1387     entry->fClipRegion = clipRegion;
   1388 
   1389     // PDF treats a shader as a color, so we only set one or the other.
   1390     SkRefPtr<SkPDFObject> pdfShader;
   1391     const SkShader* shader = paint.getShader();
   1392     SkColor color = paint.getColor();
   1393     if (shader) {
   1394         // PDF positions patterns relative to the initial transform, so
   1395         // we need to apply the current transform to the shader parameters.
   1396         SkMatrix transform = matrix;
   1397         transform.postConcat(fInitialTransform);
   1398 
   1399         // PDF doesn't support kClamp_TileMode, so we simulate it by making
   1400         // a pattern the size of the current clip.
   1401         SkIRect bounds = clipRegion.getBounds();
   1402         pdfShader = SkPDFShader::GetPDFShader(*shader, transform, bounds);
   1403         SkSafeUnref(pdfShader.get());  // getShader and SkRefPtr both took a ref
   1404 
   1405         if (pdfShader.get()) {
   1406             // pdfShader has been canonicalized so we can directly compare
   1407             // pointers.
   1408             int resourceIndex = fShaderResources.find(pdfShader.get());
   1409             if (resourceIndex < 0) {
   1410                 resourceIndex = fShaderResources.count();
   1411                 fShaderResources.push(pdfShader.get());
   1412                 pdfShader->ref();
   1413             }
   1414             entry->fShaderIndex = resourceIndex;
   1415         } else {
   1416             // A color shader is treated as an invalid shader so we don't have
   1417             // to set a shader just for a color.
   1418             entry->fShaderIndex = -1;
   1419             entry->fColor = 0;
   1420             color = 0;
   1421 
   1422             // Check for a color shader.
   1423             SkShader::GradientInfo gradientInfo;
   1424             SkColor gradientColor;
   1425             gradientInfo.fColors = &gradientColor;
   1426             gradientInfo.fColorOffsets = NULL;
   1427             gradientInfo.fColorCount = 1;
   1428             if (shader->asAGradient(&gradientInfo) ==
   1429                     SkShader::kColor_GradientType) {
   1430                 entry->fColor = SkColorSetA(gradientColor, 0xFF);
   1431                 color = gradientColor;
   1432             }
   1433         }
   1434     } else {
   1435         entry->fShaderIndex = -1;
   1436         entry->fColor = SkColorSetA(paint.getColor(), 0xFF);
   1437         color = paint.getColor();
   1438     }
   1439 
   1440     SkRefPtr<SkPDFGraphicState> newGraphicState;
   1441     if (color == paint.getColor()) {
   1442         newGraphicState = SkPDFGraphicState::GetGraphicStateForPaint(paint);
   1443     } else {
   1444         SkPaint newPaint = paint;
   1445         newPaint.setColor(color);
   1446         newGraphicState = SkPDFGraphicState::GetGraphicStateForPaint(newPaint);
   1447     }
   1448     newGraphicState->unref();  // getGraphicState and SkRefPtr both took a ref.
   1449     int resourceIndex = addGraphicStateResource(newGraphicState.get());
   1450     entry->fGraphicStateIndex = resourceIndex;
   1451 
   1452     if (hasText) {
   1453         entry->fTextScaleX = paint.getTextScaleX();
   1454         entry->fTextFill = paint.getStyle();
   1455     } else {
   1456         entry->fTextScaleX = 0;
   1457     }
   1458 }
   1459 
   1460 int SkPDFDevice::addGraphicStateResource(SkPDFGraphicState* gs) {
   1461     // Assumes that gs has been canonicalized (so we can directly compare
   1462     // pointers).
   1463     int result = fGraphicStateResources.find(gs);
   1464     if (result < 0) {
   1465         result = fGraphicStateResources.count();
   1466         fGraphicStateResources.push(gs);
   1467         gs->ref();
   1468     }
   1469     return result;
   1470 }
   1471 
   1472 void SkPDFDevice::updateFont(const SkPaint& paint, uint16_t glyphID,
   1473                              ContentEntry* contentEntry) {
   1474     SkTypeface* typeface = paint.getTypeface();
   1475     if (contentEntry->fState.fFont == NULL ||
   1476             contentEntry->fState.fTextSize != paint.getTextSize() ||
   1477             !contentEntry->fState.fFont->hasGlyph(glyphID)) {
   1478         int fontIndex = getFontResourceIndex(typeface, glyphID);
   1479         contentEntry->fContent.writeText("/F");
   1480         contentEntry->fContent.writeDecAsText(fontIndex);
   1481         contentEntry->fContent.writeText(" ");
   1482         SkPDFScalar::Append(paint.getTextSize(), &contentEntry->fContent);
   1483         contentEntry->fContent.writeText(" Tf\n");
   1484         contentEntry->fState.fFont = fFontResources[fontIndex];
   1485     }
   1486 }
   1487 
   1488 int SkPDFDevice::getFontResourceIndex(SkTypeface* typeface, uint16_t glyphID) {
   1489     SkRefPtr<SkPDFFont> newFont = SkPDFFont::GetFontResource(typeface, glyphID);
   1490     newFont->unref();  // getFontResource and SkRefPtr both took a ref.
   1491     int resourceIndex = fFontResources.find(newFont.get());
   1492     if (resourceIndex < 0) {
   1493         resourceIndex = fFontResources.count();
   1494         fFontResources.push(newFont.get());
   1495         newFont->ref();
   1496     }
   1497     return resourceIndex;
   1498 }
   1499 
   1500 void SkPDFDevice::internalDrawBitmap(const SkMatrix& matrix,
   1501                                      const SkClipStack* clipStack,
   1502                                      const SkRegion& clipRegion,
   1503                                      const SkBitmap& bitmap,
   1504                                      const SkIRect* srcRect,
   1505                                      const SkPaint& paint) {
   1506     SkMatrix scaled;
   1507     // Adjust for origin flip.
   1508     scaled.setScale(SK_Scalar1, -SK_Scalar1);
   1509     scaled.postTranslate(0, SK_Scalar1);
   1510     // Scale the image up from 1x1 to WxH.
   1511     SkIRect subset = SkIRect::MakeWH(bitmap.width(), bitmap.height());
   1512     scaled.postScale(SkIntToScalar(subset.width()),
   1513                      SkIntToScalar(subset.height()));
   1514     scaled.postConcat(matrix);
   1515     ScopedContentEntry content(this, clipStack, clipRegion, scaled, paint);
   1516     if (!content.entry()) {
   1517         return;
   1518     }
   1519 
   1520     if (srcRect && !subset.intersect(*srcRect)) {
   1521         return;
   1522     }
   1523 
   1524     SkPDFImage* image = SkPDFImage::CreateImage(bitmap, subset, paint);
   1525     if (!image) {
   1526         return;
   1527     }
   1528 
   1529     fXObjectResources.push(image);  // Transfer reference.
   1530     SkPDFUtils::DrawFormXObject(fXObjectResources.count() - 1,
   1531                                 &content.entry()->fContent);
   1532 }
   1533 
   1534 bool SkPDFDevice::onReadPixels(const SkBitmap& bitmap, int x, int y,
   1535                                SkCanvas::Config8888) {
   1536     return false;
   1537 }
   1538 
   1539 bool SkPDFDevice::allowImageFilter(SkImageFilter*) {
   1540     return false;
   1541 }
   1542 
   1543