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