• 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 cxform& cx,
00048             bool smooth);
00049     template<typename FillMode> void storeBitmap(StyleHandler& st,
00050             const agg_bitmap_info* bi, const SWFMatrix& mat, const cxform& cx,
00051             bool smooth);
00052 
00054     void storeGradient(StyleHandler& st, const GradientFill& fs,
00055             const SWFMatrix& mat, const cxform& cx);
00056     template<typename Spread> void storeGradient(StyleHandler& st,
00057             const GradientFill& fs, const SWFMatrix& mat, const cxform& cx);
00058     template<typename Spread, typename Interpolation>
00059             void storeGradient(StyleHandler& st, const GradientFill& fs,
00060             const SWFMatrix& mat, const cxform& 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 cxform& 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     gnash::cxform 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 gnash::SWFMatrix& mat, const gnash::cxform& 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 gnash::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         // Apply color transform
00372         // TODO: Check if this can be optimized
00373         if (m_cx.is_identity()) return;
00374         for (unsigned int i=0; i < len; i++) {
00375             m_cx.transform(span->r, span->g, span->b, span->a);
00376             span->premultiply();
00377             ++span;
00378         }  
00379     }
00380   
00381 private:
00382 
00383     // Color transform
00384     gnash::cxform m_cx;
00385 
00386     // Pixel access
00387     agg::rendering_buffer m_rbuf;
00388     PixelFormat m_pixf;
00389   
00390     // Span allocator
00391     Allocator m_sa;
00392   
00393     // Image accessor
00394     SourceType m_img_src;
00395   
00396     // Transformer
00397     agg::trans_affine m_tr;
00398   
00399     // Interpolator
00400     Interpolator m_interpolator;
00401   
00402     // Span generator
00403     Generator m_sg;  
00404 };
00405 
00406 }
00407 
00408 
00409 // --- AGG HELPER CLASSES ------------------------------------------------------
00410 
00414 class StyleHandler
00415 {
00416 public:
00417 
00418     StyleHandler() : 
00419         m_transparent(0, 0, 0, 0)        
00420     {}
00421     
00422     ~StyleHandler() {
00423         deleteChecked(_styles.begin(), _styles.end());
00424     }
00425 
00427     bool is_solid(unsigned style) const {
00428       assert(style < _styles.size());
00429       return _styles[style]->solid(); 
00430     }
00431     
00433     void add_color(const agg::rgba8& color) {
00434       SolidStyle *st = new SolidStyle(color);
00435       _styles.push_back(st);
00436     }
00437 
00439     void add_bitmap(const agg_bitmap_info* bi, const gnash::SWFMatrix& mat,
00440         const gnash::cxform& cx, bool repeat, bool smooth) {
00441 
00442         if (!bi) {
00443             add_color(agg::rgba8_pre(0,0,0,0));
00444             return;
00445         }
00446 
00447         // Tiled
00448         if (repeat) {
00449             storeBitmap<Tile>(*this, bi, mat, cx, smooth);
00450             return;
00451         }
00452 
00453         storeBitmap<Clip>(*this, bi, mat, cx, smooth);
00454     } 
00455 
00456     template<typename T>
00457     void addLinearGradient(const GradientFill& fs, const gnash::SWFMatrix& mat,
00458             const gnash::cxform& cx)
00459     {
00460         // NOTE: The value 256 is based on the bitmap texture used by other
00461         // Gnash renderers which is normally 256x1 pixels for linear gradients.
00462         typename T::Type* st = new typename T::Type(fs, mat, cx, 256);
00463         _styles.push_back(st);
00464     }
00465     
00466     template<typename T>
00467     void addFocalGradient(const GradientFill& fs, const gnash::SWFMatrix& mat,
00468             const gnash::cxform& cx)
00469     {
00470         // move the center of the radial fill to where it should be
00471         SWFMatrix transl;
00472         transl.set_translation(-32, -32);
00473         transl.concatenate(mat);    
00474 
00475         typename T::GradientType gr;
00476         gr.init(32.0, fs.focalPoint() * 32.0, 0.0);
00477         
00478         // div 2 because we need radius, not diameter      
00479         typename T::Type* st = new typename T::Type(fs, transl, cx, 64/2, gr); 
00480         
00481         // NOTE: The value 64 is based on the bitmap texture used by other
00482         // Gnash renderers which is normally 64x64 pixels for radial gradients.
00483         _styles.push_back(st);
00484     }
00485     
00486     template<typename T>
00487     void addRadialGradient(const GradientFill& fs, const gnash::SWFMatrix& mat,
00488             const gnash::cxform& cx)
00489     {
00490         // move the center of the radial fill to where it should be
00491         SWFMatrix transl;
00492         transl.set_translation(-32, -32);
00493         transl.concatenate(mat);    
00494 
00495         // div 2 because we need radius, not diameter      
00496         typename T::Type* st = new typename T::Type(fs, transl, cx, 64 / 2); 
00497           
00498         // NOTE: The value 64 is based on the bitmap texture used by other
00499         // Gnash renderers which is normally 64x64 pixels for radial gradients.
00500         _styles.push_back(st);
00501     }
00502 
00504     agg::rgba8 color(unsigned style) const 
00505     {
00506         if (style < _styles.size())
00507             return _styles[style]->color();
00508 
00509         return m_transparent;
00510     }
00511 
00513     void generate_span(agg::rgba8* span, int x, int y,
00514         unsigned len, unsigned style)
00515     {
00516       _styles[style]->generate_span(span,x,y,len);
00517     }
00518 
00519 
00521     //
00524     template<typename Filter> void
00525     addBitmap(const agg_bitmap_info* bi, const gnash::SWFMatrix& mat,
00526             const gnash::cxform& cx)
00527     {
00528         typedef typename Filter::PixelFormat PixelFormat;
00529         typedef typename Filter::Generator Generator;
00530         typedef typename Filter::Allocator Allocator;
00531         typedef typename Filter::SourceType SourceType;
00532         typedef typename Filter::Interpolator Interpolator;
00533 
00534         typedef BitmapStyle<PixelFormat, Allocator,
00535                 SourceType, Interpolator, Generator> Style;
00536       
00537         Style* st = new Style(bi->get_width(), bi->get_height(),
00538           bi->get_rowlen(), bi->get_data(), mat, cx);       
00539         
00540         _styles.push_back(st);
00541     }
00542 
00543     std::vector<AggStyle*> _styles;
00544     agg::rgba8 m_transparent;
00545 
00546 }; 
00547 
00548 class agg_mask_style_handler 
00549 {
00550 public:
00551 
00552   agg_mask_style_handler() :
00553     m_color(255,255)
00554   {
00555   }
00556 
00557   bool is_solid(unsigned /*style*/) const
00558   {
00559     return true;
00560   }
00561   
00562   const agg::gray8& color(unsigned /*style*/) const 
00563   {
00564     return m_color;
00565   }
00566   
00567   void generate_span(agg::gray8* /*span*/, int /*x*/, int /*y*/,
00568         int /*len*/, unsigned /*style*/)
00569   {
00570     abort(); // never call generate_span for solid fill styles
00571   }
00572 
00573 private:
00574   agg::gray8 m_color;
00575   
00576 };  // class agg_mask_style_handler
00577 
00579 //
00581 struct AddStyles : boost::static_visitor<>
00582 {
00583     AddStyles(SWFMatrix stage, SWFMatrix fill, const cxform& c,
00584             StyleHandler& sh, Quality q)
00585         :
00586         _stageMatrix(stage.invert()),
00587         _fillMatrix(fill.invert()),
00588         _cx(c),
00589         _sh(sh),
00590         _quality(q)
00591     {}
00592 
00593     void operator()(const GradientFill& f) const {
00594           SWFMatrix m = f.matrix();
00595           m.concatenate(_fillMatrix);
00596           m.concatenate(_stageMatrix);
00597           storeGradient(_sh, f, m, _cx);
00598     }
00599 
00600     void operator()(const SolidFill& f) const {
00601         const rgba color = _cx.transform(f.color());
00602 
00603         // add the color to our self-made style handler (basically
00604         // just a list)
00605         _sh.add_color(agg::rgba8_pre(color.m_r, color.m_g, color.m_b,
00606                   color.m_a));
00607     }
00608 
00609     void operator()(const BitmapFill& f) const {
00610         SWFMatrix m = f.matrix();
00611         m.concatenate(_fillMatrix);
00612         m.concatenate(_stageMatrix);
00613 
00614         // Smoothing policy:
00615         //
00616         // - If unspecified, smooth when _quality >= BEST
00617         // - If ON or forced, smooth when _quality > LOW
00618         // - If OFF, don't smooth
00619         //
00620         // TODO: take a forceBitmapSmoothing parameter.
00621         //       which should be computed by the VM looking
00622         //       at MovieClip.forceSmoothing.
00623         bool smooth = false;
00624         if (_quality > QUALITY_LOW) {
00625             // TODO: if forceSmoothing is true, smooth !
00626             switch (f.smoothingPolicy()) {
00627                 case BitmapFill::SMOOTHING_UNSPECIFIED:
00628                     if (_quality >= QUALITY_BEST) smooth = true;
00629                     break;
00630                 case BitmapFill::SMOOTHING_ON:
00631                     smooth = true;
00632                     break;
00633                 default: break;
00634             }
00635         }
00636 
00637         const bool tiled = (f.type() == BitmapFill::TILED);
00638 
00639         _sh.add_bitmap(dynamic_cast<const agg_bitmap_info*>(f.bitmap()),
00640                 m, _cx, tiled, smooth);
00641     }
00642 
00643 private:
00644 
00646     const SWFMatrix _stageMatrix;
00647     
00649     const SWFMatrix _fillMatrix;
00650     const cxform& _cx;
00651     StyleHandler& _sh;
00652     const Quality _quality;
00653 };  
00654 
00655 namespace {
00656 
00657 template<typename FillMode, typename Pixel>
00658 void
00659 storeBitmap(StyleHandler& st, const agg_bitmap_info* bi,
00660         const SWFMatrix& mat, const cxform& cx, bool smooth)
00661 {
00662     if (smooth) {
00663         st.addBitmap<AA<Pixel, FillMode> >(bi, mat, cx);
00664         return;
00665     }
00666     st.addBitmap<NN<Pixel, FillMode> >(bi, mat, cx);
00667 }
00668 
00669 template<typename FillMode>
00670 void
00671 storeBitmap(StyleHandler& st, const agg_bitmap_info* bi,
00672         const SWFMatrix& mat, const cxform& cx, bool smooth)
00673 {
00674 
00675     if (bi->get_bpp() == 24) {
00676         storeBitmap<FillMode, RGB>(st, bi, mat, cx, smooth);
00677         return;
00678     }
00679     storeBitmap<FillMode, RGBA>(st, bi, mat, cx, smooth);
00680 }
00681 
00682 template<typename Spread, typename Interpolation>
00683 void
00684 storeGradient(StyleHandler& st, const GradientFill& fs, const SWFMatrix& mat,
00685         const cxform& cx)
00686 {
00687       
00688     typedef agg::gradient_x Linear;
00689     typedef agg::gradient_radial Radial;
00690     typedef agg::gradient_radial_focus Focal;
00691 
00692     typedef Gradient<Linear, Spread, Interpolation> LinearGradient;
00693     typedef Gradient<Focal, Spread, Interpolation> FocalGradient;
00694     typedef Gradient<Radial, Spread, Interpolation> RadialGradient;
00695 
00696     switch (fs.type()) {
00697         case GradientFill::LINEAR:
00698             st.addLinearGradient<LinearGradient>(fs, mat, cx);
00699             return;
00700       
00701         case GradientFill::RADIAL:
00702             if (fs.focalPoint()) {
00703                 st.addFocalGradient<FocalGradient>(fs, mat, cx);
00704                 return;
00705             }
00706             st.addRadialGradient<RadialGradient>(fs, mat, cx);
00707     }
00708 }
00709 
00710 template<typename Spread>
00711 void
00712 storeGradient(StyleHandler& st, const GradientFill& fs, const SWFMatrix& mat,
00713         const cxform& cx)
00714 {
00715     // TODO: provide and use a linearRGB interpolator.
00716     switch (fs.interpolation) {
00717         default:
00718           storeGradient<Spread, InterpolatorRGB>(st, fs, mat, cx);
00719           break;
00720     }
00721 
00722 }
00723 
00724 void
00725 storeGradient(StyleHandler& st, const GradientFill& fs, const SWFMatrix& mat,
00726         const cxform& cx)
00727 {   
00728 
00729       switch (fs.spreadMode) {
00730           case GradientFill::PAD:
00731               storeGradient<Pad>(st, fs, mat, cx);
00732               break;
00733           case GradientFill::REFLECT:
00734               storeGradient<Reflect>(st, fs, mat, cx);
00735               break;
00736           case GradientFill::REPEAT:
00737               storeGradient<Repeat>(st, fs, mat, cx);
00738               break;
00739       }
00740 }
00741 
00742 }
00743 
00744 } // namespace gnash
00745 
00746 #endif // BACKEND_RENDER_HANDLER_AGG_STYLE_H

Generated on Fri Mar 16 2012 15:46:12 for Gnash by  doxygen 1.7.1