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//
24// Render Surface Shape Display include file
25//
26
27//
28// Macros to define before including this:
29//
30// #define NO_CLIPPING to disable shape clipping
31//
32// #define FLIP_SHAPES to flip rendering
33//
34// #define FLIP_CONDITIONAL to an argument of the function so FLIPPING can be
35// enabled/disabled with a bool
36//
37// #define XFORM_SHAPES to enable XFORMing
38//
39// #define XFORM_CONDITIONAL to an argument of the function so XFORM can be
40// enabled/disabled with a bool
41//
42// #define BLEND_SHAPES(src,dst) to an a specified blend function.
43//
44// #define BLEND_CONDITIONAL to an argument of the function so BLEND
45// painting can be enabled/disabled with a bool
46//
47
48//
49// Macros defined by this file:
50//
51// NOT_CLIPPED_Y - Does Y Clipping check per line
52//
53// NOT_CLIPPED_X - Does X Clipping check per Pixel
54//
55// LINE_END_ASSIGN - Calcuates the line_end pointer required for X clipping
56//
57// XNEG - Negates X values if doing shape flipping
58//
59// USE_XFORM_FUNC - Checks to see if we want to use XForm Blending for this pixel
60//
61// CUSTOM_BLEND - Final Blend for invisiblity
62//
63
64//
65// XForm = TRUE
66//
67#ifdef XFORM_SHAPES
68
69#ifdef XFORM_CONDITIONAL
70#define USE_XFORM_FUNC ((XFORM_CONDITIONAL) && xform_pal[*srcpix])
71#else
72#define USE_XFORM_FUNC (xform_pal[*srcpix])
73#endif
74
75//
76// XForm = FALSE
77//
78#else
79#define USE_XFORM_FUNC 0
80#endif
81
82
83//
84// Flipping = TRUE
85//
86#ifdef FLIP_SHAPES
87
88#ifdef FLIP_CONDITIONAL
89const int32 neg = (FLIP_CONDITIONAL)?-1:0;
90#define XNEG(x) (((x)+neg)^neg)
91#else
92#define XNEG(x) (-(x))
93#endif
94
95// Flipping = FALSE
96#else
97#define XNEG(x)(+(x))
98#endif
99
100
101//
102// No Clipping = TRUE
103//
104#ifdef NO_CLIPPING
105
106#define LINE_END_ASSIGN //
107#define NOT_CLIPPED_X (1)
108#define NOT_CLIPPED_Y (1)
109#define OFFSET_PIXELS (_pixels)
110
111//
112// No Clipping = FALSE
113//
114#else
115
116	const int		scrn_width = _clipWindow.width();
117	const int		scrn_height = _clipWindow.height();
118
119#define LINE_END_ASSIGN const uintX *dst_line_end = dst_line_start + scrn_width
120#define NOT_CLIPPED_X (dstpix >= dst_line_start && dstpix < dst_line_end)
121#define NOT_CLIPPED_Y (line >= 0 && line < scrn_height)
122#define OFFSET_PIXELS (off_pixels)
123
124	uint8			*off_pixels  = _pixels + _clipWindow.left * sizeof(uintX) + _clipWindow.top * _pitch;
125	x -= _clipWindow.left;
126	y -= _clipWindow.top;
127
128#endif
129
130
131//
132// Invisilibity = TRUE
133//
134#ifdef BLEND_SHAPES
135
136#ifdef BLEND_CONDITIONAL
137#define CUSTOM_BLEND(src) static_cast<uintX>((BLEND_CONDITIONAL)?BLEND_SHAPES(src,*dstpix):src)
138#else
139#define CUSTOM_BLEND(src) static_cast<uintX>(BLEND_SHAPES(src,*dstpix))
140#endif
141
142//
143// Invisilibity = FALSE
144//
145#else
146
147#define CUSTOM_BLEND(src) static_cast<uintX>(src)
148
149#endif
150
151//
152// Destination Alpha Masking
153//
154#ifdef DESTALPHA_MASK
155
156#define NOT_DESTINATION_MASKED	(*pixptr & RenderSurface::_format.aMask)
157
158#else
159
160#define NOT_DESTINATION_MASKED	(1)
161
162#endif
163
164//
165// The Function
166//
167
168	// Sanity check
169	if (framenum >= s->frameCount())
170		return;
171	if (s->getPalette() == 0)
172		return;
173
174	const ShapeFrame *frame			= s->getFrame(framenum);
175	if (!frame)
176		return;
177	const uint8		*srcpixels		= frame->_pixels;
178	const uint8		*srcmask		= frame->_mask;
179	const uint32	*pal			= untformed_pal ?
180										s->getPalette()->_native_untransformed:
181										s->getPalette()->_native;
182
183#ifdef XFORM_SHAPES
184	const uint32	*xform_pal		= untformed_pal ?
185										s->getPalette()->_xform_untransformed:
186										s->getPalette()->_xform;
187#endif
188
189	const int32 width_ = frame->_width;
190	const int32 height_ = frame->_height;
191	x -= XNEG(frame->_xoff);
192	y -= frame->_yoff;
193
194	assert(_pixels00 && _pixels && srcpixels && srcmask);
195
196	for (int i = 0; i < height_; i++)  {
197		const int line = y + i;
198
199		if (NOT_CLIPPED_Y) {
200			const uint8	*srcline = srcpixels + i * width_;
201			const uint8	*srcmaskline = srcmask + i * width_;
202			uintX *dst_line_start = reinterpret_cast<uintX *>(OFFSET_PIXELS + _pitch * line);
203			LINE_END_ASSIGN;
204
205			for (int xpos = 0; xpos < width_; xpos++) {
206				if (srcmaskline[xpos] == 0)
207					continue;
208
209				uintX *dstpix = dst_line_start + x + XNEG(xpos);
210
211				if (NOT_CLIPPED_X && NOT_DESTINATION_MASKED) {
212					const uint8 *srcpix = srcline + xpos;
213					#ifdef XFORM_SHAPES
214					if (USE_XFORM_FUNC) {
215						*dstpix = CUSTOM_BLEND(BlendPreModulated(xform_pal[*srcpix], *dstpix));
216					}
217					else
218					#endif
219					{
220						*dstpix = CUSTOM_BLEND(pal[*srcpix]);
221					}
222				}
223			}
224		}
225	}
226
227#undef NOT_DESTINATION_MASKED
228#undef OFFSET_PIXELS
229#undef CUSTOM_BLEND
230#undef LINE_END_ASSIGN
231#undef NOT_CLIPPED_X
232#undef NOT_CLIPPED_Y
233#undef XNEG
234#undef USE_XFORM_FUNC
235