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" 13static 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 37SkSurfaceProps::SkSurfaceProps() : fFlags(0), fPixelGeometry(kUnknown_SkPixelGeometry) {} 38 39SkSurfaceProps::SkSurfaceProps(InitType) : fFlags(0), fPixelGeometry(compute_default_geometry()) {} 40 41SkSurfaceProps::SkSurfaceProps(uint32_t flags, InitType) 42 : fFlags(flags) 43 , fPixelGeometry(compute_default_geometry()) 44{} 45 46SkSurfaceProps::SkSurfaceProps(uint32_t flags, SkPixelGeometry pg) 47 : fFlags(flags), fPixelGeometry(pg) 48{} 49 50/////////////////////////////////////////////////////////////////////////////// 51 52SkSurface_Base::SkSurface_Base(int width, int height, const SkSurfaceProps* props) 53 : INHERITED(width, height, props) 54{ 55 fCachedCanvas = NULL; 56 fCachedImage = NULL; 57} 58 59SkSurface_Base::SkSurface_Base(const SkImageInfo& info, const SkSurfaceProps* props) 60 : INHERITED(info, props) 61{ 62 fCachedCanvas = NULL; 63 fCachedImage = NULL; 64} 65 66SkSurface_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 76void 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 84void 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 106uint32_t SkSurface_Base::newGenerationID() { 107 SkASSERT(!fCachedCanvas || fCachedCanvas->getSurfaceBase() == this); 108 static int32_t gID; 109 return sk_atomic_inc(&gID) + 1; 110} 111 112static SkSurface_Base* asSB(SkSurface* surface) { 113 return static_cast<SkSurface_Base*>(surface); 114} 115 116/////////////////////////////////////////////////////////////////////////////// 117 118SkSurface::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 126SkSurface::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 134uint32_t SkSurface::generationID() { 135 if (0 == fGenerationID) { 136 fGenerationID = asSB(this)->newGenerationID(); 137 } 138 return fGenerationID; 139} 140 141void SkSurface::notifyContentWillChange(ContentChangeMode mode) { 142 asSB(this)->aboutToDraw(mode); 143} 144 145SkCanvas* SkSurface::getCanvas() { 146 return asSB(this)->getCachedCanvas(); 147} 148 149SkImage* SkSurface::newImageSnapshot() { 150 SkImage* image = asSB(this)->getCachedImage(); 151 SkSafeRef(image); // the caller will call unref() to balance this 152 return image; 153} 154 155SkSurface* SkSurface::newSurface(const SkImageInfo& info) { 156 return asSB(this)->onNewSurface(info); 157} 158 159void SkSurface::draw(SkCanvas* canvas, SkScalar x, SkScalar y, 160 const SkPaint* paint) { 161 return asSB(this)->onDraw(canvas, x, y, paint); 162} 163 164const 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 171static 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 179SkSurface* SkSurface::NewRenderTargetDirect(GrRenderTarget* target, TextRenderMode trm) { 180 SkSurfaceProps props = make_props(trm); 181 return NewRenderTargetDirect(target, &props); 182} 183 184SkSurface* 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 190SkSurface* 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 200SkSurface* SkSurface::NewRenderTargetDirect(GrRenderTarget*, const SkSurfaceProps*) { 201 return NULL; 202} 203 204SkSurface* SkSurface::NewRenderTarget(GrContext*, const SkImageInfo&, int, const SkSurfaceProps*) { 205 return NULL; 206} 207 208SkSurface* SkSurface::NewScratchRenderTarget(GrContext*, const SkImageInfo&, int sampleCount, 209 const SkSurfaceProps*) { 210 return NULL; 211} 212 213#endif 214