1 /* 2 * Copyright 2014, Haiku, Inc. 3 * Distributed under the terms of the MIT License. 4 * 5 * Copyright 2002-2004 Maxim Shemanarev (http://www.antigrain.com) 6 * 7 * Class clipped_alpha_mask, a modified version of alpha_mask_u8 that can 8 * offset the mask, and has a controllable value for the area outside it. 9 */ 10 11 #ifndef AGG_CLIPED_ALPHA_MASK_INCLUDED 12 #define AGG_CLIPED_ALPHA_MASK_INCLUDED 13 14 15 #include <agg_alpha_mask_u8.h> 16 #include <agg_rendering_buffer.h> 17 18 19 namespace agg 20 { 21 class clipped_alpha_mask 22 { 23 public: 24 typedef int8u cover_type; 25 enum cover_scale_e 26 { 27 cover_shift = 8, 28 cover_none = 0, 29 cover_full = 255 30 }; 31 32 clipped_alpha_mask() 33 : m_xOffset(0), m_yOffset(0), m_rbuf(0), m_outside(0) {} 34 clipped_alpha_mask(rendering_buffer& rbuf) 35 : m_xOffset(0), m_yOffset(0), m_rbuf(&rbuf), m_outside(0) {} 36 37 void attach(rendering_buffer& rbuf) 38 { 39 m_rbuf = &rbuf; 40 } 41 42 void attach(rendering_buffer& rbuf, int x, int y, int8u outside) 43 { 44 m_rbuf = &rbuf; 45 m_xOffset = x; 46 m_yOffset = y; 47 m_outside = outside; 48 } 49 50 void combine_hspan(int x, int y, cover_type* dst, int num_pix) const 51 { 52 int count = num_pix; 53 cover_type* covers = dst; 54 55 bool has_inside = _set_outside(x, y, covers, count); 56 if (!has_inside) 57 return; 58 59 const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset; 60 do 61 { 62 *covers = (cover_type)((cover_full + (*covers) * (*mask)) 63 >> cover_shift); 64 ++covers; 65 mask += Step; 66 } 67 while(--count); 68 } 69 70 void get_hspan(int x, int y, cover_type* dst, int num_pix) const 71 { 72 int count = num_pix; 73 cover_type* covers = dst; 74 75 bool has_inside = _set_outside(x, y, covers, count); 76 if (!has_inside) 77 return; 78 79 const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset; 80 memcpy(covers, mask, count); 81 } 82 83 private: 84 bool _set_outside(int& x, int& y, cover_type*& covers, 85 int& count) const 86 { 87 x -= m_xOffset; 88 y -= m_yOffset; 89 90 int xmax = m_rbuf->width() - 1; 91 int ymax = m_rbuf->height() - 1; 92 93 int num_pix = count; 94 cover_type* dst = covers; 95 96 if(y < 0 || y > ymax) 97 { 98 memset(dst, m_outside, num_pix * sizeof(cover_type)); 99 return false; 100 } 101 102 if(x < 0) 103 { 104 count += x; 105 if(count <= 0) 106 { 107 memset(dst, m_outside, num_pix * sizeof(cover_type)); 108 return false; 109 } 110 memset(covers, m_outside, -x * sizeof(cover_type)); 111 covers -= x; 112 x = 0; 113 } 114 115 if(x + count > xmax) 116 { 117 int rest = x + count - xmax - 1; 118 count -= rest; 119 if(count <= 0) 120 { 121 memset(dst, m_outside, num_pix * sizeof(cover_type)); 122 return false; 123 } 124 memset(covers + count, m_outside, rest * sizeof(cover_type)); 125 } 126 127 return true; 128 } 129 130 131 private: 132 int m_xOffset; 133 int m_yOffset; 134 135 rendering_buffer* m_rbuf; 136 int8u m_outside; 137 138 static const int Step = 1; 139 static const int Offset = 0; 140 }; 141 } 142 143 144 #endif 145