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