SkDevice* setBitmapDevice(const SkBitmap& bitmap, bool forLayer = false);
/**
- * Return the current device factory, or NULL.
+ * Return the current device factory, or NULL. The reference count of
+ * the returned factory is not changed.
*/
SkDeviceFactory* getDeviceFactory() const { return fDeviceFactory; }
/**
- * Replace any existing factory with the specified factory.
+ * Replace any existing factory with the specified factory, unrefing the
+ * previous (if any), and refing the new one (if any). For convenience,
+ * the factory parameter is also returned.
*/
SkDeviceFactory* setDeviceFactory(SkDeviceFactory*);
to pass into SkCanvas. Doing so will eliminate the need to extend
SkCanvas as well.
*/
-class SK_API SkDeviceFactory {
+class SK_API SkDeviceFactory : public SkRefCnt {
public:
+ SkDeviceFactory();
virtual ~SkDeviceFactory();
virtual SkDevice* newDevice(SkCanvas*, SkBitmap::Config, int width,
int height, bool isOpaque, bool isLayer) = 0;
SkDevice(SkCanvas*, const SkBitmap& bitmap, bool forOffscreen);
virtual ~SkDevice();
- virtual SkDeviceFactory* getDeviceFactory() {
- return SkNEW(SkRasterDeviceFactory);
- }
+ /**
+ * Return the factory that will create this subclass of SkDevice.
+ * The returned factory is cached by the device, and so its reference count
+ * is not changed by this call.
+ */
+ SkDeviceFactory* getDeviceFactory();
enum Capabilities {
kGL_Capability = 0x1, //!< mask indicating GL support
virtual bool filterTextFlags(const SkPaint& paint, TextFlags*);
protected:
+ /**
+ * subclasses must override this to return a new (or ref'd) instance of
+ * a device factory that will create this subclass of device. This value
+ * is cached, so it should get called at most once for a given instance.
+ */
+ virtual SkDeviceFactory* onNewDeviceFactory();
+
/** Update as needed the pixel value in the bitmap, so that the caller can access
the pixels directly. Note: only the pixels field should be altered. The config/width/height/rowbytes
must remain unchanged.
SkBitmap fBitmap;
SkIPoint fOrigin;
SkMetaData* fMetaData;
+
+ SkDeviceFactory* fCachedDeviceFactory;
};
#endif
virtual void makeRenderTargetCurrent();
protected:
+ // override
+ virtual SkDeviceFactory* onNewDeviceFactory();
+
class TexCache;
TexCache* lockCachedTexture(const SkBitmap& bitmap,
const GrSamplerState& sampler,
SkPDFDevice(int width, int height, const SkMatrix& initialTransform);
virtual ~SkPDFDevice();
- virtual SkDeviceFactory* getDeviceFactory() {
- return SkNEW(SkPDFDeviceFactory);
- }
-
virtual uint32_t getDeviceCapabilities() { return kVector_Capability; }
virtual int width() const { return fWidth; };
*/
SkStream* content() const;
+protected:
+ // override
+ virtual SkDeviceFactory* onNewDeviceFactory();
+
private:
int fWidth;
int fHeight;
}
SkCanvas::SkCanvas(SkDeviceFactory* factory)
- : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)),
- fDeviceFactory(factory) {
+ : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) {
inc_canvas();
- if (!factory)
- fDeviceFactory = SkNEW(SkRasterDeviceFactory);
+ if (factory) {
+ factory->ref();
+ } else {
+ factory = SkNEW(SkRasterDeviceFactory);
+ }
+ fDeviceFactory = factory;
this->init(NULL);
}
SkCanvas::SkCanvas(SkDevice* device)
- : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)),
- fDeviceFactory(device->getDeviceFactory()) {
+ : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) {
inc_canvas();
+ fDeviceFactory = device->getDeviceFactory();
+ SkASSERT(fDeviceFactory);
+ fDeviceFactory->ref();
+
this->init(device);
}
SkDevice* device = SkNEW_ARGS(SkDevice, (this, bitmap, false));
fDeviceFactory = device->getDeviceFactory();
+ SkASSERT(fDeviceFactory);
+ fDeviceFactory->ref();
+
this->init(device)->unref();
}
this->internalRestore(); // restore the last, since we're going away
SkSafeUnref(fBounder);
- SkDELETE(fDeviceFactory);
+ SkSafeUnref(fDeviceFactory);
dec_canvas();
}
}
SkDeviceFactory* SkCanvas::setDeviceFactory(SkDeviceFactory* factory) {
- SkDELETE(fDeviceFactory);
- fDeviceFactory = factory;
+ SkRefCnt_SafeAssign(fDeviceFactory, factory);
return factory;
}
#include "SkMetaData.h"
#include "SkRect.h"
-SkDeviceFactory::~SkDeviceFactory() {}
+//#define TRACE_FACTORY_LIFETIME
+
+#ifdef TRACE_FACTORY_LIFETIME
+ static int gFactoryCounter;
+#endif
+
+SkDeviceFactory::SkDeviceFactory() {
+#ifdef TRACE_FACTORY_LIFETIME
+ SkDebugf("+++ factory index %d\n", gFactoryCounter);
+ ++gFactoryCounter;
+#endif
+}
+
+SkDeviceFactory::~SkDeviceFactory() {
+#ifdef TRACE_FACTORY_LIFETIME
+ --gFactoryCounter;
+ SkDebugf("--- factory index %d\n", gFactoryCounter);
+#endif
+}
+
+///////////////////////////////////////////////////////////////////////////////
SkDevice::SkDevice(SkCanvas* canvas) : fCanvas(canvas), fMetaData(NULL) {
fOrigin.setZero();
+ fCachedDeviceFactory = NULL;
}
SkDevice::SkDevice(SkCanvas* canvas, const SkBitmap& bitmap, bool isForLayer)
}
}
}
+ fCachedDeviceFactory = NULL;
}
SkDevice::~SkDevice() {
delete fMetaData;
+ SkSafeUnref(fCachedDeviceFactory);
+}
+
+SkDeviceFactory* SkDevice::onNewDeviceFactory() {
+ return SkNEW(SkRasterDeviceFactory);
+}
+
+SkDeviceFactory* SkDevice::getDeviceFactory() {
+ if (NULL == fCachedDeviceFactory) {
+ fCachedDeviceFactory = this->onNewDeviceFactory();
+ }
+ return fCachedDeviceFactory;
}
SkMetaData& SkDevice::getMetaData() {
///////////////////////////////////////////////////////////////////////////////
-static SkDeviceFactory* make_df(GrContext* context,
- GrRenderTarget* renderTarget) {
- return SkNEW_ARGS(SkGpuDeviceFactory, (context, renderTarget));
-}
+SkGpuCanvas::SkGpuCanvas(GrContext* context, GrRenderTarget* renderTarget) {
+ SkDeviceFactory* factory = SkNEW_ARGS(SkGpuDeviceFactory,
+ (context, renderTarget));
+ this->setDeviceFactory(factory)->unref();
-SkGpuCanvas::SkGpuCanvas(GrContext* context,
- GrRenderTarget* renderTarget)
- : SkCanvas(make_df(context, renderTarget)) {
SkASSERT(context);
fContext = context;
fContext->ref();
return 0;
}
}
+
+SkDeviceFactory* SkGpuDevice::onNewDeviceFactory() {
+ return SkNEW_ARGS(SkGpuDeviceFactory, (fContext, fRenderTarget));
+}
+
///////////////////////////////////////////////////////////////////////////////
void SkGpuDevice::makeRenderTargetCurrent() {
}
}
+SkDeviceFactory* SkPDFDevice::onNewDeviceFactory() {
+ return SkNEW(SkPDFDeviceFactory);
+}
+
void SkPDFDevice::cleanUp() {
fGraphicStateResources.unrefAll();
fXObjectResources.unrefAll();