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
00027
00028
00029
00030
00031
00032
00033
00034 #include "GnashAlgorithm.h"
00035 #include "FillStyle.h"
00036
00037 namespace gnash {
00038
00039 class StyleHandler;
00040
00041
00042 namespace {
00043
00045 template<typename FillMode, typename Pixel>
00046 void storeBitmap(StyleHandler& st, const agg_bitmap_info* bi,
00047 const SWFMatrix& mat, const cxform& cx,
00048 bool smooth);
00049 template<typename FillMode> void storeBitmap(StyleHandler& st,
00050 const agg_bitmap_info* bi, const SWFMatrix& mat, const cxform& cx,
00051 bool smooth);
00052
00054 void storeGradient(StyleHandler& st, const GradientFill& fs,
00055 const SWFMatrix& mat, const cxform& cx);
00056 template<typename Spread> void storeGradient(StyleHandler& st,
00057 const GradientFill& fs, const SWFMatrix& mat, const cxform& cx);
00058 template<typename Spread, typename Interpolation>
00059 void storeGradient(StyleHandler& st, const GradientFill& fs,
00060 const SWFMatrix& mat, const cxform& cx);
00061 }
00062
00067 class AggStyle
00068 {
00069 public:
00070 AggStyle(bool solid, const agg::rgba8& color = agg::rgba8(0,0,0,0))
00071 :
00072 _solid(solid),
00073 _color(color)
00074 {
00075 }
00076
00077
00078
00079
00080
00081 virtual ~AggStyle() {}
00082 bool solid() const { return _solid; }
00083 agg::rgba8 color() const { return _color; }
00084
00085
00086 virtual void generate_span(agg::rgba8* span, int x, int y,
00087 unsigned len) = 0;
00088
00089 private:
00090
00091 const bool _solid;
00092 const agg::rgba8 _color;
00093 };
00094
00095 namespace {
00096
00098 struct Tile
00099 {
00100 template<typename P> struct Type {
00101 typedef agg::wrap_mode_repeat Wrap;
00102 typedef agg::image_accessor_wrap<P, Wrap, Wrap> type;
00103 };
00104 };
00105
00107 struct Clip
00108 {
00109 template<typename P> struct Type {
00110 typedef agg::image_accessor_clone<P> type;
00111 };
00112 };
00113
00115 template<typename P, typename W>
00116 struct FilterType
00117 {
00118 typedef typename P::PixelFormat PixelFormat;
00119 typedef typename W::template Type<PixelFormat>::type SourceType;
00120 typedef agg::span_allocator<PixelFormat> Allocator;
00121 typedef agg::span_interpolator_linear<agg::trans_affine>
00122 Interpolator;
00123 };
00124
00126 struct RGBA
00127 {
00128 typedef agg::pixfmt_rgba32_pre PixelFormat;
00129
00130 template<typename SourceType, typename Interpolator>
00131 struct Simple {
00132 typedef agg::span_image_filter_rgba_nn<SourceType, Interpolator> type;
00133 };
00134
00135 template<typename SourceType, typename Interpolator>
00136 struct AntiAlias {
00137 typedef agg::span_image_filter_rgba_bilinear<SourceType, Interpolator>
00138 type;
00139 };
00140 };
00141
00143 struct RGB
00144 {
00145 typedef agg::pixfmt_rgb24_pre PixelFormat;
00146
00147 template<typename SourceType, typename Interpolator>
00148 struct Simple {
00149 typedef agg::span_image_filter_rgb_nn<SourceType, Interpolator> type;
00150 };
00151
00152 template<typename SourceType, typename Interpolator>
00153 struct AntiAlias {
00154 typedef agg::span_image_filter_rgb_bilinear<SourceType, Interpolator>
00155 type;
00156 };
00157 };
00158
00160 template<typename P, typename W>
00161 struct NN : public FilterType<P, W>
00162 {
00163 typedef FilterType<P, W> BaseType;
00164 typedef typename P::template Simple<
00165 typename BaseType::SourceType,
00166 typename BaseType::Interpolator>::type Generator;
00167 };
00168
00170 template<typename P, typename W>
00171 struct AA : public FilterType<P, W>
00172 {
00173 typedef FilterType<P, W> BaseType;
00174 typedef typename P::template AntiAlias<
00175 typename BaseType::SourceType,
00176 typename BaseType::Interpolator>::type Generator;
00177 };
00178
00180 struct Reflect
00181 {
00182 template<typename T> struct Type {
00183 typedef agg::gradient_reflect_adaptor<T> type;
00184 };
00185 };
00186
00188 struct Repeat
00189 {
00190 template<typename T> struct Type {
00191 typedef agg::gradient_repeat_adaptor<T> type;
00192 };
00193 };
00194
00196 struct Pad
00197 {
00198 template<typename T> struct Type {
00199 typedef T type;
00200 };
00201 };
00202
00204 struct InterpolatorRGB
00205 {
00206 template<typename Pixel> struct Type {
00207 typedef agg::gradient_lut<agg::color_interpolator<Pixel>, 256> type;
00208 };
00209 };
00210
00216 template <class Color, class Allocator, class Interpolator, class GradientType,
00217 class Adaptor, class ColorInterpolator, class SpanGenerator>
00218 class GradientStyle : public AggStyle
00219 {
00220 public:
00221
00222 GradientStyle(const GradientFill& fs, const SWFMatrix& mat,
00223 const cxform& cx, int norm_size, GradientType gr = GradientType())
00224 :
00225 AggStyle(false),
00226 m_cx(cx),
00227 m_tr(mat.sx / 65536.0, mat.shx/65536.0, mat.shy / 65536.0,
00228 mat.sy / 65536.0, mat.tx, mat.ty),
00229 m_span_interpolator(m_tr),
00230 m_gradient_adaptor(gr),
00231 m_sg(m_span_interpolator, m_gradient_adaptor, m_gradient_lut, 0,
00232 norm_size),
00233
00234 m_need_premultiply(false)
00235 {
00236
00237 m_gradient_lut.remove_all();
00238 const size_t size = fs.recordCount();
00239
00240
00241
00242 assert(size > 1);
00243
00244 for (size_t i = 0; i != size; ++i) {
00245 const GradientRecord& gr = fs.record(i);
00246 const rgba tr = m_cx.transform(gr.color);
00247 if (tr.m_a < 255) m_need_premultiply = true;
00248 m_gradient_lut.add_color(gr.ratio/255.0,
00249 agg::rgba8(tr.m_r, tr.m_g, tr.m_b, tr.m_a));
00250 }
00251 m_gradient_lut.build_lut();
00252
00253 }
00254
00255 virtual ~GradientStyle() { }
00256
00257 void generate_span(Color* span, int x, int y, unsigned len) {
00258 m_sg.generate(span, x, y, len);
00259 if (!m_need_premultiply) return;
00260
00261 while (len--) {
00262 span->premultiply();
00263 ++span;
00264 }
00265 }
00266
00267 protected:
00268
00269
00270 gnash::cxform m_cx;
00271
00272
00273 Allocator m_sa;
00274
00275
00276 agg::trans_affine m_tr;
00277
00278
00279 Interpolator m_span_interpolator;
00280
00281
00282 Adaptor m_gradient_adaptor;
00283
00284
00285 ColorInterpolator m_gradient_lut;
00286
00287
00288 SpanGenerator m_sg;
00289
00290
00291 bool m_need_premultiply;
00292 };
00293
00295
00299 template<typename G, typename A, typename I>
00300 struct Gradient
00301 {
00302 typedef agg::rgba8 Color;
00303 typedef G GradientType;
00304 typedef typename A::template Type<G>::type Adaptor;
00305 typedef typename I::template Type<Color>::type ColorInterpolator;
00306 typedef agg::span_allocator<Color> Allocator;
00307 typedef agg::span_interpolator_linear<agg::trans_affine> Interpolator;
00308 typedef agg::span_gradient<Color, Interpolator, Adaptor,
00309 ColorInterpolator> Generator;
00310 typedef GradientStyle<Color, Allocator, Interpolator, GradientType,
00311 Adaptor, ColorInterpolator, Generator> Type;
00312 };
00313
00314
00317 class SolidStyle : public AggStyle
00318 {
00319 public:
00320
00321 SolidStyle(const agg::rgba8& color)
00322 :
00323 AggStyle(true, color)
00324 {
00325 }
00326
00327 void generate_span(agg::rgba8* , int , int ,
00328 unsigned )
00329 {
00330 abort();
00331 }
00332 };
00333
00334
00339 template <class PixelFormat, class Allocator, class SourceType,
00340 class Interpolator, class Generator>
00341 class BitmapStyle : public AggStyle
00342 {
00343 public:
00344
00345 BitmapStyle(int width, int height, int rowlen, boost::uint8_t* data,
00346 const gnash::SWFMatrix& mat, const gnash::cxform& cx)
00347 :
00348 AggStyle(false),
00349 m_cx(cx),
00350 m_rbuf(data, width, height, rowlen),
00351 m_pixf(m_rbuf),
00352 m_img_src(m_pixf),
00353 m_tr(mat.sx / 65535.0, mat.shx / 65535.0, mat.shy / 65535.0,
00354 mat.sy / 65535.0, mat.tx, mat.ty),
00355 m_interpolator(m_tr),
00356 m_sg(m_img_src, m_interpolator)
00357 {
00358
00359
00360
00361
00362
00363 }
00364
00365 virtual ~BitmapStyle() {
00366 }
00367
00368 void generate_span(agg::rgba8* span, int x, int y, unsigned len)
00369 {
00370 m_sg.generate(span, x, y, len);
00371
00372
00373 if (m_cx.is_identity()) return;
00374 for (unsigned int i=0; i < len; i++) {
00375 m_cx.transform(span->r, span->g, span->b, span->a);
00376 span->premultiply();
00377 ++span;
00378 }
00379 }
00380
00381 private:
00382
00383
00384 gnash::cxform m_cx;
00385
00386
00387 agg::rendering_buffer m_rbuf;
00388 PixelFormat m_pixf;
00389
00390
00391 Allocator m_sa;
00392
00393
00394 SourceType m_img_src;
00395
00396
00397 agg::trans_affine m_tr;
00398
00399
00400 Interpolator m_interpolator;
00401
00402
00403 Generator m_sg;
00404 };
00405
00406 }
00407
00408
00409
00410
00414 class StyleHandler
00415 {
00416 public:
00417
00418 StyleHandler() :
00419 m_transparent(0, 0, 0, 0)
00420 {}
00421
00422 ~StyleHandler() {
00423 deleteChecked(_styles.begin(), _styles.end());
00424 }
00425
00427 bool is_solid(unsigned style) const {
00428 assert(style < _styles.size());
00429 return _styles[style]->solid();
00430 }
00431
00433 void add_color(const agg::rgba8& color) {
00434 SolidStyle *st = new SolidStyle(color);
00435 _styles.push_back(st);
00436 }
00437
00439 void add_bitmap(const agg_bitmap_info* bi, const gnash::SWFMatrix& mat,
00440 const gnash::cxform& cx, bool repeat, bool smooth) {
00441
00442 if (!bi) {
00443 add_color(agg::rgba8_pre(0,0,0,0));
00444 return;
00445 }
00446
00447
00448 if (repeat) {
00449 storeBitmap<Tile>(*this, bi, mat, cx, smooth);
00450 return;
00451 }
00452
00453 storeBitmap<Clip>(*this, bi, mat, cx, smooth);
00454 }
00455
00456 template<typename T>
00457 void addLinearGradient(const GradientFill& fs, const gnash::SWFMatrix& mat,
00458 const gnash::cxform& cx)
00459 {
00460
00461
00462 typename T::Type* st = new typename T::Type(fs, mat, cx, 256);
00463 _styles.push_back(st);
00464 }
00465
00466 template<typename T>
00467 void addFocalGradient(const GradientFill& fs, const gnash::SWFMatrix& mat,
00468 const gnash::cxform& cx)
00469 {
00470
00471 SWFMatrix transl;
00472 transl.set_translation(-32, -32);
00473 transl.concatenate(mat);
00474
00475 typename T::GradientType gr;
00476 gr.init(32.0, fs.focalPoint() * 32.0, 0.0);
00477
00478
00479 typename T::Type* st = new typename T::Type(fs, transl, cx, 64/2, gr);
00480
00481
00482
00483 _styles.push_back(st);
00484 }
00485
00486 template<typename T>
00487 void addRadialGradient(const GradientFill& fs, const gnash::SWFMatrix& mat,
00488 const gnash::cxform& cx)
00489 {
00490
00491 SWFMatrix transl;
00492 transl.set_translation(-32, -32);
00493 transl.concatenate(mat);
00494
00495
00496 typename T::Type* st = new typename T::Type(fs, transl, cx, 64 / 2);
00497
00498
00499
00500 _styles.push_back(st);
00501 }
00502
00504 agg::rgba8 color(unsigned style) const
00505 {
00506 if (style < _styles.size())
00507 return _styles[style]->color();
00508
00509 return m_transparent;
00510 }
00511
00513 void generate_span(agg::rgba8* span, int x, int y,
00514 unsigned len, unsigned style)
00515 {
00516 _styles[style]->generate_span(span,x,y,len);
00517 }
00518
00519
00521
00524 template<typename Filter> void
00525 addBitmap(const agg_bitmap_info* bi, const gnash::SWFMatrix& mat,
00526 const gnash::cxform& cx)
00527 {
00528 typedef typename Filter::PixelFormat PixelFormat;
00529 typedef typename Filter::Generator Generator;
00530 typedef typename Filter::Allocator Allocator;
00531 typedef typename Filter::SourceType SourceType;
00532 typedef typename Filter::Interpolator Interpolator;
00533
00534 typedef BitmapStyle<PixelFormat, Allocator,
00535 SourceType, Interpolator, Generator> Style;
00536
00537 Style* st = new Style(bi->get_width(), bi->get_height(),
00538 bi->get_rowlen(), bi->get_data(), mat, cx);
00539
00540 _styles.push_back(st);
00541 }
00542
00543 std::vector<AggStyle*> _styles;
00544 agg::rgba8 m_transparent;
00545
00546 };
00547
00548 class agg_mask_style_handler
00549 {
00550 public:
00551
00552 agg_mask_style_handler() :
00553 m_color(255,255)
00554 {
00555 }
00556
00557 bool is_solid(unsigned ) const
00558 {
00559 return true;
00560 }
00561
00562 const agg::gray8& color(unsigned ) const
00563 {
00564 return m_color;
00565 }
00566
00567 void generate_span(agg::gray8* , int , int ,
00568 int , unsigned )
00569 {
00570 abort();
00571 }
00572
00573 private:
00574 agg::gray8 m_color;
00575
00576 };
00577
00579
00581 struct AddStyles : boost::static_visitor<>
00582 {
00583 AddStyles(SWFMatrix stage, SWFMatrix fill, const cxform& c,
00584 StyleHandler& sh, Quality q)
00585 :
00586 _stageMatrix(stage.invert()),
00587 _fillMatrix(fill.invert()),
00588 _cx(c),
00589 _sh(sh),
00590 _quality(q)
00591 {}
00592
00593 void operator()(const GradientFill& f) const {
00594 SWFMatrix m = f.matrix();
00595 m.concatenate(_fillMatrix);
00596 m.concatenate(_stageMatrix);
00597 storeGradient(_sh, f, m, _cx);
00598 }
00599
00600 void operator()(const SolidFill& f) const {
00601 const rgba color = _cx.transform(f.color());
00602
00603
00604
00605 _sh.add_color(agg::rgba8_pre(color.m_r, color.m_g, color.m_b,
00606 color.m_a));
00607 }
00608
00609 void operator()(const BitmapFill& f) const {
00610 SWFMatrix m = f.matrix();
00611 m.concatenate(_fillMatrix);
00612 m.concatenate(_stageMatrix);
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623 bool smooth = false;
00624 if (_quality > QUALITY_LOW) {
00625
00626 switch (f.smoothingPolicy()) {
00627 case BitmapFill::SMOOTHING_UNSPECIFIED:
00628 if (_quality >= QUALITY_BEST) smooth = true;
00629 break;
00630 case BitmapFill::SMOOTHING_ON:
00631 smooth = true;
00632 break;
00633 default: break;
00634 }
00635 }
00636
00637 const bool tiled = (f.type() == BitmapFill::TILED);
00638
00639 _sh.add_bitmap(dynamic_cast<const agg_bitmap_info*>(f.bitmap()),
00640 m, _cx, tiled, smooth);
00641 }
00642
00643 private:
00644
00646 const SWFMatrix _stageMatrix;
00647
00649 const SWFMatrix _fillMatrix;
00650 const cxform& _cx;
00651 StyleHandler& _sh;
00652 const Quality _quality;
00653 };
00654
00655 namespace {
00656
00657 template<typename FillMode, typename Pixel>
00658 void
00659 storeBitmap(StyleHandler& st, const agg_bitmap_info* bi,
00660 const SWFMatrix& mat, const cxform& cx, bool smooth)
00661 {
00662 if (smooth) {
00663 st.addBitmap<AA<Pixel, FillMode> >(bi, mat, cx);
00664 return;
00665 }
00666 st.addBitmap<NN<Pixel, FillMode> >(bi, mat, cx);
00667 }
00668
00669 template<typename FillMode>
00670 void
00671 storeBitmap(StyleHandler& st, const agg_bitmap_info* bi,
00672 const SWFMatrix& mat, const cxform& cx, bool smooth)
00673 {
00674
00675 if (bi->get_bpp() == 24) {
00676 storeBitmap<FillMode, RGB>(st, bi, mat, cx, smooth);
00677 return;
00678 }
00679 storeBitmap<FillMode, RGBA>(st, bi, mat, cx, smooth);
00680 }
00681
00682 template<typename Spread, typename Interpolation>
00683 void
00684 storeGradient(StyleHandler& st, const GradientFill& fs, const SWFMatrix& mat,
00685 const cxform& cx)
00686 {
00687
00688 typedef agg::gradient_x Linear;
00689 typedef agg::gradient_radial Radial;
00690 typedef agg::gradient_radial_focus Focal;
00691
00692 typedef Gradient<Linear, Spread, Interpolation> LinearGradient;
00693 typedef Gradient<Focal, Spread, Interpolation> FocalGradient;
00694 typedef Gradient<Radial, Spread, Interpolation> RadialGradient;
00695
00696 switch (fs.type()) {
00697 case GradientFill::LINEAR:
00698 st.addLinearGradient<LinearGradient>(fs, mat, cx);
00699 return;
00700
00701 case GradientFill::RADIAL:
00702 if (fs.focalPoint()) {
00703 st.addFocalGradient<FocalGradient>(fs, mat, cx);
00704 return;
00705 }
00706 st.addRadialGradient<RadialGradient>(fs, mat, cx);
00707 }
00708 }
00709
00710 template<typename Spread>
00711 void
00712 storeGradient(StyleHandler& st, const GradientFill& fs, const SWFMatrix& mat,
00713 const cxform& cx)
00714 {
00715
00716 switch (fs.interpolation) {
00717 default:
00718 storeGradient<Spread, InterpolatorRGB>(st, fs, mat, cx);
00719 break;
00720 }
00721
00722 }
00723
00724 void
00725 storeGradient(StyleHandler& st, const GradientFill& fs, const SWFMatrix& mat,
00726 const cxform& cx)
00727 {
00728
00729 switch (fs.spreadMode) {
00730 case GradientFill::PAD:
00731 storeGradient<Pad>(st, fs, mat, cx);
00732 break;
00733 case GradientFill::REFLECT:
00734 storeGradient<Reflect>(st, fs, mat, cx);
00735 break;
00736 case GradientFill::REPEAT:
00737 storeGradient<Repeat>(st, fs, mat, cx);
00738 break;
00739 }
00740 }
00741
00742 }
00743
00744 }
00745
00746 #endif // BACKEND_RENDER_HANDLER_AGG_STYLE_H