1 /*
2 * Copyright 2012 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8 #include "SkSurface_Base.h"
9 #include "SkImagePriv.h"
10 #include "SkCanvas.h"
11
12 #include "SkFontLCDConfig.h"
compute_default_geometry()13 static SkPixelGeometry compute_default_geometry() {
14 SkFontLCDConfig::LCDOrder order = SkFontLCDConfig::GetSubpixelOrder();
15 if (SkFontLCDConfig::kNONE_LCDOrder == order) {
16 return kUnknown_SkPixelGeometry;
17 } else {
18 // Bit0 is RGB(0), BGR(1)
19 // Bit1 is H(0), V(1)
20 const SkPixelGeometry gGeo[] = {
21 kRGB_H_SkPixelGeometry,
22 kBGR_H_SkPixelGeometry,
23 kRGB_V_SkPixelGeometry,
24 kBGR_V_SkPixelGeometry,
25 };
26 int index = 0;
27 if (SkFontLCDConfig::kBGR_LCDOrder == order) {
28 index |= 1;
29 }
30 if (SkFontLCDConfig::kVertical_LCDOrientation == SkFontLCDConfig::GetSubpixelOrientation()){
31 index |= 2;
32 }
33 return gGeo[index];
34 }
35 }
36
SkSurfaceProps()37 SkSurfaceProps::SkSurfaceProps() : fFlags(0), fPixelGeometry(kUnknown_SkPixelGeometry) {}
38
SkSurfaceProps(InitType)39 SkSurfaceProps::SkSurfaceProps(InitType) : fFlags(0), fPixelGeometry(compute_default_geometry()) {}
40
SkSurfaceProps(uint32_t flags,InitType)41 SkSurfaceProps::SkSurfaceProps(uint32_t flags, InitType)
42 : fFlags(flags)
43 , fPixelGeometry(compute_default_geometry())
44 {}
45
SkSurfaceProps(uint32_t flags,SkPixelGeometry pg)46 SkSurfaceProps::SkSurfaceProps(uint32_t flags, SkPixelGeometry pg)
47 : fFlags(flags), fPixelGeometry(pg)
48 {}
49
50 ///////////////////////////////////////////////////////////////////////////////
51
SkSurface_Base(int width,int height,const SkSurfaceProps * props)52 SkSurface_Base::SkSurface_Base(int width, int height, const SkSurfaceProps* props)
53 : INHERITED(width, height, props)
54 {
55 fCachedCanvas = NULL;
56 fCachedImage = NULL;
57 }
58
SkSurface_Base(const SkImageInfo & info,const SkSurfaceProps * props)59 SkSurface_Base::SkSurface_Base(const SkImageInfo& info, const SkSurfaceProps* props)
60 : INHERITED(info, props)
61 {
62 fCachedCanvas = NULL;
63 fCachedImage = NULL;
64 }
65
~SkSurface_Base()66 SkSurface_Base::~SkSurface_Base() {
67 // in case the canvas outsurvives us, we null the callback
68 if (fCachedCanvas) {
69 fCachedCanvas->setSurfaceBase(NULL);
70 }
71
72 SkSafeUnref(fCachedImage);
73 SkSafeUnref(fCachedCanvas);
74 }
75
onDraw(SkCanvas * canvas,SkScalar x,SkScalar y,const SkPaint * paint)76 void SkSurface_Base::onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) {
77 SkImage* image = this->newImageSnapshot();
78 if (image) {
79 canvas->drawImage(image, x, y, paint);
80 image->unref();
81 }
82 }
83
aboutToDraw(ContentChangeMode mode)84 void SkSurface_Base::aboutToDraw(ContentChangeMode mode) {
85 this->dirtyGenerationID();
86
87 SkASSERT(!fCachedCanvas || fCachedCanvas->getSurfaceBase() == this);
88
89 if (fCachedImage) {
90 // the surface may need to fork its backend, if its sharing it with
91 // the cached image. Note: we only call if there is an outstanding owner
92 // on the image (besides us).
93 if (!fCachedImage->unique()) {
94 this->onCopyOnWrite(mode);
95 }
96
97 // regardless of copy-on-write, we must drop our cached image now, so
98 // that the next request will get our new contents.
99 fCachedImage->unref();
100 fCachedImage = NULL;
101 } else if (kDiscard_ContentChangeMode == mode) {
102 this->onDiscard();
103 }
104 }
105
newGenerationID()106 uint32_t SkSurface_Base::newGenerationID() {
107 SkASSERT(!fCachedCanvas || fCachedCanvas->getSurfaceBase() == this);
108 static int32_t gID;
109 return sk_atomic_inc(&gID) + 1;
110 }
111
asSB(SkSurface * surface)112 static SkSurface_Base* asSB(SkSurface* surface) {
113 return static_cast<SkSurface_Base*>(surface);
114 }
115
116 ///////////////////////////////////////////////////////////////////////////////
117
SkSurface(int width,int height,const SkSurfaceProps * props)118 SkSurface::SkSurface(int width, int height, const SkSurfaceProps* props)
119 : fProps(SkSurfacePropsCopyOrDefault(props)), fWidth(width), fHeight(height)
120 {
121 SkASSERT(fWidth >= 0);
122 SkASSERT(fHeight >= 0);
123 fGenerationID = 0;
124 }
125
SkSurface(const SkImageInfo & info,const SkSurfaceProps * props)126 SkSurface::SkSurface(const SkImageInfo& info, const SkSurfaceProps* props)
127 : fProps(SkSurfacePropsCopyOrDefault(props)), fWidth(info.width()), fHeight(info.height())
128 {
129 SkASSERT(fWidth >= 0);
130 SkASSERT(fHeight >= 0);
131 fGenerationID = 0;
132 }
133
generationID()134 uint32_t SkSurface::generationID() {
135 if (0 == fGenerationID) {
136 fGenerationID = asSB(this)->newGenerationID();
137 }
138 return fGenerationID;
139 }
140
notifyContentWillChange(ContentChangeMode mode)141 void SkSurface::notifyContentWillChange(ContentChangeMode mode) {
142 asSB(this)->aboutToDraw(mode);
143 }
144
getCanvas()145 SkCanvas* SkSurface::getCanvas() {
146 return asSB(this)->getCachedCanvas();
147 }
148
newImageSnapshot()149 SkImage* SkSurface::newImageSnapshot() {
150 SkImage* image = asSB(this)->getCachedImage();
151 SkSafeRef(image); // the caller will call unref() to balance this
152 return image;
153 }
154
newSurface(const SkImageInfo & info)155 SkSurface* SkSurface::newSurface(const SkImageInfo& info) {
156 return asSB(this)->onNewSurface(info);
157 }
158
draw(SkCanvas * canvas,SkScalar x,SkScalar y,const SkPaint * paint)159 void SkSurface::draw(SkCanvas* canvas, SkScalar x, SkScalar y,
160 const SkPaint* paint) {
161 return asSB(this)->onDraw(canvas, x, y, paint);
162 }
163
peekPixels(SkImageInfo * info,size_t * rowBytes)164 const void* SkSurface::peekPixels(SkImageInfo* info, size_t* rowBytes) {
165 return this->getCanvas()->peekPixels(info, rowBytes);
166 }
167
168 //////////////////////////////////////////////////////////////////////////////////////
169 #ifdef SK_SUPPORT_LEGACY_TEXTRENDERMODE
170
make_props(SkSurface::TextRenderMode trm)171 static SkSurfaceProps make_props(SkSurface::TextRenderMode trm) {
172 uint32_t propsFlags = 0;
173 if (SkSurface::kDistanceField_TextRenderMode == trm) {
174 propsFlags |= SkSurfaceProps::kUseDistanceFieldFonts_Flag;
175 }
176 return SkSurfaceProps(propsFlags, SkSurfaceProps::kLegacyFontHost_InitType);
177 }
178
NewRenderTargetDirect(GrRenderTarget * target,TextRenderMode trm)179 SkSurface* SkSurface::NewRenderTargetDirect(GrRenderTarget* target, TextRenderMode trm) {
180 SkSurfaceProps props = make_props(trm);
181 return NewRenderTargetDirect(target, &props);
182 }
183
NewRenderTarget(GrContext * gr,const SkImageInfo & info,int sampleCount,TextRenderMode trm)184 SkSurface* SkSurface::NewRenderTarget(GrContext* gr, const SkImageInfo& info, int sampleCount,
185 TextRenderMode trm) {
186 SkSurfaceProps props = make_props(trm);
187 return NewRenderTarget(gr, info, sampleCount, &props);
188 }
189
NewScratchRenderTarget(GrContext * gr,const SkImageInfo & info,int sampleCount,TextRenderMode trm)190 SkSurface* SkSurface::NewScratchRenderTarget(GrContext* gr, const SkImageInfo& info, int sampleCount,
191 TextRenderMode trm) {
192 SkSurfaceProps props = make_props(trm);
193 return NewScratchRenderTarget(gr, info, sampleCount, &props);
194 }
195
196 #endif
197
198 #if !SK_SUPPORT_GPU
199
NewRenderTargetDirect(GrRenderTarget *,const SkSurfaceProps *)200 SkSurface* SkSurface::NewRenderTargetDirect(GrRenderTarget*, const SkSurfaceProps*) {
201 return NULL;
202 }
203
NewRenderTarget(GrContext *,const SkImageInfo &,int,const SkSurfaceProps *)204 SkSurface* SkSurface::NewRenderTarget(GrContext*, const SkImageInfo&, int, const SkSurfaceProps*) {
205 return NULL;
206 }
207
NewScratchRenderTarget(GrContext *,const SkImageInfo &,int sampleCount,const SkSurfaceProps *)208 SkSurface* SkSurface::NewScratchRenderTarget(GrContext*, const SkImageInfo&, int sampleCount,
209 const SkSurfaceProps*) {
210 return NULL;
211 }
212
213 #endif
214