From e844de5141a03692e74c892a35e55f1c9697719a Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Sat, 4 Sep 2010 22:29:36 +0000 Subject: SWORD25: Started rewriting vector renderer into proper one Previous attempt was all wrong, as it completely incorrectly interpreted SWF shape data. svn-id: r53319 --- engines/sword25/gfx/image/vectorimage.cpp | 11 +- engines/sword25/gfx/image/vectorimage.h | 15 +- engines/sword25/gfx/image/vectorimagerenderer.cpp | 172 ++++++++++++++++------ engines/sword25/gfx/opengl/glimage.cpp | 2 +- 4 files changed, 149 insertions(+), 51 deletions(-) (limited to 'engines/sword25') diff --git a/engines/sword25/gfx/image/vectorimage.cpp b/engines/sword25/gfx/image/vectorimage.cpp index 4cb77692fe..6c79c3043a 100644 --- a/engines/sword25/gfx/image/vectorimage.cpp +++ b/engines/sword25/gfx/image/vectorimage.cpp @@ -194,7 +194,8 @@ Common::Rect CalculateBoundingBox(const VectorImageElement &vectorImageElement) double x0, y0, x1, y1; for (int j = vectorImageElement.getPathCount() - 1; j >= 0; j--) { - ArtVpath *vec = vectorImageElement.getPathInfo(j).getVec(); + ArtBpath *bez = vectorImageElement.getPathInfo(j).getVec(); + ArtVpath *vec = art_bez_path_to_vec(bez, 0.5); if (vec[0].code == ART_END) { continue; @@ -208,6 +209,7 @@ Common::Rect CalculateBoundingBox(const VectorImageElement &vectorImageElement) if (vec[i].y > y1) y1 = vec[i].y; } } + art_free(vec); } return Common::Rect(static_cast(x0), static_cast(y0), static_cast(x1) + 1, static_cast(y1) + 1); @@ -324,9 +326,12 @@ ArtBpath *VectorImage::storeBez(ArtBpath *bez, int lineStyle, int fillStyle0, in bez = ensureBezStorage(bez, *bezNodes, bezAllocated); bez[*bezNodes].code = ART_END; - ArtVpath *vec = art_bez_path_to_vec(bez, BEZSMOOTHNESS); + ArtBpath *bez1 = art_new(ArtBpath, *bezNodes + 1); - _elements.back()._pathInfos.push_back(VectorPathInfo(vec, lineStyle, fillStyle0, fillStyle1)); + for (int i = 0; i <= *bezNodes; i++) + bez1[i] = bez[i]; + + _elements.back()._pathInfos.push_back(VectorPathInfo(bez1, *bezNodes, lineStyle, fillStyle0, fillStyle1)); return bez; } diff --git a/engines/sword25/gfx/image/vectorimage.h b/engines/sword25/gfx/image/vectorimage.h index ea9948fec7..ac53f031c5 100644 --- a/engines/sword25/gfx/image/vectorimage.h +++ b/engines/sword25/gfx/image/vectorimage.h @@ -60,17 +60,20 @@ class VectorImage; class VectorPathInfo { public: - VectorPathInfo(ArtVpath *vec, uint lineStyle, uint fillStyle0, uint fillStyle1) : - _vec(vec), _lineStyle(lineStyle), _fillStyle0(fillStyle0), _fillStyle1(fillStyle1) {} + VectorPathInfo(ArtBpath *vec, int len, uint lineStyle, uint fillStyle0, uint fillStyle1) : + _vec(vec), _lineStyle(lineStyle), _fillStyle0(fillStyle0), _fillStyle1(fillStyle1), _len(len) {} VectorPathInfo() { - _lineStyle = _fillStyle0 = _fillStyle1 = 0; + _lineStyle = _fillStyle0 = _fillStyle1 = _len = 0; _vec = 0; } - ArtVpath *getVec() const { + ArtBpath *getVec() const { return _vec; } + int getVecLen() const { + return _len; + } uint getLineStyle() const { return _lineStyle; } @@ -82,13 +85,13 @@ public: } private: - ArtVpath *_vec; + ArtBpath *_vec; uint _lineStyle; uint _fillStyle0; uint _fillStyle1; + uint _len; }; - /** @brief Ein Element eines Vektorbild. Ein BS_VectorImage besteht aus diesen Elementen, die jeweils einen Teil der Graphik definieren. Werden alle Elemente eines Vektorbildes übereinandergelegt, ergibt sich das komplette Bild. diff --git a/engines/sword25/gfx/image/vectorimagerenderer.cpp b/engines/sword25/gfx/image/vectorimagerenderer.cpp index e047935c15..2549f8c5d1 100644 --- a/engines/sword25/gfx/image/vectorimagerenderer.cpp +++ b/engines/sword25/gfx/image/vectorimagerenderer.cpp @@ -32,6 +32,7 @@ * */ +#include #include #include #include @@ -64,13 +65,13 @@ void art_rgb_run_alpha1(art_u8 *buf, art_u8 r, art_u8 g, art_u8 b, int alpha, in for (i = 0; i < n; i++) { v = *buf; - *buf++ = v + (((alpha - v) * alpha + 0x80) >> 8); - v = *buf; - *buf++ = v + (((r - v) * alpha + 0x80) >> 8); + *buf++ = v + (((b - v) * alpha + 0x80) >> 8); v = *buf; *buf++ = v + (((g - v) * alpha + 0x80) >> 8); v = *buf; - *buf++ = v + (((b - v) * alpha + 0x80) >> 8); + *buf++ = v + (((r - v) * alpha + 0x80) >> 8); + v = *buf; + *buf++ = v + (((alpha - v) * alpha + 0x80) >> 8); } } @@ -244,9 +245,63 @@ void art_rgb_svp_alpha1(const ArtSVP *svp, art_svp_render_aa(svp, x0, y0, x1, y1, art_rgb_svp_alpha_callback1, &data); } +void drawBez(ArtBpath *bez, art_u8 *buffer, int width, int height, double scaleX, double scaleY, double penWidth, unsigned int color) { + ArtVpath *vec = NULL; + ArtSVP *svp = NULL; + +#if 0 + const char *codes[] = {"ART_MOVETO", "ART_MOVETO_OPEN", "ART_CURVETO", "ART_LINETO", "ART_END"}; + for (int i = 0;; i++) { + printf(" bez[%d].code = %s;\n", i, codes[bez[i].code]); + if (bez[i].code == ART_END) + break; + if (bez[i].code == ART_CURVETO) { + printf(" bez[%d].x1 = %f; bez[%d].y1 = %f;\n", i, bez[i].x1, i, bez[i].y1); + printf(" bez[%d].x2 = %f; bez[%d].y2 = %f;\n", i, bez[i].x2, i, bez[i].y2); + } + printf(" bez[%d].x3 = %f; bez[%d].y3 = %f;\n", i, bez[i].x3, i, bez[i].y3); + } + + printf(" drawBez(bez, buffer, 1.0, 1.0, %f, 0x%08x);\n", penWidth, color); +#endif + + vec = art_bez_path_to_vec(bez, 0.5); + + if (scaleX != 1.0 || scaleY != 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 * scaleX; + vec1[k].y = vec[k].y * scaleY; + } + vec1[k].code = ART_END; + art_free(vec); + + vec = vec1; + } + + if (penWidth != -1) { + svp = art_svp_vpath_stroke(vec, ART_PATH_STROKE_JOIN_ROUND, ART_PATH_STROKE_CAP_ROUND, penWidth, 1.0, 0.5); + } else { + svp = art_svp_from_vpath(vec); + } + + art_rgb_svp_alpha1(svp, 0, 0, width, height, color, buffer, width * 4, NULL); + + art_free(svp); + art_free(vec); +} + void VectorImage::render(int width, int height) { - float scaleFactorX = (width == - 1) ? 1 : static_cast(width) / static_cast(getWidth()); - float scaleFactorY = (height == - 1) ? 1 : static_cast(height) / static_cast(getHeight()); + double scaleX = (width == - 1) ? 1 : static_cast(width) / static_cast(getWidth()); + double scaleY = (height == - 1) ? 1 : static_cast(height) / static_cast(getHeight()); if (_pixelData) free(_pixelData); @@ -254,60 +309,95 @@ void VectorImage::render(int width, int height) { _pixelData = (byte *)malloc(width * height * 4); memset(_pixelData, 0, width * height * 4); - 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; + for (uint e = 0; e < _elements.size(); e++) { - bool needfree = false; - ArtVpath *vec = _elements[j].getPathInfo(i).getVec(); + //// Draw shapes + for (uint s = 0; s < _elements[e].getFillStyleCount(); s++) { + int fill0len = 0; + int fill1len = 0; - // Upscale vector - if (scaleFactorX != 1.0 || scaleFactorY != 1.0) { - ArtVpath *vec1; - int size; + // Count vector sizes in order to minimize memory + // fragmentation + for (uint p = 0; p < _elements[e].getPathCount(); p++) { + if (_elements[e].getPathInfo(p).getFillStyle0() == s + 1) + fill1len += _elements[e].getPathInfo(p).getVecLen(); - for (size = 0; vec[size].code != ART_END; size++); + if (_elements[e].getPathInfo(p).getFillStyle1() == s + 1) + fill0len += _elements[e].getPathInfo(p).getVecLen(); + } - vec1 = art_new(ArtVpath, size + 1); + // Now lump together vectors + ArtBpath *fill1 = art_new(ArtBpath, fill1len + 1); + ArtBpath *fill0 = art_new(ArtBpath, fill0len + 1); + ArtBpath *fill1pos = fill1; + ArtBpath *fill0pos = fill0; + + for (uint p = 0; p < _elements[e].getPathCount(); p++) { + // Normal order + if (_elements[e].getPathInfo(p).getFillStyle0() == s + 1) { + for (int i = 0; i < _elements[e].getPathInfo(p).getVecLen(); i++) + *fill1pos++ = _elements[e].getPathInfo(p).getVec()[i]; + } - 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; + // Reverse order + if (_elements[e].getPathInfo(p).getFillStyle1() == s + 1) { + for (int i = _elements[e].getPathInfo(p).getVecLen() - 1; i >= 0; i--) + *fill0pos++ = _elements[e].getPathInfo(p).getVec()[i]; } + } - vec1[k].code = ART_END; + // Close vectors + (*fill1pos).code = ART_END; + (*fill0pos).code = ART_END; - vec = vec1; - needfree = true; - } + if (fill1len) + drawBez(fill1, _pixelData, width, height, scaleX, scaleY, -1, _elements[e].getFillStyleColor(s)); - ArtSVP *svp1 = art_svp_from_vpath(vec); + if (fill0len) + drawBez(fill0, _pixelData, width, height, scaleX, scaleY, -1, _elements[e].getFillStyleColor(s)); + art_free(fill0); + art_free(fill1); + } - if (_elements[j].getPathInfo(i).getFillStyle0()) { - int color1 = _elements[j].getFillStyleColor(_elements[j].getPathInfo(i).getFillStyle0() - 1); - art_rgb_svp_alpha1(svp1, 0, 0, width, height, color1, _pixelData, width * 4, NULL); - art_free(svp1); + //// Draw strokes + for (uint s = 0; s < _elements[e].getLineStyleCount(); s++) { + int strokelen = 0; + + // Count vector sizes in order to minimize memory + // fragmentation + for (uint p = 0; p < _elements[e].getPathCount(); p++) { + if (_elements[e].getPathInfo(p).getLineStyle() == s + 1) + strokelen += _elements[e].getPathInfo(p).getVecLen(); } - if (_elements[j].getPathInfo(i).getLineStyle()) { - double penWidth = _elements[j].getLineStyleWidth(_elements[j].getPathInfo(i).getLineStyle() - 1); - penWidth = sqrt(fabs(scaleFactorX * scaleFactorY)); - ArtSVP *svp2 = art_svp_vpath_stroke(vec, ART_PATH_STROKE_JOIN_ROUND, ART_PATH_STROKE_CAP_ROUND, penWidth, 1.0, 0.5); - int color2 = _elements[j].getLineStyleColor(_elements[j].getPathInfo(i).getLineStyle() - 1); + if (strokelen == 0) + continue; - art_rgb_svp_alpha1(svp2, 0, 0, width, height, color2, _pixelData, width * 4, NULL); + // Now lump together vectors + ArtBpath *stroke = art_new(ArtBpath, strokelen + 1); + ArtBpath *strokepos = stroke; - art_free(svp2); + for (uint p = 0; p < _elements[e].getPathCount(); p++) { + // Normal order + if (_elements[e].getPathInfo(p).getLineStyle() == s + 1) { + for (int i = 0; i < _elements[e].getPathInfo(p).getVecLen(); i++) + *strokepos++ = _elements[e].getPathInfo(p).getVec()[i]; + } } - if (needfree) - art_free(vec); + // Close vector + (*strokepos).code = ART_END; + + double penWidth = _elements[e].getLineStyleWidth(s); + penWidth *= sqrt(fabs(scaleX * scaleY)); + + drawBez(stroke, _pixelData, width, height, scaleX, scaleY, penWidth, _elements[e].getLineStyleColor(s)); + art_free(stroke); } + } + } diff --git a/engines/sword25/gfx/opengl/glimage.cpp b/engines/sword25/gfx/opengl/glimage.cpp index cf8b294ea7..839bc44506 100644 --- a/engines/sword25/gfx/opengl/glimage.cpp +++ b/engines/sword25/gfx/opengl/glimage.cpp @@ -176,7 +176,7 @@ bool GLImage::blit(int posX, int posY, int flipping, Common::Rect *pPartRect, ui h = pPartRect->bottom - pPartRect->top; } - debug(6, "Blit(%d, %d, %d, [%d, %d, %d, %d], %d, %d, %d)", posX, posY, flipping, x1, y1, w, h, color, width, height); + debug(6, "Blit(%d, %d, %d, [%d, %d, %d, %d], %08x, %d, %d)", posX, posY, flipping, x1, y1, w, h, color, width, height); // Skalierungen berechnen float scaleX, scaleY; -- cgit v1.2.3