Home | History | Annotate | Download | only in core
      1 /*
      2  * Copyright 2006 The Android Open Source Project
      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 #ifndef SkBlitter_DEFINED
      9 #define SkBlitter_DEFINED
     10 
     11 #include "SkBitmapProcShader.h"
     12 #include "SkColor.h"
     13 #include "SkRect.h"
     14 #include "SkRegion.h"
     15 #include "SkShader.h"
     16 #include "SkTypes.h"
     17 
     18 class SkMatrix;
     19 class SkPaint;
     20 class SkPixmap;
     21 struct SkMask;
     22 
     23 /** SkBlitter and its subclasses are responsible for actually writing pixels
     24     into memory. Besides efficiency, they handle clipping and antialiasing.
     25 */
     26 class SkBlitter {
     27 public:
     28     virtual ~SkBlitter();
     29 
     30     /// Blit a horizontal run of one or more pixels.
     31     virtual void blitH(int x, int y, int width);
     32     /// Blit a horizontal run of antialiased pixels; runs[] is a *sparse*
     33     /// zero-terminated run-length encoding of spans of constant alpha values.
     34     virtual void blitAntiH(int x, int y, const SkAlpha antialias[],
     35                            const int16_t runs[]);
     36 
     37     /// Blit a vertical run of pixels with a constant alpha value.
     38     virtual void blitV(int x, int y, int height, SkAlpha alpha);
     39     /// Blit a solid rectangle one or more pixels wide.
     40     virtual void blitRect(int x, int y, int width, int height);
     41     /** Blit a rectangle with one alpha-blended column on the left,
     42         width (zero or more) opaque pixels, and one alpha-blended column
     43         on the right.
     44         The result will always be at least two pixels wide.
     45     */
     46     virtual void blitAntiRect(int x, int y, int width, int height,
     47                               SkAlpha leftAlpha, SkAlpha rightAlpha);
     48     /// Blit a pattern of pixels defined by a rectangle-clipped mask;
     49     /// typically used for text.
     50     virtual void blitMask(const SkMask&, const SkIRect& clip);
     51 
     52     /** If the blitter just sets a single value for each pixel, return the
     53         bitmap it draws into, and assign value. If not, return nullptr and ignore
     54         the value parameter.
     55     */
     56     virtual const SkPixmap* justAnOpaqueColor(uint32_t* value);
     57 
     58     // (x, y), (x + 1, y)
     59     virtual void blitAntiH2(int x, int y, U8CPU a0, U8CPU a1) {
     60         int16_t runs[3];
     61         uint8_t aa[2];
     62 
     63         runs[0] = 1;
     64         runs[1] = 1;
     65         runs[2] = 0;
     66         aa[0] = SkToU8(a0);
     67         aa[1] = SkToU8(a1);
     68         this->blitAntiH(x, y, aa, runs);
     69     }
     70 
     71     // (x, y), (x, y + 1)
     72     virtual void blitAntiV2(int x, int y, U8CPU a0, U8CPU a1) {
     73         int16_t runs[2];
     74         uint8_t aa[1];
     75 
     76         runs[0] = 1;
     77         runs[1] = 0;
     78         aa[0] = SkToU8(a0);
     79         this->blitAntiH(x, y, aa, runs);
     80         // reset in case the clipping blitter modified runs
     81         runs[0] = 1;
     82         runs[1] = 0;
     83         aa[0] = SkToU8(a1);
     84         this->blitAntiH(x, y + 1, aa, runs);
     85     }
     86 
     87     /**
     88      *  Special method just to identify the null blitter, which is returned
     89      *  from Choose() if the request cannot be fulfilled. Default impl
     90      *  returns false.
     91      */
     92     virtual bool isNullBlitter() const;
     93 
     94     /**
     95      *  Special methods for SkShaderBlitter. On all other classes this is a no-op.
     96      */
     97     virtual bool resetShaderContext(const SkShader::ContextRec&);
     98     virtual SkShader::Context* getShaderContext() const;
     99 
    100     /**
    101      * Special methods for blitters that can blit more than one row at a time.
    102      * This function returns the number of rows that this blitter could optimally
    103      * process at a time. It is still required to support blitting one scanline
    104      * at a time.
    105      */
    106     virtual int requestRowsPreserved() const { return 1; }
    107 
    108     /**
    109      * This function allocates memory for the blitter that the blitter then owns.
    110      * The memory can be used by the calling function at will, but it will be
    111      * released when the blitter's destructor is called. This function returns
    112      * nullptr if no persistent memory is needed by the blitter.
    113      */
    114     virtual void* allocBlitMemory(size_t sz) {
    115         return fBlitMemory.reset(sz, SkAutoMalloc::kReuse_OnShrink);
    116     }
    117 
    118     ///@name non-virtual helpers
    119     void blitMaskRegion(const SkMask& mask, const SkRegion& clip);
    120     void blitRectRegion(const SkIRect& rect, const SkRegion& clip);
    121     void blitRegion(const SkRegion& clip);
    122     ///@}
    123 
    124     /** @name Factories
    125         Return the correct blitter to use given the specified context.
    126      */
    127     static SkBlitter* Choose(const SkPixmap& dst,
    128                              const SkMatrix& matrix,
    129                              const SkPaint& paint,
    130                              SkTBlitterAllocator*,
    131                              bool drawCoverage = false);
    132 
    133     static SkBlitter* ChooseSprite(const SkPixmap& dst,
    134                                    const SkPaint&,
    135                                    const SkPixmap& src,
    136                                    int left, int top,
    137                                    SkTBlitterAllocator*);
    138     ///@}
    139 
    140     static SkShader::ContextRec::DstType PreferredShaderDest(const SkImageInfo&);
    141 
    142 protected:
    143     SkAutoMalloc fBlitMemory;
    144 };
    145 
    146 /** This blitter silently never draws anything.
    147 */
    148 class SkNullBlitter : public SkBlitter {
    149 public:
    150     void blitH(int x, int y, int width) override;
    151     void blitAntiH(int x, int y, const SkAlpha[], const int16_t runs[]) override;
    152     void blitV(int x, int y, int height, SkAlpha alpha) override;
    153     void blitRect(int x, int y, int width, int height) override;
    154     void blitMask(const SkMask&, const SkIRect& clip) override;
    155     const SkPixmap* justAnOpaqueColor(uint32_t* value) override;
    156     bool isNullBlitter() const override;
    157 };
    158 
    159 /** Wraps another (real) blitter, and ensures that the real blitter is only
    160     called with coordinates that have been clipped by the specified clipRect.
    161     This means the caller need not perform the clipping ahead of time.
    162 */
    163 class SkRectClipBlitter : public SkBlitter {
    164 public:
    165     void init(SkBlitter* blitter, const SkIRect& clipRect) {
    166         SkASSERT(!clipRect.isEmpty());
    167         fBlitter = blitter;
    168         fClipRect = clipRect;
    169     }
    170 
    171     void blitH(int x, int y, int width) override;
    172     void blitAntiH(int x, int y, const SkAlpha[], const int16_t runs[]) override;
    173     void blitV(int x, int y, int height, SkAlpha alpha) override;
    174     void blitRect(int x, int y, int width, int height) override;
    175     virtual void blitAntiRect(int x, int y, int width, int height,
    176                      SkAlpha leftAlpha, SkAlpha rightAlpha) override;
    177     void blitMask(const SkMask&, const SkIRect& clip) override;
    178     const SkPixmap* justAnOpaqueColor(uint32_t* value) override;
    179 
    180     int requestRowsPreserved() const override {
    181         return fBlitter->requestRowsPreserved();
    182     }
    183 
    184     void* allocBlitMemory(size_t sz) override {
    185         return fBlitter->allocBlitMemory(sz);
    186     }
    187 
    188 private:
    189     SkBlitter*  fBlitter;
    190     SkIRect     fClipRect;
    191 };
    192 
    193 /** Wraps another (real) blitter, and ensures that the real blitter is only
    194     called with coordinates that have been clipped by the specified clipRgn.
    195     This means the caller need not perform the clipping ahead of time.
    196 */
    197 class SkRgnClipBlitter : public SkBlitter {
    198 public:
    199     void init(SkBlitter* blitter, const SkRegion* clipRgn) {
    200         SkASSERT(clipRgn && !clipRgn->isEmpty());
    201         fBlitter = blitter;
    202         fRgn = clipRgn;
    203     }
    204 
    205     void blitH(int x, int y, int width) override;
    206     void blitAntiH(int x, int y, const SkAlpha[], const int16_t runs[]) override;
    207     void blitV(int x, int y, int height, SkAlpha alpha) override;
    208     void blitRect(int x, int y, int width, int height) override;
    209     void blitAntiRect(int x, int y, int width, int height,
    210                       SkAlpha leftAlpha, SkAlpha rightAlpha) override;
    211     void blitMask(const SkMask&, const SkIRect& clip) override;
    212     const SkPixmap* justAnOpaqueColor(uint32_t* value) override;
    213 
    214     int requestRowsPreserved() const override {
    215         return fBlitter->requestRowsPreserved();
    216     }
    217 
    218     void* allocBlitMemory(size_t sz) override {
    219         return fBlitter->allocBlitMemory(sz);
    220     }
    221 
    222 private:
    223     SkBlitter*      fBlitter;
    224     const SkRegion* fRgn;
    225 };
    226 
    227 /** Factory to set up the appropriate most-efficient wrapper blitter
    228     to apply a clip. Returns a pointer to a member, so lifetime must
    229     be managed carefully.
    230 */
    231 class SkBlitterClipper {
    232 public:
    233     SkBlitter*  apply(SkBlitter* blitter, const SkRegion* clip,
    234                       const SkIRect* bounds = nullptr);
    235 
    236 private:
    237     SkNullBlitter       fNullBlitter;
    238     SkRectClipBlitter   fRectBlitter;
    239     SkRgnClipBlitter    fRgnBlitter;
    240 };
    241 
    242 #endif
    243