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, int x, int y, int8u outside) 38 { 39 m_rbuf = &rbuf; 40 m_xOffset = x; 41 m_yOffset = y; 42 m_outside = outside; 43 } 44 45 void combine_hspan(int x, int y, cover_type* dst, int num_pix) const 46 { 47 int count = num_pix; 48 cover_type* covers = dst; 49 50 bool has_inside = _set_outside(x, y, covers, count); 51 if (!has_inside) 52 return; 53 54 const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset; 55 do 56 { 57 *covers = (cover_type)((cover_full + (*covers) * (*mask)) 58 >> cover_shift); 59 ++covers; 60 mask += Step; 61 } 62 while(--count); 63 } 64 65 void get_hspan(int x, int y, cover_type* dst, int num_pix) const 66 { 67 int count = num_pix; 68 cover_type* covers = dst; 69 70 bool has_inside = _set_outside(x, y, covers, count); 71 if (!has_inside) 72 return; 73 74 const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset; 75 memcpy(covers, mask, count); 76 } 77 78 private: 79 bool _set_outside(int& x, int& y, cover_type*& covers, 80 int& count) const 81 { 82 x -= m_xOffset; 83 y -= m_yOffset; 84 85 int xmax = m_rbuf->width() - 1; 86 int ymax = m_rbuf->height() - 1; 87 88 int num_pix = count; 89 cover_type* dst = covers; 90 91 if(y < 0 || y > ymax) 92 { 93 memset(dst, m_outside, num_pix * sizeof(cover_type)); 94 return false; 95 } 96 97 if(x < 0) 98 { 99 count += x; 100 if(count <= 0) 101 { 102 memset(dst, m_outside, num_pix * sizeof(cover_type)); 103 return false; 104 } 105 memset(covers, m_outside, -x * sizeof(cover_type)); 106 covers -= x; 107 x = 0; 108 } 109 110 if(x + count > xmax) 111 { 112 int rest = x + count - xmax - 1; 113 count -= rest; 114 if(count <= 0) 115 { 116 memset(dst, m_outside, num_pix * sizeof(cover_type)); 117 return false; 118 } 119 memset(covers + count, m_outside, rest * sizeof(cover_type)); 120 } 121 122 return true; 123 } 124 125 126 private: 127 int m_xOffset; 128 int m_yOffset; 129 130 rendering_buffer* m_rbuf; 131 int8u m_outside; 132 133 static const int Step = 1; 134 static const int Offset = 0; 135 }; 136 } 137 138 139 #endif 140