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 "SkPDFCatalog.h"
14#include "SkPDFDevice.h"
15#include "SkPDFResourceDict.h"
16#include "SkPDFUtils.h"
17#include "SkStream.h"
18#include "SkTypes.h"
19
20SkPDFFormXObject::SkPDFFormXObject(SkPDFDevice* device) {
21    // We don't want to keep around device because we'd have two copies
22    // of content, so reference or copy everything we need (content and
23    // resources).
24    SkTSet<SkPDFObject*> emptySet;
25    SkPDFResourceDict* resourceDict = device->getResourceDict();
26    resourceDict->getReferencedResources(emptySet, &fResources, false);
27
28    SkAutoTUnref<SkStream> content(device->content());
29    setData(content.get());
30
31    SkAutoTUnref<SkPDFArray> bboxArray(device->copyMediaBox());
32    init(NULL, resourceDict, bboxArray);
33
34    // We invert the initial transform and apply that to the xobject so that
35    // it doesn't get applied twice. We can't just undo it because it's
36    // embedded in things like shaders and images.
37    if (!device->initialTransform().isIdentity()) {
38        SkMatrix inverse;
39        if (!device->initialTransform().invert(&inverse)) {
40            // The initial transform should be invertible.
41            SkASSERT(false);
42            inverse.reset();
43        }
44        insert("Matrix", SkPDFUtils::MatrixToArray(inverse))->unref();
45    }
46}
47
48/**
49 * Creates a FormXObject from a content stream and associated resources.
50 */
51SkPDFFormXObject::SkPDFFormXObject(SkStream* content, SkRect bbox,
52                                   SkPDFResourceDict* resourceDict) {
53    SkTSet<SkPDFObject*> emptySet;
54    resourceDict->getReferencedResources(emptySet, &fResources, false);
55
56    setData(content);
57
58    SkAutoTUnref<SkPDFArray> bboxArray(SkPDFUtils::RectToArray(bbox));
59    init("DeviceRGB", resourceDict, bboxArray);
60}
61
62/**
63 * Common initialization code.
64 * Note that bbox is unreferenced here, so calling code does not need worry.
65 */
66void SkPDFFormXObject::init(const char* colorSpace,
67                            SkPDFDict* resourceDict, SkPDFArray* bbox) {
68    insertName("Type", "XObject");
69    insertName("Subtype", "Form");
70    insert("Resources", resourceDict);
71    insert("BBox", bbox);
72
73    // Right now SkPDFFormXObject is only used for saveLayer, which implies
74    // isolated blending.  Do this conditionally if that changes.
75    SkAutoTUnref<SkPDFDict> group(new SkPDFDict("Group"));
76    group->insertName("S", "Transparency");
77
78    if (colorSpace != NULL) {
79        group->insertName("CS", colorSpace);
80    }
81    group->insert("I", new SkPDFBool(true))->unref();  // Isolated.
82    insert("Group", group.get());
83}
84
85SkPDFFormXObject::~SkPDFFormXObject() {
86    fResources.unrefAll();
87}
88
89void SkPDFFormXObject::getResources(
90        const SkTSet<SkPDFObject*>& knownResourceObjects,
91        SkTSet<SkPDFObject*>* newResourceObjects) {
92    GetResourcesHelper(&fResources.toArray(),
93                       knownResourceObjects,
94                       newResourceObjects);
95}
96