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