root/tags/rel-5-0-2/mapserver/mapagg.h

Revision 6773, 26.3 kB (checked in by tbonfort, 10 months ago)

comment fest!
fix a bug when tiling a polygon with a pixmap symbol
include the code to render directly to a gdImage while ignoring the alpha channel (still commented out though)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1 /******************************************************************************
2  * $Id$
3  *
4  * Project:  MapServer
5  * Purpose:  AGG template library types.
6  * Author:   John Novak (jnovak@novacell.com)
7  *
8  *
9  ******************************************************************************
10  * Copyright (c) 1996-2007 Regents of the University of Minnesota.
11  *
12  * Permission is hereby granted, free of charge, to any person obtaining a
13  * copy of this software and associated documentation files (the "Software"),
14  * to deal in the Software without restriction, including without limitation
15  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
16  * and/or sell copies of the Software, and to permit persons to whom the
17  * Software is furnished to do so, subject to the following conditions:
18  *
19  * The above copyright notice and this permission notice shall be included in
20  * all copies of this Software or works derived from this Software.
21  *
22  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
23  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
25  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
28  * DEALINGS IN THE SOFTWARE.
29  ******************************************************************************/
30
31 #include "agg_array.h"
32 #include "agg_rendering_buffer.h"
33
34
35 template<class T> class mapserv_row_ptr_cache
36 {
37 public:
38         typedef agg::const_row_info<T> row_data;
39
40         mapserv_row_ptr_cache() :
41             m_buf(0),
42             m_rows(),
43             m_width(0),
44             m_height(0),
45             m_stride(0)
46         {
47         }
48        
49         mapserv_row_ptr_cache( const gdImagePtr pImg ) :
50             m_buf(0),
51             m_rows(),
52             m_width(0),
53             m_height(0),
54             m_stride(0)
55         {
56                 attach( pImg->tpixels, pImg->sx, pImg->sy, pImg->sx * sizeof( T ) );
57         }
58        
59         void attach( T **ppRows, unsigned width, unsigned height, int stride )
60         {
61                 m_width = width;
62                 m_height = height;
63                 m_stride = stride;
64                
65                 if( height > m_rows.size() )
66                         m_rows.resize( height );
67                        
68                 T** rows        = &m_rows[0];
69                 int iRowIndex = 0;
70
71                 while( height--)
72                 {
73                         *rows = ppRows[iRowIndex];
74                         rows++;
75                         iRowIndex++;
76                 }
77         }
78
79         //--------------------------------------------------------------------
80         AGG_INLINE       T* buf()          { return m_buf;    }
81         AGG_INLINE const T* buf()    const { return m_buf;    }
82         AGG_INLINE unsigned width()  const { return m_width;  }
83         AGG_INLINE unsigned height() const { return m_height; }
84         AGG_INLINE int      stride() const { return m_stride; }
85         AGG_INLINE unsigned stride_abs() const
86         {
87             return (m_stride < 0) ? unsigned(-m_stride) : unsigned(m_stride);
88         }
89
90         //--------------------------------------------------------------------
91         AGG_INLINE       T* row_ptr(int, int y, unsigned)
92         {
93             return m_rows[y];
94         }
95         AGG_INLINE       T* row_ptr(int y)       { return m_rows[y]; }
96         AGG_INLINE const T* row_ptr(int y) const { return m_rows[y]; }
97         AGG_INLINE row_data row    (int y) const
98         {
99             return row_data(0, m_width-1, m_rows[y]);
100         }
101
102         //--------------------------------------------------------------------
103         T const* const* rows() const { return &m_rows[0]; }
104
105         //--------------------------------------------------------------------
106         template<class RenBuf>
107         void copy_from(const RenBuf& src)
108         {
109             unsigned h = height();
110             if(src.height() < h) h = src.height();
111        
112             unsigned l = stride_abs();
113             if(src.stride_abs() < l) l = src.stride_abs();
114        
115             l *= sizeof(T);
116
117             unsigned y;
118             unsigned w = width();
119             for (y = 0; y < h; y++)
120             {
121                 memcpy(row_ptr(0, y, w), src.row_ptr(y), l);
122             }
123         }
124
125         //--------------------------------------------------------------------
126         void clear(T value)
127         {
128             unsigned y;
129             unsigned w = width();
130             unsigned stride = stride_abs();
131             for(y = 0; y < height(); y++)
132             {
133                 T* p = row_ptr(0, y, w);
134                 unsigned x;
135                 for(x = 0; x < stride; x++)
136                 {
137                     *p++ = value;
138                 }
139             }
140         }
141
142     private:
143         //--------------------------------------------------------------------
144         T*            m_buf;        // Pointer to rendering buffer
145         agg::pod_array<T*> m_rows;       // Pointers to each row of the buffer
146         unsigned      m_width;      // Width in pixels
147         unsigned      m_height;     // Height in pixels
148         int           m_stride;     // Number of bytes per row. Can be < 0
149 };
150
151
152 #ifdef NOT_USED_YET
153 typedef agg::blender_rgb<agg::rgba8, agg::order_bgra> ms_blender_bgr24; //----blender_bgr24
154 typedef agg::blender_rgb_pre<agg::rgba8, agg::order_bgra> ms_blender_bgr24_pre; //----blender_bgr24
155
156 namespace agg
157 {
158 //==================================================pixfmt_alpha_blend_rgb_gd
159     template<class Blender, class RenBuf> class pixfmt_alpha_blend_rgb_gd
160     {
161     public:
162         typedef RenBuf   rbuf_type;
163         typedef Blender  blender_type;
164         typedef typename rbuf_type::row_data row_data;
165         typedef typename blender_type::color_type color_type;
166         typedef typename blender_type::order_type order_type;
167         typedef typename color_type::value_type value_type;
168         typedef typename color_type::calc_type calc_type;
169         enum base_scale_e
170         {
171             base_shift = color_type::base_shift,
172             base_scale = color_type::base_scale,
173             base_mask  = color_type::base_mask,
174             pix_width  = sizeof(value_type) * 4
175         };
176
177     private:
178         //--------------------------------------------------------------------
179         AGG_INLINE void copy_or_blend_pix(value_type* p,
180                                           const color_type& c,
181                                           unsigned cover)
182         {
183             if (c.a)
184             {
185                 calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8;
186                 if(alpha == base_mask)
187                 {
188                     p[order_type::R] = c.r;
189                     p[order_type::G] = c.g;
190                     p[order_type::B] = c.b;
191                 }
192                 else
193                 {
194                     m_blender.blend_pix(p, c.r, c.g, c.b, alpha, cover);
195                 }
196             }
197         }
198
199         //--------------------------------------------------------------------
200         AGG_INLINE void copy_or_blend_pix(value_type* p,
201                                           const color_type& c)
202         {
203             if (c.a)
204             {
205                 if(c.a == base_mask)
206                 {
207                     p[order_type::R] = c.r;
208                     p[order_type::G] = c.g;
209                     p[order_type::B] = c.b;
210                 }
211                 else
212                 {
213                     m_blender.blend_pix(p, c.r, c.g, c.b, c.a);
214                 }
215             }
216         }
217
218
219     public:
220         //--------------------------------------------------------------------
221         explicit pixfmt_alpha_blend_rgb_gd(rbuf_type& rb) :
222             m_rbuf(&rb)
223         {}
224         void attach(rbuf_type& rb) { m_rbuf = &rb; }
225
226         //--------------------------------------------------------------------
227         template<class PixFmt>
228         bool attach(PixFmt& pixf, int x1, int y1, int x2, int y2)
229         {
230             rect_i r(x1, y1, x2, y2);
231             if(r.clip(rect_i(0, 0, pixf.width()-1, pixf.height()-1)))
232             {
233                 int stride = pixf.stride();
234                 m_rbuf->attach(pixf.pix_ptr(r.x1, stride < 0 ? r.y2 : r.y1),
235                                (r.x2 - r.x1) + 1,
236                                (r.y2 - r.y1) + 1,
237                                stride);
238                 return true;
239             }
240             return false;
241         }
242
243         //--------------------------------------------------------------------
244         Blender& blender() { return m_blender; }
245
246         //--------------------------------------------------------------------
247         AGG_INLINE unsigned width()  const { return m_rbuf->width();  }
248         AGG_INLINE unsigned height() const { return m_rbuf->height(); }
249         AGG_INLINE int      stride() const { return m_rbuf->stride(); }
250
251         //--------------------------------------------------------------------
252         AGG_INLINE       int8u* row_ptr(int y)       { return m_rbuf->row_ptr(y); }
253         AGG_INLINE const int8u* row_ptr(int y) const { return m_rbuf->row_ptr(y); }
254         AGG_INLINE row_data     row(int y)     const { return m_rbuf->row(y); }
255
256         //--------------------------------------------------------------------
257         AGG_INLINE int8u* pix_ptr(int x, int y)
258         {
259             return m_rbuf->row_ptr(y) + x * pix_width;
260         }
261
262         AGG_INLINE const int8u* pix_ptr(int x, int y) const
263         {
264             return m_rbuf->row_ptr(y) + x * pix_width;
265         }
266
267         //--------------------------------------------------------------------
268         AGG_INLINE static void make_pix(int8u* p, const color_type& c)
269         {
270             ((value_type*)p)[order_type::R] = c.r;
271             ((value_type*)p)[order_type::G] = c.g;
272             ((value_type*)p)[order_type::B] = c.b;
273         }
274
275         //--------------------------------------------------------------------
276         AGG_INLINE color_type pixel(int x, int y) const
277         {
278             value_type* p = (value_type*)m_rbuf->row_ptr(y) + x<<2;
279             return color_type(p[order_type::R],
280                               p[order_type::G],
281                               p[order_type::B]);
282         }
283
284         //--------------------------------------------------------------------
285         AGG_INLINE void copy_pixel(int x, int y, const color_type& c)
286         {
287             value_type* p = (value_type*)m_rbuf->row_ptr(x, y, 1) + x<<2;
288             p[order_type::R] = c.r;
289             p[order_type::G] = c.g;
290             p[order_type::B] = c.b;
291         }
292
293         //--------------------------------------------------------------------
294         AGG_INLINE void blend_pixel(int x, int y, const color_type& c, int8u cover)
295         {
296             copy_or_blend_pix((value_type*)m_rbuf->row_ptr(x, y, 1) + x<<2, c, cover);
297         }
298
299
300         //--------------------------------------------------------------------
301         AGG_INLINE void copy_hline(int x, int y,
302                                    unsigned len,
303                                    const color_type& c)
304         {
305             value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x<<2);
306             do
307             {
308                 p[order_type::R] = c.r;
309                 p[order_type::G] = c.g;
310                 p[order_type::B] = c.b;
311                 p += 4;
312             }
313             while(--len);
314         }
315
316
317         //--------------------------------------------------------------------
318         AGG_INLINE void copy_vline(int x, int y,
319                                    unsigned len,
320                                    const color_type& c)
321         {
322             do
323             {
324                 value_type* p = (value_type*)
325                     m_rbuf->row_ptr(x, y++, 1) + x<<2;
326                 p[order_type::R] = c.r;
327                 p[order_type::G] = c.g;
328                 p[order_type::B] = c.b;
329             }
330             while(--len);
331         }
332
333
334         //--------------------------------------------------------------------
335         void blend_hline(int x, int y,
336                          unsigned len,
337                          const color_type& c,
338                          int8u cover)
339         {
340             if (c.a)
341             {
342                 value_type* p = (value_type*)
343                     m_rbuf->row_ptr(x, y, len) + (x<<2);
344
345                 calc_type alpha = (calc_type(c.a) * (calc_type(cover) + 1)) >> 8;
346                 if(alpha == base_mask)
347                 {
348                     do
349                     {
350                         p[order_type::R] = c.r;
351                         p[order_type::G] = c.g;
352                         p[order_type::B] = c.b;
353                         p += 4;
354                     }
355                     while(--len);
356                 }
357                 else
358                 {
359                     do
360                     {
361                         m_blender.blend_pix(p, c.r, c.g, c.b, alpha, cover);
362                         p += 4;
363                     }
364                     while(--len);
365                 }
366             }
367         }
368
369
370         //--------------------------------------------------------------------
371         void blend_vline(int x, int y,
372                          unsigned len,
373                          const color_type& c,
374                          int8u cover)
375         {
376             if (c.a)
377             {
378                 value_type* p;
379                 calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8;
380                 if(alpha == base_mask)
381                 {
382                     do
383                     {
384                         p = (value_type*)
385                             m_rbuf->row_ptr(x, y++, 1) + x<<2;
386
387                         p[order_type::R] = c.r;
388                         p[order_type::G] = c.g;
389                         p[order_type::B] = c.b;
390                     }
391                     while(--len);
392                 }
393                 else
394                 {
395                     do
396                     {
397                         p = (value_type*)
398                             m_rbuf->row_ptr(x, y++, 1) + x<<2;
399
400                         m_blender.blend_pix(p, c.r, c.g, c.b, alpha, cover);
401                     }
402                     while(--len);
403                 }
404             }
405         }
406
407
408         //--------------------------------------------------------------------
409         void blend_solid_hspan(int x, int y,
410                                unsigned len,
411                                const color_type& c,
412                                const int8u* covers)
413         {
414             if (c.a)
415             {
416                 value_type* p = (value_type*)
417                     m_rbuf->row_ptr(x, y, len) + (x<<2);
418
419                 do
420                 {
421                     calc_type alpha = (calc_type(c.a) * (calc_type(*covers) + 1)) >> 8;
422                     if(alpha == base_mask)
423                     {
424                         p[order_type::R] = c.r;
425                         p[order_type::G] = c.g;
426                         p[order_type::B] = c.b;
427                     }
428                     else
429                     {
430                         m_blender.blend_pix(p, c.r, c.g, c.b, alpha, *covers);
431                     }
432                     p += 4;
433                     ++covers;
434                 }
435                 while(--len);
436             }
437         }
438
439
440         //--------------------------------------------------------------------
441         void blend_solid_vspan(int x, int y,
442                                unsigned len,
443                                const color_type& c,
444                                const int8u* covers)
445         {
446             if (c.a)
447             {
448                 do
449                 {
450                     value_type* p = (value_type*)
451                         m_rbuf->row_ptr(x, y++, 1) + (x<<2);
452
453                     calc_type alpha = (calc_type(c.a) * (calc_type(*covers) + 1)) >> 8;
454                     if(alpha == base_mask)
455                     {
456                         p[order_type::R] = c.r;
457                         p[order_type::G] = c.g;
458                         p[order_type::B] = c.b;
459                     }
460                     else
461                     {
462                         m_blender.blend_pix(p, c.r, c.g, c.b, alpha, *covers);
463                     }
464                     ++covers;
465                 }
466                 while(--len);
467             }
468         }
469
470
471         //--------------------------------------------------------------------
472         void copy_color_hspan(int x, int y,
473                               unsigned len,
474                               const color_type* colors)
475         {
476             value_type* p = (value_type*)
477                 m_rbuf->row_ptr(x, y, len) + x<<2;
478
479             do
480             {
481                 p[order_type::R] = colors->r;
482                 p[order_type::G] = colors->g;
483                 p[order_type::B] = colors->b;
484                 ++colors;
485                 p += 4;
486             }
487             while(--len);
488         }
489
490
491         //--------------------------------------------------------------------
492         void copy_color_vspan(int x, int y,
493                               unsigned len,
494                               const color_type* colors)
495         {
496             do
497             {
498                 value_type* p = (value_type*)
499                     m_rbuf->row_ptr(x, y++, 1) + x<<2;
500                 p[order_type::R] = colors->r;
501                 p[order_type::G] = colors->g;
502                 p[order_type::B] = colors->b;
503                 ++colors;
504             }
505             while(--len);
506         }
507
508
509         //--------------------------------------------------------------------
510         void blend_color_hspan(int x, int y,
511                                unsigned len,
512                                const color_type* colors,
513                                const int8u* covers,
514                                int8u cover)
515         {
516             value_type* p = (value_type*)
517                 m_rbuf->row_ptr(x, y, len) + (x<<2);
518
519             if(covers)
520             {
521                 do
522                 {
523                     copy_or_blend_pix(p, *colors++, *covers++);
524                     p += 4;
525                 }
526                 while(--len);
527             }
528             else
529             {
530                 if(cover == 255)
531                 {
532                     do
533                     {
534                         copy_or_blend_pix(p, *colors++);
535                         p += 4;
536                     }
537                     while(--len);
538                 }
539                 else
540                 {
541                     do
542                     {
543                         copy_or_blend_pix(p, *colors++, cover);
544                         p += 4;
545                     }
546                     while(--len);
547                 }
548             }
549         }
550
551
552
553         //--------------------------------------------------------------------
554         void blend_color_vspan(int x, int y,
555                                unsigned len,
556                                const color_type* colors,
557                                const int8u* covers,
558                                int8u cover)
559         {
560             value_type* p;
561             if(covers)
562             {
563                 do
564                 {
565                     p = (value_type*)
566                         m_rbuf->row_ptr(x, y++, 1) + (x<<2);
567
568                     copy_or_blend_pix(p, *colors++, *covers++);
569                 }
570                 while(--len);
571             }
572             else
573             {
574                 if(cover == 255)
575                 {
576                     do
577                     {
578                         p = (value_type*)
579                             m_rbuf->row_ptr(x, y++, 1) + (x<<2);
580
581                         copy_or_blend_pix(p, *colors++);
582                     }
583                     while(--len);
584                 }
585                 else
586                 {
587                     do
588                     {
589                         p = (value_type*)
590                             m_rbuf->row_ptr(x, y++, 1) + (x<<2);
591
592                         copy_or_blend_pix(p, *colors++, cover);
593                     }
594                     while(--len);
595                 }
596             }
597         }
598
599         //--------------------------------------------------------------------
600         template<class Function> void for_each_pixel(Function f)
601         {
602             unsigned y;
603             for(y = 0; y < height(); ++y)
604             {
605                 row_data r = m_rbuf->row(y);
606                 if(r.ptr)
607                 {
608                     unsigned len = r.x2 - r.x1 + 1;
609                     value_type* p = (value_type*)
610                         m_rbuf->row_ptr(r.x1, y, len) + r.x1 * 4;
611                     do
612                     {
613                         f(p);
614                         p += 4;
615                     }
616                     while(--len);
617                 }
618             }
619         }
620
621         //--------------------------------------------------------------------
622         template<class GammaLut> void apply_gamma_dir(const GammaLut& g)
623         {
624             for_each_pixel(apply_gamma_dir_rgb<color_type, order_type, GammaLut>(g));
625         }
626
627         //--------------------------------------------------------------------
628         template<class GammaLut> void apply_gamma_inv(const GammaLut& g)
629         {
630             for_each_pixel(apply_gamma_inv_rgb<color_type, order_type, GammaLut>(g));
631         }
632
633         //--------------------------------------------------------------------
634         template<class RenBuf2>
635         void copy_from(const RenBuf2& from,
636                        int xdst, int ydst,
637                        int xsrc, int ysrc,
638                        unsigned len)
639         {
640             const int8u* p = from.row_ptr(ysrc);
641             if(p)
642             {
643                 memmove(m_rbuf->row_ptr(xdst, ydst, len) + xdst * pix_width,
644                         p + xsrc * pix_width,
645                         len * pix_width);
646             }
647         }
648
649
650         //--------------------------------------------------------------------
651         template<class SrcPixelFormatRenderer>
652         void blend_from(const SrcPixelFormatRenderer& from,
653                         int xdst, int ydst,
654                         int xsrc, int ysrc,
655                         unsigned len,
656                         int8u cover)
657         {
658             typedef typename SrcPixelFormatRenderer::order_type src_order;
659
660             const value_type* psrc = (const value_type*)from.row_ptr(ysrc);
661             if(psrc)
662             {
663                 psrc += xsrc * 4;
664                 value_type* pdst =
665                     (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + xdst * 4;   
666
667                 if(cover == 255)
668                 {
669                     do
670                     {
671                         value_type alpha = psrc[src_order::A];
672                         if(alpha)
673                         {
674                             if(alpha == base_mask)
675                             {
676                                 pdst[order_type::R] = psrc[src_order::R];
677                                 pdst[order_type::G] = psrc[src_order::G];
678                                 pdst[order_type::B] = psrc[src_order::B];
679                             }
680                             else
681                             {
682                                 m_blender.blend_pix(pdst,
683                                                     psrc[src_order::R],
684                                                     psrc[src_order::G],
685                                                     psrc[src_order::B],
686                                                     alpha);
687                             }
688                         }
689                         psrc += 4;
690                         pdst += 4;
691                     }
692                     while(--len);
693                 }
694                 else
695                 {
696                     color_type color;
697                     do
698                     {
699                         color.r = psrc[src_order::R];
700                         color.g = psrc[src_order::G];
701                         color.b = psrc[src_order::B];
702                         color.a = psrc[src_order::A];
703                         copy_or_blend_pix(pdst, color, cover);
704                         psrc += 4;
705                         pdst += 4;
706                     }
707                     while(--len);
708                 }
709             }
710         }
711
712         //--------------------------------------------------------------------
713         template<class SrcPixelFormatRenderer>
714         void blend_from_color(const SrcPixelFormatRenderer& from,
715                               const color_type& color,
716                               int xdst, int ydst,
717                               int xsrc, int ysrc,
718                               unsigned len,
719                               int8u cover)
720         {
721             typedef typename SrcPixelFormatRenderer::value_type src_value_type;
722             const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc);
723             if(psrc)
724             {
725                 value_type* pdst =
726                     (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + xdst * 4;
727                 do
728                 {
729                     copy_or_blend_pix(pdst,
730                                       color,
731                                       (*psrc * cover + base_mask) >> base_shift);
732                     ++psrc;
733                     pdst += 4;
734                 }
735                 while(--len);
736             }
737         }
738
739         //--------------------------------------------------------------------
740         template<class SrcPixelFormatRenderer>
741         void blend_from_lut(const SrcPixelFormatRenderer& from,
742                             const color_type* color_lut,
743                             int xdst, int ydst,
744                             int xsrc, int ysrc,
745                             unsigned len,
746                             int8u cover)
747         {
748             typedef typename SrcPixelFormatRenderer::value_type src_value_type;
749             const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc);
750             if(psrc)
751             {
752                 value_type* pdst =
753                     (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + xdst * 4;
754
755                 if(cover == 255)
756                 {
757                     do
758                     {
759                         const color_type& color = color_lut[*psrc];
760                         m_blender.blend_pix(pdst,
761                                             color.r, color.g, color.b, color.a);
762                         ++psrc;
763                         pdst += 4;
764                     }
765                     while(--len);
766                 }
767                 else
768                 {
769                     do
770                     {
771                         copy_or_blend_pix(pdst, color_lut[*psrc], cover);
772                         ++psrc;
773                         pdst += 4;
774                     }
775                     while(--len);
776                 }
777             }
778         }
779
780     private:
781         rbuf_type* m_rbuf;
782         Blender    m_blender;
783     };
784    
785 }
786 #endif
Note: See TracBrowser for help on using the browser.