1/*
2 * Copyright 2014 Haiku, Inc.
3 * Distributed under the terms of the MIT license.
4 *
5 * Authors:
6 * Adrien Destugues <pulkomandy@pulkomandy.tk>
7 */
8
9
10#include <algorithm>
11#include <stdio.h>
12#include <string.h>
13
14#include <Application.h>
15#include <GradientLinear.h>
16#include <GradientRadial.h>
17#include <LayoutBuilder.h>
18#include <List.h>
19#include <Message.h>
20#include <Picture.h>
21#include <PopUpMenu.h>
22#include <Roster.h>
23#include <ScrollView.h>
24#include <String.h>
25#include <StringView.h>
26#include <View.h>
27#include <Window.h>
28
29#include "harness.h"
30
31
32static const char* kAppSignature = "application/x-vnd.Haiku-Gradients";
33
34
35// #pragma mark - Test1
36
37
38class RadialGradientTest : public Test {
39public:
40	RadialGradientTest()
41		:
42		Test("Radial Gradient")
43	{
44	}
45
46	virtual void Draw(BView* view, BRect updateRect)
47	{
48		// Draws two radial gradients with the same stops and different radiis,
49		// and their enclosing circles. The gradients and circles should have
50		// the same size.
51		BGradientRadial g1(100, 100, 50);
52		BGradientRadial g2(300, 100, 100);
53
54		g1.AddColor(make_color(0,0,0,255), 0);
55		g1.AddColor(make_color(255,255,255,255), 255);
56
57		g2.AddColor(make_color(0,0,0,255), 0);
58		g2.AddColor(make_color(255,255,255,255), 255);
59
60		BRect r1(0, 0, 200, 200);
61		BRect r2(200, 0, 400, 200);
62		view->FillRect(r1, g1);
63		view->FillRect(r2, g2);
64
65		r1.InsetBy(50, 50);
66		view->StrokeEllipse(r1);
67		view->StrokeEllipse(r2);
68	}
69};
70
71
72// Test for https://dev.haiku-os.org/ticket/2946
73// Gradients with an alpha channel are not drawn properly
74class AlphaGradientTest : public Test {
75public:
76	AlphaGradientTest()
77		:
78		Test("Alpha gradients")
79	{
80	}
81
82	virtual void Draw(BView* view, BRect updateRect)
83	{
84		view->SetDrawingMode(B_OP_ALPHA);
85
86		// These draw as almost transparent
87
88		// Radial gradient
89		BPoint center(50, 50);
90		float radius = 50.0;
91		BGradientRadial g(center, radius);
92		g.AddColor((rgb_color){ 255, 0, 0, 255 }, 0.0);
93		g.AddColor((rgb_color){ 0, 255, 0, 0 }, 255.0);
94		view->FillEllipse(center, radius, radius, g);
95
96		// Linear gradient - Horizontal
97		BPoint from(100, 0);
98		BPoint to(200, 0);
99		BGradientLinear l(from, to);
100		l.AddColor((rgb_color){ 255, 0, 0, 0 }, 0.0);
101		l.AddColor((rgb_color){ 0, 255, 0, 255 }, 255.0);
102		view->FillRect(BRect(100, 0, 200, 100), l);
103
104		// Linear gradient - Vertical
105		// (this uses a different code path in app_server)
106		BPoint top(0, 0);
107		BPoint bot(0, 100);
108		BGradientLinear v(top, bot);
109		v.AddColor((rgb_color){ 255, 0, 0, 0 }, 0.0);
110		v.AddColor((rgb_color){ 0, 255, 0, 255 }, 255.0);
111		view->FillRect(BRect(200, 0, 300, 100), v);
112
113		// These draw as opaque or almost opaque
114
115		view->SetOrigin(BPoint(0, 100));
116
117		// Radial gradient
118		BGradientRadial go(center, radius);
119		go.AddColor((rgb_color){ 255, 0, 0, 0 }, 0.0);
120		go.AddColor((rgb_color){ 0, 255, 0, 255 }, 255.0);
121		view->FillEllipse(center, radius, radius, go);
122
123		// Linear gradient - Horizontal
124		BGradientLinear lo(from, to);
125		lo.AddColor((rgb_color){ 255, 0, 0, 255 }, 0.0);
126		lo.AddColor((rgb_color){ 0, 255, 0, 0 }, 255.0);
127		view->FillRect(BRect(100, 0, 200, 100), lo);
128
129		// Linear gradient - Vertical
130		// (this uses a different code path in app_server)
131		BGradientLinear vo(top, bot);
132		vo.AddColor((rgb_color){ 255, 0, 0, 255 }, 0.0);
133		vo.AddColor((rgb_color){ 0, 255, 0, 0 }, 255.0);
134		view->FillRect(BRect(200, 0, 300, 100), vo);
135
136		// Finally, do the same using ClipToPicture. This forces using an
137		// unpacked scanline rasterizer, and it works.
138		view->SetOrigin(BPoint(0, 0));
139
140		view->SetDrawingMode(B_OP_COPY);
141
142		BPicture picture;
143		view->BeginPicture(&picture);
144		view->SetHighColor(make_color(0,0,0,255));
145		view->FillRect(BRect(0, 200, 300, 300));
146		view->EndPicture();
147		view->ClipToPicture(&picture);
148
149		view->SetOrigin(BPoint(0, 200));
150
151		view->SetDrawingMode(B_OP_ALPHA);
152
153		view->FillEllipse(center, radius, radius, g);
154		view->FillRect(BRect(100, 0, 200, 100), l);
155		view->FillRect(BRect(200, 0, 300, 100), v);
156	}
157};
158
159
160// Test for https://dev.haiku-os.org/ticket/2945
161// Gradients with no stop at offset 0 or 255 draw random colors
162class OutOfBoundsGradientTest : public Test {
163public:
164	OutOfBoundsGradientTest()
165		:
166		Test("Out of bounds gradients")
167	{
168	}
169
170	virtual void Draw(BView* view, BRect updateRect)
171	{
172		{
173			// Linear gradient - Vertical
174			BPoint from(275, 10);
175			BPoint to(275, 138);
176			BGradientLinear l(from, to);
177			l.AddColor((rgb_color){ 255, 0, 0, 255 }, 100.0);
178			l.AddColor((rgb_color){ 255, 255, 0, 255 }, 156.0);
179			view->FillRect(BRect(275, 10, 2*265, 265), l);
180		}
181
182		{
183			// Linear gradient - Horizontal
184			BPoint from(10, 10);
185			BPoint to(138, 10);
186			BGradientLinear l(from, to);
187			l.AddColor((rgb_color){ 255, 0, 0, 255 }, 100.0);
188			l.AddColor((rgb_color){ 255, 255, 0, 255 }, 156.0);
189			view->FillRect(BRect(10, 10, 265, 265), l);
190		}
191	}
192};
193
194
195// #pragma mark -
196
197
198int
199main(int argc, char** argv)
200{
201	BApplication app(kAppSignature);
202
203	TestWindow* window = new TestWindow("Gradient tests");
204
205	window->AddTest(new RadialGradientTest());
206	window->AddTest(new AlphaGradientTest());
207	window->AddTest(new OutOfBoundsGradientTest());
208
209	window->SetToTest(0);
210	window->Show();
211
212	app.Run();
213	return 0;
214}
215