Add PDF support for drawDevice using a form xobject.

This depends on:
http://codereview.appspot.com/2719041
http://codereview.appspot.com/2720041
http://codereview.appspot.com/2721041

Review URL: http://codereview.appspot.com/2710042

git-svn-id: http://skia.googlecode.com/svn/trunk@621 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
vandebo@chromium.org 2010-10-26 19:54:45 +00:00
parent 7d71f7f655
commit eb6c7596af
4 changed files with 181 additions and 3 deletions

View File

@ -0,0 +1,73 @@
/*
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef SkPDFFormXObject_DEFINED
#define SkPDFFormXObject_DEFINED
#include "SkPDFStream.h"
#include "SkPDFTypes.h"
#include "SkRefCnt.h"
#include "SkString.h"
class SkMatrix;
class SkPDFDevice;
class SkPDFCatalog;
/** \class SkPDFFormXObject
A form XObject; a self containted description of graphics objects. A form
XObject is basically a page object with slightly different syntax, that
can be drawn onto a page.
*/
// The caller could keep track of the form XObjects it creates and
// canonicalize them, but the Skia API doesn't provide enough context to
// automatically do it (trivially).
class SkPDFFormXObject : public SkPDFObject {
public:
/** Create a PDF form XObject. Entries for the dictionary entries are
* automatically added.
* @param device The set of graphical elements on this form.
* @param matrix The mapping from user space to form space.
*/
SkPDFFormXObject(SkPDFDevice* device, const SkMatrix& matrix);
virtual ~SkPDFFormXObject();
// The SkPDFObject interface.
virtual void emitObject(SkWStream* stream, SkPDFCatalog* catalog,
bool indirect);
virtual size_t getOutputSize(SkPDFCatalog* catalog, bool indirect);
virtual void getResources(SkTDArray<SkPDFObject*>* resourceList);
/** Add the value to the stream dictionary with the given key.
* @param key The key for this dictionary entry.
* @param value The value for this dictionary entry.
*/
void insert(SkPDFName* key, SkPDFObject* value);
/** Add the value to the stream dictionary with the given key.
* @param key The text of the key for this dictionary entry.
* @param value The value for this dictionary entry.
*/
void insert(const char key[], SkPDFObject* value);
private:
SkString fContent;
SkRefPtr<SkPDFDevice> fDevice;
SkRefPtr<SkPDFStream> fStream;
};
#endif

View File

@ -21,6 +21,7 @@
#include "SkPath.h"
#include "SkPDFImage.h"
#include "SkPDFGraphicState.h"
#include "SkPDFFormXObject.h"
#include "SkPDFTypes.h"
#include "SkPDFStream.h"
#include "SkRect.h"
@ -273,9 +274,25 @@ void SkPDFDevice::drawVertices(const SkDraw&, SkCanvas::VertexMode,
NOT_IMPLEMENTED("drawVerticies", true);
}
void SkPDFDevice::drawDevice(const SkDraw&, SkDevice*, int x, int y,
const SkPaint&) {
SkASSERT(false);
void SkPDFDevice::drawDevice(const SkDraw& d, SkDevice* device, int x, int y,
const SkPaint& paint) {
if ((device->getDeviceCapabilities() & kVector_Capability) == 0) {
// If we somehow get a raster device, do what our parent would do.
SkDevice::drawDevice(d, device, x, y, paint);
return;
}
// Assume that a vector capable device means that it's a PDF Device.
// TODO(vandebo) handle the paint (alpha and compositing mode).
SkMatrix matrix;
matrix.setTranslate(x, y);
SkPDFDevice* pdfDevice = static_cast<SkPDFDevice*>(device);
SkPDFFormXObject* xobject = new SkPDFFormXObject(pdfDevice, matrix);
fXObjectResources.push(xobject); // Transfer reference.
fContent.append("/X");
fContent.appendS32(fXObjectResources.count() - 1);
fContent.append(" Do\n");
}
const SkRefPtr<SkPDFDict>& SkPDFDevice::getResourceDict() {

View File

@ -0,0 +1,87 @@
/*
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "SkPDFFormXObject.h"
#include "SkMatrix.h"
#include "SkPDFCatalog.h"
#include "SkPDFDevice.h"
#include "SkStream.h"
#include "SkTypes.h"
SkPDFFormXObject::SkPDFFormXObject(SkPDFDevice* device, const SkMatrix& matrix)
: fContent(device->content(false)),
fDevice(device) {
SkMemoryStream* stream_data = new SkMemoryStream(fContent.c_str(),
fContent.size());
SkAutoUnref stream_data_unref(stream_data);
fStream = new SkPDFStream(stream_data);
fStream->unref(); // SkRefPtr and new both took a reference.
SkRefPtr<SkPDFName> typeValue = new SkPDFName("XObject");
typeValue->unref(); // SkRefPtr and new both took a reference.
insert("Type", typeValue.get());
SkRefPtr<SkPDFName> subTypeValue = new SkPDFName("Form");
subTypeValue->unref(); // SkRefPtr and new both took a reference.
insert("Subtype", subTypeValue.get());
insert("BBox", device->getMediaBox().get());
insert("Resources", device->getResourceDict().get());
if (!matrix.isIdentity()) {
SkRefPtr<SkPDFArray> transformArray = new SkPDFArray();
transformArray->unref(); // SkRefPtr and new both took a reference.
transformArray->reserve(6);
SkScalar transform[6];
SkAssertResult(matrix.pdfTransform(transform));
for (size_t i = 0; i < SK_ARRAY_COUNT(transform); i++) {
SkRefPtr<SkPDFScalar> val = new SkPDFScalar(transform[i]);
val->unref(); // SkRefPtr and new both took a reference.
transformArray->append(val.get());
}
insert("Matrix", transformArray.get());
}
}
SkPDFFormXObject::~SkPDFFormXObject() {}
void SkPDFFormXObject::emitObject(SkWStream* stream, SkPDFCatalog* catalog,
bool indirect) {
if (indirect)
return emitIndirectObject(stream, catalog);
fStream->emitObject(stream, catalog, indirect);
}
size_t SkPDFFormXObject::getOutputSize(SkPDFCatalog* catalog, bool indirect) {
if (indirect)
return getIndirectOutputSize(catalog);
return fStream->getOutputSize(catalog, indirect);
}
void SkPDFFormXObject::getResources(SkTDArray<SkPDFObject*>* resourceList) {
fDevice->getResources(resourceList);
}
void SkPDFFormXObject::insert(SkPDFName* key, SkPDFObject* value) {
fStream->insert(key, value);
}
void SkPDFFormXObject::insert(const char key[], SkPDFObject* value) {
fStream->insert(key, value);
}

View File

@ -2,6 +2,7 @@ SOURCE := \
SkPDFCatalog.cpp \
SkPDFDevice.cpp \
SkPDFDocument.cpp \
SkPDFFormXObject.cpp \
SkPDFGraphicState.cpp \
SkPDFImage.cpp \
SkPDFPage.cpp \