123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243 |
- /*
- * Copyright 2006 The Android Open Source Project
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
- #ifndef SkMask_DEFINED
- #define SkMask_DEFINED
- #include "include/core/SkRect.h"
- #include "include/private/SkColorData.h"
- #include "include/private/SkMacros.h"
- #include "include/private/SkTemplates.h"
- #include <memory>
- /** \class SkMask
- SkMask is used to describe alpha bitmaps, either 1bit, 8bit, or
- the 3-channel 3D format. These are passed to SkMaskFilter objects.
- */
- struct SkMask {
- SkMask() : fImage(nullptr) {}
- enum Format {
- kBW_Format, //!< 1bit per pixel mask (e.g. monochrome)
- kA8_Format, //!< 8bits per pixel mask (e.g. antialiasing)
- k3D_Format, //!< 3 8bit per pixl planes: alpha, mul, add
- kARGB32_Format, //!< SkPMColor
- kLCD16_Format, //!< 565 alpha for r/g/b
- kSDF_Format, //!< 8bits representing signed distance field
- };
- enum {
- kCountMaskFormats = kSDF_Format + 1
- };
- uint8_t* fImage;
- SkIRect fBounds;
- uint32_t fRowBytes;
- Format fFormat;
- static bool IsValidFormat(uint8_t format) { return format < kCountMaskFormats; }
- /** Returns true if the mask is empty: i.e. it has an empty bounds.
- */
- bool isEmpty() const { return fBounds.isEmpty(); }
- /** Return the byte size of the mask, assuming only 1 plane.
- Does not account for k3D_Format. For that, use computeTotalImageSize().
- If there is an overflow of 32bits, then returns 0.
- */
- size_t computeImageSize() const;
- /** Return the byte size of the mask, taking into account
- any extra planes (e.g. k3D_Format).
- If there is an overflow of 32bits, then returns 0.
- */
- size_t computeTotalImageSize() const;
- /** Returns the address of the byte that holds the specified bit.
- Asserts that the mask is kBW_Format, and that x,y are in range.
- x,y are in the same coordiate space as fBounds.
- */
- uint8_t* getAddr1(int x, int y) const {
- SkASSERT(kBW_Format == fFormat);
- SkASSERT(fBounds.contains(x, y));
- SkASSERT(fImage != nullptr);
- return fImage + ((x - fBounds.fLeft) >> 3) + (y - fBounds.fTop) * fRowBytes;
- }
- /** Returns the address of the specified byte.
- Asserts that the mask is kA8_Format, and that x,y are in range.
- x,y are in the same coordiate space as fBounds.
- */
- uint8_t* getAddr8(int x, int y) const {
- SkASSERT(kA8_Format == fFormat || kSDF_Format == fFormat);
- SkASSERT(fBounds.contains(x, y));
- SkASSERT(fImage != nullptr);
- return fImage + x - fBounds.fLeft + (y - fBounds.fTop) * fRowBytes;
- }
- /**
- * Return the address of the specified 16bit mask. In the debug build,
- * this asserts that the mask's format is kLCD16_Format, and that (x,y)
- * are contained in the mask's fBounds.
- */
- uint16_t* getAddrLCD16(int x, int y) const {
- SkASSERT(kLCD16_Format == fFormat);
- SkASSERT(fBounds.contains(x, y));
- SkASSERT(fImage != nullptr);
- uint16_t* row = (uint16_t*)(fImage + (y - fBounds.fTop) * fRowBytes);
- return row + (x - fBounds.fLeft);
- }
- /**
- * Return the address of the specified 32bit mask. In the debug build,
- * this asserts that the mask's format is 32bits, and that (x,y)
- * are contained in the mask's fBounds.
- */
- uint32_t* getAddr32(int x, int y) const {
- SkASSERT(kARGB32_Format == fFormat);
- SkASSERT(fBounds.contains(x, y));
- SkASSERT(fImage != nullptr);
- uint32_t* row = (uint32_t*)(fImage + (y - fBounds.fTop) * fRowBytes);
- return row + (x - fBounds.fLeft);
- }
- /**
- * Returns the address of the specified pixel, computing the pixel-size
- * at runtime based on the mask format. This will be slightly slower than
- * using one of the routines where the format is implied by the name
- * e.g. getAddr8 or getAddr32.
- *
- * x,y must be contained by the mask's bounds (this is asserted in the
- * debug build, but not checked in the release build.)
- *
- * This should not be called with kBW_Format, as it will give unspecified
- * results (and assert in the debug build).
- */
- void* getAddr(int x, int y) const;
- enum AllocType {
- kUninit_Alloc,
- kZeroInit_Alloc,
- };
- static uint8_t* AllocImage(size_t bytes, AllocType = kUninit_Alloc);
- static void FreeImage(void* image);
- enum CreateMode {
- kJustComputeBounds_CreateMode, //!< compute bounds and return
- kJustRenderImage_CreateMode, //!< render into preallocate mask
- kComputeBoundsAndRenderImage_CreateMode //!< compute bounds, alloc image and render into it
- };
- /** Iterates over the coverage values along a scanline in a given SkMask::Format. Provides
- * constructor, copy constructor for creating
- * operator++, operator-- for iterating over the coverage values on a scanline
- * operator>>= to add row bytes
- * operator* to get the coverage value at the current location
- * operator< to compare two iterators
- */
- template <Format F> struct AlphaIter;
- /**
- * Returns initial destination mask data padded by radiusX and radiusY
- */
- static SkMask PrepareDestination(int radiusX, int radiusY, const SkMask& src);
- };
- template <> struct SkMask::AlphaIter<SkMask::kBW_Format> {
- AlphaIter(const uint8_t* ptr, int offset) : fPtr(ptr), fOffset(7 - offset) {}
- AlphaIter(const AlphaIter& that) : fPtr(that.fPtr), fOffset(that.fOffset) {}
- AlphaIter& operator++() {
- if (0 < fOffset ) {
- --fOffset;
- } else {
- ++fPtr;
- fOffset = 7;
- }
- return *this;
- }
- AlphaIter& operator--() {
- if (fOffset < 7) {
- ++fOffset;
- } else {
- --fPtr;
- fOffset = 0;
- }
- return *this;
- }
- AlphaIter& operator>>=(uint32_t rb) {
- fPtr = SkTAddOffset<const uint8_t>(fPtr, rb);
- return *this;
- }
- uint8_t operator*() const { return ((*fPtr) >> fOffset) & 1 ? 0xFF : 0; }
- bool operator<(const AlphaIter& that) const {
- return fPtr < that.fPtr || (fPtr == that.fPtr && fOffset > that.fOffset);
- }
- const uint8_t* fPtr;
- int fOffset;
- };
- template <> struct SkMask::AlphaIter<SkMask::kA8_Format> {
- AlphaIter(const uint8_t* ptr) : fPtr(ptr) {}
- AlphaIter(const AlphaIter& that) : fPtr(that.fPtr) {}
- AlphaIter& operator++() { ++fPtr; return *this; }
- AlphaIter& operator--() { --fPtr; return *this; }
- AlphaIter& operator>>=(uint32_t rb) {
- fPtr = SkTAddOffset<const uint8_t>(fPtr, rb);
- return *this;
- }
- uint8_t operator*() const { return *fPtr; }
- bool operator<(const AlphaIter& that) const { return fPtr < that.fPtr; }
- const uint8_t* fPtr;
- };
- template <> struct SkMask::AlphaIter<SkMask::kARGB32_Format> {
- AlphaIter(const uint32_t* ptr) : fPtr(ptr) {}
- AlphaIter(const AlphaIter& that) : fPtr(that.fPtr) {}
- AlphaIter& operator++() { ++fPtr; return *this; }
- AlphaIter& operator--() { --fPtr; return *this; }
- AlphaIter& operator>>=(uint32_t rb) {
- fPtr = SkTAddOffset<const uint32_t>(fPtr, rb);
- return *this;
- }
- uint8_t operator*() const { return SkGetPackedA32(*fPtr); }
- bool operator<(const AlphaIter& that) const { return fPtr < that.fPtr; }
- const uint32_t* fPtr;
- };
- template <> struct SkMask::AlphaIter<SkMask::kLCD16_Format> {
- AlphaIter(const uint16_t* ptr) : fPtr(ptr) {}
- AlphaIter(const AlphaIter& that) : fPtr(that.fPtr) {}
- AlphaIter& operator++() { ++fPtr; return *this; }
- AlphaIter& operator--() { --fPtr; return *this; }
- AlphaIter& operator>>=(uint32_t rb) {
- fPtr = SkTAddOffset<const uint16_t>(fPtr, rb);
- return *this;
- }
- uint8_t operator*() const {
- unsigned packed = *fPtr;
- unsigned r = SkPacked16ToR32(packed);
- unsigned g = SkPacked16ToG32(packed);
- unsigned b = SkPacked16ToB32(packed);
- return (r + g + b) / 3;
- }
- bool operator<(const AlphaIter& that) const { return fPtr < that.fPtr; }
- const uint16_t* fPtr;
- };
- ///////////////////////////////////////////////////////////////////////////////
- /**
- * \using SkAutoMaskImage
- *
- * Stack class used to manage the fImage buffer in a SkMask.
- * When this object loses scope, the buffer is freed with SkMask::FreeImage().
- */
- using SkAutoMaskFreeImage = std::unique_ptr<uint8_t,SkFunctionWrapper<void,void,SkMask::FreeImage>>;
- #define SkAutoMaskFreeImage(...) SK_REQUIRE_LOCAL_VAR(SkAutoMaskFreeImage)
- #endif
|