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