aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVicent Marti2008-05-01 23:50:14 +0000
committerVicent Marti2008-05-01 23:50:14 +0000
commite117038b62410392979f95cfc889c366b2723650 (patch)
tree562371e7790f8d606e2b56b1f6ba5d751aa67215
parent604ce476e46732b94e71f1963018cf285125d82c (diff)
downloadscummvm-rg350-e117038b62410392979f95cfc889c366b2723650.tar.gz
scummvm-rg350-e117038b62410392979f95cfc889c366b2723650.tar.bz2
scummvm-rg350-e117038b62410392979f95cfc889c366b2723650.zip
Implemented base API for the Vector Renderer.
Added line drawing. svn-id: r31799
-rw-r--r--dists/msvc9/scummvm.vcproj10
-rw-r--r--graphics/VectorRenderer.cpp201
-rw-r--r--graphics/VectorRenderer.h236
3 files changed, 446 insertions, 1 deletions
diff --git a/dists/msvc9/scummvm.vcproj b/dists/msvc9/scummvm.vcproj
index afeafc3dd3..889ea04b75 100644
--- a/dists/msvc9/scummvm.vcproj
+++ b/dists/msvc9/scummvm.vcproj
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
- Version="9,00"
+ Version="9.00"
Name="scummvm"
ProjectGUID="{8434CB15-D08F-427D-9E6D-581AE5B28440}"
RootNamespace="scummvm"
@@ -1300,6 +1300,14 @@
RelativePath="..\..\graphics\surface.h"
>
</File>
+ <File
+ RelativePath="..\..\graphics\VectorRenderer.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\graphics\VectorRenderer.h"
+ >
+ </File>
<Filter
Name="scaler"
>
diff --git a/graphics/VectorRenderer.cpp b/graphics/VectorRenderer.cpp
new file mode 100644
index 0000000000..3079d00666
--- /dev/null
+++ b/graphics/VectorRenderer.cpp
@@ -0,0 +1,201 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/util.h"
+#include "graphics/surface.h"
+#include "graphics/VectorRenderer.h"
+#include "graphics/colormasks.h"
+
+namespace Graphics {
+
+VectorRenderer *createRenderer()
+{
+ return new VectorRendererAA<uint16,ColorMasks<565>>;
+}
+
+template<typename PixelType, typename PixelFormat>
+void VectorRendererSpec<PixelType,PixelFormat>::
+drawLineAlg( int x1, int x2, int y1, int y2, int dx, int dy )
+{
+ PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x1, y1);
+ int pitch = surfacePitch();
+ int xdir = ( x2 > x1 ) ? 1 : -1;
+
+ *ptr = (PixelType)_color;
+
+ if ( dx > dy )
+ {
+ int ddy = dy * 2;
+ int dysub = ddy - ( dx * 2 );
+ int error_term = ddy - dx;
+
+ while ( dx-- ) {
+ if ( error_term >= 0 ) {
+ ptr += pitch;
+ error_term += dysub;
+ } else {
+ error_term += ddy;
+ }
+
+ ptr += xdir;
+ *ptr = (PixelType)_color;
+ }
+ }
+ else
+ {
+ int ddx = dx * 2;
+ int dxsub = ddx - ( dy * 2 );
+ int error_term = ddx - dy;
+
+ while ( dy-- ) {
+ if ( error_term >= 0 ) {
+ ptr += xdir;
+ error_term += dxsub;
+ } else {
+ error_term += ddx;
+ }
+
+ ptr += pitch;
+ *ptr = (PixelType)_color;
+ }
+ }
+
+ ptr = (PixelType *)_activeSurface->getBasePtr(x2, y2);
+ *ptr = (PixelType)_color;
+}
+
+template<typename PixelType, typename PixelFormat>
+void VectorRendererAA<PixelType,PixelFormat>::
+drawLineAlg( int x1, int x2, int y1, int y2, int dx, int dy )
+{
+ PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x1, y1);
+ int pitch = surfacePitch();
+ int xdir = ( x2 > x1 ) ? 1 : -1;
+
+ int error_line, error_tmp, weight;
+ int error_total = 0;
+ uint8 line_r, line_g, line_b;
+ uint8 bg_r, bg_g, bg_b;
+
+ colorToRGB<PixelFormat>( _color, line_r, line_g, line_b );
+
+ uint line_lum = (line_r >> 2) + (line_g >> 1) + (line_b >> 3);
+ uint bg_lum;
+
+ // first pixel, should be perfectly accurate so no fading out
+ *ptr = (PixelType)_color;
+
+#define __WULINE_PUTPIXEL( pixel_ptr ) \
+ { \
+ colorToRGB<PixelFormat>( (PixelType)*(pixel_ptr), bg_r, bg_g, bg_b ); \
+ bg_lum = (bg_r >> 2) + (bg_g >> 1) + (bg_b >> 3); \
+ weight = ( line_lum < bg_lum ) ? error_total >> 8 : (error_total >> 8)^0xFF; \
+ *(pixel_ptr) = RGBToColor<PixelFormat>( \
+ antialiasingBlendWeight( line_r, bg_r, weight ), \
+ antialiasingBlendWeight( line_g, bg_g, weight ), \
+ antialiasingBlendWeight( line_b, bg_b, weight ) ); \
+ }
+
+ // draw from top to bottom while fading out.
+ // optimized for mostly vertical lines
+ if ( dy > dx ) {
+ error_line = (dx << 16)/dy;
+ while ( --dy ) {
+ error_tmp = error_total;
+ error_total += error_line;
+
+ if ( error_total <= error_tmp )
+ ptr += xdir; // move right or left
+
+ ptr += pitch; // move down
+
+ __WULINE_PUTPIXEL( ptr );
+ __WULINE_PUTPIXEL( ptr+xdir );
+ }
+ } else { // optimized for mostly horizontal lines
+ error_line = (dy << 16)/dx;
+ while ( --dx ) {
+ error_tmp = error_total;
+ error_total += error_line;
+
+ if ( error_total <= error_tmp )
+ ptr += pitch; // move down
+
+ ptr += xdir; // move left or right
+
+ __WULINE_PUTPIXEL( ptr );
+ __WULINE_PUTPIXEL( ptr + pitch );
+ }
+ } // end of line direction cases
+
+ // last pixel, also perfectly accurate.
+ ptr = (PixelType *)_activeSurface->getBasePtr(x2, y2);
+ *ptr = (PixelType)_color;
+}
+
+template<typename PixelType, typename PixelFormat>
+void VectorRendererSpec<PixelType,PixelFormat>::
+drawLine( int x1, int x2, int y1, int y2 )
+{
+ // we draw from top to bottom
+ if ( y2 < y1 ) {
+ SWAP( x1, x2 );
+ SWAP( y1, y2 );
+ }
+
+ int dx = ABS(x2 - x1);
+ int dy = ABS(y2 - y1);
+
+ // this is a point, not a line. stoopid.
+ if ( dy == 0 && dx == 0 )
+ return;
+
+ PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x1, y1);
+ int pitch = surfacePitch();
+
+ if ( dy == 0 ) { // horizontal lines
+ // these can be filled really fast with a single memset.
+ // TODO: Platform specific ASM in set_to, would make this thing fly
+ Common::set_to(ptr, ptr + dx + 1, (PixelType)_color);
+
+ } else if ( dx == 0 ) { // vertical lines
+ // these ones use a static pitch increase.
+ while (y1++ <= y2) {
+ *ptr = (PixelType)_color;
+ ptr += pitch;
+ }
+
+ } else if ( ABS(dx) == ABS(dy) ) { // diagonal lines
+ // these ones also use a fixed pitch increase
+ pitch += ( x2 > x1 ) ? 1 : -1;
+
+ while ( dy-- ) {
+ *ptr = (PixelType)_color;
+ ptr += pitch;
+ }
+
+ } else { // generic lines, use the standard algorithm...
+ drawLineAlg( x1, x2, y1, y2, dx, dy );
+ }
+}
+
+} // end of namespace Graphics \ No newline at end of file
diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h
new file mode 100644
index 0000000000..b699f5cde9
--- /dev/null
+++ b/graphics/VectorRenderer.h
@@ -0,0 +1,236 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef VECTOR_RENDERER_H
+#define VECTOR_RENDERER_H
+
+#include "common/scummsys.h"
+#include "graphics/surface.h"
+
+namespace Graphics {
+
+/**
+ * VectorRenderer: The core Vector Renderer Class
+ *
+ * This virtual class which exposes the API with all the vectorial
+ * rendering functions that may be used to draw on a given Surface.
+ *
+ * This class must be instantiated as one of its children, which implement
+ * the actual rendering functionality for each Byte Depth / Byte Format
+ * combination, and may also contain platform specific code.
+ *
+ * TODO: Expand documentation.
+ *
+ * @see VectorRendererSpec
+ * @see VectorRendererAA
+ */
+class VectorRenderer {
+
+public:
+ /**
+ * Draws a line by considering the special cases for optimization.
+ *
+ * @param x1 Horizontal (X) coordinate for the line start
+ * @param x2 Horizontal (X) coordinate for the line end
+ * @param y1 Vertical (Y) coordinate for the line start
+ * @param y2 Vertical (Y) coordinate for the line end
+ */
+ virtual void drawLine( int x1, int x2, int y1, int y2 ) = 0;
+
+ /**
+ * Gets the pixel pitch for the current drawing surface.
+ * Note: This is a real pixel-pitch, not a byte-pitch.
+ * That means it can be safely used in pointer arithmetics and
+ * in pixel manipulation.
+ *
+ * @return integer with the active bytes per pixel
+ */
+ virtual uint16 surfacePitch() {
+ return _activeSurface->pitch/_activeSurface->bytesPerPixel;
+ }
+
+ /**
+ * Gets the BYTES (not bits) per Pixel we are working on,
+ * based on the active drawing surface.
+ *
+ * @return integer byte with the active bytes per pixel value
+ */
+ virtual uint8 bytesPerPixel() {
+ return _activeSurface->bytesPerPixel;
+ }
+
+ /**
+ * Set the active painting color for the renderer.
+ * All the drawing from then on will be done with that color, unless
+ * specified otherwise.
+ *
+ * @param r value of the red color byte
+ * @param g value of the green color byte
+ * @param b value of the blue color byte
+ */
+ virtual void setColor( uint8 r, uint8 g, uint8 b ) = 0;
+
+ /**
+ * Set the active painting color for the renderer, including alpha
+ * intensity. All the drawing from then on will be done with that color,
+ * unless specified otherwise.
+ *
+ * @param r value of the red color byte
+ * @param g value of the green color byte
+ * @param b value of the blue color byte
+ * @param a value of the alpha byte
+ */
+ virtual void setColor( uint8 r, uint8 g, uint8 b, uint8 a ) = 0;
+
+protected:
+
+ /**
+ * Generic line drawing algorithm. May be implemented by each
+ * inheriting class, i.e. with platform specific code.
+ *
+ * @see VectorRenderer::drawLine()
+ * @param x1 Horizontal (X) coordinate for the line start
+ * @param x2 Horizontal (X) coordinate for the line end
+ * @param y1 Vertical (Y) coordinate for the line start
+ * @param y2 Vertical (Y) coordinate for the line end
+ * @param dx Horizontal (X) increasement.
+ * @param dy Vertical (Y) increasement.
+ */
+ virtual void drawLineAlg( int x1, int x2, int y1, int y2, int dx, int dy ) = 0;
+
+ virtual void drawCircleAlg( int x, int y, int r ) = 0;
+
+ Surface *_activeSurface; /** Pointer to the surface currently being drawn */
+};
+
+
+
+/**
+ * VectorRendererSpec: Specialized Vector Renderer Class
+ *
+ * This templated class implements the basic subset of vector operations for
+ * all platforms by allowing the user to provide the actual Pixel Type and
+ * pixel information structs.
+ *
+ * This class takes two template parameters:
+ *
+ * @param PixelType Defines a type which may hold the color value of a single
+ * pixel, such as "byte" or "uint16" for 8 and 16 BPP respectively.
+ *
+ * @param PixelFormat Defines the type of the PixelFormat struct which contains all
+ * the actual information of the pixels being used, as declared in "graphics/colormasks.h"
+ *
+ * TODO: Expand documentation.
+ *
+ * @see VectorRenderer
+ */
+template<typename PixelType, typename PixelFormat>
+class VectorRendererSpec : public VectorRenderer {
+
+ /**
+ * @see VectorRenderer::drawLine()
+ */
+ void drawLine( int x1, int x2, int y1, int y2 );
+
+ /**
+ * @see VectorRenderer::setColor()
+ */
+ void setColor( uint8 r, uint8 g, uint8 b, uint8 a ) {
+ _color = ARGBToColor<PixelFormat>(r, g, b, a);
+ }
+
+ /**
+ * @see VectorRenderer::setColor()
+ */
+ void setColor( uint8 r, uint8 g, uint8 b ) {
+ _color = RGBToColor<PixelFormat>(r, g, b);
+ }
+
+protected:
+
+ /*
+ * "Bresenham's Line Algorithm", as described in Wikipedia.
+ * Based on the current implementation in "graphics/primitives.cpp".
+ *
+ * Generic line drawing algorithm for the aliased renderer. Optimized with no
+ * floating point operations and direct access to pixel buffer, assumes no special cases.
+ *
+ * @see VectorRenderer::drawLineAlg()
+ */
+ virtual void drawLineAlg( int x1, int x2, int y1, int y2, int dx, int dy );
+
+ virtual void drawCircleAlg( int x, int y, int r ) {}
+
+ PixelType _color; /** Color currently being used to draw on the renderer */
+};
+
+/**
+ * VectorRendererAA: Anti-Aliased Vector Renderer Class
+ *
+ * This templated class inherits all the functionality of the VectorRendererSpec
+ * class but uses better looking yet slightly slower AA algorithms for drawing
+ * most primivitves. May be used in faster platforms.
+ *
+ * TODO: Expand documentation.
+ *
+ * @see VectorRenderer
+ * @see VectorRendererSpec
+ */
+template<typename PixelType, typename PixelFormat>
+class VectorRendererAA : public VectorRendererSpec<PixelType,PixelFormat> {
+
+protected:
+ /**
+ * "Wu's Line Antialiasing Algorithm" as published by Xiaolin Wu, July 1991
+ * Based on the implementation found in Michael Abrash's Graphics Programming Black Book.
+ *
+ * Generic line drawing algorithm for the Antialiased renderer. Optimized with no
+ * floating point operations, assumes no special cases.
+ *
+ * @see VectorRenderer::drawLineAlg()
+ */
+ void drawLineAlg( int x1, int x2, int y1, int y2, int dx, int dy );
+
+ /**
+ * Calculates the blending weight (relative luminosity) value for
+ * a given pixel, based on the distance to the ideal line.
+ * Used for blending pixels in the Wu AA algorithm.
+ *
+ * @param line_color Byte value of a color component (R/G/B) of the color used to draw the line.
+ * @param line_color Byte value of a color component (R/G/B) of the color used to draw the BG.
+ * @param weight Weight of the pixel as calculated by Wu's algorithm.
+ * @return The new color value for the given component.
+ */
+ inline uint8 antialiasingBlendWeight( uint8 line_color, uint8 bg_color, uint weight ) {
+ uint8 value;
+ if ( bg_color > line_color ) {
+ value = weight / 255 * ( bg_color - line_color ) + bg_color;
+ } else {
+ value = weight / 255 * ( line_color - bg_color ) + line_color;
+ }
+ return value;
+ }
+};
+
+} // end of namespace Graphics
+
+#endif \ No newline at end of file