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 TR_CONTEXT 31 #define TR_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 = TR_MARK("LCD subpixel"); 42 static const char* kGrayscaleLabel = TR_MARK("Grayscale"); 43 static const char* kNoHintingLabel = TR_MARK("Off"); 44 static const char* kMonospacedHintingLabel = TR_MARK("Monospaced Fonts Only"); 45 static const char* kFullHintingLabel = TR_MARK("On"); 46 47 48 // #pragma mark - private libbe API 49 50 51 enum { 52 HINTING_MODE_OFF = 0, 53 HINTING_MODE_ON, 54 HINTING_MODE_MONOSPACED_ONLY 55 }; 56 57 extern void set_subpixel_antialiasing(bool subpix); 58 extern status_t get_subpixel_antialiasing(bool* subpix); 59 extern void set_hinting_mode(uint8 hinting); 60 extern status_t get_hinting_mode(uint8* hinting); 61 extern void set_average_weight(unsigned char averageWeight); 62 extern status_t get_average_weight(unsigned char* averageWeight); 63 64 65 // #pragma mark - 66 67 68 AntialiasingSettingsView::AntialiasingSettingsView(const char* name) 69 : BView(name, 0) 70 { 71 // collect the current system settings 72 if (get_subpixel_antialiasing(&fCurrentSubpixelAntialiasing) != B_OK) 73 fCurrentSubpixelAntialiasing = false; 74 fSavedSubpixelAntialiasing = fCurrentSubpixelAntialiasing; 75 76 if (get_hinting_mode(&fCurrentHinting) != B_OK) 77 fCurrentHinting = HINTING_MODE_ON; 78 fSavedHinting = fCurrentHinting; 79 80 if (get_average_weight(&fCurrentAverageWeight) != B_OK) 81 fCurrentAverageWeight = 100; 82 fSavedAverageWeight = fCurrentAverageWeight; 83 84 // create the controls 85 86 // antialiasing menu 87 _BuildAntialiasingMenu(); 88 fAntialiasingMenuField = new BMenuField("antialiasing", 89 TR("Anti-aliasing type:"), fAntialiasingMenu, NULL); 90 91 // "average weight" in subpixel filtering 92 fAverageWeightControl = new BSlider("averageWeightControl", 93 TR("Reduce colored edges filter strength:"), 94 new BMessage(kMsgSetAverageWeight), 0, 255, B_HORIZONTAL); 95 fAverageWeightControl->SetLimitLabels(TR("Off"), TR("Strong")); 96 fAverageWeightControl->SetHashMarks(B_HASH_MARKS_BOTTOM); 97 fAverageWeightControl->SetHashMarkCount(255 / 15); 98 fAverageWeightControl->SetEnabled(false); 99 100 // hinting menu 101 _BuildHintingMenu(); 102 fHintingMenuField = new BMenuField("hinting", TR("Glyph hinting:"), 103 fHintingMenu, NULL); 104 105 #ifdef DISABLE_HINTING_CONTROL 106 fHintingMenuField->SetEnabled(false); 107 #endif 108 109 #ifndef FT_CONFIG_OPTION_SUBPIXEL_RENDERING 110 // subpixelAntialiasingDisabledLabel 111 BFont infoFont(*be_plain_font); 112 infoFont.SetFace(B_ITALIC_FACE); 113 rgb_color infoColor = tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), 114 B_DARKEN_4_TINT); 115 // TODO: Replace with layout friendly constructor once available. 116 BRect textBounds = Bounds(); 117 BTextView* subpixelAntialiasingDisabledLabel = new BTextView( 118 textBounds, "unavailable label", textBounds, &infoFont, &infoColor, 119 B_FOLLOW_NONE, B_WILL_DRAW | B_SUPPORTS_LAYOUT); 120 subpixelAntialiasingDisabledLabel->SetText(TR("Subpixel based anti-aliasing " 121 "in combination with glyph hinting is not available in this build of " 122 "Haiku to avoid possible patent issues. To enable this feature, you " 123 "have to build Haiku yourself and enable certain options in the " 124 "libfreetype configuration header.")); 125 subpixelAntialiasingDisabledLabel->SetViewColor( 126 ui_color(B_PANEL_BACKGROUND_COLOR)); 127 subpixelAntialiasingDisabledLabel->MakeEditable(false); 128 subpixelAntialiasingDisabledLabel->MakeSelectable(false); 129 #endif // !FT_CONFIG_OPTION_SUBPIXEL_RENDERING 130 131 SetLayout(new BGroupLayout(B_VERTICAL)); 132 133 // controls pane 134 AddChild(BGridLayoutBuilder(10, 10) 135 .Add(fHintingMenuField->CreateLabelLayoutItem(), 0, 0) 136 .Add(fHintingMenuField->CreateMenuBarLayoutItem(), 1, 0) 137 138 .Add(fAntialiasingMenuField->CreateLabelLayoutItem(), 0, 1) 139 .Add(fAntialiasingMenuField->CreateMenuBarLayoutItem(), 1, 1) 140 141 .Add(fAverageWeightControl, 0, 2, 2) 142 143 #ifndef FT_CONFIG_OPTION_SUBPIXEL_RENDERING 144 // hinting+subpixel unavailable info 145 .Add(subpixelAntialiasingDisabledLabel, 0, 3, 2) 146 #else 147 .Add(BSpaceLayoutItem::CreateGlue(), 0, 3, 2) 148 #endif 149 150 .SetInsets(10, 10, 10, 10) 151 ); 152 153 _SetCurrentAntialiasing(); 154 _SetCurrentHinting(); 155 _SetCurrentAverageWeight(); 156 } 157 158 159 AntialiasingSettingsView::~AntialiasingSettingsView() 160 { 161 } 162 163 164 void 165 AntialiasingSettingsView::AttachedToWindow() 166 { 167 if (Parent() != NULL) 168 SetViewColor(Parent()->ViewColor()); 169 else 170 SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); 171 172 fAntialiasingMenu->SetTargetForItems(this); 173 fHintingMenu->SetTargetForItems(this); 174 fAverageWeightControl->SetTarget(this); 175 } 176 177 178 void 179 AntialiasingSettingsView::MessageReceived(BMessage *msg) 180 { 181 switch (msg->what) { 182 case kMsgSetAntialiasing: 183 { 184 bool subpixelAntialiasing; 185 if (msg->FindBool("antialiasing", &subpixelAntialiasing) != B_OK 186 || subpixelAntialiasing == fCurrentSubpixelAntialiasing) 187 break; 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 default: 223 BView::MessageReceived(msg); 224 } 225 } 226 227 228 void 229 AntialiasingSettingsView::_BuildAntialiasingMenu() 230 { 231 fAntialiasingMenu = new BPopUpMenu(TR("Antialiasing menu")); 232 233 BMessage* message = new BMessage(kMsgSetAntialiasing); 234 message->AddBool("antialiasing", false); 235 236 BMenuItem* item = new BMenuItem(TR(kGrayscaleLabel), message); 237 238 fAntialiasingMenu->AddItem(item); 239 240 message = new BMessage(kMsgSetAntialiasing); 241 message->AddBool("antialiasing", true); 242 243 item = new BMenuItem(TR(kSubpixelLabel), message); 244 245 fAntialiasingMenu->AddItem(item); 246 } 247 248 249 void 250 AntialiasingSettingsView::_BuildHintingMenu() 251 { 252 fHintingMenu = new BPopUpMenu(TR("Hinting menu")); 253 254 BMessage* message = new BMessage(kMsgSetHinting); 255 message->AddInt8("hinting", HINTING_MODE_OFF); 256 fHintingMenu->AddItem(new BMenuItem(TR(kNoHintingLabel), message)); 257 258 message = new BMessage(kMsgSetHinting); 259 message->AddInt8("hinting", HINTING_MODE_ON); 260 fHintingMenu->AddItem(new BMenuItem(TR(kFullHintingLabel), message)); 261 262 message = new BMessage(kMsgSetHinting); 263 message->AddInt8("hinting", HINTING_MODE_MONOSPACED_ONLY); 264 fHintingMenu->AddItem(new BMenuItem(TR(kMonospacedHintingLabel), message)); 265 } 266 267 268 void 269 AntialiasingSettingsView::_SetCurrentAntialiasing() 270 { 271 BMenuItem *item = fAntialiasingMenu->FindItem( 272 fCurrentSubpixelAntialiasing ? TR(kSubpixelLabel) : TR(kGrayscaleLabel)); 273 if (item != NULL) 274 item->SetMarked(true); 275 if (fCurrentSubpixelAntialiasing) 276 fAverageWeightControl->SetEnabled(true); 277 } 278 279 280 void 281 AntialiasingSettingsView::_SetCurrentHinting() 282 { 283 const char* label = NULL; 284 switch (fCurrentHinting) { 285 case HINTING_MODE_OFF: 286 label = kNoHintingLabel; 287 break; 288 case HINTING_MODE_ON: 289 label = kFullHintingLabel; 290 break; 291 case HINTING_MODE_MONOSPACED_ONLY: 292 label = kMonospacedHintingLabel; 293 break; 294 } 295 296 BMenuItem *item = fHintingMenu->FindItem(TR(label)); 297 if (item != NULL) 298 item->SetMarked(true); 299 } 300 301 302 void 303 AntialiasingSettingsView::_SetCurrentAverageWeight() 304 { 305 fAverageWeightControl->SetValue(fCurrentAverageWeight); 306 } 307 308 309 void 310 AntialiasingSettingsView::SetDefaults() 311 { 312 } 313 314 315 bool 316 AntialiasingSettingsView::IsDefaultable() 317 { 318 return false; 319 } 320 321 322 bool 323 AntialiasingSettingsView::IsRevertable() 324 { 325 return fCurrentSubpixelAntialiasing != fSavedSubpixelAntialiasing 326 || fCurrentHinting != fSavedHinting 327 || fCurrentAverageWeight != fSavedAverageWeight; 328 } 329 330 331 void 332 AntialiasingSettingsView::Revert() 333 { 334 if (!IsRevertable()) 335 return; 336 337 fCurrentSubpixelAntialiasing = fSavedSubpixelAntialiasing; 338 fCurrentHinting = fSavedHinting; 339 fCurrentAverageWeight = fSavedAverageWeight; 340 341 set_subpixel_antialiasing(fCurrentSubpixelAntialiasing); 342 set_hinting_mode(fCurrentHinting); 343 set_average_weight(fCurrentAverageWeight); 344 345 _SetCurrentAntialiasing(); 346 _SetCurrentHinting(); 347 _SetCurrentAverageWeight(); 348 } 349