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
32static const int32 kMsgSetAntialiasing = 'anti';
33static const int32 kMsgSetHinting = 'hint';
34static const int32 kMsgSetAverageWeight = 'avrg';
35static const char* kSubpixelLabel = B_TRANSLATE_MARK("LCD subpixel");
36static const char* kGrayscaleLabel = B_TRANSLATE_MARK("Grayscale");
37static const char* kNoHintingLabel = B_TRANSLATE_MARK("Off");
38static const char* kMonospacedHintingLabel =
39	B_TRANSLATE_MARK("Monospaced fonts only");
40static const char* kFullHintingLabel = B_TRANSLATE_MARK("On");
41
42
43// #pragma mark - private libbe API
44
45
46enum {
47	HINTING_MODE_OFF = 0,
48	HINTING_MODE_ON,
49	HINTING_MODE_MONOSPACED_ONLY
50};
51
52static const uint8 kDefaultHintingMode = HINTING_MODE_ON;
53static const unsigned char kDefaultAverageWeight = 120;
54static const bool kDefaultSubpixelAntialiasing = true;
55
56extern void set_subpixel_antialiasing(bool subpix);
57extern status_t get_subpixel_antialiasing(bool* subpix);
58extern void set_hinting_mode(uint8 hinting);
59extern status_t get_hinting_mode(uint8* hinting);
60extern void set_average_weight(unsigned char averageWeight);
61extern status_t get_average_weight(unsigned char* averageWeight);
62
63
64//	#pragma mark -
65
66
67AntialiasingSettingsView::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
124AntialiasingSettingsView::~AntialiasingSettingsView()
125{
126}
127
128
129void
130AntialiasingSettingsView::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
143void
144AntialiasingSettingsView::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
194void
195AntialiasingSettingsView::_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
216void
217AntialiasingSettingsView::_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
238void
239AntialiasingSettingsView::_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
252void
253AntialiasingSettingsView::_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
276void
277AntialiasingSettingsView::_SetCurrentAverageWeight()
278{
279	fAverageWeightControl->SetValue(fCurrentAverageWeight);
280}
281
282
283void
284AntialiasingSettingsView::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
303bool
304AntialiasingSettingsView::IsDefaultable()
305{
306	return fCurrentSubpixelAntialiasing != kDefaultSubpixelAntialiasing
307		|| fCurrentHinting != kDefaultHintingMode
308		|| fCurrentAverageWeight != kDefaultAverageWeight;
309}
310
311
312bool
313AntialiasingSettingsView::IsRevertable()
314{
315	return fCurrentSubpixelAntialiasing != fSavedSubpixelAntialiasing
316		|| fCurrentHinting != fSavedHinting
317		|| fCurrentAverageWeight != fSavedAverageWeight;
318}
319
320
321void
322AntialiasingSettingsView::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