[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Gnash-commit] /srv/bzr/gnash/trunk r12351: Add support for spread modes
From: |
Benjamin Wolsey |
Subject: |
[Gnash-commit] /srv/bzr/gnash/trunk r12351: Add support for spread modes in the AGG renderer. Implement for static and |
Date: |
Thu, 05 Aug 2010 18:02:32 +0200 |
User-agent: |
Bazaar (2.0.3) |
------------------------------------------------------------
revno: 12351 [merge]
committer: Benjamin Wolsey <address@hidden>
branch nick: trunk
timestamp: Thu 2010-08-05 18:02:32 +0200
message:
Add support for spread modes in the AGG renderer. Implement for static and
dynamic gradients.
modified:
libcore/FillStyle.cpp
libcore/FillStyle.h
libcore/asobj/MovieClip_as.cpp
librender/Renderer_agg.cpp
librender/Renderer_agg_style.h
testsuite/misc-ming.all/GradientFillTest.as
=== modified file 'libcore/FillStyle.cpp'
--- a/libcore/FillStyle.cpp 2010-08-03 19:15:45 +0000
+++ b/libcore/FillStyle.cpp 2010-08-05 14:36:40 +0000
@@ -100,7 +100,7 @@
GradientFill::GradientFill(Type t, const SWFMatrix& m,
const GradientRecords& recs)
:
- spreadMode(SWF::GRADIENT_SPREAD_PAD),
+ spreadMode(PAD),
interpolation(SWF::GRADIENT_INTERPOLATION_NORMAL),
_focalPoint(0.0),
_gradients(recs),
@@ -295,9 +295,13 @@
switch (spread) {
case SWF::GRADIENT_SPREAD_PAD:
+ gf.spreadMode = GradientFill::PAD;
+ break;
case SWF::GRADIENT_SPREAD_REFLECT:
+ gf.spreadMode = GradientFill::REFLECT;
+ break;
case SWF::GRADIENT_SPREAD_REPEAT:
- gf.spreadMode = spread;
+ gf.spreadMode = GradientFill::REPEAT;
break;
default:
IF_VERBOSE_MALFORMED_SWF(
=== modified file 'libcore/FillStyle.h'
--- a/libcore/FillStyle.h 2010-08-03 19:15:45 +0000
+++ b/libcore/FillStyle.h 2010-08-05 14:36:40 +0000
@@ -171,12 +171,17 @@
/// The type of GradientFill
//
/// A Focal fill is a gradient fill with a focal point.
- enum Type
- {
+ enum Type {
LINEAR,
RADIAL
};
+ enum SpreadMode {
+ PAD,
+ REPEAT,
+ REFLECT
+ };
+
typedef std::vector<GradientRecord> GradientRecords;
/// Construct a GradientFill
@@ -229,7 +234,7 @@
return _focalPoint;
}
- SWF::SpreadMode spreadMode;
+ SpreadMode spreadMode;
SWF::InterpolationMode interpolation;
private:
=== modified file 'libcore/asobj/MovieClip_as.cpp'
--- a/libcore/asobj/MovieClip_as.cpp 2010-08-03 16:53:57 +0000
+++ b/libcore/asobj/MovieClip_as.cpp 2010-08-05 14:36:40 +0000
@@ -1858,6 +1858,15 @@
GradientFill fd(t, mat.invert(), gradients);
+ // Set spread mode if present. Defaults to "pad", which is GradientFill's
+ // default.
+ if (fn.nargs > 5) {
+ const std::string& spread = fn.arg(5).to_string();
+ if (spread == "reflect") fd.spreadMode = GradientFill::REFLECT;
+ else if (spread == "repeat") fd.spreadMode = GradientFill::REPEAT;
+ else assert(fd.spreadMode == GradientFill::PAD);
+ }
+
/// TODO: set interpolation mode and spread mode.
/// Add a focus if present.
=== modified file 'librender/Renderer_agg.cpp'
--- a/librender/Renderer_agg.cpp 2010-08-03 16:40:04 +0000
+++ b/librender/Renderer_agg.cpp 2010-08-05 14:36:40 +0000
@@ -672,96 +672,6 @@
};
-/// Style handler
-//
-/// Transfer FillStyles to agg styles.
-struct StyleHandler : boost::static_visitor<>
-{
- StyleHandler(SWFMatrix stage, SWFMatrix fill, const cxform& c,
- agg_style_handler& sh, Quality q)
- :
- _stageMatrix(stage.invert()),
- _fillMatrix(fill.invert()),
- _cx(c),
- _sh(sh),
- _quality(q)
- {}
-
- void operator()(const GradientFill& f) const {
- SWFMatrix m = f.matrix();
-
- m.concatenate(_fillMatrix);
- m.concatenate(_stageMatrix);
- switch (f.type()) {
- case GradientFill::LINEAR:
- _sh.add_gradient_linear(f, m, _cx);
- break;
- case GradientFill::RADIAL:
- if (f.focalPoint()) {
- _sh.add_gradient_focal(f, m, _cx);
- }
- else {
- _sh.add_gradient_radial(f, m, _cx);
- }
- break;
- }
- }
-
- void operator()(const SolidFill& f) const {
- const rgba color = _cx.transform(f.color());
-
- // add the color to our self-made style handler (basically
- // just a list)
- _sh.add_color(agg::rgba8_pre(color.m_r, color.m_g, color.m_b,
- color.m_a));
- }
-
- void operator()(const BitmapFill& f) const {
- SWFMatrix m = f.matrix();
- m.concatenate(_fillMatrix);
- m.concatenate(_stageMatrix);
-
- // Smoothing policy:
- //
- // - If unspecified, smooth when _quality >= BEST
- // - If ON or forced, smooth when _quality > LOW
- // - If OFF, don't smooth
- //
- // TODO: take a forceBitmapSmoothing parameter.
- // which should be computed by the VM looking
- // at MovieClip.forceSmoothing.
- bool smooth = false;
- if (_quality > QUALITY_LOW) {
- // TODO: if forceSmoothing is true, smooth !
- switch (f.smoothingPolicy()) {
- case BitmapFill::SMOOTHING_UNSPECIFIED:
- if (_quality >= QUALITY_BEST) smooth = true;
- break;
- case BitmapFill::SMOOTHING_ON:
- smooth = true;
- break;
- default: break;
- }
- }
-
- const bool tiled = (f.type() == BitmapFill::TILED);
-
- _sh.add_bitmap(
- dynamic_cast<const agg_bitmap_info*>(f.bitmap()), m, _cx, tiled,
- smooth);
- }
-
-private:
-
- /// The inverted stage matrix.
- const SWFMatrix _stageMatrix;
-
- /// The inverted fill matrix.
- const SWFMatrix _fillMatrix;
- const cxform& _cx;
- agg_style_handler& _sh;
- const Quality _quality;
-};
}
@@ -1125,7 +1035,7 @@
std::vector<FillStyle> v(1, FillStyle(SolidFill(color)));
// prepare style handler
- agg_style_handler sh;
+ StyleHandler sh;
build_agg_styles(sh, v, mat, cxform());
draw_shape(-1, paths, agg_paths, sh, false);
@@ -1260,7 +1170,7 @@
}
// prepare fill styles
- agg_style_handler sh;
+ StyleHandler sh;
if (have_shape) build_agg_styles(sh, FillStyles, mat, cx);
// We need to separate sub-shapes during rendering.
@@ -1477,7 +1387,7 @@
} //buildPaths_rounded
// Initializes the internal styles class for AGG renderer
- void build_agg_styles(agg_style_handler& sh,
+ void build_agg_styles(StyleHandler& sh,
const std::vector<FillStyle>& FillStyles,
const SWFMatrix& fillstyle_matrix, const cxform& cx) {
@@ -1487,7 +1397,7 @@
const size_t fcount = FillStyles.size();
for (size_t fno = 0; fno < fcount; ++fno) {
- const StyleHandler st(stage_matrix, fillstyle_matrix, cx, sh,
+ const AddStyles st(stage_matrix, fillstyle_matrix, cx, sh,
_quality);
boost::apply_visitor(st, FillStyles[fno].fill);
}
@@ -1511,7 +1421,7 @@
///
void draw_shape(int subshape_id, const GnashPaths &paths,
const AggPaths& agg_paths,
- agg_style_handler& sh, bool even_odd) {
+ StyleHandler& sh, bool even_odd) {
if (_alphaMasks.empty()) {
@@ -1545,7 +1455,7 @@
template <class scanline_type>
void draw_shape_impl(int subshape_id, const GnashPaths &paths,
const AggPaths& agg_paths,
- agg_style_handler& sh, bool even_odd, scanline_type& sl) {
+ StyleHandler& sh, bool even_odd, scanline_type& sl) {
/*
Fortunately, AGG provides a rasterizer that fits perfectly to the flash
data model. So we just have to feed AGG with all data and we're done. :-)
=== modified file 'librender/Renderer_agg_style.h'
--- a/librender/Renderer_agg_style.h 2010-07-31 16:32:49 +0000
+++ b/librender/Renderer_agg_style.h 2010-08-05 15:28:36 +0000
@@ -31,56 +31,261 @@
// for debugging hidden characters.
//#define DEBUG_LIMIT_COLOR_ALPHA
+#include "GnashAlgorithm.h"
+#include "FillStyle.h"
namespace gnash {
+class StyleHandler;
+
+// Forward declarations.
+namespace {
+
+ /// Creates 8 bitmap functions
+ template<typename FillMode, typename Pixel>
+ void storeBitmap(StyleHandler& st, const agg_bitmap_info* bi,
+ const SWFMatrix& mat, const cxform& cx,
+ bool smooth);
+ template<typename FillMode> void storeBitmap(StyleHandler& st,
+ const agg_bitmap_info* bi, const SWFMatrix& mat, const cxform& cx,
+ bool smooth);
+
+ /// Creates many (should be 18) gradient functions.
+ void storeGradient(StyleHandler& st, const GradientFill& fs,
+ const SWFMatrix& mat, const cxform& cx);
+ template<typename Spread> void storeGradient(StyleHandler& st,
+ const GradientFill& fs, const SWFMatrix& mat, const cxform& cx);
+ template<typename Spread, typename Interpolation>
+ void storeGradient(StyleHandler& st, const GradientFill& fs,
+ const SWFMatrix& mat, const cxform& cx);
+}
+
/// Internal style class that represents a fill style. Roughly speaking, AGG
/// computes the fill areas of a flash composite shape and calls generate_span
/// to generate small horizontal pixel rows. generate_span provides whatever
/// fill pattern for that coordinate.
-class agg_style_base
+class AggStyle
{
public:
-
- agg_style_base(bool solid, const agg::rgba8& color = agg::rgba8(0,0,0,0))
- :
- _solid(solid),
- _color(color)
- {
- }
-
- // Everytime a class has a virtual method it should
- // also have a virtual destructor. This will ensure
- // that the destructor for the *derived* class is invoked
- // when deleting a pointer to base class !!
- virtual ~agg_style_base() {}
-
- bool solid() const { return _solid; }
-
- agg::rgba8 color() const { return _color; }
-
- // for non-solid styles:
- virtual void generate_span(agg::rgba8* span, int x, int y, unsigned len) = 0;
-
+ AggStyle(bool solid, const agg::rgba8& color = agg::rgba8(0,0,0,0))
+ :
+ _solid(solid),
+ _color(color)
+ {
+ }
+
+ // Everytime a class has a virtual method it should
+ // also have a virtual destructor. This will ensure
+ // that the destructor for the *derived* class is invoked
+ // when deleting a pointer to base class !!
+ virtual ~AggStyle() {}
+ bool solid() const { return _solid; }
+ agg::rgba8 color() const { return _color; }
+
+ // for non-solid styles:
+ virtual void generate_span(agg::rgba8* span, int x, int y,
+ unsigned len) = 0;
+
private:
-
- // for solid styles:
- const bool _solid;
-
- const agg::rgba8 _color;
-
+ // for solid styles:
+ const bool _solid;
+ const agg::rgba8 _color;
+};
+
+namespace {
+
+/// Tile bitmap fills.
+struct Tile
+{
+ template<typename P> struct Type {
+ typedef agg::wrap_mode_repeat Wrap;
+ typedef agg::image_accessor_wrap<P, Wrap, Wrap> type;
+ };
+};
+
+/// Clip bitmap fills.
+struct Clip
+{
+ template<typename P> struct Type {
+ typedef agg::image_accessor_clone<P> type;
+ };
+};
+
+/// Base class for filter types.
+template<typename P, typename W>
+struct FilterType
+{
+ typedef P PixelFormat;
+ typedef typename W::template Type<PixelFormat>::type SourceType;
+ typedef agg::span_allocator<PixelFormat> Allocator;
+ typedef agg::span_interpolator_linear<agg::trans_affine> Interpolator;
+};
+
+/// Nearest Neighbour filter type for quick, lower quality scaling.
+template<typename P, typename W>
+struct NN : public FilterType<P, W>
+{
+ typedef FilterType<P, W> BaseType;
+ typedef agg::span_image_filter_rgb_nn<
+ typename BaseType::SourceType,
+ typename BaseType::Interpolator> Generator;
+};
+
+/// Bilinear filter type for higher quality scaling.
+template<typename P, typename W>
+struct AA : public FilterType<P, W>
+{
+ typedef FilterType<P, W> BaseType;
+ typedef agg::span_image_filter_rgb_bilinear<
+ typename BaseType::SourceType,
+ typename BaseType::Interpolator> Generator;
+};
+
+/// A reflecting adaptor for Gradients.
+struct Reflect
+{
+ template<typename T> struct Type {
+ typedef agg::gradient_reflect_adaptor<T> type;
+ };
+};
+
+/// A repeating adaptor for Gradients.
+struct Repeat
+{
+ template<typename T> struct Type {
+ typedef agg::gradient_repeat_adaptor<T> type;
+ };
+};
+
+/// A padding (default) adaptor for Gradients.
+struct Pad
+{
+ template<typename T> struct Type {
+ typedef T type;
+ };
+};
+
+/// The default RGB color interpolator
+struct InterpolatorRGB
+{
+ template<typename Pixel> struct Type {
+ typedef agg::gradient_lut<agg::color_interpolator<Pixel>, 256> type;
+ };
+};
+
+/// AGG gradient fill style. Don't use Gnash texture bitmaps as this is slower
+/// and less accurate. Even worse, the bitmap fill would need to be tweaked
+/// to have non-repeating gradients (first and last color stops continue
+/// forever on each side). This class can be used for any kind of gradient, so
+/// even focal gradients should be possible.
+template <class Color, class Allocator, class Interpolator, class GradientType,
+ class Adaptor, class ColorInterpolator, class SpanGenerator>
+class GradientStyle : public AggStyle
+{
+public:
+
+ GradientStyle(const GradientFill& fs, const SWFMatrix& mat,
+ const cxform& cx, int norm_size, GradientType gr = GradientType())
+ :
+ AggStyle(false),
+ m_cx(cx),
+ m_tr(mat.sx / 65536.0, mat.shx/65536.0, mat.shy / 65536.0,
+ mat.sy / 65536.0, mat.tx, mat.ty),
+ m_span_interpolator(m_tr),
+ m_gradient_adaptor(gr),
+ m_sg(m_span_interpolator, m_gradient_adaptor, m_gradient_lut, 0,
+ norm_size),
+
+ m_need_premultiply(false)
+ {
+ // Build gradient lookup table
+ m_gradient_lut.remove_all();
+ const size_t size = fs.recordCount();
+
+ // It is essential that at least two colours are added; otherwise agg
+ // will use uninitialized values.
+ assert(size > 1);
+
+ for (size_t i = 0; i != size; ++i) {
+ const GradientRecord& gr = fs.record(i);
+ const rgba tr = m_cx.transform(gr.color);
+ if (tr.m_a < 255) m_need_premultiply = true;
+ m_gradient_lut.add_color(gr.ratio/255.0,
+ agg::rgba8(tr.m_r, tr.m_g, tr.m_b, tr.m_a));
+ }
+ m_gradient_lut.build_lut();
+
+ } // GradientStyle constructor
+
+ virtual ~GradientStyle() { }
+
+ void generate_span(Color* span, int x, int y, unsigned len) {
+ m_sg.generate(span, x, y, len);
+ if (!m_need_premultiply) return;
+
+ while (len--) {
+ span->premultiply();
+ ++span;
+ }
+ }
+
+protected:
+
+ // Color transform
+ gnash::cxform m_cx;
+
+ // Span allocator
+ Allocator m_sa;
+
+ // Transformer
+ agg::trans_affine m_tr;
+
+ // Span interpolator
+ Interpolator m_span_interpolator;
+
+ // Gradient adaptor
+ Adaptor m_gradient_adaptor;
+
+ // Gradient LUT
+ ColorInterpolator m_gradient_lut;
+
+ // Span generator
+ SpanGenerator m_sg;
+
+ // premultiplication necessary?
+ bool m_need_premultiply;
+};
+
+/// A set of typedefs for a Gradient
+//
+/// @tparam G An agg gradient type
+/// @tparam A The type of Adaptor: see Reflect, Repeat, Pad
+/// @tparam I The type of ColorInterpolator: see InterpolatorRGB
+template<typename G, typename A, typename I>
+struct Gradient
+{
+ typedef agg::rgba8 Color;
+ typedef G GradientType;
+ typedef typename A::template Type<G>::type Adaptor;
+ typedef typename I::template Type<Color>::type ColorInterpolator;
+ typedef agg::span_allocator<Color> Allocator;
+ typedef agg::span_interpolator_linear<agg::trans_affine> Interpolator;
+ typedef agg::span_gradient<Color, Interpolator, Adaptor,
+ ColorInterpolator> Generator;
+ typedef GradientStyle<Color, Allocator, Interpolator, GradientType,
+ Adaptor, ColorInterpolator, Generator> Type;
};
/// Solid AGG fill style. generate_span is not used in this case as AGG does
/// solid fill styles internally.
-class agg_style_solid : public agg_style_base
+class SolidStyle : public AggStyle
{
public:
- agg_style_solid(const agg::rgba8& color)
+ SolidStyle(const agg::rgba8& color)
:
- agg_style_base(true, color)
+ AggStyle(true, color)
{
}
@@ -92,23 +297,20 @@
};
-#define image_accessor_clip_transp agg::image_accessor_clone
-
-
/// AGG bitmap fill style. There are quite a few combinations possible and so
/// the class types are defined outside. The bitmap can be tiled or clipped.
/// It can have any transformation SWFMatrix and color transform. Any pixel
format
/// can be used, too.
-template <class PixelFormat, class span_allocator_type, class img_source_type,
- class interpolator_type, class sg_type>
-class agg_style_bitmap : public agg_style_base
+template <class PixelFormat, class Allocator, class SourceType,
+ class Interpolator, class Generator>
+class BitmapStyle : public AggStyle
{
public:
- agg_style_bitmap(int width, int height, int rowlen, boost::uint8_t* data,
+ BitmapStyle(int width, int height, int rowlen, boost::uint8_t* data,
const gnash::SWFMatrix& mat, const gnash::cxform& cx)
:
- agg_style_base(false),
+ AggStyle(false),
m_cx(cx),
m_rbuf(data, width, height, rowlen),
m_pixf(m_rbuf),
@@ -125,7 +327,7 @@
// class as this should be faster (avoid type conversion).
}
- virtual ~agg_style_bitmap() {
+ virtual ~BitmapStyle() {
}
void generate_span(agg::rgba8* span, int x, int y, unsigned len)
@@ -134,7 +336,7 @@
// Apply color transform
// TODO: Check if this can be optimized
if (m_cx.is_identity()) return;
- for (unsigned int i=0; i<len; i++) {
+ for (unsigned int i=0; i < len; i++) {
m_cx.transform(span->r, span->g, span->b, span->a);
span->premultiply();
++span;
@@ -143,136 +345,30 @@
private:
- // Color transform
- gnash::cxform m_cx;
+ // Color transform
+ gnash::cxform m_cx;
- // Pixel access
- agg::rendering_buffer m_rbuf;
- PixelFormat m_pixf;
-
- // Span allocator
- span_allocator_type m_sa;
-
- // Image accessor
- img_source_type m_img_src;
-
- // Transformer
- agg::trans_affine m_tr;
-
- // Interpolator
- interpolator_type m_interpolator;
-
- // Span generator
- sg_type m_sg;
+ // Pixel access
+ agg::rendering_buffer m_rbuf;
+ PixelFormat m_pixf;
+
+ // Span allocator
+ Allocator m_sa;
+
+ // Image accessor
+ SourceType m_img_src;
+
+ // Transformer
+ agg::trans_affine m_tr;
+
+ // Interpolator
+ Interpolator m_interpolator;
+
+ // Span generator
+ Generator m_sg;
};
-
-/// AGG gradient fill style. Don't use Gnash texture bitmaps as this is slower
-/// and less accurate. Even worse, the bitmap fill would need to be tweaked
-/// to have non-repeating gradients (first and last color stops continue
-/// forever on each side). This class can be used for any kind of gradient, so
-/// even focal gradients should be possible.
-template <class color_type, class span_allocator_type, class
interpolator_type,
- class gradient_func_type, class gradient_adaptor_type, class
color_func_type,
- class sg_type>
-class agg_style_gradient : public agg_style_base
-{
-public:
-
- agg_style_gradient(const GradientFill& fs, const SWFMatrix& mat,
- const cxform& cx, int norm_size)
- :
- agg_style_base(false),
- m_cx(cx),
- m_tr(mat.sx / 65536.0, mat.shx/65536.0, mat.shy / 65536.0,
- mat.sy / 65536.0, mat.tx, mat.ty),
- m_span_interpolator(m_tr),
- m_gradient_func(),
- m_gradient_adaptor(m_gradient_func),
- m_sg(m_span_interpolator, m_gradient_adaptor, m_gradient_lut, 0,
norm_size),
- m_need_premultiply(false)
- {
- // Build gradient lookup table
- m_gradient_lut.remove_all();
-
- const size_t size = fs.recordCount();
-
- // It is essential that at least two colours are added; otherwise agg
- // will use uninitialized values.
- assert(size > 1);
-
- for (int i = 0; i != size; ++i) {
-
- const GradientRecord& gr = fs.record(i);
- rgba trans_color = m_cx.transform(gr.color);
- if (trans_color.m_a < 255) m_need_premultiply = true;
-
- m_gradient_lut.add_color(gr.ratio/255.0, agg::rgba8(trans_color.m_r,
- trans_color.m_g, trans_color.m_b, trans_color.m_a));
-
- } // for
-
- m_gradient_lut.build_lut();
-
- } // agg_style_gradient constructor
-
-
- virtual ~agg_style_gradient()
- {
- }
-
-
- void generate_span(color_type* span, int x, int y, unsigned len)
- {
- m_sg.generate(span, x, y, len);
-
- if (!m_need_premultiply) return;
-
- while (len--) {
- span->premultiply();
- ++span;
- }
- }
-
- // Provide access to our gradient adaptor to allow re-initialization of
- // focal gradients. I wanted to do this using partial template specialization
- // but it became too complex for something that can be solved in a very easy
- // (slightly unelegant) way.
- gradient_adaptor_type& get_gradient_adaptor() {
- return m_gradient_adaptor;
- }
-
-protected:
-
- // Color transform
- gnash::cxform m_cx;
-
- // Span allocator
- span_allocator_type m_sa;
-
- // Transformer
- agg::trans_affine m_tr;
-
- // Span interpolator
- interpolator_type m_span_interpolator;
-
- gradient_func_type m_gradient_func;
-
- // Gradient adaptor
- gradient_adaptor_type m_gradient_adaptor;
-
- // Gradient LUT
- color_func_type m_gradient_lut;
-
- // Span generator
- sg_type m_sg;
-
- // premultiplication necessary?
- bool m_need_premultiply;
-
-}; // agg_style_gradient
-
-
+}
// --- AGG HELPER CLASSES
------------------------------------------------------
@@ -280,397 +376,100 @@
/// Style handler for AGG's compound rasterizer. This is the class which is
/// called by AGG itself. It provides an interface to the various fill style
/// classes defined above.
-class agg_style_handler
+class StyleHandler
{
public:
- agg_style_handler() :
+ StyleHandler() :
m_transparent(0, 0, 0, 0)
{}
- ~agg_style_handler() {
- int styles_size = m_styles.size();
- for (int i=0; i<styles_size; i++)
- delete m_styles[i];
+ ~StyleHandler() {
+ deleteChecked(_styles.begin(), _styles.end());
}
/// Called by AGG to ask if a certain style is a solid color
bool is_solid(unsigned style) const {
- assert(style < m_styles.size());
- return m_styles[style]->solid();
+ assert(style < _styles.size());
+ return _styles[style]->solid();
}
/// Adds a new solid fill color style
void add_color(const agg::rgba8& color) {
- agg_style_solid *st = new agg_style_solid(color);
- m_styles.push_back(st);
+ SolidStyle *st = new SolidStyle(color);
+ _styles.push_back(st);
}
-
+
/// Adds a new bitmap fill style
void add_bitmap(const agg_bitmap_info* bi, const gnash::SWFMatrix& mat,
- const gnash::cxform& cx, bool repeat, bool smooth)
- {
-
- if (!bi) {
- // See server/styles.h comments about when NULL return is possible.
- // Don't warn here, we already warn at parse-time
- //log_debug("WARNING: add_bitmap called with bi=NULL");
- add_color(agg::rgba8_pre(0,0,0,0));
- return;
- }
-
- // Whew! There are 8 bitmap combinations (bpp, smooth, repeat) possible
- // and AGG uses templates, so...
- // I'd need to pass "span_image_filter_rgba_nn" (because span_image_xxx
- // dependends on the pixel format) without passing the template
- // parameters, but AFAIK this can't be done. But hey, this is my first
- // C++ code (the whole AGG backend) and I immediately had to start with
- // templates. I'm giving up and write eight versions of add_bitmap_xxx.
- // So, if anyone has a better solution, for heaven's sake, implement
it!!
-
- if (repeat) {
- if (smooth) {
-
- if (bi->get_bpp()==24)
- add_bitmap_repeat_aa_rgb24 (bi, mat, cx);
- else
- if (bi->get_bpp()==32)
- add_bitmap_repeat_aa_rgba32 (bi, mat, cx);
- else
- abort();
-
- } else {
-
- if (bi->get_bpp()==24)
- add_bitmap_repeat_nn_rgb24 (bi, mat, cx);
- else
- if (bi->get_bpp()==32)
- add_bitmap_repeat_nn_rgba32 (bi, mat, cx);
- else
- abort();
-
- } // if smooth
- } else {
- if (smooth) {
-
- if (bi->get_bpp()==24)
- add_bitmap_clip_aa_rgb24 (bi, mat, cx);
- else
- if (bi->get_bpp()==32)
- add_bitmap_clip_aa_rgba32 (bi, mat, cx);
- else
- abort();
-
- } else {
-
- if (bi->get_bpp()==24)
- add_bitmap_clip_nn_rgb24 (bi, mat, cx);
- else
- if (bi->get_bpp()==32)
- add_bitmap_clip_nn_rgba32 (bi, mat, cx);
- else
- abort();
-
- } // if smooth
- } // if repeat
-
- } // add_bitmap
-
-
- // === RGB24 ===
-
-
- void add_bitmap_repeat_nn_rgb24(const agg_bitmap_info* bi,
- const gnash::SWFMatrix& mat, const gnash::cxform& cx)
- {
-
- // tiled, nearest neighbor method (faster)
-
- typedef agg::pixfmt_rgb24_pre PixelFormat;
- typedef agg::span_allocator<PixelFormat> span_allocator_type;
- typedef agg::wrap_mode_repeat wrap_type;
- typedef agg::image_accessor_wrap<PixelFormat, wrap_type, wrap_type>
img_source_type;
- typedef agg::span_interpolator_linear_subdiv<agg::trans_affine>
interpolator_type;
- typedef agg::span_image_filter_rgb_nn<img_source_type,
interpolator_type> sg_type;
-
- typedef agg_style_bitmap<PixelFormat, span_allocator_type,
img_source_type,
- interpolator_type, sg_type> st_type;
-
- st_type* st = new st_type(bi->get_width(), bi->get_height(),
- bi->get_rowlen(), bi->get_data(), mat, cx);
-
- m_styles.push_back(st);
- }
-
-
-
-
- void add_bitmap_clip_nn_rgb24(const agg_bitmap_info* bi,
- const gnash::SWFMatrix& mat, const gnash::cxform& cx)
- {
-
- // clipped, nearest neighbor method (faster)
-
- typedef agg::pixfmt_rgb24_pre PixelFormat;
- typedef agg::span_allocator<PixelFormat> span_allocator_type;
- typedef image_accessor_clip_transp<PixelFormat> img_source_type;
- typedef agg::span_interpolator_linear_subdiv<agg::trans_affine>
interpolator_type;
- typedef agg::span_image_filter_rgb_nn<img_source_type,
interpolator_type> sg_type;
-
- typedef agg_style_bitmap<PixelFormat, span_allocator_type,
img_source_type,
- interpolator_type, sg_type> st_type;
-
- st_type* st = new st_type(bi->get_width(), bi->get_height(),
- bi->get_rowlen(), bi->get_data(), mat, cx);
-
- m_styles.push_back(st);
- }
-
-
-
- void add_bitmap_repeat_aa_rgb24(const agg_bitmap_info* bi,
- const gnash::SWFMatrix& mat, const gnash::cxform& cx)
- {
-
- // tiled, bilinear method (better quality)
-
- typedef agg::pixfmt_rgb24_pre PixelFormat;
- typedef agg::span_allocator<PixelFormat> span_allocator_type;
- typedef agg::wrap_mode_repeat wrap_type;
- typedef agg::image_accessor_wrap<PixelFormat, wrap_type, wrap_type>
img_source_type;
- typedef agg::span_interpolator_linear_subdiv<agg::trans_affine>
interpolator_type;
- typedef agg::span_image_filter_rgb_bilinear<img_source_type,
interpolator_type> sg_type;
-
- typedef agg_style_bitmap<PixelFormat, span_allocator_type,
img_source_type,
- interpolator_type, sg_type> st_type;
-
- st_type* st = new st_type(bi->get_width(), bi->get_height(),
- bi->get_rowlen(), bi->get_data(), mat, cx);
-
- m_styles.push_back(st);
- }
-
-
- void add_bitmap_clip_aa_rgb24(const agg_bitmap_info* bi,
- const gnash::SWFMatrix& mat, const gnash::cxform& cx)
- {
-
- // clipped, bilinear method (better quality)
-
- typedef agg::pixfmt_rgb24_pre PixelFormat;
- typedef agg::span_allocator<PixelFormat> span_allocator_type;
- typedef image_accessor_clip_transp<PixelFormat> img_source_type;
- typedef agg::span_interpolator_linear_subdiv<agg::trans_affine>
interpolator_type;
- typedef agg::span_image_filter_rgb_bilinear<img_source_type,
interpolator_type> sg_type;
-
- typedef agg_style_bitmap<PixelFormat, span_allocator_type,
img_source_type,
- interpolator_type, sg_type> st_type;
-
- st_type* st = new st_type(bi->get_width(), bi->get_height(),
- bi->get_rowlen(), bi->get_data(), mat, cx);
-
- m_styles.push_back(st);
- }
-
-
-
- // === RGBA32 ===
-
- void add_bitmap_repeat_nn_rgba32(const agg_bitmap_info* bi,
- const gnash::SWFMatrix& mat, const gnash::cxform& cx)
- {
-
- // tiled, nearest neighbor method (faster)
-
- typedef agg::pixfmt_rgba32_pre PixelFormat;
- typedef agg::span_allocator<PixelFormat> span_allocator_type;
- typedef agg::wrap_mode_repeat wrap_type;
- typedef agg::image_accessor_wrap<PixelFormat, wrap_type, wrap_type>
img_source_type;
- typedef agg::span_interpolator_linear_subdiv<agg::trans_affine>
interpolator_type;
- typedef agg::span_image_filter_rgba_nn<img_source_type,
interpolator_type> sg_type;
-
- typedef agg_style_bitmap<PixelFormat, span_allocator_type,
img_source_type,
- interpolator_type, sg_type> st_type;
-
- st_type* st = new st_type(bi->get_width(), bi->get_height(),
- bi->get_rowlen(), bi->get_data(), mat, cx);
-
- m_styles.push_back(st);
- }
-
-
-
-
- void add_bitmap_clip_nn_rgba32(const agg_bitmap_info* bi,
- const gnash::SWFMatrix& mat, const gnash::cxform& cx)
- {
-
- // clipped, nearest neighbor method (faster)
-
- typedef agg::pixfmt_rgba32_pre PixelFormat;
- typedef agg::span_allocator<PixelFormat> span_allocator_type;
- typedef image_accessor_clip_transp<PixelFormat> img_source_type;
- typedef agg::span_interpolator_linear_subdiv<agg::trans_affine>
interpolator_type;
- typedef agg::span_image_filter_rgba_nn<img_source_type,
interpolator_type> sg_type;
-
- typedef agg_style_bitmap<PixelFormat, span_allocator_type,
img_source_type,
- interpolator_type, sg_type> st_type;
-
- st_type* st = new st_type(bi->get_width(), bi->get_height(),
- bi->get_rowlen(), bi->get_data(), mat, cx);
-
- m_styles.push_back(st);
- }
-
-
-
- void add_bitmap_repeat_aa_rgba32(const agg_bitmap_info* bi,
- const gnash::SWFMatrix& mat, const gnash::cxform& cx)
- {
-
- // tiled, bilinear method (better quality)
-
- typedef agg::pixfmt_rgba32_pre PixelFormat;
- typedef agg::span_allocator<PixelFormat> span_allocator_type;
- typedef agg::wrap_mode_repeat wrap_type;
- typedef agg::image_accessor_wrap<PixelFormat, wrap_type, wrap_type>
img_source_type;
- typedef agg::span_interpolator_linear_subdiv<agg::trans_affine>
interpolator_type;
- typedef agg::span_image_filter_rgba_bilinear<img_source_type,
interpolator_type> sg_type;
-
- typedef agg_style_bitmap<PixelFormat, span_allocator_type,
img_source_type,
- interpolator_type, sg_type> st_type;
-
- st_type* st = new st_type(bi->get_width(), bi->get_height(),
- bi->get_rowlen(), bi->get_data(), mat, cx);
-
- m_styles.push_back(st);
- }
-
-
- void add_bitmap_clip_aa_rgba32(const agg_bitmap_info* bi,
- const gnash::SWFMatrix& mat, const gnash::cxform& cx)
- {
-
- // clipped, bilinear method (better quality)
-
- typedef agg::pixfmt_rgba32_pre PixelFormat;
- typedef agg::span_allocator<PixelFormat> span_allocator_type;
- typedef image_accessor_clip_transp<PixelFormat> img_source_type;
- typedef agg::span_interpolator_linear_subdiv<agg::trans_affine>
interpolator_type;
- typedef agg::span_image_filter_rgba_bilinear<img_source_type,
interpolator_type> sg_type;
-
- typedef agg_style_bitmap<PixelFormat, span_allocator_type,
img_source_type,
- interpolator_type, sg_type> st_type;
-
- st_type* st = new st_type(bi->get_width(), bi->get_height(),
- bi->get_rowlen(), bi->get_data(), mat, cx);
-
- m_styles.push_back(st);
- }
-
-
- // === GRADIENT ===
-
- void add_gradient_linear(const GradientFill& fs,
- const gnash::SWFMatrix& mat, const gnash::cxform& cx)
- {
-
- typedef agg::rgba8 color_type;
- typedef agg::span_allocator<color_type> span_allocator_type;
- typedef agg::span_interpolator_linear<agg::trans_affine>
interpolator_type;
- typedef agg::gradient_x gradient_func_type;
- //typedef agg::gradient_repeat_adaptor<gradient_func_type>
gradient_adaptor_type;
- typedef gradient_func_type gradient_adaptor_type;
- typedef agg::gradient_lut<agg::color_interpolator<color_type>, 256>
color_func_type;
- typedef agg::span_gradient<color_type,
- interpolator_type,
- gradient_adaptor_type,
- color_func_type> sg_type;
-
- typedef agg_style_gradient<color_type, span_allocator_type,
- interpolator_type, gradient_func_type, gradient_adaptor_type,
- color_func_type, sg_type> st_type;
-
- st_type* st = new st_type(fs, mat, cx, 256);
-
- // NOTE: The value 256 is based on the bitmap texture used by other
- // Gnash renderers which is normally 256x1 pixels for linear gradients.
-
- m_styles.push_back(st);
- }
-
-
- void add_gradient_radial(const GradientFill& fs,
- const gnash::SWFMatrix& mat, const gnash::cxform& cx)
- {
-
- typedef agg::rgba8 color_type;
- typedef agg::span_allocator<color_type> span_allocator_type;
- typedef agg::span_interpolator_linear<agg::trans_affine>
- interpolator_type;
- typedef agg::gradient_radial gradient_func_type;
- typedef gradient_func_type gradient_adaptor_type;
- typedef agg::gradient_lut<agg::color_interpolator<color_type>, 256>
- color_func_type;
- typedef agg::span_gradient<color_type,
- interpolator_type,
- gradient_adaptor_type,
- color_func_type> sg_type;
-
- typedef agg_style_gradient<color_type, span_allocator_type,
- interpolator_type, gradient_func_type, gradient_adaptor_type,
- color_func_type, sg_type> st_type;
-
- // move the center of the radial fill to where it should be
- gnash::SWFMatrix transl;
- transl.set_translation(-32, -32);
- transl.concatenate(mat);
-
- // div 2 because we need radius, not diameter
- st_type* st = new st_type(fs, transl, cx, 64/2);
-
- // NOTE: The value 64 is based on the bitmap texture used by other
- // Gnash renderers which is normally 64x64 pixels for radial gradients.
-
- m_styles.push_back(st);
- }
-
- void add_gradient_focal(const GradientFill& fs,
- const gnash::SWFMatrix& mat, const gnash::cxform& cx)
- {
- typedef agg::rgba8 color_type;
- typedef agg::span_allocator<color_type> span_allocator_type;
- typedef agg::span_interpolator_linear<agg::trans_affine>
interpolator_type;
- typedef agg::gradient_radial_focus gradient_func_type;
- typedef gradient_func_type gradient_adaptor_type;
- typedef agg::gradient_lut<agg::color_interpolator<color_type>, 256>
color_func_type;
- typedef agg::span_gradient<color_type, interpolator_type,
- gradient_adaptor_type, color_func_type> sg_type;
-
- typedef agg_style_gradient<color_type, span_allocator_type,
- interpolator_type, gradient_func_type, gradient_adaptor_type,
- color_func_type, sg_type> st_type;
-
- // move the center of the focal fill (not its focal point) to where it
- // should be.
- gnash::SWFMatrix transl;
- transl.set_translation(-32, -32);
- transl.concatenate(mat);
-
- st_type* st = new st_type(fs, transl, cx, 64/2);
-
- // re-initialize focal gradient settings
- gradient_adaptor_type& adaptor = st->get_gradient_adaptor();
- adaptor.init(32.0, fs.focalPoint() * 32.0, 0.0);
-
- m_styles.push_back(st);
+ const gnash::cxform& cx, bool repeat, bool smooth) {
+
+ if (!bi) {
+ add_color(agg::rgba8_pre(0,0,0,0));
+ return;
+ }
+
+ // Tiled
+ if (repeat) {
+ storeBitmap<Tile>(*this, bi, mat, cx, smooth);
+ return;
+ }
+
+ storeBitmap<Clip>(*this, bi, mat, cx, smooth);
+ }
+
+ template<typename T>
+ void addLinearGradient(const GradientFill& fs, const gnash::SWFMatrix& mat,
+ const gnash::cxform& cx)
+ {
+ // NOTE: The value 256 is based on the bitmap texture used by other
+ // Gnash renderers which is normally 256x1 pixels for linear gradients.
+ typename T::Type* st = new typename T::Type(fs, mat, cx, 256);
+ _styles.push_back(st);
+ }
+
+ template<typename T>
+ void addFocalGradient(const GradientFill& fs, const gnash::SWFMatrix& mat,
+ const gnash::cxform& cx)
+ {
+ // move the center of the radial fill to where it should be
+ SWFMatrix transl;
+ transl.set_translation(-32, -32);
+ transl.concatenate(mat);
+
+ typename T::GradientType gr;
+ gr.init(32.0, fs.focalPoint() * 32.0, 0.0);
+
+ // div 2 because we need radius, not diameter
+ typename T::Type* st = new typename T::Type(fs, transl, cx, 64/2, gr);
+
+ // NOTE: The value 64 is based on the bitmap texture used by other
+ // Gnash renderers which is normally 64x64 pixels for radial gradients.
+ _styles.push_back(st);
+ }
+
+ template<typename T>
+ void addRadialGradient(const GradientFill& fs, const gnash::SWFMatrix& mat,
+ const gnash::cxform& cx)
+ {
+ // move the center of the radial fill to where it should be
+ SWFMatrix transl;
+ transl.set_translation(-32, -32);
+ transl.concatenate(mat);
+
+ // div 2 because we need radius, not diameter
+ typename T::Type* st = new typename T::Type(fs, transl, cx, 64 / 2);
+
+ // NOTE: The value 64 is based on the bitmap texture used by other
+ // Gnash renderers which is normally 64x64 pixels for radial gradients.
+ _styles.push_back(st);
}
/// Returns the color of a certain fill style (solid)
agg::rgba8 color(unsigned style) const
{
- if (style < m_styles.size())
- return m_styles[style]->color();
+ if (style < _styles.size())
+ return _styles[style]->color();
return m_transparent;
}
@@ -679,16 +478,37 @@
void generate_span(agg::rgba8* span, int x, int y,
unsigned len, unsigned style)
{
- m_styles[style]->generate_span(span,x,y,len);
- }
-
-
-private:
- std::vector<agg_style_base*> m_styles;
- agg::rgba8 m_transparent;
-}; // class agg_style_handler
-
-
+ _styles[style]->generate_span(span,x,y,len);
+ }
+
+
+ /// Add a bitmap with the specified filter
+ //
+ /// @tparam Filter The FilterType to use. This affects scaling
+ /// quality, pixel type etc.
+ template<typename Filter> void
+ addBitmap(const agg_bitmap_info* bi, const gnash::SWFMatrix& mat,
+ const gnash::cxform& cx)
+ {
+ typedef typename Filter::PixelFormat PixelFormat;
+ typedef typename Filter::Generator Generator;
+ typedef typename Filter::Allocator Allocator;
+ typedef typename Filter::SourceType SourceType;
+ typedef typename Filter::Interpolator Interpolator;
+
+ typedef BitmapStyle<PixelFormat, Allocator,
+ SourceType, Interpolator, Generator> Style;
+
+ Style* st = new Style(bi->get_width(), bi->get_height(),
+ bi->get_rowlen(), bi->get_data(), mat, cx);
+
+ _styles.push_back(st);
+ }
+
+ std::vector<AggStyle*> _styles;
+ agg::rgba8 m_transparent;
+
+};
class agg_mask_style_handler
{
@@ -720,6 +540,174 @@
}; // class agg_mask_style_handler
+/// Style handler
+//
+/// Transfer FillStyles to agg styles.
+struct AddStyles : boost::static_visitor<>
+{
+ AddStyles(SWFMatrix stage, SWFMatrix fill, const cxform& c,
+ StyleHandler& sh, Quality q)
+ :
+ _stageMatrix(stage.invert()),
+ _fillMatrix(fill.invert()),
+ _cx(c),
+ _sh(sh),
+ _quality(q)
+ {}
+
+ void operator()(const GradientFill& f) const {
+ SWFMatrix m = f.matrix();
+ m.concatenate(_fillMatrix);
+ m.concatenate(_stageMatrix);
+ storeGradient(_sh, f, m, _cx);
+ }
+
+ void operator()(const SolidFill& f) const {
+ const rgba color = _cx.transform(f.color());
+
+ // add the color to our self-made style handler (basically
+ // just a list)
+ _sh.add_color(agg::rgba8_pre(color.m_r, color.m_g, color.m_b,
+ color.m_a));
+ }
+
+ void operator()(const BitmapFill& f) const {
+ SWFMatrix m = f.matrix();
+ m.concatenate(_fillMatrix);
+ m.concatenate(_stageMatrix);
+
+ // Smoothing policy:
+ //
+ // - If unspecified, smooth when _quality >= BEST
+ // - If ON or forced, smooth when _quality > LOW
+ // - If OFF, don't smooth
+ //
+ // TODO: take a forceBitmapSmoothing parameter.
+ // which should be computed by the VM looking
+ // at MovieClip.forceSmoothing.
+ bool smooth = false;
+ if (_quality > QUALITY_LOW) {
+ // TODO: if forceSmoothing is true, smooth !
+ switch (f.smoothingPolicy()) {
+ case BitmapFill::SMOOTHING_UNSPECIFIED:
+ if (_quality >= QUALITY_BEST) smooth = true;
+ break;
+ case BitmapFill::SMOOTHING_ON:
+ smooth = true;
+ break;
+ default: break;
+ }
+ }
+
+ const bool tiled = (f.type() == BitmapFill::TILED);
+
+ _sh.add_bitmap(dynamic_cast<const agg_bitmap_info*>(f.bitmap()),
+ m, _cx, tiled, smooth);
+ }
+
+private:
+
+ /// The inverted stage matrix.
+ const SWFMatrix _stageMatrix;
+
+ /// The inverted fill matrix.
+ const SWFMatrix _fillMatrix;
+ const cxform& _cx;
+ StyleHandler& _sh;
+ const Quality _quality;
+};
+
+namespace {
+
+template<typename FillMode, typename Pixel>
+void
+storeBitmap(StyleHandler& st, const agg_bitmap_info* bi,
+ const SWFMatrix& mat, const cxform& cx, bool smooth)
+{
+ if (smooth) {
+ st.addBitmap<AA<Pixel, FillMode> >(bi, mat, cx);
+ return;
+ }
+ st.addBitmap<NN<Pixel, FillMode> >(bi, mat, cx);
+}
+
+template<typename FillMode>
+void
+storeBitmap(StyleHandler& st, const agg_bitmap_info* bi,
+ const SWFMatrix& mat, const cxform& cx, bool smooth)
+{
+ // Local typedefs for the handled formats.
+ typedef agg::pixfmt_rgba32_pre RGBA;
+ typedef agg::pixfmt_rgb24_pre RGB;
+
+ if (bi->get_bpp() == 24) {
+ storeBitmap<FillMode, RGB>(st, bi, mat, cx, smooth);
+ return;
+ }
+ storeBitmap<FillMode, RGBA>(st, bi, mat, cx, smooth);
+}
+
+template<typename Spread, typename Interpolation>
+void
+storeGradient(StyleHandler& st, const GradientFill& fs, const SWFMatrix& mat,
+ const cxform& cx)
+{
+
+ typedef agg::gradient_x Linear;
+ typedef agg::gradient_radial Radial;
+ typedef agg::gradient_radial_focus Focal;
+
+ typedef Gradient<Linear, Spread, Interpolation> LinearGradient;
+ typedef Gradient<Focal, Spread, Interpolation> FocalGradient;
+ typedef Gradient<Radial, Spread, Interpolation> RadialGradient;
+
+ switch (fs.type()) {
+ case GradientFill::LINEAR:
+ st.addLinearGradient<LinearGradient>(fs, mat, cx);
+ return;
+
+ case GradientFill::RADIAL:
+ if (fs.focalPoint()) {
+ st.addFocalGradient<FocalGradient>(fs, mat, cx);
+ return;
+ }
+ st.addRadialGradient<RadialGradient>(fs, mat, cx);
+ }
+}
+
+template<typename Spread>
+void
+storeGradient(StyleHandler& st, const GradientFill& fs, const SWFMatrix& mat,
+ const cxform& cx)
+{
+ // TODO: provide and use a linearRGB interpolator.
+ switch (fs.interpolation) {
+ default:
+ storeGradient<Spread, InterpolatorRGB>(st, fs, mat, cx);
+ break;
+ }
+
+}
+
+void
+storeGradient(StyleHandler& st, const GradientFill& fs, const SWFMatrix& mat,
+ const cxform& cx)
+{
+
+ switch (fs.spreadMode) {
+ case GradientFill::PAD:
+ storeGradient<Pad>(st, fs, mat, cx);
+ break;
+ case GradientFill::REFLECT:
+ storeGradient<Reflect>(st, fs, mat, cx);
+ break;
+ case GradientFill::REPEAT:
+ storeGradient<Repeat>(st, fs, mat, cx);
+ break;
+ }
+}
+
+}
} // namespace gnash
=== modified file 'testsuite/misc-ming.all/GradientFillTest.as'
--- a/testsuite/misc-ming.all/GradientFillTest.as 2010-07-31 07:49:37
+0000
+++ b/testsuite/misc-ming.all/GradientFillTest.as 2010-08-05 14:36:40
+0000
@@ -299,7 +299,7 @@
// Shape 22
x += 100;
- // Test a radial gradient with SWF8 args
+ // Test a focal gradient with SWF8 args
fillType = "radial";
colors = [0xffff00, 0x0000ff, 0x00ffff];
alphas = [100, 100, 100];
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Gnash-commit] /srv/bzr/gnash/trunk r12351: Add support for spread modes in the AGG renderer. Implement for static and,
Benjamin Wolsey <=