Home | History | Annotate | Download | only in image
      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"
     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 
     37 SkSurfaceProps::SkSurfaceProps() : fFlags(0), fPixelGeometry(kUnknown_SkPixelGeometry) {}
     38 
     39 SkSurfaceProps::SkSurfaceProps(InitType) : fFlags(0), fPixelGeometry(compute_default_geometry()) {}
     40 
     41 SkSurfaceProps::SkSurfaceProps(uint32_t flags, InitType)
     42     : fFlags(flags)
     43     , fPixelGeometry(compute_default_geometry())
     44 {}
     45 
     46 SkSurfaceProps::SkSurfaceProps(uint32_t flags, SkPixelGeometry pg)
     47     : fFlags(flags), fPixelGeometry(pg)
     48 {}
     49 
     50 ///////////////////////////////////////////////////////////////////////////////
     51 
     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 
     59 SkSurface_Base::SkSurface_Base(const SkImageInfo& info, const SkSurfaceProps* props)
     60     : INHERITED(info, props)
     61 {
     62     fCachedCanvas = NULL;
     63     fCachedImage = NULL;
     64 }
     65 
     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 
     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 
     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 
    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 
    112 static SkSurface_Base* asSB(SkSurface* surface) {
    113     return static_cast<SkSurface_Base*>(surface);
    114 }
    115 
    116 ///////////////////////////////////////////////////////////////////////////////
    117 
    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 
    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 
    134 uint32_t SkSurface::generationID() {
    135     if (0 == fGenerationID) {
    136         fGenerationID = asSB(this)->newGenerationID();
    137     }
    138     return fGenerationID;
    139 }
    140 
    141 void SkSurface::notifyContentWillChange(ContentChangeMode mode) {
    142     asSB(this)->aboutToDraw(mode);
    143 }
    144 
    145 SkCanvas* SkSurface::getCanvas() {
    146     return asSB(this)->getCachedCanvas();
    147 }
    148 
    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 
    155 SkSurface* SkSurface::newSurface(const SkImageInfo& info) {
    156     return asSB(this)->onNewSurface(info);
    157 }
    158 
    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 
    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 
    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 
    179 SkSurface* SkSurface::NewRenderTargetDirect(GrRenderTarget* target, TextRenderMode trm) {
    180     SkSurfaceProps props = make_props(trm);
    181     return NewRenderTargetDirect(target, &props);
    182 }
    183 
    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 
    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 
    200 SkSurface* SkSurface::NewRenderTargetDirect(GrRenderTarget*, const SkSurfaceProps*) {
    201     return NULL;
    202 }
    203 
    204 SkSurface* SkSurface::NewRenderTarget(GrContext*, const SkImageInfo&, int, const SkSurfaceProps*) {
    205     return NULL;
    206 }
    207 
    208 SkSurface* SkSurface::NewScratchRenderTarget(GrContext*, const SkImageInfo&, int sampleCount,
    209                                              const SkSurfaceProps*) {
    210     return NULL;
    211 }
    212 
    213 #endif
    214