Gnash 0.8.9
|
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