Home | History | Annotate | Download | only in pdf
      1 /*
      2  * Copyright (C) 2011 Google Inc.
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include "SkPDFDevice.h"
     18 
     19 #include "SkColor.h"
     20 #include "SkClipStack.h"
     21 #include "SkDraw.h"
     22 #include "SkGlyphCache.h"
     23 #include "SkPaint.h"
     24 #include "SkPath.h"
     25 #include "SkPDFFont.h"
     26 #include "SkPDFFormXObject.h"
     27 #include "SkPDFGraphicState.h"
     28 #include "SkPDFImage.h"
     29 #include "SkPDFShader.h"
     30 #include "SkPDFStream.h"
     31 #include "SkPDFTypes.h"
     32 #include "SkPDFUtils.h"
     33 #include "SkRect.h"
     34 #include "SkString.h"
     35 #include "SkTextFormatParams.h"
     36 #include "SkTypeface.h"
     37 #include "SkTypes.h"
     38 
     39 // Utility functions
     40 
     41 static void emit_pdf_color(SkColor color, SkWStream* result) {
     42     SkASSERT(SkColorGetA(color) == 0xFF);  // We handle alpha elsewhere.
     43     SkScalar colorMax = SkIntToScalar(0xFF);
     44     SkPDFScalar::Append(
     45             SkScalarDiv(SkIntToScalar(SkColorGetR(color)), colorMax), result);
     46     result->writeText(" ");
     47     SkPDFScalar::Append(
     48             SkScalarDiv(SkIntToScalar(SkColorGetG(color)), colorMax), result);
     49     result->writeText(" ");
     50     SkPDFScalar::Append(
     51             SkScalarDiv(SkIntToScalar(SkColorGetB(color)), colorMax), result);
     52     result->writeText(" ");
     53 }
     54 
     55 static SkPaint calculate_text_paint(const SkPaint& paint) {
     56     SkPaint result = paint;
     57     if (result.isFakeBoldText()) {
     58         SkScalar fakeBoldScale = SkScalarInterpFunc(result.getTextSize(),
     59                                                     kStdFakeBoldInterpKeys,
     60                                                     kStdFakeBoldInterpValues,
     61                                                     kStdFakeBoldInterpLength);
     62         SkScalar width = SkScalarMul(result.getTextSize(), fakeBoldScale);
     63         if (result.getStyle() == SkPaint::kFill_Style)
     64             result.setStyle(SkPaint::kStrokeAndFill_Style);
     65         else
     66             width += result.getStrokeWidth();
     67         result.setStrokeWidth(width);
     68     }
     69     return result;
     70 }
     71 
     72 // Stolen from measure_text in SkDraw.cpp and then tweaked.
     73 static void align_text(SkDrawCacheProc glyphCacheProc, const SkPaint& paint,
     74                        const uint16_t* glyphs, size_t len, SkScalar* x,
     75                        SkScalar* y, SkScalar* width) {
     76     if (paint.getTextAlign() == SkPaint::kLeft_Align && width == NULL)
     77         return;
     78 
     79     SkMatrix ident;
     80     ident.reset();
     81     SkAutoGlyphCache autoCache(paint, &ident);
     82     SkGlyphCache* cache = autoCache.getCache();
     83 
     84     const char* start = (char*)glyphs;
     85     const char* stop = (char*)(glyphs + len);
     86     SkFixed xAdv = 0, yAdv = 0;
     87 
     88     // TODO(vandebo) This probably needs to take kerning into account.
     89     while (start < stop) {
     90         const SkGlyph& glyph = glyphCacheProc(cache, &start, 0, 0);
     91         xAdv += glyph.fAdvanceX;
     92         yAdv += glyph.fAdvanceY;
     93     };
     94     if (width)
     95         *width = SkFixedToScalar(xAdv);
     96     if (paint.getTextAlign() == SkPaint::kLeft_Align)
     97         return;
     98 
     99     SkScalar xAdj = SkFixedToScalar(xAdv);
    100     SkScalar yAdj = SkFixedToScalar(yAdv);
    101     if (paint.getTextAlign() == SkPaint::kCenter_Align) {
    102         xAdj = SkScalarHalf(xAdj);
    103         yAdj = SkScalarHalf(yAdj);
    104     }
    105     *x = *x - xAdj;
    106     *y = *y - yAdj;
    107 }
    108 
    109 static void set_text_transform(SkScalar x, SkScalar y, SkScalar textSkewX,
    110                                SkWStream* content) {
    111     // Flip the text about the x-axis to account for origin swap and include
    112     // the passed parameters.
    113     content->writeText("1 0 ");
    114     SkPDFScalar::Append(0 - textSkewX, content);
    115     content->writeText(" -1 ");
    116     SkPDFScalar::Append(x, content);
    117     content->writeText(" ");
    118     SkPDFScalar::Append(y, content);
    119     content->writeText(" Tm\n");
    120 }
    121 
    122 // It is important to not confuse GraphicStateEntry with SkPDFGraphicState, the
    123 // later being our representation of an object in the PDF file.
    124 struct GraphicStateEntry {
    125     GraphicStateEntry();
    126 
    127     // Compare the fields we care about when setting up a new content entry.
    128     bool compareInitialState(const GraphicStateEntry& b);
    129 
    130     SkMatrix fMatrix;
    131     // We can't do set operations on Paths, though PDF natively supports
    132     // intersect.  If the clip stack does anything other than intersect,
    133     // we have to fall back to the region.  Treat fClipStack as authoritative.
    134     // See http://code.google.com/p/skia/issues/detail?id=221
    135     SkClipStack fClipStack;
    136     SkRegion fClipRegion;
    137 
    138     // When emitting the content entry, we will ensure the graphic state
    139     // is set to these values first.
    140     SkColor fColor;
    141     SkScalar fTextScaleX;  // Zero means we don't care what the value is.
    142     SkPaint::Style fTextFill;  // Only if TextScaleX is non-zero.
    143     int fShaderIndex;
    144     int fGraphicStateIndex;
    145 
    146     // We may change the font (i.e. for Type1 support) within a
    147     // ContentEntry.  This is the one currently in effect, or NULL if none.
    148     SkPDFFont* fFont;
    149     // In PDF, text size has no default value. It is only valid if fFont is
    150     // not NULL.
    151     SkScalar fTextSize;
    152 };
    153 
    154 GraphicStateEntry::GraphicStateEntry() : fColor(SK_ColorBLACK),
    155                                          fTextScaleX(SK_Scalar1),
    156                                          fTextFill(SkPaint::kFill_Style),
    157                                          fShaderIndex(-1),
    158                                          fGraphicStateIndex(-1),
    159                                          fFont(NULL),
    160                                          fTextSize(SK_ScalarNaN) {
    161     fMatrix.reset();
    162 }
    163 
    164 bool GraphicStateEntry::compareInitialState(const GraphicStateEntry& b) {
    165     return fColor == b.fColor &&
    166            fShaderIndex == b.fShaderIndex &&
    167            fGraphicStateIndex == b.fGraphicStateIndex &&
    168            fMatrix == b.fMatrix &&
    169            fClipStack == b.fClipStack &&
    170                (fTextScaleX == 0 ||
    171                 b.fTextScaleX == 0 ||
    172                 (fTextScaleX == b.fTextScaleX && fTextFill == b.fTextFill));
    173 }
    174 
    175 class GraphicStackState {
    176 public:
    177     GraphicStackState(const SkClipStack& existingClipStack,
    178                       const SkRegion& existingClipRegion,
    179                       SkWStream* contentStream)
    180             : fStackDepth(0),
    181               fContentStream(contentStream) {
    182         fEntries[0].fClipStack = existingClipStack;
    183         fEntries[0].fClipRegion = existingClipRegion;
    184     }
    185 
    186     void updateClip(const SkClipStack& clipStack, const SkRegion& clipRegion,
    187                     const SkIPoint& translation);
    188     void updateMatrix(const SkMatrix& matrix);
    189     void updateDrawingState(const GraphicStateEntry& state);
    190 
    191     void drainStack();
    192 
    193 private:
    194     void push();
    195     void pop();
    196     GraphicStateEntry* currentEntry() { return &fEntries[fStackDepth]; }
    197 
    198     // Conservative limit on save depth, see impl. notes in PDF 1.4 spec.
    199     static const int kMaxStackDepth = 12;
    200     GraphicStateEntry fEntries[kMaxStackDepth + 1];
    201     int fStackDepth;
    202     SkWStream* fContentStream;
    203 };
    204 
    205 void GraphicStackState::drainStack() {
    206     while (fStackDepth) {
    207         pop();
    208     }
    209 }
    210 
    211 void GraphicStackState::push() {
    212     SkASSERT(fStackDepth < kMaxStackDepth);
    213     fContentStream->writeText("q\n");
    214     fStackDepth++;
    215     fEntries[fStackDepth] = fEntries[fStackDepth - 1];
    216 }
    217 
    218 void GraphicStackState::pop() {
    219     SkASSERT(fStackDepth > 0);
    220     fContentStream->writeText("Q\n");
    221     fStackDepth--;
    222 }
    223 
    224 // This function initializes iter to be an interator on the "stack" argument
    225 // and then skips over the leading entries as specified in prefix.  It requires
    226 // and asserts that "prefix" will be a prefix to "stack."
    227 static void skip_clip_stack_prefix(const SkClipStack& prefix,
    228                                    const SkClipStack& stack,
    229                                    SkClipStack::B2FIter* iter) {
    230     SkClipStack::B2FIter prefixIter(prefix);
    231     iter->reset(stack);
    232 
    233     const SkClipStack::B2FIter::Clip* prefixEntry;
    234     const SkClipStack::B2FIter::Clip* iterEntry;
    235 
    236     int count = 0;
    237     for (prefixEntry = prefixIter.next(); prefixEntry;
    238             prefixEntry = prefixIter.next(), count++) {
    239         iterEntry = iter->next();
    240         SkASSERT(iterEntry);
    241         // Because of SkClipStack does internal intersection, the last clip
    242         // entry may differ.
    243         if(*prefixEntry != *iterEntry) {
    244             SkASSERT(prefixEntry->fOp == SkRegion::kIntersect_Op);
    245             SkASSERT(iterEntry->fOp == SkRegion::kIntersect_Op);
    246             SkASSERT((iterEntry->fRect == NULL) ==
    247                     (prefixEntry->fRect == NULL));
    248             SkASSERT((iterEntry->fPath == NULL) ==
    249                     (prefixEntry->fPath == NULL));
    250             // We need to back up the iterator by one but don't have that
    251             // function, so reset and go forward by one less.
    252             iter->reset(stack);
    253             for (int i = 0; i < count; i++) {
    254                 iter->next();
    255             }
    256             prefixEntry = prefixIter.next();
    257             break;
    258         }
    259     }
    260 
    261     SkASSERT(prefixEntry == NULL);
    262 }
    263 
    264 static void emit_clip(SkPath* clipPath, SkRect* clipRect,
    265                       SkWStream* contentStream) {
    266     SkASSERT(clipPath || clipRect);
    267 
    268     SkPath::FillType clipFill;
    269     if (clipPath) {
    270         SkPDFUtils::EmitPath(*clipPath, contentStream);
    271         clipFill = clipPath->getFillType();
    272     } else if (clipRect) {
    273         SkPDFUtils::AppendRectangle(*clipRect, contentStream);
    274         clipFill = SkPath::kWinding_FillType;
    275     }
    276 
    277     NOT_IMPLEMENTED(clipFill == SkPath::kInverseEvenOdd_FillType, false);
    278     NOT_IMPLEMENTED(clipFill == SkPath::kInverseWinding_FillType, false);
    279     if (clipFill == SkPath::kEvenOdd_FillType) {
    280         contentStream->writeText("W* n\n");
    281     } else {
    282         contentStream->writeText("W n\n");
    283     }
    284 }
    285 
    286 // TODO(vandebo) Take advantage of SkClipStack::getSaveCount(), the PDF
    287 // graphic state stack, and the fact that we can know all the clips used
    288 // on the page to optimize this.
    289 void GraphicStackState::updateClip(const SkClipStack& clipStack,
    290                                    const SkRegion& clipRegion,
    291                                    const SkIPoint& translation) {
    292     if (clipStack == currentEntry()->fClipStack) {
    293         return;
    294     }
    295 
    296     while (fStackDepth > 0) {
    297         pop();
    298         if (clipStack == currentEntry()->fClipStack) {
    299             return;
    300         }
    301     }
    302     push();
    303 
    304     // gsState->initialEntry()->fClipStack/Region specifies the clip that has
    305     // already been applied.  (If this is a top level device, then it specifies
    306     // a clip to the content area.  If this is a layer, then it specifies
    307     // the clip in effect when the layer was created.)  There's no need to
    308     // reapply that clip; SKCanvas's SkDrawIter will draw anything outside the
    309     // initial clip on the parent layer.  (This means there's a bug if the user
    310     // expands the clip and then uses any xfer mode that uses dst:
    311     // http://code.google.com/p/skia/issues/detail?id=228 )
    312     SkClipStack::B2FIter iter;
    313     skip_clip_stack_prefix(fEntries[0].fClipStack, clipStack, &iter);
    314 
    315     // If the clip stack does anything other than intersect or if it uses
    316     // an inverse fill type, we have to fall back to the clip region.
    317     bool needRegion = false;
    318     const SkClipStack::B2FIter::Clip* clipEntry;
    319     for (clipEntry = iter.next(); clipEntry; clipEntry = iter.next()) {
    320         if (clipEntry->fOp != SkRegion::kIntersect_Op ||
    321                 (clipEntry->fPath && clipEntry->fPath->isInverseFillType())) {
    322             needRegion = true;
    323             break;
    324         }
    325     }
    326 
    327     if (needRegion) {
    328         SkPath clipPath;
    329         SkAssertResult(clipRegion.getBoundaryPath(&clipPath));
    330         emit_clip(&clipPath, NULL, fContentStream);
    331     } else {
    332         skip_clip_stack_prefix(fEntries[0].fClipStack, clipStack, &iter);
    333         SkMatrix transform;
    334         transform.setTranslate(translation.fX, translation.fY);
    335         const SkClipStack::B2FIter::Clip* clipEntry;
    336         for (clipEntry = iter.next(); clipEntry; clipEntry = iter.next()) {
    337             SkASSERT(clipEntry->fOp == SkRegion::kIntersect_Op);
    338             if (clipEntry->fRect) {
    339                 SkRect translatedClip;
    340                 transform.mapRect(&translatedClip, *clipEntry->fRect);
    341                 emit_clip(NULL, &translatedClip, fContentStream);
    342             } else if (clipEntry->fPath) {
    343                 SkPath translatedPath;
    344                 clipEntry->fPath->transform(transform, &translatedPath);
    345                 emit_clip(&translatedPath, NULL, fContentStream);
    346             } else {
    347                 SkASSERT(false);
    348             }
    349         }
    350     }
    351     currentEntry()->fClipStack = clipStack;
    352     currentEntry()->fClipRegion = clipRegion;
    353 }
    354 
    355 void GraphicStackState::updateMatrix(const SkMatrix& matrix) {
    356     if (matrix == currentEntry()->fMatrix) {
    357         return;
    358     }
    359 
    360     if (currentEntry()->fMatrix.getType() != SkMatrix::kIdentity_Mask) {
    361         SkASSERT(fStackDepth > 0);
    362         SkASSERT(fEntries[fStackDepth].fClipStack ==
    363                  fEntries[fStackDepth -1].fClipStack);
    364         pop();
    365 
    366         SkASSERT(currentEntry()->fMatrix.getType() == SkMatrix::kIdentity_Mask);
    367     }
    368     if (matrix.getType() == SkMatrix::kIdentity_Mask) {
    369         return;
    370     }
    371 
    372     push();
    373     SkPDFUtils::AppendTransform(matrix, fContentStream);
    374     currentEntry()->fMatrix = matrix;
    375 }
    376 
    377 void GraphicStackState::updateDrawingState(const GraphicStateEntry& state) {
    378     // PDF treats a shader as a color, so we only set one or the other.
    379     if (state.fShaderIndex >= 0) {
    380         if (state.fShaderIndex != currentEntry()->fShaderIndex) {
    381             fContentStream->writeText("/Pattern CS /Pattern cs /P");
    382             fContentStream->writeDecAsText(state.fShaderIndex);
    383             fContentStream->writeText(" SCN /P");
    384             fContentStream->writeDecAsText(state.fShaderIndex);
    385             fContentStream->writeText(" scn\n");
    386             currentEntry()->fShaderIndex = state.fShaderIndex;
    387         }
    388     } else {
    389         if (state.fColor != currentEntry()->fColor ||
    390                 currentEntry()->fShaderIndex >= 0) {
    391             emit_pdf_color(state.fColor, fContentStream);
    392             fContentStream->writeText("RG ");
    393             emit_pdf_color(state.fColor, fContentStream);
    394             fContentStream->writeText("rg\n");
    395             currentEntry()->fColor = state.fColor;
    396             currentEntry()->fShaderIndex = -1;
    397         }
    398     }
    399 
    400     if (state.fGraphicStateIndex != currentEntry()->fGraphicStateIndex) {
    401         SkPDFUtils::ApplyGraphicState(state.fGraphicStateIndex, fContentStream);
    402         currentEntry()->fGraphicStateIndex = state.fGraphicStateIndex;
    403     }
    404 
    405     if (state.fTextScaleX) {
    406         if (state.fTextScaleX != currentEntry()->fTextScaleX) {
    407             SkScalar pdfScale = SkScalarMul(state.fTextScaleX,
    408                                             SkIntToScalar(100));
    409             SkPDFScalar::Append(pdfScale, fContentStream);
    410             fContentStream->writeText(" Tz\n");
    411             currentEntry()->fTextScaleX = state.fTextScaleX;
    412         }
    413         if (state.fTextFill != currentEntry()->fTextFill) {
    414             SK_COMPILE_ASSERT(SkPaint::kFill_Style == 0, enum_must_match_value);
    415             SK_COMPILE_ASSERT(SkPaint::kStroke_Style == 1,
    416                               enum_must_match_value);
    417             SK_COMPILE_ASSERT(SkPaint::kStrokeAndFill_Style == 2,
    418                               enum_must_match_value);
    419             fContentStream->writeDecAsText(state.fTextFill);
    420             fContentStream->writeText(" Tr\n");
    421             currentEntry()->fTextFill = state.fTextFill;
    422         }
    423     }
    424 }
    425 
    426 struct ContentEntry {
    427     GraphicStateEntry fState;
    428     SkDynamicMemoryWStream fContent;
    429     SkTScopedPtr<ContentEntry> fNext;
    430 };
    431 
    432 // A helper class to automatically finish a ContentEntry at the end of a
    433 // drawing method and maintain the state needed between set up and finish.
    434 class ScopedContentEntry {
    435 public:
    436     ScopedContentEntry(SkPDFDevice* device, const SkDraw& draw,
    437                        const SkPaint& paint, bool hasText = false)
    438         : fDevice(device),
    439           fContentEntry(NULL),
    440           fXfermode(SkXfermode::kSrcOver_Mode) {
    441         init(draw.fClipStack, *draw.fClip, *draw.fMatrix, paint, hasText);
    442     }
    443     ScopedContentEntry(SkPDFDevice* device, const SkClipStack* clipStack,
    444                        const SkRegion& clipRegion, const SkMatrix& matrix,
    445                        const SkPaint& paint, bool hasText = false)
    446         : fDevice(device),
    447           fContentEntry(NULL),
    448           fXfermode(SkXfermode::kSrcOver_Mode) {
    449         init(clipStack, clipRegion, matrix, paint, hasText);
    450     }
    451 
    452     ~ScopedContentEntry() {
    453         if (fContentEntry) {
    454             fDevice->finishContentEntry(fXfermode, fDstFormXObject.get());
    455         }
    456     }
    457 
    458     ContentEntry* entry() { return fContentEntry; }
    459 private:
    460     SkPDFDevice* fDevice;
    461     ContentEntry* fContentEntry;
    462     SkXfermode::Mode fXfermode;
    463     SkRefPtr<SkPDFFormXObject> fDstFormXObject;
    464 
    465     void init(const SkClipStack* clipStack, const SkRegion& clipRegion,
    466               const SkMatrix& matrix, const SkPaint& paint, bool hasText) {
    467         if (paint.getXfermode()) {
    468             paint.getXfermode()->asMode(&fXfermode);
    469         }
    470         fContentEntry = fDevice->setUpContentEntry(clipStack, clipRegion,
    471                                                    matrix, paint, hasText,
    472                                                    &fDstFormXObject);
    473     }
    474 };
    475 
    476 ////////////////////////////////////////////////////////////////////////////////
    477 
    478 SkDevice* SkPDFDeviceFactory::newDevice(SkCanvas* c, SkBitmap::Config config,
    479                                         int width, int height, bool isOpaque,
    480                                         bool isForLayer) {
    481     SkMatrix initialTransform;
    482     initialTransform.reset();
    483     SkISize size = SkISize::Make(width, height);
    484     if (isForLayer) {
    485         return SkNEW_ARGS(SkPDFDevice, (size, c->getTotalClipStack(),
    486                                         c->getTotalClip()));
    487     } else {
    488         return SkNEW_ARGS(SkPDFDevice, (size, size, initialTransform));
    489     }
    490 }
    491 
    492 static inline SkBitmap makeContentBitmap(const SkISize& contentSize,
    493                                          const SkMatrix* initialTransform) {
    494     SkBitmap bitmap;
    495     if (initialTransform) {
    496         // Compute the size of the drawing area.
    497         SkVector drawingSize;
    498         SkMatrix inverse;
    499         drawingSize.set(contentSize.fWidth, contentSize.fHeight);
    500         initialTransform->invert(&inverse);
    501         inverse.mapVectors(&drawingSize, 1);
    502         SkISize size = SkSize::Make(drawingSize.fX, drawingSize.fY).toRound();
    503         bitmap.setConfig(SkBitmap::kNo_Config, abs(size.fWidth),
    504                          abs(size.fHeight));
    505     } else {
    506         bitmap.setConfig(SkBitmap::kNo_Config, abs(contentSize.fWidth),
    507                          abs(contentSize.fHeight));
    508     }
    509 
    510     return bitmap;
    511 }
    512 
    513 SkPDFDevice::SkPDFDevice(const SkISize& pageSize, const SkISize& contentSize,
    514                          const SkMatrix& initialTransform)
    515     : SkDevice(NULL, makeContentBitmap(contentSize, &initialTransform), false),
    516       fPageSize(pageSize),
    517       fContentSize(contentSize),
    518       fLastContentEntry(NULL) {
    519     // Skia generally uses the top left as the origin but PDF natively has the
    520     // origin at the bottom left. This matrix corrects for that.  But that only
    521     // needs to be done once, we don't do it when layering.
    522     fInitialTransform.setTranslate(0, pageSize.fHeight);
    523     fInitialTransform.preScale(1, -1);
    524     fInitialTransform.preConcat(initialTransform);
    525 
    526     SkIRect existingClip = SkIRect::MakeWH(this->width(), this->height());
    527     fExistingClipStack.clipDevRect(existingClip);
    528     fExistingClipRegion.setRect(existingClip);
    529 
    530     this->init();
    531 }
    532 
    533 SkPDFDevice::SkPDFDevice(const SkISize& layerSize,
    534                          const SkClipStack& existingClipStack,
    535                          const SkRegion& existingClipRegion)
    536     : SkDevice(NULL, makeContentBitmap(layerSize, NULL), false),
    537       fPageSize(layerSize),
    538       fContentSize(layerSize),
    539       fExistingClipStack(existingClipStack),
    540       fExistingClipRegion(existingClipRegion),
    541       fLastContentEntry(NULL) {
    542     fInitialTransform.reset();
    543     this->init();
    544 }
    545 
    546 SkPDFDevice::~SkPDFDevice() {
    547     this->cleanUp();
    548 }
    549 
    550 void SkPDFDevice::init() {
    551     fResourceDict = NULL;
    552     fContentEntries.reset();
    553     fLastContentEntry = NULL;
    554 }
    555 
    556 SkDeviceFactory* SkPDFDevice::onNewDeviceFactory() {
    557     return SkNEW(SkPDFDeviceFactory);
    558 }
    559 
    560 void SkPDFDevice::cleanUp() {
    561     fGraphicStateResources.unrefAll();
    562     fXObjectResources.unrefAll();
    563     fFontResources.unrefAll();
    564     fShaderResources.unrefAll();
    565 }
    566 
    567 void SkPDFDevice::clear(SkColor color) {
    568     this->cleanUp();
    569     this->init();
    570 
    571     SkPaint paint;
    572     paint.setColor(color);
    573     paint.setStyle(SkPaint::kFill_Style);
    574     SkMatrix identity;
    575     identity.reset();
    576     ScopedContentEntry content(this, &fExistingClipStack, fExistingClipRegion,
    577                                identity, paint);
    578     internalDrawPaint(paint, content.entry());
    579 }
    580 
    581 void SkPDFDevice::drawPaint(const SkDraw& d, const SkPaint& paint) {
    582     SkPaint newPaint = paint;
    583     newPaint.setStyle(SkPaint::kFill_Style);
    584     ScopedContentEntry content(this, d, newPaint);
    585     internalDrawPaint(newPaint, content.entry());
    586 }
    587 
    588 void SkPDFDevice::internalDrawPaint(const SkPaint& paint,
    589                                     ContentEntry* contentEntry) {
    590     if (!contentEntry) {
    591         return;
    592     }
    593     SkRect bbox = SkRect::MakeWH(SkIntToScalar(this->width()),
    594                                  SkIntToScalar(this->height()));
    595     SkMatrix totalTransform = fInitialTransform;
    596     totalTransform.preConcat(contentEntry->fState.fMatrix);
    597     SkMatrix inverse;
    598     inverse.reset();
    599     totalTransform.invert(&inverse);
    600     inverse.mapRect(&bbox);
    601 
    602     SkPDFUtils::AppendRectangle(bbox, &contentEntry->fContent);
    603     SkPDFUtils::PaintPath(paint.getStyle(), SkPath::kWinding_FillType,
    604                           &contentEntry->fContent);
    605 }
    606 
    607 void SkPDFDevice::drawPoints(const SkDraw& d, SkCanvas::PointMode mode,
    608                              size_t count, const SkPoint* points,
    609                              const SkPaint& passedPaint) {
    610     if (count == 0) {
    611         return;
    612     }
    613 
    614     // SkDraw::drawPoints converts to multiple calls to fDevice->drawPath.
    615     // We only use this when there's a path effect because of the overhead
    616     // of multiple calls to setUpContentEntry it causes.
    617     if (passedPaint.getPathEffect()) {
    618         if (d.fClip->isEmpty()) {
    619             return;
    620         }
    621         SkDraw pointDraw(d);
    622         pointDraw.fDevice = this;
    623         pointDraw.drawPoints(mode, count, points, passedPaint, true);
    624         return;
    625     }
    626 
    627     const SkPaint* paint = &passedPaint;
    628     SkPaint modifiedPaint;
    629 
    630     if (mode == SkCanvas::kPoints_PointMode &&
    631             paint->getStrokeCap() != SkPaint::kRound_Cap) {
    632         modifiedPaint = *paint;
    633         paint = &modifiedPaint;
    634         if (paint->getStrokeWidth()) {
    635             // PDF won't draw a single point with square/butt caps because the
    636             // orientation is ambiguous.  Draw a rectangle instead.
    637             modifiedPaint.setStyle(SkPaint::kFill_Style);
    638             SkScalar strokeWidth = paint->getStrokeWidth();
    639             SkScalar halfStroke = SkScalarHalf(strokeWidth);
    640             for (size_t i = 0; i < count; i++) {
    641                 SkRect r = SkRect::MakeXYWH(points[i].fX, points[i].fY, 0, 0);
    642                 r.inset(-halfStroke, -halfStroke);
    643                 drawRect(d, r, modifiedPaint);
    644             }
    645             return;
    646         } else {
    647             modifiedPaint.setStrokeCap(SkPaint::kRound_Cap);
    648         }
    649     }
    650 
    651     ScopedContentEntry content(this, d, *paint);
    652     if (!content.entry()) {
    653         return;
    654     }
    655 
    656     switch (mode) {
    657         case SkCanvas::kPolygon_PointMode:
    658             SkPDFUtils::MoveTo(points[0].fX, points[0].fY,
    659                                &content.entry()->fContent);
    660             for (size_t i = 1; i < count; i++) {
    661                 SkPDFUtils::AppendLine(points[i].fX, points[i].fY,
    662                                        &content.entry()->fContent);
    663             }
    664             SkPDFUtils::StrokePath(&content.entry()->fContent);
    665             break;
    666         case SkCanvas::kLines_PointMode:
    667             for (size_t i = 0; i < count/2; i++) {
    668                 SkPDFUtils::MoveTo(points[i * 2].fX, points[i * 2].fY,
    669                                    &content.entry()->fContent);
    670                 SkPDFUtils::AppendLine(points[i * 2 + 1].fX,
    671                                        points[i * 2 + 1].fY,
    672                                        &content.entry()->fContent);
    673                 SkPDFUtils::StrokePath(&content.entry()->fContent);
    674             }
    675             break;
    676         case SkCanvas::kPoints_PointMode:
    677             SkASSERT(paint->getStrokeCap() == SkPaint::kRound_Cap);
    678             for (size_t i = 0; i < count; i++) {
    679                 SkPDFUtils::MoveTo(points[i].fX, points[i].fY,
    680                                    &content.entry()->fContent);
    681                 SkPDFUtils::ClosePath(&content.entry()->fContent);
    682                 SkPDFUtils::StrokePath(&content.entry()->fContent);
    683             }
    684             break;
    685         default:
    686             SkASSERT(false);
    687     }
    688 }
    689 
    690 void SkPDFDevice::drawRect(const SkDraw& d, const SkRect& r,
    691                            const SkPaint& paint) {
    692     if (paint.getPathEffect()) {
    693         if (d.fClip->isEmpty()) {
    694             return;
    695         }
    696         SkPath path;
    697         path.addRect(r);
    698         drawPath(d, path, paint, NULL, true);
    699         return;
    700     }
    701 
    702     ScopedContentEntry content(this, d, paint);
    703     if (!content.entry()) {
    704         return;
    705     }
    706     SkPDFUtils::AppendRectangle(r, &content.entry()->fContent);
    707     SkPDFUtils::PaintPath(paint.getStyle(), SkPath::kWinding_FillType,
    708                           &content.entry()->fContent);
    709 }
    710 
    711 void SkPDFDevice::drawPath(const SkDraw& d, const SkPath& origPath,
    712                            const SkPaint& paint, const SkMatrix* prePathMatrix,
    713                            bool pathIsMutable) {
    714     SkPath modifiedPath;
    715     SkPath* pathPtr = const_cast<SkPath*>(&origPath);
    716 
    717     SkMatrix matrix = *d.fMatrix;
    718     if (prePathMatrix) {
    719         if (paint.getPathEffect() || paint.getStyle() != SkPaint::kFill_Style) {
    720             if (!pathIsMutable) {
    721                 pathPtr = &modifiedPath;
    722                 pathIsMutable = true;
    723             }
    724             origPath.transform(*prePathMatrix, pathPtr);
    725         } else {
    726             if (!matrix.preConcat(*prePathMatrix)) {
    727                 return;
    728             }
    729         }
    730     }
    731 
    732     if (paint.getPathEffect()) {
    733         if (d.fClip->isEmpty()) {
    734             return;
    735         }
    736         if (!pathIsMutable) {
    737             pathPtr = &modifiedPath;
    738             pathIsMutable = true;
    739         }
    740         bool fill = paint.getFillPath(origPath, pathPtr);
    741 
    742         SkPaint noEffectPaint(paint);
    743         noEffectPaint.setPathEffect(NULL);
    744         if (fill) {
    745             noEffectPaint.setStyle(SkPaint::kFill_Style);
    746         } else {
    747             noEffectPaint.setStyle(SkPaint::kStroke_Style);
    748             noEffectPaint.setStrokeWidth(0);
    749         }
    750         drawPath(d, *pathPtr, noEffectPaint, NULL, true);
    751         return;
    752     }
    753 
    754     ScopedContentEntry content(this, d, paint);
    755     if (!content.entry()) {
    756         return;
    757     }
    758     SkPDFUtils::EmitPath(*pathPtr, &content.entry()->fContent);
    759     SkPDFUtils::PaintPath(paint.getStyle(), pathPtr->getFillType(),
    760                           &content.entry()->fContent);
    761 }
    762 
    763 void SkPDFDevice::drawBitmap(const SkDraw& d, const SkBitmap& bitmap,
    764                              const SkIRect* srcRect, const SkMatrix& matrix,
    765                              const SkPaint& paint) {
    766     if (d.fClip->isEmpty()) {
    767         return;
    768     }
    769 
    770     SkMatrix transform = matrix;
    771     transform.postConcat(*d.fMatrix);
    772     internalDrawBitmap(transform, d.fClipStack, *d.fClip, bitmap, srcRect,
    773                        paint);
    774 }
    775 
    776 void SkPDFDevice::drawSprite(const SkDraw& d, const SkBitmap& bitmap,
    777                              int x, int y, const SkPaint& paint) {
    778     if (d.fClip->isEmpty()) {
    779         return;
    780     }
    781 
    782     SkMatrix matrix;
    783     matrix.setTranslate(SkIntToScalar(x), SkIntToScalar(y));
    784     internalDrawBitmap(matrix, d.fClipStack, *d.fClip, bitmap, NULL, paint);
    785 }
    786 
    787 void SkPDFDevice::drawText(const SkDraw& d, const void* text, size_t len,
    788                            SkScalar x, SkScalar y, const SkPaint& paint) {
    789     SkPaint textPaint = calculate_text_paint(paint);
    790     ScopedContentEntry content(this, d, textPaint, true);
    791     if (!content.entry()) {
    792         return;
    793     }
    794 
    795     // We want the text in glyph id encoding and a writable buffer, so we end
    796     // up making a copy either way.
    797     size_t numGlyphs = paint.textToGlyphs(text, len, NULL);
    798     uint16_t* glyphIDs =
    799         (uint16_t*)sk_malloc_flags(numGlyphs * 2,
    800                                    SK_MALLOC_TEMP | SK_MALLOC_THROW);
    801     SkAutoFree autoFreeGlyphIDs(glyphIDs);
    802     if (paint.getTextEncoding() != SkPaint::kGlyphID_TextEncoding) {
    803         paint.textToGlyphs(text, len, glyphIDs);
    804         textPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
    805     } else {
    806         SkASSERT((len & 1) == 0);
    807         SkASSERT(len / 2 == numGlyphs);
    808         memcpy(glyphIDs, text, len);
    809     }
    810 
    811     SkScalar width;
    812     SkScalar* widthPtr = NULL;
    813     if (textPaint.isUnderlineText() || textPaint.isStrikeThruText())
    814         widthPtr = &width;
    815 
    816     SkDrawCacheProc glyphCacheProc = textPaint.getDrawCacheProc();
    817     align_text(glyphCacheProc, textPaint, glyphIDs, numGlyphs, &x, &y,
    818                widthPtr);
    819     content.entry()->fContent.writeText("BT\n");
    820     set_text_transform(x, y, textPaint.getTextSkewX(),
    821                        &content.entry()->fContent);
    822     size_t consumedGlyphCount = 0;
    823     while (numGlyphs > consumedGlyphCount) {
    824         updateFont(textPaint, glyphIDs[consumedGlyphCount], content.entry());
    825         SkPDFFont* font = content.entry()->fState.fFont;
    826         size_t availableGlyphs =
    827             font->glyphsToPDFFontEncoding(glyphIDs + consumedGlyphCount,
    828                                           numGlyphs - consumedGlyphCount);
    829         SkString encodedString =
    830             SkPDFString::formatString(glyphIDs + consumedGlyphCount,
    831                                       availableGlyphs, font->multiByteGlyphs());
    832         content.entry()->fContent.writeText(encodedString.c_str());
    833         consumedGlyphCount += availableGlyphs;
    834         content.entry()->fContent.writeText(" Tj\n");
    835     }
    836     content.entry()->fContent.writeText("ET\n");
    837 
    838     // Draw underline and/or strikethrough if the paint has them.
    839     // drawPosText() and drawTextOnPath() don't draw underline or strikethrough
    840     // because the raster versions don't.  Use paint instead of textPaint
    841     // because we may have changed strokeWidth to do fakeBold text.
    842     if (paint.isUnderlineText() || paint.isStrikeThruText()) {
    843         SkScalar textSize = paint.getTextSize();
    844         SkScalar height = SkScalarMul(textSize, kStdUnderline_Thickness);
    845 
    846         if (paint.isUnderlineText()) {
    847             SkScalar top = SkScalarMulAdd(textSize, kStdUnderline_Offset, y);
    848             SkRect r = SkRect::MakeXYWH(x, top - height, width, height);
    849             drawRect(d, r, paint);
    850         }
    851         if (paint.isStrikeThruText()) {
    852             SkScalar top = SkScalarMulAdd(textSize, kStdStrikeThru_Offset, y);
    853             SkRect r = SkRect::MakeXYWH(x, top - height, width, height);
    854             drawRect(d, r, paint);
    855         }
    856     }
    857 }
    858 
    859 void SkPDFDevice::drawPosText(const SkDraw& d, const void* text, size_t len,
    860                               const SkScalar pos[], SkScalar constY,
    861                               int scalarsPerPos, const SkPaint& paint) {
    862     SkASSERT(1 == scalarsPerPos || 2 == scalarsPerPos);
    863     SkPaint textPaint = calculate_text_paint(paint);
    864     ScopedContentEntry content(this, d, textPaint, true);
    865     if (!content.entry()) {
    866         return;
    867     }
    868 
    869     // Make sure we have a glyph id encoding.
    870     SkAutoFree glyphStorage;
    871     uint16_t* glyphIDs;
    872     size_t numGlyphs;
    873     if (paint.getTextEncoding() != SkPaint::kGlyphID_TextEncoding) {
    874         numGlyphs = paint.textToGlyphs(text, len, NULL);
    875         glyphIDs = (uint16_t*)sk_malloc_flags(numGlyphs * 2,
    876                                               SK_MALLOC_TEMP | SK_MALLOC_THROW);
    877         glyphStorage.set(glyphIDs);
    878         paint.textToGlyphs(text, len, glyphIDs);
    879         textPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
    880     } else {
    881         SkASSERT((len & 1) == 0);
    882         numGlyphs = len / 2;
    883         glyphIDs = (uint16_t*)text;
    884     }
    885 
    886     SkDrawCacheProc glyphCacheProc = textPaint.getDrawCacheProc();
    887     content.entry()->fContent.writeText("BT\n");
    888     updateFont(textPaint, glyphIDs[0], content.entry());
    889     for (size_t i = 0; i < numGlyphs; i++) {
    890         SkPDFFont* font = content.entry()->fState.fFont;
    891         uint16_t encodedValue = glyphIDs[i];
    892         if (font->glyphsToPDFFontEncoding(&encodedValue, 1) != 1) {
    893             updateFont(textPaint, glyphIDs[i], content.entry());
    894             i--;
    895             continue;
    896         }
    897         SkScalar x = pos[i * scalarsPerPos];
    898         SkScalar y = scalarsPerPos == 1 ? constY : pos[i * scalarsPerPos + 1];
    899         align_text(glyphCacheProc, textPaint, glyphIDs + i, 1, &x, &y, NULL);
    900         set_text_transform(x, y, textPaint.getTextSkewX(),
    901                            &content.entry()->fContent);
    902         SkString encodedString =
    903             SkPDFString::formatString(&encodedValue, 1,
    904                                       font->multiByteGlyphs());
    905         content.entry()->fContent.writeText(encodedString.c_str());
    906         content.entry()->fContent.writeText(" Tj\n");
    907     }
    908     content.entry()->fContent.writeText("ET\n");
    909 }
    910 
    911 void SkPDFDevice::drawTextOnPath(const SkDraw& d, const void* text, size_t len,
    912                                  const SkPath& path, const SkMatrix* matrix,
    913                                  const SkPaint& paint) {
    914     if (d.fClip->isEmpty()) {
    915         return;
    916     }
    917     NOT_IMPLEMENTED("drawTextOnPath", true);
    918 }
    919 
    920 void SkPDFDevice::drawVertices(const SkDraw& d, SkCanvas::VertexMode,
    921                                int vertexCount, const SkPoint verts[],
    922                                const SkPoint texs[], const SkColor colors[],
    923                                SkXfermode* xmode, const uint16_t indices[],
    924                                int indexCount, const SkPaint& paint) {
    925     if (d.fClip->isEmpty()) {
    926         return;
    927     }
    928     NOT_IMPLEMENTED("drawVerticies", true);
    929 }
    930 
    931 void SkPDFDevice::drawDevice(const SkDraw& d, SkDevice* device, int x, int y,
    932                              const SkPaint& paint) {
    933     if ((device->getDeviceCapabilities() & kVector_Capability) == 0) {
    934         // If we somehow get a raster device, do what our parent would do.
    935         SkDevice::drawDevice(d, device, x, y, paint);
    936         return;
    937     }
    938 
    939     // Assume that a vector capable device means that it's a PDF Device.
    940     SkPDFDevice* pdfDevice = static_cast<SkPDFDevice*>(device);
    941     if (pdfDevice->isContentEmpty()) {
    942         return;
    943     }
    944 
    945     SkMatrix matrix;
    946     matrix.setTranslate(SkIntToScalar(x), SkIntToScalar(y));
    947     ScopedContentEntry content(this, d.fClipStack, *d.fClip, matrix, paint);
    948     if (!content.entry()) {
    949         return;
    950     }
    951 
    952     SkPDFFormXObject* xobject = new SkPDFFormXObject(pdfDevice);
    953     fXObjectResources.push(xobject);  // Transfer reference.
    954     SkPDFUtils::DrawFormXObject(fXObjectResources.count() - 1,
    955                                 &content.entry()->fContent);
    956 }
    957 
    958 const SkRefPtr<SkPDFDict>& SkPDFDevice::getResourceDict() {
    959     if (fResourceDict.get() == NULL) {
    960         fResourceDict = new SkPDFDict;
    961         fResourceDict->unref();  // SkRefPtr and new both took a reference.
    962 
    963         if (fGraphicStateResources.count()) {
    964             SkRefPtr<SkPDFDict> extGState = new SkPDFDict();
    965             extGState->unref();  // SkRefPtr and new both took a reference.
    966             for (int i = 0; i < fGraphicStateResources.count(); i++) {
    967                 SkString nameString("G");
    968                 nameString.appendS32(i);
    969                 extGState->insert(
    970                         nameString.c_str(),
    971                         new SkPDFObjRef(fGraphicStateResources[i]))->unref();
    972             }
    973             fResourceDict->insert("ExtGState", extGState.get());
    974         }
    975 
    976         if (fXObjectResources.count()) {
    977             SkRefPtr<SkPDFDict> xObjects = new SkPDFDict();
    978             xObjects->unref();  // SkRefPtr and new both took a reference.
    979             for (int i = 0; i < fXObjectResources.count(); i++) {
    980                 SkString nameString("X");
    981                 nameString.appendS32(i);
    982                 xObjects->insert(
    983                         nameString.c_str(),
    984                         new SkPDFObjRef(fXObjectResources[i]))->unref();
    985             }
    986             fResourceDict->insert("XObject", xObjects.get());
    987         }
    988 
    989         if (fFontResources.count()) {
    990             SkRefPtr<SkPDFDict> fonts = new SkPDFDict();
    991             fonts->unref();  // SkRefPtr and new both took a reference.
    992             for (int i = 0; i < fFontResources.count(); i++) {
    993                 SkString nameString("F");
    994                 nameString.appendS32(i);
    995                 fonts->insert(nameString.c_str(),
    996                               new SkPDFObjRef(fFontResources[i]))->unref();
    997             }
    998             fResourceDict->insert("Font", fonts.get());
    999         }
   1000 
   1001         if (fShaderResources.count()) {
   1002             SkRefPtr<SkPDFDict> patterns = new SkPDFDict();
   1003             patterns->unref();  // SkRefPtr and new both took a reference.
   1004             for (int i = 0; i < fShaderResources.count(); i++) {
   1005                 SkString nameString("P");
   1006                 nameString.appendS32(i);
   1007                 patterns->insert(nameString.c_str(),
   1008                                  new SkPDFObjRef(fShaderResources[i]))->unref();
   1009             }
   1010             fResourceDict->insert("Pattern", patterns.get());
   1011         }
   1012 
   1013         // For compatibility, add all proc sets (only used for output to PS
   1014         // devices).
   1015         const char procs[][7] = {"PDF", "Text", "ImageB", "ImageC", "ImageI"};
   1016         SkRefPtr<SkPDFArray> procSets = new SkPDFArray();
   1017         procSets->unref();  // SkRefPtr and new both took a reference.
   1018         procSets->reserve(SK_ARRAY_COUNT(procs));
   1019         for (size_t i = 0; i < SK_ARRAY_COUNT(procs); i++)
   1020             procSets->append(new SkPDFName(procs[i]))->unref();
   1021         fResourceDict->insert("ProcSet", procSets.get());
   1022     }
   1023     return fResourceDict;
   1024 }
   1025 
   1026 void SkPDFDevice::getResources(SkTDArray<SkPDFObject*>* resourceList) const {
   1027     resourceList->setReserve(resourceList->count() +
   1028                              fGraphicStateResources.count() +
   1029                              fXObjectResources.count() +
   1030                              fFontResources.count() +
   1031                              fShaderResources.count());
   1032     for (int i = 0; i < fGraphicStateResources.count(); i++) {
   1033         resourceList->push(fGraphicStateResources[i]);
   1034         fGraphicStateResources[i]->ref();
   1035         fGraphicStateResources[i]->getResources(resourceList);
   1036     }
   1037     for (int i = 0; i < fXObjectResources.count(); i++) {
   1038         resourceList->push(fXObjectResources[i]);
   1039         fXObjectResources[i]->ref();
   1040         fXObjectResources[i]->getResources(resourceList);
   1041     }
   1042     for (int i = 0; i < fFontResources.count(); i++) {
   1043         resourceList->push(fFontResources[i]);
   1044         fFontResources[i]->ref();
   1045         fFontResources[i]->getResources(resourceList);
   1046     }
   1047     for (int i = 0; i < fShaderResources.count(); i++) {
   1048         resourceList->push(fShaderResources[i]);
   1049         fShaderResources[i]->ref();
   1050         fShaderResources[i]->getResources(resourceList);
   1051     }
   1052 }
   1053 
   1054 const SkTDArray<SkPDFFont*>& SkPDFDevice::getFontResources() const {
   1055     return fFontResources;
   1056 }
   1057 
   1058 SkRefPtr<SkPDFArray> SkPDFDevice::getMediaBox() const {
   1059     SkRefPtr<SkPDFInt> zero = new SkPDFInt(0);
   1060     zero->unref();  // SkRefPtr and new both took a reference.
   1061 
   1062     SkRefPtr<SkPDFArray> mediaBox = new SkPDFArray();
   1063     mediaBox->unref();  // SkRefPtr and new both took a reference.
   1064     mediaBox->reserve(4);
   1065     mediaBox->append(zero.get());
   1066     mediaBox->append(zero.get());
   1067     mediaBox->append(new SkPDFInt(fPageSize.fWidth))->unref();
   1068     mediaBox->append(new SkPDFInt(fPageSize.fHeight))->unref();
   1069     return mediaBox;
   1070 }
   1071 
   1072 SkStream* SkPDFDevice::content() const {
   1073     SkDynamicMemoryWStream data;
   1074     if (fInitialTransform.getType() != SkMatrix::kIdentity_Mask) {
   1075         SkPDFUtils::AppendTransform(fInitialTransform, &data);
   1076     }
   1077     // If the content area is the entire page, then we don't need to clip
   1078     // the content area (PDF area clips to the page size).  Otherwise,
   1079     // we have to clip to the content area; we've already applied the
   1080     // initial transform, so just clip to the device size.
   1081     if (fPageSize != fContentSize) {
   1082         SkRect r = SkRect::MakeWH(this->width(), this->height());
   1083         emit_clip(NULL, &r, &data);
   1084     }
   1085 
   1086     GraphicStackState gsState(fExistingClipStack, fExistingClipRegion, &data);
   1087     for (ContentEntry* entry = fContentEntries.get();
   1088             entry != NULL;
   1089             entry = entry->fNext.get()) {
   1090         SkIPoint translation = this->getOrigin();
   1091         translation.negate();
   1092         gsState.updateClip(entry->fState.fClipStack, entry->fState.fClipRegion,
   1093                            translation);
   1094         gsState.updateMatrix(entry->fState.fMatrix);
   1095         gsState.updateDrawingState(entry->fState);
   1096         data.write(entry->fContent.getStream(), entry->fContent.getOffset());
   1097     }
   1098     gsState.drainStack();
   1099 
   1100     SkMemoryStream* result = new SkMemoryStream;
   1101     result->setMemoryOwned(data.detach(), data.getOffset());
   1102     return result;
   1103 }
   1104 
   1105 void SkPDFDevice::createFormXObjectFromDevice(
   1106         SkRefPtr<SkPDFFormXObject>* xobject) {
   1107     *xobject = new SkPDFFormXObject(this);
   1108     (*xobject)->unref();  // SkRefPtr and new both took a reference.
   1109     cleanUp();  // Reset this device to have no content.
   1110     init();
   1111 }
   1112 
   1113 void SkPDFDevice::clearClipFromContent(const SkClipStack* clipStack,
   1114                                        const SkRegion& clipRegion) {
   1115     if (clipRegion.isEmpty() || isContentEmpty()) {
   1116         return;
   1117     }
   1118     SkRefPtr<SkPDFFormXObject> curContent;
   1119     createFormXObjectFromDevice(&curContent);
   1120 
   1121     // Redraw what we already had, but with the clip as a mask.
   1122     drawFormXObjectWithClip(curContent.get(), clipStack, clipRegion, true);
   1123 }
   1124 
   1125 void SkPDFDevice::drawFormXObjectWithClip(SkPDFFormXObject* xobject,
   1126                                           const SkClipStack* clipStack,
   1127                                           const SkRegion& clipRegion,
   1128                                           bool invertClip) {
   1129     if (clipRegion.isEmpty() && !invertClip) {
   1130         return;
   1131     }
   1132 
   1133     // Create the mask.
   1134     SkMatrix identity;
   1135     identity.reset();
   1136     SkDraw draw;
   1137     draw.fMatrix = &identity;
   1138     draw.fClip = &clipRegion;
   1139     draw.fClipStack = clipStack;
   1140     SkPaint stockPaint;
   1141     this->drawPaint(draw, stockPaint);
   1142     SkRefPtr<SkPDFFormXObject> maskFormXObject;
   1143     createFormXObjectFromDevice(&maskFormXObject);
   1144     SkRefPtr<SkPDFGraphicState> sMaskGS =
   1145         SkPDFGraphicState::getSMaskGraphicState(maskFormXObject.get(),
   1146                                                 invertClip);
   1147     sMaskGS->unref();  // SkRefPtr and getSMaskGraphicState both took a ref.
   1148 
   1149     // Draw the xobject with the clip as a mask.
   1150     ScopedContentEntry content(this, &fExistingClipStack, fExistingClipRegion,
   1151                                  identity, stockPaint);
   1152     if (!content.entry()) {
   1153         return;
   1154     }
   1155     SkPDFUtils::ApplyGraphicState(addGraphicStateResource(sMaskGS.get()),
   1156                                   &content.entry()->fContent);
   1157     SkPDFUtils::DrawFormXObject(fXObjectResources.count(),
   1158                                 &content.entry()->fContent);
   1159     fXObjectResources.push(xobject);
   1160     xobject->ref();
   1161 
   1162     sMaskGS = SkPDFGraphicState::getNoSMaskGraphicState();
   1163     sMaskGS->unref();  // SkRefPtr and getSMaskGraphicState both took a ref.
   1164     SkPDFUtils::ApplyGraphicState(addGraphicStateResource(sMaskGS.get()),
   1165                                   &content.entry()->fContent);
   1166 }
   1167 
   1168 ContentEntry* SkPDFDevice::setUpContentEntry(const SkClipStack* clipStack,
   1169                                              const SkRegion& clipRegion,
   1170                                              const SkMatrix& matrix,
   1171                                              const SkPaint& paint,
   1172                                              bool hasText,
   1173                                              SkRefPtr<SkPDFFormXObject>* dst) {
   1174     if (clipRegion.isEmpty()) {
   1175         return NULL;
   1176     }
   1177 
   1178     // The clip stack can come from an SkDraw where it is technically optional.
   1179     SkClipStack synthesizedClipStack;
   1180     if (clipStack == NULL) {
   1181         if (clipRegion == fExistingClipRegion) {
   1182             clipStack = &fExistingClipStack;
   1183         } else {
   1184             // GraphicStackState::updateClip expects the clip stack to have
   1185             // fExistingClip as a prefix, so start there, then set the clip
   1186             // to the passed region.
   1187             synthesizedClipStack = fExistingClipStack;
   1188             SkPath clipPath;
   1189             clipRegion.getBoundaryPath(&clipPath);
   1190             synthesizedClipStack.clipDevPath(clipPath, SkRegion::kReplace_Op);
   1191             clipStack = &synthesizedClipStack;
   1192         }
   1193     }
   1194 
   1195     SkXfermode::Mode xfermode = SkXfermode::kSrcOver_Mode;
   1196     if (paint.getXfermode()) {
   1197         paint.getXfermode()->asMode(&xfermode);
   1198     }
   1199 
   1200     if (xfermode == SkXfermode::kClear_Mode ||
   1201             xfermode == SkXfermode::kSrc_Mode) {
   1202         this->clearClipFromContent(clipStack, clipRegion);
   1203     } else if (xfermode == SkXfermode::kSrcIn_Mode ||
   1204                xfermode == SkXfermode::kDstIn_Mode ||
   1205                xfermode == SkXfermode::kSrcOut_Mode ||
   1206                xfermode == SkXfermode::kDstOut_Mode) {
   1207         // For the following modes, we use both source and destination, but
   1208         // we use one as a smask for the other, so we have to make form xobjects
   1209         // out of both of them: SrcIn, DstIn, SrcOut, DstOut.
   1210         if (isContentEmpty()) {
   1211             return NULL;
   1212         } else {
   1213             createFormXObjectFromDevice(dst);
   1214         }
   1215     }
   1216     // TODO(vandebo) Figure out how/if we can handle the following modes:
   1217     // SrcAtop, DestAtop, Xor, Plus.
   1218 
   1219     // These xfer modes don't draw source at all.
   1220     if (xfermode == SkXfermode::kClear_Mode ||
   1221             xfermode == SkXfermode::kDst_Mode) {
   1222         return NULL;
   1223     }
   1224 
   1225     ContentEntry* entry;
   1226     SkTScopedPtr<ContentEntry> newEntry;
   1227     if (fLastContentEntry && fLastContentEntry->fContent.getOffset() == 0) {
   1228         entry = fLastContentEntry;
   1229     } else {
   1230         newEntry.reset(new ContentEntry);
   1231         entry = newEntry.get();
   1232     }
   1233 
   1234     populateGraphicStateEntryFromPaint(matrix, *clipStack, clipRegion, paint,
   1235                                        hasText, &entry->fState);
   1236     if (fLastContentEntry && xfermode != SkXfermode::kDstOver_Mode &&
   1237             entry->fState.compareInitialState(fLastContentEntry->fState)) {
   1238         return fLastContentEntry;
   1239     }
   1240 
   1241     if (!fLastContentEntry) {
   1242         fContentEntries.reset(entry);
   1243         fLastContentEntry = entry;
   1244     } else if (xfermode == SkXfermode::kDstOver_Mode) {
   1245         entry->fNext.reset(fContentEntries.release());
   1246         fContentEntries.reset(entry);
   1247     } else {
   1248         fLastContentEntry->fNext.reset(entry);
   1249         fLastContentEntry = entry;
   1250     }
   1251     newEntry.release();
   1252     return entry;
   1253 }
   1254 
   1255 void SkPDFDevice::finishContentEntry(const SkXfermode::Mode xfermode,
   1256                                      SkPDFFormXObject* dst) {
   1257     if (xfermode != SkXfermode::kSrcIn_Mode &&
   1258             xfermode != SkXfermode::kDstIn_Mode &&
   1259             xfermode != SkXfermode::kSrcOut_Mode &&
   1260             xfermode != SkXfermode::kDstOut_Mode) {
   1261         SkASSERT(!dst);
   1262         return;
   1263     }
   1264     SkASSERT(dst);
   1265     SkASSERT(!fContentEntries->fNext.get());
   1266 
   1267     // We have to make a copy of these here because changing the current
   1268     // content into a form xobject will destroy them.
   1269     SkClipStack clipStack = fContentEntries->fState.fClipStack;
   1270     SkRegion clipRegion = fContentEntries->fState.fClipRegion;
   1271 
   1272     SkRefPtr<SkPDFFormXObject> srcFormXObject;
   1273     if (!isContentEmpty()) {
   1274         createFormXObjectFromDevice(&srcFormXObject);
   1275     }
   1276 
   1277     drawFormXObjectWithClip(dst, &clipStack, clipRegion, true);
   1278 
   1279     // We've redrawn dst minus the clip area, if there's no src, we're done.
   1280     if (!srcFormXObject.get()) {
   1281         return;
   1282     }
   1283 
   1284     SkMatrix identity;
   1285     identity.reset();
   1286     SkPaint stockPaint;
   1287     ScopedContentEntry inClipContentEntry(this, &fExistingClipStack,
   1288                                           fExistingClipRegion, identity,
   1289                                           stockPaint);
   1290     if (!inClipContentEntry.entry()) {
   1291         return;
   1292     }
   1293 
   1294     SkRefPtr<SkPDFGraphicState> sMaskGS;
   1295     if (xfermode == SkXfermode::kSrcIn_Mode ||
   1296             xfermode == SkXfermode::kSrcOut_Mode) {
   1297         sMaskGS = SkPDFGraphicState::getSMaskGraphicState(
   1298                 dst, xfermode == SkXfermode::kSrcOut_Mode);
   1299         fXObjectResources.push(srcFormXObject.get());
   1300         srcFormXObject->ref();
   1301     } else {
   1302         sMaskGS = SkPDFGraphicState::getSMaskGraphicState(
   1303                 srcFormXObject.get(), xfermode == SkXfermode::kDstOut_Mode);
   1304         // dst already added to fXObjectResources in drawFormXObjectWithClip.
   1305     }
   1306     sMaskGS->unref();  // SkRefPtr and getSMaskGraphicState both took a ref.
   1307     SkPDFUtils::ApplyGraphicState(addGraphicStateResource(sMaskGS.get()),
   1308                                   &inClipContentEntry.entry()->fContent);
   1309 
   1310     SkPDFUtils::DrawFormXObject(fXObjectResources.count() - 1,
   1311                                 &inClipContentEntry.entry()->fContent);
   1312 
   1313     sMaskGS = SkPDFGraphicState::getNoSMaskGraphicState();
   1314     sMaskGS->unref();  // SkRefPtr and getSMaskGraphicState both took a ref.
   1315     SkPDFUtils::ApplyGraphicState(addGraphicStateResource(sMaskGS.get()),
   1316                                   &inClipContentEntry.entry()->fContent);
   1317 }
   1318 
   1319 bool SkPDFDevice::isContentEmpty() {
   1320     if (!fContentEntries.get() || fContentEntries->fContent.getOffset() == 0) {
   1321         SkASSERT(!fContentEntries.get() || !fContentEntries->fNext.get());
   1322         return true;
   1323     }
   1324     return false;
   1325 }
   1326 
   1327 
   1328 void SkPDFDevice::populateGraphicStateEntryFromPaint(
   1329         const SkMatrix& matrix,
   1330         const SkClipStack& clipStack,
   1331         const SkRegion& clipRegion,
   1332         const SkPaint& paint,
   1333         bool hasText,
   1334         GraphicStateEntry* entry) {
   1335     SkASSERT(paint.getPathEffect() == NULL);
   1336 
   1337     NOT_IMPLEMENTED(paint.getMaskFilter() != NULL, false);
   1338     NOT_IMPLEMENTED(paint.getColorFilter() != NULL, false);
   1339 
   1340     entry->fMatrix = matrix;
   1341     entry->fClipStack = clipStack;
   1342     entry->fClipRegion = clipRegion;
   1343 
   1344     // PDF treats a shader as a color, so we only set one or the other.
   1345     SkRefPtr<SkPDFShader> pdfShader;
   1346     const SkShader* shader = paint.getShader();
   1347     SkColor color = paint.getColor();
   1348     if (shader) {
   1349         // PDF positions patterns relative to the initial transform, so
   1350         // we need to apply the current transform to the shader parameters.
   1351         SkMatrix transform = matrix;
   1352         transform.postConcat(fInitialTransform);
   1353 
   1354         // PDF doesn't support kClamp_TileMode, so we simulate it by making
   1355         // a pattern the size of the current clip.
   1356         SkIRect bounds = clipRegion.getBounds();
   1357         pdfShader = SkPDFShader::getPDFShader(*shader, transform, bounds);
   1358         SkSafeUnref(pdfShader.get());  // getShader and SkRefPtr both took a ref
   1359 
   1360         // A color shader is treated as an invalid shader so we don't have
   1361         // to set a shader just for a color.
   1362         if (pdfShader.get() == NULL) {
   1363             entry->fColor = 0;
   1364             color = 0;
   1365 
   1366             // Check for a color shader.
   1367             SkShader::GradientInfo gradientInfo;
   1368             SkColor gradientColor;
   1369             gradientInfo.fColors = &gradientColor;
   1370             gradientInfo.fColorOffsets = NULL;
   1371             gradientInfo.fColorCount = 1;
   1372             if (shader->asAGradient(&gradientInfo) ==
   1373                     SkShader::kColor_GradientType) {
   1374                 entry->fColor = SkColorSetA(gradientColor, 0xFF);
   1375                 color = gradientColor;
   1376             }
   1377         }
   1378     }
   1379 
   1380     if (pdfShader) {
   1381         // pdfShader has been canonicalized so we can directly compare
   1382         // pointers.
   1383         int resourceIndex = fShaderResources.find(pdfShader.get());
   1384         if (resourceIndex < 0) {
   1385             resourceIndex = fShaderResources.count();
   1386             fShaderResources.push(pdfShader.get());
   1387             pdfShader->ref();
   1388         }
   1389         entry->fShaderIndex = resourceIndex;
   1390     } else {
   1391         entry->fShaderIndex = -1;
   1392         entry->fColor = SkColorSetA(paint.getColor(), 0xFF);
   1393         color = paint.getColor();
   1394     }
   1395 
   1396     SkRefPtr<SkPDFGraphicState> newGraphicState;
   1397     if (color == paint.getColor()) {
   1398         newGraphicState = SkPDFGraphicState::getGraphicStateForPaint(paint);
   1399     } else {
   1400         SkPaint newPaint = paint;
   1401         newPaint.setColor(color);
   1402         newGraphicState = SkPDFGraphicState::getGraphicStateForPaint(newPaint);
   1403     }
   1404     newGraphicState->unref();  // getGraphicState and SkRefPtr both took a ref.
   1405     int resourceIndex = addGraphicStateResource(newGraphicState.get());
   1406     entry->fGraphicStateIndex = resourceIndex;
   1407 
   1408     if (hasText) {
   1409         entry->fTextScaleX = paint.getTextScaleX();
   1410         entry->fTextFill = paint.getStyle();
   1411     } else {
   1412         entry->fTextScaleX = 0;
   1413     }
   1414 }
   1415 
   1416 int SkPDFDevice::addGraphicStateResource(SkPDFGraphicState* gs) {
   1417     // Assumes that gs has been canonicalized (so we can directly compare
   1418     // pointers).
   1419     int result = fGraphicStateResources.find(gs);
   1420     if (result < 0) {
   1421         result = fGraphicStateResources.count();
   1422         fGraphicStateResources.push(gs);
   1423         gs->ref();
   1424     }
   1425     return result;
   1426 }
   1427 
   1428 void SkPDFDevice::updateFont(const SkPaint& paint, uint16_t glyphID,
   1429                              ContentEntry* contentEntry) {
   1430     SkTypeface* typeface = paint.getTypeface();
   1431     if (contentEntry->fState.fFont == NULL ||
   1432             contentEntry->fState.fTextSize != paint.getTextSize() ||
   1433             !contentEntry->fState.fFont->hasGlyph(glyphID)) {
   1434         int fontIndex = getFontResourceIndex(typeface, glyphID);
   1435         contentEntry->fContent.writeText("/F");
   1436         contentEntry->fContent.writeDecAsText(fontIndex);
   1437         contentEntry->fContent.writeText(" ");
   1438         SkPDFScalar::Append(paint.getTextSize(), &contentEntry->fContent);
   1439         contentEntry->fContent.writeText(" Tf\n");
   1440         contentEntry->fState.fFont = fFontResources[fontIndex];
   1441     }
   1442 }
   1443 
   1444 int SkPDFDevice::getFontResourceIndex(SkTypeface* typeface, uint16_t glyphID) {
   1445     SkRefPtr<SkPDFFont> newFont = SkPDFFont::getFontResource(typeface, glyphID);
   1446     newFont->unref();  // getFontResource and SkRefPtr both took a ref.
   1447     int resourceIndex = fFontResources.find(newFont.get());
   1448     if (resourceIndex < 0) {
   1449         resourceIndex = fFontResources.count();
   1450         fFontResources.push(newFont.get());
   1451         newFont->ref();
   1452     }
   1453     return resourceIndex;
   1454 }
   1455 
   1456 void SkPDFDevice::internalDrawBitmap(const SkMatrix& matrix,
   1457                                      const SkClipStack* clipStack,
   1458                                      const SkRegion& clipRegion,
   1459                                      const SkBitmap& bitmap,
   1460                                      const SkIRect* srcRect,
   1461                                      const SkPaint& paint) {
   1462     SkMatrix scaled;
   1463     // Adjust for origin flip.
   1464     scaled.setScale(1, -1);
   1465     scaled.postTranslate(0, 1);
   1466     // Scale the image up from 1x1 to WxH.
   1467     SkIRect subset = SkIRect::MakeWH(bitmap.width(), bitmap.height());
   1468     scaled.postScale(SkIntToScalar(subset.width()),
   1469                      SkIntToScalar(subset.height()));
   1470     scaled.postConcat(matrix);
   1471     ScopedContentEntry content(this, clipStack, clipRegion, scaled, paint);
   1472     if (!content.entry()) {
   1473         return;
   1474     }
   1475 
   1476     if (srcRect && !subset.intersect(*srcRect)) {
   1477         return;
   1478     }
   1479 
   1480     SkPDFImage* image = SkPDFImage::CreateImage(bitmap, subset, paint);
   1481     if (!image) {
   1482         return;
   1483     }
   1484 
   1485     fXObjectResources.push(image);  // Transfer reference.
   1486     SkPDFUtils::DrawFormXObject(fXObjectResources.count() - 1,
   1487                                 &content.entry()->fContent);
   1488 }
   1489