1 /* 2 * Copyright (C) 2006 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef SkMask_DEFINED 18 #define SkMask_DEFINED 19 20 #include "SkRect.h" 21 22 /** \class SkMask 23 SkMask is used to describe alpha bitmaps, either 1bit, 8bit, or 24 the 3-channel 3D format. These are passed to SkMaskFilter objects. 25 */ 26 struct SkMask { 27 enum Format { 28 kBW_Format, //!< 1bit per pixel mask (e.g. monochrome) 29 kA8_Format, //!< 8bits per pixel mask (e.g. antialiasing) 30 k3D_Format, //!< 3 8bit per pixl planes: alpha, mul, add 31 32 /* The LCD formats look like this in memory: 33 34 First, there's an A8 plane which contains the average alpha value for 35 each pixel. Because of this, the LCD formats can be passed directly 36 to functions which expect an A8 and everything will just work. 37 38 After that in memory, there's a bitmap of 32-bit values which have 39 been RGB order corrected for the current screen (based on the 40 settings in SkFontHost at the time of renderering). The alpha value 41 for each pixel is the maximum of the three alpha values. 42 43 kHorizontalLCD_Format has an extra column of pixels on the left and right 44 edges. kVerticalLCD_Format has an extra row at the top and bottom. 45 */ 46 47 kHorizontalLCD_Format, //!< 4 bytes/pixel: a/r/g/b 48 kVerticalLCD_Format, //!< 4 bytes/pixel: a/r/g/b 49 kARGB32_Format, //!< SkPMColor 50 kLCD16_Format //!< 565 alpha for r/g/b 51 }; 52 53 enum { 54 kCountMaskFormats = kVerticalLCD_Format + 1 55 }; 56 57 uint8_t* fImage; 58 SkIRect fBounds; 59 uint32_t fRowBytes; 60 Format fFormat; 61 62 /** Returns true if the mask is empty: i.e. it has an empty bounds. 63 */ isEmptySkMask64 bool isEmpty() const { return fBounds.isEmpty(); } 65 66 /** Return the byte size of the mask, assuming only 1 plane. 67 Does not account for k3D_Format. For that, use computeTotalImageSize(). 68 If there is an overflow of 32bits, then returns 0. 69 */ 70 size_t computeImageSize() const; 71 72 /** Return the byte size of the mask, taking into account 73 any extra planes (e.g. k3D_Format). 74 If there is an overflow of 32bits, then returns 0. 75 */ 76 size_t computeTotalImageSize() const; 77 78 /** Returns the address of the byte that holds the specified bit. 79 Asserts that the mask is kBW_Format, and that x,y are in range. 80 x,y are in the same coordiate space as fBounds. 81 */ getAddr1SkMask82 uint8_t* getAddr1(int x, int y) const { 83 SkASSERT(fFormat == kBW_Format); 84 SkASSERT(fBounds.contains(x, y)); 85 SkASSERT(fImage != NULL); 86 return fImage + ((x - fBounds.fLeft) >> 3) + (y - fBounds.fTop) * fRowBytes; 87 } 88 89 /** Returns the address of the specified byte. 90 Asserts that the mask is kA8_Format, and that x,y are in range. 91 x,y are in the same coordiate space as fBounds. 92 */ getAddrSkMask93 uint8_t* getAddr(int x, int y) const { 94 SkASSERT(fFormat != kBW_Format); 95 SkASSERT(fBounds.contains(x, y)); 96 SkASSERT(fImage != NULL); 97 return fImage + x - fBounds.fLeft + (y - fBounds.fTop) * fRowBytes; 98 } 99 100 /** 101 * Return the address of the specified 16bit mask. In the debug build, 102 * this asserts that the mask's format is kLCD16_Format, and that (x,y) 103 * are contained in the mask's fBounds. 104 */ getAddrLCD16SkMask105 uint16_t* getAddrLCD16(int x, int y) const { 106 SkASSERT(kLCD16_Format == fFormat); 107 SkASSERT(fBounds.contains(x, y)); 108 SkASSERT(fImage != NULL); 109 uint16_t* row = (uint16_t*)(fImage + (y - fBounds.fTop) * fRowBytes); 110 return row + (x - fBounds.fLeft); 111 } 112 113 /** Return an address into the 32-bit plane of an LCD or VerticalLCD mask 114 for the given position. 115 */ getAddrLCDSkMask116 const uint32_t* getAddrLCD(int x, int y) const { 117 SkASSERT(fFormat == kHorizontalLCD_Format || fFormat == kVerticalLCD_Format); 118 SkASSERT(fImage != NULL); 119 120 return reinterpret_cast<const uint32_t*>(fImage + SkAlign4(fRowBytes * fBounds.height())) + 121 x - fBounds.fLeft + (y - fBounds.fTop) * rowWordsLCD(); 122 } 123 124 /** Return the number of 32-bit words in a row of the 32-bit plane of an 125 LCD or VerticalLCD mask. 126 */ rowWordsLCDSkMask127 unsigned rowWordsLCD() const { 128 SkASSERT(fFormat == kHorizontalLCD_Format || fFormat == kVerticalLCD_Format); 129 if (fFormat == kHorizontalLCD_Format) { 130 return fBounds.width() + 2; 131 } else { 132 return fBounds.width(); 133 } 134 } 135 136 static uint8_t* AllocImage(size_t bytes); 137 static void FreeImage(void* image); 138 139 enum CreateMode { 140 kJustComputeBounds_CreateMode, //!< compute bounds and return 141 kJustRenderImage_CreateMode, //!< render into preallocate mask 142 kComputeBoundsAndRenderImage_CreateMode //!< compute bounds, alloc image and render into it 143 }; 144 FormatIsLCDSkMask145 static bool FormatIsLCD(Format fm) { 146 return kHorizontalLCD_Format == fm || kVerticalLCD_Format == fm; 147 } 148 }; 149 150 #endif 151 152