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