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