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