1 module dlangui.platforms.common.startup; 2 3 import dlangui.core.config; 4 import dlangui.core.events; 5 import dlangui.widgets.styles; 6 import dlangui.graphics.fonts; 7 import dlangui.graphics.resources; 8 import dlangui.widgets.widget; 9 10 static if (BACKEND_GUI) { 11 import dlangui.graphics.ftfonts; 12 13 version (Windows) { 14 15 /// initialize font manager - default implementation 16 /// On win32 - first it tries to init freetype, and falls back to win32 fonts. 17 /// On linux/mac - tries to init freetype with some hardcoded font paths 18 extern(C) bool initFontManager() { 19 import core.sys.windows.windows; 20 import std.utf; 21 import dlangui.platforms.windows.win32fonts; 22 try { 23 /// testing freetype font manager 24 static if (ENABLE_FREETYPE) { 25 Log.v("Trying to init FreeType font manager"); 26 27 import dlangui.graphics.ftfonts; 28 // trying to create font manager 29 Log.v("Creating FreeTypeFontManager"); 30 FreeTypeFontManager ftfontMan = new FreeTypeFontManager(); 31 32 import core.sys.windows.shlobj; 33 string fontsPath = "c:\\Windows\\Fonts\\"; 34 static if (true) { // SHGetFolderPathW not found in shell32.lib 35 WCHAR[MAX_PATH] szPath; 36 static if (false) { 37 const CSIDL_FLAG_NO_ALIAS = 0x1000; 38 const CSIDL_FLAG_DONT_UNEXPAND = 0x2000; 39 if(SUCCEEDED(SHGetFolderPathW(NULL, 40 CSIDL_FONTS|CSIDL_FLAG_NO_ALIAS|CSIDL_FLAG_DONT_UNEXPAND, 41 NULL, 42 0, 43 szPath.ptr))) 44 { 45 fontsPath = toUTF8(fromWStringz(szPath)); 46 } 47 } else { 48 if (GetWindowsDirectory(szPath.ptr, MAX_PATH - 1)) { 49 fontsPath = toUTF8(fromWStringz(szPath)); 50 Log.i("Windows directory: ", fontsPath); 51 fontsPath ~= "\\Fonts\\"; 52 Log.i("Fonts directory: ", fontsPath); 53 } 54 } 55 } 56 Log.v("Registering fonts"); 57 ftfontMan.registerFont(fontsPath ~ "arial.ttf", FontFamily.SansSerif, "Arial", false, FontWeight.Normal); 58 ftfontMan.registerFont(fontsPath ~ "arialbd.ttf", FontFamily.SansSerif, "Arial", false, FontWeight.Bold); 59 ftfontMan.registerFont(fontsPath ~ "arialbi.ttf", FontFamily.SansSerif, "Arial", true, FontWeight.Bold); 60 ftfontMan.registerFont(fontsPath ~ "ariali.ttf", FontFamily.SansSerif, "Arial", true, FontWeight.Normal); 61 ftfontMan.registerFont(fontsPath ~ "cour.ttf", FontFamily.MonoSpace, "Courier New", false, FontWeight.Normal); 62 ftfontMan.registerFont(fontsPath ~ "courbd.ttf", FontFamily.MonoSpace, "Courier New", false, FontWeight.Bold); 63 ftfontMan.registerFont(fontsPath ~ "courbi.ttf", FontFamily.MonoSpace, "Courier New", true, FontWeight.Bold); 64 ftfontMan.registerFont(fontsPath ~ "couri.ttf", FontFamily.MonoSpace, "Courier New", true, FontWeight.Normal); 65 ftfontMan.registerFont(fontsPath ~ "times.ttf", FontFamily.Serif, "Times New Roman", false, FontWeight.Normal); 66 ftfontMan.registerFont(fontsPath ~ "timesbd.ttf", FontFamily.Serif, "Times New Roman", false, FontWeight.Bold); 67 ftfontMan.registerFont(fontsPath ~ "timesbi.ttf", FontFamily.Serif, "Times New Roman", true, FontWeight.Bold); 68 ftfontMan.registerFont(fontsPath ~ "timesi.ttf", FontFamily.Serif, "Times New Roman", true, FontWeight.Normal); 69 ftfontMan.registerFont(fontsPath ~ "consola.ttf", FontFamily.MonoSpace, "Consolas", false, FontWeight.Normal); 70 ftfontMan.registerFont(fontsPath ~ "consolab.ttf", FontFamily.MonoSpace, "Consolas", false, FontWeight.Bold); 71 ftfontMan.registerFont(fontsPath ~ "consolai.ttf", FontFamily.MonoSpace, "Consolas", true, FontWeight.Normal); 72 ftfontMan.registerFont(fontsPath ~ "consolaz.ttf", FontFamily.MonoSpace, "Consolas", true, FontWeight.Bold); 73 ftfontMan.registerFont(fontsPath ~ "verdana.ttf", FontFamily.SansSerif, "Verdana", false, FontWeight.Normal); 74 ftfontMan.registerFont(fontsPath ~ "verdanab.ttf", FontFamily.SansSerif, "Verdana", false, FontWeight.Bold); 75 ftfontMan.registerFont(fontsPath ~ "verdanai.ttf", FontFamily.SansSerif, "Verdana", true, FontWeight.Normal); 76 ftfontMan.registerFont(fontsPath ~ "verdanaz.ttf", FontFamily.SansSerif, "Verdana", true, FontWeight.Bold); 77 if (ftfontMan.registeredFontCount()) { 78 FontManager.instance = ftfontMan; 79 } else { 80 Log.w("No fonts registered in FreeType font manager. Disabling FreeType."); 81 destroy(ftfontMan); 82 } 83 } 84 } catch (Exception e) { 85 Log.e("Cannot create FreeTypeFontManager - falling back to win32"); 86 } 87 88 // use Win32 font manager 89 if (FontManager.instance is null) { 90 FontManager.instance = new Win32FontManager(); 91 } 92 return true; 93 } 94 95 } else { 96 import dlangui.graphics.ftfonts; 97 bool registerFonts(FreeTypeFontManager ft, string path) { 98 import std.file; 99 if (!exists(path) || !isDir(path)) 100 return false; 101 ft.registerFont(path ~ "DejaVuSans.ttf", FontFamily.SansSerif, "DejaVuSans", false, FontWeight.Normal); 102 ft.registerFont(path ~ "DejaVuSans-Bold.ttf", FontFamily.SansSerif, "DejaVuSans", false, FontWeight.Bold); 103 ft.registerFont(path ~ "DejaVuSans-Oblique.ttf", FontFamily.SansSerif, "DejaVuSans", true, FontWeight.Normal); 104 ft.registerFont(path ~ "DejaVuSans-BoldOblique.ttf", FontFamily.SansSerif, "DejaVuSans", true, FontWeight.Bold); 105 ft.registerFont(path ~ "DejaVuSansMono.ttf", FontFamily.MonoSpace, "DejaVuSansMono", false, FontWeight.Normal); 106 ft.registerFont(path ~ "DejaVuSansMono-Bold.ttf", FontFamily.MonoSpace, "DejaVuSansMono", false, FontWeight.Bold); 107 ft.registerFont(path ~ "DejaVuSansMono-Oblique.ttf", FontFamily.MonoSpace, "DejaVuSansMono", true, FontWeight.Normal); 108 ft.registerFont(path ~ "DejaVuSansMono-BoldOblique.ttf", FontFamily.MonoSpace, "DejaVuSansMono", true, FontWeight.Bold); 109 return true; 110 } 111 112 string[] findFontsInDirectory(string dir) { 113 import dlangui.core.files; 114 import std.file : DirEntry; 115 DirEntry[] entries; 116 try { 117 entries = listDirectory(dir, AttrFilter.files, ["*.ttf"]); 118 } catch(Exception e) { 119 return null; 120 } 121 122 string[] res; 123 foreach(entry; entries) { 124 res ~= entry.name; 125 } 126 return res; 127 } 128 129 void registerFontsFromDirectory(FreeTypeFontManager ft, string dir) { 130 string[] fontFiles = findFontsInDirectory(dir); 131 Log.d("Fonts in ", dir, " : ", fontFiles); 132 foreach(file; fontFiles) 133 ft.registerFont(file); 134 } 135 136 /// initialize font manager - default implementation 137 /// On win32 - first it tries to init freetype, and falls back to win32 fonts. 138 /// On linux/mac - tries to init freetype with some hardcoded font paths 139 extern(C) bool initFontManager() { 140 FreeTypeFontManager ft = new FreeTypeFontManager(); 141 142 if (!registerFontConfigFonts(ft)) { 143 // TODO: use FontConfig 144 Log.w("No fonts found using FontConfig. Trying hardcoded paths."); 145 version (Android) { 146 ft.registerFontsFromDirectory("/system/fonts"); 147 } else { 148 ft.registerFonts("/usr/share/fonts/truetype/dejavu/"); 149 ft.registerFonts("/usr/share/fonts/TTF/"); 150 ft.registerFonts("/usr/share/fonts/dejavu/"); 151 ft.registerFonts("/usr/share/fonts/truetype/ttf-dejavu/"); // let it compile on Debian Wheezy 152 } 153 version(OSX) { 154 ft.registerFont("/Library/Fonts/Arial.ttf", FontFamily.SansSerif, "Arial", false, FontWeight.Normal, true); 155 ft.registerFont("/Library/Fonts/Arial Bold.ttf", FontFamily.SansSerif, "Arial", false, FontWeight.Bold, true); 156 ft.registerFont("/Library/Fonts/Arial Italic.ttf", FontFamily.SansSerif, "Arial", true, FontWeight.Normal, true); 157 ft.registerFont("/Library/Fonts/Arial Bold Italic.ttf", FontFamily.SansSerif, "Arial", true, FontWeight.Bold, true); 158 ft.registerFont("/Library/Fonts/Arial.ttf", FontFamily.SansSerif, "Arial", false, FontWeight.Normal, true); 159 ft.registerFont("/Library/Fonts/Arial Bold.ttf", FontFamily.SansSerif, "Arial", false, FontWeight.Bold, true); 160 ft.registerFont("/Library/Fonts/Arial Italic.ttf", FontFamily.SansSerif, "Arial", true, FontWeight.Normal, true); 161 ft.registerFont("/Library/Fonts/Arial Bold Italic.ttf", FontFamily.SansSerif, "Arial", true, FontWeight.Bold, true); 162 ft.registerFont("/Library/Fonts/Arial Narrow.ttf", FontFamily.SansSerif, "Arial Narrow", false, FontWeight.Normal, true); 163 ft.registerFont("/Library/Fonts/Arial Narrow Bold.ttf", FontFamily.SansSerif, "Arial Narrow", false, FontWeight.Bold, true); 164 ft.registerFont("/Library/Fonts/Arial Narrow Italic.ttf", FontFamily.SansSerif, "Arial Narrow", true, FontWeight.Normal, true); 165 ft.registerFont("/Library/Fonts/Arial Narrow Bold Italic.ttf", FontFamily.SansSerif, "Arial Narrow", true, FontWeight.Bold, true); 166 ft.registerFont("/Library/Fonts/Courier New.ttf", FontFamily.MonoSpace, "Courier New", false, FontWeight.Normal, true); 167 ft.registerFont("/Library/Fonts/Courier New Bold.ttf", FontFamily.MonoSpace, "Courier New", false, FontWeight.Bold, true); 168 ft.registerFont("/Library/Fonts/Courier New Italic.ttf", FontFamily.MonoSpace, "Courier New", true, FontWeight.Normal, true); 169 ft.registerFont("/Library/Fonts/Courier New Bold Italic.ttf", FontFamily.MonoSpace, "Courier New", true, FontWeight.Bold, true); 170 ft.registerFont("/Library/Fonts/Georgia.ttf", FontFamily.Serif, "Georgia", false, FontWeight.Normal, true); 171 ft.registerFont("/Library/Fonts/Georgia Bold.ttf", FontFamily.Serif, "Georgia", false, FontWeight.Bold, true); 172 ft.registerFont("/Library/Fonts/Georgia Italic.ttf", FontFamily.Serif, "Georgia", true, FontWeight.Normal, true); 173 ft.registerFont("/Library/Fonts/Georgia Bold Italic.ttf", FontFamily.Serif, "Georgia", true, FontWeight.Bold, true); 174 ft.registerFont("/Library/Fonts/Comic Sans MS.ttf", FontFamily.SansSerif, "Comic Sans", false, FontWeight.Normal, true); 175 ft.registerFont("/Library/Fonts/Comic Sans MS Bold.ttf", FontFamily.SansSerif, "Comic Sans", false, FontWeight.Bold, true); 176 ft.registerFont("/Library/Fonts/Tahoma.ttf", FontFamily.SansSerif, "Tahoma", false, FontWeight.Normal, true); 177 ft.registerFont("/Library/Fonts/Tahoma Bold.ttf", FontFamily.SansSerif, "Tahoma", false, FontWeight.Bold, true); 178 179 ft.registerFont("/Library/Fonts/Microsoft/Arial.ttf", FontFamily.SansSerif, "Arial", false, FontWeight.Normal, true); 180 ft.registerFont("/Library/Fonts/Microsoft/Arial Bold.ttf", FontFamily.SansSerif, "Arial", false, FontWeight.Bold, true); 181 ft.registerFont("/Library/Fonts/Microsoft/Arial Italic.ttf", FontFamily.SansSerif, "Arial", true, FontWeight.Normal, true); 182 ft.registerFont("/Library/Fonts/Microsoft/Arial Bold Italic.ttf", FontFamily.SansSerif, "Arial", true, FontWeight.Bold, true); 183 ft.registerFont("/Library/Fonts/Microsoft/Calibri.ttf", FontFamily.SansSerif, "Calibri", false, FontWeight.Normal, true); 184 ft.registerFont("/Library/Fonts/Microsoft/Calibri Bold.ttf", FontFamily.SansSerif, "Calibri", false, FontWeight.Bold, true); 185 ft.registerFont("/Library/Fonts/Microsoft/Calibri Italic.ttf", FontFamily.SansSerif, "Calibri", true, FontWeight.Normal, true); 186 ft.registerFont("/Library/Fonts/Microsoft/Calibri Bold Italic.ttf", FontFamily.SansSerif, "Calibri", true, FontWeight.Bold, true); 187 ft.registerFont("/Library/Fonts/Microsoft/Times New Roman.ttf", FontFamily.Serif, "Times New Roman", false, FontWeight.Normal, true); 188 ft.registerFont("/Library/Fonts/Microsoft/Times New Roman Bold.ttf", FontFamily.Serif, "Times New Roman", false, FontWeight.Bold, true); 189 ft.registerFont("/Library/Fonts/Microsoft/Times New Roman Italic.ttf", FontFamily.Serif, "Times New Roman", true, FontWeight.Normal, true); 190 ft.registerFont("/Library/Fonts/Microsoft/Times New Roman Bold Italic.ttf", FontFamily.Serif, "Times New Roman", true, FontWeight.Bold, true); 191 ft.registerFont("/Library/Fonts/Microsoft/Verdana.ttf", FontFamily.SansSerif, "Verdana", false, FontWeight.Normal, true); 192 ft.registerFont("/Library/Fonts/Microsoft/Verdana Bold.ttf", FontFamily.SansSerif, "Verdana", false, FontWeight.Bold, true); 193 ft.registerFont("/Library/Fonts/Microsoft/Verdana Italic.ttf", FontFamily.SansSerif, "Verdana", true, FontWeight.Normal, true); 194 ft.registerFont("/Library/Fonts/Microsoft/Verdana Bold Italic.ttf", FontFamily.SansSerif, "Verdana", true, FontWeight.Bold, true); 195 196 ft.registerFont("/Library/Fonts/Microsoft/Consolas.ttf", FontFamily.MonoSpace, "Consolas", false, FontWeight.Normal, true); 197 ft.registerFont("/Library/Fonts/Microsoft/Consolas Bold.ttf", FontFamily.MonoSpace, "Consolas", false, FontWeight.Bold, true); 198 ft.registerFont("/Library/Fonts/Microsoft/Consolas Italic.ttf", FontFamily.MonoSpace, "Consolas", true, FontWeight.Normal, true); 199 ft.registerFont("/Library/Fonts/Microsoft/Consolas Bold Italic.ttf", FontFamily.MonoSpace, "Consolas", true, FontWeight.Bold, true); 200 201 ft.registerFont("/System/Library/Fonts/Menlo.ttc", FontFamily.MonoSpace, "Menlo", false, FontWeight.Normal, true); 202 } 203 } 204 205 if (!ft.registeredFontCount) 206 return false; 207 208 FontManager.instance = ft; 209 return true; 210 } 211 } 212 } 213 214 /// initialize logging (for win32 - to file ui.log, for other platforms - stderr; log level is TRACE for debug builds, and WARN for release builds) 215 extern (C) void initLogs() { 216 static if (BACKEND_CONSOLE) { 217 static import std.stdio; 218 debug { 219 Log.setFileLogger(new std.stdio.File("ui.log", "w")); 220 Log.i("Debug build. Logging to file ui.log"); 221 Log.setLogLevel(LogLevel.Trace); 222 } else { 223 // no logging unless version ForceLogs is set 224 version(ForceLogs) { 225 Log.setFileLogger(new std.stdio.File("ui.log", "w")); 226 Log.i("Logging to file ui.log"); 227 //Log.setLogLevel(LogLevel.Trace); 228 } 229 } 230 } else { 231 static import std.stdio; 232 version (Windows) { 233 debug { 234 Log.setFileLogger(new std.stdio.File("ui.log", "w")); 235 } else { 236 // no logging unless version ForceLogs is set 237 version(ForceLogs) { 238 Log.setFileLogger(new std.stdio.File("ui.log", "w")); 239 Log.i("Logging to file ui.log"); 240 } 241 } 242 } else version(Android) { 243 Log.setLogTag("dlangui"); 244 Log.setLogLevel(LogLevel.Trace); 245 } else { 246 Log.setStderrLogger(); 247 } 248 debug { 249 Log.setLogLevel(LogLevel.Trace); 250 } else { 251 version(ForceLogs) { 252 Log.setLogLevel(LogLevel.Trace); 253 Log.i("Log level: trace"); 254 } else { 255 Log.setLogLevel(LogLevel.Warn); 256 Log.i("Log level: warn"); 257 } 258 } 259 } 260 Log.i("Logger is initialized"); 261 } 262 263 /// call this on application initialization 264 extern (C) void initResourceManagers() { 265 Log.d("initResourceManagers()"); 266 import dlangui.graphics.fonts; 267 _gamma65 = new glyph_gamma_table!65(1.0); 268 _gamma256 = new glyph_gamma_table!256(1.0); 269 static if (ENABLE_FREETYPE) { 270 import dlangui.graphics.ftfonts; 271 STD_FONT_FACES = [ 272 "Arial": 12, 273 "Times New Roman": 12, 274 "Courier New": 10, 275 "DejaVu Serif": 10, 276 "DejaVu Sans": 10, 277 "DejaVu Sans Mono": 10, 278 "Liberation Serif": 11, 279 "Liberation Sans": 11, 280 "Liberation Mono": 11, 281 "Verdana": 10, 282 "Menlo": 13, 283 "Consolas": 12, 284 "DejaVuSansMono": 10, 285 "Lucida Sans Typewriter": 10, 286 "Lucida Console": 12, 287 "FreeMono": 8, 288 "FreeSans": 8, 289 "FreeSerif": 8, 290 ]; 291 } 292 static if (ENABLE_OPENGL) { 293 import dlangui.graphics.gldrawbuf; 294 initGLCaches(); 295 } 296 import dlangui.graphics.resources; 297 embedStandardDlangUIResources(); 298 static if (BACKEND_GUI) { 299 _imageCache = new ImageCache(); 300 } 301 _drawableCache = new DrawableCache(); 302 static if (BACKEND_GUI) { 303 version (Windows) { 304 import dlangui.platforms.windows.win32fonts; 305 initWin32FontsTables(); 306 } 307 } 308 309 Log.d("Calling initSharedResourceManagers()"); 310 initSharedResourceManagers(); 311 312 Log.d("Calling initStandardEditorActions()"); 313 import dlangui.widgets.editors; 314 initStandardEditorActions(); 315 316 Log.d("Calling registerStandardWidgets()"); 317 registerStandardWidgets(); 318 319 320 Log.d("initResourceManagers() -- finished"); 321 } 322 323 /// register standard widgets to use in DML 324 void registerStandardWidgets() { 325 Log.d("Registering standard widgets for DML"); 326 import dlangui.widgets.metadata; 327 import dlangui.widgets.widget; 328 import dlangui.widgets.layouts; 329 import dlangui.widgets.controls; 330 import dlangui.widgets.scrollbar; 331 import dlangui.widgets.lists; 332 import dlangui.widgets.combobox; 333 import dlangui.widgets.editors; 334 import dlangui.widgets.grid; 335 import dlangui.widgets.groupbox; 336 import dlangui.widgets.progressbar; 337 import dlangui.dialogs.filedlg; 338 import dlangui.widgets.menu; 339 import dlangui.widgets.tree; 340 mixin(registerWidgets!(FileNameEditLine, DirEditLine, //dlangui.dialogs.filedlg 341 ComboBox, ComboEdit, //dlangui.widgets.combobox 342 Widget, TextWidget, MultilineTextWidget, Button, ImageWidget, ImageButton, ImageCheckButton, ImageTextButton, 343 SwitchButton, RadioButton, CheckBox, HSpacer, VSpacer, CanvasWidget, // dlangui.widgets.controls 344 ScrollBar, SliderWidget, // dlangui.widgets.scrollbar 345 EditLine, EditBox, LogWidget,//dlangui.widgets.editors 346 GroupBox, // dlangui.widgets.groupbox 347 ProgressBarWidget, // dlangui.widgets.progressbar 348 StringGridWidget, //dlangui.widgets.grid 349 VerticalLayout, HorizontalLayout, TableLayout, FrameLayout, // dlangui.widgets.layouts 350 ListWidget, StringListWidget,//dlangui.widgets.lists 351 MainMenu, //dlangui.widgets.menu 352 TreeWidget, // dlangui.widgets.tree 353 )("void registerWidgets")); 354 registerWidgets(); 355 } 356 357 /// call this from shared static this() 358 extern (C) void initSharedResourceManagers() { 359 //Log.d("initSharedResourceManagers()"); 360 //import dlangui.core.i18n; 361 //if (!i18n) { 362 // Log.d("Creating i18n object"); 363 // i18n = new shared UIStringTranslator(); 364 //} 365 } 366 367 shared static this() { 368 //initSharedResourceManagers(); 369 } 370 371 /// call this when all resources are supposed to be freed to report counts of non-freed resources by type 372 extern (C) void releaseResourcesOnAppExit() { 373 374 // 375 debug setAppShuttingDownFlag(); 376 377 debug { 378 if (Widget.instanceCount() > 0) { 379 Log.e("Non-zero Widget instance count when exiting: ", Widget.instanceCount); 380 } 381 } 382 383 currentTheme = null; 384 drawableCache = null; 385 static if (BACKEND_GUI) { 386 imageCache = null; 387 } 388 FontManager.instance = null; 389 static if (ENABLE_OPENGL) { 390 import dlangui.graphics.gldrawbuf; 391 destroyGLCaches(); 392 } 393 394 debug { 395 if (DrawBuf.instanceCount > 0) { 396 Log.e("Non-zero DrawBuf instance count when exiting: ", DrawBuf.instanceCount); 397 } 398 if (Style.instanceCount > 0) { 399 Log.e("Non-zero Style instance count when exiting: ", Style.instanceCount); 400 } 401 if (ImageDrawable.instanceCount > 0) { 402 Log.e("Non-zero ImageDrawable instance count when exiting: ", ImageDrawable.instanceCount); 403 } 404 if (Drawable.instanceCount > 0) { 405 Log.e("Non-zero Drawable instance count when exiting: ", Drawable.instanceCount); 406 } 407 static if (ENABLE_FREETYPE) { 408 import dlangui.graphics.ftfonts; 409 if (FreeTypeFontFile.instanceCount > 0) { 410 Log.e("Non-zero FreeTypeFontFile instance count when exiting: ", FreeTypeFontFile.instanceCount); 411 } 412 if (FreeTypeFont.instanceCount > 0) { 413 Log.e("Non-zero FreeTypeFont instance count when exiting: ", FreeTypeFont.instanceCount); 414 } 415 } 416 } 417 } 418 419 version(unittest) { 420 version (Windows) { 421 mixin APP_ENTRY_POINT; 422 423 /// entry point for dlangui based application 424 extern (C) int UIAppMain(string[] args) { 425 // just to enable running unit tests 426 import core.runtime; 427 import std.stdio; 428 if (!runModuleUnitTests()) { 429 writeln("Error occured in unit tests. Press enter."); 430 readln(); 431 return 1; 432 } 433 return 0; 434 } 435 } 436 } 437 438