1 // LineStyle.cpp Line style types.
3 // Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
4 // Free Software Foundation, Inc
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 "movie_definition.h"
31 #include "GnashException.h"
32 #include "FillStyle.h"
33 #include "GnashNumeric.h"
39 class GetColor
: public boost::static_visitor
<rgba
>
42 rgba
operator()(const SolidFill
& f
) const {
45 rgba
operator()(const GradientFill
&) const {
48 rgba
operator()(const BitmapFill
&) const {
55 LineStyle::LineStyle()
59 _scaleVertically(true),
60 _scaleHorizontally(true),
63 _startCapStyle(CAP_ROUND
),
64 _endCapStyle(CAP_ROUND
),
65 _joinStyle(JOIN_ROUND
),
66 _miterLimitFactor(1.0f
)
71 LineStyle::read_morph(SWFStream
& in
, SWF::TagType t
, movie_definition
& md
,
72 const RunResources
& /*r*/, LineStyle
*pOther
)
74 if (t
== SWF::DEFINEMORPHSHAPE
)
76 in
.ensureBytes(2 + 2);
77 m_width
= in
.read_u16();
78 pOther
->m_width
= in
.read_u16();
79 m_color
= readRGBA(in
);
80 pOther
->m_color
= readRGBA(in
);
84 assert(t
== SWF::DEFINEMORPHSHAPE2
|| t
== SWF::DEFINEMORPHSHAPE2_
);
86 // MorphShape 2 from here down.
87 in
.ensureBytes(4 + 2);
89 m_width
= in
.read_u16();
90 pOther
->m_width
= in
.read_u16();
92 int flags1
= in
.read_u8();
93 int flags2
= in
.read_u8();
94 _startCapStyle
= (CapStyle
)((flags1
& 0xC0) >> 6);
95 _joinStyle
= (JoinStyle
)((flags1
& 0x30) >> 4);
96 bool has_fill
= flags1
& (1 << 3);
97 _scaleHorizontally
= !(flags1
& (1 << 2));
98 _scaleVertically
= !(flags1
& (1 << 1));
99 _pixelHinting
= flags1
& (1 << 0);
100 _noClose
= flags2
& (1 << 2);
101 _endCapStyle
= (CapStyle
) (flags2
& 0x03);
103 if (_joinStyle
== JOIN_MITER
)
106 _miterLimitFactor
= in
.read_short_ufixed();
109 OptionalFillPair fp
= readFills(in
, t
, md
, true);
111 // TODO: store a fill style properly, removing the need for the
113 m_color
= boost::apply_visitor(GetColor(), fp
.first
.fill
);
114 pOther
->m_color
= boost::apply_visitor(GetColor(), fp
.second
->fill
);
117 m_color
= readRGBA(in
);
118 pOther
->m_color
= readRGBA(in
);
123 LineStyle::read(SWFStream
& in
, SWF::TagType t
, movie_definition
& md
,
124 const RunResources
& /*r*/)
130 m_width
= in
.read_u16();
131 m_color
= readRGBA(in
);
134 case SWF::DEFINESHAPE
:
135 case SWF::DEFINESHAPE2
:
137 m_width
= in
.read_u16();
138 m_color
= readRGB(in
);
141 case SWF::DEFINESHAPE4
:
142 case SWF::DEFINESHAPE4_
:
144 // TODO: Unfinished. Temporary to allow DefineShape4 to work in
145 // many cases, but does not work correctly in all cases.
147 m_width
= in
.read_u16();
149 const std::uint8_t flags1
= in
.read_u8();
150 const std::uint8_t flags2
= in
.read_u8();
152 _startCapStyle
= (CapStyle
)((flags1
& 0xC0) >> 6);
153 _joinStyle
= (JoinStyle
)((flags1
& 0x30) >> 4);
154 const bool has_fill
= flags1
& (1 << 3);
155 _scaleHorizontally
= !(flags1
& (1 << 2));
156 _scaleVertically
= !(flags1
& (1 << 1));
157 _pixelHinting
= flags1
& (1 << 0);
158 _noClose
= flags2
& (1 << 2);
159 _endCapStyle
= (CapStyle
) (flags2
& 0x03);
161 if (_joinStyle
== JOIN_MITER
) {
163 _miterLimitFactor
= in
.read_short_ufixed();
166 // TODO: store a fill style properly, removing the need for the
168 OptionalFillPair fp
= readFills(in
, t
, md
, false);
169 m_color
= boost::apply_visitor(GetColor(), fp
.first
.fill
);
172 m_color
= readRGBA(in
);
179 LineStyle::set_lerp(const LineStyle
& ls1
, const LineStyle
& ls2
, float ratio
)
181 m_width
= static_cast<std::uint16_t>(
182 frnd(lerp
<float>(ls1
.getThickness(), ls2
.getThickness(), ratio
)));
183 m_color
= lerp(ls1
.get_color(), ls2
.get_color(), ratio
);
184 if ( ls1
._scaleVertically
!= ls2
._scaleVertically
)
186 LOG_ONCE(log_error(_("UNTESTED: Do not know how to interpolate"
187 " line styles with different vertical thickness scaling")));
189 if ( ls1
._scaleHorizontally
!= ls2
._scaleHorizontally
)
191 LOG_ONCE(log_error(_("UNTESTED: Do not know how to interpolate"
192 " line styles with different horizontal thickness scaling")));