1 // LineStyle.cpp Line style types.
3 // Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 Free Software
6 // This program is free software; you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation; either version 3 of the License, or
9 // (at your option) any later version.
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software
18 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 // Based on public domain work by Thatcher Ulrich <tu@tulrich.com> 2003
21 // styles.cpp -- Thatcher Ulrich <tu@tulrich.com> 2003
23 #include "LineStyle.h"
25 #include "TypesParser.h"
26 #include "RunResources.h"
28 #include "SWFStream.h"
29 #include "smart_ptr.h"
30 #include "movie_definition.h"
32 #include "GnashException.h"
33 #include "FillStyle.h"
34 #include "GnashNumeric.h"
40 class GetColor
: public boost::static_visitor
<rgba
>
43 rgba
operator()(const SolidFill
& f
) const {
46 rgba
operator()(const GradientFill
&) const {
49 rgba
operator()(const BitmapFill
&) const {
56 LineStyle::LineStyle()
60 _scaleVertically(true),
61 _scaleHorizontally(true),
64 _startCapStyle(CAP_ROUND
),
65 _endCapStyle(CAP_ROUND
),
66 _joinStyle(JOIN_ROUND
),
67 _miterLimitFactor(1.0f
)
72 LineStyle::read_morph(SWFStream
& in
, SWF::TagType t
, movie_definition
& md
,
73 const RunResources
& /*r*/, LineStyle
*pOther
)
75 if (t
== SWF::DEFINEMORPHSHAPE
)
77 in
.ensureBytes(2 + 2);
78 m_width
= in
.read_u16();
79 pOther
->m_width
= in
.read_u16();
80 m_color
= readRGBA(in
);
81 pOther
->m_color
= readRGBA(in
);
85 assert(t
== SWF::DEFINEMORPHSHAPE2
|| t
== SWF::DEFINEMORPHSHAPE2_
);
87 // MorphShape 2 from here down.
88 in
.ensureBytes(4 + 2);
90 m_width
= in
.read_u16();
91 pOther
->m_width
= in
.read_u16();
93 int flags1
= in
.read_u8();
94 int flags2
= in
.read_u8();
95 _startCapStyle
= (CapStyle
)((flags1
& 0xC0) >> 6);
96 _joinStyle
= (JoinStyle
)((flags1
& 0x30) >> 4);
97 bool has_fill
= flags1
& (1 << 3);
98 _scaleHorizontally
= !(flags1
& (1 << 2));
99 _scaleVertically
= !(flags1
& (1 << 1));
100 _pixelHinting
= flags1
& (1 << 0);
101 _noClose
= flags2
& (1 << 2);
102 _endCapStyle
= (CapStyle
) (flags2
& 0x03);
104 if (_joinStyle
== JOIN_MITER
)
107 _miterLimitFactor
= in
.read_short_ufixed();
110 OptionalFillPair fp
= readFills(in
, t
, md
, true);
112 // TODO: store a fill style properly, removing the need for the
114 m_color
= boost::apply_visitor(GetColor(), fp
.first
.fill
);
115 pOther
->m_color
= boost::apply_visitor(GetColor(), fp
.second
->fill
);
118 m_color
= readRGBA(in
);
119 pOther
->m_color
= readRGBA(in
);
124 LineStyle::read(SWFStream
& in
, SWF::TagType t
, movie_definition
& md
,
125 const RunResources
& /*r*/)
131 m_width
= in
.read_u16();
132 m_color
= readRGBA(in
);
135 case SWF::DEFINESHAPE
:
136 case SWF::DEFINESHAPE2
:
138 m_width
= in
.read_u16();
139 m_color
= readRGB(in
);
142 case SWF::DEFINESHAPE4
:
143 case SWF::DEFINESHAPE4_
:
145 // TODO: Unfinished. Temporary to allow DefineShape4 to work in
146 // many cases, but does not work correctly in all cases.
148 m_width
= in
.read_u16();
150 const boost::uint8_t flags1
= in
.read_u8();
151 const boost::uint8_t flags2
= in
.read_u8();
153 _startCapStyle
= (CapStyle
)((flags1
& 0xC0) >> 6);
154 _joinStyle
= (JoinStyle
)((flags1
& 0x30) >> 4);
155 const bool has_fill
= flags1
& (1 << 3);
156 _scaleHorizontally
= !(flags1
& (1 << 2));
157 _scaleVertically
= !(flags1
& (1 << 1));
158 _pixelHinting
= flags1
& (1 << 0);
159 _noClose
= flags2
& (1 << 2);
160 _endCapStyle
= (CapStyle
) (flags2
& 0x03);
162 if (_joinStyle
== JOIN_MITER
) {
164 _miterLimitFactor
= in
.read_short_ufixed();
167 // TODO: store a fill style properly, removing the need for the
169 OptionalFillPair fp
= readFills(in
, t
, md
, false);
170 m_color
= boost::apply_visitor(GetColor(), fp
.first
.fill
);
173 m_color
= readRGBA(in
);
180 LineStyle::set_lerp(const LineStyle
& ls1
, const LineStyle
& ls2
, float ratio
)
182 m_width
= static_cast<boost::uint16_t>(
183 frnd(lerp
<float>(ls1
.getThickness(), ls2
.getThickness(), ratio
)));
184 m_color
.set_lerp(ls1
.get_color(), ls2
.get_color(), ratio
);
185 if ( ls1
._scaleVertically
!= ls2
._scaleVertically
)
187 LOG_ONCE( log_error("UNTESTED: Dunno how to interpolate line styles with different vertical thickness scaling") );
189 if ( ls1
._scaleHorizontally
!= ls2
._scaleHorizontally
)
191 LOG_ONCE( log_error("UNTESTED: Dunno how to interpolate line styles with different horizontal thickness scaling") );