xref: /haiku/src/kits/interface/PicturePlayer.cpp (revision 3cb015b1ee509d69c643506e8ff573808c86dcfc)
1 /*
2  * Copyright 2001-2006, 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  */
9 
10 /**	PicturePlayer is used to create and play picture data. */
11 
12 #include <stdio.h>
13 
14 #include <PicturePlayer.h>
15 #include <PictureProtocol.h>
16 
17 #include <Shape.h>
18 
19 typedef void (*fnc)(void*);
20 typedef void (*fnc_BPoint)(void*, BPoint);
21 typedef void (*fnc_BPointBPoint)(void*, BPoint, BPoint);
22 typedef void (*fnc_BRect)(void*, BRect);
23 typedef void (*fnc_BRectBPoint)(void*, BRect, BPoint);
24 typedef void (*fnc_PBPoint)(void*, BPoint*);
25 typedef void (*fnc_i)(void*, int32);
26 typedef void (*fnc_iPBPointb)(void*, int32, BPoint*, bool);
27 typedef void (*fnc_iPBPoint)(void*, int32, BPoint*);
28 typedef void (*fnc_Pc)(void*, char*);
29 typedef void (*fnc_Pcff)(void*, char*, float, float);
30 typedef void (*fnc_BPointBPointff)(void*, BPoint, BPoint, float, float);
31 typedef void (*fnc_s)(void*, int16);
32 typedef void (*fnc_ssf)(void*, int16, int16, float);
33 typedef void (*fnc_f)(void*, float);
34 typedef void (*fnc_Color)(void*, rgb_color);
35 typedef void (*fnc_Pattern)(void*, pattern);
36 typedef void (*fnc_ss)(void *, int16, int16);
37 typedef void (*fnc_PBRecti)(void*, BRect*, int32);
38 typedef void (*fnc_DrawPixels)(void *, BRect, BRect, int32, int32, int32,
39 							   int32, int32, void*);
40 typedef void (*fnc_BShape)(void*, BShape*);
41 
42 
43 PicturePlayer::PicturePlayer(const void *data, int32 size, BList *pictures)
44 	:	fData(data, size),
45 		fPictures(pictures)
46 {
47 }
48 
49 
50 PicturePlayer::~PicturePlayer()
51 {
52 }
53 
54 
55 int16
56 PicturePlayer::GetOp()
57 {
58 	int16 data;
59 
60 	fData.Read(&data, sizeof(int16));
61 
62 	return data;
63 }
64 
65 
66 int8
67 PicturePlayer::GetInt8()
68 {
69 	int8 data;
70 
71 	fData.Read(&data, sizeof(int8));
72 
73 	return data;
74 }
75 
76 
77 int16
78 PicturePlayer::GetInt16()
79 {
80 	int16 data;
81 
82 	fData.Read(&data, sizeof(int16));
83 
84 	return data;
85 }
86 
87 
88 int32
89 PicturePlayer::GetInt32()
90 {
91 	int32 data;
92 
93 	fData.Read(&data, sizeof(int32));
94 
95 	return data;
96 }
97 
98 
99 float
100 PicturePlayer::GetFloat()
101 {
102 	float data;
103 
104 	fData.Read(&data, sizeof(float));
105 
106 	return data;
107 }
108 
109 
110 BPoint
111 PicturePlayer::GetCoord()
112 {
113 	BPoint data;
114 
115 	fData.Read(&data, sizeof(BPoint));
116 
117 	return data;
118 }
119 
120 
121 BRect
122 PicturePlayer::GetRect()
123 {
124 	BRect data;
125 
126 	fData.Read(&data, sizeof(BRect));
127 
128 	return data;
129 }
130 
131 
132 rgb_color
133 PicturePlayer::GetColor()
134 {
135 	rgb_color data;
136 
137 	fData.Read(&data, sizeof(rgb_color));
138 
139 	return data;
140 }
141 
142 
143 void
144 PicturePlayer::GetData(void *data, int32 size)
145 {
146 	fData.Read(data, size);
147 }
148 
149 
150 status_t
151 PicturePlayer::Play(void **callBackTable, int32 tableEntries, void *userData)
152 {
153 	// TODO: we should probably check if the functions in the table are not NULL
154 	//       before calling them.
155 
156 	// lenght of the stream
157 	size_t length = fData.Seek(0, SEEK_END);
158 	fData.Seek(0, SEEK_SET);
159 
160 	while (fData.Position() < length) {
161 		int16 op = GetOp();
162 		int32 size = GetInt32();
163 		off_t pos = fData.Position();
164 
165 		switch (op) {
166 			case B_PIC_MOVE_PEN_BY:
167 			{
168 				BPoint where = GetCoord();
169 				((fnc_BPoint)callBackTable[1])(userData, where);
170 				break;
171 			}
172 
173 			case B_PIC_STROKE_LINE:
174 			{
175 				BPoint start = GetCoord();
176 				BPoint end = GetCoord();
177 				((fnc_BPointBPoint)callBackTable[2])(userData, start, end);
178 				break;
179 			}
180 
181 			case B_PIC_STROKE_RECT:
182 			{
183 				BRect rect = GetRect();
184 				((fnc_BRect)callBackTable[3])(userData, rect);
185 				break;
186 			}
187 
188 			case B_PIC_FILL_RECT:
189 			{
190 				BRect rect = GetRect();
191 				((fnc_BRect)callBackTable[4])(userData, rect);
192 				break;
193 			}
194 
195 			case B_PIC_STROKE_ROUND_RECT:
196 			{
197 				BRect rect = GetRect();
198 				BPoint radii = GetCoord();
199 				((fnc_BRectBPoint)callBackTable[5])(userData, rect, radii);
200 				break;
201 			}
202 
203 			case B_PIC_FILL_ROUND_RECT:
204 			{
205 				BRect rect = GetRect();
206 				BPoint radii = GetCoord();
207 				((fnc_BRectBPoint)callBackTable[6])(userData, rect, radii);
208 				break;
209 			}
210 
211 			case B_PIC_STROKE_BEZIER:
212 			{
213 				BPoint control[4];
214 				GetData(control, sizeof(control));
215 				((fnc_PBPoint)callBackTable[7])(userData, control);
216 				break;
217 			}
218 
219 			case B_PIC_FILL_BEZIER:
220 			{
221 				BPoint control[4];
222 				GetData(control, sizeof(control));
223 				((fnc_PBPoint)callBackTable[8])(userData, control);
224 				break;
225 			}
226 
227 			case B_PIC_STROKE_ARC:
228 			{
229 				BPoint center = GetCoord();
230 				BPoint radii = GetCoord();
231 				float startTheta = GetFloat();
232 				float arcTheta = GetFloat();
233 				((fnc_BPointBPointff)callBackTable[9])(userData, center, radii,
234 					startTheta, arcTheta);
235 				break;
236 			}
237 
238 			case B_PIC_FILL_ARC:
239 			{
240 				BPoint center = GetCoord();
241 				BPoint radii = GetCoord();
242 				float startTheta = GetFloat();
243 				float arcTheta = GetFloat();
244 				((fnc_BPointBPointff)callBackTable[10])(userData, center, radii,
245 					startTheta, arcTheta);
246 				break;
247 			}
248 
249 			case B_PIC_STROKE_ELLIPSE:
250 			{
251 				BRect rect = GetRect();
252 				BPoint radii((rect.Width() + 1) / 2.0f, (rect.Height() + 1) / 2.0f);
253 				BPoint center = rect.LeftTop() + radii;
254 				((fnc_BPointBPoint)callBackTable[11])(userData, center, radii);
255 				break;
256 			}
257 
258 			case B_PIC_FILL_ELLIPSE:
259 			{
260 				BRect rect = GetRect();
261 				BPoint radii((rect.Width() + 1) / 2.0f, (rect.Height() + 1) / 2.0f);
262 				BPoint center = rect.LeftTop() + radii;
263 				((fnc_BPointBPoint)callBackTable[12])(userData, center, radii);
264 				break;
265 			}
266 
267 			case B_PIC_STROKE_POLYGON:
268 			{
269 				int32 numPoints = GetInt32();
270 				BPoint *points = new BPoint[numPoints];
271 				GetData(points, numPoints * sizeof(BPoint));
272 				bool isClosed = (bool)GetInt8();
273 				((fnc_iPBPointb)callBackTable[13])(userData, numPoints, points, isClosed);
274 				delete[] points;
275 				break;
276 			}
277 
278 			case B_PIC_FILL_POLYGON:
279 			{
280 				int32 numPoints = GetInt32();
281 				BPoint *points = new BPoint[numPoints];
282 				GetData(points, numPoints * sizeof(BPoint));
283 				((fnc_iPBPoint)callBackTable[14])(userData, numPoints, points);
284 				delete[] points;
285 				break;
286 			}
287 
288 			case B_PIC_STROKE_SHAPE:
289 			case B_PIC_FILL_SHAPE:
290 			{
291 				int32 opCount = GetInt32();
292 				uint32 *opList = new uint32[opCount];
293 				GetData(opList, opCount * sizeof(uint32));
294 
295 				int32 ptCount = GetInt32();
296 				BPoint *ptList = new BPoint[ptCount];
297 				GetData(ptList, ptCount * sizeof(BPoint));
298 
299 				BShape shape;
300 				shape.SetData(opCount, ptCount, opList, ptList);
301 
302 				const int32 tableIndex = (op == B_PIC_STROKE_SHAPE) ? 15 : 16;
303 				((fnc_BShape)callBackTable[tableIndex])(userData, &shape);
304 
305 				delete[] opList;
306 				delete[] ptList;
307 
308 				break;
309 			}
310 
311 			case B_PIC_DRAW_STRING:
312 			{
313 				int32 len = GetInt32();
314 				char *string = new char[len + 1];
315 				GetData(string, len);
316 				string[len] = '\0';
317 				float deltax = GetFloat();
318 				float deltay = GetFloat();
319 				((fnc_Pcff)callBackTable[17])(userData, string, deltax, deltay);
320 				delete[] string;
321 				break;
322 			}
323 
324 			case B_PIC_DRAW_PIXELS:
325 			{
326 				BRect src = GetRect();
327 				BRect dest = GetRect();
328 				int32 width = GetInt32();
329 				int32 height = GetInt32();
330 				int32 bytesPerRow = GetInt32();
331 				int32 pixelFormat = GetInt32();
332 				int32 flags = GetInt32();
333 				int32 length = GetInt32();
334 				char *data = new char[length];
335 				GetData(data, length);
336 				((fnc_DrawPixels)callBackTable[18])(userData, src, dest,
337 					width, height, bytesPerRow, pixelFormat, flags, data);
338 				delete[] data;
339 				break;
340 			}
341 
342 			case B_PIC_DRAW_PICTURE:
343 			{
344 				break;
345 			}
346 
347 			case B_PIC_SET_CLIPPING_RECTS:
348 			{
349 				break;
350 			}
351 
352 			case B_PIC_CLEAR_CLIPPING_RECTS:
353 			{
354 				((fnc_PBRecti)callBackTable[20])(userData, NULL, 0);
355 				break;
356 			}
357 
358 			case B_PIC_CLIP_TO_PICTURE:
359 			{
360 				break;
361 			}
362 
363 			case B_PIC_PUSH_STATE:
364 			{
365 				((fnc)callBackTable[22])(userData);
366 				break;
367 			}
368 
369 			case B_PIC_POP_STATE:
370 			{
371 				((fnc)callBackTable[23])(userData);
372 				break;
373 			}
374 
375 			case B_PIC_ENTER_STATE_CHANGE:
376 			{
377 				((fnc)callBackTable[24])(userData);
378 				break;
379 			}
380 
381 			case B_PIC_ENTER_FONT_STATE:
382 			{
383 				((fnc)callBackTable[26])(userData);
384 				break;
385 			}
386 
387 			case B_PIC_SET_ORIGIN:
388 			{
389 				BPoint pt = GetCoord();
390 				((fnc_BPoint)callBackTable[28])(userData, pt);
391 				break;
392 			}
393 
394 			case B_PIC_SET_PEN_LOCATION:
395 			{
396 				BPoint pt = GetCoord();
397 				((fnc_BPoint)callBackTable[29])(userData, pt);
398 				break;
399 			}
400 
401 			case B_PIC_SET_DRAWING_MODE:
402 			{
403 				int16 mode = GetInt16();
404 				((fnc_s)callBackTable[30])(userData, mode);
405 				break;
406 			}
407 
408 			case B_PIC_SET_LINE_MODE:
409 			{
410 				int16 capMode = GetInt16();
411 				int16 joinMode = GetInt16();
412 				float miterLimit = GetFloat();
413 				((fnc_ssf)callBackTable[31])(userData, capMode, joinMode, miterLimit);
414 				break;
415 			}
416 
417 			case B_PIC_SET_PEN_SIZE:
418 			{
419 				float size = GetFloat();
420 				((fnc_f)callBackTable[32])(userData, size);
421 				break;
422 			}
423 
424 			case B_PIC_SET_FORE_COLOR:
425 			{
426 				rgb_color color = GetColor();
427 				((fnc_Color)callBackTable[33])(userData, color);
428 				break;
429 			}
430 
431 			case B_PIC_SET_BACK_COLOR:
432 			{
433 				rgb_color color = GetColor();
434 				((fnc_Color)callBackTable[34])(userData, color);
435 				break;
436 			}
437 
438 			case B_PIC_SET_STIPLE_PATTERN:
439 			{
440 				pattern p;
441 				GetData(&p, sizeof(p));
442 				((fnc_Pattern)callBackTable[35])(userData, p);
443 				break;
444 			}
445 
446 			case B_PIC_SET_SCALE:
447 			{
448 				float scale = GetFloat();
449 				((fnc_f)callBackTable[36])(userData, scale);
450 				break;
451 			}
452 
453 			case B_PIC_SET_FONT_FAMILY:
454 			{
455 				int32 len = GetInt32();
456 				char *string = new char[len + 1];
457 				GetData(string, len);
458 				string[len] = '\0';
459 				((fnc_Pc)callBackTable[37])(userData, string);
460 				delete[] string;
461 				break;
462 			}
463 
464 			case B_PIC_SET_FONT_STYLE:
465 			{
466 				int32 len = GetInt32();
467 				char *string = new char[len + 1];
468 				GetData(string, len);
469 				string[len] = '\0';
470 				((fnc_Pc)callBackTable[38])(userData, string);
471 				delete[] string;
472 				break;
473 			}
474 
475 			case B_PIC_SET_FONT_SPACING:
476 			{
477 				int32 spacing = GetInt32();
478 				((fnc_i)callBackTable[39])(userData, spacing);
479 				break;
480 			}
481 
482 			case B_PIC_SET_FONT_SIZE:
483 			{
484 				float size = GetFloat();
485 				((fnc_f)callBackTable[40])(userData, size);
486 				break;
487 			}
488 
489 			case B_PIC_SET_FONT_ROTATE:
490 			{
491 				float rotation = GetFloat();
492 				((fnc_f)callBackTable[41])(userData, rotation);
493 				break;
494 			}
495 
496 			case B_PIC_SET_FONT_ENCODING:
497 			{
498 				int32 encoding = GetInt32();
499 				((fnc_i)callBackTable[42])(userData, encoding);
500 				break;
501 			}
502 
503 			case B_PIC_SET_FONT_FLAGS:
504 			{
505 				int32 flags = GetInt32();
506 				((fnc_i)callBackTable[43])(userData, flags);
507 				break;
508 			}
509 
510 			case B_PIC_SET_FONT_SHEAR:
511 			{
512 				float shear = GetFloat();
513 				((fnc_f)callBackTable[44])(userData, shear);
514 				break;
515 			}
516 
517 			case B_PIC_SET_FONT_FACE:
518 			{
519 				int32 flags = GetInt32();
520 				((fnc_i)callBackTable[46])(userData, flags);
521 				break;
522 			}
523 			// TODO: Looks like R5 function table only exports 47 functions...
524 			// I added this here as a temporary workaround, because there seems to be
525 			// no room for this op, although it's obviously implemented in some way...
526 			case B_PIC_SET_BLENDING_MODE:
527 			{
528 				int16 alphaSrcMode = GetInt16();
529 				int16 alphaFncMode = GetInt16();
530 				((fnc_ss)callBackTable[47])(userData, alphaSrcMode, alphaFncMode);
531 				break;
532 			}
533 
534 			default:
535 				break;
536 		}
537 
538 		// If we didn't read enough bytes, skip them. This is not a error
539 		// since the instructions can change over time.
540 		// Don't do that for state change ops, they don't have a fixed size
541 		if (op != B_PIC_ENTER_STATE_CHANGE && op != B_PIC_ENTER_FONT_STATE && fData.Position() - pos < size)
542 			fData.Seek(size - (fData.Position() - pos), SEEK_CUR);
543 
544 		// TODO: what if too much was read, should we return B_ERROR?
545 	}
546 
547 	return B_OK;
548 }
549