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 
SkPDFFormXObject(SkPDFDevice * device)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(nullptr, 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  */
SkPDFFormXObject(SkStream * content,SkRect bbox,SkPDFDict * resourceDict)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  */
init(const char * colorSpace,SkPDFDict * resourceDict,SkPDFArray * bbox)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 != nullptr) {
72         group->insertName("CS", colorSpace);
73     }
74     group->insertBool("I", true);  // Isolated.
75     this->insertObject("Group", group.detach());
76 }
77 
~SkPDFFormXObject()78 SkPDFFormXObject::~SkPDFFormXObject() {}
79