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