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