tcp: Fix 64 bit build with debugging features enabled.
[haiku.git] / src / kits / interface / PicturePlayer.cpp
blobf337bc18962598251b85ac11f176d46a5bd5d16c
1 /*
2 * Copyright 2001-2007, Haiku Inc.
3 * Distributed under the terms of the MIT License.
5 * Authors:
6 * Marc Flerackers (mflerackers@androme.be)
7 * Stefano Ceccherini (stefano.ceccherini@gmail.com)
8 * Marcus Overhagen (marcus@overhagen.de)
9 */
11 /** PicturePlayer is used to play picture data. */
13 #include <PicturePlayer.h>
15 #include <stdio.h>
16 #include <string.h>
18 #include <AffineTransform.h>
19 #include <PictureProtocol.h>
20 #include <Shape.h>
23 using BPrivate::PicturePlayer;
26 typedef void (*fnc)(void*);
27 typedef void (*fnc_BPoint)(void*, BPoint);
28 typedef void (*fnc_BPointBPoint)(void*, BPoint, BPoint);
29 typedef void (*fnc_BRect)(void*, BRect);
30 typedef void (*fnc_BRectBPoint)(void*, BRect, BPoint);
31 typedef void (*fnc_PBPoint)(void*, const BPoint*);
32 typedef void (*fnc_i)(void*, int32);
33 typedef void (*fnc_iPBPointb)(void*, int32, const BPoint*, bool);
34 typedef void (*fnc_iPBPoint)(void*, int32, const BPoint*);
35 typedef void (*fnc_Pc)(void*, const char*);
36 typedef void (*fnc_Pcff)(void*, const char*, float, float);
37 typedef void (*fnc_BPointBPointff)(void*, BPoint, BPoint, float, float);
38 typedef void (*fnc_s)(void*, int16);
39 typedef void (*fnc_ssf)(void*, int16, int16, float);
40 typedef void (*fnc_f)(void*, float);
41 typedef void (*fnc_Color)(void*, rgb_color);
42 typedef void (*fnc_Pattern)(void*, pattern);
43 typedef void (*fnc_ss)(void *, int16, int16);
44 typedef void (*fnc_PBRecti)(void*, const BRect*, uint32);
45 typedef void (*fnc_DrawPixels)(void *, BRect, BRect, int32, int32, int32,
46 int32, int32, const void *);
47 typedef void (*fnc_DrawPicture)(void *, BPoint, int32);
48 typedef void (*fnc_BShape)(void*, BShape*);
49 typedef void (*fnc_BAffineTransform)(void*, BAffineTransform);
52 static void
53 nop()
58 #if DEBUG > 1
59 static const char *
60 PictureOpToString(int op)
62 #define RETURN_STRING(x) case x: return #x
64 switch(op) {
65 RETURN_STRING(B_PIC_MOVE_PEN_BY);
66 RETURN_STRING(B_PIC_STROKE_LINE);
67 RETURN_STRING(B_PIC_STROKE_RECT);
68 RETURN_STRING(B_PIC_FILL_RECT);
69 RETURN_STRING(B_PIC_STROKE_ROUND_RECT);
70 RETURN_STRING(B_PIC_FILL_ROUND_RECT);
71 RETURN_STRING(B_PIC_STROKE_BEZIER);
72 RETURN_STRING(B_PIC_FILL_BEZIER);
73 RETURN_STRING(B_PIC_STROKE_POLYGON);
74 RETURN_STRING(B_PIC_FILL_POLYGON);
75 RETURN_STRING(B_PIC_STROKE_SHAPE);
76 RETURN_STRING(B_PIC_FILL_SHAPE);
77 RETURN_STRING(B_PIC_DRAW_STRING);
78 RETURN_STRING(B_PIC_DRAW_PIXELS);
79 RETURN_STRING(B_PIC_DRAW_PICTURE);
80 RETURN_STRING(B_PIC_STROKE_ARC);
81 RETURN_STRING(B_PIC_FILL_ARC);
82 RETURN_STRING(B_PIC_STROKE_ELLIPSE);
83 RETURN_STRING(B_PIC_FILL_ELLIPSE);
85 RETURN_STRING(B_PIC_ENTER_STATE_CHANGE);
86 RETURN_STRING(B_PIC_SET_CLIPPING_RECTS);
87 RETURN_STRING(B_PIC_CLIP_TO_PICTURE);
88 RETURN_STRING(B_PIC_PUSH_STATE);
89 RETURN_STRING(B_PIC_POP_STATE);
90 RETURN_STRING(B_PIC_CLEAR_CLIPPING_RECTS);
92 RETURN_STRING(B_PIC_SET_ORIGIN);
93 RETURN_STRING(B_PIC_SET_PEN_LOCATION);
94 RETURN_STRING(B_PIC_SET_DRAWING_MODE);
95 RETURN_STRING(B_PIC_SET_LINE_MODE);
96 RETURN_STRING(B_PIC_SET_PEN_SIZE);
97 RETURN_STRING(B_PIC_SET_SCALE);
98 RETURN_STRING(B_PIC_SET_TRANSFORM);
99 RETURN_STRING(B_PIC_SET_FORE_COLOR);
100 RETURN_STRING(B_PIC_SET_BACK_COLOR);
101 RETURN_STRING(B_PIC_SET_STIPLE_PATTERN);
102 RETURN_STRING(B_PIC_ENTER_FONT_STATE);
103 RETURN_STRING(B_PIC_SET_BLENDING_MODE);
104 RETURN_STRING(B_PIC_SET_FONT_FAMILY);
105 RETURN_STRING(B_PIC_SET_FONT_STYLE);
106 RETURN_STRING(B_PIC_SET_FONT_SPACING);
107 RETURN_STRING(B_PIC_SET_FONT_ENCODING);
108 RETURN_STRING(B_PIC_SET_FONT_FLAGS);
109 RETURN_STRING(B_PIC_SET_FONT_SIZE);
110 RETURN_STRING(B_PIC_SET_FONT_ROTATE);
111 RETURN_STRING(B_PIC_SET_FONT_SHEAR);
112 RETURN_STRING(B_PIC_SET_FONT_BPP);
113 RETURN_STRING(B_PIC_SET_FONT_FACE);
114 default: return "Unknown op";
116 #undef RETURN_STRING
118 #endif
121 PicturePlayer::PicturePlayer(const void *data, size_t size, BList *pictures)
122 : fData(data),
123 fSize(size),
124 fPictures(pictures)
129 PicturePlayer::~PicturePlayer()
134 status_t
135 PicturePlayer::Play(void **callBackTable, int32 tableEntries, void *userData)
137 // We don't check if the functions in the table are NULL, but we
138 // check the tableEntries to see if the table is big enough.
139 // If an application supplies the wrong size or an invalid pointer,
140 // it's its own fault.
141 #if DEBUG
142 FILE *file = fopen("/var/log/PicturePlayer.log", "a");
143 fprintf(file, "Start rendering BPicture...\n");
144 bigtime_t startTime = system_time();
145 int32 numOps = 0;
146 #endif
147 // If the caller supplied a function table smaller than needed,
148 // we use our dummy table, and copy the supported ops from the supplied one.
149 void **functionTable = callBackTable;
150 void *dummyTable[kOpsTableSize] = {
151 (void *)nop, (void *)nop, (void *)nop, (void *)nop,
152 (void *)nop, (void *)nop, (void *)nop, (void *)nop,
153 (void *)nop, (void *)nop, (void *)nop, (void *)nop,
154 (void *)nop, (void *)nop, (void *)nop, (void *)nop,
155 (void *)nop, (void *)nop, (void *)nop, (void *)nop,
156 (void *)nop, (void *)nop, (void *)nop, (void *)nop,
157 (void *)nop, (void *)nop, (void *)nop, (void *)nop,
158 (void *)nop, (void *)nop, (void *)nop, (void *)nop,
159 (void *)nop, (void *)nop, (void *)nop, (void *)nop,
160 (void *)nop, (void *)nop, (void *)nop, (void *)nop,
161 (void *)nop, (void *)nop, (void *)nop, (void *)nop,
162 (void *)nop, (void *)nop, (void *)nop, (void *)nop
165 if ((uint32)tableEntries < kOpsTableSize) {
166 #if DEBUG
167 fprintf(file, "PicturePlayer: A smaller than needed function table was supplied.\n");
168 #endif
169 functionTable = dummyTable;
170 memcpy(functionTable, callBackTable, tableEntries * sizeof(void *));
173 const char *data = reinterpret_cast<const char *>(fData);
174 size_t pos = 0;
176 int32 fontStateBlockSize = -1;
177 int32 stateBlockSize = -1;
179 while ((pos + 6) <= fSize) {
180 int16 op = *reinterpret_cast<const int16 *>(data);
181 int32 size = *reinterpret_cast<const int32 *>(data + 2);
182 pos += 6;
183 data += 6;
185 if (pos + size > fSize)
186 debugger("PicturePlayer::Play: buffer overrun\n");
188 #if DEBUG > 1
189 bigtime_t startOpTime = system_time();
190 fprintf(file, "Op %s ", PictureOpToString(op));
191 #endif
192 switch (op) {
193 case B_PIC_MOVE_PEN_BY:
195 ((fnc_BPoint)functionTable[1])(userData,
196 *reinterpret_cast<const BPoint *>(data)); /* where */
197 break;
200 case B_PIC_STROKE_LINE:
202 ((fnc_BPointBPoint)functionTable[2])(userData,
203 *reinterpret_cast<const BPoint *>(data), /* start */
204 *reinterpret_cast<const BPoint *>(data + sizeof(BPoint))); /* end */
205 break;
208 case B_PIC_STROKE_RECT:
210 ((fnc_BRect)functionTable[3])(userData,
211 *reinterpret_cast<const BRect *>(data)); /* rect */
212 break;
215 case B_PIC_FILL_RECT:
217 ((fnc_BRect)functionTable[4])(userData,
218 *reinterpret_cast<const BRect *>(data)); /* rect */
219 break;
222 case B_PIC_STROKE_ROUND_RECT:
224 ((fnc_BRectBPoint)functionTable[5])(userData,
225 *reinterpret_cast<const BRect *>(data), /* rect */
226 *reinterpret_cast<const BPoint *>(data + sizeof(BRect))); /* radii */
227 break;
230 case B_PIC_FILL_ROUND_RECT:
232 ((fnc_BRectBPoint)functionTable[6])(userData,
233 *reinterpret_cast<const BRect *>(data), /* rect */
234 *reinterpret_cast<const BPoint *>(data + sizeof(BRect))); /* radii */
235 break;
238 case B_PIC_STROKE_BEZIER:
240 ((fnc_PBPoint)functionTable[7])(userData,
241 reinterpret_cast<const BPoint *>(data));
242 break;
245 case B_PIC_FILL_BEZIER:
247 ((fnc_PBPoint)functionTable[8])(userData,
248 reinterpret_cast<const BPoint *>(data));
249 break;
252 case B_PIC_STROKE_ARC:
254 ((fnc_BPointBPointff)functionTable[9])(userData,
255 *reinterpret_cast<const BPoint *>(data), /* center */
256 *reinterpret_cast<const BPoint *>(data + sizeof(BPoint)), /* radii */
257 *reinterpret_cast<const float *>(data + 2 * sizeof(BPoint)), /* startTheta */
258 *reinterpret_cast<const float *>(data + 2 * sizeof(BPoint) + sizeof(float))); /* arcTheta */
259 break;
262 case B_PIC_FILL_ARC:
264 ((fnc_BPointBPointff)functionTable[10])(userData,
265 *reinterpret_cast<const BPoint *>(data), /* center */
266 *reinterpret_cast<const BPoint *>(data + sizeof(BPoint)), /* radii */
267 *reinterpret_cast<const float *>(data + 2 * sizeof(BPoint)), /* startTheta */
268 *reinterpret_cast<const float *>(data + 2 * sizeof(BPoint) + sizeof(float))); /* arcTheta */
269 break;
272 case B_PIC_STROKE_ELLIPSE:
274 const BRect *rect = reinterpret_cast<const BRect *>(data);
275 BPoint radii((rect->Width() + 1) / 2.0f, (rect->Height() + 1) / 2.0f);
276 BPoint center = rect->LeftTop() + radii;
277 ((fnc_BPointBPoint)functionTable[11])(userData, center, radii);
278 break;
281 case B_PIC_FILL_ELLIPSE:
283 const BRect *rect = reinterpret_cast<const BRect *>(data);
284 BPoint radii((rect->Width() + 1) / 2.0f, (rect->Height() + 1) / 2.0f);
285 BPoint center = rect->LeftTop() + radii;
286 ((fnc_BPointBPoint)functionTable[12])(userData, center, radii);
287 break;
290 case B_PIC_STROKE_POLYGON:
292 int32 numPoints = *reinterpret_cast<const int32 *>(data);
293 ((fnc_iPBPointb)functionTable[13])(userData,
294 numPoints,
295 reinterpret_cast<const BPoint *>(data + sizeof(int32)), /* points */
296 *reinterpret_cast<const uint8 *>(data + sizeof(int32) + numPoints * sizeof(BPoint))); /* is-closed */
297 break;
300 case B_PIC_FILL_POLYGON:
302 ((fnc_iPBPoint)functionTable[14])(userData,
303 *reinterpret_cast<const int32 *>(data), /* numPoints */
304 reinterpret_cast<const BPoint *>(data + sizeof(int32))); /* points */
305 break;
308 case B_PIC_STROKE_SHAPE:
309 case B_PIC_FILL_SHAPE:
311 const bool stroke = (op == B_PIC_STROKE_SHAPE);
312 int32 opCount = *reinterpret_cast<const int32 *>(data);
313 int32 ptCount = *reinterpret_cast<const int32 *>(data + sizeof(int32));
314 const uint32 *opList = reinterpret_cast<const uint32 *>(data + 2 * sizeof(int32));
315 const BPoint *ptList = reinterpret_cast<const BPoint *>(data + 2 * sizeof(int32) + opCount * sizeof(uint32));
317 // TODO: remove BShape data copying
318 BShape shape;
319 shape.SetData(opCount, ptCount, opList, ptList);
321 const int32 tableIndex = stroke ? 15 : 16;
322 ((fnc_BShape)functionTable[tableIndex])(userData, &shape);
323 break;
326 case B_PIC_DRAW_STRING:
328 ((fnc_Pcff)functionTable[17])(userData,
329 reinterpret_cast<const char *>(data + 2 * sizeof(float)), /* string */
330 *reinterpret_cast<const float *>(data), /* escapement.space */
331 *reinterpret_cast<const float *>(data + sizeof(float))); /* escapement.nonspace */
332 break;
335 case B_PIC_DRAW_PIXELS:
337 ((fnc_DrawPixels)functionTable[18])(userData,
338 *reinterpret_cast<const BRect *>(data), /* src */
339 *reinterpret_cast<const BRect *>(data + 1 * sizeof(BRect)), /* dst */
340 *reinterpret_cast<const int32 *>(data + 2 * sizeof(BRect)), /* width */
341 *reinterpret_cast<const int32 *>(data + 2 * sizeof(BRect) + 1 * sizeof(int32)), /* height */
342 *reinterpret_cast<const int32 *>(data + 2 * sizeof(BRect) + 2 * sizeof(int32)), /* bytesPerRow */
343 *reinterpret_cast<const int32 *>(data + 2 * sizeof(BRect) + 3 * sizeof(int32)), /* pixelFormat */
344 *reinterpret_cast<const int32 *>(data + 2 * sizeof(BRect) + 4 * sizeof(int32)), /* flags */
345 reinterpret_cast<const void *>(data + 2 * sizeof(BRect) + 5 * sizeof(int32))); /* data */
346 break;
349 case B_PIC_DRAW_PICTURE:
351 ((fnc_DrawPicture)functionTable[19])(userData,
352 *reinterpret_cast<const BPoint *>(data),
353 *reinterpret_cast<const int32 *>(data + sizeof(BPoint)));
354 break;
357 case B_PIC_SET_CLIPPING_RECTS:
359 // TODO: Not sure if it's compatible with R5's BPicture version
360 const uint32 numRects = *reinterpret_cast<const uint32 *>(data);
361 const BRect *rects = reinterpret_cast<const BRect *>(data + sizeof(uint32));
362 ((fnc_PBRecti)functionTable[20])(userData, rects, numRects);
364 break;
367 case B_PIC_CLEAR_CLIPPING_RECTS:
369 ((fnc_PBRecti)functionTable[20])(userData, NULL, 0);
370 break;
373 case B_PIC_CLIP_TO_PICTURE:
375 // TODO: Implement
376 break;
379 case B_PIC_PUSH_STATE:
381 ((fnc)functionTable[22])(userData);
382 break;
385 case B_PIC_POP_STATE:
387 ((fnc)functionTable[23])(userData);
388 break;
391 case B_PIC_ENTER_STATE_CHANGE:
393 ((fnc)functionTable[24])(userData);
394 stateBlockSize = size;
395 break;
398 case B_PIC_ENTER_FONT_STATE:
400 ((fnc)functionTable[26])(userData);
401 fontStateBlockSize = size;
402 break;
405 case B_PIC_SET_ORIGIN:
407 ((fnc_BPoint)functionTable[28])(userData,
408 *reinterpret_cast<const BPoint *>(data)); /* origin */
409 break;
412 case B_PIC_SET_PEN_LOCATION:
414 ((fnc_BPoint)functionTable[29])(userData,
415 *reinterpret_cast<const BPoint *>(data)); /* location */
416 break;
419 case B_PIC_SET_DRAWING_MODE:
421 ((fnc_s)functionTable[30])(userData,
422 *reinterpret_cast<const int16 *>(data)); /* mode */
423 break;
426 case B_PIC_SET_LINE_MODE:
428 ((fnc_ssf)functionTable[31])(userData,
429 *reinterpret_cast<const int16 *>(data), /* cap-mode */
430 *reinterpret_cast<const int16 *>(data + 1 * sizeof(int16)), /* join-mode */
431 *reinterpret_cast<const float *>(data + 2 * sizeof(int16))); /* miter-limit */
432 break;
435 case B_PIC_SET_PEN_SIZE:
437 ((fnc_f)functionTable[32])(userData,
438 *reinterpret_cast<const float *>(data)); /* size */
439 break;
442 case B_PIC_SET_FORE_COLOR:
444 ((fnc_Color)functionTable[33])(userData,
445 *reinterpret_cast<const rgb_color *>(data)); /* color */
446 break;
449 case B_PIC_SET_BACK_COLOR:
451 ((fnc_Color)functionTable[34])(userData,
452 *reinterpret_cast<const rgb_color *>(data)); /* color */
453 break;
456 case B_PIC_SET_STIPLE_PATTERN:
458 ((fnc_Pattern)functionTable[35])(userData,
459 *reinterpret_cast<const pattern *>(data)); /* pattern */
460 break;
463 case B_PIC_SET_SCALE:
465 ((fnc_f)functionTable[36])(userData,
466 *reinterpret_cast<const float *>(data)); /* scale */
467 break;
470 case B_PIC_SET_FONT_FAMILY:
472 ((fnc_Pc)functionTable[37])(userData,
473 reinterpret_cast<const char *>(data)); /* string */
474 break;
477 case B_PIC_SET_FONT_STYLE:
479 ((fnc_Pc)functionTable[38])(userData,
480 reinterpret_cast<const char *>(data)); /* string */
481 break;
484 case B_PIC_SET_FONT_SPACING:
486 ((fnc_i)functionTable[39])(userData,
487 *reinterpret_cast<const int32 *>(data)); /* spacing */
488 break;
491 case B_PIC_SET_FONT_SIZE:
493 ((fnc_f)functionTable[40])(userData,
494 *reinterpret_cast<const float *>(data)); /* size */
495 break;
498 case B_PIC_SET_FONT_ROTATE:
500 ((fnc_f)functionTable[41])(userData,
501 *reinterpret_cast<const float *>(data)); /* rotation */
502 break;
505 case B_PIC_SET_FONT_ENCODING:
507 ((fnc_i)functionTable[42])(userData,
508 *reinterpret_cast<const int32 *>(data)); /* encoding */
509 break;
512 case B_PIC_SET_FONT_FLAGS:
514 ((fnc_i)functionTable[43])(userData,
515 *reinterpret_cast<const int32 *>(data)); /* flags */
516 break;
519 case B_PIC_SET_FONT_SHEAR:
521 ((fnc_f)functionTable[44])(userData,
522 *reinterpret_cast<const float *>(data)); /* shear */
523 break;
526 case B_PIC_SET_FONT_FACE:
528 ((fnc_i)functionTable[46])(userData,
529 *reinterpret_cast<const int32 *>(data)); /* flags */
530 break;
533 case B_PIC_SET_BLENDING_MODE:
535 ((fnc_ss)functionTable[47])(userData,
536 *reinterpret_cast<const int16 *>(data), /* alphaSrcMode */
537 *reinterpret_cast<const int16 *>(data + sizeof(int16))); /* alphaFncMode */
538 break;
541 case B_PIC_SET_TRANSFORM:
543 ((fnc_BAffineTransform)functionTable[48])(userData,
544 *reinterpret_cast<const BAffineTransform *>(data));
545 break;
548 default:
549 break;
552 // Skip the already handled block unless it's one of these two,
553 // since they can contain other nested ops.
554 if (op != B_PIC_ENTER_STATE_CHANGE && op != B_PIC_ENTER_FONT_STATE) {
555 pos += size;
556 data += size;
557 if (stateBlockSize > 0)
558 stateBlockSize -= size + 6;
559 if (fontStateBlockSize > 0)
560 fontStateBlockSize -= size + 6;
563 // call the exit_state_change hook if needed
564 if (stateBlockSize == 0) {
565 ((fnc)functionTable[25])(userData);
566 stateBlockSize = -1;
569 // call the exit_font_state hook if needed
570 if (fontStateBlockSize == 0) {
571 ((fnc)functionTable[27])(userData);
572 fontStateBlockSize = -1;
574 #if DEBUG
575 numOps++;
576 #if DEBUG > 1
577 fprintf(file, "executed in %" B_PRId64 " usecs\n", system_time()
578 - startOpTime);
579 #endif
580 #endif
581 // TODO: what if too much was read, should we return B_ERROR?
584 #if DEBUG
585 fprintf(file, "Done! %" B_PRId32 " ops, rendering completed in %"
586 B_PRId64 " usecs.\n", numOps, system_time() - startTime);
587 fclose(file);
588 #endif
589 return B_OK;