1 2 /* 3 * Copyright 2010 The Android Open Source Project 4 * 5 * Use of this source code is governed by a BSD-style license that can be 6 * found in the LICENSE file. 7 */ 8 9 10 #include "SkPDFFormXObject.h" 11 12 #include "SkMatrix.h" 13 #include "SkPDFDevice.h" 14 #include "SkPDFUtils.h" 15 #include "SkStream.h" 16 #include "SkTypes.h" 17 18 SkPDFFormXObject::SkPDFFormXObject(SkPDFDevice* device) { 19 // We don't want to keep around device because we'd have two copies 20 // of content, so reference or copy everything we need (content and 21 // resources). 22 SkAutoTUnref<SkPDFDict> resourceDict(device->createResourceDict()); 23 24 SkAutoTDelete<SkStreamAsset> content(device->content()); 25 this->setData(content.get()); 26 27 SkAutoTUnref<SkPDFArray> bboxArray(device->copyMediaBox()); 28 this->init(NULL, resourceDict.get(), bboxArray); 29 30 // We invert the initial transform and apply that to the xobject so that 31 // it doesn't get applied twice. We can't just undo it because it's 32 // embedded in things like shaders and images. 33 if (!device->initialTransform().isIdentity()) { 34 SkMatrix inverse; 35 if (!device->initialTransform().invert(&inverse)) { 36 // The initial transform should be invertible. 37 SkASSERT(false); 38 inverse.reset(); 39 } 40 this->insertObject("Matrix", SkPDFUtils::MatrixToArray(inverse)); 41 } 42 } 43 44 /** 45 * Creates a FormXObject from a content stream and associated resources. 46 */ 47 SkPDFFormXObject::SkPDFFormXObject(SkStream* content, SkRect bbox, 48 SkPDFDict* resourceDict) { 49 setData(content); 50 51 SkAutoTUnref<SkPDFArray> bboxArray(SkPDFUtils::RectToArray(bbox)); 52 init("DeviceRGB", resourceDict, bboxArray); 53 } 54 55 /** 56 * Common initialization code. 57 * Note that bbox is unreferenced here, so calling code does not need worry. 58 */ 59 void SkPDFFormXObject::init(const char* colorSpace, 60 SkPDFDict* resourceDict, SkPDFArray* bbox) { 61 this->insertName("Type", "XObject"); 62 this->insertName("Subtype", "Form"); 63 this->insertObject("Resources", SkRef(resourceDict)); 64 this->insertObject("BBox", SkRef(bbox)); 65 66 // Right now SkPDFFormXObject is only used for saveLayer, which implies 67 // isolated blending. Do this conditionally if that changes. 68 SkAutoTUnref<SkPDFDict> group(new SkPDFDict("Group")); 69 group->insertName("S", "Transparency"); 70 71 if (colorSpace != NULL) { 72 group->insertName("CS", colorSpace); 73 } 74 group->insertBool("I", true); // Isolated. 75 this->insertObject("Group", group.detach()); 76 } 77 78 SkPDFFormXObject::~SkPDFFormXObject() {} 79