00001
00025
00026
00027 #ifndef __ETL_PEN_H
00028 #define __ETL_PEN_H
00029
00030
00031
00032 #include "_curve_func.h"
00033 #include <cassert>
00034 #include <iterator>
00035 #include <algorithm>
00036
00037
00038
00039
00040
00041
00042
00043 _ETL_BEGIN_NAMESPACE
00044
00045 template<typename T>
00046 class generic_pen_row_iterator
00047 {
00048 public:
00049 struct iterator_category : public std::random_access_iterator_tag {};
00050 typedef T value_type;
00051 typedef int difference_type;
00052 typedef value_type* pointer;
00053 typedef value_type& reference;
00054
00055 typedef generic_pen_row_iterator<value_type> self_type;
00056
00057 pointer data_;
00058 int pitch_;
00059
00060 reference operator[](int i)const { assert(data_); return *(pointer)( (char*)data_+pitch_*i ); }
00061 reference operator*()const { assert(data_); return *data_; }
00062 pointer operator->() const { assert(data_); return &(operator*()); }
00063
00064 void inc() { assert(data_); data_ = (pointer)((char*)data_ + pitch_); }
00065 void inc(int n) { assert(data_); data_ = (pointer)((char*)data_ + n*pitch_); }
00066
00067 void dec() { assert(data_); data_ = (pointer)((char*)data_ - pitch_); }
00068 void dec(int n) { assert(data_); data_ = (pointer)((char*)data_ - n*pitch_); }
00069
00070 const self_type &operator++() { assert(data_); inc(); return *this; }
00071 const self_type &operator--() { assert(data_); dec(); return *this; }
00072
00073 self_type operator++(int)
00074 { assert(data_); self_type ret(*this); inc(); return ret; }
00075 self_type operator--(int)
00076 { assert(data_); self_type ret(*this); dec(); return ret; }
00077
00078 bool operator==(const self_type &rhs)const
00079 { return data_==rhs.data_; }
00080
00081 bool operator!=(const self_type &rhs)const
00082 { return data_!=rhs.data_; }
00083
00084 difference_type operator-(const self_type &rhs)const
00085 { assert(data_); return ((char*)data_-(char*)rhs.data_-1)/pitch_+1; }
00086
00087 self_type operator+(const difference_type &rhs)const
00088 {
00089 assert(data_);
00090 self_type ret(*this);
00091 ret.inc(rhs);
00092 return ret;
00093 }
00094
00095 self_type operator-(const difference_type &rhs)const
00096 {
00097 assert(data_);
00098 self_type ret(*this);
00099 ret.dec(rhs);
00100 return ret;
00101 }
00102
00103 operator const generic_pen_row_iterator<const value_type>()const
00104 {
00105 return generic_pen_row_iterator<const value_type>(data_,pitch_);
00106 }
00107
00108 operator bool()const { return (bool)data_; }
00109 bool operator!()const { return !data_; }
00110
00111 generic_pen_row_iterator(pointer data, int pitch):data_(data),pitch_(pitch) { }
00112 generic_pen_row_iterator():data_(NULL) { }
00113 };
00114
00115 template<typename T, typename AT=T>
00116 class generic_pen
00117 {
00118 public:
00119 typedef T value_type;
00120 typedef AT accumulator_type;
00121 typedef value_type* pointer;
00122 typedef const value_type* const_pointer;
00123 typedef value_type& reference;
00124 typedef const value_type& const_reference;
00125
00126 typedef pointer iterator_x;
00127 typedef const_pointer const_iterator_x;
00128
00129 typedef generic_pen_row_iterator<value_type> iterator_y;
00130 typedef generic_pen_row_iterator<const value_type> const_iterator_y;
00131
00132 struct difference_type
00133 {
00134 typedef int value_type;
00135 value_type x,y;
00136 difference_type(value_type x, value_type y):x(x),y(y) { }
00137 value_type &operator[](int i)const { return i?y:x; }
00138 };
00139
00140 protected:
00141 int x_,y_;
00142 int w_,h_;
00143 private:
00144 int pitch_;
00145 value_type value_;
00146 value_type *data_;
00147
00148 typedef generic_pen<T,AT> self_type;
00149
00150 void addptr(int nbytes)
00151 {
00152 data_ = (pointer)((char*)data_ + nbytes);
00153 }
00154
00155 void subptr(int nbytes)
00156 {
00157 data_ = (pointer)((char*)data_ + nbytes);
00158 }
00159
00160 public:
00161
00162 generic_pen(value_type *data, int w, int h, int pitch):
00163 x_(0),
00164 y_(0),
00165 w_(w),
00166 h_(h),
00167 pitch_(pitch),
00168 data_(data)
00169 {
00170 }
00171
00172 generic_pen(value_type *data, int w, int h):
00173 x_(0),
00174 y_(0),
00175 w_(w),
00176 h_(h),
00177 pitch_(sizeof(value_type)*w),
00178 data_(data)
00179 {
00180 }
00181
00182 generic_pen():data_(NULL) { }
00183
00184 self_type& move(int a, int b)
00185 {
00186 assert(data_);
00187 x_ += a, y_ += b;
00188 addptr(b*pitch_ + a*sizeof(value_type));
00189 return *this;
00190 }
00191 self_type& move_to(int x, int y) { assert(data_); return move(x - x_,y - y_);}
00192 void set_value(const value_type &v) { value_=v; }
00193
00194 void inc_x() { assert(data_); x_++; data_++; }
00195 void dec_x() { assert(data_); x_--; data_--; }
00196 void inc_y() { assert(data_); y_++; addptr(pitch_); }
00197 void dec_y() { assert(data_); y_--; subptr(pitch_); }
00198
00199 void inc_x(int n) { assert(data_); x_+=n; data_+=n; }
00200 void dec_x(int n) { assert(data_); x_-=n; data_-=n; }
00201 void inc_y(int n) { assert(data_); y_+=n; data_ = (pointer)((char*)data_ + pitch_*n); }
00202 void dec_y(int n) { assert(data_); y_-=n; data_ = (pointer)((char*)data_ - pitch_*n); }
00203
00204 void put_value(const value_type &v)const { assert(data_); *data_=v; }
00205 void put_value()const { assert(data_); put_value(value_); }
00206
00207 void put_value_clip(const value_type &v)const
00208 { if(!clipped()) put_value(v); }
00209 void put_value_clip()const { put_value_clip(value_); }
00210
00211 const_reference get_value()const { assert(data_); return *data_; }
00212
00213 const_reference get_value_at(int x, int y)const { assert(data_); return ((pointer)(((char*)data_)+y*pitch_))[x]; }
00214
00215 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]; }
00216
00217 value_type get_value_clip()const { assert(data_); if(clipped())return value_type(); return *data_; }
00218
00219 value_type get_pen_value()const { return value_; }
00220
00221 void put_hline(int l,const value_type &v)
00222 {for(;l>0;l--,inc_x())put_value(v);}
00223
00224 void put_hline(int l) {put_hline(l,value_);}
00225
00226 void put_hline_clip(int l, const value_type &v)
00227 {l=std::min(l,w_-x_);for(;l>0;l--,inc_x())put_value_clip(v);}
00228
00229 void put_hline_clip(int l) {put_hline_clip(l,value_);}
00230
00231
00232 void put_block(int h, int w, const value_type &v)
00233 {
00234 self_type row(*this);
00235 for(;h>0;h--,row.inc_y())
00236 {
00237 self_type col(row);
00238 col.put_hline(w,v);
00239 }
00240 }
00241
00242 void put_block(int h, int w) { put_block(h,w,value_); }
00243
00244 void put_block_clip(int h, int w, const value_type &v)
00245 {
00246 self_type row(*this);
00247
00248
00249 if(row.x_ < 0) { w+=row.x_; row.inc_x(-row.x_); }
00250 if(row.y_ < 0) { h+=row.y_; row.inc_y(-row.y_); }
00251
00252
00253 h = std::min(h,h_-y_);
00254 w = std::min(w,w_-x_);
00255
00256
00257 for(;h>0;h--,row.inc_y())
00258 {
00259 self_type col(row);
00260 col.put_hline(w,v);
00261 }
00262 }
00263
00264 void put_block_clip(int h, int w) { put_block(h,w,value_); }
00265
00266
00267 iterator_x operator[](int i)const { assert(data_); return (pointer)(((char*)data_)+i*pitch_); }
00268
00269 iterator_x x() { assert(data_); return data_; }
00270 iterator_x begin_x() { assert(data_); return data_-x_; }
00271 iterator_x end_x() { assert(data_); return data_-x_+w_; }
00272
00273 iterator_y y() { assert(data_); return iterator_y(data_,pitch_); }
00274 iterator_y begin_y() { assert(data_); return iterator_y((pointer)((char*)data_ - y_*pitch_),pitch_); }
00275 iterator_y end_y() { assert(data_); return iterator_y((pointer)((char*)data_ + (h_-y_)*pitch_),pitch_); }
00276
00277 operator bool()const { return (bool)data_; }
00278 bool operator!()const { return !data_; }
00279 bool operator==(const self_type &rhs)const { return data_==rhs.data_; }
00280 bool operator!=(const self_type &rhs)const { return data_!=rhs.data_; }
00281 bool clipped(int x, int y)const { return !(x_+x>=0 && y_+y>=0 && x_+x<w_ && y_+y<h_); }
00282 bool clipped()const { return !(x_>=0 && y_>=0 && x_<w_ && y_<h_); }
00283
00284 difference_type operator-(const self_type &rhs)const
00285 {
00286 assert(data_);
00287 assert(pitch_==rhs.pitch_);
00288 int ptr_diff=(char*)data_-(char*)rhs.data_-1;
00289 return difference_type(ptr_diff%pitch_/sizeof(value_type)+1,ptr_diff/pitch_);
00290 }
00291
00292 self_type operator+(const difference_type &rhs)const
00293 {
00294 assert(data_);
00295 self_type ret(*this);
00296 ret.move(rhs.x,rhs.y);
00297 return ret;
00298 }
00299
00300 difference_type diff_begin()const {return difference_type(-x_,-y_);}
00301 difference_type diff_end()const {return difference_type(w_-x_,h_-y_);}
00302
00303 self_type get_start()const {return *this + diff_begin(); }
00304 self_type get_end()const {return *this + diff_end(); }
00305
00306 int get_width()const {return w_;}
00307 int get_height()const {return h_;}
00308
00309 int get_w()const {return w_;}
00310 int get_h()const {return h_;}
00311 int get_pitch()const {return pitch_;}
00312 };
00313
00314 template <
00315 typename PEN_,
00316 typename A_=float,
00317 class AFFINE_=affine_combo<typename PEN_::value_type,A_>
00318 >
00319 class alpha_pen : public PEN_
00320 {
00321 public:
00322 typedef A_ alpha_type;
00323 typedef AFFINE_ affine_func_type;
00324
00325 typedef typename PEN_::value_type value_type;
00326 typedef alpha_pen self_type;
00327
00328 private:
00329 alpha_type alpha_;
00330
00331 protected:
00332 affine_func_type affine_func_;
00333
00334 public:
00335 using PEN_::get_value;
00336 using PEN_::get_pen_value;
00337 using PEN_::inc_x;
00338 using PEN_::dec_x;
00339 using PEN_::inc_y;
00340 using PEN_::dec_y;
00341 using PEN_::clipped;
00342 using PEN_::w_;
00343 using PEN_::h_;
00344 using PEN_::x_;
00345 using PEN_::y_;
00346
00347 alpha_pen(const alpha_type &a = 1, const affine_func_type &func = affine_func_type()):alpha_(a),affine_func_(func) { }
00348 alpha_pen(const PEN_ &x, const alpha_type &a=1, const affine_func_type &func=affine_func_type())
00349 :PEN_(x),alpha_(a),affine_func_(func) { }
00350
00351 const alpha_type& get_alpha()const { return alpha_; }
00352 void get_alpha(alpha_type &a) const { a=alpha_; }
00353 void set_alpha(alpha_type a) { alpha_=a; }
00354
00355 void put_value(const value_type &v, alpha_type a=1)const
00356 { PEN_::put_value(affine_func_(get_value(),v,alpha_*a)); }
00357 void put_value()const { put_value(get_pen_value()); }
00358 void put_value_alpha(alpha_type a)const { put_value(get_pen_value(),a); }
00359 void put_hline(int l, const alpha_type &a = 1){for(;l>0;l--,inc_x())put_value_alpha(a);}
00360
00361 void put_value_clip(const value_type &v, alpha_type a=1)const
00362 { if(!clipped())PEN_::put_value(affine_func_(get_value(),v,alpha_*a)); }
00363 void put_value_clip()const { put_value_clip(get_pen_value()); }
00364 void put_value_clip_alpha(alpha_type a)const { put_value_clip(get_pen_value(),a); }
00365 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);}
00366
00367
00368 void put_block(int h, int w, const alpha_type &a = 1)
00369 {
00370 self_type row(*this);
00371 for(;h>0;h--,row.inc_y())
00372 {
00373 self_type col(row);
00374 col.put_hline(w,a);
00375 }
00376 }
00377
00378 void put_block_clip(int h, int w, const alpha_type &a = 1)
00379 {
00380 self_type row(*this);
00381
00382
00383 if(row.x_ < 0) { w+=row.x_; row.inc_x(-row.x_); }
00384 if(row.y_ < 0) { h+=row.y_; row.inc_y(-row.y_); }
00385
00386
00387 h = std::min(h,h_-y_);
00388 w = std::min(w,w_-x_);
00389
00390
00391 for(;h>0;h--,row.inc_y())
00392 {
00393 self_type col(row);
00394 col.put_hline(w,a);
00395 }
00396 }
00397 };
00398
00399 _ETL_END_NAMESPACE
00400
00401
00402
00403
00404
00405 #endif