~ubuntu-branches/ubuntu/lucid/etl/lucid

« back to all changes in this revision

Viewing changes to ETL/_surface.h

  • Committer: Bazaar Package Importer
  • Author(s): Paul Wise
  • Date: 2005-11-07 13:33:17 UTC
  • Revision ID: james.westby@ubuntu.com-20051107133317-ayuv6ogo0ikjbstm
Tags: upstream-0.04.07
ImportĀ upstreamĀ versionĀ 0.04.07

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*! ========================================================================
 
2
** Extended Template and Library
 
3
** Surface Class Implementation
 
4
** $Id: _surface.h,v 1.1.1.1 2005/01/04 01:31:48 darco Exp $
 
5
**
 
6
** Copyright (c) 2002 Robert B. Quattlebaum Jr.
 
7
**
 
8
** This package is free software; you can redistribute it and/or
 
9
** modify it under the terms of the GNU General Public License as
 
10
** published by the Free Software Foundation; either version 2 of
 
11
** the License, or (at your option) any later version.
 
12
**
 
13
** This package is distributed in the hope that it will be useful,
 
14
** but WITHOUT ANY WARRANTY; without even the implied warranty of
 
15
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
16
** General Public License for more details.
 
17
**
 
18
** === N O T E S ===========================================================
 
19
**
 
20
** This is an internal header file, included by other ETL headers.
 
21
** You should not attempt to use it directly.
 
22
**
 
23
** ========================================================================= */
 
24
 
 
25
/* === S T A R T =========================================================== */
 
26
 
 
27
#ifndef __ETL__SURFACE_H
 
28
#define __ETL__SURFACE_H
 
29
 
 
30
/* === H E A D E R S ======================================================= */
 
31
 
 
32
#include "_pen.h"
 
33
#include "_misc.h"
 
34
//#include <algorithm>
 
35
 
 
36
/* === M A C R O S ========================================================= */
 
37
 
 
38
/* === C L A S S E S & S T R U C T S ======================================= */
 
39
 
 
40
_ETL_BEGIN_NAMESPACE
 
41
 
 
42
template <typename T, typename AT>
 
43
class value_prep
 
44
{
 
45
public:
 
46
        typedef T value_type;
 
47
        typedef AT accumulator_type;
 
48
 
 
49
        accumulator_type cook(const value_type& x)const { return (accumulator_type)x; }
 
50
        value_type uncook(const accumulator_type& x)const { return (value_type)x; }
 
51
};
 
52
 
 
53
template <typename T, typename AT=T, class VP=value_prep<T,AT> >
 
54
class surface
 
