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