xref: /haiku/src/kits/interface/PicturePlayer.cpp (revision 1acbe440b8dd798953bec31d18ee589aa3f71b73)
1 /*
2  * Copyright 2001-2007, Haiku Inc.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Marc Flerackers (mflerackers@androme.be)
7  *		Stefano Ceccherini (burton666@libero.it)
8  *		Marcus Overhagen (marcus@overhagen.de)
9  */
10 
11 /**	PicturePlayer is used to create and play picture data. */
12 
13 #include <stdio.h>
14 
15 #include <PicturePlayer.h>
16 #include <PictureProtocol.h>
17 
18 #include <Shape.h>
19 
20 typedef void (*fnc)(void*);
21 typedef void (*fnc_BPoint)(void*, BPoint);
22 typedef void (*fnc_BPointBPoint)(void*, BPoint, BPoint);
23 typedef void (*fnc_BRect)(void*, BRect);
24 typedef void (*fnc_BRectBPoint)(void*, BRect, BPoint);
25 typedef void (*fnc_PBPoint)(void*, const BPoint*);
26 typedef void (*fnc_i)(void*, int32);
27 typedef void (*fnc_iPBPointb)(void*, int32, const BPoint*, bool);
28 typedef void (*fnc_iPBPoint)(void*, int32, const BPoint*);
29 typedef void (*fnc_Pc)(void*, const char*);
30 typedef void (*fnc_Pcff)(void*, const char*, float, float);
31 typedef void (*fnc_BPointBPointff)(void*, BPoint, BPoint, float, float);
32 typedef void (*fnc_s)(void*, int16);
33 typedef void (*fnc_ssf)(void*, int16, int16, float);
34 typedef void (*fnc_f)(void*, float);
35 typedef void (*fnc_Color)(void*, rgb_color);
36 typedef void (*fnc_Pattern)(void*, pattern);
37 typedef void (*fnc_ss)(void *, int16, int16);
38 typedef void (*fnc_PBRecti)(void*, const BRect*, int32);
39 typedef void (*fnc_DrawPixels)(void *, BRect, BRect, int32, int32, int32,
40 							   int32, int32, const void *);
41 typedef void (*fnc_BShape)(void*, BShape*);
42 
43 
44 PicturePlayer::PicturePlayer(const void *data, size_t size, BList *pictures)
45 	:	fData(data),
46 		fSize(size),
47 		fPictures(pictures)
48 {
49 }
50 
51 
52 PicturePlayer::~PicturePlayer()
53 {
54 }
55 
56 
57 status_t
58 PicturePlayer::Play(void **callBackTable, int32 tableEntries, void *userData)
59 {
60 	// TODO: we should probably check if the functions in the table are not NULL
61 	//       before calling them.
62 
63 	const char *data = reinterpret_cast<const char *>(fData);
64 	size_t pos = 0;
65 
66 	while ((pos + 6) <= fSize) {
67 		int16 op = *reinterpret_cast<const int16 *>(data);
68 		int32 size = *reinterpret_cast<const int32 *>(data + 2);
69 		pos += 6;
70 		data += 6;
71 
72 		if (pos + size > fSize)
73 			debugger("PicturePlayer::Play: buffer overrun\n");
74 
75 		switch (op) {
76 			case B_PIC_MOVE_PEN_BY:
77 			{
78 				((fnc_BPoint)callBackTable[1])(userData,
79 					*reinterpret_cast<const BPoint *>(data)); /* where */
80 				break;
81 			}
82 
83 			case B_PIC_STROKE_LINE:
84 			{
85 				((fnc_BPointBPoint)callBackTable[2])(userData,
86 					*reinterpret_cast<const BPoint *>(data), /* start */
87 					*reinterpret_cast<const BPoint *>(data + sizeof(BPoint))); /* end */
88 				break;
89 			}
90 
91 			case B_PIC_STROKE_RECT:
92 			{
93 				((fnc_BRect)callBackTable[3])(userData,
94 					*reinterpret_cast<const BRect *>(data)); /* rect */
95 				break;
96 			}
97 
98 			case B_PIC_FILL_RECT:
99 			{
100 				((fnc_BRect)callBackTable[4])(userData,
101 					*reinterpret_cast<const BRect *>(data)); /* rect */
102 				break;
103 			}
104 
105 			case B_PIC_STROKE_ROUND_RECT:
106 			{
107 				((fnc_BRectBPoint)callBackTable[5])(userData,
108 					*reinterpret_cast<const BRect *>(data), /* rect */
109 					*reinterpret_cast<const BPoint *>(data + sizeof(BRect))); /* radii */
110 				break;
111 			}
112 
113 			case B_PIC_FILL_ROUND_RECT:
114 			{
115 				((fnc_BRectBPoint)callBackTable[6])(userData,
116 					*reinterpret_cast<const BRect *>(data), /* rect */
117 					*reinterpret_cast<const BPoint *>(data + sizeof(BRect))); /* radii */
118 				break;
119 			}
120 
121 			case B_PIC_STROKE_BEZIER:
122 			{
123 				((fnc_PBPoint)callBackTable[7])(userData,
124 					reinterpret_cast<const BPoint *>(data));
125 				break;
126 			}
127 
128 			case B_PIC_FILL_BEZIER:
129 			{
130 				((fnc_PBPoint)callBackTable[8])(userData,
131 					reinterpret_cast<const BPoint *>(data));
132 				break;
133 			}
134 
135 			case B_PIC_STROKE_ARC:
136 			{
137 				((fnc_BPointBPointff)callBackTable[9])(userData,
138 					*reinterpret_cast<const BPoint *>(data), /* center */
139 					*reinterpret_cast<const BPoint *>(data + sizeof(BPoint)), /* radii */
140 					*reinterpret_cast<const float *>(data + 2 * sizeof(BPoint)), /* startTheta */
141 					*reinterpret_cast<const float *>(data + 2 * sizeof(BPoint) + sizeof(float))); /* arcTheta */
142 				break;
143 			}
144 
145 			case B_PIC_FILL_ARC:
146 			{
147 				((fnc_BPointBPointff)callBackTable[10])(userData,
148 					*reinterpret_cast<const BPoint *>(data), /* center */
149 					*reinterpret_cast<const BPoint *>(data + sizeof(BPoint)), /* radii */
150 					*reinterpret_cast<const float *>(data + 2 * sizeof(BPoint)), /* startTheta */
151 					*reinterpret_cast<const float *>(data + 2 * sizeof(BPoint) + sizeof(float))); /* arcTheta */
152 				break;
153 			}
154 
155 			case B_PIC_STROKE_ELLIPSE:
156 			{
157 				const BRect *rect = reinterpret_cast<const BRect *>(data);
158 				BPoint radii((rect->Width() + 1) / 2.0f, (rect->Height() + 1) / 2.0f);
159 				BPoint center = rect->LeftTop() + radii;
160 				((fnc_BPointBPoint)callBackTable[11])(userData, center, radii);
161 				break;
162 			}
163 
164 			case B_PIC_FILL_ELLIPSE:
165 			{
166 				const BRect *rect = reinterpret_cast<const BRect *>(data);
167 				BPoint radii((rect->Width() + 1) / 2.0f, (rect->Height() + 1) / 2.0f);
168 				BPoint center = rect->LeftTop() + radii;
169 				((fnc_BPointBPoint)callBackTable[12])(userData, center, radii);
170 				break;
171 			}
172 
173 			case B_PIC_STROKE_POLYGON:
174 			{
175 				int32 numPoints = *reinterpret_cast<const int32 *>(data);
176 				((fnc_iPBPointb)callBackTable[13])(userData,
177 					numPoints,
178 					reinterpret_cast<const BPoint *>(data + sizeof(int32)), /* points */
179 					*reinterpret_cast<const uint8 *>(data + sizeof(int32) + numPoints * sizeof(BPoint))); /* is-closed */
180 				break;
181 			}
182 
183 			case B_PIC_FILL_POLYGON:
184 			{
185 				((fnc_iPBPoint)callBackTable[14])(userData,
186 					*reinterpret_cast<const int32 *>(data), /* numPoints */
187 					reinterpret_cast<const BPoint *>(data + sizeof(int32))); /* points */
188 				break;
189 			}
190 
191 			case B_PIC_STROKE_SHAPE:
192 			case B_PIC_FILL_SHAPE:
193 			{
194 				int32 opCount = *reinterpret_cast<const int32 *>(data);
195 				int32 ptCount = *reinterpret_cast<const int32 *>(data + sizeof(int32));
196 				const uint32 *opList = reinterpret_cast<const uint32 *>(data + 2 * sizeof(int32));
197 				const BPoint *ptList = reinterpret_cast<const BPoint *>(data + 2 * sizeof(int32) + opCount * sizeof(uint32));
198 
199 				// TODO: remove BShape data copying
200 				BShape shape;
201 				shape.SetData(opCount, ptCount, opList, ptList);
202 
203 				const int32 tableIndex = (op == B_PIC_STROKE_SHAPE) ? 15 : 16;
204 				((fnc_BShape)callBackTable[tableIndex])(userData, &shape);
205 				break;
206 			}
207 
208 			case B_PIC_DRAW_STRING:
209 			{
210 				((fnc_Pcff)callBackTable[17])(userData,
211 					reinterpret_cast<const char *>(data + 2 * sizeof(float)), /* string */
212 					*reinterpret_cast<const float *>(data), /* escapement.space */
213 					*reinterpret_cast<const float *>(data + sizeof(float))); /* escapement.nonspace */
214 				break;
215 			}
216 
217 			case B_PIC_DRAW_PIXELS:
218 			{
219 				((fnc_DrawPixels)callBackTable[18])(userData,
220 					*reinterpret_cast<const BRect *>(data), /* src */
221 					*reinterpret_cast<const BRect *>(data + 1 * sizeof(BRect)), /* dst */
222 					*reinterpret_cast<const int32 *>(data + 2 * sizeof(BRect)), /* width */
223 					*reinterpret_cast<const int32 *>(data + 2 * sizeof(BRect) + 1 * sizeof(int32)), /* height */
224 					*reinterpret_cast<const int32 *>(data + 2 * sizeof(BRect) + 2 * sizeof(int32)), /* bytesPerRow */
225 					*reinterpret_cast<const int32 *>(data + 2 * sizeof(BRect) + 3 * sizeof(int32)), /* pixelFormat */
226 					*reinterpret_cast<const int32 *>(data + 2 * sizeof(BRect) + 4 * sizeof(int32)), /* flags */
227 					reinterpret_cast<const void *>(data + 2 * sizeof(BRect) + 5 * sizeof(int32))); /* data */
228 				break;
229 			}
230 
231 			case B_PIC_DRAW_PICTURE:
232 			{
233 				break;
234 			}
235 
236 			case B_PIC_SET_CLIPPING_RECTS:
237 			{
238 				break;
239 			}
240 
241 			case B_PIC_CLEAR_CLIPPING_RECTS:
242 			{
243 				((fnc_PBRecti)callBackTable[20])(userData, NULL, 0);
244 				break;
245 			}
246 
247 			case B_PIC_CLIP_TO_PICTURE:
248 			{
249 				break;
250 			}
251 
252 			case B_PIC_PUSH_STATE:
253 			{
254 				((fnc)callBackTable[22])(userData);
255 				break;
256 			}
257 
258 			case B_PIC_POP_STATE:
259 			{
260 				((fnc)callBackTable[23])(userData);
261 				break;
262 			}
263 
264 			case B_PIC_ENTER_STATE_CHANGE:
265 			{
266 				((fnc)callBackTable[24])(userData);
267 				break;
268 			}
269 
270 			case B_PIC_ENTER_FONT_STATE:
271 			{
272 				((fnc)callBackTable[26])(userData);
273 				break;
274 			}
275 
276 			case B_PIC_SET_ORIGIN:
277 			{
278 				((fnc_BPoint)callBackTable[28])(userData,
279 					*reinterpret_cast<const BPoint *>(data)); /* origin */
280 				break;
281 			}
282 
283 			case B_PIC_SET_PEN_LOCATION:
284 			{
285 				((fnc_BPoint)callBackTable[29])(userData,
286 					*reinterpret_cast<const BPoint *>(data)); /* location */
287 				break;
288 			}
289 
290 			case B_PIC_SET_DRAWING_MODE:
291 			{
292 				((fnc_s)callBackTable[30])(userData,
293 					*reinterpret_cast<const int16 *>(data)); /* mode */
294 				break;
295 			}
296 
297 			case B_PIC_SET_LINE_MODE:
298 			{
299 				((fnc_ssf)callBackTable[31])(userData,
300 					*reinterpret_cast<const int16 *>(data), /* cap-mode */
301 					*reinterpret_cast<const int16 *>(data + 1 * sizeof(int16)), /* join-mode */
302 					*reinterpret_cast<const float *>(data + 2 * sizeof(int16))); /* miter-limit */
303 				break;
304 			}
305 
306 			case B_PIC_SET_PEN_SIZE:
307 			{
308 				((fnc_f)callBackTable[32])(userData,
309 					*reinterpret_cast<const float *>(data)); /* size */
310 				break;
311 			}
312 
313 			case B_PIC_SET_FORE_COLOR:
314 			{
315 				((fnc_Color)callBackTable[33])(userData,
316 					*reinterpret_cast<const rgb_color *>(data)); /* color */
317 				break;
318 			}
319 
320 			case B_PIC_SET_BACK_COLOR:
321 			{
322 				((fnc_Color)callBackTable[34])(userData,
323 					*reinterpret_cast<const rgb_color *>(data)); /* color */
324 				break;
325 			}
326 
327 			case B_PIC_SET_STIPLE_PATTERN:
328 			{
329 				((fnc_Pattern)callBackTable[35])(userData,
330 					*reinterpret_cast<const pattern *>(data)); /* pattern */
331 				break;
332 			}
333 
334 			case B_PIC_SET_SCALE:
335 			{
336 				((fnc_f)callBackTable[36])(userData,
337 					*reinterpret_cast<const float *>(data)); /* scale */
338 				break;
339 			}
340 
341 			case B_PIC_SET_FONT_FAMILY:
342 			{
343 				debugger("B_PIC_SET_FONT_FAMILY"); // TODO: is this unused?
344 				((fnc_Pc)callBackTable[37])(userData,
345 					reinterpret_cast<const char *>(data)); /* string */
346 				break;
347 			}
348 
349 			case B_PIC_SET_FONT_STYLE:
350 			{
351 				debugger("B_PIC_SET_FONT_STYLE"); // TODO: is this unused?
352 				((fnc_Pc)callBackTable[38])(userData,
353 					reinterpret_cast<const char *>(data)); /* string */
354 				break;
355 			}
356 
357 			case B_PIC_SET_FONT_SPACING:
358 			{
359 				((fnc_i)callBackTable[39])(userData,
360 					*reinterpret_cast<const int32 *>(data)); /* spacing */
361 				break;
362 			}
363 
364 			case B_PIC_SET_FONT_SIZE:
365 			{
366 				((fnc_f)callBackTable[40])(userData,
367 					*reinterpret_cast<const float *>(data)); /* size */
368 				break;
369 			}
370 
371 			case B_PIC_SET_FONT_ROTATE:
372 			{
373 				((fnc_f)callBackTable[41])(userData,
374 					*reinterpret_cast<const float *>(data)); /* rotation */
375 				break;
376 			}
377 
378 			case B_PIC_SET_FONT_ENCODING:
379 			{
380 				((fnc_i)callBackTable[42])(userData,
381 					*reinterpret_cast<const int32 *>(data)); /* encoding */
382 				break;
383 			}
384 
385 			case B_PIC_SET_FONT_FLAGS:
386 			{
387 				((fnc_i)callBackTable[43])(userData,
388 					*reinterpret_cast<const int32 *>(data)); /* flags */
389 				break;
390 			}
391 
392 			case B_PIC_SET_FONT_SHEAR:
393 			{
394 				((fnc_f)callBackTable[44])(userData,
395 					*reinterpret_cast<const float *>(data)); /* shear */
396 				break;
397 			}
398 
399 			case B_PIC_SET_FONT_FACE:
400 			{
401 				((fnc_i)callBackTable[46])(userData,
402 					*reinterpret_cast<const int32 *>(data)); /* flags */
403 				break;
404 			}
405 
406 			// TODO: Looks like R5 function table only exports 47 functions...
407 			// I added this here as a temporary workaround, because there seems to be
408 			// no room for this op, although it's obviously implemented in some way...
409 			case B_PIC_SET_BLENDING_MODE:
410 			{
411 				((fnc_ss)callBackTable[47])(userData,
412 					*reinterpret_cast<const int16 *>(data), /* alphaSrcMode */
413 					*reinterpret_cast<const int16 *>(data + sizeof(int16))); /* alphaFncMode */
414 				break;
415 			}
416 
417 			default:
418 				break;
419 		}
420 
421 		pos += size;
422 		data += size;
423 
424 		// TODO: what if too much was read, should we return B_ERROR?
425 	}
426 
427 	return B_OK;
428 }
429