Home | History | Annotate | Download | only in pdf
      1 /*
      2  * Copyright 2011 Google Inc.
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 #include "SkPDFDevice.h"
      9 
     10 #include "SkAnnotation.h"
     11 #include "SkBitmapDevice.h"
     12 #include "SkColor.h"
     13 #include "SkClipStack.h"
     14 #include "SkData.h"
     15 #include "SkDraw.h"
     16 #include "SkFontHost.h"
     17 #include "SkGlyphCache.h"
     18 #include "SkPaint.h"
     19 #include "SkPath.h"
     20 #include "SkPathOps.h"
     21 #include "SkPDFFont.h"
     22 #include "SkPDFFormXObject.h"
     23 #include "SkPDFGraphicState.h"
     24 #include "SkPDFImage.h"
     25 #include "SkPDFResourceDict.h"
     26 #include "SkPDFShader.h"
     27 #include "SkPDFStream.h"
     28 #include "SkPDFTypes.h"
     29 #include "SkPDFUtils.h"
     30 #include "SkRect.h"
     31 #include "SkRRect.h"
     32 #include "SkString.h"
     33 #include "SkSurface.h"
     34 #include "SkTextFormatParams.h"
     35 #include "SkTemplates.h"
     36 #include "SkTypefacePriv.h"
     37 #include "SkTSet.h"
     38 
     39 #define DPI_FOR_RASTER_SCALE_ONE 72
     40 
     41 // Utility functions
     42 
     43 static void emit_pdf_color(SkColor color, SkWStream* result) {
     44     SkASSERT(SkColorGetA(color) == 0xFF);  // We handle alpha elsewhere.
     45     SkScalar colorMax = SkIntToScalar(0xFF);
     46     SkPDFScalar::Append(
     47             SkScalarDiv(SkIntToScalar(SkColorGetR(color)), colorMax), result);
     48     result->writeText(" ");
     49     SkPDFScalar::Append(
     50             SkScalarDiv(SkIntToScalar(SkColorGetG(color)), colorMax), result);
     51     result->writeText(" ");
     52     SkPDFScalar::Append(
     53             SkScalarDiv(SkIntToScalar(SkColorGetB(color)), colorMax), result);
     54     result->writeText(" ");
     55 }
     56 
     57 static SkPaint calculate_text_paint(const SkPaint& paint) {
     58     SkPaint result = paint;
     59     if (result.isFakeBoldText()) {
     60         SkScalar fakeBoldScale = SkScalarInterpFunc(result.getTextSize(),
     61                                                     kStdFakeBoldInterpKeys,
     62                                                     kStdFakeBoldInterpValues,
     63                                                     kStdFakeBoldInterpLength);
     64         SkScalar width = SkScalarMul(result.getTextSize(), fakeBoldScale);
     65         if (result.getStyle() == SkPaint::kFill_Style) {
     66             result.setStyle(SkPaint::kStrokeAndFill_Style);
     67         } else {
     68             width += result.getStrokeWidth();
     69         }
     70         result.setStrokeWidth(width);
     71     }
     72     return result;
     73 }
     74 
     75 // Stolen from measure_text in SkDraw.cpp and then tweaked.
     76 static void align_text(SkDrawCacheProc glyphCacheProc, const SkPaint& paint,
     77                        const uint16_t* glyphs, size_t len,
     78                        SkScalar* x, SkScalar* y) {
     79     if (paint.getTextAlign() == SkPaint::kLeft_Align) {
     80         return;
     81     }
     82 
     83     SkMatrix ident;
     84     ident.reset();
     85     SkAutoGlyphCache autoCache(paint, NULL, &ident);
     86     SkGlyphCache* cache = autoCache.getCache();
     87 
     88     const char* start = reinterpret_cast<const char*>(glyphs);
     89     const char* stop = reinterpret_cast<const char*>(glyphs + len);
     90     SkFixed xAdv = 0, yAdv = 0;
     91 
     92     // TODO(vandebo): This probably needs to take kerning into account.
     93     while (start < stop) {
     94         const SkGlyph& glyph = glyphCacheProc(cache, &start, 0, 0);
     95         xAdv += glyph.fAdvanceX;
     96         yAdv += glyph.fAdvanceY;
     97     };
     98     if (paint.getTextAlign() == SkPaint::kLeft_Align) {
     99         return;
    100     }
    101 
    102     SkScalar xAdj = SkFixedToScalar(xAdv);
    103     SkScalar yAdj = SkFixedToScalar(yAdv);
    104     if (paint.getTextAlign() == SkPaint::kCenter_Align) {
    105         xAdj = SkScalarHalf(xAdj);
    106         yAdj = SkScalarHalf(yAdj);
    107     }
    108     *x = *x - xAdj;
    109     *y = *y - yAdj;
    110 }
    111 
    112 static int max_glyphid_for_typeface(SkTypeface* typeface) {
    113     SkAutoResolveDefaultTypeface autoResolve(typeface);
    114     typeface = autoResolve.get();
    115     return typeface->countGlyphs() - 1;
    116 }
    117 
    118 typedef SkAutoSTMalloc<128, uint16_t> SkGlyphStorage;
    119 
    120 static int force_glyph_encoding(const SkPaint& paint, const void* text,
    121                                 size_t len, SkGlyphStorage* storage,
    122                                 const uint16_t** glyphIDs) {
    123     // Make sure we have a glyph id encoding.
    124     if (paint.getTextEncoding() != SkPaint::kGlyphID_TextEncoding) {
    125         int numGlyphs = paint.textToGlyphs(text, len, NULL);
    126         storage->reset(numGlyphs);
    127         paint.textToGlyphs(text, len, storage->get());
    128         *glyphIDs = storage->get();
    129         return numGlyphs;
    130     }
    131 
    132     // For user supplied glyph ids we need to validate them.
    133     SkASSERT((len & 1) == 0);
    134     int numGlyphs = SkToInt(len / 2);
    135     const uint16_t* input = static_cast<const uint16_t*>(text);
    136 
    137     int maxGlyphID = max_glyphid_for_typeface(paint.getTypeface());
    138     int validated;
    139     for (validated = 0; validated < numGlyphs; ++validated) {
    140         if (input[validated] > maxGlyphID) {
    141             break;
    142         }
    143     }
    144     if (validated >= numGlyphs) {
    145         *glyphIDs = static_cast<const uint16_t*>(text);
    146         return numGlyphs;
    147     }
    148 
    149     // Silently drop anything out of range.
    150     storage->reset(numGlyphs);
    151     if (validated > 0) {
    152         memcpy(storage->get(), input, validated * sizeof(uint16_t));
    153     }
    154 
    155     for (int i = validated; i < numGlyphs; ++i) {
    156         storage->get()[i] = input[i];
    157         if (input[i] > maxGlyphID) {
    158             storage->get()[i] = 0;
    159         }
    160     }
    161     *glyphIDs = storage->get();
    162     return numGlyphs;
    163 }
    164 
    165 static void set_text_transform(SkScalar x, SkScalar y, SkScalar textSkewX,
    166                                SkWStream* content) {
    167     // Flip the text about the x-axis to account for origin swap and include
    168     // the passed parameters.
    169     content->writeText("1 0 ");
    170     SkPDFScalar::Append(0 - textSkewX, content);
    171     content->writeText(" -1 ");
    172     SkPDFScalar::Append(x, content);
    173     content->writeText(" ");
    174     SkPDFScalar::Append(y, content);
    175     content->writeText(" Tm\n");
    176 }
    177 
    178 // It is important to not confuse GraphicStateEntry with SkPDFGraphicState, the
    179 // later being our representation of an object in the PDF file.
    180 struct GraphicStateEntry {
    181     GraphicStateEntry();
    182 
    183     // Compare the fields we care about when setting up a new content entry.
    184     bool compareInitialState(const GraphicStateEntry& b);
    185 
    186     SkMatrix fMatrix;
    187     // We can't do set operations on Paths, though PDF natively supports
    188     // intersect.  If the clip stack does anything other than intersect,
    189     // we have to fall back to the region.  Treat fClipStack as authoritative.
    190     // See http://code.google.com/p/skia/issues/detail?id=221
    191     SkClipStack fClipStack;
    192     SkRegion fClipRegion;
    193 
    194     // When emitting the content entry, we will ensure the graphic state
    195     // is set to these values first.
    196     SkColor fColor;
    197     SkScalar fTextScaleX;  // Zero means we don't care what the value is.
    198     SkPaint::Style fTextFill;  // Only if TextScaleX is non-zero.
    199     int fShaderIndex;
    200     int fGraphicStateIndex;
    201 
    202     // We may change the font (i.e. for Type1 support) within a
    203     // ContentEntry.  This is the one currently in effect, or NULL if none.
    204     SkPDFFont* fFont;
    205     // In PDF, text size has no default value. It is only valid if fFont is
    206     // not NULL.
    207     SkScalar fTextSize;
    208 };
    209 
    210 GraphicStateEntry::GraphicStateEntry() : fColor(SK_ColorBLACK),
    211                                          fTextScaleX(SK_Scalar1),
    212                                          fTextFill(SkPaint::kFill_Style),
    213                                          fShaderIndex(-1),
    214                                          fGraphicStateIndex(-1),
    215                                          fFont(NULL),
    216                                          fTextSize(SK_ScalarNaN) {
    217     fMatrix.reset();
    218 }
    219 
    220 bool GraphicStateEntry::compareInitialState(const GraphicStateEntry& cur) {
    221     return fColor == cur.fColor &&
    222            fShaderIndex == cur.fShaderIndex &&
    223            fGraphicStateIndex == cur.fGraphicStateIndex &&
    224            fMatrix == cur.fMatrix &&
    225            fClipStack == cur.fClipStack &&
    226            (fTextScaleX == 0 ||
    227                (fTextScaleX == cur.fTextScaleX && fTextFill == cur.fTextFill));
    228 }
    229 
    230 class GraphicStackState {
    231 public:
    232     GraphicStackState(const SkClipStack& existingClipStack,
    233                       const SkRegion& existingClipRegion,
    234                       SkWStream* contentStream)
    235             : fStackDepth(0),
    236               fContentStream(contentStream) {
    237         fEntries[0].fClipStack = existingClipStack;
    238         fEntries[0].fClipRegion = existingClipRegion;
    239     }
    240 
    241     void updateClip(const SkClipStack& clipStack, const SkRegion& clipRegion,
    242                     const SkPoint& translation);
    243     void updateMatrix(const SkMatrix& matrix);
    244     void updateDrawingState(const GraphicStateEntry& state);
    245 
    246     void drainStack();
    247 
    248 private:
    249     void push();
    250     void pop();
    251     GraphicStateEntry* currentEntry() { return &fEntries[fStackDepth]; }
    252 
    253     // Conservative limit on save depth, see impl. notes in PDF 1.4 spec.
    254     static const int kMaxStackDepth = 12;
    255     GraphicStateEntry fEntries[kMaxStackDepth + 1];
    256     int fStackDepth;
    257     SkWStream* fContentStream;
    258 };
    259 
    260 void GraphicStackState::drainStack() {
    261     while (fStackDepth) {
    262         pop();
    263     }
    264 }
    265 
    266 void GraphicStackState::push() {
    267     SkASSERT(fStackDepth < kMaxStackDepth);
    268     fContentStream->writeText("q\n");
    269     fStackDepth++;
    270     fEntries[fStackDepth] = fEntries[fStackDepth - 1];
    271 }
    272 
    273 void GraphicStackState::pop() {
    274     SkASSERT(fStackDepth > 0);
    275     fContentStream->writeText("Q\n");
    276     fStackDepth--;
    277 }
    278 
    279 // This function initializes iter to be an iterator on the "stack" argument
    280 // and then skips over the leading entries as specified in prefix.  It requires
    281 // and asserts that "prefix" will be a prefix to "stack."
    282 static void skip_clip_stack_prefix(const SkClipStack& prefix,
    283                                    const SkClipStack& stack,
    284                                    SkClipStack::Iter* iter) {
    285     SkClipStack::B2TIter prefixIter(prefix);
    286     iter->reset(stack, SkClipStack::Iter::kBottom_IterStart);
    287 
    288     const SkClipStack::Element* prefixEntry;
    289     const SkClipStack::Element* iterEntry;
    290 
    291     for (prefixEntry = prefixIter.next(); prefixEntry;
    292             prefixEntry = prefixIter.next()) {
    293         iterEntry = iter->next();
    294         SkASSERT(iterEntry);
    295         // Because of SkClipStack does internal intersection, the last clip
    296         // entry may differ.
    297         if (*prefixEntry != *iterEntry) {
    298             SkASSERT(prefixEntry->getOp() == SkRegion::kIntersect_Op);
    299             SkASSERT(iterEntry->getOp() == SkRegion::kIntersect_Op);
    300             SkASSERT(iterEntry->getType() == prefixEntry->getType());
    301             // back up the iterator by one
    302             iter->prev();
    303             prefixEntry = prefixIter.next();
    304             break;
    305         }
    306     }
    307 
    308     SkASSERT(prefixEntry == NULL);
    309 }
    310 
    311 static void emit_clip(SkPath* clipPath, SkRect* clipRect,
    312                       SkWStream* contentStream) {
    313     SkASSERT(clipPath || clipRect);
    314 
    315     SkPath::FillType clipFill;
    316     if (clipPath) {
    317         SkPDFUtils::EmitPath(*clipPath, SkPaint::kFill_Style, contentStream);
    318         clipFill = clipPath->getFillType();
    319     } else {
    320         SkPDFUtils::AppendRectangle(*clipRect, contentStream);
    321         clipFill = SkPath::kWinding_FillType;
    322     }
    323 
    324     NOT_IMPLEMENTED(clipFill == SkPath::kInverseEvenOdd_FillType, false);
    325     NOT_IMPLEMENTED(clipFill == SkPath::kInverseWinding_FillType, false);
    326     if (clipFill == SkPath::kEvenOdd_FillType) {
    327         contentStream->writeText("W* n\n");
    328     } else {
    329         contentStream->writeText("W n\n");
    330     }
    331 }
    332 
    333 #ifdef SK_PDF_USE_PATHOPS
    334 /* Calculate an inverted path's equivalent non-inverted path, given the
    335  * canvas bounds.
    336  * outPath may alias with invPath (since this is supported by PathOps).
    337  */
    338 static bool calculate_inverse_path(const SkRect& bounds, const SkPath& invPath,
    339                                    SkPath* outPath) {
    340     SkASSERT(invPath.isInverseFillType());
    341 
    342     SkPath clipPath;
    343     clipPath.addRect(bounds);
    344 
    345     return Op(clipPath, invPath, kIntersect_PathOp, outPath);
    346 }
    347 
    348 // Sanity check the numerical values of the SkRegion ops and PathOps ops
    349 // enums so region_op_to_pathops_op can do a straight passthrough cast.
    350 // If these are failing, it may be necessary to make region_op_to_pathops_op
    351 // do more.
    352 SK_COMPILE_ASSERT(SkRegion::kDifference_Op == (int)kDifference_PathOp,
    353                   region_pathop_mismatch);
    354 SK_COMPILE_ASSERT(SkRegion::kIntersect_Op == (int)kIntersect_PathOp,
    355                   region_pathop_mismatch);
    356 SK_COMPILE_ASSERT(SkRegion::kUnion_Op == (int)kUnion_PathOp,
    357                   region_pathop_mismatch);
    358 SK_COMPILE_ASSERT(SkRegion::kXOR_Op == (int)kXOR_PathOp,
    359                   region_pathop_mismatch);
    360 SK_COMPILE_ASSERT(SkRegion::kReverseDifference_Op ==
    361                   (int)kReverseDifference_PathOp,
    362                   region_pathop_mismatch);
    363 
    364 static SkPathOp region_op_to_pathops_op(SkRegion::Op op) {
    365     SkASSERT(op >= 0);
    366     SkASSERT(op <= SkRegion::kReverseDifference_Op);
    367     return (SkPathOp)op;
    368 }
    369 
    370 /* Uses Path Ops to calculate a vector SkPath clip from a clip stack.
    371  * Returns true if successful, or false if not successful.
    372  * If successful, the resulting clip is stored in outClipPath.
    373  * If not successful, outClipPath is undefined, and a fallback method
    374  * should be used.
    375  */
    376 static bool get_clip_stack_path(const SkMatrix& transform,
    377                                 const SkClipStack& clipStack,
    378                                 const SkRegion& clipRegion,
    379                                 SkPath* outClipPath) {
    380     outClipPath->reset();
    381     outClipPath->setFillType(SkPath::kInverseWinding_FillType);
    382 
    383     const SkClipStack::Element* clipEntry;
    384     SkClipStack::Iter iter;
    385     iter.reset(clipStack, SkClipStack::Iter::kBottom_IterStart);
    386     for (clipEntry = iter.next(); clipEntry; clipEntry = iter.next()) {
    387         SkPath entryPath;
    388         if (SkClipStack::Element::kEmpty_Type == clipEntry->getType()) {
    389             outClipPath->reset();
    390             outClipPath->setFillType(SkPath::kInverseWinding_FillType);
    391             continue;
    392         } else {
    393             clipEntry->asPath(&entryPath);
    394         }
    395         entryPath.transform(transform);
    396 
    397         if (SkRegion::kReplace_Op == clipEntry->getOp()) {
    398             *outClipPath = entryPath;
    399         } else {
    400             SkPathOp op = region_op_to_pathops_op(clipEntry->getOp());
    401             if (!Op(*outClipPath, entryPath, op, outClipPath)) {
    402                 return false;
    403             }
    404         }
    405     }
    406 
    407     if (outClipPath->isInverseFillType()) {
    408         // The bounds are slightly outset to ensure this is correct in the
    409         // face of floating-point accuracy and possible SkRegion bitmap
    410         // approximations.
    411         SkRect clipBounds = SkRect::Make(clipRegion.getBounds());
    412         clipBounds.outset(SK_Scalar1, SK_Scalar1);
    413         if (!calculate_inverse_path(clipBounds, *outClipPath, outClipPath)) {
    414             return false;
    415         }
    416     }
    417     return true;
    418 }
    419 #endif
    420 
    421 // TODO(vandebo): Take advantage of SkClipStack::getSaveCount(), the PDF
    422 // graphic state stack, and the fact that we can know all the clips used
    423 // on the page to optimize this.
    424 void GraphicStackState::updateClip(const SkClipStack& clipStack,
    425                                    const SkRegion& clipRegion,
    426                                    const SkPoint& translation) {
    427     if (clipStack == currentEntry()->fClipStack) {
    428         return;
    429     }
    430 
    431     while (fStackDepth > 0) {
    432         pop();
    433         if (clipStack == currentEntry()->fClipStack) {
    434             return;
    435         }
    436     }
    437     push();
    438 
    439     currentEntry()->fClipStack = clipStack;
    440     currentEntry()->fClipRegion = clipRegion;
    441 
    442     SkMatrix transform;
    443     transform.setTranslate(translation.fX, translation.fY);
    444 
    445 #ifdef SK_PDF_USE_PATHOPS
    446     SkPath clipPath;
    447     if (get_clip_stack_path(transform, clipStack, clipRegion, &clipPath)) {
    448         emit_clip(&clipPath, NULL, fContentStream);
    449         return;
    450     }
    451 #endif
    452     // gsState->initialEntry()->fClipStack/Region specifies the clip that has
    453     // already been applied.  (If this is a top level device, then it specifies
    454     // a clip to the content area.  If this is a layer, then it specifies
    455     // the clip in effect when the layer was created.)  There's no need to
    456     // reapply that clip; SKCanvas's SkDrawIter will draw anything outside the
    457     // initial clip on the parent layer.  (This means there's a bug if the user
    458     // expands the clip and then uses any xfer mode that uses dst:
    459     // http://code.google.com/p/skia/issues/detail?id=228 )
    460     SkClipStack::Iter iter;
    461     skip_clip_stack_prefix(fEntries[0].fClipStack, clipStack, &iter);
    462 
    463     // If the clip stack does anything other than intersect or if it uses
    464     // an inverse fill type, we have to fall back to the clip region.
    465     bool needRegion = false;
    466     const SkClipStack::Element* clipEntry;
    467     for (clipEntry = iter.next(); clipEntry; clipEntry = iter.next()) {
    468         if (clipEntry->getOp() != SkRegion::kIntersect_Op ||
    469                 clipEntry->isInverseFilled()) {
    470             needRegion = true;
    471             break;
    472         }
    473     }
    474 
    475     if (needRegion) {
    476         SkPath clipPath;
    477         SkAssertResult(clipRegion.getBoundaryPath(&clipPath));
    478         emit_clip(&clipPath, NULL, fContentStream);
    479     } else {
    480         skip_clip_stack_prefix(fEntries[0].fClipStack, clipStack, &iter);
    481         const SkClipStack::Element* clipEntry;
    482         for (clipEntry = iter.next(); clipEntry; clipEntry = iter.next()) {
    483             SkASSERT(clipEntry->getOp() == SkRegion::kIntersect_Op);
    484             switch (clipEntry->getType()) {
    485                 case SkClipStack::Element::kRect_Type: {
    486                     SkRect translatedClip;
    487                     transform.mapRect(&translatedClip, clipEntry->getRect());
    488                     emit_clip(NULL, &translatedClip, fContentStream);
    489                     break;
    490                 }
    491                 default: {
    492                     SkPath translatedPath;
    493                     clipEntry->asPath(&translatedPath);
    494                     translatedPath.transform(transform, &translatedPath);
    495                     emit_clip(&translatedPath, NULL, fContentStream);
    496                     break;
    497                 }
    498             }
    499         }
    500     }
    501 }
    502 
    503 void GraphicStackState::updateMatrix(const SkMatrix& matrix) {
    504     if (matrix == currentEntry()->fMatrix) {
    505         return;
    506     }
    507 
    508     if (currentEntry()->fMatrix.getType() != SkMatrix::kIdentity_Mask) {
    509         SkASSERT(fStackDepth > 0);
    510         SkASSERT(fEntries[fStackDepth].fClipStack ==
    511                  fEntries[fStackDepth -1].fClipStack);
    512         pop();
    513 
    514         SkASSERT(currentEntry()->fMatrix.getType() == SkMatrix::kIdentity_Mask);
    515     }
    516     if (matrix.getType() == SkMatrix::kIdentity_Mask) {
    517         return;
    518     }
    519 
    520     push();
    521     SkPDFUtils::AppendTransform(matrix, fContentStream);
    522     currentEntry()->fMatrix = matrix;
    523 }
    524 
    525 void GraphicStackState::updateDrawingState(const GraphicStateEntry& state) {
    526     // PDF treats a shader as a color, so we only set one or the other.
    527     if (state.fShaderIndex >= 0) {
    528         if (state.fShaderIndex != currentEntry()->fShaderIndex) {
    529             SkPDFUtils::ApplyPattern(state.fShaderIndex, fContentStream);
    530             currentEntry()->fShaderIndex = state.fShaderIndex;
    531         }
    532     } else {
    533         if (state.fColor != currentEntry()->fColor ||
    534                 currentEntry()->fShaderIndex >= 0) {
    535             emit_pdf_color(state.fColor, fContentStream);
    536             fContentStream->writeText("RG ");
    537             emit_pdf_color(state.fColor, fContentStream);
    538             fContentStream->writeText("rg\n");
    539             currentEntry()->fColor = state.fColor;
    540             currentEntry()->fShaderIndex = -1;
    541         }
    542     }
    543 
    544     if (state.fGraphicStateIndex != currentEntry()->fGraphicStateIndex) {
    545         SkPDFUtils::ApplyGraphicState(state.fGraphicStateIndex, fContentStream);
    546         currentEntry()->fGraphicStateIndex = state.fGraphicStateIndex;
    547     }
    548 
    549     if (state.fTextScaleX) {
    550         if (state.fTextScaleX != currentEntry()->fTextScaleX) {
    551             SkScalar pdfScale = SkScalarMul(state.fTextScaleX,
    552                                             SkIntToScalar(100));
    553             SkPDFScalar::Append(pdfScale, fContentStream);
    554             fContentStream->writeText(" Tz\n");
    555             currentEntry()->fTextScaleX = state.fTextScaleX;
    556         }
    557         if (state.fTextFill != currentEntry()->fTextFill) {
    558             SK_COMPILE_ASSERT(SkPaint::kFill_Style == 0, enum_must_match_value);
    559             SK_COMPILE_ASSERT(SkPaint::kStroke_Style == 1,
    560                               enum_must_match_value);
    561             SK_COMPILE_ASSERT(SkPaint::kStrokeAndFill_Style == 2,
    562                               enum_must_match_value);
    563             fContentStream->writeDecAsText(state.fTextFill);
    564             fContentStream->writeText(" Tr\n");
    565             currentEntry()->fTextFill = state.fTextFill;
    566         }
    567     }
    568 }
    569 
    570 SkBaseDevice* SkPDFDevice::onCreateDevice(const SkImageInfo& info, Usage usage) {
    571     // PDF does not support image filters, so render them on CPU.
    572     // Note that this rendering is done at "screen" resolution (100dpi), not
    573     // printer resolution.
    574     // FIXME: It may be possible to express some filters natively using PDF
    575     // to improve quality and file size (http://skbug.com/3043)
    576     if (kImageFilter_Usage == usage) {
    577         return SkBitmapDevice::Create(info);
    578     }
    579 
    580     SkMatrix initialTransform;
    581     initialTransform.reset();
    582     SkISize size = SkISize::Make(info.width(), info.height());
    583     return SkNEW_ARGS(SkPDFDevice, (size, size, initialTransform));
    584 }
    585 
    586 
    587 struct ContentEntry {
    588     GraphicStateEntry fState;
    589     SkDynamicMemoryWStream fContent;
    590     SkAutoTDelete<ContentEntry> fNext;
    591 
    592     // If the stack is too deep we could get Stack Overflow.
    593     // So we manually destruct the object.
    594     ~ContentEntry() {
    595         ContentEntry* val = fNext.detach();
    596         while (val != NULL) {
    597             ContentEntry* valNext = val->fNext.detach();
    598             // When the destructor is called, fNext is NULL and exits.
    599             delete val;
    600             val = valNext;
    601         }
    602     }
    603 };
    604 
    605 // A helper class to automatically finish a ContentEntry at the end of a
    606 // drawing method and maintain the state needed between set up and finish.
    607 class ScopedContentEntry {
    608 public:
    609     ScopedContentEntry(SkPDFDevice* device, const SkDraw& draw,
    610                        const SkPaint& paint, bool hasText = false)
    611         : fDevice(device),
    612           fContentEntry(NULL),
    613           fXfermode(SkXfermode::kSrcOver_Mode),
    614           fDstFormXObject(NULL) {
    615         init(draw.fClipStack, *draw.fClip, *draw.fMatrix, paint, hasText);
    616     }
    617     ScopedContentEntry(SkPDFDevice* device, const SkClipStack* clipStack,
    618                        const SkRegion& clipRegion, const SkMatrix& matrix,
    619                        const SkPaint& paint, bool hasText = false)
    620         : fDevice(device),
    621           fContentEntry(NULL),
    622           fXfermode(SkXfermode::kSrcOver_Mode),
    623           fDstFormXObject(NULL) {
    624         init(clipStack, clipRegion, matrix, paint, hasText);
    625     }
    626 
    627     ~ScopedContentEntry() {
    628         if (fContentEntry) {
    629             SkPath* shape = &fShape;
    630             if (shape->isEmpty()) {
    631                 shape = NULL;
    632             }
    633             fDevice->finishContentEntry(fXfermode, fDstFormXObject, shape);
    634         }
    635         SkSafeUnref(fDstFormXObject);
    636     }
    637 
    638     ContentEntry* entry() { return fContentEntry; }
    639 
    640     /* Returns true when we explicitly need the shape of the drawing. */
    641     bool needShape() {
    642         switch (fXfermode) {
    643             case SkXfermode::kClear_Mode:
    644             case SkXfermode::kSrc_Mode:
    645             case SkXfermode::kSrcIn_Mode:
    646             case SkXfermode::kSrcOut_Mode:
    647             case SkXfermode::kDstIn_Mode:
    648             case SkXfermode::kDstOut_Mode:
    649             case SkXfermode::kSrcATop_Mode:
    650             case SkXfermode::kDstATop_Mode:
    651             case SkXfermode::kModulate_Mode:
    652                 return true;
    653             default:
    654                 return false;
    655         }
    656     }
    657 
    658     /* Returns true unless we only need the shape of the drawing. */
    659     bool needSource() {
    660         if (fXfermode == SkXfermode::kClear_Mode) {
    661             return false;
    662         }
    663         return true;
    664     }
    665 
    666     /* If the shape is different than the alpha component of the content, then
    667      * setShape should be called with the shape.  In particular, images and
    668      * devices have rectangular shape.
    669      */
    670     void setShape(const SkPath& shape) {
    671         fShape = shape;
    672     }
    673 
    674 private:
    675     SkPDFDevice* fDevice;
    676     ContentEntry* fContentEntry;
    677     SkXfermode::Mode fXfermode;
    678     SkPDFFormXObject* fDstFormXObject;
    679     SkPath fShape;
    680 
    681     void init(const SkClipStack* clipStack, const SkRegion& clipRegion,
    682               const SkMatrix& matrix, const SkPaint& paint, bool hasText) {
    683         // Shape has to be flatten before we get here.
    684         if (matrix.hasPerspective()) {
    685             NOT_IMPLEMENTED(!matrix.hasPerspective(), false);
    686             return;
    687         }
    688         if (paint.getXfermode()) {
    689             paint.getXfermode()->asMode(&fXfermode);
    690         }
    691         fContentEntry = fDevice->setUpContentEntry(clipStack, clipRegion,
    692                                                    matrix, paint, hasText,
    693                                                    &fDstFormXObject);
    694     }
    695 };
    696 
    697 ////////////////////////////////////////////////////////////////////////////////
    698 
    699 static inline SkImageInfo make_content_info(const SkISize& contentSize,
    700                                             const SkMatrix* initialTransform) {
    701     SkImageInfo info;
    702     if (initialTransform) {
    703         // Compute the size of the drawing area.
    704         SkVector drawingSize;
    705         SkMatrix inverse;
    706         drawingSize.set(SkIntToScalar(contentSize.fWidth),
    707                         SkIntToScalar(contentSize.fHeight));
    708         if (!initialTransform->invert(&inverse)) {
    709             // This shouldn't happen, initial transform should be invertible.
    710             SkASSERT(false);
    711             inverse.reset();
    712         }
    713         inverse.mapVectors(&drawingSize, 1);
    714         SkISize size = SkSize::Make(drawingSize.fX, drawingSize.fY).toRound();
    715         info = SkImageInfo::MakeUnknown(abs(size.fWidth), abs(size.fHeight));
    716     } else {
    717         info = SkImageInfo::MakeUnknown(abs(contentSize.fWidth),
    718                                         abs(contentSize.fHeight));
    719     }
    720     return info;
    721 }
    722 
    723 // TODO(vandebo) change pageSize to SkSize.
    724 SkPDFDevice::SkPDFDevice(const SkISize& pageSize, const SkISize& contentSize,
    725                          const SkMatrix& initialTransform)
    726     : fPageSize(pageSize)
    727     , fContentSize(contentSize)
    728     , fLastContentEntry(NULL)
    729     , fLastMarginContentEntry(NULL)
    730     , fClipStack(NULL)
    731     , fEncoder(NULL)
    732     , fRasterDpi(72.0f)
    733 {
    734     const SkImageInfo info = make_content_info(contentSize, &initialTransform);
    735 
    736     // Just report that PDF does not supports perspective in the
    737     // initial transform.
    738     NOT_IMPLEMENTED(initialTransform.hasPerspective(), true);
    739 
    740     // Skia generally uses the top left as the origin but PDF natively has the
    741     // origin at the bottom left. This matrix corrects for that.  But that only
    742     // needs to be done once, we don't do it when layering.
    743     fInitialTransform.setTranslate(0, SkIntToScalar(pageSize.fHeight));
    744     fInitialTransform.preScale(SK_Scalar1, -SK_Scalar1);
    745     fInitialTransform.preConcat(initialTransform);
    746     fLegacyBitmap.setInfo(info);
    747 
    748     SkIRect existingClip = SkIRect::MakeWH(info.width(), info.height());
    749     fExistingClipRegion.setRect(existingClip);
    750     this->init();
    751 }
    752 
    753 // TODO(vandebo) change layerSize to SkSize.
    754 SkPDFDevice::SkPDFDevice(const SkISize& layerSize,
    755                          const SkClipStack& existingClipStack,
    756                          const SkRegion& existingClipRegion)
    757     : fPageSize(layerSize)
    758     , fContentSize(layerSize)
    759     , fExistingClipStack(existingClipStack)
    760     , fExistingClipRegion(existingClipRegion)
    761     , fLastContentEntry(NULL)
    762     , fLastMarginContentEntry(NULL)
    763     , fClipStack(NULL)
    764     , fEncoder(NULL)
    765     , fRasterDpi(72.0f)
    766 {
    767     fInitialTransform.reset();
    768     fLegacyBitmap.setInfo(make_content_info(layerSize, NULL));
    769 
    770     this->init();
    771 }
    772 
    773 SkPDFDevice::~SkPDFDevice() {
    774     this->cleanUp(true);
    775 }
    776 
    777 void SkPDFDevice::init() {
    778     fAnnotations = NULL;
    779     fResourceDict = NULL;
    780     fContentEntries.free();
    781     fLastContentEntry = NULL;
    782     fMarginContentEntries.free();
    783     fLastMarginContentEntry = NULL;
    784     fDrawingArea = kContent_DrawingArea;
    785     if (fFontGlyphUsage.get() == NULL) {
    786         fFontGlyphUsage.reset(new SkPDFGlyphSetMap());
    787     }
    788 }
    789 
    790 void SkPDFDevice::cleanUp(bool clearFontUsage) {
    791     fGraphicStateResources.unrefAll();
    792     fXObjectResources.unrefAll();
    793     fFontResources.unrefAll();
    794     fShaderResources.unrefAll();
    795     SkSafeUnref(fAnnotations);
    796     SkSafeUnref(fResourceDict);
    797     fNamedDestinations.deleteAll();
    798 
    799     if (clearFontUsage) {
    800         fFontGlyphUsage->reset();
    801     }
    802 }
    803 
    804 void SkPDFDevice::clear(SkColor color) {
    805     this->cleanUp(true);
    806     this->init();
    807 
    808     SkPaint paint;
    809     paint.setColor(color);
    810     paint.setStyle(SkPaint::kFill_Style);
    811     SkMatrix identity;
    812     identity.reset();
    813     ScopedContentEntry content(this, &fExistingClipStack, fExistingClipRegion,
    814                                identity, paint);
    815     internalDrawPaint(paint, content.entry());
    816 }
    817 
    818 void SkPDFDevice::drawPaint(const SkDraw& d, const SkPaint& paint) {
    819     SkPaint newPaint = paint;
    820     newPaint.setStyle(SkPaint::kFill_Style);
    821     ScopedContentEntry content(this, d, newPaint);
    822     internalDrawPaint(newPaint, content.entry());
    823 }
    824 
    825 void SkPDFDevice::internalDrawPaint(const SkPaint& paint,
    826                                     ContentEntry* contentEntry) {
    827     if (!contentEntry) {
    828         return;
    829     }
    830     SkRect bbox = SkRect::MakeWH(SkIntToScalar(this->width()),
    831                                  SkIntToScalar(this->height()));
    832     SkMatrix inverse;
    833     if (!contentEntry->fState.fMatrix.invert(&inverse)) {
    834         return;
    835     }
    836     inverse.mapRect(&bbox);
    837 
    838     SkPDFUtils::AppendRectangle(bbox, &contentEntry->fContent);
    839     SkPDFUtils::PaintPath(paint.getStyle(), SkPath::kWinding_FillType,
    840                           &contentEntry->fContent);
    841 }
    842 
    843 void SkPDFDevice::drawPoints(const SkDraw& d, SkCanvas::PointMode mode,
    844                              size_t count, const SkPoint* points,
    845                              const SkPaint& passedPaint) {
    846     if (count == 0) {
    847         return;
    848     }
    849 
    850     if (handlePointAnnotation(points, count, *d.fMatrix, passedPaint)) {
    851         return;
    852     }
    853 
    854     // SkDraw::drawPoints converts to multiple calls to fDevice->drawPath.
    855     // We only use this when there's a path effect because of the overhead
    856     // of multiple calls to setUpContentEntry it causes.
    857     if (passedPaint.getPathEffect()) {
    858         if (d.fClip->isEmpty()) {
    859             return;
    860         }
    861         SkDraw pointDraw(d);
    862         pointDraw.fDevice = this;
    863         pointDraw.drawPoints(mode, count, points, passedPaint, true);
    864         return;
    865     }
    866 
    867     const SkPaint* paint = &passedPaint;
    868     SkPaint modifiedPaint;
    869 
    870     if (mode == SkCanvas::kPoints_PointMode &&
    871             paint->getStrokeCap() != SkPaint::kRound_Cap) {
    872         modifiedPaint = *paint;
    873         paint = &modifiedPaint;
    874         if (paint->getStrokeWidth()) {
    875             // PDF won't draw a single point with square/butt caps because the
    876             // orientation is ambiguous.  Draw a rectangle instead.
    877             modifiedPaint.setStyle(SkPaint::kFill_Style);
    878             SkScalar strokeWidth = paint->getStrokeWidth();
    879             SkScalar halfStroke = SkScalarHalf(strokeWidth);
    880             for (size_t i = 0; i < count; i++) {
    881                 SkRect r = SkRect::MakeXYWH(points[i].fX, points[i].fY, 0, 0);
    882                 r.inset(-halfStroke, -halfStroke);
    883                 drawRect(d, r, modifiedPaint);
    884             }
    885             return;
    886         } else {
    887             modifiedPaint.setStrokeCap(SkPaint::kRound_Cap);
    888         }
    889     }
    890 
    891     ScopedContentEntry content(this, d, *paint);
    892     if (!content.entry()) {
    893         return;
    894     }
    895 
    896     switch (mode) {
    897         case SkCanvas::kPolygon_PointMode:
    898             SkPDFUtils::MoveTo(points[0].fX, points[0].fY,
    899                                &content.entry()->fContent);
    900             for (size_t i = 1; i < count; i++) {
    901                 SkPDFUtils::AppendLine(points[i].fX, points[i].fY,
    902                                        &content.entry()->fContent);
    903             }
    904             SkPDFUtils::StrokePath(&content.entry()->fContent);
    905             break;
    906         case SkCanvas::kLines_PointMode:
    907             for (size_t i = 0; i < count/2; i++) {
    908                 SkPDFUtils::MoveTo(points[i * 2].fX, points[i * 2].fY,
    909                                    &content.entry()->fContent);
    910                 SkPDFUtils::AppendLine(points[i * 2 + 1].fX,
    911                                        points[i * 2 + 1].fY,
    912                                        &content.entry()->fContent);
    913                 SkPDFUtils::StrokePath(&content.entry()->fContent);
    914             }
    915             break;
    916         case SkCanvas::kPoints_PointMode:
    917             SkASSERT(paint->getStrokeCap() == SkPaint::kRound_Cap);
    918             for (size_t i = 0; i < count; i++) {
    919                 SkPDFUtils::MoveTo(points[i].fX, points[i].fY,
    920                                    &content.entry()->fContent);
    921                 SkPDFUtils::ClosePath(&content.entry()->fContent);
    922                 SkPDFUtils::StrokePath(&content.entry()->fContent);
    923             }
    924             break;
    925         default:
    926             SkASSERT(false);
    927     }
    928 }
    929 
    930 void SkPDFDevice::drawRect(const SkDraw& d, const SkRect& rect,
    931                            const SkPaint& paint) {
    932     SkRect r = rect;
    933     r.sort();
    934 
    935     if (paint.getPathEffect()) {
    936         if (d.fClip->isEmpty()) {
    937             return;
    938         }
    939         SkPath path;
    940         path.addRect(r);
    941         drawPath(d, path, paint, NULL, true);
    942         return;
    943     }
    944 
    945     if (handleRectAnnotation(r, *d.fMatrix, paint)) {
    946         return;
    947     }
    948 
    949     ScopedContentEntry content(this, d, paint);
    950     if (!content.entry()) {
    951         return;
    952     }
    953     SkPDFUtils::AppendRectangle(r, &content.entry()->fContent);
    954     SkPDFUtils::PaintPath(paint.getStyle(), SkPath::kWinding_FillType,
    955                           &content.entry()->fContent);
    956 }
    957 
    958 void SkPDFDevice::drawRRect(const SkDraw& draw, const SkRRect& rrect, const SkPaint& paint) {
    959     SkPath  path;
    960     path.addRRect(rrect);
    961     this->drawPath(draw, path, paint, NULL, true);
    962 }
    963 
    964 void SkPDFDevice::drawOval(const SkDraw& draw, const SkRect& oval, const SkPaint& paint) {
    965     SkPath  path;
    966     path.addOval(oval);
    967     this->drawPath(draw, path, paint, NULL, true);
    968 }
    969 
    970 void SkPDFDevice::drawPath(const SkDraw& d, const SkPath& origPath,
    971                            const SkPaint& paint, const SkMatrix* prePathMatrix,
    972                            bool pathIsMutable) {
    973     SkPath modifiedPath;
    974     SkPath* pathPtr = const_cast<SkPath*>(&origPath);
    975 
    976     SkMatrix matrix = *d.fMatrix;
    977     if (prePathMatrix) {
    978         if (paint.getPathEffect() || paint.getStyle() != SkPaint::kFill_Style) {
    979             if (!pathIsMutable) {
    980                 pathPtr = &modifiedPath;
    981                 pathIsMutable = true;
    982             }
    983             origPath.transform(*prePathMatrix, pathPtr);
    984         } else {
    985             matrix.preConcat(*prePathMatrix);
    986         }
    987     }
    988 
    989     if (paint.getPathEffect()) {
    990         if (d.fClip->isEmpty()) {
    991             return;
    992         }
    993         if (!pathIsMutable) {
    994             pathPtr = &modifiedPath;
    995             pathIsMutable = true;
    996         }
    997         bool fill = paint.getFillPath(origPath, pathPtr);
    998 
    999         SkPaint noEffectPaint(paint);
   1000         noEffectPaint.setPathEffect(NULL);
   1001         if (fill) {
   1002             noEffectPaint.setStyle(SkPaint::kFill_Style);
   1003         } else {
   1004             noEffectPaint.setStyle(SkPaint::kStroke_Style);
   1005             noEffectPaint.setStrokeWidth(0);
   1006         }
   1007         drawPath(d, *pathPtr, noEffectPaint, NULL, true);
   1008         return;
   1009     }
   1010 
   1011 #ifdef SK_PDF_USE_PATHOPS
   1012     if (handleInversePath(d, origPath, paint, pathIsMutable, prePathMatrix)) {
   1013         return;
   1014     }
   1015 #endif
   1016 
   1017     if (handleRectAnnotation(pathPtr->getBounds(), matrix, paint)) {
   1018         return;
   1019     }
   1020 
   1021     ScopedContentEntry content(this, d.fClipStack, *d.fClip, matrix, paint);
   1022     if (!content.entry()) {
   1023         return;
   1024     }
   1025     SkPDFUtils::EmitPath(*pathPtr, paint.getStyle(),
   1026                          &content.entry()->fContent);
   1027     SkPDFUtils::PaintPath(paint.getStyle(), pathPtr->getFillType(),
   1028                           &content.entry()->fContent);
   1029 }
   1030 
   1031 void SkPDFDevice::drawBitmapRect(const SkDraw& draw, const SkBitmap& bitmap,
   1032                                  const SkRect* src, const SkRect& dst,
   1033                                  const SkPaint& paint,
   1034                                  SkCanvas::DrawBitmapRectFlags flags) {
   1035     // TODO: this code path must be updated to respect the flags parameter
   1036     SkMatrix    matrix;
   1037     SkRect      bitmapBounds, tmpSrc, tmpDst;
   1038     SkBitmap    tmpBitmap;
   1039 
   1040     bitmapBounds.isetWH(bitmap.width(), bitmap.height());
   1041 
   1042     // Compute matrix from the two rectangles
   1043     if (src) {
   1044         tmpSrc = *src;
   1045     } else {
   1046         tmpSrc = bitmapBounds;
   1047     }
   1048     matrix.setRectToRect(tmpSrc, dst, SkMatrix::kFill_ScaleToFit);
   1049 
   1050     const SkBitmap* bitmapPtr = &bitmap;
   1051 
   1052     // clip the tmpSrc to the bounds of the bitmap, and recompute dstRect if
   1053     // needed (if the src was clipped). No check needed if src==null.
   1054     if (src) {
   1055         if (!bitmapBounds.contains(*src)) {
   1056             if (!tmpSrc.intersect(bitmapBounds)) {
   1057                 return; // nothing to draw
   1058             }
   1059             // recompute dst, based on the smaller tmpSrc
   1060             matrix.mapRect(&tmpDst, tmpSrc);
   1061         }
   1062 
   1063         // since we may need to clamp to the borders of the src rect within
   1064         // the bitmap, we extract a subset.
   1065         // TODO: make sure this is handled in drawBitmap and remove from here.
   1066         SkIRect srcIR;
   1067         tmpSrc.roundOut(&srcIR);
   1068         if (!bitmap.extractSubset(&tmpBitmap, srcIR)) {
   1069             return;
   1070         }
   1071         bitmapPtr = &tmpBitmap;
   1072 
   1073         // Since we did an extract, we need to adjust the matrix accordingly
   1074         SkScalar dx = 0, dy = 0;
   1075         if (srcIR.fLeft > 0) {
   1076             dx = SkIntToScalar(srcIR.fLeft);
   1077         }
   1078         if (srcIR.fTop > 0) {
   1079             dy = SkIntToScalar(srcIR.fTop);
   1080         }
   1081         if (dx || dy) {
   1082             matrix.preTranslate(dx, dy);
   1083         }
   1084     }
   1085     this->drawBitmap(draw, *bitmapPtr, matrix, paint);
   1086 }
   1087 
   1088 void SkPDFDevice::drawBitmap(const SkDraw& d, const SkBitmap& bitmap,
   1089                              const SkMatrix& matrix, const SkPaint& paint) {
   1090     if (d.fClip->isEmpty()) {
   1091         return;
   1092     }
   1093 
   1094     SkMatrix transform = matrix;
   1095     transform.postConcat(*d.fMatrix);
   1096     this->internalDrawBitmap(transform, d.fClipStack, *d.fClip, bitmap, NULL,
   1097                              paint);
   1098 }
   1099 
   1100 void SkPDFDevice::drawSprite(const SkDraw& d, const SkBitmap& bitmap,
   1101                              int x, int y, const SkPaint& paint) {
   1102     if (d.fClip->isEmpty()) {
   1103         return;
   1104     }
   1105 
   1106     SkMatrix matrix;
   1107     matrix.setTranslate(SkIntToScalar(x), SkIntToScalar(y));
   1108     this->internalDrawBitmap(matrix, d.fClipStack, *d.fClip, bitmap, NULL,
   1109                              paint);
   1110 }
   1111 
   1112 void SkPDFDevice::drawText(const SkDraw& d, const void* text, size_t len,
   1113                            SkScalar x, SkScalar y, const SkPaint& paint) {
   1114     NOT_IMPLEMENTED(paint.getMaskFilter() != NULL, false);
   1115     if (paint.getMaskFilter() != NULL) {
   1116         // Don't pretend we support drawing MaskFilters, it makes for artifacts
   1117         // making text unreadable (e.g. same text twice when using CSS shadows).
   1118         return;
   1119     }
   1120     SkPaint textPaint = calculate_text_paint(paint);
   1121     ScopedContentEntry content(this, d, textPaint, true);
   1122     if (!content.entry()) {
   1123         return;
   1124     }
   1125 
   1126     SkGlyphStorage storage(0);
   1127     const uint16_t* glyphIDs = NULL;
   1128     int numGlyphs = force_glyph_encoding(paint, text, len, &storage, &glyphIDs);
   1129     textPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
   1130 
   1131     SkDrawCacheProc glyphCacheProc = textPaint.getDrawCacheProc();
   1132     align_text(glyphCacheProc, textPaint, glyphIDs, numGlyphs, &x, &y);
   1133     content.entry()->fContent.writeText("BT\n");
   1134     set_text_transform(x, y, textPaint.getTextSkewX(),
   1135                        &content.entry()->fContent);
   1136     int consumedGlyphCount = 0;
   1137     while (numGlyphs > consumedGlyphCount) {
   1138         updateFont(textPaint, glyphIDs[consumedGlyphCount], content.entry());
   1139         SkPDFFont* font = content.entry()->fState.fFont;
   1140         //TODO: the const_cast here is a bug if the encoding started out as glyph encoding.
   1141         int availableGlyphs =
   1142             font->glyphsToPDFFontEncoding(const_cast<uint16_t*>(glyphIDs) + consumedGlyphCount,
   1143                                           numGlyphs - consumedGlyphCount);
   1144         fFontGlyphUsage->noteGlyphUsage(font, glyphIDs + consumedGlyphCount,
   1145                                         availableGlyphs);
   1146         SkString encodedString =
   1147             SkPDFString::FormatString(glyphIDs + consumedGlyphCount,
   1148                                       availableGlyphs, font->multiByteGlyphs());
   1149         content.entry()->fContent.writeText(encodedString.c_str());
   1150         consumedGlyphCount += availableGlyphs;
   1151         content.entry()->fContent.writeText(" Tj\n");
   1152     }
   1153     content.entry()->fContent.writeText("ET\n");
   1154 }
   1155 
   1156 void SkPDFDevice::drawPosText(const SkDraw& d, const void* text, size_t len,
   1157                               const SkScalar pos[], SkScalar constY,
   1158                               int scalarsPerPos, const SkPaint& paint) {
   1159     NOT_IMPLEMENTED(paint.getMaskFilter() != NULL, false);
   1160     if (paint.getMaskFilter() != NULL) {
   1161         // Don't pretend we support drawing MaskFilters, it makes for artifacts
   1162         // making text unreadable (e.g. same text twice when using CSS shadows).
   1163         return;
   1164     }
   1165     SkASSERT(1 == scalarsPerPos || 2 == scalarsPerPos);
   1166     SkPaint textPaint = calculate_text_paint(paint);
   1167     ScopedContentEntry content(this, d, textPaint, true);
   1168     if (!content.entry()) {
   1169         return;
   1170     }
   1171 
   1172     SkGlyphStorage storage(0);
   1173     const uint16_t* glyphIDs = NULL;
   1174     size_t numGlyphs = force_glyph_encoding(paint, text, len, &storage, &glyphIDs);
   1175     textPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
   1176 
   1177     SkDrawCacheProc glyphCacheProc = textPaint.getDrawCacheProc();
   1178     content.entry()->fContent.writeText("BT\n");
   1179     updateFont(textPaint, glyphIDs[0], content.entry());
   1180     for (size_t i = 0; i < numGlyphs; i++) {
   1181         SkPDFFont* font = content.entry()->fState.fFont;
   1182         uint16_t encodedValue = glyphIDs[i];
   1183         if (font->glyphsToPDFFontEncoding(&encodedValue, 1) != 1) {
   1184             // The current pdf font cannot encode the current glyph.
   1185             // Try to get a pdf font which can encode the current glyph.
   1186             updateFont(textPaint, glyphIDs[i], content.entry());
   1187             font = content.entry()->fState.fFont;
   1188             if (font->glyphsToPDFFontEncoding(&encodedValue, 1) != 1) {
   1189                 SkDEBUGFAIL("PDF could not encode glyph.");
   1190                 continue;
   1191             }
   1192         }
   1193 
   1194         fFontGlyphUsage->noteGlyphUsage(font, &encodedValue, 1);
   1195         SkScalar x = pos[i * scalarsPerPos];
   1196         SkScalar y = scalarsPerPos == 1 ? constY : pos[i * scalarsPerPos + 1];
   1197         align_text(glyphCacheProc, textPaint, glyphIDs + i, 1, &x, &y);
   1198         set_text_transform(x, y, textPaint.getTextSkewX(), &content.entry()->fContent);
   1199         SkString encodedString =
   1200             SkPDFString::FormatString(&encodedValue, 1, font->multiByteGlyphs());
   1201         content.entry()->fContent.writeText(encodedString.c_str());
   1202         content.entry()->fContent.writeText(" Tj\n");
   1203     }
   1204     content.entry()->fContent.writeText("ET\n");
   1205 }
   1206 
   1207 void SkPDFDevice::drawTextOnPath(const SkDraw& d, const void* text, size_t len,
   1208                                  const SkPath& path, const SkMatrix* matrix,
   1209                                  const SkPaint& paint) {
   1210     if (d.fClip->isEmpty()) {
   1211         return;
   1212     }
   1213     d.drawTextOnPath((const char*)text, len, path, matrix, paint);
   1214 }
   1215 
   1216 void SkPDFDevice::drawVertices(const SkDraw& d, SkCanvas::VertexMode,
   1217                                int vertexCount, const SkPoint verts[],
   1218                                const SkPoint texs[], const SkColor colors[],
   1219                                SkXfermode* xmode, const uint16_t indices[],
   1220                                int indexCount, const SkPaint& paint) {
   1221     if (d.fClip->isEmpty()) {
   1222         return;
   1223     }
   1224     // TODO: implement drawVertices
   1225 }
   1226 
   1227 void SkPDFDevice::drawDevice(const SkDraw& d, SkBaseDevice* device,
   1228                              int x, int y, const SkPaint& paint) {
   1229     // our onCreateDevice() always creates SkPDFDevice subclasses.
   1230     SkPDFDevice* pdfDevice = static_cast<SkPDFDevice*>(device);
   1231     if (pdfDevice->isContentEmpty()) {
   1232         return;
   1233     }
   1234 
   1235     SkMatrix matrix;
   1236     matrix.setTranslate(SkIntToScalar(x), SkIntToScalar(y));
   1237     ScopedContentEntry content(this, d.fClipStack, *d.fClip, matrix, paint);
   1238     if (!content.entry()) {
   1239         return;
   1240     }
   1241     if (content.needShape()) {
   1242         SkPath shape;
   1243         shape.addRect(SkRect::MakeXYWH(SkIntToScalar(x), SkIntToScalar(y),
   1244                                        SkIntToScalar(device->width()),
   1245                                        SkIntToScalar(device->height())));
   1246         content.setShape(shape);
   1247     }
   1248     if (!content.needSource()) {
   1249         return;
   1250     }
   1251 
   1252     SkAutoTUnref<SkPDFFormXObject> xObject(new SkPDFFormXObject(pdfDevice));
   1253     SkPDFUtils::DrawFormXObject(this->addXObjectResource(xObject.get()),
   1254                                 &content.entry()->fContent);
   1255 
   1256     // Merge glyph sets from the drawn device.
   1257     fFontGlyphUsage->merge(pdfDevice->getFontGlyphUsage());
   1258 }
   1259 
   1260 SkImageInfo SkPDFDevice::imageInfo() const {
   1261     return fLegacyBitmap.info();
   1262 }
   1263 
   1264 void SkPDFDevice::onAttachToCanvas(SkCanvas* canvas) {
   1265     INHERITED::onAttachToCanvas(canvas);
   1266 
   1267     // Canvas promises that this ptr is valid until onDetachFromCanvas is called
   1268     fClipStack = canvas->getClipStack();
   1269 }
   1270 
   1271 void SkPDFDevice::onDetachFromCanvas() {
   1272     INHERITED::onDetachFromCanvas();
   1273 
   1274     fClipStack = NULL;
   1275 }
   1276 
   1277 SkSurface* SkPDFDevice::newSurface(const SkImageInfo& info, const SkSurfaceProps& props) {
   1278     return SkSurface::NewRaster(info, &props);
   1279 }
   1280 
   1281 ContentEntry* SkPDFDevice::getLastContentEntry() {
   1282     if (fDrawingArea == kContent_DrawingArea) {
   1283         return fLastContentEntry;
   1284     } else {
   1285         return fLastMarginContentEntry;
   1286     }
   1287 }
   1288 
   1289 SkAutoTDelete<ContentEntry>* SkPDFDevice::getContentEntries() {
   1290     if (fDrawingArea == kContent_DrawingArea) {
   1291         return &fContentEntries;
   1292     } else {
   1293         return &fMarginContentEntries;
   1294     }
   1295 }
   1296 
   1297 void SkPDFDevice::setLastContentEntry(ContentEntry* contentEntry) {
   1298     if (fDrawingArea == kContent_DrawingArea) {
   1299         fLastContentEntry = contentEntry;
   1300     } else {
   1301         fLastMarginContentEntry = contentEntry;
   1302     }
   1303 }
   1304 
   1305 void SkPDFDevice::setDrawingArea(DrawingArea drawingArea) {
   1306     // A ScopedContentEntry only exists during the course of a draw call, so
   1307     // this can't be called while a ScopedContentEntry exists.
   1308     fDrawingArea = drawingArea;
   1309 }
   1310 
   1311 SkPDFResourceDict* SkPDFDevice::getResourceDict() {
   1312     if (NULL == fResourceDict) {
   1313         fResourceDict = SkNEW(SkPDFResourceDict);
   1314 
   1315         if (fGraphicStateResources.count()) {
   1316             for (int i = 0; i < fGraphicStateResources.count(); i++) {
   1317                 fResourceDict->insertResourceAsReference(
   1318                         SkPDFResourceDict::kExtGState_ResourceType,
   1319                         i, fGraphicStateResources[i]);
   1320             }
   1321         }
   1322 
   1323         if (fXObjectResources.count()) {
   1324             for (int i = 0; i < fXObjectResources.count(); i++) {
   1325                 fResourceDict->insertResourceAsReference(
   1326                         SkPDFResourceDict::kXObject_ResourceType,
   1327                         i, fXObjectResources[i]);
   1328             }
   1329         }
   1330 
   1331         if (fFontResources.count()) {
   1332             for (int i = 0; i < fFontResources.count(); i++) {
   1333                 fResourceDict->insertResourceAsReference(
   1334                         SkPDFResourceDict::kFont_ResourceType,
   1335                         i, fFontResources[i]);
   1336             }
   1337         }
   1338 
   1339         if (fShaderResources.count()) {
   1340             SkAutoTUnref<SkPDFDict> patterns(new SkPDFDict());
   1341             for (int i = 0; i < fShaderResources.count(); i++) {
   1342                 fResourceDict->insertResourceAsReference(
   1343                         SkPDFResourceDict::kPattern_ResourceType,
   1344                         i, fShaderResources[i]);
   1345             }
   1346         }
   1347     }
   1348     return fResourceDict;
   1349 }
   1350 
   1351 const SkTDArray<SkPDFFont*>& SkPDFDevice::getFontResources() const {
   1352     return fFontResources;
   1353 }
   1354 
   1355 SkPDFArray* SkPDFDevice::copyMediaBox() const {
   1356     // should this be a singleton?
   1357     SkAutoTUnref<SkPDFInt> zero(SkNEW_ARGS(SkPDFInt, (0)));
   1358 
   1359     SkPDFArray* mediaBox = SkNEW(SkPDFArray);
   1360     mediaBox->reserve(4);
   1361     mediaBox->append(zero.get());
   1362     mediaBox->append(zero.get());
   1363     mediaBox->appendInt(fPageSize.fWidth);
   1364     mediaBox->appendInt(fPageSize.fHeight);
   1365     return mediaBox;
   1366 }
   1367 
   1368 SkStream* SkPDFDevice::content() const {
   1369     SkMemoryStream* result = new SkMemoryStream;
   1370     result->setData(this->copyContentToData())->unref();
   1371     return result;
   1372 }
   1373 
   1374 void SkPDFDevice::copyContentEntriesToData(ContentEntry* entry,
   1375         SkWStream* data) const {
   1376     // TODO(ctguil): For margins, I'm not sure fExistingClipStack/Region is the
   1377     // right thing to pass here.
   1378     GraphicStackState gsState(fExistingClipStack, fExistingClipRegion, data);
   1379     while (entry != NULL) {
   1380         SkPoint translation;
   1381         translation.iset(this->getOrigin());
   1382         translation.negate();
   1383         gsState.updateClip(entry->fState.fClipStack, entry->fState.fClipRegion,
   1384                            translation);
   1385         gsState.updateMatrix(entry->fState.fMatrix);
   1386         gsState.updateDrawingState(entry->fState);
   1387 
   1388         SkAutoDataUnref copy(entry->fContent.copyToData());
   1389         data->write(copy->data(), copy->size());
   1390         entry = entry->fNext.get();
   1391     }
   1392     gsState.drainStack();
   1393 }
   1394 
   1395 SkData* SkPDFDevice::copyContentToData() const {
   1396     SkDynamicMemoryWStream data;
   1397     if (fInitialTransform.getType() != SkMatrix::kIdentity_Mask) {
   1398         SkPDFUtils::AppendTransform(fInitialTransform, &data);
   1399     }
   1400 
   1401     // TODO(aayushkumar): Apply clip along the margins.  Currently, webkit
   1402     // colors the contentArea white before it starts drawing into it and
   1403     // that currently acts as our clip.
   1404     // Also, think about adding a transform here (or assume that the values
   1405     // sent across account for that)
   1406     SkPDFDevice::copyContentEntriesToData(fMarginContentEntries.get(), &data);
   1407 
   1408     // If the content area is the entire page, then we don't need to clip
   1409     // the content area (PDF area clips to the page size).  Otherwise,
   1410     // we have to clip to the content area; we've already applied the
   1411     // initial transform, so just clip to the device size.
   1412     if (fPageSize != fContentSize) {
   1413         SkRect r = SkRect::MakeWH(SkIntToScalar(this->width()),
   1414                                   SkIntToScalar(this->height()));
   1415         emit_clip(NULL, &r, &data);
   1416     }
   1417 
   1418     SkPDFDevice::copyContentEntriesToData(fContentEntries.get(), &data);
   1419 
   1420     // potentially we could cache this SkData, and only rebuild it if we
   1421     // see that our state has changed.
   1422     return data.copyToData();
   1423 }
   1424 
   1425 #ifdef SK_PDF_USE_PATHOPS
   1426 /* Draws an inverse filled path by using Path Ops to compute the positive
   1427  * inverse using the current clip as the inverse bounds.
   1428  * Return true if this was an inverse path and was properly handled,
   1429  * otherwise returns false and the normal drawing routine should continue,
   1430  * either as a (incorrect) fallback or because the path was not inverse
   1431  * in the first place.
   1432  */
   1433 bool SkPDFDevice::handleInversePath(const SkDraw& d, const SkPath& origPath,
   1434                                     const SkPaint& paint, bool pathIsMutable,
   1435                                     const SkMatrix* prePathMatrix) {
   1436     if (!origPath.isInverseFillType()) {
   1437         return false;
   1438     }
   1439 
   1440     if (d.fClip->isEmpty()) {
   1441         return false;
   1442     }
   1443 
   1444     SkPath modifiedPath;
   1445     SkPath* pathPtr = const_cast<SkPath*>(&origPath);
   1446     SkPaint noInversePaint(paint);
   1447 
   1448     // Merge stroking operations into final path.
   1449     if (SkPaint::kStroke_Style == paint.getStyle() ||
   1450         SkPaint::kStrokeAndFill_Style == paint.getStyle()) {
   1451         bool doFillPath = paint.getFillPath(origPath, &modifiedPath);
   1452         if (doFillPath) {
   1453             noInversePaint.setStyle(SkPaint::kFill_Style);
   1454             noInversePaint.setStrokeWidth(0);
   1455             pathPtr = &modifiedPath;
   1456         } else {
   1457             // To be consistent with the raster output, hairline strokes
   1458             // are rendered as non-inverted.
   1459             modifiedPath.toggleInverseFillType();
   1460             drawPath(d, modifiedPath, paint, NULL, true);
   1461             return true;
   1462         }
   1463     }
   1464 
   1465     // Get bounds of clip in current transform space
   1466     // (clip bounds are given in device space).
   1467     SkRect bounds;
   1468     SkMatrix transformInverse;
   1469     SkMatrix totalMatrix = *d.fMatrix;
   1470     if (prePathMatrix) {
   1471         totalMatrix.preConcat(*prePathMatrix);
   1472     }
   1473     if (!totalMatrix.invert(&transformInverse)) {
   1474         return false;
   1475     }
   1476     bounds.set(d.fClip->getBounds());
   1477     transformInverse.mapRect(&bounds);
   1478 
   1479     // Extend the bounds by the line width (plus some padding)
   1480     // so the edge doesn't cause a visible stroke.
   1481     bounds.outset(paint.getStrokeWidth() + SK_Scalar1,
   1482                   paint.getStrokeWidth() + SK_Scalar1);
   1483 
   1484     if (!calculate_inverse_path(bounds, *pathPtr, &modifiedPath)) {
   1485         return false;
   1486     }
   1487 
   1488     drawPath(d, modifiedPath, noInversePaint, prePathMatrix, true);
   1489     return true;
   1490 }
   1491 #endif
   1492 
   1493 bool SkPDFDevice::handleRectAnnotation(const SkRect& r, const SkMatrix& matrix,
   1494                                        const SkPaint& p) {
   1495     SkAnnotation* annotationInfo = p.getAnnotation();
   1496     if (!annotationInfo) {
   1497         return false;
   1498     }
   1499     SkData* urlData = annotationInfo->find(SkAnnotationKeys::URL_Key());
   1500     if (urlData) {
   1501         handleLinkToURL(urlData, r, matrix);
   1502         return p.getAnnotation() != NULL;
   1503     }
   1504     SkData* linkToName = annotationInfo->find(
   1505             SkAnnotationKeys::Link_Named_Dest_Key());
   1506     if (linkToName) {
   1507         handleLinkToNamedDest(linkToName, r, matrix);
   1508         return p.getAnnotation() != NULL;
   1509     }
   1510     return false;
   1511 }
   1512 
   1513 bool SkPDFDevice::handlePointAnnotation(const SkPoint* points, size_t count,
   1514                                         const SkMatrix& matrix,
   1515                                         const SkPaint& paint) {
   1516     SkAnnotation* annotationInfo = paint.getAnnotation();
   1517     if (!annotationInfo) {
   1518         return false;
   1519     }
   1520     SkData* nameData = annotationInfo->find(
   1521             SkAnnotationKeys::Define_Named_Dest_Key());
   1522     if (nameData) {
   1523         for (size_t i = 0; i < count; i++) {
   1524             defineNamedDestination(nameData, points[i], matrix);
   1525         }
   1526         return paint.getAnnotation() != NULL;
   1527     }
   1528     return false;
   1529 }
   1530 
   1531 SkPDFDict* SkPDFDevice::createLinkAnnotation(const SkRect& r,
   1532                                              const SkMatrix& matrix) {
   1533     SkMatrix transform = matrix;
   1534     transform.postConcat(fInitialTransform);
   1535     SkRect translatedRect;
   1536     transform.mapRect(&translatedRect, r);
   1537 
   1538     if (NULL == fAnnotations) {
   1539         fAnnotations = SkNEW(SkPDFArray);
   1540     }
   1541     SkPDFDict* annotation(SkNEW_ARGS(SkPDFDict, ("Annot")));
   1542     annotation->insertName("Subtype", "Link");
   1543     fAnnotations->append(annotation);
   1544 
   1545     SkAutoTUnref<SkPDFArray> border(SkNEW(SkPDFArray));
   1546     border->reserve(3);
   1547     border->appendInt(0);  // Horizontal corner radius.
   1548     border->appendInt(0);  // Vertical corner radius.
   1549     border->appendInt(0);  // Width, 0 = no border.
   1550     annotation->insert("Border", border.get());
   1551 
   1552     SkAutoTUnref<SkPDFArray> rect(SkNEW(SkPDFArray));
   1553     rect->reserve(4);
   1554     rect->appendScalar(translatedRect.fLeft);
   1555     rect->appendScalar(translatedRect.fTop);
   1556     rect->appendScalar(translatedRect.fRight);
   1557     rect->appendScalar(translatedRect.fBottom);
   1558     annotation->insert("Rect", rect.get());
   1559 
   1560     return annotation;
   1561 }
   1562 
   1563 void SkPDFDevice::handleLinkToURL(SkData* urlData, const SkRect& r,
   1564                                   const SkMatrix& matrix) {
   1565     SkAutoTUnref<SkPDFDict> annotation(createLinkAnnotation(r, matrix));
   1566 
   1567     SkString url(static_cast<const char *>(urlData->data()),
   1568                  urlData->size() - 1);
   1569     SkAutoTUnref<SkPDFDict> action(SkNEW_ARGS(SkPDFDict, ("Action")));
   1570     action->insertName("S", "URI");
   1571     action->insert("URI", SkNEW_ARGS(SkPDFString, (url)))->unref();
   1572     annotation->insert("A", action.get());
   1573 }
   1574 
   1575 void SkPDFDevice::handleLinkToNamedDest(SkData* nameData, const SkRect& r,
   1576                                         const SkMatrix& matrix) {
   1577     SkAutoTUnref<SkPDFDict> annotation(createLinkAnnotation(r, matrix));
   1578     SkString name(static_cast<const char *>(nameData->data()),
   1579                   nameData->size() - 1);
   1580     annotation->insert("Dest", SkNEW_ARGS(SkPDFName, (name)))->unref();
   1581 }
   1582 
   1583 struct NamedDestination {
   1584     const SkData* nameData;
   1585     SkPoint point;
   1586 
   1587     NamedDestination(const SkData* nameData, const SkPoint& point)
   1588         : nameData(nameData), point(point) {
   1589         nameData->ref();
   1590     }
   1591 
   1592     ~NamedDestination() {
   1593         nameData->unref();
   1594     }
   1595 };
   1596 
   1597 void SkPDFDevice::defineNamedDestination(SkData* nameData, const SkPoint& point,
   1598                                          const SkMatrix& matrix) {
   1599     SkMatrix transform = matrix;
   1600     transform.postConcat(fInitialTransform);
   1601     SkPoint translatedPoint;
   1602     transform.mapXY(point.x(), point.y(), &translatedPoint);
   1603     fNamedDestinations.push(
   1604         SkNEW_ARGS(NamedDestination, (nameData, translatedPoint)));
   1605 }
   1606 
   1607 void SkPDFDevice::appendDestinations(SkPDFDict* dict, SkPDFObject* page) {
   1608     int nDest = fNamedDestinations.count();
   1609     for (int i = 0; i < nDest; i++) {
   1610         NamedDestination* dest = fNamedDestinations[i];
   1611         SkAutoTUnref<SkPDFArray> pdfDest(SkNEW(SkPDFArray));
   1612         pdfDest->reserve(5);
   1613         pdfDest->append(SkNEW_ARGS(SkPDFObjRef, (page)))->unref();
   1614         pdfDest->appendName("XYZ");
   1615         pdfDest->appendScalar(dest->point.x());
   1616         pdfDest->appendScalar(dest->point.y());
   1617         pdfDest->appendInt(0);  // Leave zoom unchanged
   1618         dict->insert(static_cast<const char *>(dest->nameData->data()),
   1619                      pdfDest);
   1620     }
   1621 }
   1622 
   1623 SkPDFFormXObject* SkPDFDevice::createFormXObjectFromDevice() {
   1624     SkPDFFormXObject* xobject = SkNEW_ARGS(SkPDFFormXObject, (this));
   1625     // We always draw the form xobjects that we create back into the device, so
   1626     // we simply preserve the font usage instead of pulling it out and merging
   1627     // it back in later.
   1628     cleanUp(false);  // Reset this device to have no content.
   1629     init();
   1630     return xobject;
   1631 }
   1632 
   1633 void SkPDFDevice::drawFormXObjectWithMask(int xObjectIndex,
   1634                                           SkPDFFormXObject* mask,
   1635                                           const SkClipStack* clipStack,
   1636                                           const SkRegion& clipRegion,
   1637                                           SkXfermode::Mode mode,
   1638                                           bool invertClip) {
   1639     if (clipRegion.isEmpty() && !invertClip) {
   1640         return;
   1641     }
   1642 
   1643     SkAutoTUnref<SkPDFGraphicState> sMaskGS(
   1644         SkPDFGraphicState::GetSMaskGraphicState(
   1645             mask, invertClip, SkPDFGraphicState::kAlpha_SMaskMode));
   1646 
   1647     SkMatrix identity;
   1648     identity.reset();
   1649     SkPaint paint;
   1650     paint.setXfermodeMode(mode);
   1651     ScopedContentEntry content(this, clipStack, clipRegion, identity, paint);
   1652     if (!content.entry()) {
   1653         return;
   1654     }
   1655     SkPDFUtils::ApplyGraphicState(addGraphicStateResource(sMaskGS.get()),
   1656                                   &content.entry()->fContent);
   1657     SkPDFUtils::DrawFormXObject(xObjectIndex, &content.entry()->fContent);
   1658 
   1659     sMaskGS.reset(SkPDFGraphicState::GetNoSMaskGraphicState());
   1660     SkPDFUtils::ApplyGraphicState(addGraphicStateResource(sMaskGS.get()),
   1661                                   &content.entry()->fContent);
   1662 }
   1663 
   1664 ContentEntry* SkPDFDevice::setUpContentEntry(const SkClipStack* clipStack,
   1665                                              const SkRegion& clipRegion,
   1666                                              const SkMatrix& matrix,
   1667                                              const SkPaint& paint,
   1668                                              bool hasText,
   1669                                              SkPDFFormXObject** dst) {
   1670     *dst = NULL;
   1671     if (clipRegion.isEmpty()) {
   1672         return NULL;
   1673     }
   1674 
   1675     // The clip stack can come from an SkDraw where it is technically optional.
   1676     SkClipStack synthesizedClipStack;
   1677     if (clipStack == NULL) {
   1678         if (clipRegion == fExistingClipRegion) {
   1679             clipStack = &fExistingClipStack;
   1680         } else {
   1681             // GraphicStackState::updateClip expects the clip stack to have
   1682             // fExistingClip as a prefix, so start there, then set the clip
   1683             // to the passed region.
   1684             synthesizedClipStack = fExistingClipStack;
   1685             SkPath clipPath;
   1686             clipRegion.getBoundaryPath(&clipPath);
   1687             synthesizedClipStack.clipDevPath(clipPath, SkRegion::kReplace_Op,
   1688                                              false);
   1689             clipStack = &synthesizedClipStack;
   1690         }
   1691     }
   1692 
   1693     SkXfermode::Mode xfermode = SkXfermode::kSrcOver_Mode;
   1694     if (paint.getXfermode()) {
   1695         paint.getXfermode()->asMode(&xfermode);
   1696     }
   1697 
   1698     // For the following modes, we want to handle source and destination
   1699     // separately, so make an object of what's already there.
   1700     if (xfermode == SkXfermode::kClear_Mode       ||
   1701             xfermode == SkXfermode::kSrc_Mode     ||
   1702             xfermode == SkXfermode::kSrcIn_Mode   ||
   1703             xfermode == SkXfermode::kDstIn_Mode   ||
   1704             xfermode == SkXfermode::kSrcOut_Mode  ||
   1705             xfermode == SkXfermode::kDstOut_Mode  ||
   1706             xfermode == SkXfermode::kSrcATop_Mode ||
   1707             xfermode == SkXfermode::kDstATop_Mode ||
   1708             xfermode == SkXfermode::kModulate_Mode) {
   1709         if (!isContentEmpty()) {
   1710             *dst = createFormXObjectFromDevice();
   1711             SkASSERT(isContentEmpty());
   1712         } else if (xfermode != SkXfermode::kSrc_Mode &&
   1713                    xfermode != SkXfermode::kSrcOut_Mode) {
   1714             // Except for Src and SrcOut, if there isn't anything already there,
   1715             // then we're done.
   1716             return NULL;
   1717         }
   1718     }
   1719     // TODO(vandebo): Figure out how/if we can handle the following modes:
   1720     // Xor, Plus.
   1721 
   1722     // Dst xfer mode doesn't draw source at all.
   1723     if (xfermode == SkXfermode::kDst_Mode) {
   1724         return NULL;
   1725     }
   1726 
   1727     ContentEntry* entry;
   1728     SkAutoTDelete<ContentEntry> newEntry;
   1729 
   1730     ContentEntry* lastContentEntry = getLastContentEntry();
   1731     if (lastContentEntry && lastContentEntry->fContent.getOffset() == 0) {
   1732         entry = lastContentEntry;
   1733     } else {
   1734         newEntry.reset(new ContentEntry);
   1735         entry = newEntry.get();
   1736     }
   1737 
   1738     populateGraphicStateEntryFromPaint(matrix, *clipStack, clipRegion, paint,
   1739                                        hasText, &entry->fState);
   1740     if (lastContentEntry && xfermode != SkXfermode::kDstOver_Mode &&
   1741             entry->fState.compareInitialState(lastContentEntry->fState)) {
   1742         return lastContentEntry;
   1743     }
   1744 
   1745     SkAutoTDelete<ContentEntry>* contentEntries = getContentEntries();
   1746     if (!lastContentEntry) {
   1747         contentEntries->reset(entry);
   1748         setLastContentEntry(entry);
   1749     } else if (xfermode == SkXfermode::kDstOver_Mode) {
   1750         entry->fNext.reset(contentEntries->detach());
   1751         contentEntries->reset(entry);
   1752     } else {
   1753         lastContentEntry->fNext.reset(entry);
   1754         setLastContentEntry(entry);
   1755     }
   1756     newEntry.detach();
   1757     return entry;
   1758 }
   1759 
   1760 void SkPDFDevice::finishContentEntry(SkXfermode::Mode xfermode,
   1761                                      SkPDFFormXObject* dst,
   1762                                      SkPath* shape) {
   1763     if (xfermode != SkXfermode::kClear_Mode       &&
   1764             xfermode != SkXfermode::kSrc_Mode     &&
   1765             xfermode != SkXfermode::kDstOver_Mode &&
   1766             xfermode != SkXfermode::kSrcIn_Mode   &&
   1767             xfermode != SkXfermode::kDstIn_Mode   &&
   1768             xfermode != SkXfermode::kSrcOut_Mode  &&
   1769             xfermode != SkXfermode::kDstOut_Mode  &&
   1770             xfermode != SkXfermode::kSrcATop_Mode &&
   1771             xfermode != SkXfermode::kDstATop_Mode &&
   1772             xfermode != SkXfermode::kModulate_Mode) {
   1773         SkASSERT(!dst);
   1774         return;
   1775     }
   1776     if (xfermode == SkXfermode::kDstOver_Mode) {
   1777         SkASSERT(!dst);
   1778         ContentEntry* firstContentEntry = getContentEntries()->get();
   1779         if (firstContentEntry->fContent.getOffset() == 0) {
   1780             // For DstOver, an empty content entry was inserted before the rest
   1781             // of the content entries. If nothing was drawn, it needs to be
   1782             // removed.
   1783             SkAutoTDelete<ContentEntry>* contentEntries = getContentEntries();
   1784             contentEntries->reset(firstContentEntry->fNext.detach());
   1785         }
   1786         return;
   1787     }
   1788     if (!dst) {
   1789         SkASSERT(xfermode == SkXfermode::kSrc_Mode ||
   1790                  xfermode == SkXfermode::kSrcOut_Mode);
   1791         return;
   1792     }
   1793 
   1794     ContentEntry* contentEntries = getContentEntries()->get();
   1795     SkASSERT(dst);
   1796     SkASSERT(!contentEntries->fNext.get());
   1797     // Changing the current content into a form-xobject will destroy the clip
   1798     // objects which is fine since the xobject will already be clipped. However
   1799     // if source has shape, we need to clip it too, so a copy of the clip is
   1800     // saved.
   1801     SkClipStack clipStack = contentEntries->fState.fClipStack;
   1802     SkRegion clipRegion = contentEntries->fState.fClipRegion;
   1803 
   1804     SkMatrix identity;
   1805     identity.reset();
   1806     SkPaint stockPaint;
   1807 
   1808     SkAutoTUnref<SkPDFFormXObject> srcFormXObject;
   1809     if (isContentEmpty()) {
   1810         // If nothing was drawn and there's no shape, then the draw was a
   1811         // no-op, but dst needs to be restored for that to be true.
   1812         // If there is shape, then an empty source with Src, SrcIn, SrcOut,
   1813         // DstIn, DstAtop or Modulate reduces to Clear and DstOut or SrcAtop
   1814         // reduces to Dst.
   1815         if (shape == NULL || xfermode == SkXfermode::kDstOut_Mode ||
   1816                 xfermode == SkXfermode::kSrcATop_Mode) {
   1817             ScopedContentEntry content(this, &fExistingClipStack,
   1818                                        fExistingClipRegion, identity,
   1819                                        stockPaint);
   1820             SkPDFUtils::DrawFormXObject(this->addXObjectResource(dst),
   1821                                         &content.entry()->fContent);
   1822             return;
   1823         } else {
   1824             xfermode = SkXfermode::kClear_Mode;
   1825         }
   1826     } else {
   1827         SkASSERT(!fContentEntries->fNext.get());
   1828         srcFormXObject.reset(createFormXObjectFromDevice());
   1829     }
   1830 
   1831     // TODO(vandebo) srcFormXObject may contain alpha, but here we want it
   1832     // without alpha.
   1833     if (xfermode == SkXfermode::kSrcATop_Mode) {
   1834         // TODO(vandebo): In order to properly support SrcATop we have to track
   1835         // the shape of what's been drawn at all times. It's the intersection of
   1836         // the non-transparent parts of the device and the outlines (shape) of
   1837         // all images and devices drawn.
   1838         drawFormXObjectWithMask(addXObjectResource(srcFormXObject.get()), dst,
   1839                                 &fExistingClipStack, fExistingClipRegion,
   1840                                 SkXfermode::kSrcOver_Mode, true);
   1841     } else {
   1842         SkAutoTUnref<SkPDFFormXObject> dstMaskStorage;
   1843         SkPDFFormXObject* dstMask = srcFormXObject.get();
   1844         if (shape != NULL) {
   1845             // Draw shape into a form-xobject.
   1846             SkDraw d;
   1847             d.fMatrix = &identity;
   1848             d.fClip = &clipRegion;
   1849             d.fClipStack = &clipStack;
   1850             SkPaint filledPaint;
   1851             filledPaint.setColor(SK_ColorBLACK);
   1852             filledPaint.setStyle(SkPaint::kFill_Style);
   1853             this->drawPath(d, *shape, filledPaint, NULL, true);
   1854 
   1855             dstMaskStorage.reset(createFormXObjectFromDevice());
   1856             dstMask = dstMaskStorage.get();
   1857         }
   1858         drawFormXObjectWithMask(addXObjectResource(dst), dstMask,
   1859                                 &fExistingClipStack, fExistingClipRegion,
   1860                                 SkXfermode::kSrcOver_Mode, true);
   1861     }
   1862 
   1863     if (xfermode == SkXfermode::kClear_Mode) {
   1864         return;
   1865     } else if (xfermode == SkXfermode::kSrc_Mode ||
   1866             xfermode == SkXfermode::kDstATop_Mode) {
   1867         ScopedContentEntry content(this, &fExistingClipStack,
   1868                                    fExistingClipRegion, identity, stockPaint);
   1869         if (content.entry()) {
   1870             SkPDFUtils::DrawFormXObject(
   1871                     this->addXObjectResource(srcFormXObject.get()),
   1872                     &content.entry()->fContent);
   1873         }
   1874         if (xfermode == SkXfermode::kSrc_Mode) {
   1875             return;
   1876         }
   1877     } else if (xfermode == SkXfermode::kSrcATop_Mode) {
   1878         ScopedContentEntry content(this, &fExistingClipStack,
   1879                                    fExistingClipRegion, identity, stockPaint);
   1880         if (content.entry()) {
   1881             SkPDFUtils::DrawFormXObject(this->addXObjectResource(dst),
   1882                                         &content.entry()->fContent);
   1883         }
   1884     }
   1885 
   1886     SkASSERT(xfermode == SkXfermode::kSrcIn_Mode   ||
   1887              xfermode == SkXfermode::kDstIn_Mode   ||
   1888              xfermode == SkXfermode::kSrcOut_Mode  ||
   1889              xfermode == SkXfermode::kDstOut_Mode  ||
   1890              xfermode == SkXfermode::kSrcATop_Mode ||
   1891              xfermode == SkXfermode::kDstATop_Mode ||
   1892              xfermode == SkXfermode::kModulate_Mode);
   1893 
   1894     if (xfermode == SkXfermode::kSrcIn_Mode ||
   1895             xfermode == SkXfermode::kSrcOut_Mode ||
   1896             xfermode == SkXfermode::kSrcATop_Mode) {
   1897         drawFormXObjectWithMask(addXObjectResource(srcFormXObject.get()), dst,
   1898                                 &fExistingClipStack, fExistingClipRegion,
   1899                                 SkXfermode::kSrcOver_Mode,
   1900                                 xfermode == SkXfermode::kSrcOut_Mode);
   1901     } else {
   1902         SkXfermode::Mode mode = SkXfermode::kSrcOver_Mode;
   1903         if (xfermode == SkXfermode::kModulate_Mode) {
   1904             drawFormXObjectWithMask(addXObjectResource(srcFormXObject.get()),
   1905                                     dst, &fExistingClipStack,
   1906                                     fExistingClipRegion,
   1907                                     SkXfermode::kSrcOver_Mode, false);
   1908             mode = SkXfermode::kMultiply_Mode;
   1909         }
   1910         drawFormXObjectWithMask(addXObjectResource(dst), srcFormXObject.get(),
   1911                                 &fExistingClipStack, fExistingClipRegion, mode,
   1912                                 xfermode == SkXfermode::kDstOut_Mode);
   1913     }
   1914 }
   1915 
   1916 bool SkPDFDevice::isContentEmpty() {
   1917     ContentEntry* contentEntries = getContentEntries()->get();
   1918     if (!contentEntries || contentEntries->fContent.getOffset() == 0) {
   1919         SkASSERT(!contentEntries || !contentEntries->fNext.get());
   1920         return true;
   1921     }
   1922     return false;
   1923 }
   1924 
   1925 void SkPDFDevice::populateGraphicStateEntryFromPaint(
   1926         const SkMatrix& matrix,
   1927         const SkClipStack& clipStack,
   1928         const SkRegion& clipRegion,
   1929         const SkPaint& paint,
   1930         bool hasText,
   1931         GraphicStateEntry* entry) {
   1932     NOT_IMPLEMENTED(paint.getPathEffect() != NULL, false);
   1933     NOT_IMPLEMENTED(paint.getMaskFilter() != NULL, false);
   1934     NOT_IMPLEMENTED(paint.getColorFilter() != NULL, false);
   1935 
   1936     entry->fMatrix = matrix;
   1937     entry->fClipStack = clipStack;
   1938     entry->fClipRegion = clipRegion;
   1939     entry->fColor = SkColorSetA(paint.getColor(), 0xFF);
   1940     entry->fShaderIndex = -1;
   1941 
   1942     // PDF treats a shader as a color, so we only set one or the other.
   1943     SkAutoTUnref<SkPDFObject> pdfShader;
   1944     const SkShader* shader = paint.getShader();
   1945     SkColor color = paint.getColor();
   1946     if (shader) {
   1947         // PDF positions patterns relative to the initial transform, so
   1948         // we need to apply the current transform to the shader parameters.
   1949         SkMatrix transform = matrix;
   1950         transform.postConcat(fInitialTransform);
   1951 
   1952         // PDF doesn't support kClamp_TileMode, so we simulate it by making
   1953         // a pattern the size of the current clip.
   1954         SkIRect bounds = clipRegion.getBounds();
   1955 
   1956         // We need to apply the initial transform to bounds in order to get
   1957         // bounds in a consistent coordinate system.
   1958         SkRect boundsTemp;
   1959         boundsTemp.set(bounds);
   1960         fInitialTransform.mapRect(&boundsTemp);
   1961         boundsTemp.roundOut(&bounds);
   1962 
   1963         pdfShader.reset(SkPDFShader::GetPDFShader(*shader, transform, bounds));
   1964 
   1965         if (pdfShader.get()) {
   1966             // pdfShader has been canonicalized so we can directly compare
   1967             // pointers.
   1968             int resourceIndex = fShaderResources.find(pdfShader.get());
   1969             if (resourceIndex < 0) {
   1970                 resourceIndex = fShaderResources.count();
   1971                 fShaderResources.push(pdfShader.get());
   1972                 pdfShader.get()->ref();
   1973             }
   1974             entry->fShaderIndex = resourceIndex;
   1975         } else {
   1976             // A color shader is treated as an invalid shader so we don't have
   1977             // to set a shader just for a color.
   1978             SkShader::GradientInfo gradientInfo;
   1979             SkColor gradientColor;
   1980             gradientInfo.fColors = &gradientColor;
   1981             gradientInfo.fColorOffsets = NULL;
   1982             gradientInfo.fColorCount = 1;
   1983             if (shader->asAGradient(&gradientInfo) ==
   1984                     SkShader::kColor_GradientType) {
   1985                 entry->fColor = SkColorSetA(gradientColor, 0xFF);
   1986                 color = gradientColor;
   1987             }
   1988         }
   1989     }
   1990 
   1991     SkAutoTUnref<SkPDFGraphicState> newGraphicState;
   1992     if (color == paint.getColor()) {
   1993         newGraphicState.reset(
   1994                 SkPDFGraphicState::GetGraphicStateForPaint(paint));
   1995     } else {
   1996         SkPaint newPaint = paint;
   1997         newPaint.setColor(color);
   1998         newGraphicState.reset(
   1999                 SkPDFGraphicState::GetGraphicStateForPaint(newPaint));
   2000     }
   2001     int resourceIndex = addGraphicStateResource(newGraphicState.get());
   2002     entry->fGraphicStateIndex = resourceIndex;
   2003 
   2004     if (hasText) {
   2005         entry->fTextScaleX = paint.getTextScaleX();
   2006         entry->fTextFill = paint.getStyle();
   2007     } else {
   2008         entry->fTextScaleX = 0;
   2009     }
   2010 }
   2011 
   2012 int SkPDFDevice::addGraphicStateResource(SkPDFGraphicState* gs) {
   2013     // Assumes that gs has been canonicalized (so we can directly compare
   2014     // pointers).
   2015     int result = fGraphicStateResources.find(gs);
   2016     if (result < 0) {
   2017         result = fGraphicStateResources.count();
   2018         fGraphicStateResources.push(gs);
   2019         gs->ref();
   2020     }
   2021     return result;
   2022 }
   2023 
   2024 int SkPDFDevice::addXObjectResource(SkPDFObject* xObject) {
   2025     // Assumes that xobject has been canonicalized (so we can directly compare
   2026     // pointers).
   2027     int result = fXObjectResources.find(xObject);
   2028     if (result < 0) {
   2029         result = fXObjectResources.count();
   2030         fXObjectResources.push(xObject);
   2031         xObject->ref();
   2032     }
   2033     return result;
   2034 }
   2035 
   2036 void SkPDFDevice::updateFont(const SkPaint& paint, uint16_t glyphID,
   2037                              ContentEntry* contentEntry) {
   2038     SkTypeface* typeface = paint.getTypeface();
   2039     if (contentEntry->fState.fFont == NULL ||
   2040             contentEntry->fState.fTextSize != paint.getTextSize() ||
   2041             !contentEntry->fState.fFont->hasGlyph(glyphID)) {
   2042         int fontIndex = getFontResourceIndex(typeface, glyphID);
   2043         contentEntry->fContent.writeText("/");
   2044         contentEntry->fContent.writeText(SkPDFResourceDict::getResourceName(
   2045                 SkPDFResourceDict::kFont_ResourceType,
   2046                 fontIndex).c_str());
   2047         contentEntry->fContent.writeText(" ");
   2048         SkPDFScalar::Append(paint.getTextSize(), &contentEntry->fContent);
   2049         contentEntry->fContent.writeText(" Tf\n");
   2050         contentEntry->fState.fFont = fFontResources[fontIndex];
   2051     }
   2052 }
   2053 
   2054 int SkPDFDevice::getFontResourceIndex(SkTypeface* typeface, uint16_t glyphID) {
   2055     SkAutoTUnref<SkPDFFont> newFont(SkPDFFont::GetFontResource(typeface,
   2056                                                                glyphID));
   2057     int resourceIndex = fFontResources.find(newFont.get());
   2058     if (resourceIndex < 0) {
   2059         resourceIndex = fFontResources.count();
   2060         fFontResources.push(newFont.get());
   2061         newFont.get()->ref();
   2062     }
   2063     return resourceIndex;
   2064 }
   2065 
   2066 void SkPDFDevice::internalDrawBitmap(const SkMatrix& origMatrix,
   2067                                      const SkClipStack* clipStack,
   2068                                      const SkRegion& origClipRegion,
   2069                                      const SkBitmap& origBitmap,
   2070                                      const SkIRect* srcRect,
   2071                                      const SkPaint& paint) {
   2072     SkMatrix matrix = origMatrix;
   2073     SkRegion perspectiveBounds;
   2074     const SkRegion* clipRegion = &origClipRegion;
   2075     SkBitmap perspectiveBitmap;
   2076     const SkBitmap* bitmap = &origBitmap;
   2077     SkBitmap tmpSubsetBitmap;
   2078 
   2079     // Rasterize the bitmap using perspective in a new bitmap.
   2080     if (origMatrix.hasPerspective()) {
   2081         if (fRasterDpi == 0) {
   2082             return;
   2083         }
   2084         SkBitmap* subsetBitmap;
   2085         if (srcRect) {
   2086             if (!origBitmap.extractSubset(&tmpSubsetBitmap, *srcRect)) {
   2087                return;
   2088             }
   2089             subsetBitmap = &tmpSubsetBitmap;
   2090         } else {
   2091             subsetBitmap = &tmpSubsetBitmap;
   2092             *subsetBitmap = origBitmap;
   2093         }
   2094         srcRect = NULL;
   2095 
   2096         // Transform the bitmap in the new space, without taking into
   2097         // account the initial transform.
   2098         SkPath perspectiveOutline;
   2099         perspectiveOutline.addRect(
   2100                 SkRect::MakeWH(SkIntToScalar(subsetBitmap->width()),
   2101                                SkIntToScalar(subsetBitmap->height())));
   2102         perspectiveOutline.transform(origMatrix);
   2103 
   2104         // TODO(edisonn): perf - use current clip too.
   2105         // Retrieve the bounds of the new shape.
   2106         SkRect bounds = perspectiveOutline.getBounds();
   2107 
   2108         // Transform the bitmap in the new space, taking into
   2109         // account the initial transform.
   2110         SkMatrix total = origMatrix;
   2111         total.postConcat(fInitialTransform);
   2112         total.postScale(SkIntToScalar(fRasterDpi) /
   2113                             SkIntToScalar(DPI_FOR_RASTER_SCALE_ONE),
   2114                         SkIntToScalar(fRasterDpi) /
   2115                             SkIntToScalar(DPI_FOR_RASTER_SCALE_ONE));
   2116         SkPath physicalPerspectiveOutline;
   2117         physicalPerspectiveOutline.addRect(
   2118                 SkRect::MakeWH(SkIntToScalar(subsetBitmap->width()),
   2119                                SkIntToScalar(subsetBitmap->height())));
   2120         physicalPerspectiveOutline.transform(total);
   2121 
   2122         SkScalar scaleX = physicalPerspectiveOutline.getBounds().width() /
   2123                               bounds.width();
   2124         SkScalar scaleY = physicalPerspectiveOutline.getBounds().height() /
   2125                               bounds.height();
   2126 
   2127         // TODO(edisonn): A better approach would be to use a bitmap shader
   2128         // (in clamp mode) and draw a rect over the entire bounding box. Then
   2129         // intersect perspectiveOutline to the clip. That will avoid introducing
   2130         // alpha to the image while still giving good behavior at the edge of
   2131         // the image.  Avoiding alpha will reduce the pdf size and generation
   2132         // CPU time some.
   2133 
   2134         const int w = SkScalarCeilToInt(physicalPerspectiveOutline.getBounds().width());
   2135         const int h = SkScalarCeilToInt(physicalPerspectiveOutline.getBounds().height());
   2136         if (!perspectiveBitmap.tryAllocN32Pixels(w, h)) {
   2137             return;
   2138         }
   2139         perspectiveBitmap.eraseColor(SK_ColorTRANSPARENT);
   2140 
   2141         SkCanvas canvas(perspectiveBitmap);
   2142 
   2143         SkScalar deltaX = bounds.left();
   2144         SkScalar deltaY = bounds.top();
   2145 
   2146         SkMatrix offsetMatrix = origMatrix;
   2147         offsetMatrix.postTranslate(-deltaX, -deltaY);
   2148         offsetMatrix.postScale(scaleX, scaleY);
   2149 
   2150         // Translate the draw in the new canvas, so we perfectly fit the
   2151         // shape in the bitmap.
   2152         canvas.setMatrix(offsetMatrix);
   2153 
   2154         canvas.drawBitmap(*subsetBitmap, SkIntToScalar(0), SkIntToScalar(0));
   2155 
   2156         // Make sure the final bits are in the bitmap.
   2157         canvas.flush();
   2158 
   2159         // In the new space, we use the identity matrix translated
   2160         // and scaled to reflect DPI.
   2161         matrix.setScale(1 / scaleX, 1 / scaleY);
   2162         matrix.postTranslate(deltaX, deltaY);
   2163 
   2164         perspectiveBounds.setRect(
   2165                 SkIRect::MakeXYWH(SkScalarFloorToInt(bounds.x()),
   2166                                   SkScalarFloorToInt(bounds.y()),
   2167                                   SkScalarCeilToInt(bounds.width()),
   2168                                   SkScalarCeilToInt(bounds.height())));
   2169         clipRegion = &perspectiveBounds;
   2170         srcRect = NULL;
   2171         bitmap = &perspectiveBitmap;
   2172     }
   2173 
   2174     SkMatrix scaled;
   2175     // Adjust for origin flip.
   2176     scaled.setScale(SK_Scalar1, -SK_Scalar1);
   2177     scaled.postTranslate(0, SK_Scalar1);
   2178     // Scale the image up from 1x1 to WxH.
   2179     SkIRect subset = SkIRect::MakeWH(bitmap->width(), bitmap->height());
   2180     scaled.postScale(SkIntToScalar(subset.width()),
   2181                      SkIntToScalar(subset.height()));
   2182     scaled.postConcat(matrix);
   2183     ScopedContentEntry content(this, clipStack, *clipRegion, scaled, paint);
   2184     if (!content.entry() || (srcRect && !subset.intersect(*srcRect))) {
   2185         return;
   2186     }
   2187     if (content.needShape()) {
   2188         SkPath shape;
   2189         shape.addRect(SkRect::MakeWH(SkIntToScalar(subset.width()),
   2190                                      SkIntToScalar( subset.height())));
   2191         shape.transform(matrix);
   2192         content.setShape(shape);
   2193     }
   2194     if (!content.needSource()) {
   2195         return;
   2196     }
   2197 
   2198     SkAutoTUnref<SkPDFObject> image(
   2199             SkPDFCreateImageObject(*bitmap, subset, fEncoder));
   2200     if (!image) {
   2201         return;
   2202     }
   2203 
   2204     SkPDFUtils::DrawFormXObject(this->addXObjectResource(image.get()),
   2205                                 &content.entry()->fContent);
   2206 }
   2207 
   2208