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