ETL  0.04.19
_pen.h
Go to the documentation of this file.
1 
25 /* === S T A R T =========================================================== */
26 
27 #ifndef __ETL__PEN_H
28 #define __ETL__PEN_H
29 
30 /* === H E A D E R S ======================================================= */
31 
32 #include "_curve_func.h"
33 #include <cassert>
34 #include <iterator>
35 #include <algorithm>
36 
37 /* === M A C R O S ========================================================= */
38 
39 /* === T Y P E D E F S ===================================================== */
40 
41 /* === C L A S S E S & S T R U C T S ======================================= */
42 
44 
45 template<typename T>
47 {
48 public:
49  struct iterator_category : public std::random_access_iterator_tag {};
50  typedef T value_type;
51  typedef int difference_type;
52  typedef value_type* pointer;
54 
56 
58  int pitch_;
59 
60  reference operator[](int i)const { assert(data_); return *(pointer)( (char*)data_+pitch_*i ); }
61  reference operator*()const { assert(data_); return *data_; }
62  pointer operator->() const { assert(data_); return &(operator*()); }
63 
64  void inc() { assert(data_); data_ = (pointer)((char*)data_ + pitch_); }
65  void inc(int n) { assert(data_); data_ = (pointer)((char*)data_ + n*pitch_); }
66 
67  void dec() { assert(data_); data_ = (pointer)((char*)data_ - pitch_); }
68  void dec(int n) { assert(data_); data_ = (pointer)((char*)data_ - n*pitch_); }
69 
70  const self_type &operator++() { assert(data_); inc(); return *this; }
71  const self_type &operator--() { assert(data_); dec(); return *this; }
72 
74  { assert(data_); self_type ret(*this); inc(); return ret; }
76  { assert(data_); self_type ret(*this); dec(); return ret; }
77 
78  bool operator==(const self_type &rhs)const
79  { return data_==rhs.data_; }
80 
81  bool operator!=(const self_type &rhs)const
82  { return data_!=rhs.data_; }
83 
85  { assert(data_); return ((char*)data_-(char*)rhs.data_-1)/pitch_+1; }
86 
88  {
89  assert(data_);
90  self_type ret(*this);
91  ret.inc(rhs);
92  return ret;
93  }
94 
96  {
97  assert(data_);
98  self_type ret(*this);
99  ret.dec(rhs);
100  return ret;
101  }
102 
104  {
106  }
107 
108  operator bool()const { return (bool)data_; }
109  bool operator!()const { return !data_; }
110 
111  generic_pen_row_iterator(pointer data, int pitch):data_(data),pitch_(pitch) { }
113 };
114 
115 template<typename T, typename AT=T>
117 {
118 public:
119  typedef T value_type;
120  typedef AT accumulator_type;
121  typedef value_type* pointer;
123  typedef const value_type* const_pointer;
126  typedef const value_type& const_reference;
127 
130 
133 
135  {
136  typedef int value_type;
139  value_type &operator[](int i)const { return i?y:x; }
140  };
141 
142 protected:
143  int x_,y_;
144  int w_,h_;
145 private:
146  int pitch_;
149 
151 
152  void addptr(int nbytes)
153  {
154  data_ = (pointer)((char*)data_ + nbytes);
155  }
156 
157  void subptr(int nbytes)
158  {
159  data_ = (pointer)((char*)data_ - nbytes);
160  }
161 
162 public:
163 
164  generic_pen(value_type *data, int w, int h, int pitch):
165  x_(0),
166  y_(0),
167  w_(w),
168  h_(h),
169  pitch_(pitch),
170  data_(data)
171  {
172  }
173 
174  generic_pen(value_type *data, int w, int h):
175  x_(0),
176  y_(0),
177  w_(w),
178  h_(h),
179  pitch_(sizeof(value_type)*w),
180  data_(data)
181  {
182  }
183 
185 
186  self_type& move(int a, int b)
187  {
188  assert(data_);
189  x_ += a, y_ += b;
190  addptr(b*pitch_ + a*sizeof(value_type));
191  return *this;
192  }
193  self_type& move_to(int x, int y) { assert(data_); return move(x - x_,y - y_);}
194  void set_value(const value_type &v) { value_=v; }
195 
196  void inc_x() { assert(data_); x_++; data_++; }
197  void dec_x() { assert(data_); x_--; data_--; }
198  void inc_y() { assert(data_); y_++; addptr(pitch_); }
199  void dec_y() { assert(data_); y_--; subptr(pitch_); }
200 
201  void inc_x(int n) { assert(data_); x_+=n; data_+=n; }
202  void dec_x(int n) { assert(data_); x_-=n; data_-=n; }
203  void inc_y(int n) { assert(data_); y_+=n; data_ = (pointer)((char*)data_ + pitch_*n); }
204  void dec_y(int n) { assert(data_); y_-=n; data_ = (pointer)((char*)data_ - pitch_*n); }
205 
206  void put_value(const value_type &v)const { assert(data_); *data_=v; }
207  void put_value()const { assert(data_); put_value(value_); }
208 
209  void put_value_clip(const value_type &v)const
210  { if(!clipped()) put_value(v); }
212 
213  const_reference get_value()const { assert(data_); return *data_; }
214 
215  const_reference get_value_at(int x, int y)const { assert(data_); return ((pointer)(((char*)data_)+y*pitch_))[x]; }
216 
217  const_reference get_value_clip_at(int x, int y)const { assert(data_); if(clipped(x,y))return value_type(); return ((pointer)(((char*)data_)+y*pitch_))[x]; }
218 
219  const value_type get_value_clip()const { assert(data_); if(clipped())return value_type(); return *data_; }
220 
221  const value_type get_pen_value()const { return value_; }
222 
223  void put_hline(int l,const value_type &v)
224  {for(;l>0;l--,inc_x())put_value(v);}
225 
226  void put_hline(int l) {put_hline(l,value_);}
227 
228  void put_hline_clip(int l, const value_type &v)
229  {l=std::min(l,w_-x_);for(;l>0;l--,inc_x())put_value_clip(v);}
230 
232 
233  //the put_block functions do not modify the pen
234  void put_block(int h, int w, const value_type &v)
235  {
236  self_type row(*this);
237  for(;h>0;h--,row.inc_y())
238  {
239  self_type col(row);
240  col.put_hline(w,v);
241  }
242  }
243 
244  void put_block(int h, int w) { put_block(h,w,value_); }
245 
246  void put_block_clip(int h, int w, const value_type &v)
247  {
248  self_type row(*this);
249 
250  //clip start position
251  if(row.x_ < 0) { w+=row.x_; row.inc_x(-row.x_); }
252  if(row.y_ < 0) { h+=row.y_; row.inc_y(-row.y_); }
253 
254  //clip width and height of copy rect
255  h = std::min(h,h_-y_);
256  w = std::min(w,w_-x_);
257 
258  //copy rect
259  for(;h>0;h--,row.inc_y())
260  {
261  self_type col(row);
262  col.put_hline(w,v); //already clipped
263  }
264  }
265 
266  void put_block_clip(int h, int w) { put_block(h,w,value_); }
267 
268 
269  iterator_x operator[](int i)const { assert(data_); return (pointer)(((char*)data_)+i*pitch_); }
270 
271  iterator_x x() { assert(data_); return data_; }
272  iterator_x begin_x() { assert(data_); return data_-x_; }
273  iterator_x end_x() { assert(data_); return data_-x_+w_; }
274 
275  iterator_y y() { assert(data_); return iterator_y(data_,pitch_); }
276  iterator_y begin_y() { assert(data_); return iterator_y((pointer)((char*)data_ - y_*pitch_),pitch_); }
277  iterator_y end_y() { assert(data_); return iterator_y((pointer)((char*)data_ + (h_-y_)*pitch_),pitch_); }
278 
279  operator bool()const { return (bool)data_; }
280  bool operator!()const { return !data_; }
281  bool operator==(const self_type &rhs)const { return data_==rhs.data_; }
282  bool operator!=(const self_type &rhs)const { return data_!=rhs.data_; }
283  bool clipped(int x, int y)const { return !(x_+x>=0 && y_+y>=0 && x_+x<w_ && y_+y<h_); }
284  bool clipped()const { return !(x_>=0 && y_>=0 && x_<w_ && y_<h_); }
285 
287  {
288  assert(data_);
289  assert(pitch_==rhs.pitch_);
290  int ptr_diff=(char*)data_-(char*)rhs.data_-1;
291  return difference_type(ptr_diff%pitch_/sizeof(value_type)+1,ptr_diff/pitch_);
292  }
293 
295  {
296  assert(data_);
297  self_type ret(*this);
298  ret.move(rhs.x,rhs.y);
299  return ret;
300  }
301 
304 
305  self_type get_start()const {return *this + diff_begin(); }
306  self_type get_end()const {return *this + diff_end(); }
307 
308  int get_width()const {return w_;}
309  int get_height()const {return h_;}
310 
311  int get_w()const {return w_;}
312  int get_h()const {return h_;}
313  int get_pitch()const {return pitch_;}
314 };
315 
316 template <
317  typename PEN_,
318  typename A_=float,
320 >
321 class alpha_pen : public PEN_
322 {
323 public:
324  typedef A_ alpha_type;
325  typedef AFFINE_ affine_func_type;
326 
327  typedef typename PEN_::value_type value_type;
329 
330 private:
332 
333 protected:
335 
336 public:
337  using PEN_::get_value;
338  using PEN_::get_pen_value;
339  using PEN_::inc_x;
340  using PEN_::dec_x;
341  using PEN_::inc_y;
342  using PEN_::dec_y;
343  using PEN_::clipped;
344  using PEN_::w_;
345  using PEN_::h_;
346  using PEN_::x_;
347  using PEN_::y_;
348 
349  alpha_pen(const alpha_type &a = 1, const affine_func_type &func = affine_func_type()):alpha_(a),affine_func_(func) { }
350  alpha_pen(const PEN_ &x, const alpha_type &a=1, const affine_func_type &func=affine_func_type())
351  :PEN_(x),alpha_(a),affine_func_(func) { }
352 
353  const alpha_type& get_alpha()const { return alpha_; }
354  void get_alpha(alpha_type &a) const { a=alpha_; }
355  void set_alpha(alpha_type a) { alpha_=a; }
356 
357  void put_value(const value_type &v, alpha_type a=1)const
358  { PEN_::put_value(affine_func_(get_value(),v,alpha_*a)); }
359  void put_value()const { put_value(get_pen_value()); }
360  void put_value_alpha(alpha_type a)const { put_value(get_pen_value(),a); }
361  void put_hline(int l, const alpha_type &a = 1){for(;l>0;l--,inc_x())put_value_alpha(a);}
362 
363  void put_value_clip(const value_type &v, alpha_type a=1)const
364  { if(!clipped())PEN_::put_value(affine_func_(get_value(),v,alpha_*a)); }
365  void put_value_clip()const { put_value_clip(get_pen_value()); }
366  void put_value_clip_alpha(alpha_type a)const { put_value_clip(get_pen_value(),a); }
367  void put_hline_clip(int l, const alpha_type &a = 1){l=std::min(l,w_-x_);for(;l>0;l--,inc_x())put_value_clip_alpha(a);}
368 
369  //the put_block functions do not modify the pen
370  void put_block(int h, int w, const alpha_type &a = 1)
371  {
372  self_type row(*this);
373  for(;h>0;h--,row.inc_y())
374  {
375  self_type col(row);
376  col.put_hline(w,a);
377  }
378  }
379 
380  void put_block_clip(int h, int w, const alpha_type &a = 1)
381  {
382  self_type row(*this);
383 
384  //clip start position
385  if(row.x_ < 0) { w+=row.x_; row.inc_x(-row.x_); }
386  if(row.y_ < 0) { h+=row.y_; row.inc_y(-row.y_); }
387 
388  //clip width and height of copy rect
389  h = std::min(h,h_-y_);
390  w = std::min(w,w_-x_);
391 
392  //copy rect
393  for(;h>0;h--,row.inc_y())
394  {
395  self_type col(row);
396  col.put_hline(w,a); //already clipped
397  }
398  }
399 };
400 
402 
403 /* === E X T E R N S ======================================================= */
404 
405 /* === E N D =============================================================== */
406 
407 #endif