// Copyright (c) 2019-2021 Alexander Medvednikov. All rights reserved. // Use of this source code is governed by an MIT license that can be found in the LICENSE file. module gg import os import gx enum FontVariant { normal = 0 bold mono italic } struct FTConfig { font_path string custom_bold_font_path string scale f32 = 1.0 font_size int bytes_normal []byte bytes_bold []byte bytes_mono []byte bytes_italic []byte } struct StringToRender { x int y int text string cfg gx.TextCfg } pub fn system_font_path() string { env_font := os.getenv('VUI_FONT') if env_font != '' && os.exists(env_font) { return env_font } $if windows { return 'C:\\Windows\\Fonts\\arial.ttf' } mut fonts := ['Ubuntu-R.ttf', 'Arial.ttf', 'LiberationSans-Regular.ttf', 'NotoSans-Regular.ttf', 'FreeSans.ttf', 'DejaVuSans.ttf'] $if macos { fonts = ['/System/Library/Fonts/SFNS.ttf', '/System/Library/Fonts/SFNSText.ttf', '/Library/Fonts/Arial.ttf'] for font in fonts { if os.is_file(font) { return font } } } $if android { xml_files := ['/system/etc/system_fonts.xml', '/system/etc/fonts.xml', '/etc/system_fonts.xml', '/etc/fonts.xml', '/data/fonts/fonts.xml', '/etc/fallback_fonts.xml'] font_locations := ['/system/fonts', '/data/fonts'] for xml_file in xml_files { if os.is_file(xml_file) && os.is_readable(xml_file) { xml := os.read_file(xml_file) or { continue } lines := xml.split('\n') mut candidate_font := '' for line in lines { if line.contains('').all_before('<').trim(' \n\t\r') if candidate_font.contains('.ttf') { for location in font_locations { candidate_path := os.join_path(location, candidate_font) if os.is_file(candidate_path) && os.is_readable(candidate_path) { return candidate_path } } } } } } } } s := os.execute('fc-list') if s.exit_code != 0 { panic('failed to fetch system fonts') } system_fonts := s.output.split('\n') for line in system_fonts { for font in fonts { if line.contains(font) && line.contains(':') { res := line.all_before(':') println('Using font $res') return res } } } panic('failed to init the font') } fn get_font_path_variant(font_path string, variant FontVariant) string { // TODO: find some way to make this shorter and more eye-pleasant // NotoSans, LiberationSans, DejaVuSans, Arial and SFNS should work mut file := os.file_name(font_path) mut fpath := font_path.replace(file, '') file = file.replace('.ttf', '') match variant { .normal {} .bold { if fpath.ends_with('-Regular') { file = file.replace('-Regular', '-Bold') } else if file.starts_with('DejaVuSans') { file += '-Bold' } else if file.to_lower().starts_with('arial') { file += 'bd' } else { file += '-bold' } $if macos { if os.exists('SFNS-bold') { file = 'SFNS-bold' } } } .italic { if file.ends_with('-Regular') { file = file.replace('-Regular', '-Italic') } else if file.starts_with('DejaVuSans') { file += '-Oblique' } else if file.to_lower().starts_with('arial') { file += 'i' } else { file += 'Italic' } } .mono { if !file.ends_with('Mono-Regular') && file.ends_with('-Regular') { file = file.replace('-Regular', 'Mono-Regular') } else if file.to_lower().starts_with('arial') { // Arial has no mono variant } else { file += 'Mono' } } } return fpath + file + '.ttf' } fn debug_font_println(s string) { $if debug_font ? { println(s) } }