michael@0: michael@0: /* michael@0: * Copyright 2010 The Android Open Source Project michael@0: * michael@0: * Use of this source code is governed by a BSD-style license that can be michael@0: * found in the LICENSE file. michael@0: */ michael@0: michael@0: michael@0: #include "SkPDFFormXObject.h" michael@0: michael@0: #include "SkMatrix.h" michael@0: #include "SkPDFCatalog.h" michael@0: #include "SkPDFDevice.h" michael@0: #include "SkPDFResourceDict.h" michael@0: #include "SkPDFUtils.h" michael@0: #include "SkStream.h" michael@0: #include "SkTypes.h" michael@0: michael@0: SkPDFFormXObject::SkPDFFormXObject(SkPDFDevice* device) { michael@0: // We don't want to keep around device because we'd have two copies michael@0: // of content, so reference or copy everything we need (content and michael@0: // resources). michael@0: SkTSet emptySet; michael@0: SkPDFResourceDict* resourceDict = device->getResourceDict(); michael@0: resourceDict->getReferencedResources(emptySet, &fResources, false); michael@0: michael@0: SkAutoTUnref content(device->content()); michael@0: setData(content.get()); michael@0: michael@0: SkAutoTUnref bboxArray(device->copyMediaBox()); michael@0: init(NULL, resourceDict, bboxArray); michael@0: michael@0: // We invert the initial transform and apply that to the xobject so that michael@0: // it doesn't get applied twice. We can't just undo it because it's michael@0: // embedded in things like shaders and images. michael@0: if (!device->initialTransform().isIdentity()) { michael@0: SkMatrix inverse; michael@0: if (!device->initialTransform().invert(&inverse)) { michael@0: // The initial transform should be invertible. michael@0: SkASSERT(false); michael@0: inverse.reset(); michael@0: } michael@0: insert("Matrix", SkPDFUtils::MatrixToArray(inverse))->unref(); michael@0: } michael@0: } michael@0: michael@0: /** michael@0: * Creates a FormXObject from a content stream and associated resources. michael@0: */ michael@0: SkPDFFormXObject::SkPDFFormXObject(SkStream* content, SkRect bbox, michael@0: SkPDFResourceDict* resourceDict) { michael@0: SkTSet emptySet; michael@0: resourceDict->getReferencedResources(emptySet, &fResources, false); michael@0: michael@0: setData(content); michael@0: michael@0: SkAutoTUnref bboxArray(SkPDFUtils::RectToArray(bbox)); michael@0: init("DeviceRGB", resourceDict, bboxArray); michael@0: } michael@0: michael@0: /** michael@0: * Common initialization code. michael@0: * Note that bbox is unreferenced here, so calling code does not need worry. michael@0: */ michael@0: void SkPDFFormXObject::init(const char* colorSpace, michael@0: SkPDFDict* resourceDict, SkPDFArray* bbox) { michael@0: insertName("Type", "XObject"); michael@0: insertName("Subtype", "Form"); michael@0: insert("Resources", resourceDict); michael@0: insert("BBox", bbox); michael@0: michael@0: // Right now SkPDFFormXObject is only used for saveLayer, which implies michael@0: // isolated blending. Do this conditionally if that changes. michael@0: SkAutoTUnref group(new SkPDFDict("Group")); michael@0: group->insertName("S", "Transparency"); michael@0: michael@0: if (colorSpace != NULL) { michael@0: group->insertName("CS", colorSpace); michael@0: } michael@0: group->insert("I", new SkPDFBool(true))->unref(); // Isolated. michael@0: insert("Group", group.get()); michael@0: } michael@0: michael@0: SkPDFFormXObject::~SkPDFFormXObject() { michael@0: fResources.unrefAll(); michael@0: } michael@0: michael@0: void SkPDFFormXObject::getResources( michael@0: const SkTSet& knownResourceObjects, michael@0: SkTSet* newResourceObjects) { michael@0: GetResourcesHelper(&fResources.toArray(), michael@0: knownResourceObjects, michael@0: newResourceObjects); michael@0: }