- Main Page
- Related Pages
- Classes
- Files

# _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     const value_type get_value_clip()const { assert(data_); if(clipped())return value_type(); return *data_; }
    00218
    00219     const 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