xref: /haiku/src/preferences/appearance/AntialiasingSettingsView.cpp (revision a4ef4a49150f118d47324242917a596a3f8f8bd5)
1 /*
2  * Copyright 2008, Stephan Aßmus, <superstippi@gmx.de>
3  * Copyright 2008, Andrej Spielmann, <andrej.spielmann@seh.ox.ac.uk>
4  * All rights reserved. Distributed under the terms of the MIT License.
5  */
6 
7 #include "AntialiasingSettingsView.h"
8 
9 #include <stdio.h>
10 #include <stdlib.h>
11 
12 #include <freetype/config/ftoption.h>
13 	// for detected the availablility of subpixel anti-aliasing
14 
15 #include <Box.h>
16 #include <GridLayoutBuilder.h>
17 #include <GroupLayoutBuilder.h>
18 #include <MenuField.h>
19 #include <MenuItem.h>
20 #include <PopUpMenu.h>
21 #include <Slider.h>
22 #include <SpaceLayoutItem.h>
23 #include <String.h>
24 #include <TextView.h>
25 
26 #include "APRWindow.h"
27 
28 
29 //#define DISABLE_HINTING_CONTROL
30 	// if defined, the hinting menu is disabled (hinting not properly
31 	// implemented)
32 
33 static const int32 kMsgSetAntialiasing = 'anti';
34 static const int32 kMsgSetHinting = 'hint';
35 static const int32 kMsgSetAverageWeight = 'avrg';
36 static const char* kSubpixelLabel = "LCD subpixel";
37 static const char* kGrayscaleLabel = "Grayscale";
38 static const char* kNoHintingLabel = "Off";
39 static const char* kMonospacedHintingLabel = "Monospaced Fonts Only";
40 static const char* kFullHintingLabel = "On";
41 
42 
43 // #pragma mark - private libbe API
44 
45 
46 enum {
47 	HINTING_MODE_OFF = 0,
48 	HINTING_MODE_ON,
49 	HINTING_MODE_MONOSPACED_ONLY
50 };
51 
52 extern void set_subpixel_antialiasing(bool subpix);
53 extern status_t get_subpixel_antialiasing(bool* subpix);
54 extern void set_hinting_mode(uint8 hinting);
55 extern status_t get_hinting_mode(uint8* hinting);
56 extern void set_average_weight(unsigned char averageWeight);
57 extern status_t get_average_weight(unsigned char* averageWeight);
58 
59 
60 //	#pragma mark -
61 
62 
63 AntialiasingSettingsView::AntialiasingSettingsView(const char* name)
64 	: BView(name, 0)
65 {
66 	// collect the current system settings
67 	if (get_subpixel_antialiasing(&fCurrentSubpixelAntialiasing) != B_OK)
68 		fCurrentSubpixelAntialiasing = false;
69 	fSavedSubpixelAntialiasing = fCurrentSubpixelAntialiasing;
70 
71 	if (get_hinting_mode(&fCurrentHinting) != B_OK)
72 		fCurrentHinting = HINTING_MODE_ON;
73 	fSavedHinting = fCurrentHinting;
74 
75 	if (get_average_weight(&fCurrentAverageWeight) != B_OK)
76 		fCurrentAverageWeight = 100;
77 	fSavedAverageWeight = fCurrentAverageWeight;
78 
79 	// create the controls
80 
81 	// antialiasing menu
82 	_BuildAntialiasingMenu();
83 	fAntialiasingMenuField = new BMenuField("antialiasing",
84 		"Anti-aliasing type:", fAntialiasingMenu, NULL);
85 
86 	// "average weight" in subpixel filtering
87 	fAverageWeightControl = new BSlider("averageWeightControl",
88 		"Reduce colored edges filter strength:",
89 		new BMessage(kMsgSetAverageWeight), 0, 255, B_HORIZONTAL);
90 	fAverageWeightControl->SetLimitLabels("Off", "Strong");
91 	fAverageWeightControl->SetHashMarks(B_HASH_MARKS_BOTTOM);
92 	fAverageWeightControl->SetHashMarkCount(255 / 15);
93 	fAverageWeightControl->SetEnabled(false);
94 
95 	// hinting menu
96 	_BuildHintingMenu();
97 	fHintingMenuField = new BMenuField("hinting", "Glyph hinting:",
98 		fHintingMenu, NULL);
99 
100 #ifdef DISABLE_HINTING_CONTROL
101 	fHintingMenuField->SetEnabled(false);
102 #endif
103 
104 #ifndef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
105 	// subpixelAntialiasingDisabledLabel
106 	BFont infoFont(*be_plain_font);
107 	infoFont.SetFace(B_ITALIC_FACE);
108 	rgb_color infoColor = tint_color(ui_color(B_PANEL_BACKGROUND_COLOR),
109 		B_DARKEN_4_TINT);
110 	// TODO: Replace with layout friendly constructor once available.
111 	BRect textBounds = Bounds();
112 	BTextView* subpixelAntialiasingDisabledLabel = new BTextView(
113 		textBounds, "unavailable label", textBounds, &infoFont, &infoColor,
114 		B_FOLLOW_NONE, B_WILL_DRAW | B_SUPPORTS_LAYOUT);
115 	subpixelAntialiasingDisabledLabel->SetText("Subpixel based anti-aliasing "
116 		"in combination with glyph hinting is not available in this build of "
117 		"Haiku to avoid possible patent issues. To enable this feature, you "
118 		"have to build Haiku yourself and enable certain options in the "
119 		"libfreetype configuration header.");
120 	subpixelAntialiasingDisabledLabel->SetViewColor(
121 		ui_color(B_PANEL_BACKGROUND_COLOR));
122 	subpixelAntialiasingDisabledLabel->MakeEditable(false);
123 	subpixelAntialiasingDisabledLabel->MakeSelectable(false);
124 #endif // !FT_CONFIG_OPTION_SUBPIXEL_RENDERING
125 
126 	SetLayout(new BGroupLayout(B_VERTICAL));
127 
128 	// controls pane
129 	AddChild(BGridLayoutBuilder(10, 10)
130 		.Add(fHintingMenuField->CreateLabelLayoutItem(), 0, 0)
131 		.Add(fHintingMenuField->CreateMenuBarLayoutItem(), 1, 0)
132 
133 		.Add(fAntialiasingMenuField->CreateLabelLayoutItem(), 0, 1)
134 		.Add(fAntialiasingMenuField->CreateMenuBarLayoutItem(), 1, 1)
135 
136 		.Add(fAverageWeightControl, 0, 2, 2)
137 
138 #ifndef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
139 		// hinting+subpixel unavailable info
140 		.Add(subpixelAntialiasingDisabledLabel, 0, 3, 2)
141 #else
142 		.Add(BSpaceLayoutItem::CreateGlue(), 0, 3, 2)
143 #endif
144 
145 		.SetInsets(10, 10, 10, 10)
146 	);
147 
148 	_SetCurrentAntialiasing();
149 	_SetCurrentHinting();
150 	_SetCurrentAverageWeight();
151 }
152 
153 
154 AntialiasingSettingsView::~AntialiasingSettingsView()
155 {
156 }
157 
158 
159 void
160 AntialiasingSettingsView::AttachedToWindow()
161 {
162 	if (Parent() != NULL)
163 		SetViewColor(Parent()->ViewColor());
164 	else
165 		SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
166 
167 	fAntialiasingMenu->SetTargetForItems(this);
168 	fHintingMenu->SetTargetForItems(this);
169 	fAverageWeightControl->SetTarget(this);
170 }
171 
172 
173 void
174 AntialiasingSettingsView::MessageReceived(BMessage *msg)
175 {
176 	switch (msg->what) {
177 		case kMsgSetAntialiasing:
178 		{
179 			bool subpixelAntialiasing;
180 			if (msg->FindBool("antialiasing", &subpixelAntialiasing) != B_OK
181 				|| subpixelAntialiasing == fCurrentSubpixelAntialiasing)
182 				break;
183 			fCurrentSubpixelAntialiasing = subpixelAntialiasing;
184 			fAverageWeightControl->SetEnabled(fCurrentSubpixelAntialiasing);
185 
186 			set_subpixel_antialiasing(fCurrentSubpixelAntialiasing);
187 
188 			Window()->PostMessage(kMsgUpdate);
189 			break;
190 		}
191 		case kMsgSetHinting:
192 		{
193 			int8 hinting;
194 			if (msg->FindInt8("hinting", &hinting) != B_OK
195 				|| hinting == fCurrentHinting)
196 				break;
197 
198 			fCurrentHinting = hinting;
199 			set_hinting_mode(fCurrentHinting);
200 
201 			Window()->PostMessage(kMsgUpdate);
202 			break;
203 		}
204 		case kMsgSetAverageWeight:
205 		{
206 			int32 averageWeight = fAverageWeightControl->Value();
207 			if (averageWeight == fCurrentAverageWeight)
208 				break;
209 
210 			fCurrentAverageWeight = averageWeight;
211 
212 			set_average_weight(fCurrentAverageWeight);
213 
214 			Window()->PostMessage(kMsgUpdate);
215 			break;
216 		}
217 		default:
218 			BView::MessageReceived(msg);
219 	}
220 }
221 
222 
223 void
224 AntialiasingSettingsView::_BuildAntialiasingMenu()
225 {
226 	fAntialiasingMenu = new BPopUpMenu("Antialiasing menu");
227 
228 	BMessage* message = new BMessage(kMsgSetAntialiasing);
229 	message->AddBool("antialiasing", false);
230 
231 	BMenuItem* item = new BMenuItem(kGrayscaleLabel, message);
232 
233 	fAntialiasingMenu->AddItem(item);
234 
235 	message = new BMessage(kMsgSetAntialiasing);
236 	message->AddBool("antialiasing", true);
237 
238 	item = new BMenuItem(kSubpixelLabel, message);
239 
240 	fAntialiasingMenu->AddItem(item);
241 }
242 
243 
244 void
245 AntialiasingSettingsView::_BuildHintingMenu()
246 {
247 	fHintingMenu = new BPopUpMenu("Hinting menu");
248 
249 	BMessage* message = new BMessage(kMsgSetHinting);
250 	message->AddInt8("hinting", HINTING_MODE_OFF);
251 	fHintingMenu->AddItem(new BMenuItem(kNoHintingLabel, message));
252 
253 	message = new BMessage(kMsgSetHinting);
254 	message->AddInt8("hinting", HINTING_MODE_ON);
255 	fHintingMenu->AddItem(new BMenuItem(kFullHintingLabel, message));
256 
257 	message = new BMessage(kMsgSetHinting);
258 	message->AddInt8("hinting", HINTING_MODE_MONOSPACED_ONLY);
259 	fHintingMenu->AddItem(new BMenuItem(kMonospacedHintingLabel, message));
260 }
261 
262 
263 void
264 AntialiasingSettingsView::_SetCurrentAntialiasing()
265 {
266 	BMenuItem *item = fAntialiasingMenu->FindItem(
267 		fCurrentSubpixelAntialiasing ? kSubpixelLabel : kGrayscaleLabel);
268 	if (item != NULL)
269 		item->SetMarked(true);
270 	if (fCurrentSubpixelAntialiasing)
271 		fAverageWeightControl->SetEnabled(true);
272 }
273 
274 
275 void
276 AntialiasingSettingsView::_SetCurrentHinting()
277 {
278 	const char* label = NULL;
279 	switch (fCurrentHinting) {
280 		case HINTING_MODE_OFF:
281 			label = kNoHintingLabel;
282 			break;
283 		case HINTING_MODE_ON:
284 			label = kFullHintingLabel;
285 			break;
286 		case HINTING_MODE_MONOSPACED_ONLY:
287 			label = kMonospacedHintingLabel;
288 			break;
289 	}
290 
291 	BMenuItem *item = fHintingMenu->FindItem(label);
292 	if (item != NULL)
293 		item->SetMarked(true);
294 }
295 
296 
297 void
298 AntialiasingSettingsView::_SetCurrentAverageWeight()
299 {
300 	fAverageWeightControl->SetValue(fCurrentAverageWeight);
301 }
302 
303 
304 void
305 AntialiasingSettingsView::SetDefaults()
306 {
307 }
308 
309 
310 bool
311 AntialiasingSettingsView::IsDefaultable()
312 {
313 	return false;
314 }
315 
316 
317 bool
318 AntialiasingSettingsView::IsRevertable()
319 {
320 	return fCurrentSubpixelAntialiasing != fSavedSubpixelAntialiasing
321 		|| fCurrentHinting != fSavedHinting
322 		|| fCurrentAverageWeight != fSavedAverageWeight;
323 }
324 
325 
326 void
327 AntialiasingSettingsView::Revert()
328 {
329 	if (!IsRevertable())
330 		return;
331 
332 	fCurrentSubpixelAntialiasing = fSavedSubpixelAntialiasing;
333 	fCurrentHinting = fSavedHinting;
334 	fCurrentAverageWeight = fSavedAverageWeight;
335 
336 	set_subpixel_antialiasing(fCurrentSubpixelAntialiasing);
337 	set_hinting_mode(fCurrentHinting);
338 	set_average_weight(fCurrentAverageWeight);
339 
340 	_SetCurrentAntialiasing();
341 	_SetCurrentHinting();
342 	_SetCurrentAverageWeight();
343 }
344