diff options
author | Eugene Sandulenko | 2010-09-03 23:02:00 +0000 |
---|---|---|
committer | Eugene Sandulenko | 2010-10-12 23:34:25 +0000 |
commit | 7032c209a7e8bbd77bc7638f1a173a992bdb5e81 (patch) | |
tree | 7657c701d1edd8e218f233546f8ed4cac950e079 /engines/sword25/gfx/image/vectorimagerenderer.cpp | |
parent | 5f83fd19540c3072f50edff0acddf1cb6a072b78 (diff) | |
download | scummvm-rg350-7032c209a7e8bbd77bc7638f1a173a992bdb5e81.tar.gz scummvm-rg350-7032c209a7e8bbd77bc7638f1a173a992bdb5e81.tar.bz2 scummvm-rg350-7032c209a7e8bbd77bc7638f1a173a992bdb5e81.zip |
SWORD25: Initial code for vector image rendering. Crashes badly.
svn-id: r53314
Diffstat (limited to 'engines/sword25/gfx/image/vectorimagerenderer.cpp')
-rw-r--r-- | engines/sword25/gfx/image/vectorimagerenderer.cpp | 392 |
1 files changed, 246 insertions, 146 deletions
diff --git a/engines/sword25/gfx/image/vectorimagerenderer.cpp b/engines/sword25/gfx/image/vectorimagerenderer.cpp index de34302908..5031123b3c 100644 --- a/engines/sword25/gfx/image/vectorimagerenderer.cpp +++ b/engines/sword25/gfx/image/vectorimagerenderer.cpp @@ -32,182 +32,282 @@ * */ -// ----------------------------------------------------------------------------- -// Includes -// ----------------------------------------------------------------------------- +#include <libart_lgpl/art_vpath_bpath.h> +#include <libart_lgpl/art_svp_vpath.h> +#include <libart_lgpl/art_svp_vpath_stroke.h> +#include <libart_lgpl/art_svp_render_aa.h> +#include <libart_lgpl/art_rgb_svp.h> +#include <libart_lgpl/art_rgb.h> -#include "sword25/gfx/image/vectorimagerenderer.h" #include "sword25/gfx/image/vectorimage.h" -#if 0 // TODO -#include "agg_conv_curve.h" -#include "agg_path_storage.h" -#include "agg_conv_stroke.h" -#endif - namespace Sword25 { -#if 0 // TODO -// ----------------------------------------------------------------------------- -// 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 +art_rgb_fill_run1(art_u8 *buf, art_u8 r, art_u8 g, art_u8 b, int n) { + int i; + + if (r == g && g == b && r == 255) { + memset(buf, g, n + n + n + n); + } else { + art_u32 *alt = (art_u32 *)buf; + //art_u32 color = (r << 24) | (g << 16) | (b << 8) | 0xff; + art_u32 color = (r << 0) | (g << 8) | (b << 16) | (0xff << 24); + for (i = 0; i < n; i++) + *alt++ = color; } +} - void rewind(unsigned path_id) { - m_Trans.rewind(path_id); +void +art_rgb_run_alpha1(art_u8 *buf, art_u8 r, art_u8 g, art_u8 b, int alpha, int n) { + int i; + int v; + + for (i = 0; i < n; i++) { + v = *buf; + *buf++ = v + (((r - v) * alpha + 0x80) >> 8); + v = *buf; + *buf++ = v + (((g - v) * alpha + 0x80) >> 8); + v = *buf; + *buf++ = v + (((b - v) * alpha + 0x80) >> 8); + v = *buf; + *buf++ = v + (((alpha - v) * alpha + 0x80) >> 8); } +} - unsigned vertex(double *x, double *y) { - return m_Trans.vertex(x, y); - } +typedef struct _ArtRgbSVPAlphaData ArtRgbSVPAlphaData; -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; +struct _ArtRgbSVPAlphaData { + int alphatab[256]; + art_u8 r, g, b, alpha; + art_u8 *buf; + int rowstride; + int x0, x1; }; +static void +art_rgb_svp_alpha_callback1(void *callback_data, int y, + int start, ArtSVPRenderAAStep *steps, int n_steps) { + ArtRgbSVPAlphaData *data = (ArtRgbSVPAlphaData *)callback_data; + art_u8 *linebuf; + int run_x0, run_x1; + art_u32 running_sum = start; + int x0, x1; + int k; + art_u8 r, g, b; + int *alphatab; + int alpha; + + linebuf = data->buf; + x0 = data->x0; + x1 = data->x1; + + r = data->r; + g = data->g; + b = data->b; + alphatab = data->alphatab; + + if (n_steps > 0) { + run_x1 = steps[0].x; + if (run_x1 > x0) { + alpha = (running_sum >> 16) & 0xff; + if (alpha) + art_rgb_run_alpha1(linebuf, r, g, b, alphatab[alpha], run_x1 - x0); + } -// ----------------------------------------------------------------------------- -// StyleHandler -// ----------------------------------------------------------------------------- + for (k = 0; k < n_steps - 1; k++) { + running_sum += steps[k].delta; + run_x0 = run_x1; + run_x1 = steps[k + 1].x; + if (run_x1 > run_x0) { + alpha = (running_sum >> 16) & 0xff; + if (alpha) + art_rgb_run_alpha1(linebuf + (run_x0 - x0) * 4, r, g, b, alphatab[alpha], run_x1 - run_x0); + } + } + running_sum += steps[k].delta; + if (x1 > run_x1) { + alpha = (running_sum >> 16) & 0xff; + if (alpha) + art_rgb_run_alpha1(linebuf + (run_x1 - x0) * 4, r, g, b, alphatab[alpha], x1 - run_x1); + } + } else { + alpha = (running_sum >> 16) & 0xff; + if (alpha) + art_rgb_run_alpha1(linebuf, r, g, b, alphatab[alpha], x1 - x0); + } -class StyleHandler { -public: - StyleHandler(const BS_VectorImageElement &VectorImageElement) : m_ImageElement(VectorImageElement) {} + data->buf += data->rowstride; +} - bool is_solid(uint style) const { - return true; - } +static void +art_rgb_svp_alpha_opaque_callback1(void *callback_data, int y, + int start, + ArtSVPRenderAAStep *steps, int n_steps) { + ArtRgbSVPAlphaData *data = (ArtRgbSVPAlphaData *)callback_data; + art_u8 *linebuf; + int run_x0, run_x1; + art_u32 running_sum = start; + int x0, x1; + int k; + art_u8 r, g, b; + int *alphatab; + int alpha; + + linebuf = data->buf; + x0 = data->x0; + x1 = data->x1; + + r = data->r; + g = data->g; + b = data->b; + alphatab = data->alphatab; + + if (n_steps > 0) { + run_x1 = steps[0].x; + if (run_x1 > x0) { + alpha = running_sum >> 16; + if (alpha) { + if (alpha >= 255) + art_rgb_fill_run1(linebuf, r, g, b, run_x1 - x0); + else + art_rgb_run_alpha1(linebuf, r, g, b, alphatab[alpha], run_x1 - x0); + } + } - const agg::rgba8 &color(unsigned style) const { - return m_ImageElement.GetFillStyleColor(style); + for (k = 0; k < n_steps - 1; k++) { + running_sum += steps[k].delta; + run_x0 = run_x1; + run_x1 = steps[k + 1].x; + if (run_x1 > run_x0) { + alpha = running_sum >> 16; + if (alpha) { + if (alpha >= 255) + art_rgb_fill_run1(linebuf + (run_x0 - x0) * 4, r, g, b, run_x1 - run_x0); + else + art_rgb_run_alpha1(linebuf + (run_x0 - x0) * 4, r, g, b, alphatab[alpha], run_x1 - run_x0); + } + } + } + running_sum += steps[k].delta; + if (x1 > run_x1) { + alpha = running_sum >> 16; + if (alpha) { + if (alpha >= 255) + art_rgb_fill_run1(linebuf + (run_x1 - x0) * 4, r, g, b, x1 - run_x1); + else + art_rgb_run_alpha1(linebuf + (run_x1 - x0) * 4, r, g, b, alphatab[alpha], x1 - run_x1); + } + } + } else { + alpha = running_sum >> 16; + if (alpha) { + if (alpha >= 255) + art_rgb_fill_run1(linebuf, r, g, b, x1 - x0); + else + art_rgb_run_alpha1(linebuf, r, g, b, alphatab[alpha], x1 - x0); + } } - void generate_span(agg::rgba8 *span, int x, int y, unsigned len, unsigned style) { - // Wird nicht benutzt - return; + data->buf += data->rowstride; +} + +void +art_rgb_svp_alpha1(const ArtSVP *svp, + int x0, int y0, int x1, int y1, + art_u32 rgba, + art_u8 *buf, int rowstride, + ArtAlphaGamma *alphagamma) { + ArtRgbSVPAlphaData data; + int r, g, b, alpha; + int i; + int a, da; + + r = rgba >> 24; + g = (rgba >> 16) & 0xff; + b = (rgba >> 8) & 0xff; + alpha = rgba & 0xff; + + data.r = r; + data.g = g; + data.b = b; + data.alpha = alpha; + + a = 0x8000; + da = (alpha * 66051 + 0x80) >> 8; /* 66051 equals 2 ^ 32 / (255 * 255) */ + + for (i = 0; i < 256; i++) { + data.alphatab[i] = a >> 16; + a += da; } -private: - const BS_VectorImageElement &m_ImageElement; -}; + data.buf = buf; + data.rowstride = rowstride; + data.x0 = x0; + data.x1 = x1; + if (alpha == 255) + art_svp_render_aa(svp, x0, y0, x1, y1, art_rgb_svp_alpha_opaque_callback1, &data); + else + art_svp_render_aa(svp, x0, y0, x1, y1, art_rgb_svp_alpha_callback1, &data); +} -BS_VectorImageRenderer::BS_VectorImageRenderer() : - PixelFormat(rbuf) { +void VectorImage::render(float scaleFactorX, float scaleFactorY, uint &width, uint &height) { + width = static_cast<uint>(getWidth() * scaleFactorX); + height = static_cast<uint>(getHeight() * scaleFactorY); -} + if (_pixelData) + free(_pixelData); + _pixelData = (byte *)malloc(width * height * 4); + memset(_pixelData, 0, width * height * 4); -bool BS_VectorImageRenderer::Render(const BS_VectorImage &VectorImage, - float ScaleFactorX, float ScaleFactorY, - uint &Width, uint &Height, - byte *ImageData, - float LineScaleFactor, - bool NoAlphaShapes) { - Width = static_cast<uint>(VectorImage.GetWidth() * ScaleFactorX); - Height = static_cast<uint>(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 (uint 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 (uint i = 0; i < CurImageElement.GetPathCount(); ++i) { - uint FillStyle0 = CurImageElement.GetPathInfo(i).GetFillStyle0(); - uint 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; - } + for (int j = _elements.size() - 1; j >= 0; j--) + for (int i = _elements[j].getPathCount() - 1; i >= 0; i--) { + if (!_elements[j].getPathInfo(i).getVec()) + continue; - 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 (uint i = 0; i < CurImageElement.GetPathCount(); ++i) { - Rasterizer.reset(); - - uint 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); + bool needfree = false; + ArtVpath *vec = _elements[j].getPathInfo(i).getVec(); + + // Upscale vector + if (scaleFactorX != 1.0 || scaleFactorY != 1.0) { + ArtVpath *vec1; + int size; + + for (size = 0; vec[size].code != ART_END; size++); + + vec1 = art_new(ArtVpath, size + 1); + + int k; + for (k = 0; k < size; k++) { + vec1[k].code = vec[k].code; + vec1[k].x = vec[k].x * scaleFactorX; + vec1[k].y = vec[k].y * scaleFactorY; + } + + vec1[k].code = ART_END; + + vec = vec1; + needfree = true; } - } - } - return true; -} + ArtSVP *svp1 = art_svp_from_vpath(vec); + + int penWidth = _elements[j].getLineStyleWidth(_elements[j].getPathInfo(i).getLineStyle()); + ArtSVP *svp2 = art_svp_vpath_stroke(vec, ART_PATH_STROKE_JOIN_ROUND, ART_PATH_STROKE_CAP_ROUND, penWidth, 1.0, 0.5); + if (needfree) + art_free(vec); -#else + int color1 = _elements[j].getFillStyleColor(_elements[j].getPathInfo(i).getFillStyle0()); + int color2 = _elements[j].getLineStyleColor(_elements[j].getPathInfo(i).getLineStyle()); -VectorImageRenderer::VectorImageRenderer() {} + art_rgb_svp_alpha1(svp1, 0, 0, width, height, color1, _pixelData, width * 4, NULL); + art_rgb_svp_alpha1(svp2, 0, 0, width, height, color2, _pixelData, width * 4, NULL); -bool VectorImageRenderer::Render(const VectorImage &VectorImage, - float ScaleFactorX, float ScaleFactorY, - uint &Width, uint &Height, - byte *ImageData, - float LineScaleFactor, - bool NoAlphaShapes) { - return true; + art_free(svp2); + art_free(svp1); + } } -#endif + } // End of namespace Sword25 |