55
{
 
56
public:
 
57
        typedef T value_type;
 
58
        typedef AT accumulator_type;
 
59
        typedef value_type* pointer;
 
60
        typedef const value_type* const_pointer;
 
61
        typedef value_type& reference;
 
62
        typedef generic_pen<value_type,accumulator_type> pen;
 
63
        typedef generic_pen<const value_type,accumulator_type> const_pen;
 
64
        typedef VP value_prep_type;
 
65
 
 
66
        typedef alpha_pen<const_pen> const_alpha_pen;
 
67
        typedef alpha_pen<pen> alpha_pen;
 
68
 
 
69
        typedef typename pen::difference_type size_type;
 
70
        typedef typename pen::difference_type difference_type;
 
71
 
 
72
        typedef typename pen::iterator_x iterator_x;
 
73
        typedef typename pen::iterator_y iterator_y;
 
74
        typedef typename pen::const_iterator_x const_iterator_x;
 
75
        typedef typename pen::const_iterator_y const_iterator_y;
 
76
 
 
77
private:
 
78
        value_type *data_;
 
79
        value_type *zero_pos_;
 
80
        typename difference_type::value_type pitch_;
 
81
        int w_, h_;
 
82
        bool deletable_;
 
83
 
 
84
        value_prep_type cooker_;
 
85
        
 
86
        void swap(const surface &x)
 
87
        {
 
88
                std::swap(data_,x.data_);
 
89
                std::swap(zero_pos_,x.zero_pos_);
 
90
                std::swap(pitch_,x.pitch_);
 
91
                std::swap(w_,x.w_);
 
92
                std::swap(h_,x.h_);
 
93
                std::swap(deletable_,x.deletable_);
 
94
        }
 
95
        
 
96
public:
 
97
        surface():
 
98
                data_(0),
 
99
                zero_pos_(data_),
 
100
                pitch_(0),
 
101
                w_(0),h_(0),
 
102
                deletable_(false) { }
 
103
 
 
104
        surface(value_type* data, int w, int h, bool deletable=false):
 
105
                data_(data),
 
106
                zero_pos_(data),
 
107
                pitch_(sizeof(value_type)*w),
 
108
                w_(w),h_(h),
 
109
                deletable_(deletable) { }
 
110
 
 
111
        surface(const typename size_type::value_type &w, const typename size_type::value_type &h):
 
112
                data_(new value_type[w*h]),
 
113
                zero_pos_(data_),
 
114
                pitch_(sizeof(value_type)*w),
 
115
                w_(w),h_(h),
 
116
                deletable_(true) { }
 
117
 
 
118
        surface(const size_type &s):
 
119
                data_(new value_type[s.x*s.y]),
 
120
                zero_pos_(data_),
 
121
                pitch_(sizeof(value_type)*s.x),
 
122
                w_(s.x),h_(s.y),
 
123
                deletable_(true) { }
 
124
        
 
125
        template <typename _pen>
 
126
        surface(const _pen &_begin, const _pen &_end)
 
127
        {
 
128
                typename _pen::difference_type size=_end-_begin;
 
129
 
 
130
                data_=new value_type[size.x*size.y];
 
131
                w_=size.x;
 
132
                h_=size.y;
 
133
                zero_pos_=data_;
 
134
                pitch_=sizeof(value_type)*w_;
 
135
                deletable_=true;
 
136
 
 
137
                int x,y;
 
138
 
 
139
                for(y=0;y<h_;y++)
 
140
                        for(x=0;x<w_;x++)
 
141
                                (*this)[y][x]=_begin.get_value_at(x,y);
 
142
        }
 
143
 
 
144
        surface(const surface &s):
 
145
                data_(s.data_?new value_type[s.w_*s.h_]:0),
 
146
                zero_pos_(data_+(s.zero_pos_-s.data_)),
 
147
                pitch_(s.pitch_),
 
148
                w_(s.w_),
 
149
                h_(s.h_),
 
150
                deletable_(s.data_?true:false)
 
151
        {
 
152
                assert(&s);
 
153
                if(s.data_)
 
154
                {
 
155
                        assert(data_);
 
156
                        memcpy(data_,s.data_,abs(pitch_)*h_);
 
157
                }
 
158
        }
 
159
 
 
160
public:
 
161
        ~surface()
 
162
        {
 
163
                if(deletable_)
 
164
                        delete [] data_;
 
165
        }
 
166
        
 
167
        size_type 
 
168
        size()const
 
169
        { return size_type(w_,h_); }
 
170
 
 
171
        typename size_type::value_type get_pitch()const { return pitch_; }
 
172
        typename size_type::value_type get_w()const { return w_; }
 
173
        typename size_type::value_type get_h()const { return h_; }
 
174
 
 
175
        const surface &mirror(const surface &rhs)
 
176
        {
 
177
                if(deletable_)delete [] data_;
 
178
                        
 
179
                data_=rhs.data_;
 
180
                zero_pos_=rhs.zero_pos_;
 
181
                pitch_=rhs.pitch_;
 
182
                w_=rhs.w_;
 
183
                h_=rhs.h_;
 
184
                deletable_=false;
 
185
                
 
186
                return *this;
 
187
        }
 
188
        
 
189
        const surface &operator=(const surface &rhs)
 
190
        {
 
191
                set_wh(rhs.w_,rhs.h_);
 
192
                zero_pos_=data_+(rhs.zero_pos_-rhs.data_);
 
193
                pitch_=rhs.pitch_;
 
194
                deletable_=true;
 
195
        
 
196
                memcpy(data_,rhs.data_,pitch_*h_);
 
197
 
 
198
                return *this;
 
199
        }
 
200
 
 
201
        void
 
202
        set_wh(typename size_type::value_type w, typename size_type::value_type h)
 
203
        {
 
204
                if(data_)
 
205
                {
 
206
                        if(w==w_ && h==h_ && deletable_)
 
207
                                return;
 
208
                        if(deletable_)
 
209
                                delete [] data_;
 
210
                }
 
211
 
 
212
                w_=w;
 
213
                h_=h;
 
214
                pitch_=sizeof(value_type)*w_;
 
215
                zero_pos_=data_=new value_type[h_*w_];
 
216
                deletable_=true;
 
217
        }
 
218
 
 
219
        void
 
220
        fill(value_type v, int x, int y, int w, int h)
 
221
        {
 
222
                assert(data_);
 
223
                if(w<=0 || h<=0)return;
 
224
                int i;
 
225
                pen PEN(get_pen(x,y));
 
226
                PEN.set_value(v);
 
227
                for(i=0;i<h;i++,PEN.inc_y(),PEN.dec_x(w))
 
228
                        PEN.put_hline(w);
 
229
        }
 
230
 
 
231
        template <class _pen> void 
 
232
        fill(value_type v, _pen& PEN, int w, int h)
 
233
        {
 
234
                assert(data_);
 
235
                if(w<=0 || h<=0)return;
 
236
                int y;
 
237
                PEN.set_value(v);
 
238
                for(y=0;y<h;y++,PEN.inc_y(),PEN.dec_x(w))
 
239
                        PEN.put_hline(w);
 
240
        }
 
241
 
 
242
        void
 
243
        fill(value_type v)
 
244
        {
 
245
                assert(data_);
 
246
                int y;
 
247
                pen pen_=begin();
 
248
                pen_.set_value(v);
 
249
                for(y=0;y<h_;y++,pen_.inc_y(),pen_.dec_x(w_))
 
250
                        pen_.put_hline(w_);
 
251
        }
 
252
 
 
253
        template <class _pen> void blit_to(_pen &pen)
 
254
        { return blit_to(pen,0,0, get_w(),get_h()); }
 
255
        
 
256
        template <class _pen> void
 
257
        blit_to(_pen &DEST_PEN,
 
258
                        int x, int y, int w, int h) //src param
 
259
        {
 
260
                if(x>=w_ || y>=h_)
 
261
                        return;
 
262
 
 
263
                //clip source origin
 
264
                if(x<0)
 
265
                {
 
266
                        w+=x;   //decrease
 
267
                        x=0;            
 
268
                }
 
269
                
 
270
                if(y<0)
 
271
                {
 
272
                        h+=y;   //decrease
 
273
                        y=0;            
 
274
                }
 
275
                                
 
276
                //clip width against dest width
 
277
                w = std::min(w,DEST_PEN.end_x()-DEST_PEN.x());
 
278
                h = std::min(h,DEST_PEN.end_y()-DEST_PEN.y());
 
279
                
 
280
                //clip width against src width
 
281
                w = std::min(w,w_-x);           
 
282
                h = std::min(h,h_-y);   
 
283
 
 
284
                if(w<=0 || h<=0)
 
285
                        return;
 
286
                
 
287
                pen SOURCE_PEN(get_pen(x,y));
 
288
                
 
289
                for(; h>0; h--,DEST_PEN.inc_y(),SOURCE_PEN.inc_y())
 
290
                {
 
291
                        int i;
 
292
                        for(i=0; i<w; i++,DEST_PEN.inc_x(),SOURCE_PEN.inc_x())
 
293
                        {
 
294
                                DEST_PEN.put_value(SOURCE_PEN.get_value());
 
295
                        }
 
296
                        DEST_PEN.dec_x(w);
 
297
                        SOURCE_PEN.dec_x(w);
 
298
                }
 
299
        }
 
300
 
 
301
        void
 
302
        clear()
 
303
        {
 
304
                assert(data_);
 
305
                if(pitch_==(signed int)sizeof(value_type)*w_)
 
306
                        memset(data_,0,h_*pitch_);
 
307
                else
 
308
                        fill(value_type());
 
309
        }
 
310
 
 
311
        iterator_x
 
312
        operator[](const int &y)
 
313
        { assert(data_); return (pointer)(((char*)zero_pos_)+y*pitch_); }
 
314
 
 
315
        const_iterator_x
 
316
        operator[](const int &y)const
 
317
        { assert(data_); return (const_pointer)(((const char*)zero_pos_)+y*pitch_); }
 
318
 
 
319
        void
 
320
        flip_v()
 
321
        {
 
322
                assert(data_);
 
323
 
 
324
                zero_pos_=(pointer)(((char*)zero_pos_)+pitch_*h_);
 
325
 
 
326
                pitch_=-pitch_;
 
327
        }
 
328
 
 
329
        bool is_valid()const
 
330
        {
 
331
                return  data_!=0
 
332
                        &&      zero_pos_!=0
 
333
                        &&      w_>0
 
334
                        &&      h_>0
 
335
                        &&      pitch_!=0
 
336
                ;
 
337
        }
 
338
        
 
339
        operator bool()const { return is_valid(); }
 
340
        
 
341
        pen begin() { assert(data_); return pen(data_,w_,h_,pitch_); }
 
342
        pen get_pen(int x, int y) { assert(data_); return begin().move(x,y); }
 
343
        pen end() { assert(data_); return get_pen(w_,h_); }
 
344
 
 
345
        const_pen begin()const { assert(data_); return const_pen(data_,w_,h_,pitch_); }
 
346
        const_pen get_pen(int x, int y)const { assert(data_); return begin().move(x,y); }
 
347
        const_pen end()const { assert(data_); return get_pen(w_,h_); }
 
348
        
 
349
        //! Linear sample
 
350
        value_type linear_sample(const float x, const float y)const
 
351
        {
 
352
                int u(floor_to_int(x)), v(floor_to_int(y));
 
353
                float a, b;
 
354
                static const float epsilon(1.0e-6);
 
355
                
 
356
                if(x<0.0f)u=0,a=0.0f;
 
357
                else if(x>w_-1)u=w_-1,a=0.0f;
 
358
                else a=x-u;
 
359
                
 
360
                if(y<0.0f)v=0,b=0.0f;
 
361
                else if(y>h_-1)v=h_-1,b=0.0f;
 
362
                else b=y-v;
 
363
                        
 
364
                const float
 
365
                        c(1.0f-a), d(1.0f-b),
 
366
                        e(a*d),f(c*b),g(a*b);
 
367
 
 
368
                accumulator_type ret(cooker_.cook((*this)[v][u])*(c*d));
 
369
                if(e>=epsilon)ret+=cooker_.cook((*this)[v][u+1])*e;
 
370
                if(f>=epsilon)ret+=cooker_.cook((*this)[v+1][u])*f;
 
371
                if(g>=epsilon)ret+=cooker_.cook((*this)[v+1][u+1])*g;
 
372
                return cooker_.uncook(ret);
 
373
        }
 
374
 
 
375
        //! Cosine sample
 
376
        value_type cosine_sample(const float x, const float y)const
 
377
        {
 
378
                int u(floor_to_int(x)), v(floor_to_int(y));
 
379
                float a, b;
 
380
                static const float epsilon(1.0e-6);
 
381
                
 
382
                if(x<0.0f)u=0,a=0.0f;
 
383
                else if(x>w_-1)u=w_-1,a=0.0f;
 
384
                else a=x-u;
 
385
                
 
386
                if(y<0.0f)v=0,b=0.0f;
 
387
                else if(y>h_-1)v=h_-1,b=0.0f;
 
388
                else b=y-v;
 
389
 
 
390
                a=(1.0f-cos(a*3.1415927f))*0.5f;
 
391
                b=(1.0f-cos(b*3.1415927f))*0.5f;
 
392
                        
 
393
                const float
 
394
                        c(1.0f-a), d(1.0f-b),
 
395
                        e(a*d),f(c*b),g(a*b);
 
396
                
 
397
                accumulator_type ret(cooker_.cook((*this)[v][u])*(c*d));
 
398
                if(e>=epsilon)ret+=cooker_.cook((*this)[v][u+1])*e;
 
399
                if(f>=epsilon)ret+=cooker_.cook((*this)[v+1][u])*f;
 
400
                if(g>=epsilon)ret+=cooker_.cook((*this)[v+1][u+1])*g;
 
401
 
 
402
                return cooker_.uncook(ret);
 
403
        }
 
404
 
 
405
        //! Cubic sample                
 
406
        value_type cubic_sample(float x, float y)const
 
407
        {
 
408
                #if 0
 
409
        #define P(x)    (((x)>=0)?((x)*(x)*(x)):0.0f)
 
410
        #define R(x)    ( P(x+2) - 4.0f*P(x+1) + 6.0f*P(x) - 4.0f*P(x-1) )*(1.0f/6.0f)
 
411
        #define F(i,j)  (cooker_.cook((*this)[max(min(j+v,h_-1),0)][max(min(i+u,w_-1),0)])*(R((i)-a)*R(b-(j))))
 
412
        #define Z(i,j) ret+=F(i,j)
 
413
        #define X(i,j)  // placeholder... To make box more symetric
 
414
                
 
415
                int u(floor_to_int(x)), v(floor_to_int(y));
 
416
                float a, b;
 
417
                
 
418
                // Clamp X
 
419
                if(x<0.0f)u=0,a=0.0f;
 
420
                else if(u>w_-1)u=w_-1,a=0.0f;
 
421
                else a=x-u;
 
422
                
 
423
                // Clamp Y
 
424
                if(y<0.0f)v=0,b=0.0f;
 
425
                else if(v>h_-1)v=h_-1,b=0.0f;
 
426
                else b=y-v;
 
427
 
 
428
                // Interpolate
 
429
                accumulator_type ret(F(0,0));
 
430
                Z(-1,-1); Z(-1, 0); Z(-1, 1); Z(-1, 2);
 
431
                Z( 0,-1); X( 0, 0); Z( 0, 1); Z( 0, 2);
 
432
                Z( 1,-1); Z( 1, 0); Z( 1, 1); Z( 1, 2);
 
433
                Z( 2,-1); Z( 2, 0); Z( 2, 1); Z( 2, 2);
 
434
 
 
435
                return cooker_.uncook(ret);
 
436
        
 
437
        #undef X
 
438
        #undef Z
 
439
        #undef F
 
440
        #undef P
 
441
        #undef R
 
442
                #else
 
443
                
 
444
                #define f(j,i)  (cooker_.cook((*this)[j][i]))
 
445
                //Using catmull rom interpolation because it doesn't blur at all
 
446
                //bezier curve with intermediate ctrl pts: 0.5/3(p(i+1) - p(i-1)) and similar
 
447
                accumulator_type xfa [4];
 
448
                
 
449
                //precalculate indices (all clamped) and offset
 
450
                const int xi = x > 0 ? (x < w_ ? (int)floor(x) : w_-1) : 0;
 
451
                const int xa[] = {std::max(0,xi-1),xi,std::min(w_-1,xi+1),std::min(w_-1,xi+2)};
 
452
                
 
453
                const int yi = y > 0 ? (y < h_ ? (int)floor(y) : h_-1) : 0;
 
454
                const int ya[] = {std::max(0,yi-1),yi,std::min(h_-1,yi+1),std::min(h_-1,yi+2)};
 
455
                
 
456
                const float xf = x-xi;
 
457
                const float yf = y-yi;
 
458
                
 
459
                //figure polynomials for each point
 
460
                const float txf[] = 
 
461
                {
 
462
                        0.5*xf*(xf*(xf*(-1) + 2) - 1),  //-t + 2t^2 -t^3
 
463
                        0.5*(xf*(xf*(3*xf - 5)) + 2),   //2 - 5t^2 + 3t^3
 
464
                        0.5*xf*(xf*(-3*xf + 4) + 1),    //t + 4t^2 - 3t^3
 
465
                        0.5*xf*xf*(xf-1)                                //-t^2 + t^3
 
466
                };
 
467
                
 
468
                const float tyf[] = 
 
469
                {
 
470
                        0.5*yf*(yf*(yf*(-1) + 2) - 1),  //-t + 2t^2 -t^3
 
471
                        0.5*(yf*(yf*(3*yf - 5)) + 2),   //2 - 5t^2 + 3t^3
 
472
                        0.5*yf*(yf*(-3*yf + 4) + 1),    //t + 4t^2 - 3t^3
 
473
                        0.5*yf*yf*(yf-1)                                //-t^2 + t^3
 
474
                };
 
475
                
 
476
                //evaluate polynomial for each row              
 
477
                for(int i = 0; i < 4; ++i)
 
478
                {
 
479
                        xfa[i] = f(ya[i],xa[0])*txf[0] + f(ya[i],xa[1])*txf[1] + f(ya[i],xa[2])*txf[2] + f(ya[i],xa[3])*txf[3];
 
480
                }
 
481
                
 
482
                //return the cumulative column evaluation
 
483
                return cooker_.uncook(xfa[0]*tyf[0] + xfa[1]*tyf[1] + xfa[2]*tyf[2] + xfa[3]*tyf[3]);
 
484
#undef f
 
485
#endif
 
486
        }
 
487
 
 
488
        value_type      sample_rect(float x0,float y0,float x1,float y1) const
 
489
        {
 
490
                const surface &s = *this;
 
491
                
 
492
                //assumes it's clamped to the boundary of the image
 
493
                //force min max relationship for x0,x1 and y0,y1
 
494
                if(x0 > x1) std::swap(x0,x1);
 
495
                if(y0 > y1) std::swap(y0,y1);
 
496
                
 
497
                //local variable madness
 
498
                //all things that want to interoperate should provide a default value constructor for = 0
 
499
                accumulator_type acum = 0;
 
500
                int xi=0,yi=0;
 
501
                
 
502
                int     xib=(int)floor(x0),
 
503
                        xie=(int)floor(x1);
 
504
                
 
505
                int     yib=(int)floor(y0),
 
506
                        yie=(int)floor(y1);
 
507
                
 
508
                //the weight for the pixel should remain the same...
 
509
                float weight = (y1-y0)*(x1-x0);
 
510
                assert(weight != 0);
 
511
                
 
512
                float ylast = y0, xlastb = x0;          
 
513
                const_pen       pen_ = s.get_pen(xib,yib);
 
514
                
 
515
                for(yi = yib; yi < yie; ylast = ++yi, pen_.inc_y())
 
516
                {
 
517
                        const float yweight = yi+1 - ylast;
 
518
                        
 
519
                        float xlast = xlastb;           
 
520
                        for(xi = xib; xi < xie; xlast = ++xi, pen_.inc_x())
 
521
                        {
 
522
                                const float w = yweight*(xi+1 - xlast);                         
 
523
                                acum += cooker_.cook(pen_.get_value())*w;
 
524
                        }
 
525
                        
 
526
                        //post... with next being fractional...
 
527
                        const float w = yweight*(x1 - xlast);
 
528
                        acum += cooker_.cook(pen_.get_value())*w;
 
529
                        
 
530
                        pen_.dec_x(xie-xib);
 
531
                }
 
532
                
 
533
                //post in y direction... must have all x...
 
534
                {
 
535
                        const float yweight = y1 - ylast;
 
536
                        
 
537
                        float xlast = xlastb;
 
538
                        for(xi = xib; xi < xie; xlast = ++xi)
 
539
                        {
 
540
                                const float w = yweight*(xi+1 - xlast);
 
541
                        
 
542
                                acum += cooker_.cook(pen_.get_value())*w;
 
543
                        }
 
544
                        
 
545
                        //post... with next being fractional...
 
546
                        const float w = yweight*(x1 - xlast);
 
547
                        acum += cooker_.cook(pen_.get_value())*w;
 
548
                }
 
549
                
 
550
                acum *= 1/weight;
 
551
                return cooker_.uncook(acum);
 
552
        }
 
553
        
 
554
        value_type      sample_rect_clip(float x0,float y0,float x1,float y1) const
 
555
        {
 
556
                const surface &s = *this;
 
557
                
 
558
                //assumes it's clamped to the boundary of the image
 
559
                //force min max relationship for x0,x1 and y0,y1
 
560
                if(x0 > x1) std::swap(x0,x1);
 
561
                if(y0 > y1) std::swap(y0,y1);
 
562
                
 
563
                //local variable madness
 
564
                //all things that want to interoperate should provide a default value constructor for = 0
 
565
                accumulator_type acum = 0;
 
566
                int xi=0,yi=0;
 
567
                
 
568
                int     xib=(int)floor(x0),
 
569
                        xie=(int)floor(x1);
 
570
                
 
571
                int     yib=(int)floor(y0),
 
572
                        yie=(int)floor(y1);
 
573
                
 
574
                //the weight for the pixel should remain the same...
 
575
                float weight = (y1-y0)*(x1-x0);
 
576
                
 
577
                assert(weight != 0);
 
578
                
 
579
                //clip to the input region
 
580
                if(x0 >= s.get_w() || x1 <= 0) return acum;
 
581
                if(y0 >= s.get_h() || y1 <= 0) return acum;
 
582
                
 
583
                if(x0 < 0) { x0 = 0; xib = 0; }
 
584
                if(x1 >= s.get_w())
 
585
                {
 
586
                        x1 = s.get_w(); //want to be just below the last pixel...
 
587
                        xie = s.get_w()-1;
 
588
                }
 
589
                        
 
590
                if(y0 < 0) { y0 = 0; yib = 0; }
 
591
                if(y1 >= s.get_h()) 
 
592
                {
 
593
                        y1 = s.get_h(); //want to be just below the last pixel...
 
594
                        yie = s.get_h()-1;
 
595
                }
 
596
                
 
597
                float ylast = y0, xlastb = x0;          
 
598
                const_pen       pen = s.get_pen(xib,yib);
 
599
                
 
600
                for(yi = yib; yi < yie; ylast = ++yi, pen.inc_y())
 
601
                {
 
602
                        const float yweight = yi+1 - ylast;
 
603
                        
 
604
                        float xlast = xlastb;           
 
605
                        for(xi = xib; xi < xie; xlast = ++xi, pen.inc_x())
 
606
                        {
 
607
                                const float w = yweight*(xi+1 - xlast);                         
 
608
                                acum += cooker_.cook(pen.get_value())*w;
 
609
                        }
 
610
                        
 
611
                        //post... with next being fractional...
 
612
                        const float w = yweight*(x1 - xlast);
 
613
                        acum += cooker_.cook(pen.get_value())*w;
 
614
                        
 
615
                        pen.dec_x(xie-xib);
 
616
                }
 
617
                
 
618
                //post in y direction... must have all x...
 
619
                {
 
620
                        const float yweight = y1 - ylast;
 
621
                        
 
622
                        float xlast = xlastb;
 
623
                        for(xi = xib; xi < xie; xlast = ++xi)
 
624
                        {
 
625
                                const float w = yweight*(xi+1 - xlast);
 
626
                        
 
627
                                acum += cooker_.cook(pen.get_value())*w;
 
628
                        }
 
629
                        
 
630
                        //post... with next being fractional...
 
631
                        const float w = yweight*(x1 - xlast);
 
632
                        acum += cooker_.cook(pen.get_value())*w;
 
633
                }
 
634
                
 
635
                acum *= 1/weight;
 
636
                return cooker_.uncook(acum);
 
637
        }
 
638
};
 
639
 
 
640
_ETL_END_NAMESPACE
 
641
 
 
642
/* === T Y P E D E F S ===================================================== */
 
643
 
 
644
 
 
645
/* === E N D =============================================================== */
 
646
 
 
647
#endif