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 <ft2build.h> 14 #include FT_CONFIG_OPTIONS_H 15 // for detected the availablility of subpixel anti-aliasing 16 17 #include <Box.h> 18 #include <Catalog.h> 19 #include <LayoutBuilder.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 30 #include "APRWindow.h" 31 32 #undef B_TRANSLATION_CONTEXT 33 #define B_TRANSLATION_CONTEXT "AntialiasingSettingsView" 34 35 36 //#define DISABLE_HINTING_CONTROL 37 // if defined, the hinting menu is disabled (hinting not properly 38 // implemented) 39 40 static const int32 kMsgSetAntialiasing = 'anti'; 41 static const int32 kMsgSetHinting = 'hint'; 42 static const int32 kMsgSetAverageWeight = 'avrg'; 43 static const char* kSubpixelLabel = B_TRANSLATE_MARK("LCD subpixel"); 44 static const char* kGrayscaleLabel = B_TRANSLATE_MARK("Grayscale"); 45 static const char* kNoHintingLabel = B_TRANSLATE_MARK("Off"); 46 static const char* kMonospacedHintingLabel = 47 B_TRANSLATE_MARK("Monospaced fonts only"); 48 static const char* kFullHintingLabel = B_TRANSLATE_MARK("On"); 49 50 51 // #pragma mark - private libbe API 52 53 54 enum { 55 HINTING_MODE_OFF = 0, 56 HINTING_MODE_ON, 57 HINTING_MODE_MONOSPACED_ONLY 58 }; 59 60 static const uint8 kDefaultHintingMode = HINTING_MODE_ON; 61 static const unsigned char kDefaultAverageWeight = 120; 62 static const bool kDefaultSubpixelAntialiasing = false; 63 64 extern void set_subpixel_antialiasing(bool subpix); 65 extern status_t get_subpixel_antialiasing(bool* subpix); 66 extern void set_hinting_mode(uint8 hinting); 67 extern status_t get_hinting_mode(uint8* hinting); 68 extern void set_average_weight(unsigned char averageWeight); 69 extern status_t get_average_weight(unsigned char* averageWeight); 70 71 72 // #pragma mark - 73 74 75 AntialiasingSettingsView::AntialiasingSettingsView(const char* name) 76 : BView(name, 0) 77 { 78 // collect the current system settings 79 if (get_subpixel_antialiasing(&fCurrentSubpixelAntialiasing) != B_OK) 80 fCurrentSubpixelAntialiasing = kDefaultSubpixelAntialiasing; 81 fSavedSubpixelAntialiasing = fCurrentSubpixelAntialiasing; 82 83 if (get_hinting_mode(&fCurrentHinting) != B_OK) 84 fCurrentHinting = kDefaultHintingMode; 85 fSavedHinting = fCurrentHinting; 86 87 if (get_average_weight(&fCurrentAverageWeight) != B_OK) 88 fCurrentAverageWeight = kDefaultAverageWeight; 89 fSavedAverageWeight = fCurrentAverageWeight; 90 91 // create the controls 92 93 // antialiasing menu 94 _BuildAntialiasingMenu(); 95 fAntialiasingMenuField = new BMenuField("antialiasing", 96 B_TRANSLATE("Antialiasing type:"), fAntialiasingMenu); 97 98 // "average weight" in subpixel filtering 99 fAverageWeightControl = new BSlider("averageWeightControl", 100 B_TRANSLATE("Reduce colored edges filter strength:"), 101 new BMessage(kMsgSetAverageWeight), 0, 255, B_HORIZONTAL); 102 fAverageWeightControl->SetLimitLabels(B_TRANSLATE("Off"), 103 B_TRANSLATE("Strong")); 104 fAverageWeightControl->SetHashMarks(B_HASH_MARKS_BOTTOM); 105 fAverageWeightControl->SetHashMarkCount(255 / 15); 106 fAverageWeightControl->SetEnabled(false); 107 108 // hinting menu 109 _BuildHintingMenu(); 110 fHintingMenuField = new BMenuField("hinting", B_TRANSLATE("Glyph hinting:"), 111 fHintingMenu); 112 113 #ifdef DISABLE_HINTING_CONTROL 114 fHintingMenuField->SetEnabled(false); 115 #endif 116 117 #ifndef FT_CONFIG_OPTION_SUBPIXEL_RENDERING 118 // subpixelAntialiasingDisabledLabel 119 // TODO: Replace with layout friendly constructor once available. 120 fSubpixelAntialiasingDisabledLabel 121 = new BTextView("unavailable label"); 122 fSubpixelAntialiasingDisabledLabel->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 fSubpixelAntialiasingDisabledLabel->SetViewUIColor(B_PANEL_BACKGROUND_COLOR); 128 fSubpixelAntialiasingDisabledLabel->MakeEditable(false); 129 fSubpixelAntialiasingDisabledLabel->MakeSelectable(false); 130 #endif // !FT_CONFIG_OPTION_SUBPIXEL_RENDERING 131 132 BLayoutBuilder::Grid<>(this, B_USE_DEFAULT_SPACING, B_USE_DEFAULT_SPACING) 133 // controls pane 134 .Add(fHintingMenuField->CreateLabelLayoutItem(), 0, 0) 135 .Add(fHintingMenuField->CreateMenuBarLayoutItem(), 1, 0) 136 137 .Add(fAntialiasingMenuField->CreateLabelLayoutItem(), 0, 1) 138 .Add(fAntialiasingMenuField->CreateMenuBarLayoutItem(), 1, 1) 139 140 .Add(fAverageWeightControl, 0, 2, 2) 141 142 #ifndef FT_CONFIG_OPTION_SUBPIXEL_RENDERING 143 // hinting+subpixel unavailable info 144 .Add(fSubpixelAntialiasingDisabledLabel, 0, 3, 2) 145 #else 146 .Add(BSpaceLayoutItem::CreateGlue(), 0, 3, 2) 147 #endif 148 .AddGlue(0, 4) 149 .SetInsets(B_USE_WINDOW_SPACING); 150 151 _SetCurrentAntialiasing(); 152 _SetCurrentHinting(); 153 _SetCurrentAverageWeight(); 154 _UpdateColors(); 155 } 156 157 158 AntialiasingSettingsView::~AntialiasingSettingsView() 159 { 160 } 161 162 163 void 164 AntialiasingSettingsView::AttachedToWindow() 165 { 166 AdoptParentColors(); 167 168 if (Parent() == NULL) 169 SetViewUIColor(B_PANEL_BACKGROUND_COLOR); 170 171 fAntialiasingMenu->SetTargetForItems(this); 172 fHintingMenu->SetTargetForItems(this); 173 fAverageWeightControl->SetTarget(this); 174 } 175 176 177 void 178 AntialiasingSettingsView::MessageReceived(BMessage *msg) 179 { 180 switch (msg->what) { 181 case kMsgSetAntialiasing: 182 { 183 bool subpixelAntialiasing; 184 if (msg->FindBool("antialiasing", &subpixelAntialiasing) != B_OK 185 || subpixelAntialiasing == fCurrentSubpixelAntialiasing) 186 break; 187 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 case B_COLORS_UPDATED: 223 { 224 if (msg->HasColor(ui_color_name(B_PANEL_BACKGROUND_COLOR)) 225 || msg->HasColor(ui_color_name(B_PANEL_TEXT_COLOR))) { 226 _UpdateColors(); 227 } 228 break; 229 } 230 default: 231 BView::MessageReceived(msg); 232 } 233 } 234 235 236 void 237 AntialiasingSettingsView::_BuildAntialiasingMenu() 238 { 239 fAntialiasingMenu = new BPopUpMenu(B_TRANSLATE("Antialiasing menu")); 240 241 BMessage* message = new BMessage(kMsgSetAntialiasing); 242 message->AddBool("antialiasing", false); 243 244 BMenuItem* item 245 = new BMenuItem(B_TRANSLATE_NOCOLLECT(kGrayscaleLabel), message); 246 247 fAntialiasingMenu->AddItem(item); 248 249 message = new BMessage(kMsgSetAntialiasing); 250 message->AddBool("antialiasing", true); 251 252 item = new BMenuItem(B_TRANSLATE_NOCOLLECT(kSubpixelLabel), message); 253 254 fAntialiasingMenu->AddItem(item); 255 } 256 257 258 void 259 AntialiasingSettingsView::_BuildHintingMenu() 260 { 261 fHintingMenu = new BPopUpMenu(B_TRANSLATE("Hinting menu")); 262 263 BMessage* message = new BMessage(kMsgSetHinting); 264 message->AddInt8("hinting", HINTING_MODE_OFF); 265 fHintingMenu->AddItem(new BMenuItem(B_TRANSLATE_NOCOLLECT(kNoHintingLabel), 266 message)); 267 268 message = new BMessage(kMsgSetHinting); 269 message->AddInt8("hinting", HINTING_MODE_ON); 270 fHintingMenu->AddItem(new BMenuItem( 271 B_TRANSLATE_NOCOLLECT(kFullHintingLabel), message)); 272 273 message = new BMessage(kMsgSetHinting); 274 message->AddInt8("hinting", HINTING_MODE_MONOSPACED_ONLY); 275 fHintingMenu->AddItem(new BMenuItem( 276 B_TRANSLATE_NOCOLLECT(kMonospacedHintingLabel), message)); 277 } 278 279 280 void 281 AntialiasingSettingsView::_SetCurrentAntialiasing() 282 { 283 BMenuItem *item = fAntialiasingMenu->FindItem( 284 fCurrentSubpixelAntialiasing 285 ? B_TRANSLATE_NOCOLLECT(kSubpixelLabel) 286 : B_TRANSLATE_NOCOLLECT(kGrayscaleLabel)); 287 if (item != NULL) 288 item->SetMarked(true); 289 if (fCurrentSubpixelAntialiasing) 290 fAverageWeightControl->SetEnabled(true); 291 } 292 293 294 void 295 AntialiasingSettingsView::_SetCurrentHinting() 296 { 297 const char* label; 298 switch (fCurrentHinting) { 299 case HINTING_MODE_OFF: 300 label = kNoHintingLabel; 301 break; 302 case HINTING_MODE_ON: 303 label = kFullHintingLabel; 304 break; 305 case HINTING_MODE_MONOSPACED_ONLY: 306 label = kMonospacedHintingLabel; 307 break; 308 default: 309 return; 310 } 311 312 BMenuItem *item = fHintingMenu->FindItem(B_TRANSLATE_NOCOLLECT(label)); 313 if (item != NULL) 314 item->SetMarked(true); 315 } 316 317 318 void 319 AntialiasingSettingsView::_SetCurrentAverageWeight() 320 { 321 fAverageWeightControl->SetValue(fCurrentAverageWeight); 322 } 323 324 325 void 326 AntialiasingSettingsView::_UpdateColors() 327 { 328 #ifndef FT_CONFIG_OPTION_SUBPIXEL_RENDERING 329 rgb_color infoColor = disable_color(ui_color(B_PANEL_BACKGROUND_COLOR), 330 ui_color(B_PANEL_TEXT_COLOR)); 331 332 BFont font; 333 uint32 mode = 0; 334 fSubpixelAntialiasingDisabledLabel->GetFontAndColor(&font, &mode); 335 font.SetFace(B_ITALIC_FACE); 336 fSubpixelAntialiasingDisabledLabel->SetFontAndColor(&font, mode, 337 &infoColor); 338 #endif 339 } 340 341 342 void 343 AntialiasingSettingsView::SetDefaults() 344 { 345 if (!IsDefaultable()) 346 return; 347 348 fCurrentSubpixelAntialiasing = kDefaultSubpixelAntialiasing; 349 fCurrentHinting = kDefaultHintingMode; 350 fCurrentAverageWeight = kDefaultAverageWeight; 351 352 set_subpixel_antialiasing(fCurrentSubpixelAntialiasing); 353 set_hinting_mode(fCurrentHinting); 354 set_average_weight(fCurrentAverageWeight); 355 356 _SetCurrentAntialiasing(); 357 _SetCurrentHinting(); 358 _SetCurrentAverageWeight(); 359 } 360 361 362 bool 363 AntialiasingSettingsView::IsDefaultable() 364 { 365 return fCurrentSubpixelAntialiasing != kDefaultSubpixelAntialiasing 366 || fCurrentHinting != kDefaultHintingMode 367 || fCurrentAverageWeight != kDefaultAverageWeight; 368 } 369 370 371 bool 372 AntialiasingSettingsView::IsRevertable() 373 { 374 return fCurrentSubpixelAntialiasing != fSavedSubpixelAntialiasing 375 || fCurrentHinting != fSavedHinting 376 || fCurrentAverageWeight != fSavedAverageWeight; 377 } 378 379 380 void 381 AntialiasingSettingsView::Revert() 382 { 383 if (!IsRevertable()) 384 return; 385 386 fCurrentSubpixelAntialiasing = fSavedSubpixelAntialiasing; 387 fCurrentHinting = fSavedHinting; 388 fCurrentAverageWeight = fSavedAverageWeight; 389 390 set_subpixel_antialiasing(fCurrentSubpixelAntialiasing); 391 set_hinting_mode(fCurrentHinting); 392 set_average_weight(fCurrentAverageWeight); 393 394 _SetCurrentAntialiasing(); 395 _SetCurrentHinting(); 396 _SetCurrentAverageWeight(); 397 } 398