1 /* 2 * Copyright 2001-2006, Haiku. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Marc Flerackers (mflerackers@androme.be) 7 * Stefano Ceccherini (burton666@libero.it) 8 */ 9 10 11 #include "DrawingEngine.h" 12 #include "ServerBitmap.h" 13 #include "ServerPicture.h" 14 #include "ServerTokenSpace.h" 15 #include "ViewLayer.h" 16 #include "WindowLayer.h" 17 18 #include <PicturePlayer.h> 19 #include <PictureProtocol.h> 20 #include <ServerProtocol.h> 21 #include <ShapePrivate.h> 22 23 #include <Bitmap.h> 24 #include <Shape.h> 25 26 #include <stdio.h> 27 #include <stack> 28 29 30 class ShapePainter : public BShapeIterator { 31 public: 32 ShapePainter(); 33 virtual ~ShapePainter(); 34 35 virtual status_t IterateMoveTo(BPoint *point); 36 virtual status_t IterateLineTo(int32 lineCount, BPoint *linePts); 37 virtual status_t IterateBezierTo(int32 bezierCount, BPoint *bezierPts); 38 virtual status_t IterateClose(); 39 40 void Draw(ViewLayer *view, BRect frame, bool filled); 41 42 private: 43 stack<uint32> fOpStack; 44 stack<BPoint> fPtStack; 45 }; 46 47 ShapePainter::ShapePainter() 48 : BShapeIterator() 49 { 50 } 51 52 ShapePainter::~ShapePainter() 53 { 54 } 55 56 status_t 57 ShapePainter::IterateMoveTo(BPoint *point) 58 { 59 fOpStack.push(OP_MOVETO); 60 fPtStack.push(*point); 61 62 return B_OK; 63 } 64 65 status_t 66 ShapePainter::IterateLineTo(int32 lineCount, BPoint *linePts) 67 { 68 fOpStack.push(OP_LINETO | lineCount); 69 for(int32 i = 0;i < lineCount;i++) 70 fPtStack.push(linePts[i]); 71 72 return B_OK; 73 } 74 75 status_t 76 ShapePainter::IterateBezierTo(int32 bezierCount, BPoint *bezierPts) 77 { 78 bezierCount *= 3; 79 fOpStack.push(OP_BEZIERTO | bezierCount); 80 for(int32 i = 0;i < bezierCount;i++) 81 fPtStack.push(bezierPts[i]); 82 83 return B_OK; 84 } 85 86 status_t 87 ShapePainter::IterateClose(void) 88 { 89 fOpStack.push(OP_CLOSE); 90 91 return B_OK; 92 } 93 94 void 95 ShapePainter::Draw(ViewLayer *view, BRect frame, bool filled) 96 { 97 // We're going to draw the currently iterated picture. 98 int32 opCount, ptCount; 99 opCount = fOpStack.size(); 100 ptCount = fPtStack.size(); 101 102 uint32 *opList; 103 BPoint *ptList; 104 if(opCount > 0 && ptCount > 0) { 105 int32 i; 106 opList = new uint32[opCount]; 107 ptList = new BPoint[ptCount]; 108 109 for(i = (opCount - 1);i >= 0;i--) { 110 opList[i] = fOpStack.top(); 111 fOpStack.pop(); 112 } 113 114 for(i = (ptCount - 1);i >= 0;i--) { 115 ptList[i] = fPtStack.top(); 116 fPtStack.pop(); 117 } 118 119 view->Window()->GetDrawingEngine()->DrawShape(frame, opCount, opList, ptCount, ptList, 120 view->CurrentState(), filled); 121 } 122 } 123 124 static void 125 nop() 126 { 127 } 128 129 130 static void 131 move_pen_by(ViewLayer *view, BPoint delta) 132 { 133 view->CurrentState()->SetPenLocation(delta - view->CurrentState()->PenLocation()); 134 } 135 136 137 static void 138 stroke_line(ViewLayer *view, BPoint start, BPoint end) 139 { 140 view->ConvertToScreenForDrawing(&start); 141 view->ConvertToScreenForDrawing(&end); 142 view->Window()->GetDrawingEngine()->StrokeLine(start, end, view->CurrentState()); 143 } 144 145 146 static void 147 stroke_rect(ViewLayer *view, BRect rect) 148 { 149 view->ConvertToScreenForDrawing(&rect); 150 view->Window()->GetDrawingEngine()->StrokeRect(rect, view->CurrentState()); 151 } 152 153 154 static void 155 fill_rect(ViewLayer *view, BRect rect) 156 { 157 view->ConvertToScreenForDrawing(&rect); 158 view->Window()->GetDrawingEngine()->FillRect(rect, view->CurrentState()); 159 } 160 161 162 static void 163 stroke_round_rect(ViewLayer *view, BRect rect, BPoint radii) 164 { 165 view->ConvertToScreenForDrawing(&rect); 166 view->Window()->GetDrawingEngine()->DrawRoundRect(rect, radii.x, radii.y, view->CurrentState(), false); 167 } 168 169 170 static void 171 fill_round_rect(ViewLayer *view, BRect rect, BPoint radii) 172 { 173 view->ConvertToScreenForDrawing(&rect); 174 view->Window()->GetDrawingEngine()->DrawRoundRect(rect, radii.x, radii.y, view->CurrentState(), true); 175 } 176 177 178 static void 179 stroke_bezier(ViewLayer *view, BPoint *points) 180 { 181 for (int32 i = 0; i < 4; i++) 182 view->ConvertToScreenForDrawing(&points[i]); 183 184 view->Window()->GetDrawingEngine()->DrawBezier(points, view->CurrentState(), false); 185 } 186 187 188 static void 189 fill_bezier(ViewLayer *view, BPoint *points) 190 { 191 for (int32 i = 0; i < 4; i++) 192 view->ConvertToScreenForDrawing(&points[i]); 193 194 view->Window()->GetDrawingEngine()->DrawBezier(points, view->CurrentState(), true); 195 } 196 197 198 static void 199 stroke_arc(ViewLayer *view, BPoint center, BPoint radii, float startTheta, 200 float arcTheta) 201 { 202 BRect rect(center.x - radii.x, center.y - radii.y, center.x + radii.x, 203 center.y + radii.y); 204 view->ConvertToScreenForDrawing(&rect); 205 view->Window()->GetDrawingEngine()->DrawArc(rect, startTheta, arcTheta, view->CurrentState(), false); 206 } 207 208 209 static void 210 fill_arc(ViewLayer *view, BPoint center, BPoint radii, float startTheta, 211 float arcTheta) 212 { 213 BRect rect(center.x - radii.x, center.y - radii.y, center.x + radii.x, 214 center.y + radii.y); 215 view->ConvertToScreenForDrawing(&rect); 216 view->Window()->GetDrawingEngine()->DrawArc(rect, startTheta, arcTheta, view->CurrentState(), true); 217 } 218 219 220 static void 221 stroke_ellipse(ViewLayer *view, BPoint center, BPoint radii) 222 { 223 BRect rect(center.x - radii.x, center.y - radii.y, center.x + radii.x, 224 center.y + radii.y); 225 view->ConvertToScreenForDrawing(&rect); 226 view->Window()->GetDrawingEngine()->DrawEllipse(rect, view->CurrentState(), false); 227 } 228 229 230 static void 231 fill_ellipse(ViewLayer *view, BPoint center, BPoint radii) 232 { 233 BRect rect(center.x - radii.x, center.y - radii.y, center.x + radii.x, 234 center.y + radii.y); 235 view->ConvertToScreenForDrawing(&rect); 236 view->Window()->GetDrawingEngine()->DrawEllipse(rect, view->CurrentState(), true); 237 } 238 239 240 static void 241 stroke_polygon(ViewLayer *view, int32 numPoints, BPoint *points, bool isClosed) 242 { 243 for (int32 i = 0; i < numPoints; i++) 244 view->ConvertToScreenForDrawing(&points[i]); 245 246 BRect polyFrame = BRect(points[0], points[0]); 247 248 for (int32 i = 1; i < numPoints; i++) { 249 if (points[i].x < polyFrame.left) 250 polyFrame.left = points[i].x; 251 if (points[i].y < polyFrame.top) 252 polyFrame.top = points[i].y; 253 if (points[i].x > polyFrame.right) 254 polyFrame.right = points[i].x; 255 if (points[i].y > polyFrame.bottom) 256 polyFrame.bottom = points[i].y; 257 } 258 259 view->Window()->GetDrawingEngine()->DrawPolygon(points, numPoints, polyFrame, view->CurrentState(), 260 false, isClosed && numPoints > 2); 261 } 262 263 264 static void 265 fill_polygon(ViewLayer *view, int32 numPoints, BPoint *points) 266 { 267 for (int32 i = 0; i < numPoints; i++) 268 view->ConvertToScreenForDrawing(&points[i]); 269 270 BRect polyFrame = BRect(points[0], points[0]); 271 272 for (int32 i = 1; i < numPoints; i++) { 273 if (points[i].x < polyFrame.left) 274 polyFrame.left = points[i].x; 275 if (points[i].y < polyFrame.top) 276 polyFrame.top = points[i].y; 277 if (points[i].x > polyFrame.right) 278 polyFrame.right = points[i].x; 279 if (points[i].y > polyFrame.bottom) 280 polyFrame.bottom = points[i].y; 281 } 282 283 view->Window()->GetDrawingEngine()->DrawPolygon(points, numPoints, polyFrame, view->CurrentState(), 284 true, true); 285 } 286 287 288 static void 289 stroke_shape(ViewLayer *view, BShape *shape) 290 { 291 ShapePainter drawShape; 292 293 drawShape.Iterate(shape); 294 drawShape.Draw(view, shape->Bounds(), false); 295 } 296 297 298 static void 299 fill_shape(ViewLayer *view, BShape *shape) 300 { 301 ShapePainter drawShape; 302 303 drawShape.Iterate(shape); 304 drawShape.Draw(view, shape->Bounds(), true); 305 } 306 307 308 static void 309 draw_string(ViewLayer *view, char *string, float deltaSpace, float deltaNonSpace) 310 { 311 BPoint location = view->CurrentState()->PenLocation(); 312 escapement_delta delta = {deltaSpace, deltaNonSpace }; 313 view->ConvertToScreenForDrawing(&location); 314 view->Window()->GetDrawingEngine()->DrawString(string, strlen(string), location, 315 view->CurrentState(), &delta); 316 // TODO: Update pen location ? 317 318 } 319 320 321 static void 322 draw_pixels(ViewLayer *view, BRect src, BRect dest, int32 width, int32 height, 323 int32 bytesPerRow, int32 pixelFormat, int32 flags, void *data) 324 { 325 // TODO: Review this 326 UtilityBitmap bitmap(BRect(0, 0, width - 1, height - 1), (color_space)pixelFormat, flags, bytesPerRow); 327 328 if (!bitmap.IsValid()) 329 return; 330 331 uint8 *pixels = (uint8 *)data; 332 uint8 *destPixels = (uint8 *)bitmap.Bits(); 333 for (int32 h = 0; h < height; h++) { 334 memcpy(destPixels, pixels, bytesPerRow); 335 pixels += bytesPerRow; 336 destPixels += bytesPerRow; 337 } 338 339 view->ConvertToScreenForDrawing(&dest); 340 341 view->Window()->GetDrawingEngine()->DrawBitmap(&bitmap, src, dest, view->CurrentState()); 342 } 343 344 345 static void 346 set_clipping_rects(ViewLayer *view, BRect *rects, uint32 numRects) 347 { 348 // TODO: This is too slow, we should copy the rects directly to BRegion's internal data 349 BRegion region; 350 for (uint32 c = 0; c < numRects; c++) 351 region.Include(rects[c]); 352 view->SetUserClipping(®ion); 353 } 354 355 356 static void 357 clip_to_picture(ViewLayer *view, BPicture *picture, BPoint pt, 358 bool clip_to_inverse_picture) 359 { 360 printf("ClipToPicture(picture, BPoint(%.2f, %.2f), %s)\n", pt.x, pt.y, 361 clip_to_inverse_picture ? "inverse" : ""); 362 } 363 364 365 static void 366 push_state(ViewLayer *view) 367 { 368 view->PushState(); 369 } 370 371 372 static void 373 pop_state(ViewLayer *view) 374 { 375 view->PopState(); 376 } 377 378 379 static void 380 enter_state_change(ViewLayer *view) 381 { 382 printf("EnterStateChange\n"); 383 } 384 385 386 static void 387 exit_state_change(ViewLayer *view) 388 { 389 printf("ExitStateChange\n"); 390 } 391 392 393 static void 394 enter_font_state(ViewLayer *view) 395 { 396 printf("EnterFontState\n"); 397 } 398 399 400 static void 401 exit_font_state(ViewLayer *view) 402 { 403 printf("ExitFontState\n"); 404 } 405 406 407 static void 408 set_origin(ViewLayer *view, BPoint pt) 409 { 410 view->CurrentState()->SetOrigin(pt); 411 } 412 413 414 static void 415 set_pen_location(ViewLayer *view, BPoint pt) 416 { 417 view->CurrentState()->SetPenLocation(pt); 418 } 419 420 421 static void 422 set_drawing_mode(ViewLayer *view, drawing_mode mode) 423 { 424 view->CurrentState()->SetDrawingMode(mode); 425 } 426 427 428 static void 429 set_line_mode(ViewLayer *view, cap_mode capMode, join_mode joinMode, float miterLimit) 430 { 431 DrawState *state = view->CurrentState(); 432 state->SetLineCapMode(capMode); 433 state->SetLineJoinMode(joinMode); 434 state->SetMiterLimit(miterLimit); 435 } 436 437 438 static void 439 set_pen_size(ViewLayer *view, float size) 440 { 441 view->CurrentState()->SetPenSize(size); 442 } 443 444 445 static void 446 set_fore_color(ViewLayer *view, rgb_color color) 447 { 448 view->CurrentState()->SetHighColor(RGBColor(color)); 449 } 450 451 452 static void 453 set_back_color(ViewLayer *view, rgb_color color) 454 { 455 view->CurrentState()->SetLowColor(RGBColor(color)); 456 } 457 458 459 static void 460 set_stipple_pattern(ViewLayer *view, pattern p) 461 { 462 printf("SetStipplePattern\n"); 463 } 464 465 466 static void 467 set_scale(ViewLayer *view, float scale) 468 { 469 view->CurrentState()->SetScale(scale); 470 } 471 472 473 static void 474 set_font_family(ViewLayer *view, char *family) 475 { 476 printf("SetFontFamily(%s)\n", family); 477 } 478 479 480 static void 481 set_font_style(ViewLayer *view, char *style) 482 { 483 printf("SetFontStyle(%s)\n", style); 484 } 485 486 487 static void 488 set_font_spacing(ViewLayer *view, int32 spacing) 489 { 490 printf("SetFontSpacing(%ld)\n", spacing); 491 } 492 493 494 static void 495 set_font_size(ViewLayer *view, float size) 496 { 497 ServerFont font; 498 font.SetSize(size); 499 view->CurrentState()->SetFont(font, B_FONT_SIZE); 500 } 501 502 503 static void 504 set_font_rotate(ViewLayer *view, float rotation) 505 { 506 printf("SetFontRotate(%.2f)\n", rotation); 507 } 508 509 510 static void 511 set_font_encoding(ViewLayer *view, int32 encoding) 512 { 513 printf("SetFontEncoding(%ld)\n", encoding); 514 } 515 516 517 static void 518 set_font_flags(ViewLayer *view, int32 flags) 519 { 520 printf("SetFontFlags(%ld)\n", flags); 521 } 522 523 524 static void 525 set_font_shear(ViewLayer *view, float shear) 526 { 527 printf("SetFontShear(%.2f)\n", shear); 528 } 529 530 531 static void 532 set_font_face(ViewLayer *view, int32 flags) 533 { 534 printf("SetFontFace(%ld)\n", flags); 535 } 536 537 538 static void 539 set_blending_mode(ViewLayer *view, int16 alphaSrcMode, int16 alphaFncMode) 540 { 541 view->CurrentState()->SetBlendingMode((source_alpha)alphaSrcMode, (alpha_function)alphaFncMode); 542 } 543 544 545 static void 546 reserved() 547 { 548 } 549 550 551 const void *tableEntries[] = { 552 (const void *)nop, 553 (const void *)move_pen_by, 554 (const void *)stroke_line, 555 (const void *)stroke_rect, 556 (const void *)fill_rect, 557 (const void *)stroke_round_rect, 558 (const void *)fill_round_rect, 559 (const void *)stroke_bezier, 560 (const void *)fill_bezier, 561 (const void *)stroke_arc, 562 (const void *)fill_arc, 563 (const void *)stroke_ellipse, 564 (const void *)fill_ellipse, 565 (const void *)stroke_polygon, 566 (const void *)fill_polygon, 567 (const void *)stroke_shape, 568 (const void *)fill_shape, 569 (const void *)draw_string, 570 (const void *)draw_pixels, 571 (const void *)reserved, // TODO: This is probably "draw_picture". Investigate 572 (const void *)set_clipping_rects, 573 (const void *)clip_to_picture, 574 (const void *)push_state, 575 (const void *)pop_state, 576 (const void *)enter_state_change, 577 (const void *)exit_state_change, 578 (const void *)enter_font_state, 579 (const void *)exit_font_state, 580 (const void *)set_origin, 581 (const void *)set_pen_location, 582 (const void *)set_drawing_mode, 583 (const void *)set_line_mode, 584 (const void *)set_pen_size, 585 (const void *)set_fore_color, 586 (const void *)set_back_color, 587 (const void *)set_stipple_pattern, 588 (const void *)set_scale, 589 (const void *)set_font_family, 590 (const void *)set_font_style, 591 (const void *)set_font_spacing, 592 (const void *)set_font_size, 593 (const void *)set_font_rotate, 594 (const void *)set_font_encoding, 595 (const void *)set_font_flags, 596 (const void *)set_font_shear, 597 (const void *)reserved, // TODO: Marc Flerackers calls this "set_font_bpp". Investigate 598 (const void *)set_font_face, // TODO: R5 function table ends here... how is set blending mode implemented there ? 599 (const void *)set_blending_mode 600 }; 601 602 603 // ServerPicture 604 ServerPicture::ServerPicture() 605 { 606 fToken = gTokenSpace.NewToken(kPictureToken, this); 607 } 608 609 610 ServerPicture::ServerPicture(const ServerPicture &picture) 611 { 612 fToken = gTokenSpace.NewToken(kPictureToken, this); 613 614 AddData(picture.Data(), picture.DataLength()); 615 } 616 617 618 ServerPicture::~ServerPicture() 619 { 620 } 621 622 623 void 624 ServerPicture::BeginOp(int16 op) 625 { 626 fStack.push(fData.Position()); 627 fData.Write(&op, sizeof(op)); 628 629 // Init the size of the opcode block to 0 630 size_t size = 0; 631 fData.Write(&size, sizeof(size)); 632 } 633 634 635 void 636 ServerPicture::EndOp() 637 { 638 off_t curPos = fData.Position(); 639 off_t stackPos = fStack.top(); 640 fStack.pop(); 641 642 // The size of the op is calculated like this: 643 // current position on the stream minus the position on the stack, 644 // minus the space occupied by the op code itself (int16) 645 // and the space occupied by the size field (size_t) 646 size_t size = curPos - stackPos - sizeof(size_t) - sizeof(int16); 647 648 // Size was set to 0 in BeginOp(). Now we overwrite it with the correct value 649 fData.Seek(stackPos + sizeof(int16), SEEK_SET); 650 fData.Write(&size, sizeof(size)); 651 fData.Seek(curPos, SEEK_SET); 652 } 653 654 655 void 656 ServerPicture::EnterStateChange() 657 { 658 // BeginOp(B_PIC_ENTER_STATE_CHANGE); 659 } 660 661 662 void 663 ServerPicture::ExitStateChange() 664 { 665 // EndOp(); 666 } 667 668 669 void 670 ServerPicture::EnterFontChange() 671 { 672 // BeginOp(B_PIC_ENTER_FONT_STATE); 673 } 674 675 676 void 677 ServerPicture::ExitFontChange() 678 { 679 // EndOp(); 680 } 681 682 683 void 684 ServerPicture::AddInt8(int8 data) 685 { 686 fData.Write(&data, sizeof(data)); 687 } 688 689 690 void 691 ServerPicture::AddInt16(int16 data) 692 { 693 fData.Write(&data, sizeof(data)); 694 } 695 696 697 void 698 ServerPicture::AddInt32(int32 data) 699 { 700 fData.Write(&data, sizeof(data)); 701 } 702 703 704 void 705 ServerPicture::AddInt64(int64 data) 706 { 707 fData.Write(&data, sizeof(data)); 708 } 709 710 711 void 712 ServerPicture::AddFloat(float data) 713 { 714 fData.Write(&data, sizeof(data)); 715 } 716 717 718 void 719 ServerPicture::AddCoord(BPoint data) 720 { 721 fData.Write(&data, sizeof(data)); 722 } 723 724 725 void 726 ServerPicture::AddRect(BRect data) 727 { 728 fData.Write(&data, sizeof(data)); 729 } 730 731 732 void 733 ServerPicture::AddColor(rgb_color data) 734 { 735 fData.Write(&data, sizeof(data)); 736 } 737 738 739 void 740 ServerPicture::AddString(const char *data) 741 { 742 int32 len = data ? strlen(data) : 0; 743 fData.Write(&len, sizeof(int32)); 744 fData.Write(data, len); 745 } 746 747 748 void 749 ServerPicture::AddData(const void *data, int32 size) 750 { 751 fData.Write(data, size); 752 } 753 754 755 void 756 ServerPicture::SyncState(ViewLayer *view) 757 { 758 BeginOp(B_PIC_ENTER_STATE_CHANGE); 759 760 BeginOp(B_PIC_SET_PEN_LOCATION); 761 AddCoord(view->CurrentState()->PenLocation()); 762 EndOp(); 763 764 BeginOp(B_PIC_SET_PEN_SIZE); 765 AddFloat(view->CurrentState()->PenSize()); 766 EndOp(); 767 768 BeginOp(B_PIC_SET_SCALE); 769 AddFloat(view->CurrentState()->Scale()); 770 EndOp(); 771 772 BeginOp(B_PIC_SET_LINE_MODE); 773 AddInt16((int16)view->CurrentState()->LineCapMode()); 774 AddInt16((int16)view->CurrentState()->LineJoinMode()); 775 AddFloat(view->CurrentState()->MiterLimit()); 776 EndOp(); 777 778 BeginOp(B_PIC_SET_STIPLE_PATTERN); 779 AddData(view->CurrentState()->GetPattern().GetInt8(), sizeof(pattern)); 780 EndOp(); 781 782 BeginOp(B_PIC_SET_DRAWING_MODE); 783 AddInt16((int16)view->CurrentState()->GetDrawingMode()); 784 EndOp(); 785 786 BeginOp(B_PIC_SET_BLENDING_MODE); 787 AddInt16((int16)view->CurrentState()->AlphaSrcMode()); 788 AddInt16((int16)view->CurrentState()->AlphaFncMode()); 789 EndOp(); 790 791 BeginOp(B_PIC_SET_FORE_COLOR); 792 AddColor(view->CurrentState()->HighColor().GetColor32()); 793 EndOp(); 794 795 BeginOp(B_PIC_SET_BACK_COLOR); 796 AddColor(view->CurrentState()->LowColor().GetColor32()); 797 EndOp(); 798 799 EndOp(); 800 } 801 802 803 void 804 ServerPicture::Play(ViewLayer *view) 805 { 806 PicturePlayer player(const_cast<void *>(fData.Buffer()), fData.BufferLength(), NULL); 807 player.Play(const_cast<void **>(tableEntries), sizeof(tableEntries) / sizeof(void *), view); 808 } 809