Gnash 0.8.9

Renderer_agg_style.h

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