1 /* 2 * Copyright 2007, Haiku. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Michael Pfeiffer 7 */ 8 9 #include "PictureTestCases.h" 10 11 #include <GradientLinear.h> 12 #include <GradientRadial.h> 13 #include <GradientRadialFocus.h> 14 #include <GradientDiamond.h> 15 #include <GradientConic.h> 16 17 #include <stdio.h> 18 19 static const rgb_color kBlack = {0, 0, 0}; 20 static const rgb_color kWhite = {255, 255, 255}; 21 static const rgb_color kRed = {255, 0, 0}; 22 static const rgb_color kGreen = {0, 255, 0}; 23 static const rgb_color kBlue = {0, 0, 255}; 24 25 static BPoint centerPoint(BRect rect) 26 { 27 int x = (int)(rect.left + rect.IntegerWidth() / 2); 28 int y = (int)(rect.top + rect.IntegerHeight() / 2); 29 return BPoint(x, y); 30 } 31 32 static void testNoOp(BView *view, BRect frame) 33 { 34 // no op 35 } 36 37 static void testDrawChar(BView *view, BRect frame) 38 { 39 view->MovePenTo(frame.left, frame.bottom - 5); 40 view->DrawChar('A'); 41 42 view->DrawChar('B', BPoint(frame.left + 20, frame.bottom - 5)); 43 } 44 45 static void testDrawString(BView *view, BRect frame) 46 { 47 BFont font; 48 view->GetFont(&font); 49 font_height height; 50 font.GetHeight(&height); 51 float baseline = frame.bottom - height.descent; 52 // draw base line 53 view->SetHighColor(kGreen); 54 view->StrokeLine(BPoint(frame.left, baseline - 1), BPoint(frame.right, baseline -1)); 55 56 view->SetHighColor(kBlack); 57 view->DrawString("Haiku [ÖÜÄöüä]", BPoint(frame.left, baseline)); 58 } 59 60 static void testDrawStringWithLength(BView *view, BRect frame) 61 { 62 BFont font; 63 view->GetFont(&font); 64 font_height height; 65 font.GetHeight(&height); 66 float baseline = frame.bottom - height.descent; 67 // draw base line 68 view->SetHighColor(kGreen); 69 view->StrokeLine(BPoint(frame.left, baseline - 1), BPoint(frame.right, baseline -1)); 70 71 view->SetHighColor(kBlack); 72 view->DrawString("Haiku [ÖÜÄöüä]", 13, BPoint(frame.left, baseline)); 73 } 74 75 76 static void testDrawStringWithOffsets(BView* view, BRect frame) 77 { 78 BFont font; 79 view->GetFont(&font); 80 font_height height; 81 font.GetHeight(&height); 82 float baseline = frame.bottom - height.descent; 83 // draw base line 84 view->SetHighColor(kGreen); 85 view->StrokeLine(BPoint(frame.left, baseline - 1), BPoint(frame.right, baseline -1)); 86 87 view->SetHighColor(kBlack); 88 BPoint point(frame.left, baseline); 89 BPoint pointArray[] = { 90 point, 91 point, 92 point, 93 point, 94 point 95 }; 96 97 for (size_t i = 1; i < (sizeof(pointArray) / sizeof(pointArray[0])); i++) 98 pointArray[i] = pointArray[i - 1] + BPoint(10, 0); 99 100 view->DrawString("Haiku", pointArray, sizeof(pointArray) / sizeof(pointArray[0])); 101 } 102 103 104 static void testDrawStringWithoutPosition(BView* view, BRect frame) 105 { 106 BFont font; 107 view->GetFont(&font); 108 font_height height; 109 font.GetHeight(&height); 110 float baseline = frame.bottom - height.descent; 111 // draw base line 112 view->SetHighColor(kGreen); 113 view->StrokeLine(BPoint(frame.left, baseline - 1), BPoint(frame.right, baseline -1)); 114 115 view->SetHighColor(kBlack); 116 view->MovePenTo(BPoint(frame.left, baseline)); 117 view->DrawString("H"); 118 view->DrawString("a"); 119 view->DrawString("i"); 120 view->DrawString("k"); 121 view->DrawString("u"); 122 } 123 124 125 static void testFillArc(BView *view, BRect frame) 126 { 127 frame.InsetBy(2, 2); 128 view->FillArc(frame, 45, 180); 129 } 130 131 static void testStrokeArc(BView *view, BRect frame) 132 { 133 frame.InsetBy(2, 2); 134 view->StrokeArc(frame, 45, 180); 135 } 136 137 static void testFillBezier(BView *view, BRect frame) 138 { 139 frame.InsetBy(2, 2); 140 BPoint points[4]; 141 points[0] = BPoint(frame.left, frame.bottom); 142 points[1] = BPoint(frame.left, frame.top); 143 points[1] = BPoint(frame.left, frame.top); 144 points[3] = BPoint(frame.right, frame.top); 145 view->FillBezier(points); 146 } 147 148 static void testStrokeBezier(BView *view, BRect frame) 149 { 150 frame.InsetBy(2, 2); 151 BPoint points[4]; 152 points[0] = BPoint(frame.left, frame.bottom); 153 points[1] = BPoint(frame.left, frame.top); 154 points[1] = BPoint(frame.left, frame.top); 155 points[3] = BPoint(frame.right, frame.top); 156 view->StrokeBezier(points); 157 } 158 159 static void testFillEllipse(BView *view, BRect frame) 160 { 161 frame.InsetBy(2, 2); 162 view->FillEllipse(frame); 163 164 view->SetHighColor(kRed); 165 float r = frame.Width() / 3; 166 float s = frame.Height() / 4; 167 view->FillEllipse(centerPoint(frame), r, s); 168 } 169 170 static void testStrokeEllipse(BView *view, BRect frame) 171 { 172 frame.InsetBy(2, 2); 173 view->StrokeEllipse(frame); 174 175 view->SetHighColor(kRed); 176 float r = frame.Width() / 3; 177 float s = frame.Height() / 4; 178 view->StrokeEllipse(centerPoint(frame), r, s); 179 } 180 181 static void testFillPolygon(BView *view, BRect frame) 182 { 183 frame.InsetBy(2, 2); 184 185 BPoint points[4]; 186 points[0] = BPoint(frame.left, frame.top); 187 points[1] = BPoint(frame.right, frame.bottom); 188 points[2] = BPoint(frame.right, frame.top); 189 points[3] = BPoint(frame.left, frame.bottom); 190 191 view->FillPolygon(points, 4); 192 } 193 194 static void testStrokePolygon(BView *view, BRect frame) 195 { 196 frame.InsetBy(2, 2); 197 198 BPoint points[4]; 199 points[0] = BPoint(frame.left, frame.top); 200 points[1] = BPoint(frame.right, frame.bottom); 201 points[2] = BPoint(frame.right, frame.top); 202 points[3] = BPoint(frame.left, frame.bottom); 203 204 view->StrokePolygon(points, 4); 205 } 206 207 static void testFillRect(BView *view, BRect frame) 208 { 209 frame.InsetBy(2, 2); 210 view->FillRect(frame); 211 } 212 213 static void testFillRectGradientLinear(BView* view, BRect frame) 214 { 215 BGradientLinear gradient(0, 0, frame.right, frame.bottom); 216 gradient.AddColor(kRed, 0); 217 gradient.AddColor(kBlue, 255); 218 frame.InsetBy(2, 2); 219 view->FillRect(frame, gradient); 220 } 221 222 static void testFillRectGradientRadial(BView* view, BRect frame) 223 { 224 BGradientRadial gradient(10, 10, 10); 225 gradient.AddColor(kRed, 0); 226 gradient.AddColor(kBlue, 255); 227 frame.InsetBy(2, 2); 228 view->FillRect(frame, gradient); 229 } 230 231 static void testFillRectGradientRadialFocus(BView* view, BRect frame) 232 { 233 BGradientRadialFocus gradient(0, 0, 10, 10, 5); 234 gradient.AddColor(kRed, 0); 235 gradient.AddColor(kBlue, 255); 236 frame.InsetBy(2, 2); 237 view->FillRect(frame, gradient); 238 } 239 240 static void testFillRectGradientDiamond(BView* view, BRect frame) 241 { 242 BGradientDiamond gradient(0, 10); 243 gradient.AddColor(kRed, 0); 244 gradient.AddColor(kBlue, 255); 245 frame.InsetBy(2, 2); 246 view->FillRect(frame, gradient); 247 } 248 249 static void testFillRectGradientConic(BView* view, BRect frame) 250 { 251 BGradientConic gradient(0, 0, 10); 252 gradient.AddColor(kRed, 0); 253 gradient.AddColor(kBlue, 255); 254 frame.InsetBy(2, 2); 255 view->FillRect(frame, gradient); 256 } 257 258 static void testStrokeRect(BView *view, BRect frame) 259 { 260 frame.InsetBy(2, 2); 261 view->StrokeRect(frame); 262 } 263 264 static void testFillRegion(BView *view, BRect frame) 265 { 266 frame.InsetBy(2, 2); 267 BRegion region(frame); 268 frame.InsetBy(10, 10); 269 region.Exclude(frame); 270 view->FillRegion(®ion); 271 } 272 273 static void testFillRegionGradientLinear(BView* view, BRect frame) 274 { 275 BGradientLinear gradient(0, 0, frame.right, frame.bottom); 276 gradient.AddColor(kRed, 0); 277 gradient.AddColor(kBlue, 255); 278 frame.InsetBy(2, 2); 279 BRegion region(frame); 280 frame.InsetBy(10, 10); 281 region.Exclude(frame); 282 view->FillRegion(®ion, gradient); 283 } 284 285 static void testFillRegionGradientRadial(BView* view, BRect frame) 286 { 287 BGradientRadial gradient(10, 10, 10); 288 gradient.AddColor(kRed, 0); 289 gradient.AddColor(kBlue, 255); 290 frame.InsetBy(2, 2); 291 BRegion region(frame); 292 frame.InsetBy(10, 10); 293 region.Exclude(frame); 294 view->FillRegion(®ion, gradient); 295 } 296 297 static void testFillRegionGradientRadialFocus(BView* view, BRect frame) 298 { 299 BGradientRadialFocus gradient(0, 0, 10, 10, 5); 300 gradient.AddColor(kRed, 0); 301 gradient.AddColor(kBlue, 255); 302 frame.InsetBy(2, 2); 303 BRegion region(frame); 304 frame.InsetBy(10, 10); 305 region.Exclude(frame); 306 view->FillRegion(®ion, gradient); 307 } 308 309 static void testFillRegionGradientDiamond(BView* view, BRect frame) 310 { 311 BGradientDiamond gradient(0, 10); 312 gradient.AddColor(kRed, 0); 313 gradient.AddColor(kBlue, 255); 314 frame.InsetBy(2, 2); 315 BRegion region(frame); 316 frame.InsetBy(10, 10); 317 region.Exclude(frame); 318 view->FillRegion(®ion, gradient); 319 } 320 321 static void testFillRegionGradientConic(BView* view, BRect frame) 322 { 323 BGradientConic gradient(0, 0, 10); 324 gradient.AddColor(kRed, 0); 325 gradient.AddColor(kBlue, 255); 326 frame.InsetBy(2, 2); 327 BRegion region(frame); 328 frame.InsetBy(10, 10); 329 region.Exclude(frame); 330 view->FillRegion(®ion, gradient); 331 } 332 333 static void testFillRoundRect(BView *view, BRect frame) 334 { 335 frame.InsetBy(2, 2); 336 view->FillRoundRect(frame, 5, 3); 337 } 338 339 static void testFillRoundRectGradientLinear(BView* view, BRect frame) 340 { 341 BGradientLinear gradient(0, 0, frame.right, frame.bottom); 342 gradient.AddColor(kRed, 0); 343 gradient.AddColor(kBlue, 255); 344 frame.InsetBy(2, 2); 345 view->FillRoundRect(frame, 5, 3, gradient); 346 } 347 348 static void testFillRoundRectGradientRadial(BView* view, BRect frame) 349 { 350 BGradientRadial gradient(10, 10, 10); 351 gradient.AddColor(kRed, 0); 352 gradient.AddColor(kBlue, 255); 353 frame.InsetBy(2, 2); 354 view->FillRoundRect(frame, 5, 3, gradient); 355 } 356 357 static void testFillRoundRectGradientRadialFocus(BView* view, BRect frame) 358 { 359 BGradientRadialFocus gradient(0, 0, 10, 10, 5); 360 gradient.AddColor(kRed, 0); 361 gradient.AddColor(kBlue, 255); 362 view->FillRoundRect(frame, 5, 3, gradient); 363 } 364 365 static void testFillRoundRectGradientDiamond(BView* view, BRect frame) 366 { 367 BGradientDiamond gradient(0, 10); 368 gradient.AddColor(kRed, 0); 369 gradient.AddColor(kBlue, 255); 370 frame.InsetBy(2, 2); 371 view->FillRoundRect(frame, 5, 3, gradient); 372 } 373 374 static void testFillRoundRectGradientConic(BView* view, BRect frame) 375 { 376 BGradientConic gradient(0, 0, 10); 377 gradient.AddColor(kRed, 0); 378 gradient.AddColor(kBlue, 255); 379 frame.InsetBy(2, 2); 380 view->FillRoundRect(frame, 5, 3, gradient); 381 } 382 383 static void testStrokeRoundRect(BView *view, BRect frame) 384 { 385 frame.InsetBy(2, 2); 386 view->StrokeRoundRect(frame, 5, 3); 387 } 388 389 static void testFillTriangle(BView *view, BRect frame) 390 { 391 frame.InsetBy(2, 2); 392 BPoint points[3]; 393 points[0] = BPoint(frame.left, frame.bottom); 394 points[1] = BPoint(centerPoint(frame).x, frame.top); 395 points[2] = BPoint(frame.right, frame.bottom); 396 view->FillTriangle(points[0], points[1], points[2]); 397 } 398 399 static void testFillTriangleGradientLinear(BView* view, BRect frame) 400 { 401 BGradientLinear gradient(0, 0, frame.right, frame.bottom); 402 gradient.AddColor(kRed, 0); 403 gradient.AddColor(kBlue, 255); 404 frame.InsetBy(2, 2); 405 BPoint points[3]; 406 points[0] = BPoint(frame.left, frame.bottom); 407 points[1] = BPoint(centerPoint(frame).x, frame.top); 408 points[2] = BPoint(frame.right, frame.bottom); 409 view->FillTriangle(points[0], points[1], points[2], gradient); 410 } 411 412 static void testFillTriangleGradientRadial(BView* view, BRect frame) 413 { 414 BGradientRadial gradient(10, 10, 10); 415 gradient.AddColor(kRed, 0); 416 gradient.AddColor(kBlue, 255); 417 frame.InsetBy(2, 2); 418 BPoint points[3]; 419 points[0] = BPoint(frame.left, frame.bottom); 420 points[1] = BPoint(centerPoint(frame).x, frame.top); 421 points[2] = BPoint(frame.right, frame.bottom); 422 view->FillTriangle(points[0], points[1], points[2], gradient); 423 } 424 425 static void testFillTriangleGradientRadialFocus(BView* view, BRect frame) 426 { 427 BGradientRadialFocus gradient(0, 0, 10, 10, 5); 428 gradient.AddColor(kRed, 0); 429 gradient.AddColor(kBlue, 255); 430 frame.InsetBy(2, 2); 431 BPoint points[3]; 432 points[0] = BPoint(frame.left, frame.bottom); 433 points[1] = BPoint(centerPoint(frame).x, frame.top); 434 points[2] = BPoint(frame.right, frame.bottom); 435 view->FillTriangle(points[0], points[1], points[2], gradient); 436 } 437 438 static void testFillTriangleGradientDiamond(BView* view, BRect frame) 439 { 440 BGradientDiamond gradient(0, 10); 441 gradient.AddColor(kRed, 0); 442 gradient.AddColor(kBlue, 255); 443 frame.InsetBy(2, 2); 444 BPoint points[3]; 445 points[0] = BPoint(frame.left, frame.bottom); 446 points[1] = BPoint(centerPoint(frame).x, frame.top); 447 points[2] = BPoint(frame.right, frame.bottom); 448 view->FillTriangle(points[0], points[1], points[2], gradient); 449 } 450 451 static void testFillTriangleGradientConic(BView* view, BRect frame) 452 { 453 BGradientConic gradient(0, 0, 10); 454 gradient.AddColor(kRed, 0); 455 gradient.AddColor(kBlue, 255); 456 frame.InsetBy(2, 2); 457 BPoint points[3]; 458 points[0] = BPoint(frame.left, frame.bottom); 459 points[1] = BPoint(centerPoint(frame).x, frame.top); 460 points[2] = BPoint(frame.right, frame.bottom); 461 view->FillTriangle(points[0], points[1], points[2], gradient); 462 } 463 464 static void testStrokeTriangle(BView *view, BRect frame) 465 { 466 frame.InsetBy(2, 2); 467 BPoint points[3]; 468 points[0] = BPoint(frame.left, frame.bottom); 469 points[1] = BPoint(centerPoint(frame).x, frame.top); 470 points[2] = BPoint(frame.right, frame.bottom); 471 view->StrokeTriangle(points[0], points[1], points[2]); 472 } 473 474 static void testStrokeLine(BView *view, BRect frame) 475 { 476 frame.InsetBy(2, 2); 477 view->StrokeLine(BPoint(frame.left, frame.top), BPoint(frame.right, frame.top)); 478 479 frame.top += 2; 480 frame.bottom -= 2; 481 view->StrokeLine(BPoint(frame.left, frame.top), BPoint(frame.right, frame.bottom)); 482 483 frame.bottom += 2;; 484 frame.top = frame.bottom; 485 view->StrokeLine(BPoint(frame.right, frame.top), BPoint(frame.left, frame.top)); 486 } 487 488 static void testFillShape(BView *view, BRect frame) 489 { 490 frame.InsetBy(2, 2); 491 BShape shape; 492 shape.MoveTo(BPoint(frame.left, frame.bottom)); 493 shape.LineTo(BPoint(frame.right, frame.top)); 494 shape.LineTo(BPoint(frame.left, frame.top)); 495 shape.LineTo(BPoint(frame.right, frame.bottom)); 496 view->FillShape(&shape); 497 } 498 499 static void testStrokeShape(BView *view, BRect frame) 500 { 501 frame.InsetBy(2, 2); 502 BShape shape; 503 shape.MoveTo(BPoint(frame.left, frame.bottom)); 504 shape.LineTo(BPoint(frame.right, frame.top)); 505 shape.LineTo(BPoint(frame.left, frame.top)); 506 shape.LineTo(BPoint(frame.right, frame.bottom)); 507 view->StrokeShape(&shape); 508 } 509 510 static void testRecordPicture(BView *view, BRect frame) 511 { 512 BPicture *picture = new BPicture(); 513 view->BeginPicture(picture); 514 view->FillRect(frame); 515 view->EndPicture(); 516 delete picture; 517 } 518 519 static void testRecordAndPlayPicture(BView *view, BRect frame) 520 { 521 BPicture *picture = new BPicture(); 522 view->BeginPicture(picture); 523 frame.InsetBy(2, 2); 524 view->FillRect(frame); 525 view->EndPicture(); 526 view->DrawPicture(picture); 527 delete picture; 528 } 529 530 static void testRecordAndPlayPictureWithOffset(BView *view, BRect frame) 531 { 532 BPicture *picture = new BPicture(); 533 view->BeginPicture(picture); 534 frame.InsetBy(frame.Width() / 4, frame.Height() / 4); 535 frame.OffsetTo(0, 0); 536 view->FillRect(frame); 537 view->EndPicture(); 538 539 view->DrawPicture(picture, BPoint(10, 10)); 540 // color of picture should not change 541 view->SetLowColor(kGreen); 542 view->SetLowColor(kRed); 543 view->DrawPicture(picture, BPoint(0, 0)); 544 delete picture; 545 } 546 547 static void testAppendToPicture(BView *view, BRect frame) 548 { 549 frame.InsetBy(2, 2); 550 view->BeginPicture(new BPicture()); 551 view->FillRect(frame); 552 BPicture* picture = view->EndPicture(); 553 if (picture == NULL) 554 return; 555 556 frame.InsetBy(2, 2); 557 view->AppendToPicture(picture); 558 view->SetHighColor(kRed); 559 view->FillRect(frame); 560 if (view->EndPicture() != picture) 561 return; 562 563 view->DrawPicture(picture); 564 delete picture; 565 } 566 567 static void testDrawScaledPicture(BView* view, BRect frame) 568 { 569 view->BeginPicture(new BPicture()); 570 view->FillRect(BRect(0, 0, 15, 15)); 571 BPicture* picture = view->EndPicture(); 572 573 // first unscaled at left, top 574 view->DrawPicture(picture, BPoint(2, 2)); 575 576 // draw scaled at middle top 577 view->SetScale(0.5); 578 // the drawing offset must be scaled too! 579 view->DrawPicture(picture, BPoint(frame.Width(), 4)); 580 581 delete picture; 582 } 583 584 static void testLineArray(BView *view, BRect frame) 585 { 586 frame.InsetBy(2, 2); 587 view->BeginLineArray(3); 588 view->AddLine(BPoint(frame.left, frame.top), BPoint(frame.right, frame.top), kBlack); 589 590 frame.top += 2; 591 frame.bottom -= 2; 592 view->AddLine(BPoint(frame.left, frame.top), BPoint(frame.right, frame.bottom), kRed); 593 594 frame.bottom += 2;; 595 frame.top = frame.bottom; 596 view->AddLine(BPoint(frame.right, frame.top), BPoint(frame.left, frame.top), kGreen); 597 598 view->EndLineArray(); 599 } 600 601 static void testInvertRect(BView *view, BRect frame) 602 { 603 frame.InsetBy(2, 2); 604 view->InvertRect(frame); 605 } 606 607 static void testInvertRectSetDrawingMode(BView *view, BRect frame) 608 { 609 view->SetDrawingMode(B_OP_ALPHA); 610 view->SetHighColor(128, 128, 128, 128); 611 frame.InsetBy(2, 2); 612 view->InvertRect(frame); 613 frame.InsetBy(10, 10); 614 view->FillRect(frame, B_SOLID_HIGH); 615 } 616 617 static bool isBorder(int32 x, int32 y, int32 width, int32 height) { 618 return x == 0 || y == 0 || x == width - 1 || y == height - 1; 619 } 620 621 static void fillBitmap(BBitmap &bitmap) { 622 int32 height = bitmap.Bounds().IntegerHeight()+1; 623 int32 width = bitmap.Bounds().IntegerWidth()+1; 624 for (int32 y = 0; y < height; y ++) { 625 for (int32 x = 0; x < width; x ++) { 626 char *pixel = (char*)bitmap.Bits(); 627 pixel += bitmap.BytesPerRow() * y + 4 * x; 628 if (isBorder(x, y, width, height)) { 629 // fill with green 630 pixel[0] = 255; 631 pixel[1] = 0; 632 pixel[2] = 255; 633 pixel[3] = 0; 634 } else { 635 // fill with blue 636 pixel[0] = 255; 637 pixel[1] = 0; 638 pixel[2] = 0; 639 pixel[3] = 255; 640 } 641 } 642 } 643 } 644 645 static void testDrawBitmap(BView *view, BRect frame) { 646 BBitmap bitmap(frame, B_RGBA32); 647 fillBitmap(bitmap); 648 view->DrawBitmap(&bitmap, BPoint(0, 0)); 649 } 650 651 static void testDrawBitmapAtPoint(BView *view, BRect frame) { 652 frame.InsetBy(2, 2); 653 654 BRect bounds(frame); 655 bounds.OffsetTo(0, 0); 656 bounds.right /= 2; 657 bounds.bottom /= 2; 658 659 BBitmap bitmap(bounds, B_RGBA32); 660 fillBitmap(bitmap); 661 view->DrawBitmap(&bitmap, centerPoint(frame)); 662 } 663 664 static void testDrawBitmapAtRect(BView *view, BRect frame) { 665 BRect bounds(frame); 666 BBitmap bitmap(bounds, B_RGBA32); 667 fillBitmap(bitmap); 668 frame.InsetBy(2, 2); 669 view->DrawBitmap(&bitmap, frame); 670 } 671 672 static void testDrawLargeBitmap(BView *view, BRect frame) { 673 BRect bounds(frame); 674 bounds.OffsetTo(0, 0); 675 bounds.right *= 4; 676 bounds.bottom *= 4; 677 BBitmap bitmap(bounds, B_RGBA32); 678 fillBitmap(bitmap); 679 frame.InsetBy(2, 2); 680 view->DrawBitmap(&bitmap, frame); 681 } 682 683 static void testConstrainClippingRegion(BView *view, BRect frame) 684 { 685 frame.InsetBy(2, 2); 686 // draw background 687 view->SetHighColor(kRed); 688 view->FillRect(frame); 689 690 frame.InsetBy(1, 1); 691 BRegion region(frame); 692 BRect r(frame); 693 r.InsetBy(r.IntegerWidth() / 4, r.IntegerHeight() / 4); 694 region.Exclude(r); 695 view->ConstrainClippingRegion(®ion); 696 697 frame.InsetBy(-1, -1); 698 view->SetHighColor(kBlack); 699 view->FillRect(frame); 700 // a filled black rectangle with a red one pixel border 701 // and inside a red rectangle should be drawn. 702 } 703 704 static void testClipToPicture(BView *view, BRect frame) 705 { 706 frame.InsetBy(2, 2); 707 view->BeginPicture(new BPicture()); 708 view->FillEllipse(frame); 709 BPicture *picture = view->EndPicture(); 710 if (picture == NULL) 711 return; 712 713 view->ClipToPicture(picture); 714 delete picture; 715 716 view->FillRect(frame); 717 // black ellipse should be drawn 718 } 719 720 static void testClipToInversePicture(BView *view, BRect frame) 721 { 722 frame.InsetBy(2, 2); 723 724 view->BeginPicture(new BPicture()); 725 view->FillEllipse(frame); 726 BPicture *picture = view->EndPicture(); 727 if (picture == NULL) 728 return; 729 730 view->ClipToInversePicture(picture); 731 delete picture; 732 733 view->FillRect(frame); 734 // white ellipse inside a black rectangle 735 } 736 737 static void testSetPenSize(BView *view, BRect frame) 738 { 739 frame.InsetBy(8, 2); 740 float x = centerPoint(frame).x; 741 742 view->StrokeLine(BPoint(frame.left, frame.top), BPoint(frame.right, frame.top)); 743 744 frame.OffsetBy(0, 5); 745 view->SetPenSize(1); 746 view->StrokeLine(BPoint(frame.left, frame.top), BPoint(x, frame.top)); 747 view->SetPenSize(0); 748 view->StrokeLine(BPoint(x+1, frame.top), BPoint(frame.right, frame.top)); 749 750 frame.OffsetBy(0, 5); 751 view->SetPenSize(1); 752 view->StrokeLine(BPoint(frame.left, frame.top), BPoint(x, frame.top)); 753 view->SetPenSize(2); 754 view->StrokeLine(BPoint(x+1, frame.top), BPoint(frame.right, frame.top)); 755 756 frame.OffsetBy(0, 5); 757 view->SetPenSize(1); 758 view->StrokeLine(BPoint(frame.left, frame.top), BPoint(x, frame.top)); 759 view->SetPenSize(3); 760 view->StrokeLine(BPoint(x+1, frame.top), BPoint(frame.right, frame.top)); 761 762 frame.OffsetBy(0, 5); 763 view->SetPenSize(1); 764 view->StrokeLine(BPoint(frame.left, frame.top), BPoint(x, frame.top)); 765 view->SetPenSize(4); 766 view->StrokeLine(BPoint(x+1, frame.top), BPoint(frame.right, frame.top)); 767 } 768 769 static void testSetPenSize2(BView *view, BRect frame) 770 { 771 // test if pen size is scaled too 772 frame.InsetBy(2, 2); 773 frame.OffsetBy(0, 5); 774 view->SetPenSize(4); 775 view->StrokeLine(BPoint(frame.left, frame.top), BPoint(frame.right, frame.top)); 776 view->SetScale(0.5); 777 view->StrokeLine(BPoint(frame.left + 2, frame.bottom), BPoint(frame.right + 2, frame.bottom)); 778 779 // black line from left to right, 4 pixel size 780 // below black line with half the length of the first one 781 // and 2 pixel size 782 } 783 784 static void testPattern(BView *view, BRect frame) 785 { 786 frame.InsetBy(2, 2); 787 int x = frame.IntegerWidth() / 3; 788 frame.right = frame.left + x - 2; 789 // -2 for an empty pixel row between 790 // filled rectangles 791 792 view->SetLowColor(kGreen); 793 view->SetHighColor(kRed); 794 795 view->FillRect(frame, B_SOLID_HIGH); 796 797 frame.OffsetBy(x, 0); 798 view->FillRect(frame, B_MIXED_COLORS); 799 800 frame.OffsetBy(x, 0); 801 view->FillRect(frame, B_SOLID_LOW); 802 } 803 804 static void testSetOrigin(BView *view, BRect frame) 805 { 806 BPoint origin = view->Origin(); 807 BPoint center = centerPoint(frame); 808 view->SetOrigin(center); 809 810 BRect r(0, 0, center.x, center.y); 811 view->SetHighColor(kBlue); 812 view->FillRect(r); 813 814 view->SetOrigin(origin); 815 view->SetHighColor(kRed); 816 view->FillRect(r); 817 818 // red rectangle in left, top corner 819 // blue rectangle in right, bottom corner 820 // the red rectangle overwrites the 821 // top, left pixel of the blue rectangle 822 } 823 824 static void testSetOrigin2(BView *view, BRect frame) 825 { 826 BPoint center = centerPoint(frame); 827 BRect r(0, 0, center.x, center.y); 828 view->SetOrigin(center); 829 view->PushState(); 830 view->SetOrigin(BPoint(-center.x, 0)); 831 view->FillRect(r); 832 view->PopState(); 833 // black rectangle in left, bottom corner 834 } 835 836 static void testSetScale(BView *view, BRect frame) 837 { 838 view->SetScale(0.5); 839 view->FillRect(frame); 840 // black rectangle in left, top corner 841 } 842 843 static void testSetScale2(BView *view, BRect frame) 844 { 845 view->SetScale(0.5); 846 view->PushState(); 847 view->SetScale(0.5); 848 view->FillRect(frame); 849 view->PopState(); 850 // black rectangle in left, top corner 851 // with half the size of the rectangle 852 // from test testSetScaling 853 } 854 855 static void testSetScale3(BView *view, BRect frame) 856 { 857 view->SetScale(0.5); 858 view->PushState(); 859 // if the second scale value differs slightly 860 // the bug under BeOS R5 in testSetScale2 861 // does not occur 862 view->SetScale(0.5000001); 863 view->FillRect(frame); 864 view->PopState(); 865 // black rectangle in left, top corner 866 // with half the size of the rectangle 867 // from test testSetScaling 868 } 869 870 static void testSetOriginAndScale(BView *view, BRect frame) 871 { 872 frame.InsetBy(2, 2); 873 BPoint center = centerPoint(frame); 874 875 BRect r(0, 0, frame.IntegerWidth() / 2, frame.IntegerHeight() / 2); 876 view->SetOrigin(center); 877 view->FillRect(r); 878 879 view->SetScale(0.5); 880 view->SetHighColor(kRed); 881 view->FillRect(r); 882 } 883 884 static void testSetOriginAndScale2(BView *view, BRect frame) 885 { 886 frame.InsetBy(2, 2); 887 BPoint center = centerPoint(frame); 888 889 BRect r(0, 0, frame.IntegerWidth() / 2, frame.IntegerHeight() / 2); 890 view->SetOrigin(center); 891 view->FillRect(r); 892 893 view->SetScale(0.5); 894 view->SetHighColor(kRed); 895 view->FillRect(r); 896 897 view->SetOrigin(0, 0); 898 view->SetHighColor(kGreen); 899 view->FillRect(r); 900 } 901 902 static void testSetOriginAndScale3(BView *view, BRect frame) 903 { 904 frame.InsetBy(2, 2); 905 BPoint center = centerPoint(frame); 906 907 BRect r(0, 0, frame.IntegerWidth() / 2, frame.IntegerHeight() / 2); 908 view->SetOrigin(center); 909 view->FillRect(r); 910 911 view->SetScale(0.5); 912 view->SetHighColor(kRed); 913 view->FillRect(r); 914 915 view->SetScale(0.25); 916 view->SetHighColor(kGreen); 917 view->FillRect(r); 918 } 919 920 static void testSetOriginAndScale4(BView *view, BRect frame) 921 { 922 frame.InsetBy(2, 2); 923 BPoint center = centerPoint(frame); 924 925 BRect r(0, 0, frame.IntegerWidth() / 2, frame.IntegerHeight() / 2); 926 view->SetOrigin(center); 927 view->FillRect(r); 928 929 view->SetScale(0.5); 930 view->SetHighColor(kRed); 931 view->FillRect(r); 932 933 view->PushState(); 934 // 935 view->SetOrigin(center.x+1, center.y); 936 // +1 to work around BeOS bug 937 // where setting the origin has no 938 // effect if it is the same as 939 // the previous value althou 940 // it is from the "outer" coordinate 941 // system 942 view->SetHighColor(kGreen); 943 view->FillRect(r); 944 view->PopState(); 945 } 946 947 static void testSetOriginAndScale5(BView *view, BRect frame) 948 { 949 frame.InsetBy(2, 2); 950 BPoint center = centerPoint(frame); 951 952 BRect r(0, 0, frame.IntegerWidth() / 2, frame.IntegerHeight() / 2); 953 view->SetOrigin(center); 954 view->FillRect(r); 955 956 view->SetScale(0.5); 957 view->SetHighColor(kRed); 958 view->FillRect(r); 959 960 view->PushState(); 961 view->SetScale(0.75); 962 view->SetHighColor(kGreen); 963 view->FillRect(r); 964 view->PopState(); 965 } 966 967 static void testSetFontSize(BView *view, BRect frame) 968 { 969 frame.InsetBy(2, 2); 970 int size = frame.IntegerHeight() / 3; 971 972 frame.OffsetBy(0, size); 973 view->MovePenTo(BPoint(frame.left, frame.top)); 974 view->SetFontSize(size); 975 view->DrawString("Haiku"); 976 977 size *= 2; 978 frame.OffsetBy(0, size); 979 view->MovePenTo(BPoint(frame.left, frame.top)); 980 view->SetFontSize(size); 981 view->DrawString("Haiku"); 982 } 983 984 static void testSetFontFamilyAndStyle(BView *view, BRect frame) 985 { 986 view->DrawString("This is a test", BPoint(2, 6)); 987 988 BFont font; 989 view->GetFont(&font); 990 991 int32 families = count_font_families(); 992 font_family familyName; 993 get_font_family(families - 1, &familyName); 994 995 int32 styles = count_font_styles(familyName); 996 font_style styleName; 997 get_font_style(familyName, styles - 1, &styleName); 998 font.SetFamilyAndStyle(familyName, styleName); 999 view->SetFont(&font); 1000 view->DrawString( "This is a test", BPoint(2, 19)); 1001 } 1002 1003 static void testSetDrawingMode(BView *view, BRect frame) 1004 { 1005 frame.InsetBy(2, 2); 1006 view->StrokeLine(frame.LeftTop(), frame.RightBottom()); 1007 view->StrokeLine(frame.LeftBottom(), frame.RightTop()); 1008 view->SetDrawingMode(B_OP_ALPHA); 1009 rgb_color color = kRed; 1010 color.alpha = 127; 1011 view->SetHighColor(color); 1012 view->FillRect(frame, B_SOLID_HIGH); 1013 } 1014 1015 static void testPushPopState(BView *view, BRect frame) 1016 { 1017 frame.InsetBy(2, 2); 1018 view->SetHighColor(kGreen); 1019 view->PushState(); 1020 view->SetHighColor(kRed); 1021 view->PopState(); 1022 1023 view->FillRect(frame, B_SOLID_HIGH); 1024 } 1025 1026 static void testFontRotation(BView* view, BRect frame) 1027 { 1028 BFont font; 1029 view->GetFont(&font); 1030 1031 font.SetRotation(90); 1032 view->SetFont(&font, B_FONT_ROTATION); 1033 view->DrawString("This is a test!", BPoint(frame.Width() / 2, frame.bottom - 3)); 1034 1035 view->GetFont(&font); 1036 if (font.Rotation() != 90.0) 1037 fprintf(stderr, "Error: Rotation is %f but should be 90.0\n", font.Rotation()); 1038 } 1039 1040 1041 static void testClipToRect(BView* view, BRect frame) 1042 { 1043 BRect clipped = frame; 1044 clipped.InsetBy(5, 5); 1045 1046 view->ClipToRect(clipped); 1047 1048 view->FillRect(frame); 1049 } 1050 1051 1052 static void testClipToInverseRect(BView* view, BRect frame) 1053 { 1054 BRect clipped = frame; 1055 clipped.InsetBy(5, 5); 1056 1057 view->ClipToInverseRect(clipped); 1058 1059 view->FillRect(frame); 1060 } 1061 1062 1063 static void testClipToShape(BView* view, BRect frame) 1064 { 1065 frame.InsetBy(2, 2); 1066 BShape shape; 1067 shape.MoveTo(BPoint(frame.left, frame.bottom)); 1068 shape.LineTo(BPoint(frame.right, frame.top)); 1069 shape.LineTo(BPoint(frame.left, frame.top)); 1070 shape.LineTo(BPoint(frame.right, frame.bottom)); 1071 view->ClipToShape(&shape); 1072 1073 view->FillRect(frame); 1074 } 1075 1076 1077 static void testClipToInverseShape(BView* view, BRect frame) 1078 { 1079 frame.InsetBy(2, 2); 1080 BShape shape; 1081 shape.MoveTo(BPoint(frame.left, frame.bottom)); 1082 shape.LineTo(BPoint(frame.right, frame.top)); 1083 shape.LineTo(BPoint(frame.left, frame.top)); 1084 shape.LineTo(BPoint(frame.right, frame.bottom)); 1085 view->ClipToInverseShape(&shape); 1086 1087 view->FillRect(frame); 1088 } 1089 1090 1091 // TODO 1092 // - blending mode 1093 // - line mode 1094 // - push/pop state 1095 // - move pen 1096 // - set font 1097 1098 1099 TestCase gTestCases[] = { 1100 { "Test No Operation", testNoOp }, 1101 { "Test DrawChar", testDrawChar }, 1102 { "Test Draw String", testDrawString }, 1103 { "Test Draw String With Length", testDrawStringWithLength }, 1104 { "Test Draw String With Offsets", testDrawStringWithOffsets }, 1105 { "Test Draw String Without Position", testDrawStringWithoutPosition }, 1106 { "Test FillArc", testFillArc }, 1107 { "Test StrokeArc", testStrokeArc }, 1108 // testFillBezier fails under BeOS because the 1109 // direct draw version is not correct 1110 { "Test FillBezier", testFillBezier }, 1111 { "Test StrokeBezier", testStrokeBezier }, 1112 { "Test FillEllipse", testFillEllipse }, 1113 { "Test StrokeEllipse", testStrokeEllipse }, 1114 { "Test FillPolygon", testFillPolygon }, 1115 { "Test StrokePolygon", testStrokePolygon }, 1116 { "Test FillRect", testFillRect }, 1117 { "Test FillRectGradientLinear", testFillRectGradientLinear }, 1118 { "Test FillRectGradientRadial", testFillRectGradientRadial }, 1119 { "Test FillRectGradientRadialFocus", testFillRectGradientRadialFocus }, 1120 { "Test FillRectGradientDiamond", testFillRectGradientDiamond }, 1121 { "Test FillRectGradientConic", testFillRectGradientConic }, 1122 { "Test StrokeRect", testStrokeRect }, 1123 { "Test FillRegion", testFillRegion }, 1124 { "Test FillRegionGradientLinear", testFillRegionGradientLinear }, 1125 { "Test FillRegionGradientRadial", testFillRegionGradientRadial }, 1126 { "Test FillRegionGradientRadialFocus", testFillRegionGradientRadialFocus }, 1127 { "Test FillRegionGradientDiamond", testFillRegionGradientDiamond }, 1128 { "Test FillRegionGradientConic", testFillRegionGradientConic }, 1129 { "Test FillRoundRect", testFillRoundRect }, 1130 { "Test FillRoundRectGradientLinear", testFillRoundRectGradientLinear }, 1131 { "Test FillRoundRectGradientRadial", testFillRoundRectGradientRadial }, 1132 { "Test FillRoundRectGradientRadialFocus", testFillRoundRectGradientRadialFocus }, 1133 { "Test FillRoundRectGradientDiamond", testFillRoundRectGradientDiamond }, 1134 { "Test FillRoundRectGradientConic", testFillRoundRectGradientConic }, 1135 { "Test StrokeRoundRect", testStrokeRoundRect }, 1136 { "Test FillTriangle", testFillTriangle }, 1137 { "Test FillTriangleGradientLinear", testFillTriangleGradientLinear }, 1138 { "Test FillTriangleGradientRadial", testFillTriangleGradientRadial }, 1139 { "Test FillTriangleGradientRadialFocus", testFillTriangleGradientRadialFocus }, 1140 { "Test FillTriangleGradientDiamond", testFillTriangleGradientDiamond }, 1141 { "Test FillTriangleGradientConic", testFillTriangleGradientConic }, 1142 { "Test StrokeTriangle", testStrokeTriangle }, 1143 { "Test StrokeLine", testStrokeLine }, 1144 { "Test FillShape", testFillShape }, 1145 { "Test StrokeShape", testStrokeShape }, 1146 { "Test Record Picture", testRecordPicture }, 1147 { "Test Record And Play Picture", testRecordAndPlayPicture }, 1148 { "Test Record And Play Picture With Offset", testRecordAndPlayPictureWithOffset }, 1149 { "Test AppendToPicture", testAppendToPicture }, 1150 { "Test Draw Scaled Picture", testDrawScaledPicture }, 1151 { "Test LineArray", testLineArray }, 1152 { "Test InvertRect", testInvertRect }, 1153 { "Test InvertRectSetDrawingMode", testInvertRectSetDrawingMode }, 1154 { "Test DrawBitmap", testDrawBitmap }, 1155 { "Test DrawBitmapAtPoint", testDrawBitmapAtPoint }, 1156 { "Test DrawBitmapAtRect", testDrawBitmapAtRect }, 1157 { "Test DrawLargeBitmap", testDrawLargeBitmap }, 1158 { "Test ConstrainClippingRegion", testConstrainClippingRegion }, 1159 { "Test ClipToPicture", testClipToPicture }, 1160 { "Test ClipToInversePicture", testClipToInversePicture }, 1161 { "Test ClipToRect", testClipToRect }, 1162 { "Test ClipToInverseRect", testClipToInverseRect }, 1163 { "Test ClipToShape", testClipToShape }, 1164 { "Test ClipToInverseShape", testClipToInverseShape }, 1165 { "Test SetPenSize", testSetPenSize }, 1166 { "Test SetPenSize2", testSetPenSize2 }, 1167 { "Test Pattern", testPattern }, 1168 { "Test SetOrigin", testSetOrigin }, 1169 { "Test SetOrigin2", testSetOrigin2 }, 1170 { "Test SetScale", testSetScale }, 1171 // testSetScale2 fails under BeOS. The picture versions of the 1172 // rectangle are twice as large as the direct draw version 1173 { "Test SetScale2", testSetScale2 }, 1174 { "Test SetScale3", testSetScale3 }, 1175 { "Test SetOriginAndScale", testSetOriginAndScale }, 1176 { "Test SetOriginAndScale2", testSetOriginAndScale2 }, 1177 { "Test SetOriginAndScale3", testSetOriginAndScale3 }, 1178 { "Test SetOriginAndScale4", testSetOriginAndScale4 }, 1179 { "Test SetOriginAndScale5", testSetOriginAndScale5 }, 1180 { "Test SetFontSize", testSetFontSize }, 1181 { "Test SetFontFamilyAndStyle", testSetFontFamilyAndStyle }, 1182 { "Test SetDrawingMode", testSetDrawingMode }, 1183 { "Test PushPopState", testPushPopState }, 1184 { "Test FontRotation", testFontRotation }, 1185 { NULL, NULL } 1186 }; 1187 1188 1189