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 41 nop() 42 { 43 } 44 45 46 static void 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 * 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 707 PicturePlayer::PicturePlayer(const void *data, size_t size, BList *pictures) 708 : fData(data), 709 fSize(size), 710 fPictures(pictures) 711 { 712 } 713 714 715 PicturePlayer::~PicturePlayer() 716 { 717 } 718 719 720 status_t 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 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: 816 DataReader(const void* buffer, size_t length) 817 : 818 fBuffer((const uint8*)buffer), 819 fRemaining(length) 820 { 821 } 822 823 size_t 824 Remaining() const 825 { 826 return fRemaining; 827 } 828 829 template<typename T> 830 bool 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 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 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 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