• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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