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