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 39 static const int32 kMsgSetAntialiasing = 'anti'; 40 static const int32 kMsgSetHinting = 'hint'; 41 static const int32 kMsgSetAverageWeight = 'avrg'; 42 static const char* kSubpixelLabel = B_TRANSLATE_MARK("LCD subpixel"); 43 static const char* kGrayscaleLabel = B_TRANSLATE_MARK("Grayscale"); 44 static const char* kNoHintingLabel = B_TRANSLATE_MARK("Off"); 45 static const char* kMonospacedHintingLabel = 46 B_TRANSLATE_MARK("Monospaced fonts only"); 47 static const char* kFullHintingLabel = B_TRANSLATE_MARK("On"); 48 49 50 // #pragma mark - private libbe API 51 52 53 enum { 54 HINTING_MODE_OFF = 0, 55 HINTING_MODE_ON, 56 HINTING_MODE_MONOSPACED_ONLY 57 }; 58 59 static const uint8 kDefaultHintingMode = HINTING_MODE_ON; 60 static const unsigned char kDefaultAverageWeight = 120; 61 static const bool kDefaultSubpixelAntialiasing = false; 62 63 extern void set_subpixel_antialiasing(bool subpix); 64 extern status_t get_subpixel_antialiasing(bool* subpix); 65 extern void set_hinting_mode(uint8 hinting); 66 extern status_t get_hinting_mode(uint8* hinting); 67 extern void set_average_weight(unsigned char averageWeight); 68 extern status_t get_average_weight(unsigned char* averageWeight); 69 70 71 // #pragma mark - 72 73 74 AntialiasingSettingsView::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 166 AntialiasingSettingsView::~AntialiasingSettingsView() 167 { 168 } 169 170 171 void 172 AntialiasingSettingsView::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 185 void 186 AntialiasingSettingsView::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 239 void 240 AntialiasingSettingsView::_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 261 void 262 AntialiasingSettingsView::_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 283 void 284 AntialiasingSettingsView::_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 297 void 298 AntialiasingSettingsView::_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 321 void 322 AntialiasingSettingsView::_SetCurrentAverageWeight() 323 { 324 fAverageWeightControl->SetValue(fCurrentAverageWeight); 325 } 326 327 328 void 329 AntialiasingSettingsView::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 348 bool 349 AntialiasingSettingsView::IsDefaultable() 350 { 351 return fCurrentSubpixelAntialiasing != kDefaultSubpixelAntialiasing 352 || fCurrentHinting != kDefaultHintingMode 353 || fCurrentAverageWeight != kDefaultAverageWeight; 354 } 355 356 357 bool 358 AntialiasingSettingsView::IsRevertable() 359 { 360 return fCurrentSubpixelAntialiasing != fSavedSubpixelAntialiasing 361 || fCurrentHinting != fSavedHinting 362 || fCurrentAverageWeight != fSavedAverageWeight; 363 } 364 365 366 void 367 AntialiasingSettingsView::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