00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #ifndef BACKEND_RENDER_HANDLER_AGG_STYLE_H
00020 #define BACKEND_RENDER_HANDLER_AGG_STYLE_H
00021
00022
00023
00024
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
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
00090
00091
00092
00093 virtual ~AggStyle() {}
00094 bool solid() const { return _solid; }
00095 agg::rgba8 color() const { return _color; }
00096
00097
00098 virtual void generate_span(agg::rgba8* span, int x, int y,
00099 unsigned len) = 0;
00100
00101 private:
00102
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
00257 m_gradient_lut.remove_all();
00258 const size_t size = fs.recordCount();
00259
00260
00261
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 }
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
00290 SWFCxForm m_cx;
00291
00292
00293 Allocator m_sa;
00294
00295
00296 agg::trans_affine m_tr;
00297
00298
00299 Interpolator m_span_interpolator;
00300
00301
00302 Adaptor m_gradient_adaptor;
00303
00304
00305 ColorInterpolator m_gradient_lut;
00306
00307
00308 SpanGenerator m_sg;
00309
00310
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* , int , int ,
00348 unsigned )
00349 {
00350 abort();
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
00391
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
00406 SWFCxForm m_cx;
00407
00408
00409 agg::rendering_buffer m_rbuf;
00410 PixelFormat m_pixf;
00411
00412
00413 Allocator m_sa;
00414
00415
00416 SourceType m_img_src;
00417
00418
00419 agg::trans_affine m_tr;
00420
00421
00422 Interpolator m_interpolator;
00423
00424
00425 Generator m_sg;
00426 };
00427
00428 }
00429
00430
00431
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
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
00479
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
00492 typename T::Type* st = new typename T::Type(fs, mat, cx, 32.0, gr);
00493
00494
00495
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
00505 typename T::Type* st = new typename T::Type(fs, mat, cx, 64 / 2);
00506
00507
00508
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 ) const
00567 {
00568 return true;
00569 }
00570
00571 const agg::gray8& color(unsigned ) const
00572 {
00573 return m_color;
00574 }
00575
00576 void generate_span(agg::gray8* , int , int ,
00577 int , unsigned )
00578 {
00579 abort();
00580 }
00581
00582 private:
00583 agg::gray8 m_color;
00584
00585 };
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
00614
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
00625
00626
00627
00628
00629
00630
00631
00632
00633 bool smooth = false;
00634 if (_quality > QUALITY_LOW) {
00635
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
00653 _sh.add_color(agg::rgba8_pre(255,0,0,255));
00654 }
00655 else if ( bm->disposed() ) {
00656
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 }
00769
00770 #endif // BACKEND_RENDER_HANDLER_AGG_STYLE_H