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