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