xref: /haiku/src/preferences/appearance/AntialiasingSettingsView.cpp (revision 385ee03ba83b7a40d315e17b03031b3ca37820c0)
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 <LayoutBuilder.h>
20 #include <Locale.h>
21 #include <MenuField.h>
22 #include <MenuItem.h>
23 #include <PopUpMenu.h>
24 #include <Slider.h>
25 #include <SpaceLayoutItem.h>
26 #include <String.h>
27 #include <TextView.h>
28 
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 	// TODO: Replace with layout friendly constructor once available.
120 	fSubpixelAntialiasingDisabledLabel
121 		= new BTextView("unavailable label");
122 	fSubpixelAntialiasingDisabledLabel->SetText(B_TRANSLATE(
123 		"Subpixel based anti-aliasing in combination with glyph hinting is not "
124 		"available in this build of Haiku to avoid possible patent issues. To "
125 		"enable this feature, you have to build Haiku yourself and enable "
126 		"certain options in the libfreetype configuration header."));
127 	fSubpixelAntialiasingDisabledLabel->SetViewUIColor(B_PANEL_BACKGROUND_COLOR);
128 	fSubpixelAntialiasingDisabledLabel->MakeEditable(false);
129 	fSubpixelAntialiasingDisabledLabel->MakeSelectable(false);
130 #endif // !FT_CONFIG_OPTION_SUBPIXEL_RENDERING
131 
132 	BLayoutBuilder::Grid<>(this, B_USE_DEFAULT_SPACING, B_USE_DEFAULT_SPACING)
133 	// controls pane
134 		.Add(fHintingMenuField->CreateLabelLayoutItem(), 0, 0)
135 		.Add(fHintingMenuField->CreateMenuBarLayoutItem(), 1, 0)
136 
137 		.Add(fAntialiasingMenuField->CreateLabelLayoutItem(), 0, 1)
138 		.Add(fAntialiasingMenuField->CreateMenuBarLayoutItem(), 1, 1)
139 
140 		.Add(fAverageWeightControl, 0, 2, 2)
141 
142 #ifndef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
143 		// hinting+subpixel unavailable info
144 		.Add(fSubpixelAntialiasingDisabledLabel, 0, 3, 2)
145 #else
146 		.Add(BSpaceLayoutItem::CreateGlue(), 0, 3, 2)
147 #endif
148 		.AddGlue(0, 4)
149 		.SetInsets(B_USE_WINDOW_SPACING);
150 
151 	_SetCurrentAntialiasing();
152 	_SetCurrentHinting();
153 	_SetCurrentAverageWeight();
154 	_UpdateColors();
155 }
156 
157 
158 AntialiasingSettingsView::~AntialiasingSettingsView()
159 {
160 }
161 
162 
163 void
164 AntialiasingSettingsView::AttachedToWindow()
165 {
166 	AdoptParentColors();
167 
168 	if (Parent() == NULL)
169 		SetViewUIColor(B_PANEL_BACKGROUND_COLOR);
170 
171 	fAntialiasingMenu->SetTargetForItems(this);
172 	fHintingMenu->SetTargetForItems(this);
173 	fAverageWeightControl->SetTarget(this);
174 }
175 
176 
177 void
178 AntialiasingSettingsView::MessageReceived(BMessage *msg)
179 {
180 	switch (msg->what) {
181 		case kMsgSetAntialiasing:
182 		{
183 			bool subpixelAntialiasing;
184 			if (msg->FindBool("antialiasing", &subpixelAntialiasing) != B_OK
185 				|| subpixelAntialiasing == fCurrentSubpixelAntialiasing)
186 				break;
187 
188 			fCurrentSubpixelAntialiasing = subpixelAntialiasing;
189 			fAverageWeightControl->SetEnabled(fCurrentSubpixelAntialiasing);
190 
191 			set_subpixel_antialiasing(fCurrentSubpixelAntialiasing);
192 
193 			Window()->PostMessage(kMsgUpdate);
194 			break;
195 		}
196 		case kMsgSetHinting:
197 		{
198 			int8 hinting;
199 			if (msg->FindInt8("hinting", &hinting) != B_OK
200 				|| hinting == fCurrentHinting)
201 				break;
202 
203 			fCurrentHinting = hinting;
204 			set_hinting_mode(fCurrentHinting);
205 
206 			Window()->PostMessage(kMsgUpdate);
207 			break;
208 		}
209 		case kMsgSetAverageWeight:
210 		{
211 			int32 averageWeight = fAverageWeightControl->Value();
212 			if (averageWeight == fCurrentAverageWeight)
213 				break;
214 
215 			fCurrentAverageWeight = averageWeight;
216 
217 			set_average_weight(fCurrentAverageWeight);
218 
219 			Window()->PostMessage(kMsgUpdate);
220 			break;
221 		}
222 		case B_COLORS_UPDATED:
223 		{
224 			if (msg->HasColor(ui_color_name(B_PANEL_BACKGROUND_COLOR))
225 				|| msg->HasColor(ui_color_name(B_PANEL_TEXT_COLOR))) {
226 				_UpdateColors();
227 			}
228 			break;
229 		}
230 		default:
231 			BView::MessageReceived(msg);
232 	}
233 }
234 
235 
236 void
237 AntialiasingSettingsView::_BuildAntialiasingMenu()
238 {
239 	fAntialiasingMenu = new BPopUpMenu(B_TRANSLATE("Antialiasing menu"));
240 
241 	BMessage* message = new BMessage(kMsgSetAntialiasing);
242 	message->AddBool("antialiasing", false);
243 
244 	BMenuItem* item
245 		= new BMenuItem(B_TRANSLATE_NOCOLLECT(kGrayscaleLabel), message);
246 
247 	fAntialiasingMenu->AddItem(item);
248 
249 	message = new BMessage(kMsgSetAntialiasing);
250 	message->AddBool("antialiasing", true);
251 
252 	item = new BMenuItem(B_TRANSLATE_NOCOLLECT(kSubpixelLabel), message);
253 
254 	fAntialiasingMenu->AddItem(item);
255 }
256 
257 
258 void
259 AntialiasingSettingsView::_BuildHintingMenu()
260 {
261 	fHintingMenu = new BPopUpMenu(B_TRANSLATE("Hinting menu"));
262 
263 	BMessage* message = new BMessage(kMsgSetHinting);
264 	message->AddInt8("hinting", HINTING_MODE_OFF);
265 	fHintingMenu->AddItem(new BMenuItem(B_TRANSLATE_NOCOLLECT(kNoHintingLabel),
266 		message));
267 
268 	message = new BMessage(kMsgSetHinting);
269 	message->AddInt8("hinting", HINTING_MODE_ON);
270 	fHintingMenu->AddItem(new BMenuItem(
271 		B_TRANSLATE_NOCOLLECT(kFullHintingLabel), message));
272 
273 	message = new BMessage(kMsgSetHinting);
274 	message->AddInt8("hinting", HINTING_MODE_MONOSPACED_ONLY);
275 	fHintingMenu->AddItem(new BMenuItem(
276 		B_TRANSLATE_NOCOLLECT(kMonospacedHintingLabel), message));
277 }
278 
279 
280 void
281 AntialiasingSettingsView::_SetCurrentAntialiasing()
282 {
283 	BMenuItem *item = fAntialiasingMenu->FindItem(
284 		fCurrentSubpixelAntialiasing
285 		? B_TRANSLATE_NOCOLLECT(kSubpixelLabel)
286 		: B_TRANSLATE_NOCOLLECT(kGrayscaleLabel));
287 	if (item != NULL)
288 		item->SetMarked(true);
289 	if (fCurrentSubpixelAntialiasing)
290 		fAverageWeightControl->SetEnabled(true);
291 }
292 
293 
294 void
295 AntialiasingSettingsView::_SetCurrentHinting()
296 {
297 	const char* label;
298 	switch (fCurrentHinting) {
299 		case HINTING_MODE_OFF:
300 			label = kNoHintingLabel;
301 			break;
302 		case HINTING_MODE_ON:
303 			label = kFullHintingLabel;
304 			break;
305 		case HINTING_MODE_MONOSPACED_ONLY:
306 			label = kMonospacedHintingLabel;
307 			break;
308 		default:
309 			return;
310 	}
311 
312 	BMenuItem *item = fHintingMenu->FindItem(B_TRANSLATE_NOCOLLECT(label));
313 	if (item != NULL)
314 		item->SetMarked(true);
315 }
316 
317 
318 void
319 AntialiasingSettingsView::_SetCurrentAverageWeight()
320 {
321 	fAverageWeightControl->SetValue(fCurrentAverageWeight);
322 }
323 
324 
325 void
326 AntialiasingSettingsView::_UpdateColors()
327 {
328 #ifndef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
329 	rgb_color infoColor = disable_color(ui_color(B_PANEL_BACKGROUND_COLOR),
330 		ui_color(B_PANEL_TEXT_COLOR));
331 
332 	BFont font;
333 	uint32 mode = 0;
334 	fSubpixelAntialiasingDisabledLabel->GetFontAndColor(&font, &mode);
335 	font.SetFace(B_ITALIC_FACE);
336 	fSubpixelAntialiasingDisabledLabel->SetFontAndColor(&font, mode,
337 		&infoColor);
338 #endif
339 }
340 
341 
342 void
343 AntialiasingSettingsView::SetDefaults()
344 {
345 	if (!IsDefaultable())
346 		return;
347 
348 	fCurrentSubpixelAntialiasing = kDefaultSubpixelAntialiasing;
349 	fCurrentHinting = kDefaultHintingMode;
350 	fCurrentAverageWeight = kDefaultAverageWeight;
351 
352 	set_subpixel_antialiasing(fCurrentSubpixelAntialiasing);
353 	set_hinting_mode(fCurrentHinting);
354 	set_average_weight(fCurrentAverageWeight);
355 
356 	_SetCurrentAntialiasing();
357 	_SetCurrentHinting();
358 	_SetCurrentAverageWeight();
359 }
360 
361 
362 bool
363 AntialiasingSettingsView::IsDefaultable()
364 {
365 	return fCurrentSubpixelAntialiasing != kDefaultSubpixelAntialiasing
366 		|| fCurrentHinting != kDefaultHintingMode
367 		|| fCurrentAverageWeight != kDefaultAverageWeight;
368 }
369 
370 
371 bool
372 AntialiasingSettingsView::IsRevertable()
373 {
374 	return fCurrentSubpixelAntialiasing != fSavedSubpixelAntialiasing
375 		|| fCurrentHinting != fSavedHinting
376 		|| fCurrentAverageWeight != fSavedAverageWeight;
377 }
378 
379 
380 void
381 AntialiasingSettingsView::Revert()
382 {
383 	if (!IsRevertable())
384 		return;
385 
386 	fCurrentSubpixelAntialiasing = fSavedSubpixelAntialiasing;
387 	fCurrentHinting = fSavedHinting;
388 	fCurrentAverageWeight = fSavedAverageWeight;
389 
390 	set_subpixel_antialiasing(fCurrentSubpixelAntialiasing);
391 	set_hinting_mode(fCurrentHinting);
392 	set_average_weight(fCurrentAverageWeight);
393 
394 	_SetCurrentAntialiasing();
395 	_SetCurrentHinting();
396 	_SetCurrentAverageWeight();
397 }
398