summaryrefslogtreecommitdiffstats
path: root/gfx/skia/skia/src/core/SkMask.h
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/skia/skia/src/core/SkMask.h')
-rw-r--r--gfx/skia/skia/src/core/SkMask.h243
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