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