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 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 fCurrentHinting = hinting; 213 set_hinting_mode(fCurrentHinting); 214 215 Window()->PostMessage(kMsgUpdate); 216 break; 217 } 218 case kMsgSetAverageWeight: 219 { 220 int32 averageWeight = fAverageWeightControl->Value(); 221 if (averageWeight == fCurrentAverageWeight) 222 break; 223 224 fCurrentAverageWeight = averageWeight; 225 226 set_average_weight(fCurrentAverageWeight); 227 228 Window()->PostMessage(kMsgUpdate); 229 break; 230 } 231 default: 232 BView::MessageReceived(msg); 233 } 234 } 235 236 237 void 238 AntialiasingSettingsView::_BuildAntialiasingMenu() 239 { 240 fAntialiasingMenu = new BPopUpMenu(B_TRANSLATE("Antialiasing menu")); 241 242 BMessage* message = new BMessage(kMsgSetAntialiasing); 243 message->AddBool("antialiasing", false); 244 245 BMenuItem* item 246 = new BMenuItem(B_TRANSLATE_NOCOLLECT(kGrayscaleLabel), message); 247 248 fAntialiasingMenu->AddItem(item); 249 250 message = new BMessage(kMsgSetAntialiasing); 251 message->AddBool("antialiasing", true); 252 253 item = new BMenuItem(B_TRANSLATE_NOCOLLECT(kSubpixelLabel), message); 254 255 fAntialiasingMenu->AddItem(item); 256 } 257 258 259 void 260 AntialiasingSettingsView::_BuildHintingMenu() 261 { 262 fHintingMenu = new BPopUpMenu(B_TRANSLATE("Hinting menu")); 263 264 BMessage* message = new BMessage(kMsgSetHinting); 265 message->AddInt8("hinting", HINTING_MODE_OFF); 266 fHintingMenu->AddItem(new BMenuItem(B_TRANSLATE_NOCOLLECT(kNoHintingLabel), 267 message)); 268 269 message = new BMessage(kMsgSetHinting); 270 message->AddInt8("hinting", HINTING_MODE_ON); 271 fHintingMenu->AddItem(new BMenuItem( 272 B_TRANSLATE_NOCOLLECT(kFullHintingLabel), message)); 273 274 message = new BMessage(kMsgSetHinting); 275 message->AddInt8("hinting", HINTING_MODE_MONOSPACED_ONLY); 276 fHintingMenu->AddItem(new BMenuItem( 277 B_TRANSLATE_NOCOLLECT(kMonospacedHintingLabel), message)); 278 } 279 280 281 void 282 AntialiasingSettingsView::_SetCurrentAntialiasing() 283 { 284 BMenuItem *item = fAntialiasingMenu->FindItem( 285 fCurrentSubpixelAntialiasing 286 ? B_TRANSLATE_NOCOLLECT(kSubpixelLabel) 287 : B_TRANSLATE_NOCOLLECT(kGrayscaleLabel)); 288 if (item != NULL) 289 item->SetMarked(true); 290 if (fCurrentSubpixelAntialiasing) 291 fAverageWeightControl->SetEnabled(true); 292 } 293 294 295 void 296 AntialiasingSettingsView::_SetCurrentHinting() 297 { 298 const char* label; 299 switch (fCurrentHinting) { 300 case HINTING_MODE_OFF: 301 label = kNoHintingLabel; 302 break; 303 case HINTING_MODE_ON: 304 label = kFullHintingLabel; 305 break; 306 case HINTING_MODE_MONOSPACED_ONLY: 307 label = kMonospacedHintingLabel; 308 break; 309 default: 310 return; 311 } 312 313 BMenuItem *item = fHintingMenu->FindItem(B_TRANSLATE_NOCOLLECT(label)); 314 if (item != NULL) 315 item->SetMarked(true); 316 } 317 318 319 void 320 AntialiasingSettingsView::_SetCurrentAverageWeight() 321 { 322 fAverageWeightControl->SetValue(fCurrentAverageWeight); 323 } 324 325 326 void 327 AntialiasingSettingsView::SetDefaults() 328 { 329 if (!IsDefaultable()) 330 return; 331 332 fCurrentSubpixelAntialiasing = kDefaultSubpixelAntialiasing; 333 fCurrentHinting = kDefaultHintingMode; 334 fCurrentAverageWeight = kDefaultAverageWeight; 335 336 set_subpixel_antialiasing(fCurrentSubpixelAntialiasing); 337 set_hinting_mode(fCurrentHinting); 338 set_average_weight(fCurrentAverageWeight); 339 340 _SetCurrentAntialiasing(); 341 _SetCurrentHinting(); 342 _SetCurrentAverageWeight(); 343 } 344 345 346 bool 347 AntialiasingSettingsView::IsDefaultable() 348 { 349 return fCurrentSubpixelAntialiasing != kDefaultSubpixelAntialiasing 350 || fCurrentHinting != kDefaultHintingMode 351 || fCurrentAverageWeight != kDefaultAverageWeight; 352 } 353 354 355 bool 356 AntialiasingSettingsView::IsRevertable() 357 { 358 return fCurrentSubpixelAntialiasing != fSavedSubpixelAntialiasing 359 || fCurrentHinting != fSavedHinting 360 || fCurrentAverageWeight != fSavedAverageWeight; 361 } 362 363 364 void 365 AntialiasingSettingsView::Revert() 366 { 367 if (!IsRevertable()) 368 return; 369 370 fCurrentSubpixelAntialiasing = fSavedSubpixelAntialiasing; 371 fCurrentHinting = fSavedHinting; 372 fCurrentAverageWeight = fSavedAverageWeight; 373 374 set_subpixel_antialiasing(fCurrentSubpixelAntialiasing); 375 set_hinting_mode(fCurrentHinting); 376 set_average_weight(fCurrentAverageWeight); 377 378 _SetCurrentAntialiasing(); 379 _SetCurrentHinting(); 380 _SetCurrentAverageWeight(); 381 } 382