diff options
Diffstat (limited to 'gfx/skia/skia/src/core/SkMask.h')
-rw-r--r-- | gfx/skia/skia/src/core/SkMask.h | 243 |
1 files changed, 243 insertions, 0 deletions
diff --git a/gfx/skia/skia/src/core/SkMask.h b/gfx/skia/skia/src/core/SkMask.h new file mode 100644 index 0000000000..619dfcf76d --- /dev/null +++ b/gfx/skia/skia/src/core/SkMask.h @@ -0,0 +1,243 @@ +/* + * 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/base/SkMacros.h" +#include "include/private/base/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 : uint8_t { + 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, SkFunctionObject<SkMask::FreeImage>>; + +#endif |