xref: /haiku/src/preferences/appearance/AntialiasingSettingsView.cpp (revision ca8ed5ea660fb6275799a3b7f138b201c41a667b)
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 			fCurrentSubpixelAntialiasing = subpixelAntialiasing;
198 			fAverageWeightControl->SetEnabled(fCurrentSubpixelAntialiasing);
199 
200 			set_subpixel_antialiasing(fCurrentSubpixelAntialiasing);
201 
202 			Window()->PostMessage(kMsgUpdate);
203 			break;
204 		}
205 		case kMsgSetHinting:
206 		{
207 			int8 hinting;
208 			if (msg->FindInt8("hinting", &hinting) != B_OK
209 				|| hinting == fCurrentHinting)
210 				break;
211 
212 			fCurrentHinting = hinting;
213 			set_hinting_mode(fCurrentHinting);
214 
215 			Window()->PostMessage(kMsgUpdate);
216 			break;
217 		}
218 		case kMsgSetAverageWeight:
219 		{
220 			int32 averageWeight = fAverageWeightControl->Value();
221 			if (averageWeight == fCurrentAverageWeight)
222 				break;
223 
224 			fCurrentAverageWeight = averageWeight;
225 
226 			set_average_weight(fCurrentAverageWeight);
227 
228 			Window()->PostMessage(kMsgUpdate);
229 			break;
230 		}
231 		default:
232 			BView::MessageReceived(msg);
233 	}
234 }
235 
236 
237 void
238 AntialiasingSettingsView::_BuildAntialiasingMenu()
239 {
240 	fAntialiasingMenu = new BPopUpMenu(B_TRANSLATE("Antialiasing menu"));
241 
242 	BMessage* message = new BMessage(kMsgSetAntialiasing);
243 	message->AddBool("antialiasing", false);
244 
245 	BMenuItem* item
246 		= new BMenuItem(B_TRANSLATE_NOCOLLECT(kGrayscaleLabel), message);
247 
248 	fAntialiasingMenu->AddItem(item);
249 
250 	message = new BMessage(kMsgSetAntialiasing);
251 	message->AddBool("antialiasing", true);
252 
253 	item = new BMenuItem(B_TRANSLATE_NOCOLLECT(kSubpixelLabel), message);
254 
255 	fAntialiasingMenu->AddItem(item);
256 }
257 
258 
259 void
260 AntialiasingSettingsView::_BuildHintingMenu()
261 {
262 	fHintingMenu = new BPopUpMenu(B_TRANSLATE("Hinting menu"));
263 
264 	BMessage* message = new BMessage(kMsgSetHinting);
265 	message->AddInt8("hinting", HINTING_MODE_OFF);
266 	fHintingMenu->AddItem(new BMenuItem(B_TRANSLATE_NOCOLLECT(kNoHintingLabel),
267 		message));
268 
269 	message = new BMessage(kMsgSetHinting);
270 	message->AddInt8("hinting", HINTING_MODE_ON);
271 	fHintingMenu->AddItem(new BMenuItem(
272 		B_TRANSLATE_NOCOLLECT(kFullHintingLabel), message));
273 
274 	message = new BMessage(kMsgSetHinting);
275 	message->AddInt8("hinting", HINTING_MODE_MONOSPACED_ONLY);
276 	fHintingMenu->AddItem(new BMenuItem(
277 		B_TRANSLATE_NOCOLLECT(kMonospacedHintingLabel), message));
278 }
279 
280 
281 void
282 AntialiasingSettingsView::_SetCurrentAntialiasing()
283 {
284 	BMenuItem *item = fAntialiasingMenu->FindItem(
285 		fCurrentSubpixelAntialiasing
286 		? B_TRANSLATE_NOCOLLECT(kSubpixelLabel)
287 		: B_TRANSLATE_NOCOLLECT(kGrayscaleLabel));
288 	if (item != NULL)
289 		item->SetMarked(true);
290 	if (fCurrentSubpixelAntialiasing)
291 		fAverageWeightControl->SetEnabled(true);
292 }
293 
294 
295 void
296 AntialiasingSettingsView::_SetCurrentHinting()
297 {
298 	const char* label;
299 	switch (fCurrentHinting) {
300 		case HINTING_MODE_OFF:
301 			label = kNoHintingLabel;
302 			break;
303 		case HINTING_MODE_ON:
304 			label = kFullHintingLabel;
305 			break;
306 		case HINTING_MODE_MONOSPACED_ONLY:
307 			label = kMonospacedHintingLabel;
308 			break;
309 		default:
310 			return;
311 	}
312 
313 	BMenuItem *item = fHintingMenu->FindItem(B_TRANSLATE_NOCOLLECT(label));
314 	if (item != NULL)
315 		item->SetMarked(true);
316 }
317 
318 
319 void
320 AntialiasingSettingsView::_SetCurrentAverageWeight()
321 {
322 	fAverageWeightControl->SetValue(fCurrentAverageWeight);
323 }
324 
325 
326 void
327 AntialiasingSettingsView::SetDefaults()
328 {
329 	if (!IsDefaultable())
330 		return;
331 
332 	fCurrentSubpixelAntialiasing = kDefaultSubpixelAntialiasing;
333 	fCurrentHinting = kDefaultHintingMode;
334 	fCurrentAverageWeight = kDefaultAverageWeight;
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 
345 
346 bool
347 AntialiasingSettingsView::IsDefaultable()
348 {
349 	return fCurrentSubpixelAntialiasing != kDefaultSubpixelAntialiasing
350 		|| fCurrentHinting != kDefaultHintingMode
351 		|| fCurrentAverageWeight != kDefaultAverageWeight;
352 }
353 
354 
355 bool
356 AntialiasingSettingsView::IsRevertable()
357 {
358 	return fCurrentSubpixelAntialiasing != fSavedSubpixelAntialiasing
359 		|| fCurrentHinting != fSavedHinting
360 		|| fCurrentAverageWeight != fSavedAverageWeight;
361 }
362 
363 
364 void
365 AntialiasingSettingsView::Revert()
366 {
367 	if (!IsRevertable())
368 		return;
369 
370 	fCurrentSubpixelAntialiasing = fSavedSubpixelAntialiasing;
371 	fCurrentHinting = fSavedHinting;
372 	fCurrentAverageWeight = fSavedAverageWeight;
373 
374 	set_subpixel_antialiasing(fCurrentSubpixelAntialiasing);
375 	set_hinting_mode(fCurrentHinting);
376 	set_average_weight(fCurrentAverageWeight);
377 
378 	_SetCurrentAntialiasing();
379 	_SetCurrentHinting();
380 	_SetCurrentAverageWeight();
381 }
382