• Main Page
  • Related Pages
  • Namespaces
  • Classes
  • Files
  • Examples
  • File List
  • File Members

Renderer_agg_style.h

Go to the documentation of this file.
00001 // 
00002 //   Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 Free Software
00003 //   Foundation, Inc
00004 // 
00005 // This program is free software; you can redistribute it and/or modify
00006 // it under the terms of the GNU General Public License as published by
00007 // the Free Software Foundation; either version 3 of the License, or
00008 // (at your option) any later version.
00009 // 
00010 // This program is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 // GNU General Public License for more details.
00014 // 
00015 // You should have received a copy of the GNU General Public License
00016 // along with this program; if not, write to the Free Software
00017 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00018 
00019 #ifndef BACKEND_RENDER_HANDLER_AGG_STYLE_H
00020 #define BACKEND_RENDER_HANDLER_AGG_STYLE_H
00021 
00022 // This include file used only to make Renderer_agg more readable.
00023 
00024 
00025 // TODO: Instead of re-creating AGG fill styles again and again, they should
00026 // be cached somewhere.
00027 
00028 
00029 // Enable this DEFINE to limit the alpha value of all colors to 50% at most.
00030 // This works only with solid and gradient fills (not bitmaps) and is used
00031 // for debugging hidden characters.
00032 //#define DEBUG_LIMIT_COLOR_ALPHA 
00033 
00034 #include "GnashAlgorithm.h"
00035 #include "FillStyle.h"
00036 
00037 namespace gnash {
00038 
00039 class StyleHandler;
00040 
00041 // Forward declarations.
00042 namespace {
00043 
00045     template<typename FillMode, typename Pixel>
00046             void storeBitmap(StyleHandler& st, const agg_bitmap_info* bi,
00047             const SWFMatrix& mat, const SWFCxForm& cx,
00048             bool smooth);
00049     template<typename FillMode> void storeBitmap(StyleHandler& st,
00050             const agg_bitmap_info* bi, const SWFMatrix& mat, const SWFCxForm& cx,
00051             bool smooth);
00052 
00054     void storeGradient(StyleHandler& st, const GradientFill& fs,
00055             const SWFMatrix& mat, const SWFCxForm& cx);
00056     template<typename Spread> void storeGradient(StyleHandler& st,
00057             const GradientFill& fs, const SWFMatrix& mat, const SWFCxForm& cx);
00058     template<typename Spread, typename Interpolation>
00059             void storeGradient(StyleHandler& st, const GradientFill& fs,
00060             const SWFMatrix& mat, const SWFCxForm& cx);
00061 }
00062 
00067 class AggStyle 
00068 {
00069 public:
00070     AggStyle(bool solid, const agg::rgba8& color = agg::rgba8(0,0,0,0))
00071       :
00072       _solid(solid),
00073       _color(color)
00074     {
00075     }
00076     
00077     // Everytime a class has a virtual method it should
00078     // also have a virtual destructor. This will ensure
00079     // that the destructor for the *derived* class is invoked
00080     // when deleting a pointer to base class !!
00081     virtual ~AggStyle() {}
00082     bool solid() const { return _solid; }
00083     agg::rgba8 color() const { return _color; }
00084   
00085     // for non-solid styles:
00086     virtual void generate_span(agg::rgba8* span, int x, int y,
00087             unsigned len) = 0;
00088   
00089 private:
00090     // for solid styles:
00091     const bool _solid;
00092     const agg::rgba8 _color; 
00093 };
00094 
00095 namespace {
00096 
00098 struct Tile
00099 {
00100     template<typename P> struct Type {
00101         typedef agg::wrap_mode_repeat Wrap;
00102         typedef agg::image_accessor_wrap<P, Wrap, Wrap> type; 
00103     };
00104 };
00105 
00107 struct Clip
00108 {
00109     template<typename P> struct Type {
00110         typedef agg::image_accessor_clone<P> type; 
00111     };
00112 };
00113 
00115 template<typename P, typename W>
00116 struct FilterType
00117 {
00118     typedef typename P::PixelFormat PixelFormat;
00119     typedef typename W::template Type<PixelFormat>::type SourceType;
00120     typedef agg::span_allocator<PixelFormat> Allocator;
00121     typedef agg::span_interpolator_linear<agg::trans_affine>
00122         Interpolator;
00123 };
00124 
00126 struct RGBA 
00127 {
00128     typedef agg::pixfmt_rgba32_pre PixelFormat;
00129 
00130     template<typename SourceType, typename Interpolator>
00131     struct Simple {
00132         typedef agg::span_image_filter_rgba_nn<SourceType, Interpolator> type;
00133     };
00134 
00135     template<typename SourceType, typename Interpolator>
00136     struct AntiAlias {
00137         typedef agg::span_image_filter_rgba_bilinear<SourceType, Interpolator>
00138             type;
00139     };
00140 };
00141 
00143 struct RGB 
00144 {
00145     typedef agg::pixfmt_rgb24_pre PixelFormat;
00146 
00147     template<typename SourceType, typename Interpolator>
00148     struct Simple {
00149         typedef agg::span_image_filter_rgb_nn<SourceType, Interpolator> type;
00150     };
00151 
00152     template<typename SourceType, typename Interpolator>
00153     struct AntiAlias {
00154         typedef agg::span_image_filter_rgb_bilinear<SourceType, Interpolator>
00155             type;
00156     };
00157 };
00158 
00160 template<typename P, typename W>
00161 struct NN : public FilterType<P, W>
00162 {
00163     typedef FilterType<P, W> BaseType;
00164     typedef typename P::template Simple<
00165                 typename BaseType::SourceType,
00166                 typename BaseType::Interpolator>::type Generator;
00167 };
00168 
00170 template<typename P, typename W>
00171 struct AA : public FilterType<P, W>
00172 {
00173     typedef FilterType<P, W> BaseType;
00174     typedef typename P::template AntiAlias<
00175                 typename BaseType::SourceType,
00176                 typename BaseType::Interpolator>::type Generator;
00177 };
00178 
00180 struct Reflect
00181 {
00182     template<typename T> struct Type {
00183         typedef agg::gradient_reflect_adaptor<T> type;
00184     };
00185 };
00186 
00188 struct Repeat
00189 {
00190     template<typename T> struct Type {
00191         typedef agg::gradient_repeat_adaptor<T> type;
00192     };
00193 };
00194 
00196 struct Pad
00197 {
00198     template<typename T> struct Type {
00199         typedef T type;
00200     };
00201 };
00202 
00204 struct InterpolatorRGB
00205 {
00206     template<typename Pixel> struct Type {
00207         typedef agg::gradient_lut<agg::color_interpolator<Pixel>, 256> type;
00208     };
00209 };
00210 
00216 template <class Color, class Allocator, class Interpolator, class GradientType,
00217          class Adaptor, class ColorInterpolator, class SpanGenerator>
00218 class GradientStyle : public AggStyle
00219 {
00220 public:
00221   
00222     GradientStyle(const GradientFill& fs, const SWFMatrix& mat,
00223             const SWFCxForm& cx, int norm_size, GradientType gr = GradientType())
00224         :
00225         AggStyle(false),
00226         m_cx(cx),
00227         m_tr(mat.sx / 65536.0, mat.shx/65536.0, mat.shy / 65536.0,
00228               mat.sy / 65536.0, mat.tx, mat.ty),
00229         m_span_interpolator(m_tr),
00230         m_gradient_adaptor(gr),
00231         m_sg(m_span_interpolator, m_gradient_adaptor, m_gradient_lut, 0,
00232                 norm_size),
00233       
00234         m_need_premultiply(false)
00235     {
00236         // Build gradient lookup table
00237         m_gradient_lut.remove_all(); 
00238         const size_t size = fs.recordCount();
00239       
00240         // It is essential that at least two colours are added; otherwise agg
00241         // will use uninitialized values.
00242         assert(size > 1);
00243     
00244         for (size_t i = 0; i != size; ++i) { 
00245             const GradientRecord& gr = fs.record(i); 
00246             const rgba tr = m_cx.transform(gr.color);
00247             if (tr.m_a < 255) m_need_premultiply = true;    
00248             m_gradient_lut.add_color(gr.ratio/255.0,
00249                     agg::rgba8(tr.m_r, tr.m_g, tr.m_b, tr.m_a));
00250         } 
00251         m_gradient_lut.build_lut();
00252         
00253     } // GradientStyle constructor
00254   
00255     virtual ~GradientStyle() { }
00256   
00257     void generate_span(Color* span, int x, int y, unsigned len) {
00258         m_sg.generate(span, x, y, len);
00259         if (!m_need_premultiply) return;
00260         
00261         while (len--) {
00262             span->premultiply();
00263             ++span;
00264         }
00265     }
00266     
00267 protected:
00268     
00269     // Color transform
00270     SWFCxForm m_cx;
00271     
00272     // Span allocator
00273     Allocator m_sa;
00274     
00275     // Transformer
00276     agg::trans_affine m_tr;
00277     
00278     // Span interpolator
00279     Interpolator m_span_interpolator;
00280     
00281     // Gradient adaptor
00282     Adaptor m_gradient_adaptor;  
00283     
00284     // Gradient LUT
00285     ColorInterpolator m_gradient_lut;
00286     
00287     // Span generator
00288     SpanGenerator m_sg;  
00289   
00290     // premultiplication necessary?
00291     bool m_need_premultiply;
00292 }; 
00293 
00295 //
00299 template<typename G, typename A, typename I>
00300 struct Gradient
00301 {
00302     typedef agg::rgba8 Color;            
00303     typedef G GradientType;
00304     typedef typename A::template Type<G>::type Adaptor;
00305     typedef typename I::template Type<Color>::type ColorInterpolator;
00306     typedef agg::span_allocator<Color> Allocator;
00307     typedef agg::span_interpolator_linear<agg::trans_affine> Interpolator;
00308     typedef agg::span_gradient<Color, Interpolator, Adaptor,
00309             ColorInterpolator> Generator;
00310     typedef GradientStyle<Color, Allocator, Interpolator, GradientType,
00311                              Adaptor, ColorInterpolator, Generator> Type;
00312 };
00313 
00314 
00317 class SolidStyle : public AggStyle 
00318 {
00319 public:
00320 
00321   SolidStyle(const agg::rgba8& color)
00322     :
00323     AggStyle(true, color)
00324   {
00325   }
00326 
00327   void generate_span(agg::rgba8* /*span*/, int /*x*/, int /*y*/,
00328         unsigned /*len*/)
00329   {
00330     abort(); // never call generate_span for solid fill styles
00331   }
00332 };
00333 
00334 
00339 template <class PixelFormat, class Allocator, class SourceType,
00340        class Interpolator, class Generator>
00341 class BitmapStyle : public AggStyle
00342 {
00343 public:
00344     
00345   BitmapStyle(int width, int height, int rowlen, boost::uint8_t* data, 
00346     const SWFMatrix& mat, const SWFCxForm& cx)
00347     :
00348     AggStyle(false),
00349     m_cx(cx),
00350     m_rbuf(data, width, height, rowlen),  
00351     m_pixf(m_rbuf),
00352     m_img_src(m_pixf),
00353     m_tr(mat.sx / 65535.0, mat.shx / 65535.0, mat.shy / 65535.0,
00354             mat.sy / 65535.0, mat.tx, mat.ty),
00355     m_interpolator(m_tr),
00356     m_sg(m_img_src, m_interpolator)
00357   {
00358     
00359     // Convert the transformation SWFMatrix to AGG's class. It's basically the
00360     // same and we could even use SWFMatrix since AGG does not require
00361     // a real AGG descendant (templates!). However, it's better to use AGG's
00362     // class as this should be faster (avoid type conversion).
00363   }
00364   
00365   virtual ~BitmapStyle() {
00366   }
00367     
00368     void generate_span(agg::rgba8* span, int x, int y, unsigned len)
00369     {
00370         m_sg.generate(span, x, y, len);
00371 
00372         const bool transform = (m_cx != SWFCxForm());
00373 
00374         for (size_t i = 0; i < len; ++i) {
00375             // We must always do this because dynamic bitmaps (BitmapData)
00376             // can have any values. Loaded bitmaps are handled when loaded.
00377             span->r = std::min(span->r, span->a);
00378             span->g = std::min(span->g, span->a);
00379             span->b = std::min(span->b, span->a);
00380             if (transform) {
00381                 m_cx.transform(span->r, span->g, span->b, span->a);
00382                 span->premultiply();
00383             }
00384             ++span;
00385         }  
00386     }
00387   
00388 private:
00389 
00390     // Color transform
00391     SWFCxForm m_cx;
00392 
00393     // Pixel access
00394     agg::rendering_buffer m_rbuf;
00395     PixelFormat m_pixf;
00396   
00397     // Span allocator
00398     Allocator m_sa;
00399   
00400     // Image accessor
00401     SourceType m_img_src;
00402   
00403     // Transformer
00404     agg::trans_affine m_tr;
00405   
00406     // Interpolator
00407     Interpolator m_interpolator;
00408   
00409     // Span generator
00410     Generator m_sg;  
00411 };
00412 
00413 }
00414 
00415 
00416 // --- AGG HELPER CLASSES ------------------------------------------------------
00417 
00421 class StyleHandler
00422 {
00423 public:
00424 
00425     StyleHandler() : 
00426         m_transparent(0, 0, 0, 0)        
00427     {}
00428     
00429     ~StyleHandler() {
00430         deleteChecked(_styles.begin(), _styles.end());
00431     }
00432 
00434     bool is_solid(unsigned style) const {
00435       assert(style < _styles.size());
00436       return _styles[style]->solid(); 
00437     }
00438     
00440     void add_color(const agg::rgba8& color) {
00441       SolidStyle *st = new SolidStyle(color);
00442       _styles.push_back(st);
00443     }
00444 
00446     void add_bitmap(const agg_bitmap_info* bi, const SWFMatrix& mat,
00447         const SWFCxForm& cx, bool repeat, bool smooth) {
00448 
00449         if (!bi) {
00450             add_color(agg::rgba8_pre(0,0,0,0));
00451             return;
00452         }
00453 
00454         // Tiled
00455         if (repeat) {
00456             storeBitmap<Tile>(*this, bi, mat, cx, smooth);
00457             return;
00458         }
00459 
00460         storeBitmap<Clip>(*this, bi, mat, cx, smooth);
00461     } 
00462 
00463     template<typename T>
00464     void addLinearGradient(const GradientFill& fs, const SWFMatrix& mat,
00465             const SWFCxForm& cx)
00466     {
00467         // NOTE: The value 256 is based on the bitmap texture used by other
00468         // Gnash renderers which is normally 256x1 pixels for linear gradients.
00469         typename T::Type* st = new typename T::Type(fs, mat, cx, 256);
00470         _styles.push_back(st);
00471     }
00472     
00473     template<typename T>
00474     void addFocalGradient(const GradientFill& fs, const SWFMatrix& mat,
00475             const SWFCxForm& cx)
00476     {
00477         // move the center of the radial fill to where it should be
00478         SWFMatrix transl;
00479         transl.set_translation(-32, -32);
00480         transl.concatenate(mat);    
00481 
00482         typename T::GradientType gr;
00483         gr.init(32.0, fs.focalPoint() * 32.0, 0.0);
00484         
00485         // div 2 because we need radius, not diameter      
00486         typename T::Type* st = new typename T::Type(fs, transl, cx, 64/2, gr); 
00487         
00488         // NOTE: The value 64 is based on the bitmap texture used by other
00489         // Gnash renderers which is normally 64x64 pixels for radial gradients.
00490         _styles.push_back(st);
00491     }
00492     
00493     template<typename T>
00494     void addRadialGradient(const GradientFill& fs, const SWFMatrix& mat,
00495             const SWFCxForm& cx)
00496     {
00497         // move the center of the radial fill to where it should be
00498         SWFMatrix transl;
00499         transl.set_translation(-32, -32);
00500         transl.concatenate(mat);    
00501 
00502         // div 2 because we need radius, not diameter      
00503         typename T::Type* st = new typename T::Type(fs, transl, cx, 64 / 2); 
00504           
00505         // NOTE: The value 64 is based on the bitmap texture used by other
00506         // Gnash renderers which is normally 64x64 pixels for radial gradients.
00507         _styles.push_back(st);
00508     }
00509 
00511     agg::rgba8 color(unsigned style) const 
00512     {
00513         if (style < _styles.size())
00514             return _styles[style]->color();
00515 
00516         return m_transparent;
00517     }
00518 
00520     void generate_span(agg::rgba8* span, int x, int y,
00521         unsigned len, unsigned style)
00522     {
00523       _styles[style]->generate_span(span,x,y,len);
00524     }
00525 
00526 
00528     //
00531     template<typename Filter> void
00532     addBitmap(const agg_bitmap_info* bi, const SWFMatrix& mat,
00533             const SWFCxForm& cx)
00534     {
00535         typedef typename Filter::PixelFormat PixelFormat;
00536         typedef typename Filter::Generator Generator;
00537         typedef typename Filter::Allocator Allocator;
00538         typedef typename Filter::SourceType SourceType;
00539         typedef typename Filter::Interpolator Interpolator;
00540 
00541         typedef BitmapStyle<PixelFormat, Allocator,
00542                 SourceType, Interpolator, Generator> Style;
00543       
00544         Style* st = new Style(bi->get_width(), bi->get_height(),
00545           bi->get_rowlen(), bi->get_data(), mat, cx);       
00546         
00547         _styles.push_back(st);
00548     }
00549 
00550     std::vector<AggStyle*> _styles;
00551     agg::rgba8 m_transparent;
00552 
00553 }; 
00554 
00555 class agg_mask_style_handler 
00556 {
00557 public:
00558 
00559   agg_mask_style_handler() :
00560     m_color(255,255)
00561   {
00562   }
00563 
00564   bool is_solid(unsigned /*style*/) const
00565   {
00566     return true;
00567   }
00568   
00569   const agg::gray8& color(unsigned /*style*/) const 
00570   {
00571     return m_color;
00572   }
00573   
00574   void generate_span(agg::gray8* /*span*/, int /*x*/, int /*y*/,
00575         int /*len*/, unsigned /*style*/)
00576   {
00577     abort(); // never call generate_span for solid fill styles
00578   }
00579 
00580 private:
00581   agg::gray8 m_color;
00582   
00583 };  // class agg_mask_style_handler
00584 
00586 //
00588 struct AddStyles : boost::static_visitor<>
00589 {
00590     AddStyles(SWFMatrix stage, SWFMatrix fill, const SWFCxForm& c,
00591             StyleHandler& sh, Quality q)
00592         :
00593         _stageMatrix(stage.invert()),
00594         _fillMatrix(fill.invert()),
00595         _cx(c),
00596         _sh(sh),
00597         _quality(q)
00598     {}
00599 
00600     void operator()(const GradientFill& f) const {
00601           SWFMatrix m = f.matrix();
00602           m.concatenate(_fillMatrix);
00603           m.concatenate(_stageMatrix);
00604           storeGradient(_sh, f, m, _cx);
00605     }
00606 
00607     void operator()(const SolidFill& f) const {
00608         const rgba color = _cx.transform(f.color());
00609 
00610         // add the color to our self-made style handler (basically
00611         // just a list)
00612         _sh.add_color(agg::rgba8_pre(color.m_r, color.m_g, color.m_b,
00613                   color.m_a));
00614     }
00615 
00616     void operator()(const BitmapFill& f) const {
00617         SWFMatrix m = f.matrix();
00618         m.concatenate(_fillMatrix);
00619         m.concatenate(_stageMatrix);
00620 
00621         // Smoothing policy:
00622         //
00623         // - If unspecified, smooth when _quality >= BEST
00624         // - If ON or forced, smooth when _quality > LOW
00625         // - If OFF, don't smooth
00626         //
00627         // TODO: take a forceBitmapSmoothing parameter.
00628         //       which should be computed by the VM looking
00629         //       at MovieClip.forceSmoothing.
00630         bool smooth = false;
00631         if (_quality > QUALITY_LOW) {
00632             // TODO: if forceSmoothing is true, smooth !
00633             switch (f.smoothingPolicy()) {
00634                 case BitmapFill::SMOOTHING_UNSPECIFIED:
00635                     if (_quality >= QUALITY_BEST) smooth = true;
00636                     break;
00637                 case BitmapFill::SMOOTHING_ON:
00638                     smooth = true;
00639                     break;
00640                 default: break;
00641             }
00642         }
00643 
00644         const bool tiled = (f.type() == BitmapFill::TILED);
00645 
00646         _sh.add_bitmap(dynamic_cast<const agg_bitmap_info*>(f.bitmap()),
00647                 m, _cx, tiled, smooth);
00648     }
00649 
00650 private:
00651 
00653     const SWFMatrix _stageMatrix;
00654     
00656     const SWFMatrix _fillMatrix;
00657     const SWFCxForm& _cx;
00658     StyleHandler& _sh;
00659     const Quality _quality;
00660 };  
00661 
00662 namespace {
00663 
00664 template<typename FillMode, typename Pixel>
00665 void
00666 storeBitmap(StyleHandler& st, const agg_bitmap_info* bi,
00667         const SWFMatrix& mat, const SWFCxForm& cx, bool smooth)
00668 {
00669     if (smooth) {
00670         st.addBitmap<AA<Pixel, FillMode> >(bi, mat, cx);
00671         return;
00672     }
00673     st.addBitmap<NN<Pixel, FillMode> >(bi, mat, cx);
00674 }
00675 
00676 template<typename FillMode>
00677 void
00678 storeBitmap(StyleHandler& st, const agg_bitmap_info* bi,
00679         const SWFMatrix& mat, const SWFCxForm& cx, bool smooth)
00680 {
00681 
00682     if (bi->get_bpp() == 24) {
00683         storeBitmap<FillMode, RGB>(st, bi, mat, cx, smooth);
00684         return;
00685     }
00686     storeBitmap<FillMode, RGBA>(st, bi, mat, cx, smooth);
00687 }
00688 
00689 template<typename Spread, typename Interpolation>
00690 void
00691 storeGradient(StyleHandler& st, const GradientFill& fs, const SWFMatrix& mat,
00692         const SWFCxForm& cx)
00693 {
00694       
00695     typedef agg::gradient_x Linear;
00696     typedef agg::gradient_radial Radial;
00697     typedef agg::gradient_radial_focus Focal;
00698 
00699     typedef Gradient<Linear, Spread, Interpolation> LinearGradient;
00700     typedef Gradient<Focal, Spread, Interpolation> FocalGradient;
00701     typedef Gradient<Radial, Spread, Interpolation> RadialGradient;
00702 
00703     switch (fs.type()) {
00704         case GradientFill::LINEAR:
00705             st.addLinearGradient<LinearGradient>(fs, mat, cx);
00706             return;
00707       
00708         case GradientFill::RADIAL:
00709             if (fs.focalPoint()) {
00710                 st.addFocalGradient<FocalGradient>(fs, mat, cx);
00711                 return;
00712             }
00713             st.addRadialGradient<RadialGradient>(fs, mat, cx);
00714     }
00715 }
00716 
00717 template<typename Spread>
00718 void
00719 storeGradient(StyleHandler& st, const GradientFill& fs, const SWFMatrix& mat,
00720         const SWFCxForm& cx)
00721 {
00722     // TODO: provide and use a linearRGB interpolator.
00723     switch (fs.interpolation) {
00724         default:
00725           storeGradient<Spread, InterpolatorRGB>(st, fs, mat, cx);
00726           break;
00727     }
00728 
00729 }
00730 
00731 void
00732 storeGradient(StyleHandler& st, const GradientFill& fs, const SWFMatrix& mat,
00733         const SWFCxForm& cx)
00734 {   
00735 
00736       switch (fs.spreadMode) {
00737           case GradientFill::PAD:
00738               storeGradient<Pad>(st, fs, mat, cx);
00739               break;
00740           case GradientFill::REFLECT:
00741               storeGradient<Reflect>(st, fs, mat, cx);
00742               break;
00743           case GradientFill::REPEAT:
00744               storeGradient<Repeat>(st, fs, mat, cx);
00745               break;
00746       }
00747 }
00748 
00749 }
00750 
00751 } // namespace gnash
00752 
00753 #endif // BACKEND_RENDER_HANDLER_AGG_STYLE_H

Generated on Thu Sep 2 2010 for Gnash by  doxygen 1.7.1