xref: /haiku/src/tests/servers/app/painter/main.cpp (revision f2b4344867e97c3f4e742a1b4a15e6879644601a)
1 // main.cpp
2 
3 #include <stdio.h>
4 
5 #include <Application.h>
6 #include <Bitmap.h>
7 #include <GraphicsDefs.h>
8 #include <Region.h>
9 #include <Window.h>
10 
11 #include "BitmapView.h"
12 #include "BitmapBuffer.h"
13 #include "FontManager.h"
14 #include "Painter.h"
15 
16 const pattern kStripes = (pattern){ { 0xc7, 0x8f, 0x1f, 0x3e, 0x7c, 0xf8, 0xf1, 0xe3 } };
17 const pattern kDotted = (pattern){ { 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa } };
18 const pattern kDottedBigger = (pattern){ { 0x33, 0x33, 0xcc, 0xcc, 0x33, 0x33, 0xcc, 0xcc } };
19 
20 // test_straight_lines
21 template<class Surface>
22 bigtime_t
23 test_straight_lines(Surface& s, uint32 width, uint32 height)
24 {
25 	bigtime_t now = system_time();
26 
27 	s.SetPenSize(1.0);
28 	s.SetDrawingMode(B_OP_COPY);
29 	s.SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_OVERLAY);
30 
31 	s.SetHighColor(0, 0, 0, 255);
32 	s.SetLowColor(130, 0, 20, 255);
33 
34 	const pattern pat = B_SOLID_HIGH;
35 
36 	for (uint32 y = 0; y <= height; y += 5) {
37 		s.StrokeLine(BPoint(0, y), BPoint(width - 1, y), pat);
38 	}
39 	for (uint32 x = 0; x <= width; x += 5) {
40 		s.StrokeLine(BPoint(x, 0), BPoint(x, height - 1), pat);
41 	}
42 
43 	s.Sync();
44 
45 	return system_time() - now;
46 }
47 
48 // test_fill_rect
49 template<class Surface>
50 bigtime_t
51 test_fill_rect(Surface& s, uint32 width, uint32 height)
52 {
53 	bigtime_t now = system_time();
54 
55 	s.SetPenSize(1.0);
56 	s.SetDrawingMode(B_OP_COPY);
57 	s.SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_OVERLAY);
58 
59 	s.SetHighColor(0, 0, 0, 255);
60 	s.SetLowColor(130, 0, 20, 255);
61 
62 	const pattern pat = B_SOLID_HIGH;
63 
64 	BRect r;
65 	for (uint32 y = 10; y <= height; y += 20) {
66 		for (uint32 x = 10; x <= width; x += 20) {
67 			r.Set(x - 9, y - 9, x + 9, y + 9);
68 			s.FillRect(r, pat);
69 		}
70 	}
71 
72 	s.Sync();
73 
74 	return system_time() - now;
75 }
76 
77 // test_ellipses
78 template<class Surface>
79 bigtime_t
80 test_ellipses(Surface& s, uint32 width, uint32 height)
81 {
82 	bigtime_t now = system_time();
83 
84 	s.SetPenSize(2.0);
85 	s.SetDrawingMode(B_OP_COPY);
86 	s.SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_OVERLAY);
87 
88 	s.SetHighColor(0, 0, 0, 255);
89 	s.SetLowColor(130, 0, 20, 255);
90 
91 	const pattern pat = B_SOLID_HIGH;
92 
93 	BPoint center(floorf(width / 2.0), floorf(height / 2.0));
94 	float xRadius = width / 2.0;
95 	float yRadius = height / 2.0;
96 
97 	uint32 count = 40;
98 	for (uint32 i = 0; i < count; i ++) {
99 		s.StrokeEllipse(center, xRadius * (i / (float)count),
100 								yRadius * (i / (float)count), pat);
101 	}
102 
103 	s.Sync();
104 
105 	return system_time() - now;
106 }
107 
108 // test_lines
109 template<class Surface>
110 bigtime_t
111 test_lines(Surface& s, uint32 width, uint32 height)
112 {
113 	bigtime_t now = system_time();
114 
115 	s.SetPenSize(1.0);
116 	s.SetDrawingMode(B_OP_COPY);
117 	s.SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_OVERLAY);
118 
119 	s.SetHighColor(0, 0, 0, 255);
120 	s.SetLowColor(130, 0, 20, 255);
121 
122 	const pattern pat = B_SOLID_HIGH;
123 
124 	for (uint32 y = 0; y <= height; y += 10) {
125 		s.StrokeLine(BPoint(0, 0), BPoint(width, y), pat);
126 		s.StrokeLine(BPoint(width - 1, 0), BPoint(0, y), pat);
127 	}
128 	for (uint32 x = 0; x <= width; x += 10) {
129 		s.StrokeLine(BPoint(0, 0), BPoint(x, height), pat);
130 		s.StrokeLine(BPoint(width - 1, 0), BPoint(x, height), pat);
131 	}
132 
133 	s.Sync();
134 
135 	return system_time() - now;
136 }
137 
138 // test
139 template<class Surface>
140 bigtime_t
141 test(Surface& s, uint32 width, uint32 height, BBitmap* testBitmap)
142 {
143 	bigtime_t now = system_time();
144 
145 // TODO: Painter behaves differently when origin has subpixel offset
146 //	BPoint origin(20.3, 10.8);
147 	BPoint origin(20, 10);
148 
149 	BPoint center(width / 2.0, height / 2.0);
150 	float xRadius = 30.0;
151 	float yRadius = 20.0;
152 
153 	s.SetOrigin(origin);
154 	s.SetScale(1.0);
155 
156 	s.SetDrawingMode(B_OP_COPY);
157 //	s.SetDrawingMode(B_OP_SUBTRACT);
158 //	s.SetDrawingMode(B_OP_OVER);
159 	s.SetHighColor(20, 20, 20, 255);
160 	s.SetLowColor(220, 120, 80, 255);
161 	for (uint32 y = 0; y <= height / 2; y += 10)
162 		s.StrokeLine(BPoint(0, 0), BPoint(width / 2, y)/*, kDottedBigger*/);
163 	for (uint32 x = 0; x <= width; x += 10)
164 		s.StrokeLine(BPoint(0, 0), BPoint(x, height)/*, kDottedBigger*/);
165 	s.SetPenSize(1.0 * 5);
166 	s.SetHighColor(255, 0, 0, 255);
167 	s.SetLowColor(0, 0, 255, 255);
168 //	s.SetScale(1.0);
169 //	s.SetOrigin(B_ORIGIN);
170 //	s.SetDrawingMode(B_OP_INVERT);
171 	s.SetDrawingMode(B_OP_COPY);
172 //	s.StrokeRect(BRect(20.2, 45.6, 219.0, 139.0));
173 	s.StrokeRect(BRect(20.2, 45.6, 219.0, 139.0), kStripes);
174 
175 //	s.ConstrainClipping(noClip);
176 /*	s.SetPenLocation(BPoint(230.0, 30.0));
177 	s.StrokeLine(BPoint(250.0, 30.0));
178 	s.StrokeLine(BPoint(250.0, 50.0));
179 	s.StrokeLine(BPoint(230.0, 50.0));
180 	s.StrokeLine(BPoint(230.0, 30.0));*/
181 
182 	s.SetHighColor(255, 255, 0, 255);
183 	s.SetLowColor(128, 0, 50, 255);
184 //	s.SetDrawingMode(B_OP_OVER);
185 	s.SetDrawingMode(B_OP_ERASE);
186 	s.StrokeEllipse(center, xRadius, yRadius, kDottedBigger);
187 	s.SetHighColor(255, 0, 0, 255);
188 	s.SetDrawingMode(B_OP_INVERT);
189 	s.FillArc(center, xRadius * 2, yRadius * 2, 40.0, 230.0);
190 //	s.StrokeArc(center, xRadius * 2, yRadius * 2, 40.0, 230.0);
191 	s.SetDrawingMode(B_OP_OVER);
192 	s.SetPenSize(2.0);
193 	s.StrokeEllipse(center, xRadius * 3, yRadius * 2);
194 //	s.FillEllipse(center, xRadius * 3, yRadius * 2);
195 //	s.StrokeLine(bounds.RightTop());
196 //	s.FillRect(rect);
197 	s.SetHighColor(0, 0, 255, 255);
198 	s.SetLowColor(255, 0, 0, 255);
199 	s.SetPenSize(1.0);
200 //	s.SetDrawingMode(B_OP_SELECT);
201 	s.StrokeRoundRect(BRect(40, 100, 250, 220.0), 40, 40);
202 //	s.FillRoundRect(BRect(40, 100, 250, 220.0), 40, 40);
203 
204 	// text rendering
205 	const char* string1 = "The Quick Brown Fox...";
206 	const char* string2 = "jumps!";
207 	BPoint stringLocation1(10.0, 220.0);
208 	BPoint stringLocation2(30.0 / 2.5, 115.0 / 2.5);
209 
210 	BFont font(be_plain_font);
211 	font.SetSize(12.0);
212 	font.SetRotation(8.0);
213 //	font.SetFamilyAndStyle(1);
214 
215 	s.SetFont(&font);
216 	s.SetHighColor(91, 105, 98, 120);
217 	s.SetDrawingMode(B_OP_OVER);
218 	s.DrawString(string1, stringLocation1);
219 	s.DrawString(string2);
220 	s.StrokeLine(BPoint(width - 1, 0));
221 
222 //	s.SetScale(2.5);
223 	s.SetDrawingMode(B_OP_INVERT);
224 	s.SetHighColor(200, 200, 200, 255);
225 	s.DrawString("H", stringLocation2);
226 	s.DrawString("e");
227 	s.DrawString("l");
228 	s.DrawString("l");
229 	s.DrawString("o");
230 	s.DrawString(" ");
231 	s.DrawString("N");
232 	s.DrawString("u");
233 	s.DrawString("r");
234 	s.DrawString("s");
235 	s.DrawString("e");
236 	s.DrawString("!");
237 	// do the char locations match up?
238 //	s.SetHighColor(0, 60, 240);
239 //	s.DrawString("Hello Nurse!", stringLocation2);
240 
241 	// bitmap drawing
242 	BRect testBitmapCrop(testBitmap->Bounds());
243 	testBitmapCrop.left += 20.0;
244 	BRect testBitmapDestRect(testBitmapCrop);
245 	testBitmapDestRect.OffsetBy(50, 20);
246 
247 	s.SetScale(1.5);
248 	s.SetDrawingMode(B_OP_ALPHA);
249 	s.SetHighColor(0, 0, 0, 120);
250 	s.DrawBitmap(testBitmap, testBitmapCrop, testBitmapDestRect);
251 
252 	s.Sync();
253 
254 	return system_time() - now;
255 }
256 
257 
258 
259 // main
260 int
261 main(int argc, char **argv)
262 {
263 	BApplication* app = new BApplication("application/x.vnd-YellowBites.TestApp");
264 
265 	// create the default instance of the FontManager
266 	// It takes a bit to scan through the font files;
267 	// "true" means to do the font scanning inline, not
268 	// in a separate thread.
269 	fprintf(stdout, "scanning font files...");
270 	fflush(stdout);
271 	FontManager::CreateDefault(true);
272 	fprintf(stdout, "done\n");
273 
274 	BRect bounds(0.0, 0.0, 319.0, 239.0);
275 
276 	// test the clipping
277 	BRegion noClip(bounds);
278 
279 	int32 clipCount = 5;
280 	BRegion clip;
281 	float h = bounds.Width() / clipCount;
282 	float v = bounds.Height() / clipCount;
283 	float hInset = (h / 2.0) * 0.5;
284 	float vInset = (v / 2.0) * 0.5;
285 	for (int32 i = 0; i < clipCount; i++) {
286 /*		BRect b(h * i, bounds.top, h * i, bounds.bottom);
287 		b.InsetBy(-hInset, 0.0);
288 		clip.Include(b);
289 		b.Set(bounds.left, v * i, bounds.right, v * i);
290 		b.InsetBy(0.0, -vInset);
291 		clip.Include(b);*/
292 		BRect b(bounds.left, v * i, bounds.right, v * i);
293 		b.InsetBy(0.0, -vInset);
294 		clip.Include(b);
295 		b.Set(h * i, bounds.top, h * i, bounds.bottom);
296 		b.InsetBy(-hInset, 0.0);
297 		clip.Include(b);
298 	}
299 
300 	// prepare a test bitmap for bitmap rendering
301 	BBitmap* testBitmap = new BBitmap(BRect(20, 0, 150, 50), 0, B_RGB32);
302 	// fill testBitmap with content
303 	uint8* bits = (uint8*)testBitmap->Bits();
304 	uint32 bitmapWidth = testBitmap->Bounds().IntegerWidth() + 1;
305 	uint32 bitmapHeight = testBitmap->Bounds().IntegerHeight() + 1;
306 	uint32 bpr = testBitmap->BytesPerRow();
307 	for (uint32 y = 0; y < bitmapHeight; y++) {
308 		uint8* h = bits;
309 		for (uint32 x = 0; x < bitmapWidth; x++) {
310 			h[0] = (uint8)((float)x / (float)bitmapWidth * 255.0);
311 			h[1] = (uint8)((float)y / (float)bitmapHeight * 255.0);
312 			h[2] = 255 - (uint8)((float)y / (float)bitmapHeight * 255.0);
313 			h[3] = (uint8)((float)y / (float)bitmapHeight * 255.0);
314 			h += 4;
315 		}
316 		bits += bpr;
317 	}
318 	// make corners a black pixel for testing
319 	bits = (uint8*)testBitmap->Bits();
320 	*(uint32*)(&bits[0]) = 0;
321 	*(uint32*)(&bits[(bitmapWidth - 1) * 4]) = 0;
322 	*(uint32*)(&bits[(bitmapHeight - 1) * bpr]) = 0;
323 	*(uint32*)(&bits[(bitmapHeight - 1) * bpr + (bitmapWidth - 1) * 4]) = 0;
324 
325 	// create a frame buffer
326 	BBitmap* bitmap = new BBitmap(bounds, B_RGB32);
327 //memset(bitmap->Bits(), 0, bitmap->BitsLength());
328 	BitmapBuffer* buffer = new BitmapBuffer(bitmap);
329 	Painter painter;
330 	painter.AttachToBuffer(buffer);
331 
332 	uint32 width = buffer->Width();
333 	uint32 height = buffer->Height();
334 
335 //	painter.ConstrainClipping(clip);
336 
337 	int32 iterations = 40;
338 
339 	fprintf(stdout, "Painter...");
340 	fflush(stdout);
341 
342 	bigtime_t painterNow = 0;
343 	for (int32 i = 0; i < iterations; i++) {
344 		// reset bitmap contents
345 		memset(bitmap->Bits(), 255, bitmap->BitsLength());
346 		// run test
347 //		painterNow += test(painter, width, height, testBitmap);
348 //		painterNow += test_lines(painter, width, height);
349 //		painterNow += test_straight_lines(painter, width, height);
350 		painterNow += test_fill_rect(painter, width, height);
351 //		painterNow += test_ellipses(painter, width, height);
352 	}
353 
354 fprintf(stdout, " %lld µsecs\n", painterNow / iterations);
355 
356 	BitmapView* painterView = new BitmapView(bounds, "view", bitmap);
357 
358 	bitmap = new BBitmap(bounds, B_RGB32, true);
359 	BView* view = new BView(bounds, NULL, B_FOLLOW_NONE, B_WILL_DRAW);
360 //memset(bitmap->Bits(), 0, bitmap->BitsLength());
361 	bitmap->Lock();
362 	bitmap->AddChild(view);
363 
364 //	view->ConstrainClippingRegion(&clip);
365 
366 	fprintf(stdout, "BView...");
367 	fflush(stdout);
368 
369 	bigtime_t viewNow = 0;
370 	for (int32 i = 0; i < iterations; i++) {
371 		// reset bitmap contents
372 		memset(bitmap->Bits(), 255, bitmap->BitsLength());
373 		// run test
374 //		viewNow += test(*view, width, height, testBitmap);
375 //		viewNow += test_lines(*view, width, height);
376 //		viewNow += test_straight_lines(*view, width, height);
377 		viewNow += test_fill_rect(*view, width, height);
378 //		viewNow += test_ellipses(*view, width, height);
379 	}
380 
381 	bitmap->Unlock();
382 
383 	fprintf(stdout, " %lld µsecs\n", viewNow / iterations);
384 
385 	if (painterNow > viewNow)
386 		printf("BView is %.2f times faster.\n", (float)painterNow / (float)viewNow);
387 	else
388 		printf("Painter is %.2f times faster.\n", (float)viewNow / (float)painterNow);
389 
390 
391 	BitmapView* bViewView = new BitmapView(bounds, "view", bitmap);
392 	bViewView->MoveTo(BPoint(bounds.left, bounds.bottom + 1));
393 
394 	BWindow* window = new BWindow(BRect(50.0, 50.0, 50.0 + bounds.Width(), 50.0 + bounds.Height() * 2 + 1), "Painter Test",
395 								  B_TITLED_WINDOW,
396 								  B_ASYNCHRONOUS_CONTROLS | B_QUIT_ON_WINDOW_CLOSE);
397 
398 	window->AddChild(painterView);
399 	window->AddChild(bViewView);
400 
401 	window->Show();
402 	app->Run();
403 	delete app;
404 	return 0;
405 }
406