1 /*
2 * Copyright 2001-2018, Haiku Inc.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 * Marc Flerackers (mflerackers@androme.be)
7 * Stefano Ceccherini (stefano.ceccherini@gmail.com)
8 * Marcus Overhagen (marcus@overhagen.de)
9 * Stephan Aßmus <superstippi@gmx.de>
10 */
11
12 /** PicturePlayer is used to play picture data. */
13
14 #include <PicturePlayer.h>
15
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <string.h>
19
20 #include <AffineTransform.h>
21 #include <DataIO.h>
22 #include <Gradient.h>
23 #include <PictureProtocol.h>
24 #include <Shape.h>
25 #include <ShapePrivate.h>
26
27 #include <AutoDeleter.h>
28 #include <StackOrHeapArray.h>
29
30
31 using BPrivate::PicturePlayer;
32
33
34 struct adapter_context {
35 void* user_data;
36 void** function_table;
37 };
38
39
40 static void
nop()41 nop()
42 {
43 }
44
45
46 static void
move_pen_by(void * _context,const BPoint & delta)47 move_pen_by(void* _context, const BPoint& delta)
48 {
49 adapter_context* context = reinterpret_cast<adapter_context*>(_context);
50 ((void (*)(void*, BPoint))context->function_table[1])(context->user_data,
51 delta);
52 }
53
54
55 static void
stroke_line(void * _context,const BPoint & start,const BPoint & end)56 stroke_line(void* _context, const BPoint& start, const BPoint& end)
57 {
58 adapter_context* context = reinterpret_cast<adapter_context*>(_context);
59 ((void (*)(void*, BPoint, BPoint))context->function_table[2])(
60 context->user_data, start, end);
61 }
62
63
64 static void
draw_rect(void * _context,const BRect & rect,bool fill)65 draw_rect(void* _context, const BRect& rect, bool fill)
66 {
67 adapter_context* context = reinterpret_cast<adapter_context*>(_context);
68 ((void (*)(void*, BRect))context->function_table[fill ? 4 : 3])(
69 context->user_data, rect);
70 }
71
72
73 static void
draw_round_rect(void * _context,const BRect & rect,const BPoint & radii,bool fill)74 draw_round_rect(void* _context, const BRect& rect, const BPoint& radii,
75 bool fill)
76 {
77 adapter_context* context = reinterpret_cast<adapter_context*>(_context);
78 ((void (*)(void*, BRect, BPoint))context->function_table[fill ? 6 : 5])(
79 context->user_data, rect, radii);
80 }
81
82
83 static void
draw_bezier(void * _context,size_t numPoints,const BPoint _points[],bool fill)84 draw_bezier(void* _context, size_t numPoints, const BPoint _points[], bool fill)
85 {
86 adapter_context* context = reinterpret_cast<adapter_context*>(_context);
87 if (numPoints != 4)
88 return;
89
90 BPoint points[4] = { _points[0], _points[1], _points[2], _points[3] };
91 ((void (*)(void*, BPoint*))context->function_table[fill ? 8 : 7])(
92 context->user_data, points);
93 }
94
95
96 static void
draw_arc(void * _context,const BPoint & center,const BPoint & radii,float startTheta,float arcTheta,bool fill)97 draw_arc(void* _context, const BPoint& center, const BPoint& radii,
98 float startTheta, float arcTheta, bool fill)
99 {
100 adapter_context* context = reinterpret_cast<adapter_context*>(_context);
101 ((void (*)(void*, BPoint, BPoint, float, float))
102 context->function_table[fill ? 10 : 9])(context->user_data, center,
103 radii, startTheta, arcTheta);
104 }
105
106
107 static void
draw_ellipse(void * _context,const BRect & rect,bool fill)108 draw_ellipse(void* _context, const BRect& rect, bool fill)
109 {
110 adapter_context* context = reinterpret_cast<adapter_context*>(_context);
111 BPoint radii((rect.Width() + 1) / 2.0f, (rect.Height() + 1) / 2.0f);
112 BPoint center = rect.LeftTop() + radii;
113 ((void (*)(void*, BPoint, BPoint))
114 context->function_table[fill ? 12 : 11])(context->user_data, center,
115 radii);
116 }
117
118
119 static void
draw_polygon(void * _context,size_t numPoints,const BPoint _points[],bool isClosed,bool fill)120 draw_polygon(void* _context, size_t numPoints, const BPoint _points[],
121 bool isClosed, bool fill)
122 {
123 adapter_context* context = reinterpret_cast<adapter_context*>(_context);
124
125 BStackOrHeapArray<BPoint, 200> points(numPoints);
126 if (!points.IsValid())
127 return;
128
129 memcpy((void*)points, _points, numPoints * sizeof(BPoint));
130
131 ((void (*)(void*, int32, BPoint*, bool))
132 context->function_table[fill ? 14 : 13])(context->user_data, numPoints,
133 points, isClosed);
134 }
135
136
137 static void
draw_shape(void * _context,const BShape & shape,bool fill)138 draw_shape(void* _context, const BShape& shape, bool fill)
139 {
140 adapter_context* context = reinterpret_cast<adapter_context*>(_context);
141 ((void (*)(void*, BShape))context->function_table[fill ? 16 : 15])(
142 context->user_data, shape);
143 }
144
145
146 static void
draw_string(void * _context,const char * _string,size_t length,float deltaSpace,float deltaNonSpace)147 draw_string(void* _context, const char* _string, size_t length,
148 float deltaSpace, float deltaNonSpace)
149 {
150 adapter_context* context = reinterpret_cast<adapter_context*>(_context);
151 char* string = strndup(_string, length);
152
153 ((void (*)(void*, char*, float, float))
154 context->function_table[17])(context->user_data, string, deltaSpace,
155 deltaNonSpace);
156
157 free(string);
158 }
159
160
161 static void
draw_pixels(void * _context,const BRect & src,const BRect & dest,uint32 width,uint32 height,size_t bytesPerRow,color_space pixelFormat,uint32 options,const void * _data,size_t length)162 draw_pixels(void* _context, const BRect& src, const BRect& dest, uint32 width,
163 uint32 height, size_t bytesPerRow, color_space pixelFormat, uint32 options,
164 const void* _data, size_t length)
165 {
166 adapter_context* context = reinterpret_cast<adapter_context*>(_context);
167 void* data = malloc(length);
168 if (data == NULL)
169 return;
170
171 memcpy(data, _data, length);
172
173 ((void (*)(void*, BRect, BRect, int32, int32, int32, int32, int32, void*))
174 context->function_table[18])(context->user_data, src, dest, width,
175 height, bytesPerRow, pixelFormat, options, data);
176
177 free(data);
178 }
179
180
181 static void
draw_picture(void * _context,const BPoint & where,int32 token)182 draw_picture(void* _context, const BPoint& where, int32 token)
183 {
184 adapter_context* context = reinterpret_cast<adapter_context*>(_context);
185 ((void (*)(void*, BPoint, int32))context->function_table[19])(
186 context->user_data, where, token);
187 }
188
189
190 static void
set_clipping_rects(void * _context,size_t numRects,const BRect _rects[])191 set_clipping_rects(void* _context, size_t numRects, const BRect _rects[])
192 {
193 adapter_context* context = reinterpret_cast<adapter_context*>(_context);
194
195 // This is rather ugly but works for such a trivial class.
196 BStackOrHeapArray<BRect, 100> rects(numRects);
197 if (!rects.IsValid())
198 return;
199
200 memcpy((void*)rects, _rects, numRects * sizeof(BRect));
201
202 ((void (*)(void*, BRect*, uint32))context->function_table[20])(
203 context->user_data, rects, numRects);
204 }
205
206
207 static void
clip_to_picture(void * _context,int32 token,const BPoint & origin,bool clipToInverse)208 clip_to_picture(void* _context, int32 token, const BPoint& origin,
209 bool clipToInverse)
210 {
211 adapter_context* context = reinterpret_cast<adapter_context*>(_context);
212 ((void (*)(void*, int32, BPoint, bool))context->function_table[21])(
213 context->user_data, token, origin, clipToInverse);
214 }
215
216
217 static void
push_state(void * _context)218 push_state(void* _context)
219 {
220 adapter_context* context = reinterpret_cast<adapter_context*>(_context);
221 ((void (*)(void*))context->function_table[22])(context->user_data);
222 }
223
224
225 static void
pop_state(void * _context)226 pop_state(void* _context)
227 {
228 adapter_context* context = reinterpret_cast<adapter_context*>(_context);
229 ((void (*)(void*))context->function_table[23])(context->user_data);
230 }
231
232
233 static void
enter_state_change(void * _context)234 enter_state_change(void* _context)
235 {
236 adapter_context* context = reinterpret_cast<adapter_context*>(_context);
237 ((void (*)(void*))context->function_table[24])(context->user_data);
238 }
239
240
241 static void
exit_state_change(void * _context)242 exit_state_change(void* _context)
243 {
244 adapter_context* context = reinterpret_cast<adapter_context*>(_context);
245 ((void (*)(void*))context->function_table[25])(context->user_data);
246 }
247
248
249 static void
enter_font_state(void * _context)250 enter_font_state(void* _context)
251 {
252 adapter_context* context = reinterpret_cast<adapter_context*>(_context);
253 ((void (*)(void*))context->function_table[26])(context->user_data);
254 }
255
256
257 static void
exit_font_state(void * _context)258 exit_font_state(void* _context)
259 {
260 adapter_context* context = reinterpret_cast<adapter_context*>(_context);
261 ((void (*)(void*))context->function_table[27])(context->user_data);
262 }
263
264
265 static void
set_origin(void * _context,const BPoint & origin)266 set_origin(void* _context, const BPoint& origin)
267 {
268 adapter_context* context = reinterpret_cast<adapter_context*>(_context);
269 ((void (*)(void*, BPoint))context->function_table[28])(context->user_data,
270 origin);
271 }
272
273
274 static void
set_pen_location(void * _context,const BPoint & penLocation)275 set_pen_location(void* _context, const BPoint& penLocation)
276 {
277 adapter_context* context = reinterpret_cast<adapter_context*>(_context);
278 ((void (*)(void*, BPoint))context->function_table[29])(context->user_data,
279 penLocation);
280 }
281
282
283 static void
set_drawing_mode(void * _context,drawing_mode mode)284 set_drawing_mode(void* _context, drawing_mode mode)
285 {
286 adapter_context* context = reinterpret_cast<adapter_context*>(_context);
287 ((void (*)(void*, drawing_mode))context->function_table[30])(
288 context->user_data, mode);
289 }
290
291
292 static void
set_line_mode(void * _context,cap_mode capMode,join_mode joinMode,float miterLimit)293 set_line_mode(void* _context, cap_mode capMode, join_mode joinMode,
294 float miterLimit)
295 {
296 adapter_context* context = reinterpret_cast<adapter_context*>(_context);
297 ((void (*)(void*, cap_mode, join_mode, float))context->function_table[31])(
298 context->user_data, capMode, joinMode, miterLimit);
299 }
300
301
302 static void
set_pen_size(void * _context,float size)303 set_pen_size(void* _context, float size)
304 {
305 adapter_context* context = reinterpret_cast<adapter_context*>(_context);
306 ((void (*)(void*, float))context->function_table[32])(context->user_data,
307 size);
308 }
309
310
311 static void
set_fore_color(void * _context,const rgb_color & color)312 set_fore_color(void* _context, const rgb_color& color)
313 {
314 adapter_context* context = reinterpret_cast<adapter_context*>(_context);
315 ((void (*)(void*, rgb_color))context->function_table[33])(
316 context->user_data, color);
317 }
318
319
320 static void
set_back_color(void * _context,const rgb_color & color)321 set_back_color(void* _context, const rgb_color& color)
322 {
323 adapter_context* context = reinterpret_cast<adapter_context*>(_context);
324 ((void (*)(void*, rgb_color))context->function_table[34])(
325 context->user_data, color);
326 }
327
328
329 static void
set_stipple_pattern(void * _context,const pattern & stipplePattern)330 set_stipple_pattern(void* _context, const pattern& stipplePattern)
331 {
332 adapter_context* context = reinterpret_cast<adapter_context*>(_context);
333 ((void (*)(void*, pattern))context->function_table[35])(context->user_data,
334 stipplePattern);
335 }
336
337
338 static void
set_scale(void * _context,float scale)339 set_scale(void* _context, float scale)
340 {
341 adapter_context* context = reinterpret_cast<adapter_context*>(_context);
342 ((void (*)(void*, float))context->function_table[36])(context->user_data,
343 scale);
344 }
345
346
347 static void
set_font_family(void * _context,const char * _family,size_t length)348 set_font_family(void* _context, const char* _family, size_t length)
349 {
350 adapter_context* context = reinterpret_cast<adapter_context*>(_context);
351 char* family = strndup(_family, length);
352
353 ((void (*)(void*, char*))context->function_table[37])(context->user_data,
354 family);
355
356 free(family);
357 }
358
359
360 static void
set_font_style(void * _context,const char * _style,size_t length)361 set_font_style(void* _context, const char* _style, size_t length)
362 {
363 adapter_context* context = reinterpret_cast<adapter_context*>(_context);
364 char* style = strndup(_style, length);
365
366 ((void (*)(void*, char*))context->function_table[38])(context->user_data,
367 style);
368
369 free(style);
370 }
371
372
373 static void
set_font_spacing(void * _context,uint8 spacing)374 set_font_spacing(void* _context, uint8 spacing)
375 {
376 adapter_context* context = reinterpret_cast<adapter_context*>(_context);
377 ((void (*)(void*, int32))context->function_table[39])(context->user_data,
378 spacing);
379 }
380
381
382 static void
set_font_size(void * _context,float size)383 set_font_size(void* _context, float size)
384 {
385 adapter_context* context = reinterpret_cast<adapter_context*>(_context);
386 ((void (*)(void*, float))context->function_table[40])(context->user_data,
387 size);
388 }
389
390
391 static void
set_font_rotation(void * _context,float rotation)392 set_font_rotation(void* _context, float rotation)
393 {
394 adapter_context* context = reinterpret_cast<adapter_context*>(_context);
395 ((void (*)(void*, float))context->function_table[41])(context->user_data,
396 rotation);
397 }
398
399
400 static void
set_font_encoding(void * _context,uint8 encoding)401 set_font_encoding(void* _context, uint8 encoding)
402 {
403 adapter_context* context = reinterpret_cast<adapter_context*>(_context);
404 ((void (*)(void*, int32))context->function_table[42])(context->user_data,
405 encoding);
406 }
407
408
409 static void
set_font_flags(void * _context,uint32 flags)410 set_font_flags(void* _context, uint32 flags)
411 {
412 adapter_context* context = reinterpret_cast<adapter_context*>(_context);
413 ((void (*)(void*, int32))context->function_table[43])(context->user_data,
414 flags);
415 }
416
417
418 static void
set_font_shear(void * _context,float shear)419 set_font_shear(void* _context, float shear)
420 {
421 adapter_context* context = reinterpret_cast<adapter_context*>(_context);
422 ((void (*)(void*, float))context->function_table[44])(context->user_data,
423 shear);
424 }
425
426
427 static void
set_font_face(void * _context,uint16 face)428 set_font_face(void* _context, uint16 face)
429 {
430 adapter_context* context = reinterpret_cast<adapter_context*>(_context);
431 ((void (*)(void*, int32))context->function_table[46])(context->user_data,
432 face);
433 }
434
435
436 static void
set_blending_mode(void * _context,source_alpha alphaSrcMode,alpha_function alphaFncMode)437 set_blending_mode(void* _context, source_alpha alphaSrcMode,
438 alpha_function alphaFncMode)
439 {
440 adapter_context* context = reinterpret_cast<adapter_context*>(_context);
441 ((void (*)(void*, source_alpha, alpha_function))
442 context->function_table[47])(context->user_data, alphaSrcMode,
443 alphaFncMode);
444 }
445
446
447 static void
set_transform(void * _context,const BAffineTransform & transform)448 set_transform(void* _context, const BAffineTransform& transform)
449 {
450 adapter_context* context = reinterpret_cast<adapter_context*>(_context);
451 ((void (*)(void*, const BAffineTransform&))
452 context->function_table[48])(context->user_data, transform);
453 }
454
455
456 static void
translate_by(void * _context,double x,double y)457 translate_by(void* _context, double x, double y)
458 {
459 adapter_context* context = reinterpret_cast<adapter_context*>(_context);
460 ((void (*)(void*, double, double))
461 context->function_table[49])(context->user_data, x, y);
462 }
463
464
465 static void
scale_by(void * _context,double x,double y)466 scale_by(void* _context, double x, double y)
467 {
468 adapter_context* context = reinterpret_cast<adapter_context*>(_context);
469 ((void (*)(void*, double, double))
470 context->function_table[50])(context->user_data, x, y);
471 }
472
473
474 static void
rotate_by(void * _context,double angleRadians)475 rotate_by(void* _context, double angleRadians)
476 {
477 adapter_context* context = reinterpret_cast<adapter_context*>(_context);
478 ((void (*)(void*, double))
479 context->function_table[51])(context->user_data, angleRadians);
480 }
481
482
483 static void
blend_layer(void * _context,Layer * layer)484 blend_layer(void* _context, Layer* layer)
485 {
486 adapter_context* context = reinterpret_cast<adapter_context*>(_context);
487 ((void (*)(void*, Layer*))
488 context->function_table[52])(context->user_data, layer);
489 }
490
491
492 static void
clip_to_rect(void * _context,const BRect & rect,bool inverse)493 clip_to_rect(void* _context, const BRect& rect, bool inverse)
494 {
495 adapter_context* context = reinterpret_cast<adapter_context*>(_context);
496 ((void (*)(void*, const BRect&, bool))
497 context->function_table[53])(context->user_data, rect, inverse);
498 }
499
500
501 static void
clip_to_shape(void * _context,int32 opCount,const uint32 opList[],int32 ptCount,const BPoint ptList[],bool inverse)502 clip_to_shape(void* _context, int32 opCount, const uint32 opList[],
503 int32 ptCount, const BPoint ptList[], bool inverse)
504 {
505 adapter_context* context = reinterpret_cast<adapter_context*>(_context);
506 ((void (*)(void*, int32, const uint32*, int32, const BPoint*, bool))
507 context->function_table[54])(context->user_data, opCount, opList,
508 ptCount, ptList, inverse);
509 }
510
511
512 static void
draw_string_locations(void * _context,const char * _string,size_t length,const BPoint * locations,size_t locationCount)513 draw_string_locations(void* _context, const char* _string, size_t length,
514 const BPoint* locations, size_t locationCount)
515 {
516 adapter_context* context = reinterpret_cast<adapter_context*>(_context);
517 char* string = strndup(_string, length);
518
519 ((void (*)(void*, char*, const BPoint*, size_t))
520 context->function_table[55])(context->user_data, string, locations,
521 locationCount);
522
523 free(string);
524 }
525
526
527 static void
draw_rect_gradient(void * _context,const BRect & rect,BGradient & gradient,bool fill)528 draw_rect_gradient(void* _context, const BRect& rect, BGradient& gradient, bool fill)
529 {
530 adapter_context* context = reinterpret_cast<adapter_context*>(_context);
531 ((void (*)(void*, BRect, BGradient&))context->function_table[fill ? 56 : 57])(
532 context->user_data, rect, gradient);
533 }
534
535
536 static void
draw_round_rect_gradient(void * _context,const BRect & rect,const BPoint & radii,BGradient & gradient,bool fill)537 draw_round_rect_gradient(void* _context, const BRect& rect, const BPoint& radii, BGradient& gradient,
538 bool fill)
539 {
540 adapter_context* context = reinterpret_cast<adapter_context*>(_context);
541 ((void (*)(void*, BRect, BPoint, BGradient&))context->function_table[fill ? 58 : 59])(
542 context->user_data, rect, radii, gradient);
543 }
544
545
546 static void
draw_bezier_gradient(void * _context,size_t numPoints,const BPoint _points[],BGradient & gradient,bool fill)547 draw_bezier_gradient(void* _context, size_t numPoints, const BPoint _points[], BGradient& gradient, bool fill)
548 {
549 adapter_context* context = reinterpret_cast<adapter_context*>(_context);
550 if (numPoints != 4)
551 return;
552
553 BPoint points[4] = { _points[0], _points[1], _points[2], _points[3] };
554 ((void (*)(void*, BPoint*, BGradient&))context->function_table[fill ? 60 : 61])(
555 context->user_data, points, gradient);
556 }
557
558
559 static void
draw_arc_gradient(void * _context,const BPoint & center,const BPoint & radii,float startTheta,float arcTheta,BGradient & gradient,bool fill)560 draw_arc_gradient(void* _context, const BPoint& center, const BPoint& radii,
561 float startTheta, float arcTheta, BGradient& gradient, bool fill)
562 {
563 adapter_context* context = reinterpret_cast<adapter_context*>(_context);
564 ((void (*)(void*, BPoint, BPoint, float, float, BGradient&))
565 context->function_table[fill ? 62 : 63])(context->user_data, center,
566 radii, startTheta, arcTheta, gradient);
567 }
568
569
570 static void
draw_ellipse_gradient(void * _context,const BRect & rect,BGradient & gradient,bool fill)571 draw_ellipse_gradient(void* _context, const BRect& rect, BGradient& gradient, bool fill)
572 {
573 adapter_context* context = reinterpret_cast<adapter_context*>(_context);
574 BPoint radii((rect.Width() + 1) / 2.0f, (rect.Height() + 1) / 2.0f);
575 BPoint center = rect.LeftTop() + radii;
576 ((void (*)(void*, BPoint, BPoint, BGradient&))
577 context->function_table[fill ? 64 : 65])(context->user_data, center,
578 radii, gradient);
579 }
580
581
582 static void
draw_polygon_gradient(void * _context,size_t numPoints,const BPoint _points[],bool isClosed,BGradient & gradient,bool fill)583 draw_polygon_gradient(void* _context, size_t numPoints, const BPoint _points[],
584 bool isClosed, BGradient& gradient, bool fill)
585 {
586 adapter_context* context = reinterpret_cast<adapter_context*>(_context);
587
588 BStackOrHeapArray<BPoint, 200> points(numPoints);
589 if (!points.IsValid())
590 return;
591
592 memcpy((void*)points, _points, numPoints * sizeof(BPoint));
593
594 ((void (*)(void*, int32, BPoint*, bool, BGradient&))
595 context->function_table[fill ? 66 : 67])(context->user_data, numPoints,
596 points, isClosed, gradient);
597 }
598
599
600 static void
draw_shape_gradient(void * _context,const BShape & shape,BGradient & gradient,bool fill)601 draw_shape_gradient(void* _context, const BShape& shape, BGradient& gradient, bool fill)
602 {
603 adapter_context* context = reinterpret_cast<adapter_context*>(_context);
604 ((void (*)(void*, BShape, BGradient&))context->function_table[fill ? 68 : 69])(
605 context->user_data, shape, gradient);
606 }
607
608
609 static void
set_fill_rule(void * _context,int32 fillRule)610 set_fill_rule(void* _context, int32 fillRule)
611 {
612 adapter_context* context = reinterpret_cast<adapter_context*>(_context);
613 ((void (*)(void*, int32))context->function_table[70])(
614 context->user_data, fillRule);
615 }
616
617
618
619 #if DEBUG > 1
620 static const char *
PictureOpToString(int op)621 PictureOpToString(int op)
622 {
623 #define RETURN_STRING(x) case x: return #x
624
625 switch(op) {
626 RETURN_STRING(B_PIC_MOVE_PEN_BY);
627 RETURN_STRING(B_PIC_STROKE_LINE);
628 RETURN_STRING(B_PIC_STROKE_RECT);
629 RETURN_STRING(B_PIC_FILL_RECT);
630 RETURN_STRING(B_PIC_STROKE_ROUND_RECT);
631 RETURN_STRING(B_PIC_FILL_ROUND_RECT);
632 RETURN_STRING(B_PIC_STROKE_BEZIER);
633 RETURN_STRING(B_PIC_FILL_BEZIER);
634 RETURN_STRING(B_PIC_STROKE_POLYGON);
635 RETURN_STRING(B_PIC_FILL_POLYGON);
636 RETURN_STRING(B_PIC_STROKE_SHAPE);
637 RETURN_STRING(B_PIC_FILL_SHAPE);
638 RETURN_STRING(B_PIC_DRAW_STRING);
639 RETURN_STRING(B_PIC_DRAW_STRING_LOCATIONS);
640 RETURN_STRING(B_PIC_DRAW_PIXELS);
641 RETURN_STRING(B_PIC_DRAW_PICTURE);
642 RETURN_STRING(B_PIC_STROKE_ARC);
643 RETURN_STRING(B_PIC_FILL_ARC);
644 RETURN_STRING(B_PIC_STROKE_ELLIPSE);
645 RETURN_STRING(B_PIC_FILL_ELLIPSE);
646 RETURN_STRING(B_PIC_STROKE_RECT_GRADIENT);
647 RETURN_STRING(B_PIC_FILL_RECT_GRADIENT);
648 RETURN_STRING(B_PIC_STROKE_ROUND_RECT_GRADIENT);
649 RETURN_STRING(B_PIC_FILL_ROUND_RECT_GRADIENT);
650 RETURN_STRING(B_PIC_STROKE_BEZIER_GRADIENT);
651 RETURN_STRING(B_PIC_FILL_BEZIER_GRADIENT);
652 RETURN_STRING(B_PIC_STROKE_POLYGON_GRADIENT);
653 RETURN_STRING(B_PIC_FILL_POLYGON_GRADIENT);
654 RETURN_STRING(B_PIC_STROKE_SHAPE_GRADIENT);
655 RETURN_STRING(B_PIC_FILL_SHAPE_GRADIENT);
656 RETURN_STRING(B_PIC_STROKE_ARC_GRADIENT);
657 RETURN_STRING(B_PIC_FILL_ARC_GRADIENT);
658 RETURN_STRING(B_PIC_STROKE_ELLIPSE_GRADIENT);
659 RETURN_STRING(B_PIC_FILL_ELLIPSE_GRADIENT);
660
661 RETURN_STRING(B_PIC_ENTER_STATE_CHANGE);
662 RETURN_STRING(B_PIC_SET_CLIPPING_RECTS);
663 RETURN_STRING(B_PIC_CLIP_TO_PICTURE);
664 RETURN_STRING(B_PIC_PUSH_STATE);
665 RETURN_STRING(B_PIC_POP_STATE);
666 RETURN_STRING(B_PIC_CLEAR_CLIPPING_RECTS);
667 RETURN_STRING(B_PIC_CLIP_TO_RECT);
668 RETURN_STRING(B_PIC_CLIP_TO_SHAPE);
669
670 RETURN_STRING(B_PIC_SET_ORIGIN);
671 RETURN_STRING(B_PIC_SET_PEN_LOCATION);
672 RETURN_STRING(B_PIC_SET_DRAWING_MODE);
673 RETURN_STRING(B_PIC_SET_LINE_MODE);
674 RETURN_STRING(B_PIC_SET_PEN_SIZE);
675 RETURN_STRING(B_PIC_SET_SCALE);
676 RETURN_STRING(B_PIC_SET_TRANSFORM);
677 RETURN_STRING(B_PIC_SET_FORE_COLOR);
678 RETURN_STRING(B_PIC_SET_BACK_COLOR);
679 RETURN_STRING(B_PIC_SET_STIPLE_PATTERN);
680 RETURN_STRING(B_PIC_ENTER_FONT_STATE);
681 RETURN_STRING(B_PIC_SET_BLENDING_MODE);
682 RETURN_STRING(B_PIC_SET_FILL_RULE);
683 RETURN_STRING(B_PIC_SET_FONT_FAMILY);
684 RETURN_STRING(B_PIC_SET_FONT_STYLE);
685 RETURN_STRING(B_PIC_SET_FONT_SPACING);
686 RETURN_STRING(B_PIC_SET_FONT_ENCODING);
687 RETURN_STRING(B_PIC_SET_FONT_FLAGS);
688 RETURN_STRING(B_PIC_SET_FONT_SIZE);
689 RETURN_STRING(B_PIC_SET_FONT_ROTATE);
690 RETURN_STRING(B_PIC_SET_FONT_SHEAR);
691 RETURN_STRING(B_PIC_SET_FONT_BPP);
692 RETURN_STRING(B_PIC_SET_FONT_FACE);
693
694 RETURN_STRING(B_PIC_AFFINE_TRANSLATE);
695 RETURN_STRING(B_PIC_AFFINE_SCALE);
696 RETURN_STRING(B_PIC_AFFINE_ROTATE);
697
698 RETURN_STRING(B_PIC_BLEND_LAYER);
699
700 default: return "Unknown op";
701 }
702 #undef RETURN_STRING
703 }
704 #endif
705
706
PicturePlayer(const void * data,size_t size,BList * pictures)707 PicturePlayer::PicturePlayer(const void *data, size_t size, BList *pictures)
708 : fData(data),
709 fSize(size),
710 fPictures(pictures)
711 {
712 }
713
714
~PicturePlayer()715 PicturePlayer::~PicturePlayer()
716 {
717 }
718
719
720 status_t
Play(void ** callBackTable,int32 tableEntries,void * userData)721 PicturePlayer::Play(void** callBackTable, int32 tableEntries, void* userData)
722 {
723 const BPrivate::picture_player_callbacks kAdapterCallbacks = {
724 move_pen_by,
725 stroke_line,
726 draw_rect,
727 draw_round_rect,
728 draw_bezier,
729 draw_arc,
730 draw_ellipse,
731 draw_polygon,
732 draw_shape,
733 draw_string,
734 draw_pixels,
735 draw_picture,
736 set_clipping_rects,
737 clip_to_picture,
738 push_state,
739 pop_state,
740 enter_state_change,
741 exit_state_change,
742 enter_font_state,
743 exit_font_state,
744 set_origin,
745 set_pen_location,
746 set_drawing_mode,
747 set_line_mode,
748 set_pen_size,
749 set_fore_color,
750 set_back_color,
751 set_stipple_pattern,
752 set_scale,
753 set_font_family,
754 set_font_style,
755 set_font_spacing,
756 set_font_size,
757 set_font_rotation,
758 set_font_encoding,
759 set_font_flags,
760 set_font_shear,
761 set_font_face,
762 set_blending_mode,
763 set_transform,
764 translate_by,
765 scale_by,
766 rotate_by,
767 blend_layer,
768 clip_to_rect,
769 clip_to_shape,
770 draw_string_locations,
771 draw_rect_gradient,
772 draw_round_rect_gradient,
773 draw_bezier_gradient,
774 draw_arc_gradient,
775 draw_ellipse_gradient,
776 draw_polygon_gradient,
777 draw_shape_gradient,
778 set_fill_rule
779 };
780
781 // We don't check if the functions in the table are NULL, but we
782 // check the tableEntries to see if the table is big enough.
783 // If an application supplies the wrong size or an invalid pointer,
784 // it's its own fault.
785
786 // If the caller supplied a function table smaller than needed,
787 // we use our dummy table, and copy the supported ops from the supplied one.
788 void *dummyTable[kOpsTableSize];
789
790 adapter_context adapterContext;
791 adapterContext.user_data = userData;
792 adapterContext.function_table = callBackTable;
793
794 if ((size_t)tableEntries < kOpsTableSize) {
795 memcpy(dummyTable, callBackTable, tableEntries * sizeof(void*));
796 for (size_t i = (size_t)tableEntries; i < kOpsTableSize; i++)
797 dummyTable[i] = (void*)nop;
798
799 adapterContext.function_table = dummyTable;
800 }
801
802 return _Play(kAdapterCallbacks, &adapterContext, fData, fSize, 0);
803 }
804
805
806 status_t
Play(const picture_player_callbacks & callbacks,size_t callbacksSize,void * userData)807 PicturePlayer::Play(const picture_player_callbacks& callbacks,
808 size_t callbacksSize, void* userData)
809 {
810 return _Play(callbacks, userData, fData, fSize, 0);
811 }
812
813
814 class DataReader {
815 public:
DataReader(const void * buffer,size_t length)816 DataReader(const void* buffer, size_t length)
817 :
818 fBuffer((const uint8*)buffer),
819 fRemaining(length)
820 {
821 }
822
823 size_t
Remaining() const824 Remaining() const
825 {
826 return fRemaining;
827 }
828
829 template<typename T>
830 bool
Get(const T * & typed,size_t count=1)831 Get(const T*& typed, size_t count = 1)
832 {
833 if (fRemaining < sizeof(T) * count)
834 return false;
835
836 typed = reinterpret_cast<const T *>(fBuffer);
837 fRemaining -= sizeof(T) * count;
838 fBuffer += sizeof(T) * count;
839 return true;
840 }
841
GetGradient(BGradient * & gradient)842 bool GetGradient(BGradient*& gradient)
843 {
844 BMemoryIO stream(fBuffer, fRemaining);
845 printf("fRemaining: %ld\n", fRemaining);
846 if (BGradient::Unflatten(gradient, &stream) != B_OK) {
847 printf("BGradient::Unflatten(_gradient, &stream) != B_OK\n");
848 return false;
849 }
850
851 fRemaining -= stream.Position();
852 fBuffer += stream.Position();
853 return true;
854 }
855
856 template<typename T>
857 bool
GetRemaining(const T * & buffer,size_t & size)858 GetRemaining(const T*& buffer, size_t& size)
859 {
860 if (fRemaining == 0)
861 return false;
862
863 buffer = reinterpret_cast<const T*>(fBuffer);
864 size = fRemaining;
865 fRemaining = 0;
866 return true;
867 }
868
869 private:
870 const uint8* fBuffer;
871 size_t fRemaining;
872 };
873
874
875 struct picture_data_entry_header {
876 uint16 op;
877 uint32 size;
878 } _PACKED;
879
880
881 status_t
_Play(const picture_player_callbacks & callbacks,void * userData,const void * buffer,size_t length,uint16 parentOp)882 PicturePlayer::_Play(const picture_player_callbacks& callbacks, void* userData,
883 const void* buffer, size_t length, uint16 parentOp)
884 {
885 #if DEBUG
886 printf("Start rendering %sBPicture...\n", parentOp != 0 ? "sub " : "");
887 bigtime_t startTime = system_time();
888 int32 numOps = 0;
889 #endif
890
891 DataReader pictureReader(buffer, length);
892
893 while (pictureReader.Remaining() > 0) {
894 const picture_data_entry_header* header;
895 const uint8* opData = NULL;
896 if (!pictureReader.Get(header)
897 || !pictureReader.Get(opData, header->size)) {
898 return B_BAD_DATA;
899 }
900
901 DataReader reader(opData, header->size);
902
903 // Disallow ops that don't fit the parent.
904 switch (parentOp) {
905 case 0:
906 // No parent op, no restrictions.
907 break;
908
909 case B_PIC_ENTER_STATE_CHANGE:
910 if (header->op <= B_PIC_ENTER_STATE_CHANGE
911 || header->op > B_PIC_SET_TRANSFORM) {
912 return B_BAD_DATA;
913 }
914 break;
915
916 case B_PIC_ENTER_FONT_STATE:
917 if (header->op < B_PIC_SET_FONT_FAMILY
918 || header->op > B_PIC_SET_FONT_FACE) {
919 return B_BAD_DATA;
920 }
921 break;
922
923 default:
924 return B_BAD_DATA;
925 }
926
927 #if DEBUG > 1
928 bigtime_t startOpTime = system_time();
929 printf("Op %s ", PictureOpToString(header->op));
930 #endif
931 switch (header->op) {
932 case B_PIC_MOVE_PEN_BY:
933 {
934 const BPoint* where;
935 if (callbacks.move_pen_by == NULL || !reader.Get(where))
936 break;
937
938 callbacks.move_pen_by(userData, *where);
939 break;
940 }
941
942 case B_PIC_STROKE_LINE:
943 {
944 const BPoint* start;
945 const BPoint* end;
946 if (callbacks.stroke_line == NULL || !reader.Get(start)
947 || !reader.Get(end)) {
948 break;
949 }
950
951 callbacks.stroke_line(userData, *start, *end);
952 break;
953 }
954
955 case B_PIC_STROKE_RECT:
956 case B_PIC_FILL_RECT:
957 {
958 const BRect* rect;
959 if (callbacks.draw_rect == NULL || !reader.Get(rect))
960 break;
961
962 callbacks.draw_rect(userData, *rect,
963 header->op == B_PIC_FILL_RECT);
964 break;
965 }
966
967 case B_PIC_STROKE_ROUND_RECT:
968 case B_PIC_FILL_ROUND_RECT:
969 {
970 const BRect* rect;
971 const BPoint* radii;
972 if (callbacks.draw_round_rect == NULL || !reader.Get(rect)
973 || !reader.Get(radii)) {
974 break;
975 }
976
977 callbacks.draw_round_rect(userData, *rect, *radii,
978 header->op == B_PIC_FILL_ROUND_RECT);
979 break;
980 }
981
982 case B_PIC_STROKE_BEZIER:
983 case B_PIC_FILL_BEZIER:
984 {
985 const size_t kNumControlPoints = 4;
986 const BPoint* controlPoints;
987 if (callbacks.draw_bezier == NULL
988 || !reader.Get(controlPoints, kNumControlPoints)) {
989 break;
990 }
991
992 callbacks.draw_bezier(userData, kNumControlPoints,
993 controlPoints, header->op == B_PIC_FILL_BEZIER);
994 break;
995 }
996
997 case B_PIC_STROKE_ARC:
998 case B_PIC_FILL_ARC:
999 {
1000 const BPoint* center;
1001 const BPoint* radii;
1002 const float* startTheta;
1003 const float* arcTheta;
1004 if (callbacks.draw_arc == NULL || !reader.Get(center)
1005 || !reader.Get(radii) || !reader.Get(startTheta)
1006 || !reader.Get(arcTheta)) {
1007 break;
1008 }
1009
1010 callbacks.draw_arc(userData, *center, *radii, *startTheta,
1011 *arcTheta, header->op == B_PIC_FILL_ARC);
1012 break;
1013 }
1014
1015 case B_PIC_STROKE_ELLIPSE:
1016 case B_PIC_FILL_ELLIPSE:
1017 {
1018 const BRect* rect;
1019 if (callbacks.draw_ellipse == NULL || !reader.Get(rect))
1020 break;
1021
1022 callbacks.draw_ellipse(userData, *rect,
1023 header->op == B_PIC_FILL_ELLIPSE);
1024 break;
1025 }
1026
1027 case B_PIC_STROKE_POLYGON:
1028 case B_PIC_FILL_POLYGON:
1029 {
1030 const uint32* numPoints;
1031 const BPoint* points;
1032 if (callbacks.draw_polygon == NULL || !reader.Get(numPoints)
1033 || !reader.Get(points, *numPoints)) {
1034 break;
1035 }
1036
1037 bool isClosed = true;
1038 const bool* closedPointer;
1039 if (header->op != B_PIC_FILL_POLYGON) {
1040 if (!reader.Get(closedPointer))
1041 break;
1042
1043 isClosed = *closedPointer;
1044 }
1045
1046 callbacks.draw_polygon(userData, *numPoints, points, isClosed,
1047 header->op == B_PIC_FILL_POLYGON);
1048 break;
1049 }
1050
1051 case B_PIC_STROKE_SHAPE:
1052 case B_PIC_FILL_SHAPE:
1053 {
1054 const uint32* opCount;
1055 const uint32* pointCount;
1056 const uint32* opList;
1057 const BPoint* pointList;
1058 if (callbacks.draw_shape == NULL || !reader.Get(opCount)
1059 || !reader.Get(pointCount) || !reader.Get(opList, *opCount)
1060 || !reader.Get(pointList, *pointCount)) {
1061 break;
1062 }
1063
1064 // TODO: remove BShape data copying
1065 BShape shape;
1066 BShape::Private(shape).SetData(*opCount, *pointCount, opList, pointList);
1067
1068 callbacks.draw_shape(userData, shape,
1069 header->op == B_PIC_FILL_SHAPE);
1070 break;
1071 }
1072
1073 case B_PIC_STROKE_RECT_GRADIENT:
1074 case B_PIC_FILL_RECT_GRADIENT:
1075 {
1076 const BRect* rect;
1077 BGradient* gradient;
1078 if (callbacks.draw_rect_gradient == NULL || !reader.Get(rect) || !reader.GetGradient(gradient))
1079 break;
1080 ObjectDeleter<BGradient> gradientDeleter(gradient);
1081
1082 callbacks.draw_rect_gradient(userData, *rect, *gradient,
1083 header->op == B_PIC_FILL_RECT_GRADIENT);
1084 break;
1085 }
1086
1087 case B_PIC_STROKE_ROUND_RECT_GRADIENT:
1088 case B_PIC_FILL_ROUND_RECT_GRADIENT:
1089 {
1090 const BRect* rect;
1091 const BPoint* radii;
1092 BGradient* gradient;
1093 if (callbacks.draw_round_rect_gradient == NULL || !reader.Get(rect)
1094 || !reader.Get(radii) || !reader.GetGradient(gradient)) {
1095 break;
1096 }
1097 ObjectDeleter<BGradient> gradientDeleter(gradient);
1098
1099 callbacks.draw_round_rect_gradient(userData, *rect, *radii, *gradient,
1100 header->op == B_PIC_FILL_ROUND_RECT_GRADIENT);
1101 break;
1102 }
1103
1104 case B_PIC_STROKE_BEZIER_GRADIENT:
1105 case B_PIC_FILL_BEZIER_GRADIENT:
1106 {
1107 const size_t kNumControlPoints = 4;
1108 const BPoint* controlPoints;
1109 BGradient* gradient;
1110 if (callbacks.draw_bezier_gradient == NULL
1111 || !reader.Get(controlPoints, kNumControlPoints) || !reader.GetGradient(gradient)) {
1112 break;
1113 }
1114 ObjectDeleter<BGradient> gradientDeleter(gradient);
1115
1116 callbacks.draw_bezier_gradient(userData, kNumControlPoints,
1117 controlPoints, *gradient, header->op == B_PIC_FILL_BEZIER_GRADIENT);
1118 break;
1119 }
1120
1121 case B_PIC_STROKE_POLYGON_GRADIENT:
1122 case B_PIC_FILL_POLYGON_GRADIENT:
1123 {
1124 const uint32* numPoints;
1125 const BPoint* points;
1126 BGradient* gradient;
1127 if (callbacks.draw_polygon_gradient == NULL || !reader.Get(numPoints)
1128 || !reader.Get(points, *numPoints)) {
1129 break;
1130 }
1131
1132 bool isClosed = true;
1133 const bool* closedPointer;
1134 if (header->op != B_PIC_FILL_POLYGON_GRADIENT) {
1135 if (!reader.Get(closedPointer))
1136 break;
1137
1138 isClosed = *closedPointer;
1139 }
1140
1141 if (!reader.GetGradient(gradient))
1142 break;
1143 ObjectDeleter<BGradient> gradientDeleter(gradient);
1144
1145 callbacks.draw_polygon_gradient(userData, *numPoints, points, isClosed, *gradient,
1146 header->op == B_PIC_FILL_POLYGON_GRADIENT);
1147 break;
1148 }
1149
1150 case B_PIC_STROKE_SHAPE_GRADIENT:
1151 case B_PIC_FILL_SHAPE_GRADIENT:
1152 {
1153 const uint32* opCount;
1154 const uint32* pointCount;
1155 const uint32* opList;
1156 const BPoint* pointList;
1157 BGradient* gradient;
1158 if (callbacks.draw_shape_gradient == NULL || !reader.Get(opCount)
1159 || !reader.Get(pointCount) || !reader.Get(opList, *opCount)
1160 || !reader.Get(pointList, *pointCount) || !reader.GetGradient(gradient)) {
1161 break;
1162 }
1163 ObjectDeleter<BGradient> gradientDeleter(gradient);
1164
1165 // TODO: remove BShape data copying
1166 BShape shape;
1167 BShape::Private(shape).SetData(*opCount, *pointCount, opList, pointList);
1168
1169 callbacks.draw_shape_gradient(userData, shape, *gradient,
1170 header->op == B_PIC_FILL_SHAPE_GRADIENT);
1171 break;
1172 }
1173
1174 case B_PIC_STROKE_ARC_GRADIENT:
1175 case B_PIC_FILL_ARC_GRADIENT:
1176 {
1177 const BPoint* center;
1178 const BPoint* radii;
1179 const float* startTheta;
1180 const float* arcTheta;
1181 BGradient* gradient;
1182 if (callbacks.draw_arc_gradient == NULL || !reader.Get(center)
1183 || !reader.Get(radii) || !reader.Get(startTheta)
1184 || !reader.Get(arcTheta) || !reader.GetGradient(gradient)) {
1185 break;
1186 }
1187 ObjectDeleter<BGradient> gradientDeleter(gradient);
1188
1189 callbacks.draw_arc_gradient(userData, *center, *radii, *startTheta,
1190 *arcTheta, *gradient, header->op == B_PIC_FILL_ARC_GRADIENT);
1191 break;
1192 }
1193
1194 case B_PIC_STROKE_ELLIPSE_GRADIENT:
1195 case B_PIC_FILL_ELLIPSE_GRADIENT:
1196 {
1197 const BRect* rect;
1198 BGradient* gradient;
1199 if (callbacks.draw_ellipse_gradient == NULL || !reader.Get(rect) || !reader.GetGradient(gradient))
1200 break;
1201 ObjectDeleter<BGradient> gradientDeleter(gradient);
1202
1203 callbacks.draw_ellipse_gradient(userData, *rect, *gradient,
1204 header->op == B_PIC_FILL_ELLIPSE_GRADIENT);
1205 break;
1206 }
1207
1208 case B_PIC_DRAW_STRING:
1209 {
1210 const float* escapementSpace;
1211 const float* escapementNonSpace;
1212 const char* string;
1213 size_t length;
1214 if (callbacks.draw_string == NULL
1215 || !reader.Get(escapementSpace)
1216 || !reader.Get(escapementNonSpace)
1217 || !reader.GetRemaining(string, length)) {
1218 break;
1219 }
1220
1221 callbacks.draw_string(userData, string, length,
1222 *escapementSpace, *escapementNonSpace);
1223 break;
1224 }
1225
1226 case B_PIC_DRAW_STRING_LOCATIONS:
1227 {
1228 const uint32* pointCount;
1229 const BPoint* pointList;
1230 const char* string;
1231 size_t length;
1232 if (callbacks.draw_string_locations == NULL
1233 || !reader.Get(pointCount)
1234 || !reader.Get(pointList, *pointCount)
1235 || !reader.GetRemaining(string, length)) {
1236 break;
1237 }
1238
1239 callbacks.draw_string_locations(userData, string, length,
1240 pointList, *pointCount);
1241 break;
1242 }
1243
1244 case B_PIC_DRAW_PIXELS:
1245 {
1246 const BRect* sourceRect;
1247 const BRect* destinationRect;
1248 const uint32* width;
1249 const uint32* height;
1250 const uint32* bytesPerRow;
1251 const uint32* colorSpace;
1252 const uint32* flags;
1253 const void* data;
1254 size_t length;
1255 if (callbacks.draw_pixels == NULL || !reader.Get(sourceRect)
1256 || !reader.Get(destinationRect) || !reader.Get(width)
1257 || !reader.Get(height) || !reader.Get(bytesPerRow)
1258 || !reader.Get(colorSpace) || !reader.Get(flags)
1259 || !reader.GetRemaining(data, length)) {
1260 break;
1261 }
1262
1263 callbacks.draw_pixels(userData, *sourceRect, *destinationRect,
1264 *width, *height, *bytesPerRow, (color_space)*colorSpace,
1265 *flags, data, length);
1266 break;
1267 }
1268
1269 case B_PIC_DRAW_PICTURE:
1270 {
1271 const BPoint* where;
1272 const int32* token;
1273 if (callbacks.draw_picture == NULL || !reader.Get(where)
1274 || !reader.Get(token)) {
1275 break;
1276 }
1277
1278 callbacks.draw_picture(userData, *where, *token);
1279 break;
1280 }
1281
1282 case B_PIC_SET_CLIPPING_RECTS:
1283 {
1284 const uint32* numRects;
1285 const BRect* rects;
1286 if (callbacks.set_clipping_rects == NULL
1287 || !reader.Get(numRects) || !reader.Get(rects, *numRects)) {
1288 break;
1289 }
1290
1291 callbacks.set_clipping_rects(userData, *numRects, rects);
1292 break;
1293 }
1294
1295 case B_PIC_CLEAR_CLIPPING_RECTS:
1296 {
1297 if (callbacks.set_clipping_rects == NULL)
1298 break;
1299
1300 callbacks.set_clipping_rects(userData, 0, NULL);
1301 break;
1302 }
1303
1304 case B_PIC_CLIP_TO_PICTURE:
1305 {
1306 const int32* token;
1307 const BPoint* where;
1308 const bool* inverse;
1309 if (callbacks.clip_to_picture == NULL || !reader.Get(token)
1310 || !reader.Get(where) || !reader.Get(inverse))
1311 break;
1312
1313 callbacks.clip_to_picture(userData, *token, *where, *inverse);
1314 break;
1315 }
1316
1317 case B_PIC_PUSH_STATE:
1318 {
1319 if (callbacks.push_state == NULL)
1320 break;
1321
1322 callbacks.push_state(userData);
1323 break;
1324 }
1325
1326 case B_PIC_POP_STATE:
1327 {
1328 if (callbacks.pop_state == NULL)
1329 break;
1330
1331 callbacks.pop_state(userData);
1332 break;
1333 }
1334
1335 case B_PIC_ENTER_STATE_CHANGE:
1336 case B_PIC_ENTER_FONT_STATE:
1337 {
1338 const void* data;
1339 size_t length;
1340 if (!reader.GetRemaining(data, length))
1341 break;
1342
1343 if (header->op == B_PIC_ENTER_STATE_CHANGE) {
1344 if (callbacks.enter_state_change != NULL)
1345 callbacks.enter_state_change(userData);
1346 } else if (callbacks.enter_font_state != NULL)
1347 callbacks.enter_font_state(userData);
1348
1349 status_t result = _Play(callbacks, userData, data, length,
1350 header->op);
1351 if (result != B_OK)
1352 return result;
1353
1354 if (header->op == B_PIC_ENTER_STATE_CHANGE) {
1355 if (callbacks.exit_state_change != NULL)
1356 callbacks.exit_state_change(userData);
1357 } else if (callbacks.exit_font_state != NULL)
1358 callbacks.exit_font_state(userData);
1359
1360 break;
1361 }
1362
1363 case B_PIC_SET_ORIGIN:
1364 {
1365 const BPoint* origin;
1366 if (callbacks.set_origin == NULL || !reader.Get(origin))
1367 break;
1368
1369 callbacks.set_origin(userData, *origin);
1370 break;
1371 }
1372
1373 case B_PIC_SET_PEN_LOCATION:
1374 {
1375 const BPoint* location;
1376 if (callbacks.set_pen_location == NULL || !reader.Get(location))
1377 break;
1378
1379 callbacks.set_pen_location(userData, *location);
1380 break;
1381 }
1382
1383 case B_PIC_SET_DRAWING_MODE:
1384 {
1385 const uint16* mode;
1386 if (callbacks.set_drawing_mode == NULL || !reader.Get(mode))
1387 break;
1388
1389 callbacks.set_drawing_mode(userData, (drawing_mode)*mode);
1390 break;
1391 }
1392
1393 case B_PIC_SET_LINE_MODE:
1394 {
1395 const uint16* capMode;
1396 const uint16* joinMode;
1397 const float* miterLimit;
1398 if (callbacks.set_line_mode == NULL || !reader.Get(capMode)
1399 || !reader.Get(joinMode) || !reader.Get(miterLimit)) {
1400 break;
1401 }
1402
1403 callbacks.set_line_mode(userData, (cap_mode)*capMode,
1404 (join_mode)*joinMode, *miterLimit);
1405 break;
1406 }
1407
1408 case B_PIC_SET_PEN_SIZE:
1409 {
1410 const float* penSize;
1411 if (callbacks.set_pen_size == NULL || !reader.Get(penSize))
1412 break;
1413
1414 callbacks.set_pen_size(userData, *penSize);
1415 break;
1416 }
1417
1418 case B_PIC_SET_FORE_COLOR:
1419 {
1420 const rgb_color* color;
1421 if (callbacks.set_fore_color == NULL || !reader.Get(color))
1422 break;
1423
1424 callbacks.set_fore_color(userData, *color);
1425 break;
1426 }
1427
1428 case B_PIC_SET_BACK_COLOR:
1429 {
1430 const rgb_color* color;
1431 if (callbacks.set_back_color == NULL || !reader.Get(color))
1432 break;
1433
1434 callbacks.set_back_color(userData, *color);
1435 break;
1436 }
1437
1438 case B_PIC_SET_STIPLE_PATTERN:
1439 {
1440 const pattern* stipplePattern;
1441 if (callbacks.set_stipple_pattern == NULL
1442 || !reader.Get(stipplePattern)) {
1443 break;
1444 }
1445
1446 callbacks.set_stipple_pattern(userData, *stipplePattern);
1447 break;
1448 }
1449
1450 case B_PIC_SET_SCALE:
1451 {
1452 const float* scale;
1453 if (callbacks.set_scale == NULL || !reader.Get(scale))
1454 break;
1455
1456 callbacks.set_scale(userData, *scale);
1457 break;
1458 }
1459
1460 case B_PIC_SET_FONT_FAMILY:
1461 {
1462 const char* family;
1463 size_t length;
1464 if (callbacks.set_font_family == NULL
1465 || !reader.GetRemaining(family, length)) {
1466 break;
1467 }
1468
1469 callbacks.set_font_family(userData, family, length);
1470 break;
1471 }
1472
1473 case B_PIC_SET_FONT_STYLE:
1474 {
1475 const char* style;
1476 size_t length;
1477 if (callbacks.set_font_style == NULL
1478 || !reader.GetRemaining(style, length)) {
1479 break;
1480 }
1481
1482 callbacks.set_font_style(userData, style, length);
1483 break;
1484 }
1485
1486 case B_PIC_SET_FONT_SPACING:
1487 {
1488 const uint32* spacing;
1489 if (callbacks.set_font_spacing == NULL || !reader.Get(spacing))
1490 break;
1491
1492 callbacks.set_font_spacing(userData, *spacing);
1493 break;
1494 }
1495
1496 case B_PIC_SET_FONT_SIZE:
1497 {
1498 const float* size;
1499 if (callbacks.set_font_size == NULL || !reader.Get(size))
1500 break;
1501
1502 callbacks.set_font_size(userData, *size);
1503 break;
1504 }
1505
1506 case B_PIC_SET_FONT_ROTATE:
1507 {
1508 const float* rotation;
1509 if (callbacks.set_font_rotation == NULL
1510 || !reader.Get(rotation)) {
1511 break;
1512 }
1513
1514 callbacks.set_font_rotation(userData, *rotation);
1515 break;
1516 }
1517
1518 case B_PIC_SET_FONT_ENCODING:
1519 {
1520 const uint32* encoding;
1521 if (callbacks.set_font_encoding == NULL
1522 || !reader.Get(encoding)) {
1523 break;
1524 }
1525
1526 callbacks.set_font_encoding(userData, *encoding);
1527 break;
1528 }
1529
1530 case B_PIC_SET_FONT_FLAGS:
1531 {
1532 const uint32* flags;
1533 if (callbacks.set_font_flags == NULL || !reader.Get(flags))
1534 break;
1535
1536 callbacks.set_font_flags(userData, *flags);
1537 break;
1538 }
1539
1540 case B_PIC_SET_FONT_SHEAR:
1541 {
1542 const float* shear;
1543 if (callbacks.set_font_shear == NULL || !reader.Get(shear))
1544 break;
1545
1546 callbacks.set_font_shear(userData, *shear);
1547 break;
1548 }
1549
1550 case B_PIC_SET_FONT_FACE:
1551 {
1552 const uint32* face;
1553 if (callbacks.set_font_face == NULL || !reader.Get(face))
1554 break;
1555
1556 callbacks.set_font_face(userData, *face);
1557 break;
1558 }
1559
1560 case B_PIC_SET_BLENDING_MODE:
1561 {
1562 const uint16* alphaSourceMode;
1563 const uint16* alphaFunctionMode;
1564 if (callbacks.set_blending_mode == NULL
1565 || !reader.Get(alphaSourceMode)
1566 || !reader.Get(alphaFunctionMode)) {
1567 break;
1568 }
1569
1570 callbacks.set_blending_mode(userData,
1571 (source_alpha)*alphaSourceMode,
1572 (alpha_function)*alphaFunctionMode);
1573 break;
1574 }
1575
1576 case B_PIC_SET_FILL_RULE:
1577 {
1578 const uint32* fillRule;
1579 if (callbacks.set_fill_rule == NULL
1580 || !reader.Get(fillRule)) {
1581 break;
1582 }
1583
1584 callbacks.set_fill_rule(userData, *fillRule);
1585 break;
1586 }
1587
1588 case B_PIC_SET_TRANSFORM:
1589 {
1590 const BAffineTransform* transform;
1591 if (callbacks.set_transform == NULL || !reader.Get(transform))
1592 break;
1593
1594 callbacks.set_transform(userData, *transform);
1595 break;
1596 }
1597
1598 case B_PIC_AFFINE_TRANSLATE:
1599 {
1600 const double* x;
1601 const double* y;
1602 if (callbacks.translate_by == NULL || !reader.Get(x)
1603 || !reader.Get(y)) {
1604 break;
1605 }
1606
1607 callbacks.translate_by(userData, *x, *y);
1608 break;
1609 }
1610
1611 case B_PIC_AFFINE_SCALE:
1612 {
1613 const double* x;
1614 const double* y;
1615 if (callbacks.scale_by == NULL || !reader.Get(x)
1616 || !reader.Get(y)) {
1617 break;
1618 }
1619
1620 callbacks.scale_by(userData, *x, *y);
1621 break;
1622 }
1623
1624 case B_PIC_AFFINE_ROTATE:
1625 {
1626 const double* angleRadians;
1627 if (callbacks.rotate_by == NULL || !reader.Get(angleRadians))
1628 break;
1629
1630 callbacks.rotate_by(userData, *angleRadians);
1631 break;
1632 }
1633
1634 case B_PIC_BLEND_LAYER:
1635 {
1636 Layer* const* layer;
1637 if (callbacks.blend_layer == NULL || !reader.Get<Layer*>(layer))
1638 break;
1639
1640 callbacks.blend_layer(userData, *layer);
1641 break;
1642 }
1643
1644 case B_PIC_CLIP_TO_RECT:
1645 {
1646 const bool* inverse;
1647 const BRect* rect;
1648
1649 if (callbacks.clip_to_rect == NULL || !reader.Get(inverse)
1650 || !reader.Get(rect)) {
1651 break;
1652 }
1653
1654 callbacks.clip_to_rect(userData, *rect, *inverse);
1655 break;
1656 }
1657
1658 case B_PIC_CLIP_TO_SHAPE:
1659 {
1660 const bool* inverse;
1661 const uint32* opCount;
1662 const uint32* pointCount;
1663 const uint32* opList;
1664 const BPoint* pointList;
1665 if (callbacks.clip_to_shape == NULL || !reader.Get(inverse)
1666 || !reader.Get(opCount) || !reader.Get(pointCount)
1667 || !reader.Get(opList, *opCount)
1668 || !reader.Get(pointList, *pointCount)) {
1669 break;
1670 }
1671
1672 callbacks.clip_to_shape(userData, *opCount, opList,
1673 *pointCount, pointList, *inverse);
1674 break;
1675 }
1676
1677 default:
1678 break;
1679 }
1680
1681 #if DEBUG
1682 numOps++;
1683 #if DEBUG > 1
1684 printf("executed in %" B_PRId64 " usecs\n", system_time()
1685 - startOpTime);
1686 #endif
1687 #endif
1688 }
1689
1690 #if DEBUG
1691 printf("Done! %" B_PRId32 " ops, rendering completed in %" B_PRId64
1692 " usecs.\n", numOps, system_time() - startTime);
1693 #endif
1694 return B_OK;
1695 }
1696