1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
28a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/*
3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2006 The Android Open Source Project
48a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
78a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */
88a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifndef SkMask_DEFINED
118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkMask_DEFINED
128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkRect.h"
148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/** \class SkMask
168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkMask is used to describe alpha bitmaps, either 1bit, 8bit, or
178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    the 3-channel 3D format. These are passed to SkMaskFilter objects.
188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstruct SkMask {
208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    enum Format {
218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        kBW_Format, //!< 1bit per pixel mask (e.g. monochrome)
228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        kA8_Format, //!< 8bits per pixel mask (e.g. antialiasing)
238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        k3D_Format, //!< 3 8bit per pixl planes: alpha, mul, add
24f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com        kARGB32_Format,         //!< SkPMColor
251eeaf0ba2381f84ffd889f56303cbe0d1886bb21caryclark@google.com        kLCD16_Format,          //!< 565 alpha for r/g/b
261eeaf0ba2381f84ffd889f56303cbe0d1886bb21caryclark@google.com        kLCD32_Format           //!< 888 alpha for r/g/b
278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    };
28309485b7b51f4cae4c0361ab4da00fe9cc89515cagl@chromium.org
298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    enum {
30effc5016f040945a53ab0ea47f9ea02404c17805reed@google.com        kCountMaskFormats = kLCD32_Format + 1
318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    };
328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint8_t*    fImage;
348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkIRect     fBounds;
3549f0ff25a046d6001dc2d095b6fa3c30f0f46b6areed@android.com    uint32_t    fRowBytes;
3649f0ff25a046d6001dc2d095b6fa3c30f0f46b6areed@android.com    Format      fFormat;
378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
38543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com    /** Returns true if the mask is empty: i.e. it has an empty bounds.
39543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com     */
40543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com    bool isEmpty() const { return fBounds.isEmpty(); }
41543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com
428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Return the byte size of the mask, assuming only 1 plane.
43543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com        Does not account for k3D_Format. For that, use computeTotalImageSize().
44543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com        If there is an overflow of 32bits, then returns 0.
458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    size_t computeImageSize() const;
4749f0ff25a046d6001dc2d095b6fa3c30f0f46b6areed@android.com
488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Return the byte size of the mask, taking into account
498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        any extra planes (e.g. k3D_Format).
50543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com        If there is an overflow of 32bits, then returns 0.
518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    size_t computeTotalImageSize() const;
538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Returns the address of the byte that holds the specified bit.
558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        Asserts that the mask is kBW_Format, and that x,y are in range.
568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        x,y are in the same coordiate space as fBounds.
578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
5849f0ff25a046d6001dc2d095b6fa3c30f0f46b6areed@android.com    uint8_t* getAddr1(int x, int y) const {
59edb606cb999887d54629f361bcbf57c5fede1bb0reed@google.com        SkASSERT(kBW_Format == fFormat);
608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(fBounds.contains(x, y));
618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(fImage != NULL);
628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return fImage + ((x - fBounds.fLeft) >> 3) + (y - fBounds.fTop) * fRowBytes;
638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
6449f0ff25a046d6001dc2d095b6fa3c30f0f46b6areed@android.com
658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Returns the address of the specified byte.
668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        Asserts that the mask is kA8_Format, and that x,y are in range.
678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        x,y are in the same coordiate space as fBounds.
688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
697989186dab6bc2f1c1927daf91bddd32b7fd8d0creed@google.com    uint8_t* getAddr8(int x, int y) const {
70edb606cb999887d54629f361bcbf57c5fede1bb0reed@google.com        SkASSERT(kA8_Format == fFormat);
718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(fBounds.contains(x, y));
728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(fImage != NULL);
738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return fImage + x - fBounds.fLeft + (y - fBounds.fTop) * fRowBytes;
748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
76f88d6765a594cf9fb0825b74779f74394a7ccc7areed@google.com    /**
77f88d6765a594cf9fb0825b74779f74394a7ccc7areed@google.com     *  Return the address of the specified 16bit mask. In the debug build,
78f88d6765a594cf9fb0825b74779f74394a7ccc7areed@google.com     *  this asserts that the mask's format is kLCD16_Format, and that (x,y)
79f88d6765a594cf9fb0825b74779f74394a7ccc7areed@google.com     *  are contained in the mask's fBounds.
80f88d6765a594cf9fb0825b74779f74394a7ccc7areed@google.com     */
81f88d6765a594cf9fb0825b74779f74394a7ccc7areed@google.com    uint16_t* getAddrLCD16(int x, int y) const {
82f88d6765a594cf9fb0825b74779f74394a7ccc7areed@google.com        SkASSERT(kLCD16_Format == fFormat);
83f88d6765a594cf9fb0825b74779f74394a7ccc7areed@google.com        SkASSERT(fBounds.contains(x, y));
84f88d6765a594cf9fb0825b74779f74394a7ccc7areed@google.com        SkASSERT(fImage != NULL);
85f88d6765a594cf9fb0825b74779f74394a7ccc7areed@google.com        uint16_t* row = (uint16_t*)(fImage + (y - fBounds.fTop) * fRowBytes);
86f88d6765a594cf9fb0825b74779f74394a7ccc7areed@google.com        return row + (x - fBounds.fLeft);
87f88d6765a594cf9fb0825b74779f74394a7ccc7areed@google.com    }
88f88d6765a594cf9fb0825b74779f74394a7ccc7areed@google.com
891eeaf0ba2381f84ffd889f56303cbe0d1886bb21caryclark@google.com    /**
901eeaf0ba2381f84ffd889f56303cbe0d1886bb21caryclark@google.com     *  Return the address of the specified 32bit mask. In the debug build,
911eeaf0ba2381f84ffd889f56303cbe0d1886bb21caryclark@google.com     *  this asserts that the mask's format is kLCD32_Format, and that (x,y)
921eeaf0ba2381f84ffd889f56303cbe0d1886bb21caryclark@google.com     *  are contained in the mask's fBounds.
931eeaf0ba2381f84ffd889f56303cbe0d1886bb21caryclark@google.com     */
941eeaf0ba2381f84ffd889f56303cbe0d1886bb21caryclark@google.com    uint32_t* getAddrLCD32(int x, int y) const {
951eeaf0ba2381f84ffd889f56303cbe0d1886bb21caryclark@google.com        SkASSERT(kLCD32_Format == fFormat);
961eeaf0ba2381f84ffd889f56303cbe0d1886bb21caryclark@google.com        SkASSERT(fBounds.contains(x, y));
971eeaf0ba2381f84ffd889f56303cbe0d1886bb21caryclark@google.com        SkASSERT(fImage != NULL);
981eeaf0ba2381f84ffd889f56303cbe0d1886bb21caryclark@google.com        uint32_t* row = (uint32_t*)(fImage + (y - fBounds.fTop) * fRowBytes);
991eeaf0ba2381f84ffd889f56303cbe0d1886bb21caryclark@google.com        return row + (x - fBounds.fLeft);
1001eeaf0ba2381f84ffd889f56303cbe0d1886bb21caryclark@google.com    }
1012fd42c471c77f54ace35c13975651e17d5b2e8c6skia.committer@gmail.com
1025bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com    /**
1035bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com     *  Return the address of the specified 32bit mask. In the debug build,
1045bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com     *  this asserts that the mask's format is 32bits, and that (x,y)
1055bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com     *  are contained in the mask's fBounds.
1065bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com     */
1075bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com    uint32_t* getAddr32(int x, int y) const {
1085bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com        SkASSERT(kLCD32_Format == fFormat || kARGB32_Format == fFormat);
1095bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com        SkASSERT(fBounds.contains(x, y));
1105bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com        SkASSERT(fImage != NULL);
1115bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com        uint32_t* row = (uint32_t*)(fImage + (y - fBounds.fTop) * fRowBytes);
1125bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com        return row + (x - fBounds.fLeft);
1135bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com    }
1142fd42c471c77f54ace35c13975651e17d5b2e8c6skia.committer@gmail.com
115f52e55543e8e34a9fc9dd6f6f2d0e14e25d97ba5reed@google.com    /**
116f52e55543e8e34a9fc9dd6f6f2d0e14e25d97ba5reed@google.com     *  Returns the address of the specified pixel, computing the pixel-size
117f52e55543e8e34a9fc9dd6f6f2d0e14e25d97ba5reed@google.com     *  at runtime based on the mask format. This will be slightly slower than
118f52e55543e8e34a9fc9dd6f6f2d0e14e25d97ba5reed@google.com     *  using one of the routines where the format is implied by the name
119f52e55543e8e34a9fc9dd6f6f2d0e14e25d97ba5reed@google.com     *  e.g. getAddr8 or getAddrLCD32.
120f52e55543e8e34a9fc9dd6f6f2d0e14e25d97ba5reed@google.com     *
121f52e55543e8e34a9fc9dd6f6f2d0e14e25d97ba5reed@google.com     *  x,y must be contained by the mask's bounds (this is asserted in the
122f52e55543e8e34a9fc9dd6f6f2d0e14e25d97ba5reed@google.com     *  debug build, but not checked in the release build.)
123f52e55543e8e34a9fc9dd6f6f2d0e14e25d97ba5reed@google.com     *
124f52e55543e8e34a9fc9dd6f6f2d0e14e25d97ba5reed@google.com     *  This should not be called with kBW_Format, as it will give unspecified
125f52e55543e8e34a9fc9dd6f6f2d0e14e25d97ba5reed@google.com     *  results (and assert in the debug build).
126f52e55543e8e34a9fc9dd6f6f2d0e14e25d97ba5reed@google.com     */
127f52e55543e8e34a9fc9dd6f6f2d0e14e25d97ba5reed@google.com    void* getAddr(int x, int y) const;
128f52e55543e8e34a9fc9dd6f6f2d0e14e25d97ba5reed@google.com
1298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static uint8_t* AllocImage(size_t bytes);
1308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static void FreeImage(void* image);
131f88d6765a594cf9fb0825b74779f74394a7ccc7areed@google.com
1328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    enum CreateMode {
1338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        kJustComputeBounds_CreateMode,      //!< compute bounds and return
1348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        kJustRenderImage_CreateMode,        //!< render into preallocate mask
1358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        kComputeBoundsAndRenderImage_CreateMode  //!< compute bounds, alloc image and render into it
1368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    };
1378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
1388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13986b49d2ef316989a5b0b5bd533eda43438d988e3reed@google.com///////////////////////////////////////////////////////////////////////////////
14086b49d2ef316989a5b0b5bd533eda43438d988e3reed@google.com
14186b49d2ef316989a5b0b5bd533eda43438d988e3reed@google.com/**
14286b49d2ef316989a5b0b5bd533eda43438d988e3reed@google.com *  \class SkAutoMaskImage
14386b49d2ef316989a5b0b5bd533eda43438d988e3reed@google.com *
14486b49d2ef316989a5b0b5bd533eda43438d988e3reed@google.com *  Stack class used to manage the fImage buffer in a SkMask.
14586b49d2ef316989a5b0b5bd533eda43438d988e3reed@google.com *  When this object loses scope, the buffer is freed with SkMask::FreeImage().
14686b49d2ef316989a5b0b5bd533eda43438d988e3reed@google.com */
14786b49d2ef316989a5b0b5bd533eda43438d988e3reed@google.comclass SkAutoMaskFreeImage {
14886b49d2ef316989a5b0b5bd533eda43438d988e3reed@google.compublic:
14986b49d2ef316989a5b0b5bd533eda43438d988e3reed@google.com    SkAutoMaskFreeImage(uint8_t* maskImage) {
15086b49d2ef316989a5b0b5bd533eda43438d988e3reed@google.com        fImage = maskImage;
15186b49d2ef316989a5b0b5bd533eda43438d988e3reed@google.com    }
152fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
15386b49d2ef316989a5b0b5bd533eda43438d988e3reed@google.com    ~SkAutoMaskFreeImage() {
15486b49d2ef316989a5b0b5bd533eda43438d988e3reed@google.com        SkMask::FreeImage(fImage);
15586b49d2ef316989a5b0b5bd533eda43438d988e3reed@google.com    }
15686b49d2ef316989a5b0b5bd533eda43438d988e3reed@google.com
15786b49d2ef316989a5b0b5bd533eda43438d988e3reed@google.comprivate:
15886b49d2ef316989a5b0b5bd533eda43438d988e3reed@google.com    uint8_t* fImage;
15986b49d2ef316989a5b0b5bd533eda43438d988e3reed@google.com};
160e61a86cfa00ea393ecc4a71fca94e1d476a37ecccommit-bot@chromium.org#define SkAutoMaskFreeImage(...) SK_REQUIRE_LOCAL_VAR(SkAutoMaskFreeImage)
16186b49d2ef316989a5b0b5bd533eda43438d988e3reed@google.com
1628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
163