diff options
Diffstat (limited to 'engines/sword25/gfx/image/vectorimagerenderer.cpp')
-rwxr-xr-x | engines/sword25/gfx/image/vectorimagerenderer.cpp | 198 |
1 files changed, 198 insertions, 0 deletions
diff --git a/engines/sword25/gfx/image/vectorimagerenderer.cpp b/engines/sword25/gfx/image/vectorimagerenderer.cpp new file mode 100755 index 0000000000..76f2330a65 --- /dev/null +++ b/engines/sword25/gfx/image/vectorimagerenderer.cpp @@ -0,0 +1,198 @@ +// ----------------------------------------------------------------------------- +// This file is part of Broken Sword 2.5 +// Copyright (c) Malte Thiesen, Daniel Queteschiner and Michael Elsdörfer +// +// Broken Sword 2.5 is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// Broken Sword 2.5 is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Broken Sword 2.5; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// ----------------------------------------------------------------------------- + +// ----------------------------------------------------------------------------- +// Includes +// ----------------------------------------------------------------------------- + +#include "vectorimagerenderer.h" +#include "vectorimage.h" +#include "agg_conv_curve.h" +#include "agg_path_storage.h" +#include "agg_conv_stroke.h" + + +// ----------------------------------------------------------------------------- +// CompoundShape +// ----------------------------------------------------------------------------- + +class CompoundShape +{ +public: + CompoundShape(const BS_VectorImageElement & VectorImageElement) : + m_ImageElement(VectorImageElement), + m_Path(VectorImageElement.GetPaths()), + m_Affine(), + m_Curve(m_Path), + m_Trans(m_Curve, m_Affine) + {} + + unsigned operator [] (unsigned i) const + { + return m_ImageElement.GetPathInfo(i).GetID(); + } + + unsigned paths() const { return m_ImageElement.GetPathCount(); } + + void rewind(unsigned path_id) + { + m_Trans.rewind(path_id); + } + + unsigned vertex(double* x, double* y) + { + return m_Trans.vertex(x, y); + } + +private: + const BS_VectorImageElement & m_ImageElement; + agg::path_storage m_Path; + agg::trans_affine m_Affine; + agg::conv_curve<agg::path_storage> m_Curve; + agg::conv_transform< agg::conv_curve<agg::path_storage> > m_Trans; +}; + + +// ----------------------------------------------------------------------------- +// StyleHandler +// ----------------------------------------------------------------------------- + +class StyleHandler +{ +public: + StyleHandler(const BS_VectorImageElement & VectorImageElement) : m_ImageElement(VectorImageElement) {} + + bool is_solid(unsigned int style) const + { + return true; + } + + const agg::rgba8 & color(unsigned style) const + { + return m_ImageElement.GetFillStyleColor(style); + } + + void generate_span(agg::rgba8 * span, int x, int y, unsigned len, unsigned style) + { + // Wird nicht benutzt + return; + } + +private: + const BS_VectorImageElement & m_ImageElement; +}; + + +// ----------------------------------------------------------------------------- +// Konstruktion +// ----------------------------------------------------------------------------- + +BS_VectorImageRenderer::BS_VectorImageRenderer() : + PixelFormat(rbuf) +{ + +} + + +// ----------------------------------------------------------------------------- + +bool BS_VectorImageRenderer::Render(const BS_VectorImage & VectorImage, + float ScaleFactorX, float ScaleFactorY, + unsigned int & Width, unsigned int & Height, + std::vector<char> & ImageData, + float LineScaleFactor, + bool NoAlphaShapes) +{ + Width = static_cast<unsigned int>(VectorImage.GetWidth() * ScaleFactorX); + Height = static_cast<unsigned int>(VectorImage.GetHeight() * ScaleFactorY); + + ImageData.resize(Width * Height * 4); + memset(&ImageData[0], 0, ImageData.size()); + rbuf.attach(reinterpret_cast<agg::int8u *>(&ImageData[0]), Width, Height, Width * 4); + + BaseRenderer.attach(PixelFormat); + ScanlineRenderer.attach(BaseRenderer); + + // Die SWF-Shapes sind häufig nicht am Ursprung (0, 0) ausgerichtet, daher wird die Shape vor dem Rendern derart verschoben, dass + // sich die linke obere Ecke der Bounding-Box im Ursprung befindet. Danach wird die Skalierung angewandt. + Scale = agg::trans_affine_translation(- VectorImage.GetBoundingBox().left, - VectorImage.GetBoundingBox().top); + Scale *= agg::trans_affine_scaling(ScaleFactorX, ScaleFactorY); + + for (unsigned int element = 0; element < VectorImage.GetElementCount(); ++element) + { + const BS_VectorImageElement & CurImageElement = VectorImage.GetElement(element); + + CompoundShape ImageCompoundShape(CurImageElement); + StyleHandler ImageStyleHandler(CurImageElement); + agg::conv_transform<CompoundShape> Shape(ImageCompoundShape, Scale); + agg::conv_stroke<agg::conv_transform<CompoundShape> > Stroke(Shape); + + // Fill shape + //---------------------- + CompoundRasterizer.clip_box(0, 0, Width, Height); + CompoundRasterizer.reset(); + for(unsigned int i = 0; i < CurImageElement.GetPathCount(); ++i) + { + unsigned int FillStyle0 = CurImageElement.GetPathInfo(i).GetFillStyle0(); + unsigned int FillStyle1 = CurImageElement.GetPathInfo(i).GetFillStyle1(); + + if (NoAlphaShapes) + { + if (FillStyle0 != 0 && CurImageElement.GetFillStyleColor(FillStyle0 - 1).a != 255) FillStyle0 = 0; + if (FillStyle1 != 0 && CurImageElement.GetFillStyleColor(FillStyle1 - 1).a != 255) FillStyle1 = 0; + } + + if(FillStyle0 != 0 || FillStyle1 != 0) + { + CompoundRasterizer.styles(FillStyle0 - 1, FillStyle1 - 1); + CompoundRasterizer.add_path(Shape, CurImageElement.GetPathInfo(i).GetID()); + } + } + agg::render_scanlines_compound_layered(CompoundRasterizer, Scanline, BaseRenderer, Alloc, ImageStyleHandler); + + + // Draw strokes + //---------------------- + Rasterizer.clip_box(0, 0, Width, Height); + Stroke.line_join(agg::round_join); + Stroke.line_cap(agg::round_cap); + for(unsigned int i = 0; i < CurImageElement.GetPathCount(); ++i) + { + Rasterizer.reset(); + + unsigned int CurrentLineStyle = CurImageElement.GetPathInfo(i).GetLineStyle(); + if (CurrentLineStyle != 0) + { + Stroke.width(ScaleFactorX * CurImageElement.GetLineStyleWidth(CurrentLineStyle - 1) * LineScaleFactor); + Rasterizer.add_path(Stroke, CurImageElement.GetPathInfo(i).GetID()); + ScanlineRenderer.color(CurImageElement.GetLineStyleColor(CurrentLineStyle - 1)); + // HACK + // Die SWF-Frames enthalten zum Teil Reste von grünen Linien, die wohl von Bernd als Umriss benutzt wurden. + // Damit diese Reste nicht störend auffallen werden grüne Linien schlichtweg ignoriert. + if (!(CurImageElement.GetLineStyleColor(CurrentLineStyle - 1).a == 255 && + CurImageElement.GetLineStyleColor(CurrentLineStyle - 1).r == 0 && + CurImageElement.GetLineStyleColor(CurrentLineStyle - 1).g == 255 && + CurImageElement.GetLineStyleColor(CurrentLineStyle - 1).b == 0)) + agg::render_scanlines(Rasterizer, Scanline, ScanlineRenderer); + } + } + } + + return true; +} |