Klammertext runs natively on Windows; a Windows source-install guide; the bundled sh for @eval :shell
Assembled from klammertext-dev f344a37d772c. The commands, the library,
the Standard Klammer Set, the reflection klammerset and the Python
binding build and run natively on Windows (MSYS2 UCRT64 gcc, python.org
Python), and both test tiers pass there. doc/install/windows_source_install.md
is the fifth install guide: a source install parallel to the Linux and
macOS ones, verified by following it on a pristine Windows 11.
Behaviour on every system: paths Klammertext prints use forward slashes;
output is LF; the command line is UTF-8 on Windows; @eval :shell is a
POSIX shell command everywhere -- on Windows it runs the sh Klammertext
ships, BusyBox for Windows (win/busybox/, GPLv2, with its licence and the
source pointer). KLAMMERTEXT_FONTS and KLAMMERTEXT_KLAMMERSETS are lists in
the system's PATH convention (';' on Windows). On Linux and macOS nothing
observable changes.
This commit is contained in:
1 parent
f9af1ff869
commit
830b19394d
55 files changed
+1182
-153
No files matched your search
+25
-27
@@ -23,12 +23,20 @@
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
// The interpreter spawned for the font-metric script: python.org's Windows
|
||||
// build installs "python" only; Linux and macOS name it "python3".
|
||||
#ifdef _WIN32
|
||||
static const char* const python_interpreter = "python";
|
||||
#else
|
||||
static const char* const python_interpreter = "python3";
|
||||
#endif
|
||||
|
||||
|
||||
// A filesystem extension lowercased for case-insensitive matching, so a
|
||||
// font named Foo.TTF or Foo.OTF is recognized like Foo.ttf / Foo.otf.
|
||||
static std::string lower_extension(const fs::path& path)
|
||||
{
|
||||
std::string ext = path.extension();
|
||||
std::string ext = path.extension().string();
|
||||
for (char& c : ext) {
|
||||
c = std::tolower(static_cast<unsigned char>(c));
|
||||
}
|
||||
@@ -49,29 +57,14 @@ std::string name_to_dirname(const std::string& name)
|
||||
}
|
||||
|
||||
|
||||
// The directories searched for installed fonts: the colon-separated
|
||||
// KLAMMERTEXT_FONTS environment variable, or ~/.klammertext/fonts when it
|
||||
// is not set. Directories are searched in listed order, and the default
|
||||
// fonts in $KLAMMERTEXT_HOME/fnt are searched last, so an installed font
|
||||
// can deliberately shadow a default one.
|
||||
// The directories searched for installed fonts: the KLAMMERTEXT_FONTS
|
||||
// environment variable (a list in the system's PATH convention: ':' or, on
|
||||
// Windows, ';'), or ~/.klammertext/fonts when it is not set. Directories are
|
||||
// searched in listed order, and the default fonts in $KLAMMERTEXT_HOME/fnt are
|
||||
// searched last, so an installed font can deliberately shadow a default one.
|
||||
strings_t installed_font_dirs()
|
||||
{
|
||||
strings_t result {};
|
||||
std::string paths {};
|
||||
const char* env = std::getenv("KLAMMERTEXT_FONTS");
|
||||
if (env && *env) {
|
||||
paths = env;
|
||||
} else if (const char* home = std::getenv("HOME"); home && *home) {
|
||||
paths = std::string(home) + "/.klammertext/fonts";
|
||||
}
|
||||
std::stringstream ss(paths);
|
||||
std::string dir;
|
||||
while (std::getline(ss, dir, ':')) {
|
||||
if (!dir.empty()) {
|
||||
result.push_back(dir);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
return directory_list("KLAMMERTEXT_FONTS", ".klammertext/fonts");
|
||||
}
|
||||
|
||||
std::string default_font_dir()
|
||||
@@ -151,7 +144,7 @@ std::vector<Resolved_font> fonts_in_directory(const std::string& base)
|
||||
for (auto& entry : fs::directory_iterator(base)) {
|
||||
if (entry.path().extension() == ".css" &&
|
||||
fs::is_directory(base + "/" + entry.path().stem().string())) {
|
||||
names.push_back(entry.path().stem());
|
||||
names.push_back(entry.path().stem().string());
|
||||
}
|
||||
}
|
||||
std::sort(names.begin(), names.end());
|
||||
@@ -199,10 +192,12 @@ static void extract_font_metrics(Resolved_font& font)
|
||||
if (!fs::exists(ttf_path))
|
||||
return;
|
||||
// Extract both x-height and cap-height ratios from OS/2 table
|
||||
// The path goes inside a Python literal: forward slashes, which Python
|
||||
// opens on every system, where a Windows backslash would be an escape.
|
||||
std::string script =
|
||||
"python3 -c \""
|
||||
std::string(python_interpreter) + " -c \""
|
||||
"import struct; "
|
||||
"f = open('" + ttf_path + "', 'rb'); "
|
||||
"f = open('" + fs::path(ttf_path).generic_string() + "', 'rb'); "
|
||||
"_, n = struct.unpack('>IH', f.read(6)); "
|
||||
"f.read(6); "
|
||||
"t = {};\n"
|
||||
@@ -219,6 +214,9 @@ static void extract_font_metrics(Resolved_font& font)
|
||||
"print(f'{xh/upm:.4f} {ch/upm:.4f}') if ver >= 2 else None; "
|
||||
"f.close()\"";
|
||||
std::string result = trim(exec(script.c_str()));
|
||||
// A DERIVED value a designer cannot read off the font: the two ratios
|
||||
// (or nothing, when the script failed) decide the html size normalization.
|
||||
(void)K::log(3, "Font metrics of " + ttf_path + ": " + (result.empty() ? std::string("(none)") : result));
|
||||
if (!result.empty()) {
|
||||
try {
|
||||
auto pos = result.find(' ');
|
||||
@@ -418,7 +416,7 @@ std::vector<Font_file> classify_font_files(const std::string& directory)
|
||||
for (auto& entry : fs::recursive_directory_iterator(directory)) {
|
||||
std::string ext = lower_extension(entry.path());
|
||||
if (entry.is_regular_file() && (ext == ".ttf" || ext == ".otf")) {
|
||||
result.push_back(classify_font_file(entry.path()));
|
||||
result.push_back(classify_font_file(entry.path().string()));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
@@ -521,7 +519,7 @@ std::string write_font_samples(const std::string& output_dir, const std::string&
|
||||
install_fonts(source_dir, output_dir + "/fonts");
|
||||
for (auto& entry : fs::directory_iterator(output_dir + "/fonts")) {
|
||||
if (entry.path().extension() == ".css") {
|
||||
std::string css = string_from_file(entry.path());
|
||||
std::string css = string_from_file(entry.path().string());
|
||||
std::smatch match {};
|
||||
if (std::regex_search(css, match,
|
||||
std::regex(R"(font-family:\s*'([^']+)')"))) {
|
||||
|
||||
Reference in new issue
Block a user