~ubuntu-branches/ubuntu/saucy/gnash/saucy-proposed

« back to all changes in this revision

Viewing changes to backend/Renderer_agg_style.h

  • Committer: Bazaar Package Importer
  • Author(s): Sindhudweep Narayan Sarkar
  • Date: 2009-10-07 00:06:10 UTC
  • mfrom: (1.1.12 upstream)
  • Revision ID: james.westby@ubuntu.com-20091007000610-mj9rwqe774gizn1j
Tags: 0.8.6-0ubuntu1
new upstream release 0.8.6 (LP: #435897)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// 
 
2
//   Copyright (C) 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
 
3
// 
 
4
// This program is free software; you can redistribute it and/or modify
 
5
// it under the terms of the GNU General Public License as published by
 
6
// the Free Software Foundation; either version 3 of the License, or
 
7
// (at your option) any later version.
 
8
// 
 
9
// This program is distributed in the hope that it will be useful,
 
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
12
// GNU General Public License for more details.
 
13
// 
 
14
// You should have received a copy of the GNU General Public License
 
15
// along with this program; if not, write to the Free Software
 
16
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
17
 
 
18
#ifndef BACKEND_RENDER_HANDLER_AGG_STYLE_H
 
19
#define BACKEND_RENDER_HANDLER_AGG_STYLE_H
 
20
 
 
21
// This include file used only to make Renderer_agg more readable.
 
22
 
 
23
 
 
24
// TODO: Instead of re-creating AGG fill styles again and again, they should
 
25
// be cached somewhere.
 
26
 
 
27
 
 
28
// Enable this DEFINE to limit the alpha value of all colors to 50% at most.
 
29
// This works only with solid and gradient fills (not bitmaps) and is used
 
30
// for debugging hidden characters.
 
31
//#define DEBUG_LIMIT_COLOR_ALPHA 
 
32
 
 
33
 
 
34
namespace gnash {
 
35
 
 
36
/// Internal style class that represents a fill style. Roughly speaking, AGG 
 
37
/// computes the fill areas of a flash composite shape and calls generate_span
 
38
/// to generate small horizontal pixel rows. generate_span provides whatever
 
39
/// fill pattern for that coordinate. 
 
40
class agg_style_base 
 
41
{
 
42
public:
 
43
 
 
44
  agg_style_base(bool solid, const agg::rgba8& color = agg::rgba8(0,0,0,0))
 
45
    :
 
46
    _solid(solid),
 
47
    _color(color)
 
48
  {
 
49
  }
 
50
  
 
51
  // Everytime a class has a virtual method it should
 
52
  // also have a virtual destructor. This will ensure
 
53
  // that the destructor for the *derived* class is invoked
 
54
  // when deleting a pointer to base class !!
 
55
  virtual ~agg_style_base() {}
 
56
 
 
57
  bool solid() const { return _solid; }
 
58
 
 
59
  agg::rgba8 color() const { return _color; }
 
60
 
 
61
  // for non-solid styles:
 
62
  virtual void generate_span(agg::rgba8* span, int x, int y, unsigned len) = 0;
 
63
 
 
64
private:
 
65
 
 
66
  // for solid styles:
 
67
  bool _solid;
 
68
 
 
69
  agg::rgba8 _color; 
 
70
  
 
71
};
 
72
 
 
73
 
 
74
/// Solid AGG fill style. generate_span is not used in this case as AGG does
 
75
/// solid fill styles internally.
 
76
class agg_style_solid : public agg_style_base 
 
77
{
 
78
public:
 
79
 
 
80
  agg_style_solid(const agg::rgba8& color)
 
81
    :
 
82
    agg_style_base(true, color)
 
83
  {
 
84
#ifdef DEBUG_LIMIT_COLOR_ALPHA
 
85
    m_color.a = m_color.a>127 ? 127 : m_color.a;
 
86
#endif    
 
87
  }
 
88
 
 
89
  void generate_span(agg::rgba8* /*span*/, int /*x*/, int /*y*/,
 
90
        unsigned /*len*/)
 
91
  {
 
92
    abort(); // never call generate_span for solid fill styles
 
93
  }
 
94
};
 
95
 
 
96
 
 
97
#define image_accessor_clip_transp agg::image_accessor_clone
 
98
 
 
99
 
 
100
/// AGG bitmap fill style. There are quite a few combinations possible and so
 
101
/// the class types are defined outside. The bitmap can be tiled or clipped.
 
102
/// It can have any transformation SWFMatrix and color transform. Any pixel format
 
103
/// can be used, too. 
 
104
template <class PixelFormat, class span_allocator_type, class img_source_type,
 
105
       class interpolator_type, class sg_type>
 
106
class agg_style_bitmap : public agg_style_base
 
107
{
 
108
public:
 
109
    
 
110
  agg_style_bitmap(int width, int height, int rowlen, boost::uint8_t* data, 
 
111
    const gnash::SWFMatrix& mat, const gnash::cxform& cx)
 
112
    :
 
113
    agg_style_base(false),
 
114
    m_cx(cx),
 
115
    m_rbuf(data, width, height, rowlen),  
 
116
    m_pixf(m_rbuf),
 
117
    m_img_src(m_pixf),
 
118
    m_tr(mat.sx / 65535.0, mat.shx / 65535.0, mat.shy / 65535.0,
 
119
            mat.sy / 65535.0, mat.tx, mat.ty),
 
120
    m_interpolator(m_tr),
 
121
    m_sg(m_img_src, m_interpolator)
 
122
  {
 
123
    
 
124
    // Convert the transformation SWFMatrix to AGG's class. It's basically the
 
125
    // same and we could even use gnash::SWFMatrix since AGG does not require
 
126
    // a real AGG descendant (templates!). However, it's better to use AGG's
 
127
    // class as this should be faster (avoid type conversion).
 
128
  }
 
129
  
 
130
  virtual ~agg_style_bitmap() {
 
131
  }
 
132
    
 
133
    void generate_span(agg::rgba8* span, int x, int y, unsigned len)
 
134
    {
 
135
        m_sg.generate(span, x, y, len);
 
136
        // Apply color transform
 
137
        // TODO: Check if this can be optimized
 
138
        if (m_cx.is_identity()) return;
 
139
        for (unsigned int i=0; i<len; i++) {
 
140
            m_cx.transform(span->r, span->g, span->b, span->a);
 
141
            span->premultiply();
 
142
            ++span;
 
143
        }  
 
144
    }
 
145
  
 
146
private:
 
147
 
 
148
  // Color transform
 
149
  gnash::cxform m_cx;
 
150
 
 
151
  // Pixel access
 
152
  agg::rendering_buffer m_rbuf;
 
153
  PixelFormat m_pixf;
 
154
  
 
155
  // Span allocator
 
156
  span_allocator_type m_sa;
 
157
  
 
158
  // Image accessor
 
159
  img_source_type m_img_src;
 
160
  
 
161
  // Transformer
 
162
  agg::trans_affine m_tr;
 
163
  
 
164
  // Interpolator
 
165
  interpolator_type m_interpolator;
 
166
  
 
167
  // Span generator
 
168
  sg_type m_sg;  
 
169
};
 
170
 
 
171
 
 
172
/// AGG gradient fill style. Don't use Gnash texture bitmaps as this is slower
 
173
/// and less accurate. Even worse, the bitmap fill would need to be tweaked
 
174
/// to have non-repeating gradients (first and last color stops continue 
 
175
/// forever on each side). This class can be used for any kind of gradient, so
 
176
/// even focal gradients should be possible. 
 
177
template <class color_type, class span_allocator_type, class interpolator_type, 
 
178
  class gradient_func_type, class gradient_adaptor_type, class color_func_type, 
 
179
  class sg_type>
 
180
class agg_style_gradient : public agg_style_base
 
181
{
 
182
public:
 
183
 
 
184
  agg_style_gradient(const gnash::fill_style& fs,
 
185
        const gnash::SWFMatrix& mat, const gnash::cxform& cx,
 
186
        int norm_size)
 
187
    :
 
188
    agg_style_base(false),
 
189
    m_cx(cx),
 
190
    m_tr(mat.sx / 65536.0, mat.shx/65536.0, mat.shy / 65536.0,
 
191
            mat.sy / 65536.0, mat.tx, mat.ty),
 
192
    m_span_interpolator(m_tr),
 
193
    m_gradient_func(),
 
194
    m_gradient_adaptor(m_gradient_func),
 
195
    m_sg(m_span_interpolator, m_gradient_adaptor, m_gradient_lut, 0, norm_size),
 
196
    m_need_premultiply(false)
 
197
  {
 
198
    // Build gradient lookup table
 
199
    m_gradient_lut.remove_all(); 
 
200
    
 
201
    for (int i = 0, e = fs.get_color_stop_count(); i != e; ++i) {
 
202
    
 
203
      const gradient_record& gr = fs.get_color_stop(i); 
 
204
      rgba trans_color = m_cx.transform(gr.m_color);
 
205
      
 
206
#ifdef DEBUG_LIMIT_COLOR_ALPHA
 
207
      trans_color.m_a = trans_color.m_a>127 ? 127 : trans_color.m_a;
 
208
#endif
 
209
 
 
210
      if (trans_color.m_a < 255) m_need_premultiply = true;    
 
211
      
 
212
      m_gradient_lut.add_color(gr.m_ratio/255.0, agg::rgba8(trans_color.m_r, 
 
213
        trans_color.m_g, trans_color.m_b, trans_color.m_a));
 
214
        
 
215
    } // for
 
216
    
 
217
    m_gradient_lut.build_lut();
 
218
    
 
219
  } // agg_style_gradient constructor
 
220
 
 
221
 
 
222
  virtual ~agg_style_gradient() 
 
223
  {
 
224
  }
 
225
 
 
226
 
 
227
  void generate_span(color_type* span, int x, int y, unsigned len) 
 
228
  {
 
229
    m_sg.generate(span, x, y, len);
 
230
    
 
231
    if (!m_need_premultiply) return;
 
232
      
 
233
    while (len--) {
 
234
        span->premultiply();
 
235
        ++span;
 
236
    }
 
237
  }
 
238
  
 
239
  // Provide access to our gradient adaptor to allow re-initialization of
 
240
  // focal gradients. I wanted to do this using partial template specialization
 
241
  // but it became too complex for something that can be solved in a very easy
 
242
  // (slightly unelegant) way. 
 
243
  gradient_adaptor_type& get_gradient_adaptor() {
 
244
    return m_gradient_adaptor;
 
245
  }
 
246
  
 
247
protected:
 
248
  
 
249
  // Color transform
 
250
  gnash::cxform m_cx;
 
251
  
 
252
  // Span allocator
 
253
  span_allocator_type m_sa;
 
254
  
 
255
  // Transformer
 
256
  agg::trans_affine m_tr;
 
257
  
 
258
  // Span interpolator
 
259
  interpolator_type m_span_interpolator;
 
260
  
 
261
  gradient_func_type m_gradient_func;
 
262
  
 
263
  // Gradient adaptor
 
264
  gradient_adaptor_type m_gradient_adaptor;  
 
265
  
 
266
  // Gradient LUT
 
267
  color_func_type m_gradient_lut;
 
268
  
 
269
  // Span generator
 
270
  sg_type m_sg;  
 
271
 
 
272
  // premultiplication necessary?
 
273
  bool m_need_premultiply;
 
274
  
 
275
}; // agg_style_gradient
 
276
 
 
277
 
 
278
 
 
279
 
 
280
// --- AGG HELPER CLASSES ------------------------------------------------------
 
281
 
 
282
/// Style handler for AGG's compound rasterizer. This is the class which is
 
283
/// called by AGG itself. It provides an interface to the various fill style
 
284
/// classes defined above.
 
285
class agg_style_handler
 
286
{
 
287
public:
 
288
 
 
289
    agg_style_handler() : 
 
290
        m_transparent(0, 0, 0, 0)        
 
291
    {}
 
292
    
 
293
    ~agg_style_handler() {
 
294
      int styles_size = m_styles.size(); 
 
295
      for (int i=0; i<styles_size; i++)
 
296
        delete m_styles[i]; 
 
297
    }
 
298
 
 
299
    /// Called by AGG to ask if a certain style is a solid color
 
300
    bool is_solid(unsigned style) const {
 
301
      assert(style < m_styles.size());
 
302
      return m_styles[style]->solid(); 
 
303
    }
 
304
    
 
305
    /// Adds a new solid fill color style
 
306
    void add_color(const agg::rgba8& color) {
 
307
      agg_style_solid *st = new agg_style_solid(color);
 
308
      m_styles.push_back(st);
 
309
    }
 
310
    
 
311
    /// Adds a new bitmap fill style
 
312
    void add_bitmap(const agg_bitmap_info* bi, const gnash::SWFMatrix& mat,
 
313
        const gnash::cxform& cx, bool repeat, bool smooth)
 
314
    {
 
315
 
 
316
      if (!bi) {
 
317
        // See server/styles.h comments about when NULL return is possible.
 
318
        // Don't warn here, we already warn at parse-time
 
319
        //log_debug("WARNING: add_bitmap called with bi=NULL");
 
320
        add_color(agg::rgba8_pre(0,0,0,0));
 
321
        return;
 
322
      }
 
323
 
 
324
      // Whew! There are 8 bitmap combinations (bpp, smooth, repeat) possible
 
325
      // and AGG uses templates, so... 
 
326
      // I'd need to pass "span_image_filter_rgba_nn" (because span_image_xxx
 
327
      // dependends on the pixel format) without passing the template 
 
328
      // parameters, but AFAIK this can't be done. But hey, this is my first 
 
329
      // C++ code (the whole AGG backend) and I immediately had to start with 
 
330
      // templates. I'm giving up and write eight versions of add_bitmap_xxx. 
 
331
      // So, if anyone has a better solution, for heaven's sake, implement it!! 
 
332
        
 
333
      if (repeat) {
 
334
        if (smooth) {
 
335
        
 
336
          if (bi->get_bpp()==24)
 
337
            add_bitmap_repeat_aa_rgb24 (bi, mat, cx);      
 
338
          else
 
339
          if (bi->get_bpp()==32)
 
340
            add_bitmap_repeat_aa_rgba32 (bi, mat, cx);      
 
341
          else
 
342
            abort();
 
343
            
 
344
        } else {
 
345
        
 
346
          if (bi->get_bpp()==24)
 
347
            add_bitmap_repeat_nn_rgb24 (bi, mat, cx);      
 
348
          else
 
349
          if (bi->get_bpp()==32)
 
350
            add_bitmap_repeat_nn_rgba32 (bi, mat, cx);      
 
351
          else
 
352
            abort();
 
353
            
 
354
        } // if smooth
 
355
      } else {
 
356
        if (smooth) {
 
357
        
 
358
          if (bi->get_bpp()==24)
 
359
            add_bitmap_clip_aa_rgb24 (bi, mat, cx);      
 
360
          else
 
361
          if (bi->get_bpp()==32)
 
362
            add_bitmap_clip_aa_rgba32 (bi, mat, cx);      
 
363
          else
 
364
            abort();
 
365
            
 
366
        } else {
 
367
        
 
368
          if (bi->get_bpp()==24)
 
369
            add_bitmap_clip_nn_rgb24 (bi, mat, cx);      
 
370
          else
 
371
          if (bi->get_bpp()==32)
 
372
            add_bitmap_clip_nn_rgba32 (bi, mat, cx);      
 
373
          else
 
374
            abort();
 
375
            
 
376
        } // if smooth
 
377
      } // if repeat
 
378
      
 
379
    } // add_bitmap 
 
380
 
 
381
 
 
382
    // === RGB24 ===
 
383
    
 
384
 
 
385
    void add_bitmap_repeat_nn_rgb24(const agg_bitmap_info* bi,
 
386
        const gnash::SWFMatrix& mat, const gnash::cxform& cx)
 
387
    {
 
388
 
 
389
      // tiled, nearest neighbor method (faster)   
 
390
 
 
391
      typedef agg::pixfmt_rgb24_pre PixelFormat;
 
392
      typedef agg::span_allocator<PixelFormat> span_allocator_type;
 
393
      typedef agg::wrap_mode_repeat wrap_type;
 
394
      typedef agg::image_accessor_wrap<PixelFormat, wrap_type, wrap_type> img_source_type; 
 
395
      typedef agg::span_interpolator_linear_subdiv<agg::trans_affine> interpolator_type;
 
396
      typedef agg::span_image_filter_rgb_nn<img_source_type, interpolator_type> sg_type;
 
397
       
 
398
      typedef agg_style_bitmap<PixelFormat, span_allocator_type, img_source_type, 
 
399
        interpolator_type, sg_type> st_type;
 
400
      
 
401
      st_type* st = new st_type(bi->get_width(), bi->get_height(),
 
402
          bi->get_rowlen(), bi->get_data(), mat, cx);       
 
403
        
 
404
      m_styles.push_back(st);
 
405
    }
 
406
        
 
407
        
 
408
    
 
409
    
 
410
    void add_bitmap_clip_nn_rgb24(const agg_bitmap_info* bi,
 
411
        const gnash::SWFMatrix& mat, const gnash::cxform& cx)
 
412
    {
 
413
 
 
414
      // clipped, nearest neighbor method (faster)   
 
415
 
 
416
      typedef agg::pixfmt_rgb24_pre PixelFormat;
 
417
      typedef agg::span_allocator<PixelFormat> span_allocator_type;
 
418
      typedef image_accessor_clip_transp<PixelFormat> img_source_type; 
 
419
      typedef agg::span_interpolator_linear_subdiv<agg::trans_affine> interpolator_type;
 
420
      typedef agg::span_image_filter_rgb_nn<img_source_type, interpolator_type> sg_type;
 
421
       
 
422
      typedef agg_style_bitmap<PixelFormat, span_allocator_type, img_source_type, 
 
423
        interpolator_type, sg_type> st_type;
 
424
      
 
425
      st_type* st = new st_type(bi->get_width(), bi->get_height(),
 
426
          bi->get_rowlen(), bi->get_data(), mat, cx);       
 
427
        
 
428
      m_styles.push_back(st);
 
429
    }
 
430
    
 
431
    
 
432
    
 
433
    void add_bitmap_repeat_aa_rgb24(const agg_bitmap_info* bi,
 
434
        const gnash::SWFMatrix& mat, const gnash::cxform& cx)
 
435
    {
 
436
 
 
437
      // tiled, bilinear method (better quality)   
 
438
 
 
439
      typedef agg::pixfmt_rgb24_pre PixelFormat;
 
440
      typedef agg::span_allocator<PixelFormat> span_allocator_type;
 
441
      typedef agg::wrap_mode_repeat wrap_type;
 
442
      typedef agg::image_accessor_wrap<PixelFormat, wrap_type, wrap_type> img_source_type; 
 
443
      typedef agg::span_interpolator_linear_subdiv<agg::trans_affine> interpolator_type;
 
444
      typedef agg::span_image_filter_rgb_bilinear<img_source_type, interpolator_type> sg_type;
 
445
       
 
446
      typedef agg_style_bitmap<PixelFormat, span_allocator_type, img_source_type, 
 
447
        interpolator_type, sg_type> st_type;
 
448
      
 
449
      st_type* st = new st_type(bi->get_width(), bi->get_height(),
 
450
          bi->get_rowlen(), bi->get_data(), mat, cx);       
 
451
        
 
452
      m_styles.push_back(st);
 
453
    }
 
454
        
 
455
    
 
456
    void add_bitmap_clip_aa_rgb24(const agg_bitmap_info* bi,
 
457
        const gnash::SWFMatrix& mat, const gnash::cxform& cx)
 
458
    {
 
459
 
 
460
      // clipped, bilinear method (better quality)   
 
461
 
 
462
      typedef agg::pixfmt_rgb24_pre PixelFormat;
 
463
      typedef agg::span_allocator<PixelFormat> span_allocator_type;
 
464
      typedef image_accessor_clip_transp<PixelFormat> img_source_type; 
 
465
      typedef agg::span_interpolator_linear_subdiv<agg::trans_affine> interpolator_type;
 
466
      typedef agg::span_image_filter_rgb_bilinear<img_source_type, interpolator_type> sg_type;
 
467
       
 
468
      typedef agg_style_bitmap<PixelFormat, span_allocator_type, img_source_type, 
 
469
        interpolator_type, sg_type> st_type;
 
470
      
 
471
      st_type* st = new st_type(bi->get_width(), bi->get_height(),
 
472
          bi->get_rowlen(), bi->get_data(), mat, cx);       
 
473
        
 
474
      m_styles.push_back(st);
 
475
    }
 
476
    
 
477
       
 
478
    
 
479
    // === RGBA32 ===    
 
480
 
 
481
    void add_bitmap_repeat_nn_rgba32(const agg_bitmap_info* bi,
 
482
        const gnash::SWFMatrix& mat, const gnash::cxform& cx)
 
483
    {
 
484
    
 
485
      // tiled, nearest neighbor method (faster)   
 
486
 
 
487
      typedef agg::pixfmt_rgba32_pre PixelFormat;
 
488
      typedef agg::span_allocator<PixelFormat> span_allocator_type;
 
489
      typedef agg::wrap_mode_repeat wrap_type;
 
490
      typedef agg::image_accessor_wrap<PixelFormat, wrap_type, wrap_type> img_source_type; 
 
491
      typedef agg::span_interpolator_linear_subdiv<agg::trans_affine> interpolator_type;
 
492
      typedef agg::span_image_filter_rgba_nn<img_source_type, interpolator_type> sg_type;
 
493
       
 
494
      typedef agg_style_bitmap<PixelFormat, span_allocator_type, img_source_type, 
 
495
        interpolator_type, sg_type> st_type;
 
496
      
 
497
      st_type* st = new st_type(bi->get_width(), bi->get_height(),
 
498
          bi->get_rowlen(), bi->get_data(), mat, cx);
 
499
          
 
500
      m_styles.push_back(st);
 
501
    }
 
502
        
 
503
        
 
504
    
 
505
    
 
506
    void add_bitmap_clip_nn_rgba32(const agg_bitmap_info* bi,
 
507
        const gnash::SWFMatrix& mat, const gnash::cxform& cx)
 
508
    {
 
509
 
 
510
      // clipped, nearest neighbor method (faster)   
 
511
 
 
512
      typedef agg::pixfmt_rgba32_pre PixelFormat;
 
513
      typedef agg::span_allocator<PixelFormat> span_allocator_type;
 
514
      typedef image_accessor_clip_transp<PixelFormat> img_source_type; 
 
515
      typedef agg::span_interpolator_linear_subdiv<agg::trans_affine> interpolator_type;
 
516
      typedef agg::span_image_filter_rgba_nn<img_source_type, interpolator_type> sg_type;
 
517
       
 
518
      typedef agg_style_bitmap<PixelFormat, span_allocator_type, img_source_type, 
 
519
        interpolator_type, sg_type> st_type;
 
520
      
 
521
      st_type* st = new st_type(bi->get_width(), bi->get_height(),
 
522
          bi->get_rowlen(), bi->get_data(), mat, cx);
 
523
          
 
524
      m_styles.push_back(st);
 
525
    }
 
526
    
 
527
    
 
528
    
 
529
    void add_bitmap_repeat_aa_rgba32(const agg_bitmap_info* bi,
 
530
        const gnash::SWFMatrix& mat, const gnash::cxform& cx)
 
531
    {
 
532
 
 
533
      // tiled, bilinear method (better quality)   
 
534
 
 
535
      typedef agg::pixfmt_rgba32_pre PixelFormat;
 
536
      typedef agg::span_allocator<PixelFormat> span_allocator_type;
 
537
      typedef agg::wrap_mode_repeat wrap_type;
 
538
      typedef agg::image_accessor_wrap<PixelFormat, wrap_type, wrap_type> img_source_type; 
 
539
      typedef agg::span_interpolator_linear_subdiv<agg::trans_affine> interpolator_type;
 
540
      typedef agg::span_image_filter_rgba_bilinear<img_source_type, interpolator_type> sg_type;
 
541
       
 
542
      typedef agg_style_bitmap<PixelFormat, span_allocator_type, img_source_type, 
 
543
        interpolator_type, sg_type> st_type;
 
544
      
 
545
      st_type* st = new st_type(bi->get_width(), bi->get_height(),
 
546
          bi->get_rowlen(), bi->get_data(), mat, cx);       
 
547
        
 
548
      m_styles.push_back(st);
 
549
    }
 
550
        
 
551
    
 
552
    void add_bitmap_clip_aa_rgba32(const agg_bitmap_info* bi,
 
553
        const gnash::SWFMatrix& mat, const gnash::cxform& cx)
 
554
    {
 
555
 
 
556
      // clipped, bilinear method (better quality)   
 
557
 
 
558
      typedef agg::pixfmt_rgba32_pre PixelFormat;
 
559
      typedef agg::span_allocator<PixelFormat> span_allocator_type;
 
560
      typedef image_accessor_clip_transp<PixelFormat> img_source_type; 
 
561
      typedef agg::span_interpolator_linear_subdiv<agg::trans_affine> interpolator_type;
 
562
      typedef agg::span_image_filter_rgba_bilinear<img_source_type, interpolator_type> sg_type;
 
563
       
 
564
      typedef agg_style_bitmap<PixelFormat, span_allocator_type, img_source_type, 
 
565
        interpolator_type, sg_type> st_type;
 
566
      
 
567
      st_type* st = new st_type(bi->get_width(), bi->get_height(),
 
568
          bi->get_rowlen(), bi->get_data(), mat, cx);       
 
569
        
 
570
      m_styles.push_back(st);
 
571
    }
 
572
    
 
573
    
 
574
    // === GRADIENT ===
 
575
 
 
576
    void add_gradient_linear(const gnash::fill_style& fs,
 
577
        const gnash::SWFMatrix& mat, const gnash::cxform& cx)
 
578
    {
 
579
    
 
580
      typedef agg::rgba8 color_type;            
 
581
      typedef agg::span_allocator<color_type> span_allocator_type;
 
582
      typedef agg::span_interpolator_linear<agg::trans_affine> interpolator_type;
 
583
      typedef agg::gradient_x gradient_func_type;
 
584
      //typedef agg::gradient_repeat_adaptor<gradient_func_type> gradient_adaptor_type;
 
585
      typedef gradient_func_type gradient_adaptor_type;
 
586
      typedef agg::gradient_lut<agg::color_interpolator<color_type>, 256> color_func_type;
 
587
      typedef agg::span_gradient<color_type,
 
588
                                 interpolator_type,
 
589
                                 gradient_adaptor_type,
 
590
                                 color_func_type> sg_type;
 
591
       
 
592
      typedef agg_style_gradient<color_type, span_allocator_type, 
 
593
        interpolator_type, gradient_func_type, gradient_adaptor_type, 
 
594
        color_func_type, sg_type> st_type;
 
595
      
 
596
      st_type* st = new st_type(fs, mat, cx, 256);
 
597
      
 
598
      // NOTE: The value 256 is based on the bitmap texture used by other
 
599
      // Gnash renderers which is normally 256x1 pixels for linear gradients.       
 
600
        
 
601
      m_styles.push_back(st);
 
602
    }
 
603
    
 
604
 
 
605
    void add_gradient_radial(const gnash::fill_style& fs,
 
606
        const gnash::SWFMatrix& mat, const gnash::cxform& cx)
 
607
    {
 
608
    
 
609
      typedef agg::rgba8 color_type;            
 
610
      typedef agg::span_allocator<color_type> span_allocator_type;
 
611
      typedef agg::span_interpolator_linear<agg::trans_affine> 
 
612
          interpolator_type;
 
613
      typedef agg::gradient_radial gradient_func_type;
 
614
      typedef gradient_func_type gradient_adaptor_type;
 
615
      typedef agg::gradient_lut<agg::color_interpolator<color_type>, 256> 
 
616
          color_func_type;
 
617
      typedef agg::span_gradient<color_type,
 
618
                                 interpolator_type,
 
619
                                 gradient_adaptor_type,
 
620
                                 color_func_type> sg_type;
 
621
       
 
622
      typedef agg_style_gradient<color_type, span_allocator_type, 
 
623
        interpolator_type, gradient_func_type, gradient_adaptor_type, 
 
624
        color_func_type, sg_type> st_type;
 
625
      
 
626
      // move the center of the radial fill to where it should be
 
627
      gnash::SWFMatrix transl;
 
628
      transl.set_translation(-32, -32);
 
629
      transl.concatenate(mat);    
 
630
 
 
631
      // div 2 because we need radius, not diameter      
 
632
      st_type* st = new st_type(fs, transl, cx, 64/2); 
 
633
        
 
634
      // NOTE: The value 64 is based on the bitmap texture used by other
 
635
      // Gnash renderers which is normally 64x64 pixels for radial gradients.       
 
636
        
 
637
      m_styles.push_back(st);
 
638
    }
 
639
 
 
640
    void add_gradient_focal(const gnash::fill_style& fs,
 
641
        const gnash::SWFMatrix& mat, const gnash::cxform& cx)
 
642
    {
 
643
      typedef agg::rgba8 color_type;
 
644
      typedef agg::span_allocator<color_type> span_allocator_type;
 
645
      typedef agg::span_interpolator_linear<agg::trans_affine> interpolator_type;
 
646
      typedef agg::gradient_radial_focus gradient_func_type;
 
647
      typedef gradient_func_type gradient_adaptor_type;
 
648
      typedef agg::gradient_lut<agg::color_interpolator<color_type>, 256> color_func_type;
 
649
      typedef agg::span_gradient<color_type, interpolator_type,
 
650
        gradient_adaptor_type, color_func_type> sg_type;
 
651
    
 
652
      typedef agg_style_gradient<color_type, span_allocator_type,
 
653
        interpolator_type, gradient_func_type, gradient_adaptor_type,
 
654
        color_func_type, sg_type> st_type;
 
655
            
 
656
      // move the center of the focal fill (not its focal point) to where it 
 
657
      // should be.
 
658
      gnash::SWFMatrix transl;      
 
659
      transl.set_translation(-32, -32);
 
660
      transl.concatenate(mat);
 
661
      
 
662
      st_type* st = new st_type(fs, transl, cx, 64/2); 
 
663
      
 
664
      // re-initialize focal gradient settings
 
665
      gradient_adaptor_type& adaptor = st->get_gradient_adaptor();
 
666
      adaptor.init(32.0, fs.get_focal_point()*32.0, 0.0);
 
667
    
 
668
      m_styles.push_back(st);
 
669
    }
 
670
 
 
671
    /// Returns the color of a certain fill style (solid)
 
672
    agg::rgba8 color(unsigned style) const 
 
673
    {
 
674
        if (style < m_styles.size())
 
675
            return m_styles[style]->color();
 
676
 
 
677
        return m_transparent;
 
678
    }
 
679
 
 
680
    /// Called by AGG to generate a scanline span for non-solid fills 
 
681
    void generate_span(agg::rgba8* span, int x, int y,
 
682
        unsigned len, unsigned style)
 
683
    {
 
684
      m_styles[style]->generate_span(span,x,y,len);
 
685
    }
 
686
 
 
687
 
 
688
private:
 
689
    std::vector<agg_style_base*> m_styles;
 
690
    agg::rgba8          m_transparent;
 
691
};  // class agg_style_handler
 
692
 
 
693
 
 
694
 
 
695
class agg_mask_style_handler 
 
696
{
 
697
public:
 
698
 
 
699
  agg_mask_style_handler() :
 
700
    m_color(255,255)
 
701
  {
 
702
  }
 
703
 
 
704
  bool is_solid(unsigned /*style*/) const
 
705
  {
 
706
    return true;
 
707
  }
 
708
  
 
709
  const agg::gray8& color(unsigned /*style*/) const 
 
710
  {
 
711
    return m_color;
 
712
  }
 
713
  
 
714
  void generate_span(agg::gray8* /*span*/, int /*x*/, int /*y*/,
 
715
        int /*len*/, unsigned /*style*/)
 
716
  {
 
717
    abort(); // never call generate_span for solid fill styles
 
718
  }
 
719
 
 
720
private:
 
721
  agg::gray8 m_color;
 
722
  
 
723
};  // class agg_mask_style_handler
 
724
 
 
725
 
 
726
} // namespace gnash
 
727
 
 
728
#endif // BACKEND_RENDER_HANDLER_AGG_STYLE_H