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