1 2 /* 3 * Copyright 2006 The Android Open Source Project 4 * 5 * Use of this source code is governed by a BSD-style license that can be 6 * found in the LICENSE file. 7 */ 8 9 10 #include "SkBitmap.h" 11 #include "SkMask.h" 12 13 #ifndef ClearLow3Bits_DEFINED 14 #define ClearLow3Bits_DEFINED 15 #define ClearLow3Bits(x) ((unsigned)(x) >> 3 << 3) 16 #endif 17 18 /* 19 SK_BLITBWMASK_NAME name of function(const SkBitmap& bitmap, const SkMask& mask, const SkIRect& clip, SK_BLITBWMASK_ARGS) 20 SK_BLITBWMASK_ARGS list of additional arguments to SK_BLITBWMASK_NAME, beginning with a comma 21 SK_BLITBWMASK_BLIT8 name of function(U8CPU byteMask, SK_BLITBWMASK_DEVTYPE* dst, int x, int y) 22 SK_BLITBWMASK_GETADDR either getAddr32 or getAddr16 or getAddr8 23 SK_BLITBWMASK_DEVTYPE either U32 or U16 or U8 24 */ 25 26 static void SK_BLITBWMASK_NAME(const SkBitmap& bitmap, const SkMask& srcMask, const SkIRect& clip SK_BLITBWMASK_ARGS) 27 { 28 SkASSERT(clip.fRight <= srcMask.fBounds.fRight); 29 30 int cx = clip.fLeft; 31 int cy = clip.fTop; 32 int maskLeft = srcMask.fBounds.fLeft; 33 unsigned mask_rowBytes = srcMask.fRowBytes; 34 size_t bitmap_rowBytes = bitmap.rowBytes(); 35 unsigned height = clip.height(); 36 37 SkASSERT(mask_rowBytes != 0); 38 SkASSERT(bitmap_rowBytes != 0); 39 SkASSERT(height != 0); 40 41 const uint8_t* bits = srcMask.getAddr1(cx, cy); 42 SK_BLITBWMASK_DEVTYPE* device = bitmap.SK_BLITBWMASK_GETADDR(cx, cy); 43 44 if (cx == maskLeft && clip.fRight == srcMask.fBounds.fRight) 45 { 46 do { 47 SK_BLITBWMASK_DEVTYPE* dst = device; 48 unsigned rb = mask_rowBytes; 49 do { 50 U8CPU mask = *bits++; 51 SK_BLITBWMASK_BLIT8(mask, dst); 52 dst += 8; 53 } while (--rb != 0); 54 device = (SK_BLITBWMASK_DEVTYPE*)((char*)device + bitmap_rowBytes); 55 } while (--height != 0); 56 } 57 else 58 { 59 int left_edge = cx - maskLeft; 60 SkASSERT(left_edge >= 0); 61 int rite_edge = clip.fRight - maskLeft; 62 SkASSERT(rite_edge > left_edge); 63 64 int left_mask = 0xFF >> (left_edge & 7); 65 int rite_mask = 0xFF << (8 - (rite_edge & 7)); 66 rite_mask &= 0xFF; // only want low-8 bits of mask 67 int full_runs = (rite_edge >> 3) - ((left_edge + 7) >> 3); 68 69 // check for empty right mask, so we don't read off the end (or go slower than we need to) 70 if (rite_mask == 0) 71 { 72 SkASSERT(full_runs >= 0); 73 full_runs -= 1; 74 rite_mask = 0xFF; 75 } 76 if (left_mask == 0xFF) 77 full_runs -= 1; 78 79 // back up manually so we can keep in sync with our byte-aligned src 80 // and not trigger an assert from the getAddr## function 81 device -= left_edge & 7; 82 83 if (full_runs < 0) 84 { 85 left_mask &= rite_mask; 86 SkASSERT(left_mask != 0); 87 do { 88 U8CPU mask = *bits & left_mask; 89 SK_BLITBWMASK_BLIT8(mask, device); 90 bits += mask_rowBytes; 91 device = (SK_BLITBWMASK_DEVTYPE*)((char*)device + bitmap_rowBytes); 92 } while (--height != 0); 93 } 94 else 95 { 96 do { 97 int runs = full_runs; 98 SK_BLITBWMASK_DEVTYPE* dst = device; 99 const uint8_t* b = bits; 100 U8CPU mask; 101 102 mask = *b++ & left_mask; 103 SK_BLITBWMASK_BLIT8(mask, dst); 104 dst += 8; 105 106 while (--runs >= 0) 107 { 108 mask = *b++; 109 SK_BLITBWMASK_BLIT8(mask, dst); 110 dst += 8; 111 } 112 113 mask = *b & rite_mask; 114 SK_BLITBWMASK_BLIT8(mask, dst); 115 116 bits += mask_rowBytes; 117 device = (SK_BLITBWMASK_DEVTYPE*)((char*)device + bitmap_rowBytes); 118 } while (--height != 0); 119 } 120 } 121 } 122 123 #undef SK_BLITBWMASK_NAME 124 #undef SK_BLITBWMASK_ARGS 125 #undef SK_BLITBWMASK_BLIT8 126 #undef SK_BLITBWMASK_GETADDR 127 #undef SK_BLITBWMASK_DEVTYPE 128 #undef SK_BLITBWMASK_DOROWSETUP 129