skia2/include/pdf/SkPDFShader.h
vandebo@chromium.org da912d61ed [PDF] Add support for Shaders.
- Shaders, or as they are referred to in PDF, patterns, are drawn in the coordinate system of the initial page, so when we canonicalize them, we have to consider the current transform and where they are constructed.

- Image shaders are tiled by default, this makes repeat and mirror modes easy, but means we have to draw a pattern as large as the current clip to support clamp mode.

- Gradient shaders are implemented with type 4 functions, which are basically small snippets of post script code.  I've tried to make the code generation modular and heavily commented to make it easy to understand or expand.

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

git-svn-id: http://skia.googlecode.com/svn/trunk@905 2bbb7eff-a529-9590-31e7-b0007b416f81
2011-03-08 18:31:02 +00:00

111 lines
3.6 KiB
C++

/*
* Copyright (C) 2011 Google Inc.
*
* 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 SkPDFShader_DEFINED
#define SkPDFShader_DEFINED
#include "SkPDFStream.h"
#include "SkPDFTypes.h"
#include "SkMatrix.h"
#include "SkRefCnt.h"
#include "SkShader.h"
class SkObjRef;
class SkPDFCatalog;
/** \class SkPDFShader
In PDF parlance, this is a pattern, used in place of a color when the
pattern color space is selected.
*/
class SkPDFShader : public SkPDFObject {
public:
virtual ~SkPDFShader();
// 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);
/** Get the PDF shader for the passed SkShader. If the SkShader is
* invalid in some way, returns NULL. The reference count of
* the object is incremented and it is the caller's responsibility to
* unreference it when done. This is needed to accommodate the weak
* reference pattern used when the returned object is new and has no
* other references.
* @param shader The SkShader to emulate.
* @param matrix The current transform. (PDF shaders are absolutely
* positioned, relative to where the page is drawn.)
* @param surfceBBox The bounding box of the drawing surface (with matrix
* already applied).
*/
static SkPDFShader* getPDFShader(const SkShader& shader,
const SkMatrix& matrix,
const SkIRect& surfaceBBox);
private:
class State {
public:
SkShader::GradientType fType;
SkShader::GradientInfo fInfo;
SkAutoFree fColorData;
SkMatrix fCanvasTransform;
SkMatrix fShaderTransform;
SkIRect fBBox;
SkBitmap fImage;
uint32_t fPixelGeneration;
SkShader::TileMode fImageTileModes[2];
explicit State(const SkShader& shader, const SkMatrix& canvasTransform,
const SkIRect& bbox);
bool operator==(const State& b) const;
};
SkRefPtr<SkPDFDict> fContent;
SkTDArray<SkPDFObject*> fResources;
SkAutoTDelete<const State> fState;
class ShaderCanonicalEntry {
public:
SkPDFShader* fPDFShader;
const State* fState;
bool operator==(const ShaderCanonicalEntry& b) const {
return fPDFShader == b.fPDFShader || *fState == *b.fState;
}
ShaderCanonicalEntry(SkPDFShader* pdfShader, const State* state)
: fPDFShader(pdfShader),
fState(state) {
}
};
// This should be made a hash table if performance is a problem.
static SkTDArray<ShaderCanonicalEntry>& canonicalShaders();
static SkMutex& canonicalShadersMutex();
static SkPDFObject* rangeObject();
SkPDFShader(State* state);
void doFunctionShader();
void doImageShader();
SkPDFStream* makePSFunction(const SkString& psCode, SkPDFArray* domain);
};
#endif