[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Gnash-commit] /srv/bzr/gnash/trunk r12346: Rewrite fill style handling
From: |
Benjamin Wolsey |
Subject: |
[Gnash-commit] /srv/bzr/gnash/trunk r12346: Rewrite fill style handling to make it easier to extend. Fix bug #26670 |
Date: |
Mon, 02 Aug 2010 09:54:02 +0200 |
User-agent: |
Bazaar (2.0.3) |
------------------------------------------------------------
revno: 12346 [merge]
committer: Benjamin Wolsey <address@hidden>
branch nick: trunk
timestamp: Mon 2010-08-02 09:54:02 +0200
message:
Rewrite fill style handling to make it easier to extend. Fix bug #26670
and improve SWF8 gradient fills, including implementing dynamic focal
fills.
added:
testsuite/misc-ming.all/GradientFillTest.as
renamed:
libcore/fill_style.cpp => libcore/FillStyle.cpp
libcore/fill_style.h => libcore/FillStyle.h
modified:
libbase/GnashNumeric.h
libcore/Bitmap.cpp
libcore/DisplayObject.cpp
libcore/DisplayObject.h
libcore/DynamicShape.cpp
libcore/DynamicShape.h
libcore/FreetypeGlyphsProvider.cpp
libcore/Geometry.h
libcore/LineStyle.cpp
libcore/LineStyle.h
libcore/Makefile.am
libcore/MovieClip.h
libcore/RGBA.cpp
libcore/RGBA.h
libcore/SWFMatrix.cpp
libcore/SWFMatrix.h
libcore/SWFRect.cpp
libcore/asobj/MovieClip_as.cpp
libcore/swf/DefineButtonTag.cpp
libcore/swf/DefineEditTextTag.cpp
libcore/swf/DefineMorphShapeTag.cpp
libcore/swf/DefineTextTag.cpp
libcore/swf/PlaceObject2Tag.cpp
libcore/swf/PlaceObject2Tag.h
libcore/swf/SWF.h
libcore/swf/SetBackgroundColorTag.h
libcore/swf/ShapeRecord.cpp
libcore/swf/ShapeRecord.h
libcore/swf/TextRecord.cpp
librender/Renderer.h
librender/Renderer_agg.cpp
librender/Renderer_agg_style.h
librender/Renderer_cairo.cpp
librender/Renderer_cairo.h
librender/Renderer_ogl.cpp
testsuite/libcore.all/ClassSizes.cpp
testsuite/libcore.all/MatrixTest.cpp
testsuite/misc-ming.all/DrawingApiTest.as
testsuite/misc-ming.all/DrawingApiTestRunner.cpp
testsuite/misc-ming.all/Makefile.am
libcore/FillStyle.cpp
libcore/FillStyle.h
=== modified file 'libbase/GnashNumeric.h'
--- a/libbase/GnashNumeric.h 2010-01-11 06:41:38 +0000
+++ b/libbase/GnashNumeric.h 2010-07-31 16:10:47 +0000
@@ -68,8 +68,9 @@
return std::max<T>(min, std::min<T>(i, max));
}
-inline float
-flerp(float a, float b, float f)
+template<typename T>
+inline T
+lerp(T a, T b, T f)
{
return (b - a) * f + a;
}
=== modified file 'libcore/Bitmap.cpp'
--- a/libcore/Bitmap.cpp 2010-07-19 08:08:00 +0000
+++ b/libcore/Bitmap.cpp 2010-07-31 14:22:03 +0000
@@ -19,7 +19,7 @@
#include "Bitmap.h"
#include "flash/display/BitmapData_as.h"
#include "GnashImage.h"
-#include "fill_style.h"
+#include "FillStyle.h"
#include "DynamicShape.h"
#include "SWFRect.h"
#include "Renderer.h"
@@ -168,8 +168,10 @@
SWFMatrix mat;
mat.set_scale(1.0 / 20, 1.0 / 20);
- fill_style fill(bitmap(), mat);
- const size_t fillLeft = _shape.add_fill_style(fill);
+
+ // Can this be tiled?
+ FillStyle fill(BitmapFill(BitmapFill::CLIPPED, bitmap(), mat));
+ const size_t fillLeft = _shape.addFillStyle(fill);
Path bmpath(w, h, fillLeft, 0, 0, false);
bmpath.drawLineTo(w, 0);
=== modified file 'libcore/DisplayObject.cpp'
--- a/libcore/DisplayObject.cpp 2010-07-11 08:00:59 +0000
+++ b/libcore/DisplayObject.cpp 2010-07-31 16:16:12 +0000
@@ -91,7 +91,7 @@
_rotation(0),
_depth(0),
_volume(100),
- m_ratio(0),
+ _ratio(0),
m_clip_depth(noClipDepthValue),
_mask(0),
_maskee(0),
=== modified file 'libcore/DisplayObject.h'
--- a/libcore/DisplayObject.h 2010-07-10 13:40:04 +0000
+++ b/libcore/DisplayObject.h 2010-07-31 16:16:12 +0000
@@ -339,12 +339,12 @@
}
}
- int get_ratio() const { return m_ratio; }
+ int get_ratio() const { return _ratio; }
void set_ratio(int r)
{
- if (r != m_ratio) set_invalidated(__FILE__, __LINE__);
- m_ratio = r;
+ if (r != _ratio) set_invalidated(__FILE__, __LINE__);
+ _ratio = r;
}
/// Returns the clipping depth (if any) of this DisplayObject.
@@ -1050,7 +1050,7 @@
///
int _volume;
- int m_ratio;
+ int _ratio;
int m_clip_depth;
/// The DisplayObject masking this instance (if any)
=== modified file 'libcore/DynamicShape.cpp'
--- a/libcore/DynamicShape.cpp 2010-03-13 18:00:33 +0000
+++ b/libcore/DynamicShape.cpp 2010-07-31 14:05:26 +0000
@@ -17,7 +17,7 @@
#include "smart_ptr.h"
#include "DynamicShape.h"
-#include "fill_style.h"
+#include "FillStyle.h"
#include "Renderer.h"
#include "DisplayObject.h"
@@ -88,49 +88,12 @@
}
void
-DynamicShape::beginFill(const rgba& color)
-{
- // End previous fill
- endFill();
-
- // Add the new fill style and set as current
- fill_style style; style.setSolid(color);
- _currfill = add_fill_style(style);
-
- // TODO: how to know wheter the fill should be set
- // as *left* or *right* fill ?
- // A quick test shows that *left* always work fine !
- Path newPath(_x, _y, _currfill, 0, _currline, true);
- add_path(newPath);
-}
-
-void
-DynamicShape::beginLinearGradientFill(const std::vector<gradient_record>&
grad, const SWFMatrix& mat)
-{
- // Add the new fill style and set as current
- fill_style style;
- style.setLinearGradient(grad, mat);
-
- endFill();
-
- _currfill = add_fill_style(style);
- // TODO: how to know wheter the fill should be set
- // as *left* or *right* fill ?
- // A quick test shows that *left* always work fine !
- Path newPath(_x, _y, _currfill, 0, _currline, true);
- add_path(newPath);
-}
-
-void
-DynamicShape::beginRadialGradientFill(const std::vector<gradient_record>&
grad, const SWFMatrix& mat)
-{
-
- // End previous fill
- endFill();
-
- // Add the new fill style and set as current
- fill_style style; style.setRadialGradient(grad, mat);
- _currfill = add_fill_style(style);
+DynamicShape::beginFill(const FillStyle& f)
+{
+ // End previous fill
+ endFill();
+
+ _currfill = addFillStyle(f);
// TODO: how to know wheter the fill should be set
// as *left* or *right* fill ?
@@ -276,7 +239,7 @@
}
size_t
-DynamicShape::add_fill_style(const fill_style& stl)
+DynamicShape::addFillStyle(const FillStyle& stl)
{
_shape.addFillStyle(stl);
return _shape.fillStyles().size();
=== modified file 'libcore/DynamicShape.h'
--- a/libcore/DynamicShape.h 2010-07-28 07:57:23 +0000
+++ b/libcore/DynamicShape.h 2010-07-31 14:05:26 +0000
@@ -27,8 +27,8 @@
namespace gnash {
class DisplayObject;
class Renderer;
- class fill_style;
- class gradient_record;
+ class FillStyle;
+ class GradientRecord;
}
namespace gnash {
@@ -64,15 +64,7 @@
boost::int32_t ax, boost::int32_t ay, int swfVersion);
/// Start drawing with a solid fill
- void beginFill(const rgba& color);
-
- /// Start drawing with a linear gradient fill
- void beginLinearGradientFill(const std::vector<gradient_record>& grad,
- const SWFMatrix& mat);
-
- /// Start drawing with a radial gradient fill
- void beginRadialGradientFill(const std::vector<gradient_record>& grad,
- const SWFMatrix& mat);
+ void beginFill(const FillStyle& f);
/// Close an existing filled path, if any.
void endFill();
@@ -129,7 +121,7 @@
/// This offset is the one required to properly
/// reference it in gnash::path instances.
///
- size_t add_fill_style(const fill_style& stl);
+ size_t addFillStyle(const FillStyle& stl);
/// \brief
/// Add a line style, possibly reusing an existing
=== renamed file 'libcore/fill_style.cpp' => 'libcore/FillStyle.cpp'
--- a/libcore/fill_style.cpp 2010-07-12 21:18:16 +0000
+++ b/libcore/FillStyle.cpp 2010-08-01 07:47:27 +0000
@@ -1,4 +1,4 @@
-// fill_style.cpp: Graphical region filling styles, for Gnash.
+// FillStyle.cpp: Graphical region filling styles, for Gnash.
//
// Copyright (C) 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
//
@@ -17,10 +17,13 @@
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
//
-// Based on work of Thatcher Ulrich <address@hidden> 2003
+#include "FillStyle.h"
+
+#include <iostream>
+#include <boost/variant.hpp>
+#include <boost/optional.hpp>
#include "smart_ptr.h"
-#include "fill_style.h"
#include "log.h"
#include "SWFStream.h"
#include "movie_definition.h"
@@ -31,632 +34,422 @@
#include "RunResources.h"
#include "GnashImage.h"
-#include <cmath> // sqrt, floor
-#include <iostream> // for output operator
namespace gnash {
+// Forward declarations
+namespace {
+ rgba sampleGradient(const GradientFill& fill, boost::uint8_t ratio);
+ OptionalFillPair readSolidFill(SWFStream& in, SWF::TagType t,
+ bool readMorph);
+ OptionalFillPair readBitmapFill(SWFStream& in, SWF::FillType type,
+ movie_definition& md, bool readMorph);
+ GradientRecord readGradientRecord(SWFStream& in, SWF::TagType tag);
+}
+
+namespace {
+
+/// Create a lerped version of two other FillStyles.
+//
+/// The two fill styles must have exactly the same types. Callers are
+/// responsible for ensuring this.
+class SetLerp : public boost::static_visitor<>
+{
+public:
+ SetLerp(const FillStyle::Fill& a, const FillStyle::Fill& b, double ratio)
+ :
+ _a(a),
+ _b(b),
+ _ratio(ratio)
+ {
+ }
+
+ template<typename T> void operator()(T& f) const {
+ const T& a = boost::get<T>(_a);
+ const T& b = boost::get<T>(_b);
+ f.setLerp(a, b, _ratio);
+ }
+
+private:
+ const FillStyle::Fill& _a;
+ const FillStyle::Fill& _b;
+ const double _ratio;
+
+};
+
+}
+
+SWFMatrix
+gradientMatrix(GradientFill::Type t, const SWFMatrix& m)
+{
+ SWFMatrix base;
+ switch (t) {
+ case GradientFill::LINEAR:
+ base.set_translation(128, 0);
+ base.set_scale(1.0 / 128, 1.0 / 128);
+ break;
+ case GradientFill::RADIAL:
+ base.set_translation(32, 32);
+ base.set_scale(1.0 / 512, 1.0 / 512);
+ break;
+ }
+ base.concatenate(m);
+ return base;
+}
+
+GradientFill::GradientFill(Type t, const SWFMatrix& m,
+ const GradientRecords& recs)
+ :
+ spreadMode(SWF::GRADIENT_SPREAD_PAD),
+ interpolation(SWF::GRADIENT_INTERPOLATION_NORMAL),
+ _focalPoint(0.0),
+ _gradients(recs),
+ _type(t),
+ _matrix(gradientMatrix(t, m))
+{
+ assert(recs.empty() || recs.size() > 1);
+}
+
void
-gradient_record::read(SWFStream& in, SWF::TagType tag)
+GradientFill::setFocalPoint(double d)
{
- in.ensureBytes(1);
- m_ratio = in.read_u8();
- m_color.read(in, tag);
+ _focalPoint = clamp<float>(d, -1, 1);
}
-
-fill_style::fill_style()
+
+BitmapFill::BitmapFill(SWF::FillType t, movie_definition* md,
+ boost::uint16_t id, const SWFMatrix& m)
:
+ _type(),
+ _smoothingPolicy(),
+ _matrix(m),
_bitmapInfo(0),
- m_color(),
- m_spread_mode(SWF::GRADIENT_SPREAD_PAD),
- m_interpolation(SWF::GRADIENT_INTERPOL_NORMAL),
- m_type(SWF::FILL_SOLID),
- _bitmapSmoothingPolicy(BITMAP_SMOOTHING_UNSPECIFIED)
-{
-}
-
-void
-fill_style::read(SWFStream& in, SWF::TagType t, movie_definition& md,
- const RunResources& r, fill_style *pOther)
-{
- const bool is_morph = (pOther != NULL);
+ _md(md),
+ _id(id)
+{
+ assert(md);
+
+ _smoothingPolicy = md->get_version() >= 8 ?
+ BitmapFill::SMOOTHING_ON : BitmapFill::SMOOTHING_UNSPECIFIED;
+
+ switch (t) {
+ case SWF::FILL_TILED_BITMAP_HARD:
+ _type = BitmapFill::TILED;
+ _smoothingPolicy = BitmapFill::SMOOTHING_OFF;
+ break;
+
+ case SWF::FILL_TILED_BITMAP:
+ _type = BitmapFill::TILED;
+ break;
+
+ case SWF::FILL_CLIPPED_BITMAP_HARD:
+ _type = BitmapFill::CLIPPED;
+ _smoothingPolicy = BitmapFill::SMOOTHING_OFF;
+ break;
+
+ case SWF::FILL_CLIPPED_BITMAP:
+ _type = BitmapFill::CLIPPED;
+ break;
+
+ default:
+ std::abort();
+ }
+}
+
+const BitmapInfo*
+BitmapFill::bitmap() const
+{
+ if (_bitmapInfo) return _bitmapInfo.get();
+ if (!_md) return 0;
+ _bitmapInfo = _md->getBitmap(_id);
+
+ // May still be 0!
+ return _bitmapInfo.get();
+}
+
+void
+GradientFill::setLerp(const GradientFill& a, const GradientFill& b,
+ double ratio)
+{
+ assert(type() == a.type());
+ assert(_gradients.size() == a.recordCount());
+ assert(_gradients.size() == b.recordCount());
+
+ for (size_t i = 0, e = _gradients.size(); i < e; ++i) {
+ const GradientRecord& ra = a.record(i);
+ const GradientRecord& rb = b.record(i);
+ _gradients[i].ratio = frnd(lerp<float>(ra.ratio, rb.ratio, ratio));
+ _gradients[i].color.set_lerp(ra.color, rb.color, ratio);
+ }
+ _matrix.set_lerp(a.matrix(), b.matrix(), ratio);
+}
+
+void
+BitmapFill::setLerp(const BitmapFill& a, const BitmapFill& b, double ratio)
+{
+ _matrix.set_lerp(a.matrix(), b.matrix(), ratio);
+}
+
+OptionalFillPair
+readFills(SWFStream& in, SWF::TagType t, movie_definition& md, bool readMorph)
+{
in.ensureBytes(1);
- m_type = in.read_u8();
- if (is_morph)
- {
- pOther->m_type = m_type;
- }
+ const SWF::FillType type = static_cast<SWF::FillType>(in.read_u8());
IF_VERBOSE_PARSE(
- log_parse(" fill_style read type = 0x%X", (int)m_type);
+ log_parse(" FillStyle read type = 0x%X", +type);
);
- if (m_type == SWF::FILL_SOLID)
- {
- // 0x00: solid fill
- if (t == SWF::DEFINESHAPE3 || t == SWF::DEFINESHAPE4
- || t == SWF::DEFINESHAPE4_ || is_morph) {
-
- m_color.read_rgba(in);
- if (is_morph) pOther->m_color.read_rgba(in);
- }
- else {
- // For DefineMorphShape tags we should use morph_fill_style
- assert(t == SWF::DEFINESHAPE || t == SWF::DEFINESHAPE2);
- m_color.read_rgb(in);
- }
-
- IF_VERBOSE_PARSE(
- log_parse(" color: %s", m_color);
- );
- }
- else if (m_type == SWF::FILL_LINEAR_GRADIENT
- || m_type == SWF::FILL_RADIAL_GRADIENT
- || m_type == SWF::FILL_FOCAL_GRADIENT)
- {
- // 0x10: linear gradient fill
- // 0x12: radial gradient fill
- // 0x13: focal gradient fill
-
- SWFMatrix input_matrix;
- input_matrix.read(in);
-
- // shouldn't this be in initializer's list ?
- _matrix.set_identity();
- if (m_type == SWF::FILL_LINEAR_GRADIENT) {
- _matrix.set_translation(128, 0);
- _matrix.set_scale(1.0/128, 1.0/128);
- }
- else {
- // FILL_RADIAL_GRADIENT or FILL_FOCAL_GRADIENT
- _matrix.set_translation(32, 32);
- _matrix.set_scale(1.0/512, 1.0/512);
- }
-
- SWFMatrix m = input_matrix;
- m.invert();
-
- if (is_morph) pOther->_matrix = _matrix;
- _matrix.concatenate(m);
-
- if (is_morph) {
- input_matrix.read(in);
- m = input_matrix;
- m.invert();
- pOther->_matrix.concatenate(m);
- }
-
- // GRADIENT
- in.ensureBytes(1);
-
- boost::uint8_t grad_props = in.read_u8();
-
- if (t == SWF::DEFINESHAPE4 ||
- t == SWF::DEFINESHAPE4_) {
- boost::uint8_t spread_mode = grad_props >> 6;
- switch(spread_mode) {
- case 0:
- m_spread_mode = SWF::GRADIENT_SPREAD_PAD;
- break;
- case 1:
- m_spread_mode = SWF::GRADIENT_SPREAD_REFLECT;
- break;
- case 2:
- m_spread_mode = SWF::GRADIENT_SPREAD_REPEAT;
- break;
- default:
+ switch (type) {
+
+ case SWF::FILL_SOLID:
+ return readSolidFill(in, t, readMorph);
+
+ case SWF::FILL_TILED_BITMAP_HARD:
+ case SWF::FILL_CLIPPED_BITMAP_HARD:
+ case SWF::FILL_TILED_BITMAP:
+ case SWF::FILL_CLIPPED_BITMAP:
+ return readBitmapFill(in, type, md, readMorph);
+
+ case SWF::FILL_LINEAR_GRADIENT:
+ case SWF::FILL_RADIAL_GRADIENT:
+ case SWF::FILL_FOCAL_GRADIENT:
+ {
+
+ GradientFill::Type gr;
+ switch (type) {
+ case SWF::FILL_LINEAR_GRADIENT:
+ gr = GradientFill::LINEAR;
+ break;
+ case SWF::FILL_RADIAL_GRADIENT:
+ case SWF::FILL_FOCAL_GRADIENT:
+ gr = GradientFill::RADIAL;
+ break;
+ default:
+ std::abort();
+ }
+
+ SWFMatrix m = readSWFMatrix(in).invert();
+ GradientFill gf(gr, m);
+
+ boost::optional<FillStyle> morph;
+ if (readMorph) {
+ SWFMatrix m2 = readSWFMatrix(in).invert();
+ morph = GradientFill(gr, m2);
+ }
+
+ in.ensureBytes(1);
+ const boost::uint8_t grad_props = in.read_u8();
+
+ const boost::uint8_t num_gradients = grad_props & 0xF;
+ IF_VERBOSE_PARSE(
+ log_parse(" gradients: num_gradients = %d", +num_gradients);
+ );
+
+ if (!num_gradients) {
IF_VERBOSE_MALFORMED_SWF(
- log_swferror("Illegal spread mode in gradient
definition.");
- );
- }
-
- boost::uint8_t interpolation = (grad_props >> 4) & 3;
- switch(interpolation) {
- case 0:
- m_interpolation = SWF::GRADIENT_INTERPOL_NORMAL;
- break;
- case 1:
- m_interpolation = SWF::GRADIENT_INTERPOL_LINEAR;
- break;
- default:
- IF_VERBOSE_MALFORMED_SWF(
- log_swferror("Illegal interpolation mode in gradient "
- "definition.");
- );
- }
- }
-
- boost::uint8_t num_gradients = grad_props & 0xF;
- if (!num_gradients) {
- IF_VERBOSE_MALFORMED_SWF(
- log_swferror(_("num gradients 0"));
- );
- return;
- }
-
- if (num_gradients > 8 + ((t == SWF::DEFINESHAPE4 ||
- t == SWF::DEFINESHAPE4_) ? 7 : 0)) {
- // see: http://sswf.sourceforge.net/SWFalexref.html#swf_gradient
- IF_VERBOSE_MALFORMED_SWF(
- log_swferror(_("Unexpected num gradients (%d), "
- "expected 1 to 8"), static_cast<int>(num_gradients));
- );
- }
-
- if (is_morph) {
- pOther->m_gradients.resize(num_gradients);
- }
-
- m_gradients.resize(num_gradients);
- for (size_t i = 0; i < num_gradients; ++i) {
- m_gradients[i].read(in, t);
- if (is_morph) {
- pOther->m_gradients[i].read(in, t);
- }
- }
-
- // A focal gradient also has a focal point.
- if (m_type == SWF::FILL_FOCAL_GRADIENT) {
- in.ensureBytes(2);
- m_focal_point = in.read_short_sfixed();
- if (m_focal_point < -1.0f) m_focal_point = -1.0f;
- else if (m_focal_point > 1.0f) m_focal_point = 1.0f;
- }
-
- if (is_morph) {
- pOther->m_focal_point = m_focal_point;
- }
-
- IF_VERBOSE_PARSE(
- log_parse(" gradients: num_gradients = %d",
- static_cast<int>(num_gradients));
- );
-
- // @@ hack. What is it supposed to do?
- if (num_gradients > 0) {
- m_color = m_gradients[0].m_color;
- if (is_morph)
- pOther->m_color = pOther->m_gradients[0].m_color;
- }
-
- Renderer* renderer = r.renderer();
- if (renderer) {
-
- _bitmapInfo = create_gradient_bitmap(*renderer);
- if (is_morph) {
- pOther->_bitmapInfo = pOther->need_gradient_bitmap(*renderer);
- }
- }
- }
- else if (m_type == SWF::FILL_TILED_BITMAP
- || m_type == SWF::FILL_CLIPPED_BITMAP
- || m_type == SWF::FILL_TILED_BITMAP_HARD
- || m_type == SWF::FILL_CLIPPED_BITMAP_HARD)
- {
- // 0x40: tiled bitmap fill
- // 0x41: clipped bitmap fill
- // 0x42: tiled bitmap fill with hard edges
- // 0x43: clipped bitmap fill with hard edges
-
- if (m_type == SWF::FILL_TILED_BITMAP_HARD ||
- m_type == SWF::FILL_CLIPPED_BITMAP_HARD) {
- _bitmapSmoothingPolicy = BITMAP_SMOOTHING_OFF;
- }
- else if (md.get_version() >= 8) {
- _bitmapSmoothingPolicy = BITMAP_SMOOTHING_ON;
- }
- else {
- _bitmapSmoothingPolicy = BITMAP_SMOOTHING_UNSPECIFIED;
- }
-
- in.ensureBytes(2);
- int bitmap_char_id = in.read_u16();
- IF_VERBOSE_PARSE(
- log_parse(" bitmap_char = %d, smoothing_policy = %s",
- bitmap_char_id, _bitmapSmoothingPolicy);
- );
-
- // Look up the bitmap DisplayObject.
- _bitmapInfo = md.getBitmap(bitmap_char_id);
- IF_VERBOSE_MALFORMED_SWF(
- if (!_bitmapInfo) {
- LOG_ONCE(
- log_swferror(_("Bitmap fill specifies '%d' as associated"
- " bitmap DisplayObject id,"
- " but that DisplayObject is not found"
- " in the Characters Dictionary."
- " It seems common to find such "
- " malformed SWF, so we'll only warn once "
- "about this."), bitmap_char_id);
- );
- }
- );
-
- SWFMatrix m;
- m.read(in);
-
- // For some reason, it looks like they store the inverse of the
- // TWIPS-to-texcoords SWFMatrix.
- _matrix = m.invert();
-
- if (is_morph) {
- pOther->_bitmapInfo = _bitmapInfo;
- m.read(in);
- pOther->_matrix = m.invert();
- }
-
- IF_VERBOSE_PARSE(
- log_parse("SWFMatrix: %s", _matrix);
- );
- }
- else {
- std::stringstream ss;
- ss << "Unknown fill style type " << m_type;
- // This is a fatal error, we'll be leaving the stream
- // read pointer in an unknown position.
- throw ParserException(ss.str());
- }
-}
-
-
-const BitmapInfo*
-fill_style::get_bitmap_info(Renderer& renderer) const
-{
- assert(m_type != SWF::FILL_SOLID);
-
- switch (m_type)
- {
- case SWF::FILL_TILED_BITMAP:
- case SWF::FILL_CLIPPED_BITMAP:
- case SWF::FILL_TILED_BITMAP_HARD:
- case SWF::FILL_CLIPPED_BITMAP_HARD:
- if (_bitmapInfo)
- {
- return _bitmapInfo.get();
- }
- return NULL;
-
- case SWF::FILL_LINEAR_GRADIENT:
- case SWF::FILL_RADIAL_GRADIENT:
- return need_gradient_bitmap(renderer);
+ log_swferror(_("No gradients!"));
+ );
+ throw ParserException();
+ }
+
+ GradientFill::GradientRecords recs;
+ recs.reserve(num_gradients);
+
+ GradientFill::GradientRecords morphrecs;
+ morphrecs.reserve(num_gradients);
+
+ for (size_t i = 0; i < num_gradients; ++i) {
+ recs.push_back(readGradientRecord(in, t));
+ if (readMorph) {
+ morphrecs.push_back(readGradientRecord(in, t));
+ }
+ }
+
+ // A GradientFill may never have fewer than 2 colour stops. We've
+ // no tests to show what happens in that case for static fills.
+ // Dynamic fills are tested to display as a solid fill. In either
+ // case the renderer will bork if there is only 1 stop in a
+ // GradientFill.
+ if (num_gradients == 1) {
+ const rgba c1 = recs[0].color;
+ if (readMorph) {
+ const rgba c2 = morphrecs[0].color;
+ morph = SolidFill(c2);
+ }
+ return std::make_pair(SolidFill(c1), morph);
+ }
+
+ gf.setRecords(recs);
+ if (readMorph) {
+ boost::get<GradientFill>(morph->fill).setRecords(morphrecs);
+ }
+
+
+ if (t == SWF::DEFINESHAPE4 || t == SWF::DEFINESHAPE4_) {
+
+ const SWF::SpreadMode spread =
+ static_cast<SWF::SpreadMode>(grad_props >> 6);
+
+ switch (spread) {
+ case SWF::GRADIENT_SPREAD_PAD:
+ case SWF::GRADIENT_SPREAD_REFLECT:
+ case SWF::GRADIENT_SPREAD_REPEAT:
+ gf.spreadMode = spread;
+ break;
+ default:
+ IF_VERBOSE_MALFORMED_SWF(
+ log_swferror("Illegal spread mode in gradient "
+ "definition.");
+ );
+ }
+
+ // TODO: handle in GradientFill.
+ const SWF::InterpolationMode i =
+ static_cast<SWF::InterpolationMode>((grad_props >> 4) & 3);
+
+ switch (i) {
+ case SWF::GRADIENT_INTERPOLATION_NORMAL:
+ case SWF::GRADIENT_INTERPOLATION_LINEAR:
+ gf.interpolation = i;
+ default:
+ IF_VERBOSE_MALFORMED_SWF(
+ log_swferror("Illegal interpolation mode in "
+ "gradient definition.");
+ );
+ }
+ }
+
+ // A focal gradient also has a focal point.
+ if (type == SWF::FILL_FOCAL_GRADIENT) {
+ in.ensureBytes(2);
+ gf.setFocalPoint(in.read_short_sfixed());
+ }
+
+ if (readMorph) {
+ boost::get<GradientFill>(morph->fill).
+ setFocalPoint(gf.focalPoint());
+ }
+
+ return std::make_pair(gf, morph);
+ }
+
default:
- log_error(_("Unknown fill style %d"), m_type);
- // Seems a bit drastic...
- std::abort();
- }
-}
-
-const SWFMatrix&
-fill_style::getBitmapMatrix() const
-{
- assert(m_type != SWF::FILL_SOLID);
- return _matrix;
-}
-
-const SWFMatrix&
-fill_style::getGradientMatrix() const
-{
- // TODO: Why do we separate bitmap and gradient matrices?
- return _matrix;
-}
-
-rgba
-fill_style::sample_gradient(boost::uint8_t ratio) const
-{
- assert(m_type == SWF::FILL_LINEAR_GRADIENT
- || m_type == SWF::FILL_RADIAL_GRADIENT
- || m_type == SWF::FILL_FOCAL_GRADIENT);
-
- if (m_gradients.empty()) {
- static const rgba black;
- return black;
- }
-
- // By specs, first gradient should *always* be 0,
- // anyway a malformed SWF could break this,
- // so we cannot rely on that information...
- if (ratio < m_gradients[0].m_ratio)
- {
- IF_VERBOSE_MALFORMED_SWF(
- LOG_ONCE(
- log_swferror(
- _("First gradient in a fill_style "
- "have position==%d (expected 0)."
- " This seems to be common, so will"
- " warn only once."),
- static_cast<int>(m_gradients[0].m_ratio));
- );
- );
- return m_gradients[0].m_color;
- }
-
- if (ratio >= m_gradients.back().m_ratio)
- {
- return m_gradients.back().m_color;
- }
-
- for (size_t i = 1, n = m_gradients.size(); i < n; ++i)
- {
- const gradient_record& gr1 = m_gradients[i];
- if (gr1.m_ratio < ratio) continue;
-
- const gradient_record& gr0 = m_gradients[i - 1];
- if (gr0.m_ratio > ratio) continue;
-
- float f = 0.0f;
-
- if ( gr0.m_ratio != gr1.m_ratio )
- {
- f = (ratio - gr0.m_ratio) / float(gr1.m_ratio - gr0.m_ratio);
- }
- else
- {
- // Ratios are equal IFF first and second gradient_record
- // have the same ratio. This would be a malformed SWF.
- IF_VERBOSE_MALFORMED_SWF(
- log_swferror(
- _("two gradients in a fill_style "
- "have the same position/ratio: %d"),
- gr0.m_ratio);
- );
- }
-
- rgba result;
- result.set_lerp(gr0.m_color, gr1.m_color, f);
- return result;
- }
-
- // Assuming gradients are ordered by m_ratio? see start comment
- return m_gradients.back().m_color;
-}
-
-const BitmapInfo*
-fill_style::create_gradient_bitmap(Renderer& renderer) const
-{
- assert(m_type == SWF::FILL_LINEAR_GRADIENT
- || m_type == SWF::FILL_RADIAL_GRADIENT
- || m_type == SWF::FILL_FOCAL_GRADIENT);
-
- std::auto_ptr<ImageRGBA> im;
-
- switch (m_type)
- {
- case SWF::FILL_LINEAR_GRADIENT:
- // Linear gradient.
- im.reset(new ImageRGBA(256, 1));
-
- for (size_t i = 0; i < im->width(); i++) {
- rgba sample = sample_gradient(i);
- im->setPixel(i, 0, sample.m_r, sample.m_g,
- sample.m_b, sample.m_a);
- }
- break;
-
- case SWF::FILL_RADIAL_GRADIENT:
- // Radial gradient.
- im.reset(new ImageRGBA(64, 64));
-
- for (size_t j = 0; j < im->height(); j++) {
- for (size_t i = 0; i < im->width(); i++) {
- float radius = (im->height() - 1) / 2.0f;
- float y = (j - radius) / radius;
- float x = (i - radius) / radius;
- int ratio = static_cast<int>(
- std::floor(255.5f * std::sqrt(x * x + y * y)));
- if (ratio > 255) {
- ratio = 255;
- }
- rgba sample = sample_gradient(ratio);
- im->setPixel(i, j, sample.m_r, sample.m_g,
- sample.m_b, sample.m_a);
- }
- }
- break;
-
- case SWF::FILL_FOCAL_GRADIENT:
- // Focal gradient.
- im.reset(new ImageRGBA(64, 64));
-
- for (size_t j = 0; j < im->height(); j++)
- {
- for (size_t i = 0; i < im->width(); i++)
- {
- float radiusy = (im->height() - 1) / 2.0f;
- float radiusx = radiusy + std::abs(radiusy *
m_focal_point);
- float y = (j - radiusy) / radiusy;
- float x = (i - radiusx) / radiusx;
- int ratio = static_cast<int>(std::floor(255.5f *
- std::sqrt(x*x + y*y)));
-
- if (ratio > 255) ratio = 255;
-
- rgba sample = sample_gradient(ratio);
- im->setPixel(i, j, sample.m_r, sample.m_g,
- sample.m_b, sample.m_a);
- }
- }
- break;
- }
-
- const BitmapInfo* bi = renderer.createBitmapInfo(
- static_cast<std::auto_ptr<GnashImage> >(im));
-
- return bi;
-}
-
-
-const BitmapInfo*
-fill_style::need_gradient_bitmap(Renderer& renderer) const
-{
-
- if (!_bitmapInfo) {
- fill_style* this_non_const = const_cast<fill_style*>(this);
- this_non_const->_bitmapInfo = create_gradient_bitmap(renderer);
- }
-
- return _bitmapInfo.get();
-
-}
-
+ {
+ std::stringstream ss;
+ ss << "Unknown fill style type " << +type;
+ // This is a fatal error, we'll be leaving the stream
+ // read pointer in an unknown position.
+ throw ParserException(ss.str());
+ }
+ }
+}
// Sets this style to a blend of a and b. t = [0,1]
void
-fill_style::set_lerp(const fill_style& a, const fill_style& b, float t)
+setLerp(FillStyle& f, const FillStyle& a, const FillStyle& b, double t)
{
assert(t >= 0 && t <= 1);
-
- // fill style type
- m_type = a.get_type();
- assert(m_type == b.get_type());
-
- // fill style color (TODO: only for solid fills ?)
- m_color.set_lerp(a.get_color(), b.get_color(), t);
-
- bool usesMatrix = false;
-
- switch (m_type)
- {
- case SWF::FILL_LINEAR_GRADIENT:
- case SWF::FILL_RADIAL_GRADIENT:
- case SWF::FILL_FOCAL_GRADIENT:
- {
- usesMatrix = true;
-
- // fill style gradients
- assert(m_gradients.size() == a.m_gradients.size());
- assert(m_gradients.size() == b.m_gradients.size());
- for (size_t j=0, nj=m_gradients.size(); j<nj; ++j)
- {
- m_gradients[j].m_ratio =
- (boost::uint8_t) frnd( flerp(a.m_gradients[j].m_ratio,
- b.m_gradients[j].m_ratio, t)
- );
- m_gradients[j].m_color.set_lerp(a.m_gradients[j].m_color,
- b.m_gradients[j].m_color, t);
- }
- _bitmapInfo = NULL;
- break;
- }
-
- case SWF::FILL_TILED_BITMAP:
- case SWF::FILL_CLIPPED_BITMAP:
- case SWF::FILL_TILED_BITMAP_HARD:
- case SWF::FILL_CLIPPED_BITMAP_HARD:
- {
- usesMatrix = true;
-
- // fill style bitmap ID
- _bitmapInfo = a._bitmapInfo;
- assert(_bitmapInfo == b._bitmapInfo);
- break;
- }
-
+ f.fill = a.fill;
+ boost::apply_visitor(SetLerp(a.fill, b.fill, t), f.fill);
+}
+
+namespace {
+
+OptionalFillPair
+readSolidFill(SWFStream& in, SWF::TagType t, bool readMorph)
+{
+ rgba color;
+
+ boost::optional<FillStyle> morph;
+
+ // 0x00: solid fill
+ if (t == SWF::DEFINESHAPE3 || t == SWF::DEFINESHAPE4 ||
+ t == SWF::DEFINESHAPE4_ || readMorph) {
+ color = readRGBA(in);
+ if (readMorph) {
+ rgba othercolor;
+ othercolor = readRGBA(in);
+ morph = SolidFill(othercolor);
+ }
+ }
+ else {
+ // For DefineMorphShape tags we should use morphFillStyle
+ assert(t == SWF::DEFINESHAPE || t == SWF::DEFINESHAPE2);
+ color = readRGB(in);
+ }
+
+ IF_VERBOSE_PARSE(
+ log_parse(" color: %s", color);
+ );
+ return std::make_pair(SolidFill(color), morph);
+}
+
+OptionalFillPair
+readBitmapFill(SWFStream& in, SWF::FillType type, movie_definition& md,
+ bool readMorph)
+{
+
+ in.ensureBytes(2);
+ const boost::uint16_t id = in.read_u16();
+
+ SWFMatrix m = readSWFMatrix(in).invert();
+
+ boost::optional<FillStyle> morph;
+ if (readMorph) {
+ SWFMatrix m2 = readSWFMatrix(in).invert();
+ morph = BitmapFill(type, &md, id, m2);
+ }
+
+ // For some reason, it looks like they store the inverse of the
+ // TWIPS-to-texcoords SWFMatrix.
+ return std::make_pair(BitmapFill(type, &md, id, m), morph);
+}
+
+GradientRecord
+readGradientRecord(SWFStream& in, SWF::TagType tag)
+{
+ in.ensureBytes(1);
+ const boost::uint8_t ratio = in.read_u8();
+
+ switch (tag) {
+ case SWF::DEFINESHAPE:
+ case SWF::DEFINESHAPE2:
+ {
+ const rgba color = readRGB(in);
+ return GradientRecord(ratio, color);
+ }
default:
break;
}
-
- // fill style bitmap or gradient SWFMatrix
- if (usesMatrix) _matrix.set_lerp(a._matrix, b._matrix, t);
-}
-
-
-size_t
-fill_style::get_color_stop_count() const
-{
- return m_gradients.size();
-}
-
-const gradient_record&
-fill_style::get_color_stop(size_t index) const
-{
- assert(index < m_gradients.size());
- return m_gradients[index];
-}
-
-fill_style::fill_style(const BitmapInfo* const bitmap, const SWFMatrix& mat)
- :
- _matrix(mat),
- _bitmapInfo(bitmap),
- m_type(SWF::FILL_CLIPPED_BITMAP),
- _bitmapSmoothingPolicy(BITMAP_SMOOTHING_UNSPECIFIED)
-{
-}
-
-void
-fill_style::setSolid(const rgba& color)
-{
- m_type = SWF::FILL_SOLID;
- m_color = color;
- _bitmapInfo = 0;
-}
-
-void
-fill_style::setLinearGradient(const std::vector<gradient_record>& gradients,
- const SWFMatrix& mat)
-{
-
- assert(!gradients.empty());
-
- // We must ensure that all gradients have more than one colour stop
- // because asking renderers to render a gradient with one colour
- // can cause them to invoke UB.
- if (gradients.size() < 2) {
- setSolid(gradients[0].m_color);
- return;
- }
-
- m_type = SWF::FILL_LINEAR_GRADIENT;
- m_gradients = gradients;
-
- _matrix = mat;
- _bitmapInfo = 0;
-}
-
-void
-fill_style::setRadialGradient(const std::vector<gradient_record>& gradients,
- const SWFMatrix& mat)
-{
- assert(!gradients.empty());
-
- // We must ensure that all gradients have more than one colour stop
- // because asking renderers to render a gradient with one colour
- // can cause them to invoke UB.
- if (gradients.size() < 2) {
- setSolid(gradients[0].m_color);
- return;
- }
-
- m_type = SWF::FILL_RADIAL_GRADIENT;
- m_gradients = gradients;
-
- _matrix = mat;
- _bitmapInfo = 0;
-}
-
-std::ostream& operator << (std::ostream& os,
- const fill_style::BitmapSmoothingPolicy& p)
-{
- switch (p)
- {
- case fill_style::BITMAP_SMOOTHING_UNSPECIFIED:
+ const rgba color = readRGBA(in);
+ return GradientRecord(ratio, color);
+}
+
+} // anonymous namespace
+
+std::ostream&
+operator<<(std::ostream& os, const BitmapFill::SmoothingPolicy& p)
+{
+ switch (p) {
+ case BitmapFill::SMOOTHING_UNSPECIFIED:
os << "unspecified";
break;
- case fill_style::BITMAP_SMOOTHING_ON:
+ case BitmapFill::SMOOTHING_ON:
os << "on";
break;
- case fill_style::BITMAP_SMOOTHING_OFF:
+ case BitmapFill::SMOOTHING_OFF:
os << "off";
break;
default:
// cast to int required to avoid infinite recursion
- os << "unknown " << (int)p;
+ os << "unknown " << +p;
break;
}
return os;
}
-} // end of namespace
+} // namespace gnash
// Local Variables:
=== renamed file 'libcore/fill_style.h' => 'libcore/FillStyle.h'
--- a/libcore/fill_style.h 2010-07-12 21:18:16 +0000
+++ b/libcore/FillStyle.h 2010-08-01 06:17:17 +0000
@@ -15,22 +15,21 @@
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-// Based on work of Thatcher Ulrich <address@hidden> 2003
-
-
#ifndef GNASH_FILL_STYLE_H
#define GNASH_FILL_STYLE_H
+#include <boost/variant.hpp>
+#include <vector>
+#include <iosfwd>
+#include <boost/optional.hpp>
+#include <boost/intrusive_ptr.hpp>
+#include <cassert>
+
#include "SWFMatrix.h"
#include "BitmapInfo.h"
#include "SWF.h"
#include "RGBA.h" // for rgba type
-#include <vector> // for composition
-#include <iosfwd> // for output operator forward declarations
-
-#include <boost/intrusive_ptr.hpp>
-
namespace gnash {
class SWFStream;
@@ -38,240 +37,289 @@
class Renderer;
class RunResources;
-class gradient_record
+class GradientRecord
{
public:
- gradient_record()
- :
- m_ratio(0),
- m_color()
- {}
-
- gradient_record(boost::uint8_t ratio, const rgba& color)
- :
- m_ratio(ratio),
- m_color(color)
- {}
-
- void read(SWFStream& in, SWF::TagType tag);
+
+ GradientRecord(boost::uint8_t ratio, const rgba& color)
+ :
+ ratio(ratio),
+ color(color)
+ {}
//data:
- boost::uint8_t m_ratio;
- rgba m_color;
-};
-
-
-/// For the interior of outline shapes.
-class DSOEXPORT fill_style
-{
-public:
-
- /// Bitmap smoothing policy
- enum BitmapSmoothingPolicy {
-
- /// Only smooth when _quality >= BEST
- //
- /// This is the policy for bitmap fills
- /// defined by SWF up to version 7:
- /// - SWF::FILL_CLIPPED_BITMAP
- /// - SWF::FILL_TILED_BITMAP
- ///
- BITMAP_SMOOTHING_UNSPECIFIED,
-
- /// Always smooth if _quality > LOW
- //
- /// This is the policy for non-hard bitmap fills
- /// defined by SWF 8 and higher:
- /// - SWF::FILL_CLIPPED_BITMAP
- /// - SWF::FILL_TILED_BITMAP
- ///
- BITMAP_SMOOTHING_ON,
-
- /// Never smooth
- ///
- /// MovieClip.forceSmoothing can force this to
- /// behave like BITMAP_SMOOTHING_ON
- ///
- /// This is the policy for hard bitmap fills
- /// introduced in SWF 8:
- /// - SWF::FILL_CLIPPED_BITMAP_HARD
- /// - SWF::FILL_TILED_BITMAP_HARD
- ///
- ///
- BITMAP_SMOOTHING_OFF
- };
-
-
- /// Create a solid opaque white fill.
- fill_style();
-
- /// Construct a clipped bitmap fill style, for
- /// use by bitmap shape DisplayObject.
- ///
- /// TODO: use a subclass for this
- /// TODO: provide a setBitmap, for consisteny with other setType() methods
- ///
- /// @param bitmap
- /// The bitmap DisplayObject definition to use with this bitmap fill.
- ///
- /// @param mat
- /// The SWFMatrix to apply to the bitmap.
- ///
- fill_style(const BitmapInfo* const bitmap, const SWFMatrix& mat);
-
- ~fill_style() {}
-
- /// Turn this fill style into a solid fill.
- //
- /// This is used for dynamic gradient generation.
- //
- void setSolid(const rgba& color);
-
- /// Turn this fill style into a linear gradient
- //
- /// This is used for dynamic gradient generation.
- //
- /// Note: passing only one gradient record will result in a solid fill
- /// style, not a gradient. This is for compatibility with dynamic
- /// fill style generation.
- //
- /// @param gradients Gradient records.
- /// @param mat Gradient SWFMatrix.
- void setLinearGradient(const std::vector<gradient_record>& gradients,
- const SWFMatrix& mat);
-
- /// Turn this fill style into a radial gradient
- //
- /// This is used for dynamic gradient generation.
- //
- /// Note: passing only one gradient record will result in a solid fill
- /// style, not a gradient. This is for compatibility with dynamic
- /// fill style generation.
- //
- /// @param gradients Gradient records.
- /// @param mat Gradient SWFMatrix.
- void setRadialGradient(const std::vector<gradient_record>& gradients,
- const SWFMatrix& mat);
-
- /// Read the fill style from a stream
- //
- /// TODO: use a subclass for this (swf_fill_style?)
- ///
- /// Throw a ParserException if there's no enough bytes in the
- /// currently opened tag for reading. See stream::ensureBytes()
- void read(SWFStream& in, SWF::TagType t, movie_definition& m,
- const RunResources& r, fill_style *pOther = 0);
-
- /// \brief
- /// Make a BitmapInfo* corresponding to our gradient.
- /// We can use this to set the gradient fill style.
- const BitmapInfo* create_gradient_bitmap(Renderer& renderer) const;
-
- /// \brief
- /// Makes sure that _gradientBitmapInfo is not NULL. Calls
- /// create_gradient_bitmap() if necessary and returns _gradientBitmapInfo.
- const BitmapInfo* need_gradient_bitmap(Renderer& renderer) const;
-
- rgba get_color() const {
- return m_color;
- }
-
- void set_color(rgba new_color) {
- m_color = new_color;
- }
-
- /// Get fill type, see SWF::fill_style_type
- boost::uint8_t get_type() const {
- return m_type;
- }
-
- SWF::gradient_spread_mode get_gradient_spread_mode() const {
- return m_spread_mode;
- }
-
- SWF::gradient_interpolation_mode get_gradient_interpolation_mode() const {
- return m_interpolation;
- }
-
- /// Sets this style to a blend of a and b. t = [0,1] (for shape morphing)
- void set_lerp(const fill_style& a, const fill_style& b, float t);
-
- /// Returns the bitmap info for all styles except solid fills
- //
- /// NOTE: calling this method against a solid fill style will
- /// result in a failed assertion.
- ///
- /// NOTE2: this function can return NULL if the DisplayObject_id
- /// specified for the style in the SWF does not resolve
- /// to a DisplayObject defined in the DisplayObjects dictionary.
- /// (it happens..)
- ///
- const BitmapInfo* get_bitmap_info(Renderer& renderer) const;
-
- BitmapSmoothingPolicy getBitmapSmoothingPolicy() const {
- return _bitmapSmoothingPolicy;
- }
-
- /// Returns the bitmap transformation SWFMatrix
- const SWFMatrix& getBitmapMatrix() const;
-
- /// Returns the gradient transformation SWFMatrix
- const SWFMatrix& getGradientMatrix() const;
-
- /// Returns the number of color stops in the gradient
- size_t get_color_stop_count() const;
-
- /// Returns the color stop value at a specified index
- const gradient_record& get_color_stop(size_t index) const;
-
- /// Get and set the focal point for gradient focal fills.
- /// This should be from -1.0 to 1.0, representing the left
- /// and right edges of the rectangle.
- float get_focal_point() const { return m_focal_point; }
- void set_focal_point(float f) { m_focal_point = f; }
-
-private:
-
- /// Return the color at the specified ratio into our gradient.
- //
- /// @param ratio
- /// Ratio is in the range [0, 255].
- rgba sample_gradient(boost::uint8_t ratio) const;
-
- // For BITMAP or GRADIENT types
- SWFMatrix _matrix;
-
- // For BITMAP or GRADIENT types
- boost::intrusive_ptr<const BitmapInfo> _bitmapInfo;
-
- // For SOLID type (and arguably GRADIENT too)
- rgba m_color;
-
- // Only for GRADIENT type
- float m_focal_point; // For focal fill gradients.
- std::vector<gradient_record> m_gradients;
- SWF::gradient_spread_mode m_spread_mode;
- SWF::gradient_interpolation_mode m_interpolation;
-
- /// Fill type, see SWF::fill_style_type
- boost::uint8_t m_type;
-
- // Only for BITMAP type
- //
- // 0: unspecified (smooth with _quality >= BEST)
- // 1: smooth (smooth with _quality >= MEDIUM)
- // 2: don't smooth, can be forced with .forceSmoothing, in
- // which case it becomes as policy 1
- BitmapSmoothingPolicy _bitmapSmoothingPolicy;
-};
-
-DSOEXPORT std::ostream& operator << (std::ostream& os,
- const fill_style::BitmapSmoothingPolicy& p);
+ boost::uint8_t ratio;
+ rgba color;
+};
+
+
+/// A BitmapFill
+//
+/// BitmapFills can refer to a parsed bitmap tag or be constructed from
+/// bitmap data. They are used for Bitmap characters.
+//
+/// Presently all members are immutable after construction. It is of course
+/// possible to change the appearance of the fill by changing the BitmapInfo
+/// it refers to.
+//
+/// TODO: check the following:
+//
+/// It may be necessary to allow setting the smoothing policy; the use of
+/// this should certainly be extended to non-static BitmapFills.
+class DSOEXPORT BitmapFill
+{
+public:
+
+ /// How to smooth the bitmap.
+ enum SmoothingPolicy {
+ SMOOTHING_UNSPECIFIED,
+ SMOOTHING_ON,
+ SMOOTHING_OFF
+ };
+
+ /// Whether the fill is tiled or clipped.
+ //
+ /// Clipped fills use the edge pixels to fill any area outside the bounds
+ /// of the image.
+ enum Type {
+ CLIPPED,
+ TILED
+ };
+
+ /// Construct a BitmapFill from arbitrary bitmap data.
+ //
+ /// TODO: check the smoothing policy here!
+ BitmapFill(Type t, const BitmapInfo* bi, const SWFMatrix& m)
+ :
+ _type(t),
+ _smoothingPolicy(SMOOTHING_UNSPECIFIED),
+ _matrix(m),
+ _bitmapInfo(bi),
+ _md(0),
+ _id(0)
+ {
+ }
+
+ /// Construct a static BitmapFill using a SWF tag.
+ BitmapFill(SWF::FillType t, movie_definition* md, boost::uint16_t id,
+ const SWFMatrix& m);
+
+ /// Copy a BitmapFill
+ //
+ /// The copied BitmapFill refers to the same bitmap id in the same
+ /// movie_definition as the original.
+ BitmapFill(const BitmapFill& other)
+ :
+ _type(other._type),
+ _smoothingPolicy(other._smoothingPolicy),
+ _matrix(other._matrix),
+ _bitmapInfo(other._bitmapInfo),
+ _md(other._md),
+ _id(other._id)
+ {}
+
+ /// Set this fill to a lerp of two other BitmapFills.
+ void setLerp(const BitmapFill& a, const BitmapFill& b, double ratio);
+
+ /// Get the Type of this BitmapFill
+ //
+ /// BitmapFills are either tiled or clipped.
+ Type type() const {
+ return _type;
+ }
+
+ /// Get the smoothing policy of this BitmapFill.
+ SmoothingPolicy smoothingPolicy() const {
+ return _smoothingPolicy;
+ }
+
+ /// Get the actual Bitmap data.
+ const BitmapInfo* bitmap() const;
+
+ /// Get the matrix of this BitmapFill.
+ const SWFMatrix& matrix() const {
+ return _matrix;
+ }
+
+private:
+
+ Type _type;
+
+ SmoothingPolicy _smoothingPolicy;
+
+ SWFMatrix _matrix;
+
+ /// A Bitmap, used for dynamic fills and to cache parsed bitmaps.
+ mutable boost::intrusive_ptr<const BitmapInfo> _bitmapInfo;
+
+ /// The movie definition containing the bitmap
+ movie_definition* _md;
+
+ // The id of the tag containing the bitmap
+ boost::uint16_t _id;
+};
+
+
+/// A GradientFill
+//
+/// TODO: clean this up!
+class DSOEXPORT GradientFill
+{
+public:
+
+ /// The type of GradientFill
+ //
+ /// A Focal fill is a gradient fill with a focal point.
+ enum Type
+ {
+ LINEAR,
+ RADIAL
+ };
+
+ typedef std::vector<GradientRecord> GradientRecords;
+
+ /// Construct a GradientFill
+ //
+ /// Optionally the records can be passed here.
+ //
+ /// The actual matrix of the gradient depends on the type; the constructor
+ /// handles this, and users should just pass the user matrix.
+ GradientFill(Type t, const SWFMatrix& m,
+ const GradientRecords& = GradientRecords());
+
+ Type type() const {
+ return _type;
+ }
+
+ const SWFMatrix& matrix() const {
+ return _matrix;
+ }
+
+ /// Set this fill to a lerp of two other GradientFills.
+ void setLerp(const GradientFill& a, const GradientFill& b, double ratio);
+
+ void setRecords(const GradientRecords& recs) {
+ assert(recs.size() > 1);
+ _gradients = recs;
+ }
+
+ /// Get the number of records in this GradientFill
+ size_t recordCount() const {
+ return _gradients.size();
+ }
+
+ /// Query the GradientRecord at the specified index
+ //
+ /// There are recordCount() records.
+ const GradientRecord& record(size_t i) const {
+ assert(i < _gradients.size());
+ return _gradients[i];
+ }
+
+ /// Set the focal point.
+ //
+ /// Value will be clamped to the range -1..1; callers don't need to check.
+ void setFocalPoint(double d);
+
+ /// Get the focal point of this GradientFill
+ //
+ /// If the focal point is 0.0, it is a simple radial fill.
+ double focalPoint() const {
+ return _focalPoint;
+ }
+
+ SWF::SpreadMode spreadMode;
+ SWF::InterpolationMode interpolation;
+
+private:
+
+ double _focalPoint;
+ GradientRecords _gradients;
+ Type _type;
+ SWFMatrix _matrix;
+};
+
+/// A SolidFill containing one color.
+//
+/// SolidFills are the simplest fill, containing only a single color.
+struct DSOEXPORT SolidFill
+{
+public:
+
+ /// Construct a SolidFill.
+ explicit SolidFill(const rgba& c)
+ :
+ _color(c)
+ {}
+
+ /// Copy a SolidFill.
+ SolidFill(const SolidFill& other)
+ :
+ _color(other._color)
+ {}
+
+ /// Set this fill to a lerp of two other SolidFills.
+ void setLerp(const SolidFill& a, const SolidFill& b, double ratio) {
+ _color.set_lerp(a.color(), b.color(), ratio);
+ }
+
+ /// Get the color of the fill.
+ rgba color() const {
+ return _color;
+ }
+
+private:
+ rgba _color;
+};
+
+/// FillStyle describes the various fill styles for shapes
+//
+/// The FillStyle class is effectively a boost::variant, but to allow passing
+/// FillStyles using a forward declaration (and reducing compile times),
+/// it's necessary to use a class.
+class DSOEXPORT FillStyle
+{
+public:
+
+ typedef boost::variant<BitmapFill, SolidFill, GradientFill> Fill;
+
+ /// Construct a FillStyle from any Fill.
+ //
+ /// The non-explicit templated contructor allows the same syntax as a
+ /// simple boost::variant:
+ /// FillStyle f = GradientFill();
+ template<typename T> FillStyle(const T& f) : fill(f) {}
+
+ FillStyle(const FillStyle& other)
+ :
+ fill(other.fill)
+ {}
+
+ Fill fill;
+
+};
+
+/// Set the FillStyle to a lerp of a and b.
+//
+/// Callers must ensure that all FillStyles have exactly the same type! Most
+/// errors are caught by type-checking and will throw an unhandled exception.
+void setLerp(FillStyle& f, const FillStyle& a, const FillStyle& b, double t);
+
+/// Either a single or a morph-pair FillStyle.
+typedef std::pair<FillStyle, boost::optional<FillStyle> > OptionalFillPair;
+
+/// Read FillStyles from a stream
+//
+/// Read either single or morph-pair fill styles from a stream.
+OptionalFillPair readFills(SWFStream& in, SWF::TagType t, movie_definition& m,
+ bool readMorph);
+
+DSOEXPORT std::ostream& operator<<(std::ostream& os,
+ const BitmapFill::SmoothingPolicy& p);
} // namespace gnash
-
-#endif // GNASH_FILL_STYLE_H
+#endif
// Local Variables:
=== modified file 'libcore/FreetypeGlyphsProvider.cpp'
--- a/libcore/FreetypeGlyphsProvider.cpp 2010-07-28 07:57:23 +0000
+++ b/libcore/FreetypeGlyphsProvider.cpp 2010-07-31 16:42:49 +0000
@@ -27,7 +27,7 @@
#include "GnashException.h"
#include "ShapeRecord.h"
#include "log.h"
-#include "fill_style.h"
+#include "FillStyle.h"
#ifdef USE_FREETYPE
# include <ft2build.h>
@@ -98,8 +98,8 @@
_x(0),
_y(0)
{
- fill_style f;
- f.setSolid(rgba(255, 255, 255, 255));
+ /// A default fill style is solid white.
+ FillStyle f = SolidFill(rgba());
_shape.addFillStyle(f);
_shape.addPath(Path(_x, _y, 1, 0, 0, true));
_currPath = &_shape.currentPath();
=== modified file 'libcore/Geometry.h'
--- a/libcore/Geometry.h 2010-03-12 23:37:40 +0000
+++ b/libcore/Geometry.h 2010-07-31 14:05:26 +0000
@@ -489,7 +489,7 @@
/// The fill index (1-based).
/// When this path is added to a DefineShapeTag,
/// the index (decremented by 1) will reference an element
- /// in the fill_style vector defined for that shape.
+ /// in the FillStyle vector defined for that shape.
/// If zero, no fill will be active.
///
void setLeftFill(unsigned f)
@@ -508,7 +508,7 @@
/// The fill index (1-based).
/// When this path is added to a DefineShapeTag,
/// the index (decremented by 1) will reference an element
- /// in the fill_style vector defined for that shape.
+ /// in the FillStyle vector defined for that shape.
/// If zero, no fill will be active.
///
void setRightFill(unsigned f)
=== modified file 'libcore/LineStyle.cpp'
--- a/libcore/LineStyle.cpp 2010-03-12 15:42:07 +0000
+++ b/libcore/LineStyle.cpp 2010-08-01 06:48:24 +0000
@@ -28,11 +28,29 @@
#include "movie_definition.h"
#include "SWF.h"
#include "GnashException.h"
-#include "fill_style.h"
+#include "FillStyle.h"
#include "GnashNumeric.h"
namespace gnash {
+namespace {
+
+class GetColor : public boost::static_visitor<rgba>
+{
+public:
+ rgba operator()(const SolidFill& f) const {
+ return f.color();
+ }
+ rgba operator()(const GradientFill&) const {
+ return rgba();
+ }
+ rgba operator()(const BitmapFill&) const {
+ return rgba();
+ }
+};
+
+}
+
LineStyle::LineStyle()
:
m_width(0),
@@ -50,18 +68,20 @@
void
LineStyle::read_morph(SWFStream& in, SWF::TagType t, movie_definition& md,
- const RunResources& r, LineStyle *pOther)
+ const RunResources& /*r*/, LineStyle *pOther)
{
if (t == SWF::DEFINEMORPHSHAPE)
{
in.ensureBytes(2 + 2);
m_width = in.read_u16();
pOther->m_width = in.read_u16();
- m_color.read(in, t);
- pOther->m_color.read(in, t);
+ m_color = readRGBA(in);
+ pOther->m_color = readRGBA(in);
return;
}
+ assert(t == SWF::DEFINEMORPHSHAPE2 || t == SWF::DEFINEMORPHSHAPE2_);
+
// MorphShape 2 from here down.
in.ensureBytes(4 + 2);
@@ -84,66 +104,73 @@
in.ensureBytes(2);
_miterLimitFactor = in.read_short_ufixed();
}
- if (has_fill)
- {
- // read fill styles for strokes.
- // TODO: don't throw away this information, should be passed to
renderer.
- fill_style f, g;
- f.read(in, t, md, r, &g);
- m_color = f.get_color();
- pOther->m_color = g.get_color();
+ if (has_fill) {
+ OptionalFillPair fp = readFills(in, t, md, true);
+
+ // TODO: store a fill style properly, removing the need for the
+ // visitor.
+ m_color = boost::apply_visitor(GetColor(), fp.first.fill);
+ pOther->m_color = boost::apply_visitor(GetColor(), fp.second->fill);
}
- else
- {
- m_color.read(in, t);
- pOther->m_color.read(in, t);
+ else {
+ m_color = readRGBA(in);
+ pOther->m_color = readRGBA(in);
}
}
void
LineStyle::read(SWFStream& in, SWF::TagType t, movie_definition& md,
- const RunResources& r)
+ const RunResources& /*r*/)
{
- if (!(t == SWF::DEFINESHAPE4 || t == SWF::DEFINESHAPE4_))
- {
- in.ensureBytes(2);
- m_width = in.read_u16();
- m_color.read(in, t);
- return;
- }
-
- // TODO: Unfinished. Temporary to allow DefineShape4 to work in many
- // cases, but does not work correctly in all cases.
- in.ensureBytes(2+2);
- m_width = in.read_u16();
-
- int flags1 = in.read_u8();
- int flags2 = in.read_u8();
- _startCapStyle = (CapStyle)((flags1 & 0xC0) >> 6);
- _joinStyle = (JoinStyle)((flags1 & 0x30) >> 4);
- bool has_fill = flags1 & (1 << 3);
- _scaleHorizontally = !(flags1 & (1 << 2));
- _scaleVertically = !(flags1 & (1 << 1));
- _pixelHinting = flags1 & (1 << 0);
- _noClose = flags2 & (1 << 2);
- _endCapStyle = (CapStyle) (flags2 & 0x03);
-
- if (_joinStyle == JOIN_MITER)
- {
- in.ensureBytes(2);
- _miterLimitFactor = in.read_short_ufixed();
- }
- if (has_fill)
- {
- // read fill styles for strokes.
- // TODO: don't throw away this information, should be passed to
renderer.
- fill_style f;
- f.read(in, t, md, r);
- m_color = f.get_color();
- }
- else
- {
- m_color.read(in, t);
+ switch (t) {
+
+ default:
+ in.ensureBytes(2);
+ m_width = in.read_u16();
+ m_color = readRGBA(in);
+ return;
+
+ case SWF::DEFINESHAPE:
+ case SWF::DEFINESHAPE2:
+ in.ensureBytes(2);
+ m_width = in.read_u16();
+ m_color = readRGB(in);
+ return;
+
+ case SWF::DEFINESHAPE4:
+ case SWF::DEFINESHAPE4_:
+ {
+ // TODO: Unfinished. Temporary to allow DefineShape4 to work in
+ // many cases, but does not work correctly in all cases.
+ in.ensureBytes(2+2);
+ m_width = in.read_u16();
+
+ const boost::uint8_t flags1 = in.read_u8();
+ const boost::uint8_t flags2 = in.read_u8();
+
+ _startCapStyle = (CapStyle)((flags1 & 0xC0) >> 6);
+ _joinStyle = (JoinStyle)((flags1 & 0x30) >> 4);
+ const bool has_fill = flags1 & (1 << 3);
+ _scaleHorizontally = !(flags1 & (1 << 2));
+ _scaleVertically = !(flags1 & (1 << 1));
+ _pixelHinting = flags1 & (1 << 0);
+ _noClose = flags2 & (1 << 2);
+ _endCapStyle = (CapStyle) (flags2 & 0x03);
+
+ if (_joinStyle == JOIN_MITER) {
+ in.ensureBytes(2);
+ _miterLimitFactor = in.read_short_ufixed();
+ }
+ if (has_fill) {
+ // TODO: store a fill style properly, removing the need for
the
+ // visitor.
+ OptionalFillPair fp = readFills(in, t, md, false);
+ m_color = boost::apply_visitor(GetColor(), fp.first.fill);
+ }
+ else {
+ m_color = readRGBA(in);
+ }
+ }
}
}
@@ -151,7 +178,7 @@
LineStyle::set_lerp(const LineStyle& ls1, const LineStyle& ls2, float ratio)
{
m_width = static_cast<boost::uint16_t>(
- frnd(flerp(ls1.getThickness(), ls2.getThickness(), ratio)));
+ frnd(lerp<float>(ls1.getThickness(), ls2.getThickness(), ratio)));
m_color.set_lerp(ls1.get_color(), ls2.get_color(), ratio);
if ( ls1._scaleVertically != ls2._scaleVertically )
{
@@ -163,8 +190,7 @@
}
}
-// end of namespace
-}
+} // namespace gnash
// Local Variables:
=== modified file 'libcore/LineStyle.h'
--- a/libcore/LineStyle.h 2010-01-18 06:21:14 +0000
+++ b/libcore/LineStyle.h 2010-07-30 15:03:01 +0000
@@ -186,6 +186,12 @@
float _miterLimitFactor;
};
+
+inline void
+setLerp(LineStyle& s, const LineStyle& ls1, const LineStyle& ls2, double
ratio)
+{
+ s.set_lerp(ls1, ls2, ratio);
+}
} // namespace gnash
=== modified file 'libcore/Makefile.am'
--- a/libcore/Makefile.am 2010-07-24 13:44:22 +0000
+++ b/libcore/Makefile.am 2010-07-31 14:05:26 +0000
@@ -124,7 +124,7 @@
StreamProvider.cpp \
Button.cpp \
DisplayList.cpp \
- fill_style.cpp \
+ FillStyle.cpp \
Font.cpp \
fontlib.cpp \
impl.cpp \
@@ -277,7 +277,7 @@
swf/TagLoadersTable.h \
swf/SWF.h \
MovieFactory.h \
- fill_style.h \
+ FillStyle.h \
LineStyle.h \
BitmapInfo.h \
RGBA.h \
=== modified file 'libcore/MovieClip.h'
--- a/libcore/MovieClip.h 2010-07-13 06:16:31 +0000
+++ b/libcore/MovieClip.h 2010-07-31 14:05:26 +0000
@@ -47,7 +47,7 @@
class swf_event;
class drag_state;
class LoadVariablesThread;
- class gradient_record;
+ class GradientRecord;
class TextField;
class BitmapData_as;
class BitmapInfo;
@@ -559,73 +559,10 @@
const SWFRect& clipRect = SWFRect(),
bool smooth = false);
- /// @name Drawing API
- /// @{
-
- void lineStyle(boost::uint16_t thickness, const rgba& color,
- bool vScale=true, bool hScale=true,
- bool pixelHinting=false,
- bool noClose=false,
- CapStyle startCapStyle=CAP_ROUND,
- CapStyle endCapStyle=CAP_ROUND,
- JoinStyle joinStyle=JOIN_ROUND,
- float miterLimitFactor=1.0f)
- {
- _drawable.lineStyle(thickness, color, vScale, hScale,
- pixelHinting, noClose,
- startCapStyle, endCapStyle, joinStyle,
- miterLimitFactor);
- }
-
- void resetLineStyle()
- {
- _drawable.resetLineStyle();
- }
-
- void beginFill(const rgba& color)
- {
- _drawable.beginFill(color);
- }
-
- void beginLinearGradientFill(const std::vector<gradient_record>& grad,
- const SWFMatrix& mat)
- {
- _drawable.beginLinearGradientFill(grad, mat);
- }
-
- void beginRadialGradientFill(const std::vector<gradient_record>& grad,
- const SWFMatrix& mat)
- {
- _drawable.beginRadialGradientFill(grad, mat);
- }
-
- void endFill()
- {
- _drawable.endFill();
- }
-
- void moveTo(boost::int32_t x, boost::int32_t y)
- {
- _drawable.moveTo(x, y);
- }
-
- void lineTo(boost::int32_t x, boost::int32_t y)
- {
- set_invalidated();
- _drawable.lineTo(x, y, getDefinitionVersion());
- }
-
- void curveTo(boost::int32_t cx, boost::int32_t cy,
- boost::int32_t ax, boost::int32_t ay)
- {
- set_invalidated();
- _drawable.curveTo(cx, cy, ax, ay, getDefinitionVersion());
- }
-
- void clear()
- {
- set_invalidated();
- _drawable.clear();
+ /// Direct access to the Graphics object for drawing.
+ DynamicShape& graphics() {
+ set_invalidated();
+ return _drawable;
}
/// Set focus to this MovieClip
=== modified file 'libcore/RGBA.cpp'
--- a/libcore/RGBA.cpp 2010-01-18 06:38:43 +0000
+++ b/libcore/RGBA.cpp 2010-08-01 06:51:26 +0000
@@ -26,59 +26,44 @@
namespace gnash {
-void
-rgba::read(SWFStream& in, SWF::TagType tag)
-{
- switch (tag)
- {
- case SWF::DEFINESHAPE:
- case SWF::DEFINESHAPE2:
- read_rgb(in);
- break;
- default:
- case SWF::DEFINESHAPE3:
- read_rgba(in);
- break;
- }
-}
-
-void
-rgba::read_rgba(SWFStream& in)
-{
- read_rgb(in);
- in.ensureBytes(1);
- m_a = in.read_u8();
-}
-
-/// Can throw ParserException on premature end of input stream
-void
-rgba::read_rgb(SWFStream& in)
-{
- in.ensureBytes(3);
- m_r = in.read_u8();
- m_g = in.read_u8();
- m_b = in.read_u8();
- m_a = 0x0FF;
-}
-
std::string
rgba::toShortString() const
{
std::stringstream ss;
- ss << (unsigned)m_r << ","
- << (unsigned)m_g << ","
- << (unsigned)m_b << ","
- << (unsigned)m_a;
+ ss << +m_r << "," << +m_g << "," << +m_b << "," << +m_a;
return ss.str();
}
void
rgba::set_lerp(const rgba& a, const rgba& b, float f)
{
- m_r = static_cast<boost::uint8_t>(frnd(flerp(a.m_r, b.m_r, f)));
- m_g = static_cast<boost::uint8_t>(frnd(flerp(a.m_g, b.m_g, f)));
- m_b = static_cast<boost::uint8_t>(frnd(flerp(a.m_b, b.m_b, f)));
- m_a = static_cast<boost::uint8_t>(frnd(flerp(a.m_a, b.m_a, f)));
+ m_r = frnd(lerp<float>(a.m_r, b.m_r, f));
+ m_g = frnd(lerp<float>(a.m_g, b.m_g, f));
+ m_b = frnd(lerp<float>(a.m_b, b.m_b, f));
+ m_a = frnd(lerp<float>(a.m_a, b.m_a, f));
+}
+
+rgba
+readRGBA(SWFStream& in)
+{
+ in.ensureBytes(4);
+ const boost::uint8_t r = in.read_u8();
+ const boost::uint8_t g = in.read_u8();
+ const boost::uint8_t b = in.read_u8();
+ const boost::uint8_t a = in.read_u8();
+ return rgba(r, g, b, a);
+}
+
+/// Can throw ParserException on premature end of input stream
+rgba
+readRGB(SWFStream& in)
+{
+ in.ensureBytes(3);
+ const boost::uint8_t r = in.read_u8();
+ const boost::uint8_t g = in.read_u8();
+ const boost::uint8_t b = in.read_u8();
+ const boost::uint8_t a = 0xff;
+ return rgba(r, g, b, a);
}
rgba
@@ -101,11 +86,8 @@
std::ostream&
operator<<(std::ostream& os, const rgba& r)
{
- return os << "rgba: "
- << static_cast<unsigned>(r.m_r) << ","
- << static_cast<unsigned>(r.m_g) << ","
- << static_cast<unsigned>(r.m_b) << ","
- << static_cast<unsigned>(r.m_a);
+ return os << "rgba: " << +r.m_r << "," << +r.m_g << "," << +r.m_b << ","
+ << +r.m_a;
}
} // namespace gnash
=== modified file 'libcore/RGBA.h'
--- a/libcore/RGBA.h 2010-01-18 06:38:37 +0000
+++ b/libcore/RGBA.h 2010-08-01 06:48:24 +0000
@@ -101,17 +101,6 @@
return toRGB() + (m_a << 24);
}
- /// Initialize from input stream.
- //
- /// @param in The input SWFStream
- ///
- /// @param t The tag type, used to determine whether to read an RGB
- /// or RGBA record.
- //
- /// Throw a ParserException if there are not enough bytes in the
- /// currently opened tag for reading. See SWFStream::ensureBytes()
- void read(SWFStream& in, SWF::TagType t);
-
/// Set r, g, b, a values
void set(boost::uint8_t r, boost::uint8_t g, boost::uint8_t b,
boost::uint8_t a) {
@@ -127,15 +116,6 @@
/// Neater string output (example: "0,0,0,255")
std::string toShortString() const;
- /// Initialize from input stream (reads RGBA)
- //
- /// Throw a ParserException if there's no enough bytes in the
- /// currently opened tag for reading. See SWFStream::ensureBytes()
- void read_rgba(SWFStream& in);
-
- /// Initialize from intput stream (reads RGB)
- void read_rgb(SWFStream& in);
-
friend std::ostream& operator<< (std::ostream& os, const rgba& r);
bool operator==(const rgba& o) const {
@@ -154,6 +134,15 @@
};
std::ostream& operator<< (std::ostream& os, const rgba& r);
+
+/// Initialize from input stream (reads RGBA)
+//
+/// Throw a ParserException if there's no enough bytes in the
+/// currently opened tag for reading. See SWFStream::ensureBytes()
+rgba readRGBA(SWFStream& in);
+
+/// Initialize from intput stream (reads RGB)
+rgba readRGB(SWFStream& in);
/// Create an RGBA value from a hex string (e.g. FF0000)
//
=== modified file 'libcore/SWFMatrix.cpp'
--- a/libcore/SWFMatrix.cpp 2010-03-12 23:37:40 +0000
+++ b/libcore/SWFMatrix.cpp 2010-08-01 07:47:27 +0000
@@ -51,37 +51,29 @@
} // anonymous namepace
-SWFMatrix::SWFMatrix()
-{
- // Default to identity.
- sx = sy = 65536;
- shx = shy = tx = ty = 0;
-}
-
-void
-SWFMatrix::read(SWFStream& in)
-// Initialize from the stream.
+SWFMatrix
+readSWFMatrix(SWFStream& in)
{
in.align();
- set_identity();
-
in.ensureBits(1);
- bool has_scale = in.read_bit();
- if (has_scale)
- {
+ const bool has_scale = in.read_bit();
+
+ boost::int32_t sx = 65536;
+ boost::int32_t sy = 65536;
+ if (has_scale) {
in.ensureBits(5);
- int scale_nbits = in.read_uint(5);
-
+ const boost::uint8_t scale_nbits = in.read_uint(5);
in.ensureBits(scale_nbits * 2);
sx = in.read_sint(scale_nbits);
sy = in.read_sint(scale_nbits);
}
in.ensureBits(1);
- bool has_rotate = in.read_bit();
- if (has_rotate)
- {
+ const bool has_rotate = in.read_bit();
+ boost::int32_t shx = 0;
+ boost::int32_t shy = 0;
+ if (has_rotate) {
in.ensureBits(5);
int rotate_nbits = in.read_uint(5);
@@ -91,21 +83,15 @@
}
in.ensureBits(5);
- int translate_nbits = in.read_uint(5);
- if (translate_nbits > 0)
- {
+ const boost::uint8_t translate_nbits = in.read_uint(5);
+ boost::int32_t tx = 0;
+ boost::int32_t ty = 0;
+ if (translate_nbits) {
in.ensureBits(translate_nbits * 2);
tx = in.read_sint(translate_nbits);
ty = in.read_sint(translate_nbits);
}
-}
-
-bool
-SWFMatrix::is_valid() const
-{
- // The integer SWFMatrix is always valid now from outside.
- // swallow it if anything wrong inside this class.
- return true;
+ return SWFMatrix(sx, shx, shy, sy, tx, ty);
}
void
@@ -120,8 +106,8 @@
void
SWFMatrix::transform(boost::int32_t& x, boost::int32_t& y) const
{
- boost::int32_t t0 = Fixed16Mul(sx, x) + Fixed16Mul(shy, y) + tx;
- boost::int32_t t1 = Fixed16Mul(shx,x) + Fixed16Mul(sy, y) + ty;
+ const boost::int32_t t0 = Fixed16Mul(sx, x) + Fixed16Mul(shy, y) + tx;
+ const boost::int32_t t1 = Fixed16Mul(shx,x) + Fixed16Mul(sy, y) + ty;
x = t0;
y = t1;
}
@@ -129,10 +115,10 @@
void
SWFMatrix::transform(geometry::Range2d<boost::int32_t>& r) const
{
- boost::int32_t xmin = r.getMinX(),
- xmax = r.getMaxX(),
- ymin = r.getMinY(),
- ymax = r.getMaxY();
+ const boost::int32_t xmin = r.getMinX();
+ const boost::int32_t xmax = r.getMaxX();
+ const boost::int32_t ymin = r.getMinY();
+ const boost::int32_t ymax = r.getMaxY();
point p0(xmin, ymin);
point p1(xmin, ymax);
@@ -152,7 +138,6 @@
void
SWFMatrix::set_identity()
-// Set the SWFMatrix to identity.
{
sx = sy = 65536;
shx = shy = tx = ty = 0;
@@ -160,11 +145,8 @@
void
SWFMatrix::concatenate(const SWFMatrix& m)
-// Concatenate m's transform onto ours. When
-// transforming points, m happens first, then our
-// original SWFMatrix.
{
- SWFMatrix t;
+ SWFMatrix t;
t.sx = Fixed16Mul(sx, m.sx) + Fixed16Mul(shy, m.shx);
t.shx = Fixed16Mul(shx, m.sx) + Fixed16Mul(sy, m.shx);
t.shy = Fixed16Mul(sx, m.shy) + Fixed16Mul(shy, m.sy);
@@ -196,16 +178,16 @@
sy = Fixed16Mul(sy, DoubleToFixed16(yscale));
}
+// Set this SWFMatrix to a blend of m1 and m2, parameterized by t.
void
SWFMatrix::set_lerp(const SWFMatrix& m1, const SWFMatrix& m2, float t)
-// Set this SWFMatrix to a blend of m1 and m2, parameterized by t.
{
- sx = flerp(m1.sx, m2.sx, t);
- shx = flerp(m1.shx, m2.shx, t);
- shy = flerp(m1.shy, m2.shy, t);
- sy = flerp(m1.sy, m2.sy, t);
- tx = flerp(m1.tx, m2.tx, t);
- ty = flerp(m1.ty, m2.ty, t);
+ sx = lerp<float>(m1.sx, m2.sx, t);
+ shx = lerp<float>(m1.shx, m2.shx, t);
+ shy = lerp<float>(m1.shy, m2.shy, t);
+ sy = lerp<float>(m1.sy, m2.sy, t);
+ tx = lerp<float>(m1.tx, m2.tx, t);
+ ty = lerp<float>(m1.ty, m2.ty, t);
}
void
@@ -213,8 +195,8 @@
// Set the scale & rotation part of the SWFMatrix.
// angle in radians.
{
- double cos_angle = std::cos(angle);
- double sin_angle = std::sin(angle);
+ const double cos_angle = std::cos(angle);
+ const double sin_angle = std::sin(angle);
sx = DoubleToFixed16(x_scale * cos_angle);
shy = DoubleToFixed16(y_scale * -sin_angle);
shx = DoubleToFixed16(x_scale * sin_angle);
@@ -224,40 +206,43 @@
void
SWFMatrix::set_x_scale(double xscale)
{
- double rot_x = std::atan2(static_cast<double>(shx),
static_cast<double>(sx));
- sx = DoubleToFixed16(xscale * std::cos(rot_x));
- shx = DoubleToFixed16(xscale * std::sin(rot_x));
+ const double rot_x =
+ std::atan2(static_cast<double>(shx), static_cast<double>(sx));
+ sx = DoubleToFixed16(xscale * std::cos(rot_x));
+ shx = DoubleToFixed16(xscale * std::sin(rot_x));
}
void
SWFMatrix::set_y_scale(double yscale)
{
- double rot_y = std::atan2(static_cast<double>(-shy),
static_cast<double>(sy));
+ const double rot_y =
+ std::atan2(static_cast<double>(-shy), static_cast<double>(sy));
shy = -DoubleToFixed16(yscale * std::sin(rot_y));
- sy = DoubleToFixed16(yscale * std::cos(rot_y));
+ sy = DoubleToFixed16(yscale * std::cos(rot_y));
}
void
SWFMatrix::set_scale(double xscale, double yscale)
{
- double rotation = get_rotation();
+ const double rotation = get_rotation();
set_scale_rotation(xscale, yscale, rotation);
}
void
SWFMatrix::set_rotation(double rotation)
{
- double rot_x = std::atan2(static_cast<double>(shx),
static_cast<double>(sx));
- double rot_y = std::atan2(static_cast<double>(-shy),
- static_cast<double>(sy));
- double scale_x = get_x_scale();
- double scale_y = get_y_scale();
+ const double rot_x =
+ std::atan2(static_cast<double>(shx), static_cast<double>(sx));
+ const double rot_y =
+ std::atan2(static_cast<double>(-shy), static_cast<double>(sy));
+ const double scale_x = get_x_scale();
+ const double scale_y = get_y_scale();
- sx = DoubleToFixed16(scale_x * std::cos(rotation));
+ sx = DoubleToFixed16(scale_x * std::cos(rotation));
shx = DoubleToFixed16(scale_x * std::sin(rotation));
shy = -DoubleToFixed16(scale_y * std::sin(rot_y - rot_x + rotation));
- sy = DoubleToFixed16(scale_y * std::cos(rot_y - rot_x + rotation));
+ sy = DoubleToFixed16(scale_y * std::cos(rot_y - rot_x + rotation));
}
void
@@ -273,12 +258,12 @@
void
SWFMatrix::transform(SWFRect& r) const
{
- if ( r.is_null() ) return;
+ if (r.is_null()) return;
- boost::int32_t x1 = r.get_x_min();
- boost::int32_t y1 = r.get_y_min();
- boost::int32_t x2 = r.get_x_max();
- boost::int32_t y2 = r.get_y_max();
+ const boost::int32_t x1 = r.get_x_min();
+ const boost::int32_t y1 = r.get_y_min();
+ const boost::int32_t x2 = r.get_x_max();
+ const boost::int32_t y2 = r.get_y_max();
point p0(x1, y1);
point p1(x2, y1);
@@ -300,29 +285,24 @@
SWFMatrix&
SWFMatrix::invert()
{
- boost::int64_t det = determinant();
- if(det == 0)
- {
- //log_debug("Matrix not invertible, setting to identity on invert
request");
- // tested in misc-ming.all/SWFMatrix_test.c (seek "SWFMatrix
inversion")
+ const boost::int64_t det = determinant();
+ if (det == 0) {
set_identity();
- }
- else
- {
- double d = 65536.0 * 65536.0 / det;
- boost::int32_t t0, t4;
-
- t0 = (boost::int32_t)(sy * d);
- sy = (boost::int32_t)(sx * d);
- shy = (boost::int32_t)(-shy * d);
- shx = (boost::int32_t)(-shx * d);
-
- t4 = - ( Fixed16Mul(tx, t0) + Fixed16Mul(ty, shy) );
- ty = - ( Fixed16Mul(tx, shx)+ Fixed16Mul(ty, sy) );
-
- sx = t0;
- tx = t4;
- }
+ return *this;
+ }
+
+ const double d = 65536.0 * 65536.0 / det;
+
+ const boost::int32_t t0 = (boost::int32_t)(sy * d);
+ sy = (boost::int32_t)(sx * d);
+ shy = (boost::int32_t)(-shy * d);
+ shx = (boost::int32_t)(-shx * d);
+
+ const boost::int32_t t4 = - (Fixed16Mul(tx, t0) + Fixed16Mul(ty, shy));
+ ty = - (Fixed16Mul(tx, shx) + Fixed16Mul(ty, sy));
+
+ sx = t0;
+ tx = t4;
return *this;
}
=== modified file 'libcore/SWFMatrix.h'
--- a/libcore/SWFMatrix.h 2010-03-12 23:37:40 +0000
+++ b/libcore/SWFMatrix.h 2010-08-01 07:47:27 +0000
@@ -61,29 +61,45 @@
/// Xshear, 16.16 fixed point. yx in swfdec. 'b' in AS Matrix.
int shx;
+ /// Yshear, 16.16 fixed point. xy in swfdec. 'c' in AS Matrix.
+ int shy;
+
+ /// Yscale, 16.16 fixed point. yy in swfdec. 'd' in AS Matrix.
+ int sy;
+
/// Xtranslation, TWIPS. x0 in swfdec. 'tx' in AS Matrix.
int tx;
- /// Yscale, 16.16 fixed point. yy in swfdec. 'd' in AS Matrix.
- int sy;
-
- /// Yshear, 16.16 fixed point. xy in swfdec. 'c' in AS Matrix.
- int shy;
-
/// Ytranslation, TWIPS. y0 in swfdec. 'ty' in AS Matrix.
int ty;
friend bool operator== (const SWFMatrix&, const SWFMatrix&);
friend std::ostream& operator<< (std::ostream&, const SWFMatrix&);
- /// Defaults to identity
- SWFMatrix();
+ /// Construct an identity SWFMatrix
+ SWFMatrix()
+ :
+ sx(65536),
+ shx(0),
+ shy(0),
+ sy(65536),
+ tx(0),
+ ty(0)
+ {}
- /// Check validity of the SWFMatrix values
- bool is_valid() const;
+ /// Construct a SWFMatrix with all values.
+ SWFMatrix(int a, int b, int c, int d, int x, int y)
+ :
+ sx(a),
+ shx(b),
+ shy(c),
+ sy(d),
+ tx(x),
+ ty(y)
+ {}
/// Set the SWFMatrix to identity.
- void set_identity();
+ void set_identity();
/// Concatenate m's transform onto ours.
//
@@ -143,9 +159,6 @@
ty = y;
}
- /// Initialize from the SWF input stream.
- void read(SWFStream& in);
-
/// Transform a given point by our SWFMatrix
void transform(geometry::Point2d& p) const;
@@ -197,6 +210,9 @@
}; //end of SWFMatrix
+/// Read from input stream.
+SWFMatrix readSWFMatrix(SWFStream& in);
+
inline bool operator== (const SWFMatrix& a, const SWFMatrix& b)
{
return
=== modified file 'libcore/SWFRect.cpp'
--- a/libcore/SWFRect.cpp 2010-07-19 08:08:00 +0000
+++ b/libcore/SWFRect.cpp 2010-07-31 16:10:47 +0000
@@ -134,16 +134,17 @@
expand_to(p3.x, p3.y);
}
-void SWFRect::set_lerp(const SWFRect& a, const SWFRect& b, float t)
+void
+SWFRect::set_lerp(const SWFRect& a, const SWFRect& b, float t)
// Set this to the lerp of a and b.
{
assert( !a.is_null() );
assert( !b.is_null() );
- _xMin = (boost::int32_t)(flerp(a.get_x_min(), b.get_x_min(), t));
- _yMin = (boost::int32_t)(flerp(a.get_y_min(), b.get_y_min(), t));
- _xMax = (boost::int32_t)(flerp(a.get_x_max(), b.get_x_max(), t));
- _yMax = (boost::int32_t)(flerp(a.get_y_max(), b.get_y_max(), t));
+ _xMin = lerp<float>(a.get_x_min(), b.get_x_min(), t);
+ _yMin = lerp<float>(a.get_y_min(), b.get_y_min(), t);
+ _xMax = lerp<float>(a.get_x_max(), b.get_x_max(), t);
+ _yMax = lerp<float>(a.get_y_max(), b.get_y_max(), t);
}
void
=== modified file 'libcore/asobj/MovieClip_as.cpp'
--- a/libcore/asobj/MovieClip_as.cpp 2010-07-28 07:57:23 +0000
+++ b/libcore/asobj/MovieClip_as.cpp 2010-07-31 16:42:49 +0000
@@ -36,7 +36,7 @@
#include "NativeFunction.h"
#include "Bitmap.h"
#include "Array_as.h"
-#include "fill_style.h"
+#include "FillStyle.h"
#include "namedStrings.h"
namespace gnash {
@@ -1430,19 +1430,7 @@
movieclip_endFill(const fn_call& fn)
{
MovieClip* movieclip = ensure<IsDisplayObject<MovieClip> >(fn);
-
- IF_VERBOSE_ASCODING_ERRORS(
- if ( fn.nargs )
- {
- std::stringstream ss; fn.dump_args(ss);
- log_aserror(_("MovieClip.endFill(%s): args will be discarded"),
- ss.str());
- }
- );
-#ifdef DEBUG_DRAWING_API
- log_debug("%s.endFill();", movieclip->getTarget());
-#endif
- movieclip->endFill();
+ movieclip->graphics().endFill();
return as_value();
}
@@ -1451,52 +1439,24 @@
{
MovieClip* movieclip = ensure<IsDisplayObject<MovieClip> >(fn);
- if ( fn.nargs < 2 )
- {
+ if (fn.nargs < 2) {
IF_VERBOSE_ASCODING_ERRORS(
log_aserror(_("MovieClip.lineTo() needs at least two arguments"));
);
return as_value();
}
- IF_VERBOSE_ASCODING_ERRORS(
- if ( fn.nargs > 2 )
- {
- std::stringstream ss; fn.dump_args(ss);
- log_aserror(_("MovieClip.lineTo(%s): args after the first two "
- "will be discarded"), ss.str());
- }
- );
-
double x = fn.arg(0).to_number();
double y = fn.arg(1).to_number();
- if (!isFinite(x) )
- {
- IF_VERBOSE_ASCODING_ERRORS(
- std::stringstream ss; fn.dump_args(ss);
- log_aserror(_("%s.lineTo(%s) : non-finite first argument (%s), "
- "converted to zero"), movieclip->getTarget(),
- ss.str(), fn.arg(0));
- );
- x = 0;
- }
-
- if (!isFinite(y) )
- {
- IF_VERBOSE_ASCODING_ERRORS(
- std::stringstream ss; fn.dump_args(ss);
- log_aserror(_("%s.lineTo(%s) : non-finite second argument (%s), "
- "converted to zero"), movieclip->getTarget(),
- ss.str(), fn.arg(1));
- );
- y = 0;
- }
+ if (!isFinite(x)) x = 0;
+ if (!isFinite(y)) y = 0;
#ifdef DEBUG_DRAWING_API
log_debug("%s.lineTo(%g,%g);", movieclip->getTarget(), x, y);
#endif
- movieclip->lineTo(pixelsToTwips(x), pixelsToTwips(y));
+ movieclip->graphics().lineTo(pixelsToTwips(x), pixelsToTwips(y),
+ movieclip->getDefinitionVersion());
return as_value();
}
@@ -1505,52 +1465,20 @@
{
MovieClip* movieclip = ensure<IsDisplayObject<MovieClip> >(fn);
- if ( fn.nargs < 2 )
- {
+ if (fn.nargs < 2) {
IF_VERBOSE_ASCODING_ERRORS(
log_aserror(_("MovieClip.moveTo() takes two args"));
);
return as_value();
}
- IF_VERBOSE_ASCODING_ERRORS(
- if ( fn.nargs > 2 )
- {
- std::stringstream ss; fn.dump_args(ss);
- log_aserror(_("MovieClip.moveTo(%s): args after the first two will "
- "be discarded"), ss.str());
- }
- );
-
double x = fn.arg(0).to_number();
double y = fn.arg(1).to_number();
- if (!isFinite(x) )
- {
- IF_VERBOSE_ASCODING_ERRORS(
- std::stringstream ss; fn.dump_args(ss);
- log_aserror(_("%s.moveTo(%s) : non-finite first argument (%s), "
- "converted to zero"), movieclip->getTarget(),
- ss.str(), fn.arg(0));
- );
- x = 0;
- }
-
- if (!isFinite(y) )
- {
- IF_VERBOSE_ASCODING_ERRORS(
- std::stringstream ss; fn.dump_args(ss);
- log_aserror(_("%s.moveTo(%s) : non-finite second argument (%s), "
- "converted to zero"), movieclip->getTarget(),
- ss.str(), fn.arg(1));
- );
- y = 0;
- }
+ if (!isFinite(x)) x = 0;
+ if (!isFinite(y)) y = 0;
-#ifdef DEBUG_DRAWING_API
- log_debug(_("%s.moveTo(%g,%g);"), movieclip->getTarget(), x, y);
-#endif
- movieclip->moveTo(pixelsToTwips(x), pixelsToTwips(y));
+ movieclip->graphics().moveTo(pixelsToTwips(x), pixelsToTwips(y));
return as_value();
}
@@ -1565,9 +1493,8 @@
{
MovieClip* movieclip = ensure<IsDisplayObject<MovieClip> >(fn);
- if ( ! fn.nargs )
- {
- movieclip->resetLineStyle();
+ if (!fn.nargs) {
+ movieclip->graphics().resetLineStyle();
return as_value();
}
@@ -1587,8 +1514,7 @@
int arguments = fn.nargs;
const int swfVersion = getSWFVersion(fn);
- if (swfVersion < 8 && fn.nargs > 3)
- {
+ if (swfVersion < 8 && fn.nargs > 3) {
IF_VERBOSE_ASCODING_ERRORS(
std::ostringstream ss;
fn.dump_args(ss);
@@ -1598,15 +1524,8 @@
arguments = 3;
}
- switch (arguments)
- {
+ switch (arguments) {
default:
- IF_VERBOSE_ASCODING_ERRORS(
- std::ostringstream ss;
- fn.dump_args(ss);
- log_aserror(_("MovieClip.lineStyle(%s): args after the "
- "first eight will be discarded"), ss.str());
- );
case 8:
miterLimitFactor = clamp<int>(toInt(fn.arg(7)), 1, 255);
case 7:
@@ -1615,8 +1534,7 @@
if (joinStyleStr == "miter") joinStyle = JOIN_MITER;
else if (joinStyleStr == "round") joinStyle = JOIN_ROUND;
else if (joinStyleStr == "bevel") joinStyle = JOIN_BEVEL;
- else
- {
+ else {
IF_VERBOSE_ASCODING_ERRORS(
std::ostringstream ss;
fn.dump_args(ss);
@@ -1632,8 +1550,7 @@
if (capStyleStr == "none") capStyle = CAP_NONE;
else if (capStyleStr == "round") capStyle = CAP_ROUND;
else if (capStyleStr == "square") capStyle = CAP_SQUARE;
- else
- {
+ else {
IF_VERBOSE_ASCODING_ERRORS(
std::ostringstream ss;
fn.dump_args(ss);
@@ -1648,21 +1565,17 @@
// Both values to be set here are true, so just set the
// appropriate values to false.
const std::string noScaleString = fn.arg(4).to_string();
- if (noScaleString == "none")
- {
- scaleThicknessVertically = false;
- scaleThicknessHorizontally = false;
- }
- else if (noScaleString == "vertical")
- {
- scaleThicknessVertically = false;
- }
- else if (noScaleString == "horizontal")
- {
- scaleThicknessHorizontally = false;
- }
- else if (noScaleString != "normal")
- {
+ if (noScaleString == "none") {
+ scaleThicknessVertically = false;
+ scaleThicknessHorizontally = false;
+ }
+ else if (noScaleString == "vertical") {
+ scaleThicknessVertically = false;
+ }
+ else if (noScaleString == "horizontal") {
+ scaleThicknessHorizontally = false;
+ }
+ else if (noScaleString != "normal") {
IF_VERBOSE_ASCODING_ERRORS(
std::ostringstream ss;
fn.dump_args(ss);
@@ -1700,12 +1613,9 @@
rgba color(r, g, b, a);
-#ifdef DEBUG_DRAWING_API
- log_debug("%s.lineStyle(%d,%d,%d,%d);", movieclip->getTarget(), thickness,
r, g, b);
-#endif
- movieclip->lineStyle(thickness, color,
- scaleThicknessVertically, scaleThicknessHorizontally,
- pixelHinting, noClose, capStyle, capStyle, joinStyle, miterLimitFactor);
+ movieclip->graphics().lineStyle(thickness, color,
+ scaleThicknessVertically, scaleThicknessHorizontally,
+ pixelHinting, noClose, capStyle, capStyle, joinStyle,
miterLimitFactor);
return as_value();
}
@@ -1715,78 +1625,30 @@
{
MovieClip* movieclip = ensure<IsDisplayObject<MovieClip> >(fn);
- if ( fn.nargs < 4 )
- {
+ if (fn.nargs < 4) {
IF_VERBOSE_ASCODING_ERRORS(
log_aserror(_("MovieClip.curveTo() takes four args"));
);
return as_value();
}
- IF_VERBOSE_ASCODING_ERRORS(
- if ( fn.nargs > 4 )
- {
- std::stringstream ss; fn.dump_args(ss);
- log_aserror(_("MovieClip.curveTo(%s): args after the first four "
- "will be discarded"), ss.str());
- }
- );
-
double cx = fn.arg(0).to_number();
double cy = fn.arg(1).to_number();
double ax = fn.arg(2).to_number();
double ay = fn.arg(3).to_number();
- if (!isFinite(cx))
- {
- IF_VERBOSE_ASCODING_ERRORS(
- std::stringstream ss; fn.dump_args(ss);
- log_aserror(_("%s.curveTo(%s) : non-finite first argument (%s), "
- "converted to zero"), movieclip->getTarget(),
- ss.str(), fn.arg(0));
- );
- cx = 0;
- }
-
- if (!isFinite(cy))
- {
- IF_VERBOSE_ASCODING_ERRORS(
- std::stringstream ss; fn.dump_args(ss);
- log_aserror(_("%s.curveTo(%s) : non-finite second argument (%s), "
- "converted to zero"), movieclip->getTarget(),
- ss.str(), fn.arg(1));
- );
- cy = 0;
- }
-
- if (!isFinite(ax))
- {
- IF_VERBOSE_ASCODING_ERRORS(
- std::stringstream ss; fn.dump_args(ss);
- log_aserror(_("%s.curveTo(%s) : non-finite third argument (%s), "
- "converted to zero"), movieclip->getTarget(),
- ss.str(), fn.arg(0));
- );
- ax = 0;
- }
-
- if (!isFinite(ay))
- {
- IF_VERBOSE_ASCODING_ERRORS(
- std::stringstream ss; fn.dump_args(ss);
- log_aserror(_("%s.curveTo(%s) : non-finite fourth argument (%s), "
- "converted to zero"), movieclip->getTarget(),
- ss.str(), fn.arg(1));
- );
- ay = 0;
- }
+ if (!isFinite(cx)) cx = 0;
+ if (!isFinite(cy)) cy = 0;
+ if (!isFinite(ax)) ax = 0;
+ if (!isFinite(ay)) ay = 0;
#ifdef DEBUG_DRAWING_API
log_debug(_("%s.curveTo(%g,%g,%g,%g);"), movieclip->getTarget(),
cx, cy, ax, ay);
#endif
- movieclip->curveTo(pixelsToTwips(cx), pixelsToTwips(cy),
- pixelsToTwips(ax), pixelsToTwips(ay));
+ movieclip->graphics().curveTo(pixelsToTwips(cx), pixelsToTwips(cy),
+ pixelsToTwips(ax), pixelsToTwips(ay),
+ movieclip->getDefinitionVersion());
return as_value();
}
@@ -1795,21 +1657,7 @@
movieclip_clear(const fn_call& fn)
{
MovieClip* movieclip = ensure<IsDisplayObject<MovieClip> >(fn);
-
- IF_VERBOSE_ASCODING_ERRORS(
- if ( fn.nargs )
- {
- std::stringstream ss; fn.dump_args(ss);
- log_aserror(_("MovieClip.clear(%s): args will be discarded"),
- ss.str());
- }
- );
-
-#ifdef DEBUG_DRAWING_API
- log_debug(_("%s.clear();"), movieclip->getTarget());
-#endif
- movieclip->clear();
-
+ movieclip->graphics().clear();
return as_value();
}
@@ -1818,46 +1666,30 @@
{
MovieClip* movieclip = ensure<IsDisplayObject<MovieClip> >(fn);
- if ( fn.nargs < 1 )
- {
+ if (fn.nargs < 1) {
IF_VERBOSE_ASCODING_ERRORS(
- log_aserror("beginFill() with no args is a no-op");
+ log_aserror("beginFill() with no args is a no-op");
);
return as_value();
}
- boost::uint8_t r = 0;
- boost::uint8_t g = 0;
- boost::uint8_t b = 0;
- boost::uint8_t a = 255;
-
-
// 2^24 is the max here
- boost::uint32_t rgbval = boost::uint32_t(
- clamp<float>(fn.arg(0).to_number(), 0, 16777216));
- r = boost::uint8_t( (rgbval&0xFF0000) >> 16);
- g = boost::uint8_t( (rgbval&0x00FF00) >> 8);
- b = boost::uint8_t( (rgbval&0x0000FF) );
-
- if ( fn.nargs > 1 )
- {
+ const boost::uint32_t rgbval =
+ clamp<float>(fn.arg(0).to_number(), 0, 16777216);
+
+ const boost::uint8_t r = (rgbval & 0xFF0000) >> 16;
+ const boost::uint8_t g = (rgbval & 0x00FF00) >> 8;
+ const boost::uint8_t b = rgbval & 0x0000FF;
+ boost::uint8_t a = 255;
+
+ if (fn.nargs > 1) {
a = 255 * clamp<int>(toInt(fn.arg(1)), 0, 100) / 100;
- IF_VERBOSE_ASCODING_ERRORS(
- if ( fn.nargs > 2 )
- {
- std::stringstream ss; fn.dump_args(ss);
- log_aserror(_("MovieClip.beginFill(%s): args after the "
- "first will be discarded"), ss.str());
- }
- );
}
rgba color(r, g, b, a);
-#ifdef DEBUG_DRAWING_API
- log_debug(_("%s.beginFill(%d,%d,%d);"), movieclip->getTarget(), r, g, b);
-#endif
- movieclip->beginFill(color);
+ const FillStyle f = SolidFill(color);
+ movieclip->graphics().beginFill(f);
return as_value();
}
@@ -1881,41 +1713,49 @@
IF_VERBOSE_ASCODING_ERRORS(
std::stringstream ss; fn.dump_args(ss);
log_aserror(_("%s.beginGradientFill(%s): invalid call: 5 arguments "
- "needed"),
- movieclip->getTarget(), ss.str());
+ "needed"), movieclip->getTarget(), ss.str());
);
return as_value();
}
- // There are optional arguments that we do not implement!
- if (fn.nargs > 5) {
- std::stringstream ss; fn.dump_args(ss);
- LOG_ONCE(log_unimpl(_("MovieClip.beginGradientFill(%s): args after "
- "the first five will be discarded"), ss.str()));
+ const size_t maxargs = getSWFVersion(fn) >= 8 ? 8 : 5;
+
+ if (fn.nargs > maxargs) {
+ IF_VERBOSE_ASCODING_ERRORS(
+ std::stringstream ss; fn.dump_args(ss);
+ log_aserror(_("%s.beginGradientFill(%s): extra arguments "
+ "invalidate call!"));
+ );
+ return as_value();
}
- bool radial = false;
+ GradientFill::Type t;
+
std::string typeStr = fn.arg(0).to_string();
- // Case-sensitive comparison needed for this ...
- if (typeStr == "radial") radial = true;
- else if (typeStr == "linear") radial = false;
+ // An unexpected fill type results in no fill in all versions.
+ if (typeStr == "radial") {
+ t = GradientFill::RADIAL;
+ }
+ else if (typeStr == "linear") {
+ t = GradientFill::LINEAR;
+ }
else {
IF_VERBOSE_ASCODING_ERRORS(
- std::stringstream ss; fn.dump_args(ss);
- log_aserror(_("%s.beginGradientFill(%s): first arg must be "
- "'radial' or 'linear'"),
- movieclip->getTarget(), ss.str());
- );
+ std::stringstream ss; fn.dump_args(ss);
+ log_aserror(_("%s.beginGradientFill(%s): first arg must be "
+ "'radial', 'focal', or 'linear'"),
+ movieclip->getTarget(), ss.str());
+ );
return as_value();
}
typedef boost::intrusive_ptr<as_object> ObjPtr;
-
- ObjPtr colors = fn.arg(1).to_object(getGlobal(fn));
- ObjPtr alphas = fn.arg(2).to_object(getGlobal(fn));
- ObjPtr ratios = fn.arg(3).to_object(getGlobal(fn));
- ObjPtr matrix = fn.arg(4).to_object(getGlobal(fn));
+ Global_as& gl = getGlobal(fn);
+ ObjPtr colors = fn.arg(1).to_object(gl);
+ ObjPtr alphas = fn.arg(2).to_object(gl);
+ ObjPtr ratios = fn.arg(3).to_object(gl);
+ ObjPtr matrix = fn.arg(4).to_object(gl);
if (!colors || !alphas || !ratios || !matrix) {
IF_VERBOSE_ASCODING_ERRORS(
@@ -1954,23 +1794,6 @@
SWFMatrix mat;
- if (radial) {
- // A gradient box extends from (-16384, -16384) to (16384, 16384),
- // so we have set scale and translation to convert our radial
- // (0, 0)-(64, 64) range to a -16384 - 16384 square.
- mat.concatenate_translation(32, 32);
- mat.set_scale(1 / 512., 1 / 512.);
- }
- else {
- // A gradient box extends from (-16384, -16384) to (16384, 16384),
- // so we have set scale and translation to convert our linear 0-256
- // range to -16384 - 16384.
- mat.concatenate_translation(128, 0);
- mat.set_scale(1 / 128., 1 / 128.);
- }
-
- SWFMatrix input_matrix;
-
// This is case sensitive.
if (matrix->getMember(NSV::PROP_MATRIX_TYPE).to_string() == "box") {
@@ -1989,12 +1812,12 @@
const double c = -std::sin(rot) * valW * 2;
const double d = std::cos(rot) * valH * 2;
- input_matrix.sx = a;
- input_matrix.shx = b;
- input_matrix.shy = c;
- input_matrix.sy = d;
- input_matrix.tx = valX + valW / 2.0;
- input_matrix.ty = valY + valH / 2.0;
+ mat.sx = a;
+ mat.shx = b;
+ mat.shy = c;
+ mat.sy = d;
+ mat.tx = valX + valW / 2.0;
+ mat.ty = valY + valH / 2.0;
}
else {
@@ -2011,25 +1834,23 @@
const boost::int32_t valTY = pixelsToTwips(
matrix->getMember(NSV::PROP_TY).to_number());
- input_matrix.sx = valA;
- input_matrix.shx = valB;
- input_matrix.shy = valC;
- input_matrix.sy = valD;
- input_matrix.tx = valTX;
- input_matrix.ty = valTY;
+ mat.sx = valA;
+ mat.shx = valB;
+ mat.shy = valC;
+ mat.sy = valD;
+ mat.tx = valTX;
+ mat.ty = valTY;
}
- mat.concatenate(input_matrix.invert());
-
// ----------------------------
// Create the gradients vector
// ----------------------------
string_table& st = getStringTable(fn);
- std::vector<gradient_record> gradients;
+ std::vector<GradientRecord> gradients;
gradients.reserve(stops);
- for (size_t i=0; i < stops; ++i) {
+ for (size_t i = 0; i < stops; ++i) {
string_table::key key = st.find(boost::lexical_cast<std::string>(i));
@@ -2053,7 +1874,7 @@
const as_value& ratVal = ratios->getMember(key);
const boost::uint32_t minRatio =
gradients.empty() ? 0 :
- std::min<boost::uint32_t>(gradients[i - 1].m_ratio + step, 0xff);
+ std::min<boost::uint32_t>(gradients[i - 1].ratio + step, 0xff);
boost::uint8_t rat = ratVal.is_number() ?
clamp<boost::uint32_t>(toInt(ratVal), minRatio, 0xff) : minRatio;
@@ -2061,23 +1882,34 @@
// The renderer may expect successively larger ratios; failure to
// do this can lead to memory errors.
if (!gradients.empty()) {
- assert((rat != 0xff && rat > gradients[i - 1].m_ratio) ||
- (rat >= gradients[i - 1].m_ratio));
+ assert((rat != 0xff && rat > gradients[i - 1].ratio) ||
+ (rat >= gradients[i - 1].ratio));
}
rgba color;
color.parseRGB(col);
color.m_a = alp;
- gradients.push_back(gradient_record(rat, color));
- }
-
- if (radial) {
- movieclip->beginRadialGradientFill(gradients, mat);
- }
- else {
- movieclip->beginLinearGradientFill(gradients, mat);
- }
+ gradients.push_back(GradientRecord(rat, color));
+ }
+
+ // Make sure we don't try to construct a GradientFill with only 1 stop!
+ if (stops < 2) {
+ const FillStyle f = SolidFill(gradients[0].color);
+ movieclip->graphics().beginFill(f);
+ return as_value();
+ }
+
+ GradientFill fd(t, mat.invert(), gradients);
+
+ /// TODO: set interpolation mode and spread mode.
+
+ /// Add a focus if present.
+ if (fn.nargs > 7) {
+ fd.setFocalPoint(fn.arg(7).to_number());
+ }
+
+ movieclip->graphics().beginFill(fd);
return as_value();
}
=== modified file 'libcore/swf/DefineButtonTag.cpp'
--- a/libcore/swf/DefineButtonTag.cpp 2010-06-11 07:04:03 +0000
+++ b/libcore/swf/DefineButtonTag.cpp 2010-08-01 07:47:27 +0000
@@ -428,8 +428,7 @@
in.ensureBytes(2);
_buttonLayer = in.read_u16();
- // SWFMatrix::read() checks the length of the stream
- _matrix.read(in);
+ _matrix = readSWFMatrix(in);
if (t == SWF::DEFINEBUTTON2) {
_cxform.read_rgba(in);
=== modified file 'libcore/swf/DefineEditTextTag.cpp'
--- a/libcore/swf/DefineEditTextTag.cpp 2010-07-09 07:37:30 +0000
+++ b/libcore/swf/DefineEditTextTag.cpp 2010-08-01 06:36:11 +0000
@@ -122,9 +122,8 @@
fontClassName);
}
- if (hasColor)
- {
- _color.read_rgba(in);
+ if (hasColor) {
+ _color = readRGBA(in);
}
if (hasMaxChars)
=== modified file 'libcore/swf/DefineMorphShapeTag.cpp'
--- a/libcore/swf/DefineMorphShapeTag.cpp 2010-07-28 07:57:23 +0000
+++ b/libcore/swf/DefineMorphShapeTag.cpp 2010-07-31 14:05:26 +0000
@@ -32,7 +32,7 @@
#include "RunResources.h"
#include "Global_as.h"
#include "Renderer.h"
-#include "fill_style.h"
+#include "FillStyle.h"
namespace gnash {
namespace SWF {
@@ -107,11 +107,10 @@
// Next line will throw ParserException on malformed SWF
const boost::uint16_t fillCount = in.read_variable_count();
- fill_style fs1, fs2;
for (size_t i = 0; i < fillCount; ++i) {
- fs1.read(in, tag, md, r, &fs2);
- _shape1.addFillStyle(fs1);
- _shape2.addFillStyle(fs2);
+ OptionalFillPair fp = readFills(in, tag, md, true);
+ _shape1.addFillStyle(fp.first);
+ _shape2.addFillStyle(*fp.second);
}
const boost::uint16_t lineCount = in.read_variable_count();
=== modified file 'libcore/swf/DefineTextTag.cpp'
--- a/libcore/swf/DefineTextTag.cpp 2010-06-11 07:04:03 +0000
+++ b/libcore/swf/DefineTextTag.cpp 2010-08-01 07:47:27 +0000
@@ -101,7 +101,7 @@
assert(tag == DEFINETEXT || tag == DEFINETEXT2);
_rect.read(in);
- _matrix.read(in);
+ _matrix = readSWFMatrix(in);
in.ensureBytes(2); // glyph_bits + advance_bits
int glyphBits = in.read_u8();
=== modified file 'libcore/swf/PlaceObject2Tag.cpp'
--- a/libcore/swf/PlaceObject2Tag.cpp 2010-05-20 09:57:10 +0000
+++ b/libcore/swf/PlaceObject2Tag.cpp 2010-08-01 07:47:27 +0000
@@ -52,7 +52,7 @@
if (in.tell() < in.get_tag_end_position())
{
- m_matrix.read(in);
+ m_matrix = readSWFMatrix(in);
m_has_flags2 |= HAS_MATRIX_MASK;
if (in.tell() < in.get_tag_end_position())
{
@@ -270,7 +270,7 @@
if ( hasMatrix() )
{
- m_matrix.read(in);
+ m_matrix = readSWFMatrix(in);
}
if ( hasCxform() )
@@ -281,7 +281,7 @@
if ( hasRatio() )
{
in.ensureBytes(2);
- m_ratio = in.read_u16();
+ _ratio = in.read_u16();
}
if ( hasName() )
@@ -316,7 +316,7 @@
{
log_parse(_(" cxform: %s"), m_color_transform);
}
- if ( hasRatio() ) log_parse(_(" ratio: %d"), m_ratio);
+ if ( hasRatio() ) log_parse(_(" ratio: %d"), _ratio);
if ( hasName() ) log_parse(_(" name = %s"), m_name.c_str());
if ( hasClipDepth() ) log_parse(_(" clip_depth = %d (%d)"),
m_clip_depth, m_clip_depth-DisplayObject::staticDepthOffset);
log_parse(_(" m_place_type: %d"), getPlaceType() );
@@ -358,7 +358,7 @@
}
if (hasMatrix()) {
- m_matrix.read(in);
+ m_matrix = readSWFMatrix(in);
}
if (hasCxform()) {
@@ -367,7 +367,7 @@
if (hasRatio()) {
in.ensureBytes(2);
- m_ratio = in.read_u16();
+ _ratio = in.read_u16();
}
if (hasName()) {
@@ -423,7 +423,7 @@
if (hasCharacter()) log_parse(_(" char id = %d"), _id);
if (hasMatrix()) log_parse(_(" SWFMatrix: %s"), m_matrix);
if (hasCxform()) log_parse(_(" cxform: %d"), m_color_transform);
- if (hasRatio()) log_parse(_(" ratio: %d"), m_ratio);
+ if (hasRatio()) log_parse(_(" ratio: %d"), _ratio);
if (hasName()) log_parse(_(" name = %s"), m_name);
if (hasClassName()) log_parse(_(" class name = %s"), className);
if (hasClipDepth()) log_parse(_(" clip_depth = %d (%d)"),
=== modified file 'libcore/swf/PlaceObject2Tag.h'
--- a/libcore/swf/PlaceObject2Tag.h 2010-06-11 14:05:12 +0000
+++ b/libcore/swf/PlaceObject2Tag.h 2010-07-31 16:16:52 +0000
@@ -73,7 +73,7 @@
/// m_matrix:
/// The SWFMatrix transform to apply to the newly created instance.
///
-/// m_ratio
+/// _ratio
///
/// m_clip_depth:
/// If != DisplayObject::noClipDepthValue, mark the created instance
@@ -94,7 +94,7 @@
m_has_flags2(0),
m_has_flags3(0),
_id(0),
- m_ratio(0),
+ _ratio(0),
m_clip_depth(0),
_blendMode(0),
_movie_def(def)
@@ -116,7 +116,7 @@
return m_has_flags2 & (HAS_CHARACTER_MASK | MOVE_MASK);
}
- int getRatio() const { return m_ratio; }
+ int getRatio() const { return _ratio; }
int getClipDepth() const { return m_clip_depth; }
boost::uint16_t getID() const { return _id; }
const std::string& getName() const { return m_name; }
@@ -165,7 +165,7 @@
boost::uint16_t _id;
cxform m_color_transform;
SWFMatrix m_matrix;
- int m_ratio;
+ int _ratio;
std::string m_name;
int m_clip_depth;
=== modified file 'libcore/swf/SWF.h'
--- a/libcore/swf/SWF.h 2010-07-24 14:38:36 +0000
+++ b/libcore/swf/SWF.h 2010-07-31 14:05:26 +0000
@@ -1514,9 +1514,9 @@
/// SWF fill style types. Symbolic names copied from Ming.
//
/// For more info see:
-/// http://sswf.sourceforge.net/SWFalexref.html#swf_fill_style
-///
-enum fill_style_type {
+/// http://sswf.sourceforge.net/SWFalexref.html#swf_FillStyle
+enum FillType
+{
FILL_SOLID = 0x00,
FILL_LINEAR_GRADIENT = 0x10,
FILL_RADIAL_GRADIENT = 0x12,
@@ -1529,18 +1529,19 @@
/// swf8 (alexis is wrong), non-smoothed / hard edges
FILL_CLIPPED_BITMAP_HARD = 0x43
-
-};
-
-enum gradient_spread_mode {
- GRADIENT_SPREAD_PAD,
- GRADIENT_SPREAD_REFLECT,
- GRADIENT_SPREAD_REPEAT
-};
-
-enum gradient_interpolation_mode {
- GRADIENT_INTERPOL_NORMAL,
- GRADIENT_INTERPOL_LINEAR
+};
+
+enum SpreadMode
+{
+ GRADIENT_SPREAD_PAD,
+ GRADIENT_SPREAD_REFLECT,
+ GRADIENT_SPREAD_REPEAT
+};
+
+enum InterpolationMode
+{
+ GRADIENT_INTERPOLATION_NORMAL,
+ GRADIENT_INTERPOLATION_LINEAR
};
=== modified file 'libcore/swf/SetBackgroundColorTag.h'
--- a/libcore/swf/SetBackgroundColorTag.h 2010-05-20 09:57:10 +0000
+++ b/libcore/swf/SetBackgroundColorTag.h 2010-08-01 06:36:11 +0000
@@ -54,7 +54,7 @@
void read(SWFStream& in)
{
// may throw ParserException
- m_color.read_rgb(in);
+ m_color = readRGB(in);
IF_VERBOSE_PARSE(
log_parse(_(" SetBackgroundColor: %s"), m_color);
=== modified file 'libcore/swf/ShapeRecord.cpp'
--- a/libcore/swf/ShapeRecord.cpp 2010-07-29 06:24:31 +0000
+++ b/libcore/swf/ShapeRecord.cpp 2010-07-31 16:10:47 +0000
@@ -21,10 +21,9 @@
#include "SWFStream.h"
#include "movie_definition.h"
#include "smart_ptr.h"
-#include "fill_style.h"
+#include "FillStyle.h"
#include "Geometry.h"
#include "GnashNumeric.h"
-#include "RunResources.h"
#include "log.h"
#include <vector>
@@ -35,9 +34,9 @@
// Forward declarations
namespace {
void readFillStyles(ShapeRecord::FillStyles& styles, SWFStream& in,
- SWF::TagType tag, movie_definition& md, const RunResources& r);
+ SWF::TagType tag, movie_definition& md, const RunResources& /*r*/);
void readLineStyles(ShapeRecord::LineStyles& styles, SWFStream& in,
- SWF::TagType tag, movie_definition& md, const RunResources& r);
+ SWF::TagType tag, movie_definition& md, const RunResources& /*r*/);
void computeBounds(SWFRect& bounds, const ShapeRecord::Paths& paths,
const ShapeRecord::LineStyles& lineStyles, int swfVersion);
}
@@ -59,7 +58,7 @@
void operator()(typename T::value_type& st)
{
- st.set_lerp(*_style1, *_style2, _ratio);
+ setLerp(st, *_style1, *_style2, _ratio);
++_style1, ++_style2;
}
@@ -182,7 +181,7 @@
}
void
-ShapeRecord::addFillStyle(const fill_style& fs)
+ShapeRecord::addFillStyle(const FillStyle& fs)
{
_fillStyles.push_back(fs);
}
@@ -224,8 +223,8 @@
const Path& p1 = i < paths1.size() ? paths1[i] : empty_path;
const Path& p2 = n < paths2.size() ? paths2[n] : empty_path;
- const float new_ax = flerp(p1.ap.x, p2.ap.x, ratio);
- const float new_ay = flerp(p1.ap.y, p2.ap.y, ratio);
+ const float new_ax = lerp<float>(p1.ap.x, p2.ap.x, ratio);
+ const float new_ay = lerp<float>(p1.ap.y, p2.ap.y, ratio);
p.reset(new_ax, new_ay, p1.getLeftFill(),
p2.getRightFill(), p1.getLineStyle());
@@ -241,10 +240,10 @@
const Edge& e2 = k < p2.size() ? p2[k] : empty_edge;
- e.cp.x = static_cast<int>(flerp(e1.cp.x, e2.cp.x, ratio));
- e.cp.y = static_cast<int>(flerp(e1.cp.y, e2.cp.y, ratio));
- e.ap.x = static_cast<int>(flerp(e1.ap.x, e2.ap.x, ratio));
- e.ap.y = static_cast<int>(flerp(e1.ap.y, e2.ap.y, ratio));
+ e.cp.x = static_cast<int>(lerp<float>(e1.cp.x, e2.cp.x, ratio));
+ e.cp.y = static_cast<int>(lerp<float>(e1.cp.y, e2.cp.y, ratio));
+ e.ap.x = static_cast<int>(lerp<float>(e1.ap.x, e2.ap.x, ratio));
+ e.ap.y = static_cast<int>(lerp<float>(e1.ap.y, e2.ap.y, ratio));
++k;
if (p2.size() <= k) {
@@ -395,7 +394,7 @@
}
if ((flags & SHAPE_FILLSTYLE0_CHANGE) && num_fill_bits > 0)
{
- // fill_style_0_change = 1;
+ // FillStyle_0_change = 1;
if (! current_path.empty())
{
_paths.push_back(current_path);
@@ -446,7 +445,7 @@
}
if ((flags & SHAPE_FILLSTYLE1_CHANGE) && num_fill_bits > 0)
{
- // fill_style_1_change = 1;
+ // FillStyle_1_change = 1;
if (! current_path.empty())
{
_paths.push_back(current_path);
@@ -677,30 +676,29 @@
// Read fill styles, and push them onto the given style array.
void
readFillStyles(ShapeRecord::FillStyles& styles, SWFStream& in,
- SWF::TagType tag, movie_definition& m, const RunResources& r)
+ SWF::TagType tag, movie_definition& m, const RunResources& /*r*/)
{
in.ensureBytes(1);
- boost::uint16_t fill_style_count = in.read_u8();
+ boost::uint16_t FillStyle_count = in.read_u8();
if (tag != SWF::DEFINESHAPE)
{
- if (fill_style_count == 0xFF)
+ if (FillStyle_count == 0xFF)
{
in.ensureBytes(2);
- fill_style_count = in.read_u16();
+ FillStyle_count = in.read_u16();
}
}
IF_VERBOSE_PARSE (
- log_parse(_(" readFillStyles: count = %u"), fill_style_count);
+ log_parse(_(" readFillStyles: count = %u"), FillStyle_count);
);
// Read the styles.
- styles.reserve(styles.size()+fill_style_count);
- for (boost::uint16_t i = 0; i < fill_style_count; ++i) {
- // TODO: add a fill_style constructor directly reading from stream
- fill_style fs;
- fs.read(in, tag, m, r);
- styles.push_back(fs);
+ styles.reserve(styles.size()+FillStyle_count);
+ for (boost::uint16_t i = 0; i < FillStyle_count; ++i) {
+ // TODO: add a FillStyle constructor directly reading from stream
+ OptionalFillPair fp = readFills(in, tag, m, false);
+ styles.push_back(fp.first);
}
}
=== modified file 'libcore/swf/ShapeRecord.h'
--- a/libcore/swf/ShapeRecord.h 2010-07-29 06:24:31 +0000
+++ b/libcore/swf/ShapeRecord.h 2010-07-31 14:05:26 +0000
@@ -29,7 +29,7 @@
namespace gnash {
class movie_definition;
class RunResources;
- class fill_style;
+ class FillStyle;
}
namespace gnash {
@@ -52,7 +52,7 @@
{
public:
- typedef std::vector<fill_style> FillStyles;
+ typedef std::vector<FillStyle> FillStyles;
typedef std::vector<LineStyle> LineStyles;
typedef std::vector<Path> Paths;
@@ -118,7 +118,7 @@
/// Reset all shape data.
void clear();
- void addFillStyle(const fill_style& fs);
+ void addFillStyle(const FillStyle& fs);
void addPath(const Path& path) {
_paths.push_back(path);
=== modified file 'libcore/swf/TextRecord.cpp'
--- a/libcore/swf/TextRecord.cpp 2010-03-13 18:00:33 +0000
+++ b/libcore/swf/TextRecord.cpp 2010-08-01 06:36:11 +0000
@@ -81,8 +81,8 @@
if (hasColor)
{
- if (tag == DEFINETEXT) _color.read_rgb(in);
- else _color.read_rgba(in);
+ if (tag == DEFINETEXT) _color = readRGB(in);
+ else _color = readRGBA(in);
IF_VERBOSE_PARSE(
log_parse(_(" hasColor"));
=== modified file 'librender/Renderer.h'
--- a/librender/Renderer.h 2010-07-19 07:43:01 +0000
+++ b/librender/Renderer.h 2010-07-31 14:05:26 +0000
@@ -164,7 +164,7 @@
class rgba;
class SWFMatrix;
class cxform;
- class fill_style;
+ class FillStyle;
class LineStyle;
// XXX: GnashImageProxy (delayed image rendering)
@@ -219,7 +219,7 @@
/// \brief
/// Given an image, returns a pointer to a bitmap_info class
- /// that can later be passed to fill_styleX_bitmap(), to set a
+ /// that can later be passed to FillStyleX_bitmap(), to set a
/// bitmap fill style.
virtual BitmapInfo* createBitmapInfo(std::auto_ptr<GnashImage> im) = 0;
=== modified file 'librender/Renderer_agg.cpp'
--- a/librender/Renderer_agg.cpp 2010-07-28 07:57:23 +0000
+++ b/librender/Renderer_agg.cpp 2010-07-31 15:15:34 +0000
@@ -127,7 +127,7 @@
#include "GnashNumeric.h"
#include "GC.h"
#include "cxform.h"
-#include "fill_style.h"
+#include "FillStyle.h"
#ifdef HAVE_VA_VA_H
#include "GnashVaapiImage.h"
@@ -670,6 +670,98 @@
/// Whether smoothing is required.
bool _smoothing;
};
+
+
+/// 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;
+};
}
@@ -686,7 +778,7 @@
public:
// Given an image, returns a pointer to a bitmap_info class
- // that can later be passed to fill_styleX_bitmap(), to set a
+ // that can later be passed to FillStyleX_bitmap(), to set a
// bitmap fill style.
gnash::BitmapInfo* createBitmapInfo(std::auto_ptr<GnashImage> im)
{
@@ -1030,12 +1122,11 @@
AggPaths agg_paths;
buildPaths(agg_paths, paths);
- // make sure m_single_fill_styles contains the required color
- need_single_fill_style(color);
+ std::vector<FillStyle> v(1, FillStyle(SolidFill(color)));
// prepare style handler
agg_style_handler sh;
- build_agg_styles(sh, m_single_fill_styles, mat, cxform());
+ build_agg_styles(sh, v, mat, cxform());
draw_shape(-1, paths, agg_paths, sh, false);
@@ -1119,7 +1210,7 @@
drawShape(fillStyles, lineStyles, paths, worldMat, cx);
}
- void drawShape(const std::vector<fill_style>& fill_styles,
+ void drawShape(const std::vector<FillStyle>& FillStyles,
const std::vector<LineStyle>& line_styles,
const std::vector<Path>& objpaths, const SWFMatrix& mat,
const cxform& cx)
@@ -1170,7 +1261,7 @@
// prepare fill styles
agg_style_handler sh;
- if (have_shape) build_agg_styles(sh, fill_styles, mat, cx);
+ if (have_shape) build_agg_styles(sh, FillStyles, mat, cx);
// We need to separate sub-shapes during rendering.
const unsigned int subshape_count = count_sub_shapes(paths);
@@ -1384,126 +1475,23 @@
}
} //buildPaths_rounded
-
- // Initializes the internal styles class for AGG renderer
- void build_agg_styles(agg_style_handler& sh,
- const std::vector<fill_style>& fill_styles,
- const SWFMatrix& fillstyle_matrix,
- const cxform& cx) {
-
- SWFMatrix inv_stage_matrix = stage_matrix;
- inv_stage_matrix.invert();
-
- const size_t fcount = fill_styles.size();
- for (size_t fno=0; fno<fcount; ++fno) {
-
- int fill_type = fill_styles[fno].get_type();
-
- switch (fill_type) {
-
- case SWF::FILL_LINEAR_GRADIENT:
- {
- SWFMatrix m = fill_styles[fno].getGradientMatrix();
- SWFMatrix cm = fillstyle_matrix;
- cm.invert();
-
- m.concatenate(cm);
- m.concatenate(inv_stage_matrix);
-
- sh.add_gradient_linear(fill_styles[fno], m, cx);
- break;
- }
-
- case SWF::FILL_RADIAL_GRADIENT:
- {
- SWFMatrix m = fill_styles[fno].getGradientMatrix();
- SWFMatrix cm = fillstyle_matrix;
- cm.invert();
-
- m.concatenate(cm);
- m.concatenate(inv_stage_matrix);
-
- sh.add_gradient_radial(fill_styles[fno], m, cx);
- break;
- }
-
- case SWF::FILL_FOCAL_GRADIENT:
- {
- SWFMatrix m = fill_styles[fno].getGradientMatrix();
- SWFMatrix cm = fillstyle_matrix;
- cm.invert();
-
- m.concatenate(cm);
- m.concatenate(inv_stage_matrix);
-
- sh.add_gradient_focal(fill_styles[fno], m, cx);
- break;
- }
-
- case SWF::FILL_TILED_BITMAP:
- case SWF::FILL_CLIPPED_BITMAP:
- case SWF::FILL_TILED_BITMAP_HARD:
- case SWF::FILL_CLIPPED_BITMAP_HARD:
- {
- SWFMatrix m = fill_styles[fno].getBitmapMatrix();
- SWFMatrix cm = fillstyle_matrix;
- cm.invert();
-
- m.concatenate(cm);
- m.concatenate(inv_stage_matrix);
-
- //
- // 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 ) // never smooth in LOW quality
- {
- // TODO: if forceSmoothing is true, smooth !
- switch ( fill_styles[fno].getBitmapSmoothingPolicy() )
- {
- case fill_style::BITMAP_SMOOTHING_UNSPECIFIED:
- if ( _quality >= QUALITY_BEST ) smooth = true;
- break;
- case fill_style::BITMAP_SMOOTHING_ON:
- smooth = true;
- break;
- default: break;
- }
- }
-
- sh.add_bitmap(dynamic_cast<const agg_bitmap_info*>
- (fill_styles[fno].get_bitmap_info(*this)), m, cx,
- (fill_type==SWF::FILL_TILED_BITMAP) ||
- (fill_type==SWF::FILL_TILED_BITMAP_HARD),
- smooth);
-
- break;
- }
-
- case SWF::FILL_SOLID:
- default:
- {
- rgba color = cx.transform(fill_styles[fno].get_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));
- }
-
- } // switch
-
- } // for
-
- } //build_agg_styles
+
+ // Initializes the internal styles class for AGG renderer
+ void build_agg_styles(agg_style_handler& sh,
+ const std::vector<FillStyle>& FillStyles,
+ const SWFMatrix& fillstyle_matrix, const cxform& cx) {
+
+ SWFMatrix inv_stage_matrix = stage_matrix;
+ inv_stage_matrix.invert();
+
+ const size_t fcount = FillStyles.size();
+
+ for (size_t fno = 0; fno < fcount; ++fno) {
+ const StyleHandler st(stage_matrix, fillstyle_matrix, cx, sh,
+ _quality);
+ boost::apply_visitor(st, FillStyles[fno].fill);
+ }
+ }
/// Draws the given path using the given fill style and color transform.
@@ -2154,20 +2142,6 @@
private: // private variables
- /// Sets m_single_fill_styles to one solid fill with the given color
- void need_single_fill_style(const rgba& color)
- {
-
- if (m_single_fill_styles.size() == 0)
- {
- fill_style dummy;
- m_single_fill_styles.push_back(dummy);
- }
-
- m_single_fill_styles[0].set_color(color);
-
- }
-
typedef agg::renderer_base<PixelFormat> renderer_base;
// renderer base
@@ -2198,7 +2172,7 @@
AlphaMasks _alphaMasks;
/// Cached fill style list with just one entry used for font rendering
- std::vector<fill_style> m_single_fill_styles;
+ std::vector<FillStyle> m_single_FillStyles;
};
=== modified file 'librender/Renderer_agg_style.h'
--- a/librender/Renderer_agg_style.h 2010-01-13 07:54:28 +0000
+++ b/librender/Renderer_agg_style.h 2010-07-31 16:32:49 +0000
@@ -179,9 +179,8 @@
{
public:
- agg_style_gradient(const gnash::fill_style& fs,
- const gnash::SWFMatrix& mat, const gnash::cxform& cx,
- int norm_size)
+ agg_style_gradient(const GradientFill& fs, const SWFMatrix& mat,
+ const cxform& cx, int norm_size)
:
agg_style_base(false),
m_cx(cx),
@@ -196,7 +195,7 @@
// Build gradient lookup table
m_gradient_lut.remove_all();
- const size_t size = fs.get_color_stop_count();
+ const size_t size = fs.recordCount();
// It is essential that at least two colours are added; otherwise agg
// will use uninitialized values.
@@ -204,11 +203,11 @@
for (int i = 0; i != size; ++i) {
- const gradient_record& gr = fs.get_color_stop(i);
- rgba trans_color = m_cx.transform(gr.m_color);
+ 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.m_ratio/255.0, agg::rgba8(trans_color.m_r,
+ 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
@@ -572,7 +571,7 @@
// === GRADIENT ===
- void add_gradient_linear(const gnash::fill_style& fs,
+ void add_gradient_linear(const GradientFill& fs,
const gnash::SWFMatrix& mat, const gnash::cxform& cx)
{
@@ -601,7 +600,7 @@
}
- void add_gradient_radial(const gnash::fill_style& fs,
+ void add_gradient_radial(const GradientFill& fs,
const gnash::SWFMatrix& mat, const gnash::cxform& cx)
{
@@ -636,7 +635,7 @@
m_styles.push_back(st);
}
- void add_gradient_focal(const gnash::fill_style& fs,
+ void add_gradient_focal(const GradientFill& fs,
const gnash::SWFMatrix& mat, const gnash::cxform& cx)
{
typedef agg::rgba8 color_type;
@@ -662,7 +661,7 @@
// re-initialize focal gradient settings
gradient_adaptor_type& adaptor = st->get_gradient_adaptor();
- adaptor.init(32.0, fs.get_focal_point()*32.0, 0.0);
+ adaptor.init(32.0, fs.focalPoint() * 32.0, 0.0);
m_styles.push_back(st);
}
=== modified file 'librender/Renderer_cairo.cpp'
--- a/librender/Renderer_cairo.cpp 2010-07-28 07:57:23 +0000
+++ b/librender/Renderer_cairo.cpp 2010-07-31 16:32:49 +0000
@@ -42,7 +42,7 @@
#include "swf/ShapeRecord.h"
#include "Renderer_cairo.h"
#include "utility.h"
-#include "fill_style.h"
+#include "FillStyle.h"
#include <cmath>
#include <cairo/cairo.h>
@@ -51,80 +51,14 @@
namespace gnash {
-// Converts from RGB image to 32-bit pixels in CAIRO_FORMAT_RGB24 format
-static void
-rgb_to_cairo_rgb24(boost::uint8_t* dst, const GnashImage* im)
-{
- boost::uint32_t* dst32 = reinterpret_cast<boost::uint32_t*>(dst);
- for (size_t y = 0; y < im->height(); y++)
- {
- const boost::uint8_t* src = im->scanlinePointer(y);
- for (size_t x = 0; x < im->width(); x++, src += 3) {
- *dst32++ = (src[0] << 16) | (src[1] << 8) | src[2];
- }
- }
-}
-
-// Converts from RGBA image to 32-bit pixels in CAIRO_FORMAT_ARGB32 format
-static void
-rgba_to_cairo_argb(boost::uint8_t* dst, const GnashImage* im)
-{
- boost::uint32_t* dst32 = reinterpret_cast<boost::uint32_t*>(dst);
- for (size_t y = 0; y < im->height(); y++)
- {
- const boost::uint8_t* src = im->scanlinePointer(y);
- for (size_t x = 0; x < im->width(); x++, src += 4)
- {
- const boost::uint8_t& r = src[0],
- g = src[1],
- b = src[2],
- a = src[3];
-
- if (a) {
- *dst32++ = (a << 24) | (r << 16) | (g << 8) | b;
- } else {
- *dst32++ = 0;
- }
- }
- }
-}
-
-
-static void
-snap_to_half_pixel(cairo_t* cr, double& x, double& y)
-{
- cairo_user_to_device(cr, &x, &y);
-
- x = std::floor(x + 0.5) + 0.5;
- y = std::floor(y + 0.5) + 0.5;
-
- cairo_device_to_user(cr, &x, &y);
-}
-
-static void
-init_cairo_matrix(cairo_matrix_t* cairo_matrix, const SWFMatrix& gnash_matrix)
-{
- cairo_matrix_init(cairo_matrix,
- gnash_matrix.sx/65536.0, gnash_matrix.shx/65536.0,
- gnash_matrix.shy/65536.0, gnash_matrix.sy/65536.0,
- gnash_matrix.tx, gnash_matrix.ty);
-}
-
-void
-pattern_add_color_stops(const fill_style& style, cairo_pattern_t* pattern,
- const cxform& cx)
-{
- for (size_t index = 0; index < style.get_color_stop_count(); ++index) {
- const gradient_record& grad = style.get_color_stop(index);
-
- rgba c = cx.transform(grad.m_color);
-
- cairo_pattern_add_color_stop_rgba (pattern,
- grad.m_ratio / 255.0, c.m_r / 255.0, c.m_g / 255.0,
- c.m_b / 255.0, c.m_a / 255.0);
- }
-}
-
+namespace {
+ void pattern_add_color_stops(const GradientFill& f,
+ cairo_pattern_t* pattern, const cxform& cx);
+ void init_cairo_matrix(cairo_matrix_t* cairo_matrix,
+ const SWFMatrix& gnash_matrix);
+}
+
+namespace {
class bitmap_info_cairo : public BitmapInfo, boost::noncopyable
{
@@ -187,86 +121,147 @@
cairo_pattern_t* _pattern;
};
+
+/// Style handler
+//
+/// Transfer FillStyles to agg styles.
+struct StyleHandler : boost::static_visitor<cairo_pattern_t*>
+{
+ StyleHandler(const cxform& c)
+ :
+ _cx(c)
+ {}
+
+ cairo_pattern_t* operator()(const GradientFill& f) const {
+ const SWFMatrix m = f.matrix();
+ switch (f.type()) {
+ case GradientFill::LINEAR:
+ {
+ cairo_matrix_t mat;
+ init_cairo_matrix(&mat, m);
+
+ cairo_pattern_t* pattern =
+ cairo_pattern_create_linear(0, 0, 256.0, 0);
+ cairo_pattern_set_matrix (pattern, &mat);
+
+ pattern_add_color_stops(f, pattern, _cx);
+ return pattern;
+ }
+ case GradientFill::RADIAL:
+ {
+
+ // Undo the translation our parser applied.
+ gnash::SWFMatrix transl;
+ transl.concatenate_translation(-32, -32);
+ transl.concatenate(m);
+
+ cairo_matrix_t mat;
+ init_cairo_matrix(&mat, transl);
+
+ /// This is 0 for radial gradients.
+ const double focal_pos = 32.0f * f.focalPoint();
+
+ cairo_pattern_t* pattern =
+ cairo_pattern_create_radial(focal_pos, 0.0, 0.0,
+ 0.0, 0.0, 32.0f);
+
+ cairo_pattern_set_matrix (pattern, &mat);
+
+ pattern_add_color_stops(f, pattern, _cx);
+ return pattern;
+ }
+ }
+ // We should never get here.
+ return 0;
+ }
+
+ cairo_pattern_t* operator()(const SolidFill& f) const {
+ rgba c = _cx.transform(f.color());
+ cairo_pattern_t* pattern =
+ cairo_pattern_create_rgba(c.m_r / 255.0, c.m_g / 255.0,
+ c.m_b / 255.0, c.m_a / 255.0);
+ return pattern;
+ }
+
+ cairo_pattern_t* operator()(const BitmapFill& f) const {
+ SWFMatrix m = f.matrix();
+
+ const bitmap_info_cairo* binfo =
+ dynamic_cast<const bitmap_info_cairo*>(f.bitmap());
+
+ if (!binfo) return 0;
+
+ cairo_matrix_t mat;
+ init_cairo_matrix(&mat, m);
+
+ // TODO: the second argument should be fill_type but is unused.
+ cairo_pattern_t* pattern = binfo->apply(&mat, 0);
+ return pattern;
+ }
+
+private:
+ const cxform& _cx;
+};
+
+}
+
+// Converts from RGB image to 32-bit pixels in CAIRO_FORMAT_RGB24 format
+static void
+rgb_to_cairo_rgb24(boost::uint8_t* dst, const GnashImage* im)
+{
+ boost::uint32_t* dst32 = reinterpret_cast<boost::uint32_t*>(dst);
+ for (size_t y = 0; y < im->height(); y++)
+ {
+ const boost::uint8_t* src = im->scanlinePointer(y);
+ for (size_t x = 0; x < im->width(); x++, src += 3) {
+ *dst32++ = (src[0] << 16) | (src[1] << 8) | src[2];
+ }
+ }
+}
+
+// Converts from RGBA image to 32-bit pixels in CAIRO_FORMAT_ARGB32 format
+static void
+rgba_to_cairo_argb(boost::uint8_t* dst, const GnashImage* im)
+{
+ boost::uint32_t* dst32 = reinterpret_cast<boost::uint32_t*>(dst);
+ for (size_t y = 0; y < im->height(); y++)
+ {
+ const boost::uint8_t* src = im->scanlinePointer(y);
+ for (size_t x = 0; x < im->width(); x++, src += 4)
+ {
+ const boost::uint8_t& r = src[0],
+ g = src[1],
+ b = src[2],
+ a = src[3];
+
+ if (a) {
+ *dst32++ = (a << 24) | (r << 16) | (g << 8) | b;
+ } else {
+ *dst32++ = 0;
+ }
+ }
+ }
+}
+
+
+static void
+snap_to_half_pixel(cairo_t* cr, double& x, double& y)
+{
+ cairo_user_to_device(cr, &x, &y);
+
+ x = std::floor(x + 0.5) + 0.5;
+ y = std::floor(y + 0.5) + 0.5;
+
+ cairo_device_to_user(cr, &x, &y);
+}
+
static cairo_pattern_t*
-get_cairo_pattern(Renderer_cairo& renderer, const fill_style& style, const
cxform& cx)
+get_cairo_pattern(const FillStyle& style, const cxform& cx)
{
- int fill_type = style.get_type();
- cairo_pattern_t* pattern = NULL;
-
- switch (fill_type) {
-
- case SWF::FILL_LINEAR_GRADIENT:
- {
- SWFMatrix m = style.getGradientMatrix();
-
- cairo_matrix_t mat;
- init_cairo_matrix(&mat, m);
-
- pattern = cairo_pattern_create_linear(0, 0, 256.0, 0);
- cairo_pattern_set_matrix (pattern, &mat);
-
- pattern_add_color_stops(style, pattern, cx);
-
- break;
- }
- case SWF::FILL_RADIAL_GRADIENT:
- case SWF::FILL_FOCAL_GRADIENT:
- {
- SWFMatrix m = style.getGradientMatrix();
-
- // Undo the translation our parser applied.
- gnash::SWFMatrix transl;
- transl.concatenate_translation(-32, -32);
- transl.concatenate(m);
-
- cairo_matrix_t mat;
- init_cairo_matrix(&mat, transl);
-
- double focal_pos = 0;
-
- if (fill_type == SWF::FILL_FOCAL_GRADIENT) {
- focal_pos = 32.0f * style.get_focal_point();
- }
-
- pattern = cairo_pattern_create_radial(focal_pos, 0.0, 0.0, 0.0, 0.0,
32.0f);
-
- cairo_pattern_set_matrix (pattern, &mat);
-
- pattern_add_color_stops(style, pattern, cx);
- break;
- }
- case SWF::FILL_TILED_BITMAP_HARD:
- case SWF::FILL_TILED_BITMAP:
- case SWF::FILL_CLIPPED_BITMAP:
- case SWF::FILL_CLIPPED_BITMAP_HARD:
- {
- SWFMatrix m = style.getBitmapMatrix();
-
- const bitmap_info_cairo* binfo
- = dynamic_cast<const
bitmap_info_cairo*>(style.get_bitmap_info(renderer));
-
- if (!binfo) {
- return NULL;
- }
-
- cairo_matrix_t mat;
- init_cairo_matrix(&mat, m);
-
- pattern = binfo->apply(&mat, fill_type);
- break;
- }
-
- case SWF::FILL_SOLID:
- {
- rgba c = cx.transform(style.get_color());
- pattern = cairo_pattern_create_rgba (c.m_r / 255.0, c.m_g / 255.0,
- c.m_b / 255.0, c.m_a / 255.0);
- break;
- }
-
- } // switch
+ StyleHandler st(cx);
+ cairo_pattern_t* pattern = boost::apply_visitor(st, style.fill);
- return pattern;
+ return pattern;
}
@@ -275,24 +270,24 @@
public:
CairoPathRunner(Renderer_cairo& renderer,
const std::vector<Path>& paths,
- const std::vector<fill_style>& fill_styles, cairo_t* context)
- : PathParser(paths, fill_styles.size()),
+ const std::vector<FillStyle>& FillStyles, cairo_t* context)
+ : PathParser(paths, FillStyles.size()),
_renderer(renderer),
_cr(context),
_pattern(0),
- _fill_styles(fill_styles)
+ _FillStyles(FillStyles)
{
}
virtual void prepareFill(int fill_index, const cxform& cx)
{
if (!_pattern) {
- _pattern = get_cairo_pattern(_renderer, _fill_styles[fill_index-1], cx);
+ _pattern = get_cairo_pattern(_FillStyles[fill_index-1], cx);
}
}
- virtual void terminateFill(int fill_style)
+ virtual void terminateFill(int FillStyle)
{
- UNUSED(fill_style);
+ UNUSED(FillStyle);
if (!_pattern) {
cairo_new_path(_cr);
@@ -356,7 +351,7 @@
Renderer_cairo& _renderer;
cairo_t* _cr;
cairo_pattern_t* _pattern;
- const std::vector<fill_style>& _fill_styles;
+ const std::vector<FillStyle>& _FillStyles;
};
@@ -870,10 +865,10 @@
void
Renderer_cairo::draw_subshape(const PathVec& path_vec, const SWFMatrix& mat,
const cxform& cx,
- const std::vector<fill_style>& fill_styles,
+ const std::vector<FillStyle>& FillStyles,
const std::vector<LineStyle>& line_styles)
{
- CairoPathRunner runner(*this, path_vec, fill_styles, _cr);
+ CairoPathRunner runner(*this, path_vec, FillStyles, _cr);
runner.run(cx, mat);
draw_outlines(path_vec, line_styles, cx, mat);
@@ -961,7 +956,7 @@
std::vector<PathVec::const_iterator> subshapes = find_subshapes(path_vec);
- const std::vector<fill_style>& fill_styles = shape.fillStyles();
+ const std::vector<FillStyle>& FillStyles = shape.fillStyles();
const std::vector<LineStyle>& line_styles = shape.lineStyles();
for (size_t i = 0; i < subshapes.size()-1; ++i) {
@@ -973,7 +968,7 @@
subshape_paths.push_back(*subshapes[i]);
}
- draw_subshape(subshape_paths, mat, cx, fill_styles,
+ draw_subshape(subshape_paths, mat, cx, FillStyles,
line_styles);
}
}
@@ -983,10 +978,9 @@
const SWFMatrix& mat)
{
cxform dummy_cx;
- std::vector<fill_style> glyph_fs;
+ std::vector<FillStyle> glyph_fs;
- fill_style coloring;
- coloring.setSolid(color);
+ FillStyle coloring = FillStyle(SolidFill(color));
glyph_fs.push_back(coloring);
@@ -1082,6 +1076,35 @@
return true;
}
+namespace {
+
+void
+pattern_add_color_stops(const GradientFill& f, cairo_pattern_t* pattern,
+ const cxform& cx)
+{
+ for (size_t index = 0; index < f.recordCount(); ++index) {
+ const GradientRecord& grad = f.record(index);
+
+ rgba c = cx.transform(grad.color);
+
+ cairo_pattern_add_color_stop_rgba (pattern,
+ grad.ratio / 255.0, c.m_r / 255.0, c.m_g / 255.0,
+ c.m_b / 255.0, c.m_a / 255.0);
+ }
+}
+
+void
+init_cairo_matrix(cairo_matrix_t* cairo_matrix, const SWFMatrix& gnash_matrix)
+{
+ cairo_matrix_init(cairo_matrix,
+ gnash_matrix.sx/65536.0, gnash_matrix.shx/65536.0,
+ gnash_matrix.shy/65536.0, gnash_matrix.sy/65536.0,
+ gnash_matrix.tx, gnash_matrix.ty);
+}
+
+
+}
+
namespace renderer {
namespace cairo {
=== modified file 'librender/Renderer_cairo.h'
--- a/librender/Renderer_cairo.h 2010-07-19 07:43:01 +0000
+++ b/librender/Renderer_cairo.h 2010-07-31 14:05:26 +0000
@@ -87,7 +87,7 @@
void draw_subshape(const PathVec& path_vec,
const SWFMatrix& mat, const cxform& cx,
- const std::vector<fill_style>& fill_styles,
+ const std::vector<FillStyle>& FillStyles,
const std::vector<LineStyle>& line_styles);
void draw_mask(const PathVec& path_vec);
=== modified file 'librender/Renderer_ogl.cpp'
--- a/librender/Renderer_ogl.cpp 2010-07-28 07:57:23 +0000
+++ b/librender/Renderer_ogl.cpp 2010-07-31 16:32:49 +0000
@@ -35,7 +35,7 @@
#include "utility.h"
#include "Range2d.h"
#include "cxform.h"
-#include "fill_style.h"
+#include "FillStyle.h"
#if defined(_WIN32) || defined(WIN32)
# include <Windows.h>
@@ -109,6 +109,53 @@
namespace gnash {
+namespace {
+ const BitmapInfo* createGradientBitmap(const GradientFill& gf,
+ Renderer& renderer);
+}
+
+namespace {
+
+/// Style handler
+//
+/// Transfer FillStyles to the ogl renderer.
+struct StyleHandler : boost::static_visitor<>
+{
+ StyleHandler(const cxform& c, Renderer& r)
+ :
+ _cx(c),
+ _renderer(r)
+ {}
+
+ void operator()(const GradientFill& f) const {
+
+ const bitmap_info_ogl* binfo = static_cast<const bitmap_info_ogl*>(
+ createGradientBitmap(f, _renderer));
+
+ SWFMatrix m = f.matrix();
+ binfo->apply(m, bitmap_info_ogl::WRAP_CLAMP);
+ }
+
+ void operator()(const SolidFill& f) const {
+ const rgba c = _cx.transform(f.color());
+ glColor4ub(c.m_r, c.m_g, c.m_b, c.m_a);
+ }
+
+ void operator()(const BitmapFill& f) const {
+ const bitmap_info_ogl* binfo = static_cast<const bitmap_info_ogl*>(
+ f.bitmap());
+ binfo->apply(f.matrix(), f.type() == BitmapFill::TILED ?
+ bitmap_info_ogl::WRAP_REPEAT : bitmap_info_ogl::WRAP_CLAMP);
+ }
+
+private:
+ const cxform& _cx;
+ Renderer& _renderer;
+};
+
+}
+
+
#ifdef OSMESA_TESTING
class OSRenderMesa : public boost::noncopyable
@@ -1094,10 +1141,9 @@
add_paths(const PathVec& path_vec)
{
cxform dummy_cx;
- std::vector<fill_style> dummy_fs;
+ std::vector<FillStyle> dummy_fs;
- fill_style coloring;
- coloring.setSolid(rgba(0,0,0,0));
+ FillStyle coloring = FillStyle(SolidFill(rgba(0, 0, 0, 0)));
dummy_fs.push_back(coloring);
@@ -1299,63 +1345,10 @@
}
}
- void apply_fill_style(const fill_style& style, const SWFMatrix& /* mat */,
const cxform& cx)
+ void apply_FillStyle(const FillStyle& style, const SWFMatrix& /* mat */,
const cxform& cx)
{
- int fill_type = style.get_type();
-
- rgba c = cx.transform(style.get_color());
-
- glColor4ub(c.m_r, c.m_g, c.m_b, c.m_a);
-
-
- switch (fill_type) {
-
- case SWF::FILL_LINEAR_GRADIENT:
- case SWF::FILL_RADIAL_GRADIENT:
- case SWF::FILL_FOCAL_GRADIENT:
- {
-
- const bitmap_info_ogl* binfo = static_cast<const bitmap_info_ogl*>(
- style.need_gradient_bitmap(*this));
-
- SWFMatrix m = style.getGradientMatrix();
-
- binfo->apply(m, bitmap_info_ogl::WRAP_CLAMP);
-
- break;
- }
- case SWF::FILL_TILED_BITMAP_HARD:
- case SWF::FILL_TILED_BITMAP:
- {
- const bitmap_info_ogl* binfo = static_cast<const bitmap_info_ogl*>(
- style.get_bitmap_info(*this));
-
- binfo->apply(style.getBitmapMatrix(), bitmap_info_ogl::WRAP_REPEAT);
- break;
- }
-
- case SWF::FILL_CLIPPED_BITMAP:
- // smooth=true;
- case SWF::FILL_CLIPPED_BITMAP_HARD:
- {
- const bitmap_info_ogl* binfo = dynamic_cast<const bitmap_info_ogl*>(
- style.get_bitmap_info(*this));
-
- assert(binfo);
-
- binfo->apply(style.getBitmapMatrix(), bitmap_info_ogl::WRAP_CLAMP);
-
- break;
- }
-
- case SWF::FILL_SOLID:
- {
- rgba c = cx.transform(style.get_color());
-
- glColor4ub(c.m_r, c.m_g, c.m_b, c.m_a);
- }
-
- } // switch
+ const StyleHandler st(cx, *this);
+ boost::apply_visitor(st, style.fill);
}
@@ -1364,7 +1357,7 @@
{
// GNASH_REPORT_FUNCTION;
- // In case GL_TEXTURE_2D was enabled by apply_fill_style(), disable it now.
+ // In case GL_TEXTURE_2D was enabled by apply_FillStyle(), disable it now.
// FIXME: this sucks
glDisable(GL_TEXTURE_2D);
@@ -1462,7 +1455,7 @@
void
draw_outlines(const PathVec& path_vec, const PathPointMap& pathpoints,
const SWFMatrix& mat, const cxform& cx,
- const std::vector<fill_style>& /* fill_styles */,
+ const std::vector<FillStyle>& /* FillStyles */,
const std::vector<LineStyle>& line_styles)
{
@@ -1626,13 +1619,13 @@
draw_subshape(const PathVec& path_vec,
const SWFMatrix& mat,
const cxform& cx,
- const std::vector<fill_style>& fill_styles,
+ const std::vector<FillStyle>& FillStyles,
const std::vector<LineStyle>& line_styles)
{
PathVec normalized = normalize_paths(path_vec);
PathPointMap pathpoints = getPathPoints(normalized);
- for (size_t i = 0; i < fill_styles.size(); ++i) {
+ for (size_t i = 0; i < FillStyles.size(); ++i) {
PathPtrVec paths = paths_by_style(normalized, i+1);
if (!paths.size()) {
@@ -1662,20 +1655,25 @@
_tesselator.endContour();
}
-
-
- apply_fill_style(fill_styles[i], mat, cx);
-
- if (fill_styles[i].get_type() != SWF::FILL_SOLID) {
- // Apply alpha premultiplication.
- glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+ apply_FillStyle(FillStyles[i], mat, cx);
+
+ // This is terrible, but since the renderer is half dead I don't care.
+ try {
+ boost::get<SolidFill>(FillStyles[i].fill);
+ }
+ catch (const boost::bad_get&) {
+ // For non solid fills...
+ glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
}
_tesselator.tesselate();
- if (fill_styles[i].get_type() != SWF::FILL_SOLID) {
- // restore to original.
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ try {
+ boost::get<SolidFill>(FillStyles[i].fill);
+ }
+ catch (const boost::bad_get&) {
+ // Restore to original.
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
glDisable(GL_TEXTURE_GEN_S);
@@ -1684,7 +1682,7 @@
glDisable(GL_TEXTURE_2D);
}
- draw_outlines(normalized, pathpoints, mat, cx, fill_styles, line_styles);
+ draw_outlines(normalized, pathpoints, mat, cx, FillStyles, line_styles);
}
// Drawing procedure:
@@ -1731,7 +1729,7 @@
std::vector<PathVec::const_iterator> subshapes = find_subshapes(path_vec);
- const std::vector<fill_style>& fill_styles = shape.fillStyles();
+ const std::vector<FillStyle>& FillStyles = shape.fillStyles();
const std::vector<LineStyle>& line_styles = shape.lineStyles();
for (size_t i = 0; i < subshapes.size()-1; ++i) {
@@ -1743,7 +1741,7 @@
subshape_paths.push_back(*subshapes[i]);
}
- draw_subshape(subshape_paths, mat, cx, fill_styles,
+ draw_subshape(subshape_paths, mat, cx, FillStyles,
line_styles);
}
}
@@ -1753,10 +1751,9 @@
{
if (_drawing_mask) abort();
cxform dummy_cx;
- std::vector<fill_style> glyph_fs;
+ std::vector<FillStyle> glyph_fs;
- fill_style coloring;
- coloring.setSolid(c);
+ FillStyle coloring = FillStyle(SolidFill(c));
glyph_fs.push_back(coloring);
@@ -1842,16 +1839,110 @@
}
return renderer;
}
-
-
+
+namespace {
+
+// TODO: this function is rubbish and shouldn't survive a rewritten OGL
+// renderer.
+rgba
+sampleGradient(const GradientFill& fill, boost::uint8_t ratio)
+{
+
+ // By specs, first gradient should *always* be 0,
+ // anyway a malformed SWF could break this,
+ // so we cannot rely on that information...
+ if (ratio < fill.record(0).ratio) {
+ return fill.record(0).color;
+ }
+
+ if (ratio >= fill.record(fill.recordCount() - 1).ratio) {
+ return fill.record(fill.recordCount() - 1).color;
+ }
+
+ for (size_t i = 1, n = fill.recordCount(); i < n; ++i) {
+
+ const GradientRecord& gr1 = fill.record(i);
+ if (gr1.ratio < ratio) continue;
+
+ const GradientRecord& gr0 = fill.record(i - 1);
+ if (gr0.ratio > ratio) continue;
+
+ float f = 0.0f;
+
+ if (gr0.ratio != gr1.ratio) {
+ f = (ratio - gr0.ratio) / float(gr1.ratio - gr0.ratio);
+ }
+ else {
+ // Ratios are equal IFF first and second GradientRecord
+ // have the same ratio. This would be a malformed SWF.
+ IF_VERBOSE_MALFORMED_SWF(
+ log_swferror(_("two gradients in a FillStyle "
+ "have the same position/ratio: %d"),
+ gr0.ratio);
+ );
+ }
+
+ rgba result;
+ result.set_lerp(gr0.color, gr1.color, f);
+ return result;
+ }
+
+ // Assuming gradients are ordered by ratio? see start comment
+ return fill.record(fill.recordCount() - 1).color;
+}
+
+const BitmapInfo*
+createGradientBitmap(const GradientFill& gf, Renderer& renderer)
+{
+ std::auto_ptr<ImageRGBA> im;
+
+ switch (gf.type())
+ {
+ case GradientFill::LINEAR:
+ // Linear gradient.
+ im.reset(new ImageRGBA(256, 1));
+
+ for (size_t i = 0; i < im->width(); i++) {
+
+ rgba sample = sampleGradient(gf, i);
+ im->setPixel(i, 0, sample.m_r, sample.m_g,
+ sample.m_b, sample.m_a);
+ }
+ break;
+
+ case GradientFill::RADIAL:
+ // Focal gradient.
+ im.reset(new ImageRGBA(64, 64));
+
+ for (size_t j = 0; j < im->height(); j++)
+ {
+ for (size_t i = 0; i < im->width(); i++)
+ {
+ float radiusy = (im->height() - 1) / 2.0f;
+ float radiusx = radiusy + std::abs(radiusy *
gf.focalPoint());
+ float y = (j - radiusy) / radiusy;
+ float x = (i - radiusx) / radiusx;
+ int ratio = std::floor(255.5f * std::sqrt(x*x + y*y));
+
+ if (ratio > 255) ratio = 255;
+
+ rgba sample = sampleGradient(gf, ratio);
+ im->setPixel(i, j, sample.m_r, sample.m_g,
+ sample.m_b, sample.m_a);
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ const BitmapInfo* bi = renderer.createBitmapInfo(
+ static_cast<std::auto_ptr<GnashImage> >(im));
+
+ return bi;
+}
+
+}
} // namespace gnash
-
-/*
-
-Markus: A. A. I still miss you and the easter 2006, you know.
- A. J. I miss you too, but you'll probably not read this code ever... :/
-
-*/
-
=== modified file 'testsuite/libcore.all/ClassSizes.cpp'
--- a/testsuite/libcore.all/ClassSizes.cpp 2010-07-29 06:24:31 +0000
+++ b/testsuite/libcore.all/ClassSizes.cpp 2010-07-31 14:05:26 +0000
@@ -35,7 +35,7 @@
#include "Shape.h"
#include "TextField.h"
#include "SWFStream.h"
-#include "fill_style.h"
+#include "FillStyle.h"
#include "swf/DefineFontAlignZonesTag.h"
#include "swf/DefineShapeTag.h"
#include "swf/DefineButtonCxformTag.h"
@@ -74,7 +74,7 @@
(int) (float) (long) (double) \
(Property*) (auto_ptr<Property>) (scoped_ptr<Property>) \
(shared_ptr<Property>) (intrusive_ptr<as_object>) (GcResource) \
-(rgba) (SWFMatrix) (SWFRect) (LineStyle) (fill_style) (cxform) \
+(rgba) (SWFMatrix) (SWFRect) (LineStyle) (FillStyle) (cxform) \
(as_value) \
(DynamicShape)(ShapeRecord)(TextRecord) \
(Property) (PropertyList) \
=== modified file 'testsuite/libcore.all/MatrixTest.cpp'
--- a/testsuite/libcore.all/MatrixTest.cpp 2010-03-12 23:37:40 +0000
+++ b/testsuite/libcore.all/MatrixTest.cpp 2010-08-02 07:54:02 +0000
@@ -79,7 +79,6 @@
// Test identity SWFMatrix.
//
SWFMatrix identity;
- check(identity.is_valid());
check_equals(identity.get_x_scale(), 1);
check_equals(identity.get_y_scale(), 1);
check_equals(identity.get_rotation(), 0);
=== modified file 'testsuite/misc-ming.all/DrawingApiTest.as'
--- a/testsuite/misc-ming.all/DrawingApiTest.as 2010-01-26 13:40:21 +0000
+++ b/testsuite/misc-ming.all/DrawingApiTest.as 2010-07-31 07:49:37 +0000
@@ -901,6 +901,70 @@
beginGradientFill(fillType, colors, alphas, ratios, matrix);
draw100x100Box(x, y, grad);
+
+ // Shape 14
+ x += 100;
+
+ // Test a linear gradient with one stop
+ fillType = "linear";
+ colors = [0xff0000];
+ alphas = [100];
+ ratios = [0];
+ matrix.createGradientBox(90, 90, 0, x, y);
+ beginGradientFill(fillType, colors, alphas, ratios, matrix);
+ draw100x100Box(x, y, grad);
+
+
+ // Shape 15
+ x += 100;
+
+ // Test a linear gradient with one stop
+ fillType = "radial";
+ colors = [0x00ff00];
+ alphas = [100];
+ ratios = [0];
+ matrix.createGradientBox(90, 90, 0, x, y);
+ beginGradientFill(fillType, colors, alphas, ratios, matrix);
+ draw100x100Box(x, y, grad);
+
+ // Shape 16
+ x += 100;
+
+ // Bad fill style results in no fill.
+ fillType = "rodial";
+ colors = [0x0000ff, 0xffffff, 0x00ff00];
+ alphas = [100, 100, 100];
+ ratios = [0, 0x10, 0x05];
+ matrix.createGradientBox(90, 90, 0, x, y);
+ beginGradientFill(fillType, colors, alphas, ratios, matrix);
+ draw100x100Box(x, y, grad);
+
+ // Shape 17
+ x += 100;
+
+ // Extra arguments result in no fill for SWF6
+ fillType = "radial";
+ colors = [0x0000ff, 0xffffff, 0x00ff00];
+ alphas = [100, 100, 100];
+ ratios = [0, 0x10, 0x05];
+ matrix.createGradientBox(90, 90, 0, x, y);
+ beginGradientFill(fillType, colors, alphas, ratios, matrix, "pad");
+ draw100x100Box(x, y, grad);
+
+ x = 0;
+ y += 100;
+
+ // Shape 18
+
+ // 4 arguments result in no fill for SWF6
+ fillType = "radial";
+ colors = [0x0000ff, 0xffffff, 0x00ff00];
+ alphas = [100, 100, 100];
+ ratios = [0, 0x10, 0x05];
+ matrix.createGradientBox(90, 90, 0, x, y);
+ beginGradientFill(fillType, colors, alphas, ratios);
+ draw100x100Box(x, y, grad);
+
_visible = false;
};
=== modified file 'testsuite/misc-ming.all/DrawingApiTestRunner.cpp'
--- a/testsuite/misc-ming.all/DrawingApiTestRunner.cpp 2010-01-26 13:40:21
+0000
+++ b/testsuite/misc-ming.all/DrawingApiTestRunner.cpp 2010-07-31 07:49:37
+0000
@@ -22,8 +22,6 @@
#include "MovieTester.h"
#include "MovieClip.h"
-#include "DisplayObject.h"
-#include "DisplayList.h"
#include "log.h"
#include "GnashKey.h" // for gnash::key::code
@@ -1005,6 +1003,45 @@
check_pixel(x + 90 - 2, y + 2, 2, green, 2);
check_pixel(x + 90 - 2, y + 90 - 2, 2, green, 2);
+ // Shape 14
+ x += 100;
+ check_pixel(x + 7, y + 2, 2, red, 2);
+ check_pixel(x + 7, y + 90 - 2, 2, red, 2);
+ check_pixel(x + 90 - 2, y + 2, 2, red, 2);
+ check_pixel(x + 90 - 2, y + 90 - 2, 2, red, 2);
+
+ // Shape 15
+ x += 100;
+ check_pixel(x + 7, y + 2, 2, green, 2);
+ check_pixel(x + 7, y + 90 - 2, 2, green, 2);
+ check_pixel(x + 90 - 2, y + 2, 2, green, 2);
+ check_pixel(x + 90 - 2, y + 90 - 2, 2, green, 2);
+
+ // 3 invalid fills follow
+
+ // Shape 16
+ x += 100;
+ check_pixel(x + 7, y + 2, 2, white, 2);
+ check_pixel(x + 7, y + 90 - 2, 2, white, 2);
+ check_pixel(x + 90 - 2, y + 2, 2, white, 2);
+ check_pixel(x + 90 - 2, y + 90 - 2, 2, white, 2);
+
+ // Shape 17
+ x += 100;
+ check_pixel(x + 7, y + 2, 2, white, 2);
+ check_pixel(x + 7, y + 90 - 2, 2, white, 2);
+ check_pixel(x + 90 - 2, y + 2, 2, white, 2);
+ check_pixel(x + 90 - 2, y + 90 - 2, 2, white, 2);
+
+ x = 0;
+ y += 100;
+
+ // Shape 18
+ check_pixel(x + 7, y + 2, 2, white, 2);
+ check_pixel(x + 7, y + 90 - 2, 2, white, 2);
+ check_pixel(x + 90 - 2, y + 2, 2, white, 2);
+ check_pixel(x + 90 - 2, y + 90 - 2, 2, white, 2);
+
//----------------------------------------------------------
// TODO: check startDrag/stopDrag on the hit detector
// (hit 'd' key to toggle)
=== added file 'testsuite/misc-ming.all/GradientFillTest.as'
--- a/testsuite/misc-ming.all/GradientFillTest.as 1970-01-01 00:00:00
+0000
+++ b/testsuite/misc-ming.all/GradientFillTest.as 2010-07-31 07:49:37
+0000
@@ -0,0 +1,317 @@
+//
+// Some tests for the Drawing API
+// Build with:
+// makeswf -o DrawingApi.swf DrawingApi.as
+// Run with:
+// firefox DrawingApi.swf
+// Or:
+// gnash DrawingApi.swf
+//
+//
+// Click the mouse button to turn the cursor shape into a mask and back.
+// Press a number on the keyboard to switch between "pages" of the drawing.
+// We currently have pages 1, 2, 3, 4.
+// All pages are tested automatically.
+//
+// '-' and '+' decrement and increment _alpha
+// 'h' toggles _visible
+//
+
+
+#include "../actionscript.all/check.as"
+
+// This tests the gradients found in DrawingApiTest for version 8, where
+// some extra arguments were added.
+
+// Make Matrix visible for easier gradient tests.
+ASSetPropFlags(_global, "flash", 0, 5248);
+
+draw100x100Box = function(x, y, mc) {
+ s = 90;
+ with (mc) {
+ moveTo(x, y);
+ lineTo(x + s, y);
+ lineTo(x + s, y + s);
+ lineTo(x, y + s);
+ lineTo(x, y);
+ endFill();
+ };
+};
+
+createEmptyMovieClip("grad", 150);
+
+// Test gradients.
+// The beginGradientFill function works with fake Matrices, but there is no
+// point making more work for ourselves as that testing is already done for
+// the Matrix class.
+// Only the "box" matrixType gets special handling.
+
+with(grad) {
+
+ // Linear gradients
+ fillType = "linear";
+
+ x = 0;
+ y = 0;
+
+ // shape 1
+ colors = [0x0000ff, 0xffffff];
+ alphas = [100, 100];
+ ratios = [0, 0xff];
+ matrix = new flash.geom.Matrix();
+ beginGradientFill(fillType, colors, alphas, ratios, matrix);
+ draw100x100Box(x, y, grad);
+
+ // shape 2
+ x += 100;
+ colors = [0x0000ff, 0xffffff];
+ alphas = [100, 100];
+ ratios = [0, 0xff];
+ matrix.createGradientBox(90, 90, 0, x, y);
+ beginGradientFill(fillType, colors, alphas, ratios, matrix);
+ draw100x100Box(x, y, grad);
+
+ // shape 3
+ x += 100;
+ colors = [0x0000ff, 0xffffff, 0xff00ff];
+ alphas = [100, 100, 100];
+ ratios = [0, 0xff / 2, 0xff];
+ matrix.createGradientBox(90, 90, Math.PI / 4, x, y);
+ beginGradientFill(fillType, colors, alphas, ratios, matrix);
+ draw100x100Box(x, y, grad);
+
+ // shape 4
+ x += 100;
+ colors = [0x0000ff, 0xffffff, 0xff00ff];
+ alphas = [100, 100, 100];
+ ratios = [0, 0xff / 2, 0xff];
+ matrix.createGradientBox(180, 180, Math.PI / 4, x, y);
+ beginGradientFill(fillType, colors, alphas, ratios, matrix);
+ draw100x100Box(x, y, grad);
+
+ // shape 5
+ x += 100;
+ colors = [0x0000ff, 0xffffff, 0x00ff00];
+ alphas = [100, 100, 100];
+ ratios = [0, 0xff / 2, 0xff];
+ matrix.createGradientBox(180, 180, Math.PI / 4 * 3, x - 90, y - 90);
+ beginGradientFill(fillType, colors, alphas, ratios, matrix);
+ draw100x100Box(x, y, grad);
+
+ // shape 6
+ x += 100;
+ colors = [0x0000ff, 0xffffff, 0x00ff00, 0xff00ff, 0x00ffff, 0xffff00 ];
+ alphas = [100, 100, 100, 50, 25, 100];
+ ratios = [0, 0xff / 5, 0xff / 5 * 2, 0xff / 5 * 3, 0xff / 5 * 4, 0xff];
+ matrix.createGradientBox(90, 90, Math.PI / 2, x, y);
+ beginGradientFill(fillType, colors, alphas, ratios, matrix);
+ draw100x100Box(x, y, grad);
+
+ // Radial gradients
+ fillType = "radial";
+
+ x = 0;
+ y += 100;
+
+ // shape 7
+ colors = [0x0000ff, 0xffffff];
+ alphas = [100, 100];
+ ratios = [0, 0xff];
+ matrix = new flash.geom.Matrix();
+ beginGradientFill(fillType, colors, alphas, ratios, matrix);
+ draw100x100Box(x, y, grad);
+
+ // shape 8
+ x += 100;
+ colors = [0x0000ff, 0xffffff];
+ alphas = [100, 100];
+ ratios = [0, 0xff];
+ matrix.createGradientBox(90, 90, 0, x, y);
+ beginGradientFill(fillType, colors, alphas, ratios, matrix);
+ draw100x100Box(x, y, grad);
+
+ // shape 9
+ x += 100;
+ colors = [0x0000ff, 0xffffff, 0xff00ff];
+ alphas = [100, 100, 100];
+ ratios = [0, 0xff / 2, 0xff];
+ matrix.createGradientBox(90, 90, Math.PI / 4, x, y);
+ beginGradientFill(fillType, colors, alphas, ratios, matrix);
+ draw100x100Box(x, y, grad);
+
+ // shape 10
+ x += 100;
+ colors = [0x0000ff, 0xffffff, 0xff00ff];
+ alphas = [100, 100, 100];
+ ratios = [0, 0xff / 2, 0xff];
+ matrix.createGradientBox(180, 180, Math.PI / 4, x, y);
+ beginGradientFill(fillType, colors, alphas, ratios, matrix);
+ draw100x100Box(x, y, grad);
+
+ // shape 11
+ x += 100;
+ colors = [0x0000ff, 0xffffff, 0x00ff00];
+ alphas = [100, 100, 100];
+ ratios = [0, 0xff / 2, 0xff];
+ matrix.createGradientBox(180, 180, Math.PI / 4 * 3, x - 90, y - 90);
+ beginGradientFill(fillType, colors, alphas, ratios, matrix);
+ draw100x100Box(x, y, grad);
+
+ // shape 12
+ x += 100;
+ colors = [0x0000ff, 0xffffff, 0x00ff00, 0xff00ff, 0x00ffff, 0xffff00 ];
+ alphas = [100, 100, 100, 50, 25, 100];
+ ratios = [0, 0xff / 5, 0xff / 5 * 2, 0xff / 5 * 3, 0xff / 5 * 4, 0xff];
+ matrix.createGradientBox(90, 90, Math.PI / 2, x, y);
+ beginGradientFill(fillType, colors, alphas, ratios, matrix);
+ draw100x100Box(x, y, grad);
+
+ y += 100;
+ x = 0;
+
+ // Shape 13
+
+ // Check that ratios are adjusted if they do not get successively larger.
+ fillType = "linear";
+ colors = [0x0000ff, 0xffffff, 0x00ff00];
+ alphas = [100, 100, 100];
+ ratios = [0, 0x10, 0x05];
+ matrix.createGradientBox(90, 90, 0, x, y);
+ beginGradientFill(fillType, colors, alphas, ratios, matrix);
+ draw100x100Box(x, y, grad);
+
+
+ // Shape 14
+ x += 100;
+
+ // Test a linear gradient with one stop
+ fillType = "linear";
+ colors = [0xff0000];
+ alphas = [100];
+ ratios = [0];
+ matrix.createGradientBox(90, 90, 0, x, y);
+ beginGradientFill(fillType, colors, alphas, ratios, matrix);
+ draw100x100Box(x, y, grad);
+
+
+ // Shape 15
+ x += 100;
+
+ // Test a linear gradient with one stop
+ fillType = "radial";
+ colors = [0x00ff00];
+ alphas = [100];
+ ratios = [0];
+ matrix.createGradientBox(90, 90, 0, x, y);
+ beginGradientFill(fillType, colors, alphas, ratios, matrix);
+ draw100x100Box(x, y, grad);
+
+ // Shape 15
+ x += 100;
+
+ // Test a radial gradient with SWF8 args
+ fillType = "radial";
+ colors = [0xffff00, 0x0000ff, 0x00ffff];
+ alphas = [100, 100, 100];
+ ratios = [0, 0xa0, 0xff];
+ matrix.createGradientBox(90, 90, 0, x, y);
+ beginGradientFill(fillType, colors, alphas, ratios, matrix, "pad");
+ draw100x100Box(x, y, grad);
+
+ // Shape 16
+ x += 100;
+
+ // Test a radial gradient with SWF8 args
+ fillType = "radial";
+ colors = [0xffff00, 0x0000ff, 0x00ffff];
+ alphas = [100, 100, 100];
+ ratios = [0, 0xa0, 0xff];
+ matrix.createGradientBox(90, 90, 0, x, y);
+ beginGradientFill(fillType, colors, alphas, ratios, matrix, "reflect");
+ draw100x100Box(x, y, grad);
+
+ // Shape 17
+ x += 100;
+
+ // Test a radial gradient with SWF8 args
+ fillType = "radial";
+ colors = [0xffff00, 0x0000ff, 0x00ffff];
+ alphas = [100, 100, 100];
+ ratios = [0, 0xa0, 0xff];
+ matrix.createGradientBox(90, 90, 0, x, y);
+ beginGradientFill(fillType, colors, alphas, ratios, matrix, "repeat");
+ draw100x100Box(x, y, grad);
+
+ x = 0;
+ y += 100;
+
+ // Shape 18
+
+ // Test a radial gradient with SWF8 args
+ fillType = "radial";
+ colors = [0xffff00, 0x0000ff, 0x00ffff];
+ alphas = [100, 100, 100];
+ ratios = [0, 0xa0, 0xff];
+ matrix.createGradientBox(90, 90, 0, x, y);
+ beginGradientFill(fillType, colors, alphas, ratios, matrix, "");
+ draw100x100Box(x, y, grad);
+
+ // Shape 19
+ x += 100;
+
+ // Test a radial gradient with SWF8 args
+ fillType = "radial";
+ colors = [0xffff00, 0x0000ff, 0x00ffff];
+ alphas = [100, 100, 100];
+ ratios = [0, 0xa0, 0xff];
+ matrix.createGradientBox(90, 90, 0, x, y);
+ beginGradientFill(fillType, colors, alphas, ratios, matrix, "pad",
+ "RGB");
+ draw100x100Box(x, y, grad);
+
+
+ // Shape 20
+ x += 100;
+
+ // Test a radial gradient with SWF8 args
+ fillType = "radial";
+ colors = [0xffff00, 0x0000ff, 0x00ffff];
+ alphas = [100, 100, 100];
+ ratios = [0, 0xa0, 0xff];
+ matrix.createGradientBox(90, 90, 0, x, y);
+ beginGradientFill(fillType, colors, alphas, ratios, matrix, "pad",
+ "linearRGB");
+ draw100x100Box(x, y, grad);
+
+ // Shape 21
+ x += 100;
+
+ // Test a radial gradient with SWF8 args
+ fillType = "radial";
+ colors = [0xffff00, 0x0000ff, 0x00ffff];
+ alphas = [100, 100, 100];
+ ratios = [0, 0xa0, 0xff];
+ matrix.createGradientBox(90, 90, 0, x, y);
+ beginGradientFill(fillType, colors, alphas, ratios, matrix, "pad",
+ "");
+ draw100x100Box(x, y, grad);
+
+ // Shape 22
+ x += 100;
+
+ // Test a radial gradient with SWF8 args
+ fillType = "radial";
+ colors = [0xffff00, 0x0000ff, 0x00ffff];
+ alphas = [100, 100, 100];
+ ratios = [0, 0xa0, 0xff];
+ matrix.createGradientBox(90, 90, 0, x, y);
+ beginGradientFill(fillType, colors, alphas, ratios, matrix, "pad",
+ "RGB", 3.5);
+ draw100x100Box(x, y, grad);
+
+};
+grad.onRollOver = function() {};
+
+stop();
+
+
=== modified file 'testsuite/misc-ming.all/Makefile.am'
--- a/testsuite/misc-ming.all/Makefile.am 2010-07-29 06:24:31 +0000
+++ b/testsuite/misc-ming.all/Makefile.am 2010-07-31 07:49:37 +0000
@@ -37,6 +37,7 @@
remoting.php \
gotoFrame2Test.as \
DrawingApiTest.as \
+ GradientFillTest.as \
LC-Receive.as \
LC-Send.as \
FlashVarsTest.as \
@@ -2013,6 +2014,9 @@
XMLSocketTest.swf > $@
chmod 755 $@
+GradientFillTest.swf: $(srcdir)/GradientFillTest.as
+ $(MAKESWF) -v 8 -r 1 -o $@ $(srcdir)/empty.as
$(srcdir)/GradientFillTest.as
+
DrawingApiTest.swf: $(srcdir)/DrawingApiTest.as
$(MAKESWF) -r 1 -o $@ $(srcdir)/empty.as $(srcdir)/DrawingApiTest.as
- [Gnash-commit] /srv/bzr/gnash/trunk r12346: Rewrite fill style handling to make it easier to extend. Fix bug #26670,
Benjamin Wolsey <=