Make automated FSCommand invocation tests show player-side output.
[gnash.git] / libcore / LineStyle.cpp
blobeecbe3675cb6e1f325291259891a417c60dee658
1 // LineStyle.cpp Line style types.
2 //
3 // Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
4 // Free Software Foundation, Inc
5 //
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.
10 //
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.
15 //
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"
27 #include "log.h"
28 #include "SWFStream.h"
29 #include "movie_definition.h"
30 #include "SWF.h"
31 #include "GnashException.h"
32 #include "FillStyle.h"
33 #include "GnashNumeric.h"
35 namespace gnash {
37 namespace {
39 class GetColor : public boost::static_visitor<rgba>
41 public:
42 rgba operator()(const SolidFill& f) const {
43 return f.color();
45 rgba operator()(const GradientFill&) const {
46 return rgba();
48 rgba operator()(const BitmapFill&) const {
49 return rgba();
55 LineStyle::LineStyle()
57 m_width(0),
58 m_color(),
59 _scaleVertically(true),
60 _scaleHorizontally(true),
61 _pixelHinting(false),
62 _noClose(false),
63 _startCapStyle(CAP_ROUND),
64 _endCapStyle(CAP_ROUND),
65 _joinStyle(JOIN_ROUND),
66 _miterLimitFactor(1.0f)
70 void
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);
81 return;
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)
105 in.ensureBytes(2);
106 _miterLimitFactor = in.read_short_ufixed();
108 if (has_fill) {
109 OptionalFillPair fp = readFills(in, t, md, true);
111 // TODO: store a fill style properly, removing the need for the
112 // visitor.
113 m_color = boost::apply_visitor(GetColor(), fp.first.fill);
114 pOther->m_color = boost::apply_visitor(GetColor(), fp.second->fill);
116 else {
117 m_color = readRGBA(in);
118 pOther->m_color = readRGBA(in);
122 void
123 LineStyle::read(SWFStream& in, SWF::TagType t, movie_definition& md,
124 const RunResources& /*r*/)
126 switch (t) {
128 default:
129 in.ensureBytes(2);
130 m_width = in.read_u16();
131 m_color = readRGBA(in);
132 return;
134 case SWF::DEFINESHAPE:
135 case SWF::DEFINESHAPE2:
136 in.ensureBytes(2);
137 m_width = in.read_u16();
138 m_color = readRGB(in);
139 return;
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.
146 in.ensureBytes(2+2);
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) {
162 in.ensureBytes(2);
163 _miterLimitFactor = in.read_short_ufixed();
165 if (has_fill) {
166 // TODO: store a fill style properly, removing the need for the
167 // visitor.
168 OptionalFillPair fp = readFills(in, t, md, false);
169 m_color = boost::apply_visitor(GetColor(), fp.first.fill);
171 else {
172 m_color = readRGBA(in);
178 void
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")));
196 } // namespace gnash
199 // Local Variables:
200 // mode: C++
201 // End: