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 <GridLayoutBuilder.h> 20 #include <GroupLayoutBuilder.h> 21 #include <Locale.h> 22 #include <MenuField.h> 23 #include <MenuItem.h> 24 #include <PopUpMenu.h> 25 #include <Slider.h> 26 #include <SpaceLayoutItem.h> 27 #include <String.h> 28 #include <TextView.h> 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 BFont infoFont(*be_plain_font); 120 infoFont.SetFace(B_ITALIC_FACE); 121 rgb_color infoColor = tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), 122 B_DARKEN_4_TINT); 123 // TODO: Replace with layout friendly constructor once available. 124 BRect textBounds = Bounds(); 125 BTextView* subpixelAntialiasingDisabledLabel = new BTextView( 126 textBounds, "unavailable label", textBounds, &infoFont, &infoColor, 127 B_FOLLOW_NONE, B_WILL_DRAW | B_SUPPORTS_LAYOUT); 128 subpixelAntialiasingDisabledLabel->SetText(B_TRANSLATE( 129 "Subpixel based anti-aliasing in combination with glyph hinting is not " 130 "available in this build of Haiku to avoid possible patent issues. To " 131 "enable this feature, you have to build Haiku yourself and enable " 132 "certain options in the libfreetype configuration header.")); 133 subpixelAntialiasingDisabledLabel->SetViewColor( 134 ui_color(B_PANEL_BACKGROUND_COLOR)); 135 subpixelAntialiasingDisabledLabel->MakeEditable(false); 136 subpixelAntialiasingDisabledLabel->MakeSelectable(false); 137 #endif // !FT_CONFIG_OPTION_SUBPIXEL_RENDERING 138 139 SetLayout(new BGroupLayout(B_VERTICAL)); 140 141 // controls pane 142 AddChild(BGridLayoutBuilder(10, 10) 143 .Add(fHintingMenuField->CreateLabelLayoutItem(), 0, 0) 144 .Add(fHintingMenuField->CreateMenuBarLayoutItem(), 1, 0) 145 146 .Add(fAntialiasingMenuField->CreateLabelLayoutItem(), 0, 1) 147 .Add(fAntialiasingMenuField->CreateMenuBarLayoutItem(), 1, 1) 148 149 .Add(fAverageWeightControl, 0, 2, 2) 150 151 #ifndef FT_CONFIG_OPTION_SUBPIXEL_RENDERING 152 // hinting+subpixel unavailable info 153 .Add(subpixelAntialiasingDisabledLabel, 0, 3, 2) 154 #else 155 .Add(BSpaceLayoutItem::CreateGlue(), 0, 3, 2) 156 #endif 157 158 .SetInsets(10, 10, 10, 10) 159 ); 160 161 _SetCurrentAntialiasing(); 162 _SetCurrentHinting(); 163 _SetCurrentAverageWeight(); 164 } 165 166 167 AntialiasingSettingsView::~AntialiasingSettingsView() 168 { 169 } 170 171 172 void 173 AntialiasingSettingsView::AttachedToWindow() 174 { 175 if (Parent() != NULL) 176 SetViewColor(Parent()->ViewColor()); 177 else 178 SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); 179 180 fAntialiasingMenu->SetTargetForItems(this); 181 fHintingMenu->SetTargetForItems(this); 182 fAverageWeightControl->SetTarget(this); 183 } 184 185 186 void 187 AntialiasingSettingsView::MessageReceived(BMessage *msg) 188 { 189 switch (msg->what) { 190 case kMsgSetAntialiasing: 191 { 192 bool subpixelAntialiasing; 193 if (msg->FindBool("antialiasing", &subpixelAntialiasing) != B_OK 194 || subpixelAntialiasing == fCurrentSubpixelAntialiasing) 195 break; 196 197 fSavedSubpixelAntialiasing = fCurrentSubpixelAntialiasing; 198 fCurrentSubpixelAntialiasing = subpixelAntialiasing; 199 fAverageWeightControl->SetEnabled(fCurrentSubpixelAntialiasing); 200 201 set_subpixel_antialiasing(fCurrentSubpixelAntialiasing); 202 203 Window()->PostMessage(kMsgUpdate); 204 break; 205 } 206 case kMsgSetHinting: 207 { 208 int8 hinting; 209 if (msg->FindInt8("hinting", &hinting) != B_OK 210 || hinting == fCurrentHinting) 211 break; 212 213 fSavedHinting = fCurrentHinting; 214 fCurrentHinting = hinting; 215 set_hinting_mode(fCurrentHinting); 216 217 Window()->PostMessage(kMsgUpdate); 218 break; 219 } 220 case kMsgSetAverageWeight: 221 { 222 int32 averageWeight = fAverageWeightControl->Value(); 223 if (averageWeight == fCurrentAverageWeight) 224 break; 225 226 fSavedAverageWeight = fCurrentAverageWeight; 227 fCurrentAverageWeight = averageWeight; 228 229 set_average_weight(fCurrentAverageWeight); 230 231 Window()->PostMessage(kMsgUpdate); 232 break; 233 } 234 default: 235 BView::MessageReceived(msg); 236 } 237 } 238 239 240 void 241 AntialiasingSettingsView::_BuildAntialiasingMenu() 242 { 243 fAntialiasingMenu = new BPopUpMenu(B_TRANSLATE("Antialiasing menu")); 244 245 BMessage* message = new BMessage(kMsgSetAntialiasing); 246 message->AddBool("antialiasing", false); 247 248 BMenuItem* item 249 = new BMenuItem(B_TRANSLATE_NOCOLLECT(kGrayscaleLabel), message); 250 251 fAntialiasingMenu->AddItem(item); 252 253 message = new BMessage(kMsgSetAntialiasing); 254 message->AddBool("antialiasing", true); 255 256 item = new BMenuItem(B_TRANSLATE_NOCOLLECT(kSubpixelLabel), message); 257 258 fAntialiasingMenu->AddItem(item); 259 } 260 261 262 void 263 AntialiasingSettingsView::_BuildHintingMenu() 264 { 265 fHintingMenu = new BPopUpMenu(B_TRANSLATE("Hinting menu")); 266 267 BMessage* message = new BMessage(kMsgSetHinting); 268 message->AddInt8("hinting", HINTING_MODE_OFF); 269 fHintingMenu->AddItem(new BMenuItem(B_TRANSLATE_NOCOLLECT(kNoHintingLabel), 270 message)); 271 272 message = new BMessage(kMsgSetHinting); 273 message->AddInt8("hinting", HINTING_MODE_ON); 274 fHintingMenu->AddItem(new BMenuItem( 275 B_TRANSLATE_NOCOLLECT(kFullHintingLabel), message)); 276 277 message = new BMessage(kMsgSetHinting); 278 message->AddInt8("hinting", HINTING_MODE_MONOSPACED_ONLY); 279 fHintingMenu->AddItem(new BMenuItem( 280 B_TRANSLATE_NOCOLLECT(kMonospacedHintingLabel), message)); 281 } 282 283 284 void 285 AntialiasingSettingsView::_SetCurrentAntialiasing() 286 { 287 BMenuItem *item = fAntialiasingMenu->FindItem( 288 fCurrentSubpixelAntialiasing 289 ? B_TRANSLATE_NOCOLLECT(kSubpixelLabel) 290 : B_TRANSLATE_NOCOLLECT(kGrayscaleLabel)); 291 if (item != NULL) 292 item->SetMarked(true); 293 if (fCurrentSubpixelAntialiasing) 294 fAverageWeightControl->SetEnabled(true); 295 } 296 297 298 void 299 AntialiasingSettingsView::_SetCurrentHinting() 300 { 301 const char* label; 302 switch (fCurrentHinting) { 303 case HINTING_MODE_OFF: 304 label = kNoHintingLabel; 305 break; 306 case HINTING_MODE_ON: 307 label = kFullHintingLabel; 308 break; 309 case HINTING_MODE_MONOSPACED_ONLY: 310 label = kMonospacedHintingLabel; 311 break; 312 default: 313 return; 314 } 315 316 BMenuItem *item = fHintingMenu->FindItem(B_TRANSLATE_NOCOLLECT(label)); 317 if (item != NULL) 318 item->SetMarked(true); 319 } 320 321 322 void 323 AntialiasingSettingsView::_SetCurrentAverageWeight() 324 { 325 fAverageWeightControl->SetValue(fCurrentAverageWeight); 326 } 327 328 329 void 330 AntialiasingSettingsView::SetDefaults() 331 { 332 if (!IsDefaultable()) 333 return; 334 335 fCurrentSubpixelAntialiasing = kDefaultSubpixelAntialiasing; 336 fCurrentHinting = kDefaultHintingMode; 337 fCurrentAverageWeight = kDefaultAverageWeight; 338 339 set_subpixel_antialiasing(fCurrentSubpixelAntialiasing); 340 set_hinting_mode(fCurrentHinting); 341 set_average_weight(fCurrentAverageWeight); 342 343 _SetCurrentAntialiasing(); 344 _SetCurrentHinting(); 345 _SetCurrentAverageWeight(); 346 } 347 348 349 bool 350 AntialiasingSettingsView::IsDefaultable() 351 { 352 return fCurrentSubpixelAntialiasing != kDefaultSubpixelAntialiasing 353 || fCurrentHinting != kDefaultHintingMode 354 || fCurrentAverageWeight != kDefaultAverageWeight; 355 } 356 357 358 bool 359 AntialiasingSettingsView::IsRevertable() 360 { 361 return fCurrentSubpixelAntialiasing != fSavedSubpixelAntialiasing 362 || fCurrentHinting != fSavedHinting 363 || fCurrentAverageWeight != fSavedAverageWeight; 364 } 365 366 367 void 368 AntialiasingSettingsView::Revert() 369 { 370 if (!IsRevertable()) 371 return; 372 373 fCurrentSubpixelAntialiasing = fSavedSubpixelAntialiasing; 374 fCurrentHinting = fSavedHinting; 375 fCurrentAverageWeight = fSavedAverageWeight; 376 377 set_subpixel_antialiasing(fCurrentSubpixelAntialiasing); 378 set_hinting_mode(fCurrentHinting); 379 set_average_weight(fCurrentAverageWeight); 380 381 _SetCurrentAntialiasing(); 382 _SetCurrentHinting(); 383 _SetCurrentAverageWeight(); 384 } 385