_pen.h

Go to the documentation of this file.
00001 
00025 /* === S T A R T =========================================================== */
00026 
00027 #ifndef __ETL_PEN_H
00028 #define __ETL_PEN_H
00029 
00030 /* === H E A D E R S ======================================================= */
00031 
00032 #include "_curve_func.h"
00033 #include <cassert>
00034 #include <iterator>
00035 #include <algorithm>
00036 
00037 /* === M A C R O S ========================================================= */
00038 
00039 /* === T Y P E D E F S ===================================================== */
00040 
00041 /* === C L A S S E S & S T R U C T S ======================================= */
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     //the put_block functions do not modify the pen
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         //clip start position
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         //clip width and height of copy rect
00253         h = std::min(h,h_-y_);
00254         w = std::min(w,w_-x_);
00255 
00256         //copy rect
00257         for(;h>0;h--,row.inc_y())
00258         {
00259             self_type col(row);
00260             col.put_hline(w,v); //already clipped
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     //the put_block functions do not modify the pen
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         //clip start position
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         //clip width and height of copy rect
00387         h = std::min(h,h_-y_);
00388         w = std::min(w,w_-x_);
00389 
00390         //copy rect
00391         for(;h>0;h--,row.inc_y())
00392         {
00393             self_type col(row);
00394             col.put_hline(w,a); //already clipped
00395         }
00396     }
00397 };
00398 
00399 _ETL_END_NAMESPACE
00400 
00401 /* === E X T E R N S ======================================================= */
00402 
00403 /* === E N D =============================================================== */
00404 
00405 #endif

Generated on Sat Oct 27 22:32:47 2007 for ETL by  doxygen 1.5.3-20071008