1 /* ScummVM - Graphic Adventure Engine
2  *
3  * ScummVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the COPYRIGHT
5  * file distributed with this source distribution.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  */
22 
23 #ifndef VECTOR_RENDERER_H
24 #define VECTOR_RENDERER_H
25 
26 #include "common/rect.h"
27 #include "common/scummsys.h"
28 #include "common/str.h"
29 
30 #include "graphics/surface.h"
31 #include "graphics/transparent_surface.h"
32 
33 #include "gui/ThemeEngine.h"
34 
35 class OSystem;
36 
37 namespace Graphics {
38 class VectorRenderer;
39 struct DrawStep;
40 
41 
42 typedef void (VectorRenderer::*DrawingFunctionCallback)(const Common::Rect &, const Graphics::DrawStep &, const Common::Rect &);
43 
44 
45 struct DrawStep {
46 	struct Color {
47 		uint8 r, g, b;
48 		bool set;
49 	};
50 	Color fgColor; /**< Foreground color */
51 	Color bgColor; /**< background color */
52 	Color gradColor1; /**< gradient start*/
53 	Color gradColor2; /**< gradient end */
54 	Color bevelColor;
55 
56 	bool autoWidth, autoHeight;
57 	int16 x, y, w, h; /**< width, height and position, if not measured automatically.
58 						  negative values mean counting from the opposite direction */
59 
60 	Common::Rect padding;
61 
62 	enum VectorAlignment {
63 		kVectorAlignManual,
64 		kVectorAlignLeft,
65 		kVectorAlignRight,
66 		kVectorAlignBottom,
67 		kVectorAlignTop,
68 		kVectorAlignCenter
69 	};
70 
71 	VectorAlignment xAlign;
72 	VectorAlignment yAlign;
73 
74 	uint8 shadow, stroke, factor, radius, bevel; /**< Misc options... */
75 
76 	uint8 fillMode; /**< active fill mode */
77 	uint8 shadowFillMode; /**< fill mode of the shadow used */
78 
79 	uint32 extraData; /**< Generic parameter for extra options (orientation/bevel) */
80 
81 	uint32 scale; /**< scale of all the coordinates in FIXED POINT with 16 bits mantissa */
82 
83 	GUI::ThemeEngine::AutoScaleMode autoscale; /**< scale alphaimage if present */
84 
85 	DrawingFunctionCallback drawingCall; /**< Pointer to drawing function */
86 	Graphics::Surface *blitSrc;
87 	Graphics::TransparentSurface *blitAlphaSrc;
88 };
89 
90 VectorRenderer *createRenderer(int mode);
91 
92 /**
93  * VectorRenderer: The core Vector Renderer Class
94  *
95  * This virtual class exposes the API with all the vectorial
96  * rendering functions that may be used to draw on a given Surface.
97  *
98  * This class must be instantiated as one of its children, which implement
99  * the actual rendering functionality for each Byte Depth / Byte Format
100  * combination, and may also contain platform specific code.
101  *
102  * When specifying define DISABLE_FANCY_THEMES eye candy related code
103  * gets stripped off. This is especially useful for small devices like NDS.
104  *
105  * TODO: Expand documentation.
106  *
107  * @see VectorRendererSpec
108  * @see VectorRendererAA
109  */
110 class VectorRenderer {
111 public:
VectorRenderer()112 	VectorRenderer() : _activeSurface(NULL), _fillMode(kFillDisabled), _shadowOffset(0), _shadowFillMode(kShadowExponential),
113 		_disableShadows(false), _strokeWidth(1), _gradientFactor(1) {
114 
115 	}
116 
~VectorRenderer()117 	virtual ~VectorRenderer() {}
118 
119 	/** Specifies the way in which a shape is filled */
120 	enum FillMode {
121 		kFillDisabled = 0,
122 		kFillForeground = 1,
123 		kFillBackground = 2,
124 		kFillGradient = 3
125 	};
126 
127 	enum TriangleOrientation {
128 		kTriangleAuto = 0,
129 		kTriangleUp,
130 		kTriangleDown,
131 		kTriangleLeft,
132 		kTriangleRight
133 	};
134 
135 	enum ShadowFillMode {
136 		kShadowLinear = 0,
137 		kShadowExponential = 1
138 	};
139 
140 	/**
141 	 * Draws a line by considering the special cases for optimization.
142 	 *
143 	 * @param x1 Horizontal (X) coordinate for the line start
144 	 * @param x2 Horizontal (X) coordinate for the line end
145 	 * @param y1 Vertical (Y) coordinate for the line start
146 	 * @param y2 Vertical (Y) coordinate for the line end
147 	 */
148 	virtual void drawLine(int x1, int y1, int x2, int y2) = 0;
149 	virtual void drawLineClip(int x1, int y1, int x2, int y2, Common::Rect clipping) = 0;
150 
151 	/**
152 	 * Draws a circle centered at (x,y) with radius r.
153 	 *
154 	 * @param x Horizontal (X) coordinate for the center of the circle
155 	 * @param y Vertical (Y) coordinate for the center of the circle
156 	 * @param r Radius of the circle.
157 	 */
158 	virtual void drawCircle(int x, int y, int r) = 0;
159 	virtual void drawCircleClip(int x, int y, int r, Common::Rect clipping) = 0;
160 
161 	/**
162 	 * Draws a square starting at (x,y) with the given width and height.
163 	 *
164 	 * @param x Horizontal (X) coordinate for the center of the square
165 	 * @param y Vertical (Y) coordinate for the center of the square
166 	 * @param w Width of the square.
167 	 * @param h Height of the square
168 	 */
169 	virtual void drawSquare(int x, int y, int w, int h) = 0;
170 	virtual void drawSquareClip(int x, int y, int w, int h, Common::Rect clipping) = 0;
171 
172 	/**
173 	 * Draws a rounded square starting at (x,y) with the given width and height.
174 	 * The corners of the square are rounded with the given radius.
175 	 *
176 	 * @param x Horizontal (X) coordinate for the center of the square
177 	 * @param y Vertical (Y) coordinate for the center of the square
178 	 * @param w Width of the square.
179 	 * @param h Height of the square
180 	 * @param r Radius of the corners.
181 	 */
182 	virtual void drawRoundedSquare(int x, int y, int r, int w, int h) = 0;
183 	virtual void drawRoundedSquareClip(int x, int y, int r, int w, int h, Common::Rect clipping) = 0;
184 
185 	/**
186 	 * Draws a triangle starting at (x,y) with the given base and height.
187 	 * The triangle will always be isosceles, with the given base and height.
188 	 * The orientation parameter controls the position of the base of the triangle.
189 	 *
190 	 * @param x Horizontal (X) coordinate for the top left corner of the triangle
191 	 * @param y Vertical (Y) coordinate for the top left corner of the triangle
192 	 * @param base Width of the base of the triangle
193 	 * @param height Height of the triangle
194 	 * @param orient Orientation of the triangle.
195 	 */
196 	virtual void drawTriangle(int x, int y, int base, int height, TriangleOrientation orient) = 0;
197 	virtual void drawTriangleClip(int x, int y, int base, int height, TriangleOrientation orient, Common::Rect clipping) = 0;
198 
199 	/**
200 	 * Draws a beveled square like the ones in the Classic GUI themes.
201 	 * Beveled squares are always drawn with a transparent background. Draw them on top
202 	 * of a standard square to fill it.
203 	 *
204 	 * @param x Horizontal (X) coordinate for the center of the square
205 	 * @param y Vertical (Y) coordinate for the center of the square
206 	 * @param w Width of the square.
207 	 * @param h Height of the square
208 	 * @param bevel Amount of bevel. Must be positive.
209 	 */
210 	virtual void drawBeveledSquare(int x, int y, int w, int h, int bevel) = 0;
211 	virtual void drawBeveledSquareClip(int x, int y, int w, int h, int bevel, Common::Rect clipping) = 0;
212 
213 	/**
214 	 * Draws a tab-like shape, specially thought for the Tab widget.
215 	 * If a radius is given, the tab will have rounded corners. Otherwise,
216 	 * the tab will be squared.
217 	 *
218 	 * @param x Horizontal (X) coordinate for the tab
219 	 * @param y Vertical (Y) coordinate for the tab
220 	 * @param w Width of the tab
221 	 * @param h Height of the tab
222 	 * @param r Radius of the corners of the tab (0 for squared tabs).
223 	 */
224 	virtual void drawTab(int x, int y, int r, int w, int h) = 0;
225 	virtual void drawTabClip(int x, int y, int r, int w, int h, Common::Rect clipping) = 0;
226 
227 
228 	/**
229 	 * Simple helper function to draw a cross.
230 	 */
drawCross(int x,int y,int w,int h)231 	virtual void drawCross(int x, int y, int w, int h) {
232 		drawLine(x, y, x + w, y + w);
233 		drawLine(x + w, y, x, y + h);
234 	}
235 
drawCrossClip(int x,int y,int w,int h,Common::Rect clipping)236 	virtual void drawCrossClip(int x, int y, int w, int h, Common::Rect clipping) {
237 		drawLineClip(x, y, x + w, y + w, clipping);
238 		drawLineClip(x + w, y, x, y + h, clipping);
239 	}
240 
241 	/**
242 	 * Set the active foreground painting color for the renderer.
243 	 * All the foreground drawing from then on will be done with that color, unless
244 	 * specified otherwise.
245 	 *
246 	 * Foreground drawing means all outlines and basic shapes.
247 	 *
248 	 * @param r	value of the red color byte
249 	 * @param g	value of the green color byte
250 	 * @param b	value of the blue color byte
251 	 */
252 	virtual void setFgColor(uint8 r, uint8 g, uint8 b) = 0;
253 
254 	/**
255 	 * Set the active background painting color for the renderer.
256 	 * All the background drawing from then on will be done with that color, unless
257 	 * specified otherwise.
258 	 *
259 	 * Background drawing means all the shape filling.
260 	 *
261 	 * @param r	value of the red color byte
262 	 * @param g	value of the green color byte
263 	 * @param b	value of the blue color byte
264 	 */
265 	virtual void setBgColor(uint8 r, uint8 g, uint8 b) = 0;
266 
267 	virtual void setBevelColor(uint8 r, uint8 g, uint8 b) = 0;
268 
269 	/**
270 	 * Set the active gradient color. All shapes drawn using kFillGradient
271 	 * as their fill mode will use this VERTICAL gradient as their fill color.
272 	 *
273 	 * @param r1	value of the red color byte for the start color
274 	 * @param g1	value of the green color byte for the start color
275 	 * @param b1	value of the blue color byte for the start color
276 	 * @param r2	value of the red color byte for the end color
277 	 * @param g2	value of the green color byte for the end color
278 	 * @param b2	value of the blue color byte for the end color
279 	 */
280 	virtual void setGradientColors(uint8 r1, uint8 g1, uint8 b1, uint8 r2, uint8 g2, uint8 b2) = 0;
281 
282 	/**
283 	 * Sets the active drawing surface. All drawing from this
284 	 * point on will be done on that surface.
285 	 *
286 	 * @param surface Pointer to a Surface object.
287 	 */
setSurface(TransparentSurface * surface)288 	virtual void setSurface(TransparentSurface *surface) {
289 		_activeSurface = surface;
290 	}
291 
292 	/**
293 	 * Fills the active surface with the specified fg/bg color or the active gradient.
294 	 * Defaults to using the active Foreground color for filling.
295 	 */
296 	virtual void fillSurface() = 0;
297 	virtual void fillSurfaceClip(Common::Rect clipping) = 0;
298 
299 	/**
300 	 * Clears the active surface.
301 	 */
clearSurface()302 	virtual void clearSurface() {
303 		byte *src = (byte *)_activeSurface->getPixels();
304 		memset(src, 0, _activeSurface->pitch * _activeSurface->h);
305 	}
306 
307 	/**
308 	 * Sets the active fill mode for all shapes.
309 	 *
310 	 * @see VectorRenderer::FillMode
311 	 * @param mode Specified fill mode.
312 	 */
setFillMode(FillMode mode)313 	virtual void setFillMode(FillMode mode) {
314 		_fillMode = mode;
315 	}
316 
setShadowFillMode(ShadowFillMode mode)317 	virtual void setShadowFillMode(ShadowFillMode mode) {
318 		_shadowFillMode = mode;
319 	}
320 
321 	/**
322 	 * Sets the stroke width. All shapes drawn with a stroke will
323 	 * have that width. Pass 0 to disable shape stroking.
324 	 *
325 	 * @param width Width of the stroke in pixels.
326 	 */
setStrokeWidth(int width)327 	virtual void setStrokeWidth(int width) {
328 		_strokeWidth = width;
329 	}
330 
331 	/**
332 	 * Enables adding shadows to all drawn primitives.
333 	 * Shadows are drawn automatically under the shapes. The given offset
334 	 * controls their intensity and size (the higher the offset, the
335 	 * bigger the shadows). If the offset is 0, no shadows are drawn.
336 	 *
337 	 * @param offset Shadow offset.
338 	 */
setShadowOffset(int offset)339 	virtual void setShadowOffset(int offset) {
340 		if (offset >= 0)
341 			_shadowOffset = offset;
342 	}
343 
setBevel(int amount)344 	virtual void setBevel(int amount) {
345 		if (amount >= 0)
346 			_bevel = amount;
347 	}
348 
349 	/**
350 	 * Sets the multiplication factor of the active gradient.
351 	 *
352 	 * @see _gradientFactor
353 	 * @param factor Multiplication factor.
354 	 */
setGradientFactor(int factor)355 	virtual void setGradientFactor(int factor) {
356 		if (factor > 0)
357 			_gradientFactor = factor;
358 	}
359 
360 	/**
361 	 * Translates the position data inside a DrawStep into actual
362 	 * screen drawing positions.
363 	 */
364 	void stepGetPositions(const DrawStep &step, const Common::Rect &area, uint16 &in_x, uint16 &in_y, uint16 &in_w, uint16 &in_h);
365 
366 	/**
367 	 * Translates the radius data inside a drawstep into the real radius
368 	 * for the shape. Used for automatic radius calculations.
369 	 */
370 	int stepGetRadius(const DrawStep &step, const Common::Rect &area);
371 
372 	/**
373 	 * DrawStep callback functions for each drawing feature
374 	 */
drawCallback_CIRCLE(const Common::Rect & area,const DrawStep & step,const Common::Rect & clip)375 	void drawCallback_CIRCLE(const Common::Rect &area, const DrawStep &step, const Common::Rect &clip) {
376 		uint16 x, y, w, h, radius;
377 
378 		radius = stepGetRadius(step, area);
379 		stepGetPositions(step, area, x, y, w, h);
380 
381 		drawCircleClip(x + radius, y + radius, radius, clip);
382 	}
383 
drawCallback_SQUARE(const Common::Rect & area,const DrawStep & step,const Common::Rect & clip)384 	void drawCallback_SQUARE(const Common::Rect &area, const DrawStep &step, const Common::Rect &clip) {
385 		uint16 x, y, w, h;
386 		stepGetPositions(step, area, x, y, w, h);
387 		drawSquareClip(x, y, w, h, clip);
388 	}
389 
drawCallback_LINE(const Common::Rect & area,const DrawStep & step,const Common::Rect & clip)390 	void drawCallback_LINE(const Common::Rect &area, const DrawStep &step, const Common::Rect &clip) {
391 		uint16 x, y, w, h;
392 		stepGetPositions(step, area, x, y, w, h);
393 		drawLineClip(x, y, x + w, y + w, clip);
394 	}
395 
drawCallback_ROUNDSQ(const Common::Rect & area,const DrawStep & step,const Common::Rect & clip)396 	void drawCallback_ROUNDSQ(const Common::Rect &area, const DrawStep &step, const Common::Rect &clip) {
397 		uint16 x, y, w, h;
398 		stepGetPositions(step, area, x, y, w, h);
399 		drawRoundedSquareClip(x, y, stepGetRadius(step, area), w, h, clip);
400 	}
401 
drawCallback_FILLSURFACE(const Common::Rect & area,const DrawStep & step,const Common::Rect & clip)402 	void drawCallback_FILLSURFACE(const Common::Rect &area, const DrawStep &step, const Common::Rect &clip) {
403 		fillSurfaceClip(clip);
404 	}
405 
drawCallback_TRIANGLE(const Common::Rect & area,const DrawStep & step,const Common::Rect & clip)406 	void drawCallback_TRIANGLE(const Common::Rect &area, const DrawStep &step, const Common::Rect &clip) {
407 		uint16 x, y, w, h;
408 		stepGetPositions(step, area, x, y, w, h);
409 		drawTriangleClip(x, y, w, h, (TriangleOrientation)step.extraData, clip);
410 	}
411 
drawCallback_BEVELSQ(const Common::Rect & area,const DrawStep & step,const Common::Rect & clip)412 	void drawCallback_BEVELSQ(const Common::Rect &area, const DrawStep &step, const Common::Rect &clip) {
413 		uint16 x, y, w, h;
414 		stepGetPositions(step, area, x, y, w, h);
415 		drawBeveledSquareClip(x, y, w, h, _bevel, clip);
416 	}
417 
drawCallback_TAB(const Common::Rect & area,const DrawStep & step,const Common::Rect & clip)418 	void drawCallback_TAB(const Common::Rect &area, const DrawStep &step, const Common::Rect &clip) {
419 		uint16 x, y, w, h;
420 		stepGetPositions(step, area, x, y, w, h);
421 		drawTabClip(x, y, stepGetRadius(step, area), w, h, clip);
422 	}
423 
drawCallback_BITMAP(const Common::Rect & area,const DrawStep & step,const Common::Rect & clip)424 	void drawCallback_BITMAP(const Common::Rect &area, const DrawStep &step, const Common::Rect &clip) {
425 		uint16 x, y, w, h;
426 		stepGetPositions(step, area, x, y, w, h);
427 		blitKeyBitmapClip(step.blitSrc, Common::Rect(x, y, x + w, y + h), clip);
428 	}
429 
drawCallback_ALPHABITMAP(const Common::Rect & area,const DrawStep & step,const Common::Rect & clip)430 	void drawCallback_ALPHABITMAP(const Common::Rect &area, const DrawStep &step, const Common::Rect &clip) {
431 		uint16 x, y, w, h;
432 		stepGetPositions(step, area, x, y, w, h);
433 		blitAlphaBitmap(step.blitAlphaSrc, Common::Rect(x, y, x + w, y + h), step.autoscale, step.xAlign, step.yAlign); //TODO
434 	}
435 
drawCallback_CROSS(const Common::Rect & area,const DrawStep & step,const Common::Rect & clip)436 	void drawCallback_CROSS(const Common::Rect &area, const DrawStep &step, const Common::Rect &clip) {
437 		uint16 x, y, w, h;
438 		stepGetPositions(step, area, x, y, w, h);
439 		drawCrossClip(x, y, w, h, clip);
440 	}
441 
drawCallback_VOID(const Common::Rect & area,const DrawStep & step,const Common::Rect & clip)442 	void drawCallback_VOID(const Common::Rect &area, const DrawStep &step, const Common::Rect &clip) {}
443 
444 	/**
445 	 * Draws the specified draw step on the screen.
446 	 *
447 	 * @see DrawStep
448 	 * @param area Zone to paint on
449 	 * @param step Pointer to a DrawStep struct.
450 	 */
451 	virtual void drawStep(const Common::Rect &area, const DrawStep &step, uint32 extra = 0);
452 	virtual void drawStepClip(const Common::Rect &area, const Common::Rect &clip, const DrawStep &step, uint32 extra = 0);
453 
454 	/**
455 	 * Copies the part of the current frame to the system overlay.
456 	 *
457 	 * @param sys Pointer to the global System class
458 	 * @param r Zone of the surface to copy into the overlay.
459 	 */
460 	virtual void copyFrame(OSystem *sys, const Common::Rect &r) = 0;
461 
462 	/**
463 	 * Copies the current surface to the system overlay
464 	 *
465 	 * @param sys Pointer to the global System class
466 	 */
467 	virtual void copyWholeFrame(OSystem *sys) = 0;
468 
469 	/**
470 	 * Blits a given graphics surface on top of the current drawing surface.
471 	 *
472 	 * Note that the source surface and the active
473 	 * surface are expected to be of the same size, hence the area delimited
474 	 * by "r" in the source surface will be blitted into the area delimited by
475 	 * "r" on the current surface.
476 	 *
477 	 * If you wish to blit a smaller surface into the active drawing area, use
478 	 * VectorRenderer::blitSubSurface().
479 	 *
480 	 * @param source Surface to blit into the drawing surface.
481 	 * @param r Position in the active drawing surface to do the blitting.
482 	 */
483 	virtual void blitSurface(const Graphics::Surface *source, const Common::Rect &r) = 0;
484 
485 	/**
486 	 * Blits a given graphics surface into a small area of the current drawing surface.
487 	 *
488 	 * Note that the given surface is expected to be smaller than the
489 	 * active drawing surface, hence the WHOLE source surface will be
490 	 * blitted into the active surface, at the position specified by "r".
491 	 */
492 	virtual void blitSubSurface(const Graphics::Surface *source, const Common::Rect &r) = 0;
493 	virtual void blitSubSurfaceClip(const Graphics::Surface *source, const Common::Rect &r, const Common::Rect &clipping) = 0;
494 
495 	virtual void blitKeyBitmap(const Graphics::Surface *source, const Common::Rect &r) = 0;
496 	virtual void blitKeyBitmapClip(const Graphics::Surface *source, const Common::Rect &r, const Common::Rect &clipping) = 0;
497 
498 	virtual void blitAlphaBitmap(Graphics::TransparentSurface *source, const Common::Rect &r,
499 			GUI::ThemeEngine::AutoScaleMode autoscale = GUI::ThemeEngine::kAutoScaleNone,
500 			Graphics::DrawStep::VectorAlignment xAlign = Graphics::DrawStep::kVectorAlignManual,
501 			Graphics::DrawStep::VectorAlignment yAlign = Graphics::DrawStep::kVectorAlignManual,
502 			int alpha = 255) = 0;
503 
504 	/**
505 	 * Draws a string into the screen. Wrapper for the Graphics::Font string drawing
506 	 * method.
507 	 */
508 	virtual void drawString(const Graphics::Font *font, const Common::String &text,
509 	                        const Common::Rect &area, Graphics::TextAlign alignH,
510 	                        GUI::ThemeEngine::TextAlignVertical alignV, int deltax, bool useEllipsis, const Common::Rect &textDrawableArea) = 0;
511 
512 	/**
513 	 * Allows to temporarily enable/disable all shadows drawing.
514 	 * i.e. for performance issues, blitting, etc
515 	 */
disableShadows()516 	virtual void disableShadows() { _disableShadows = true; }
enableShadows()517 	virtual void enableShadows() { _disableShadows = false; }
518 
519 	/**
520 	 * Applies a whole-screen shading effect, used before opening a new dialog.
521 	 * Currently supports screen dimmings and luminance (b&w).
522 	 */
523 	virtual void applyScreenShading(GUI::ThemeEngine::ShadingStyle) = 0;
524 
525 protected:
526 	TransparentSurface *_activeSurface; /**< Pointer to the surface currently being drawn */
527 
528 	FillMode _fillMode; /**< Defines in which way (if any) are filled the drawn shapes */
529 	ShadowFillMode _shadowFillMode;
530 
531 	int _shadowOffset; /**< offset for drawn shadows */
532 	int _bevel; /**< amount of fake bevel */
533 	bool _disableShadows; /**< Disables temporarily shadow drawing for overlayed images. */
534 	int _strokeWidth; /**< Width of the stroke of all drawn shapes */
535 	uint32 _dynamicData; /**< Dynamic data from the GUI Theme that modifies the drawing of the current shape */
536 
537 	int _gradientFactor; /**< Multiplication factor of the active gradient */
538 };
539 
540 } // End of namespace Graphics
541 
542 #endif
543