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