More work on text rendering
This commit is contained in:
parent
cdbc096990
commit
41b9495588
@ -10,6 +10,7 @@
|
||||
#include "fonts.h"
|
||||
#include <fontconfig/fontconfig.h>
|
||||
#include "emoji.h"
|
||||
#include "freetype_render_ui_text.h"
|
||||
#ifndef FC_COLOR
|
||||
#define FC_COLOR "color"
|
||||
#endif
|
||||
@ -168,28 +169,36 @@ end:
|
||||
if (charset != NULL) FcCharSetDestroy(charset);
|
||||
}
|
||||
|
||||
const char*
|
||||
file_path_for_font(const char *family, bool bold, bool italic) {
|
||||
const char *ans = NULL;
|
||||
bool
|
||||
information_for_font_family(const char *family, bool bold, bool italic, FontConfigFace *ans) {
|
||||
memset(ans, 0, sizeof(FontConfigFace));
|
||||
FcPattern *match = NULL;
|
||||
FcPattern *pat = FcPatternCreate();
|
||||
if (pat == NULL) { PyErr_NoMemory(); return NULL; }
|
||||
bool ok = false;
|
||||
if (pat == NULL) { PyErr_NoMemory(); return ok; }
|
||||
if (family && strlen(family) > 0) AP(FcPatternAddString, FC_FAMILY, (const FcChar8*)family, "family");
|
||||
if (bold) { AP(FcPatternAddInteger, FC_WEIGHT, FC_WEIGHT_BOLD, "weight"); }
|
||||
if (italic) { AP(FcPatternAddInteger, FC_SLANT, FC_SLANT_ITALIC, "slant"); }
|
||||
FcResult result;
|
||||
FcConfigSubstitute(NULL, pat, FcMatchPattern);
|
||||
FcDefaultSubstitute(pat);
|
||||
/* printf("fc_match = %s\n", FcNameUnparse(pat)); */
|
||||
match = FcFontMatch(NULL, pat, &result);
|
||||
if (match == NULL) { PyErr_SetString(PyExc_KeyError, "FcFontMatch() failed"); goto end; }
|
||||
FcChar8 *out;
|
||||
if (FcPatternGetString(pat, FC_FILE, 0, &out) != FcResultMatch) { PyErr_SetString(PyExc_ValueError, "No path found in fontconfig result"); goto end; }
|
||||
ans = strdup((char*)out);
|
||||
if (!ans) { PyErr_NoMemory(); goto end; }
|
||||
#define g(func, prop, output) if (func(match, prop, 0, &output) != FcResultMatch) { PyErr_SetString(PyExc_ValueError, "No " #prop " found in fontconfig match result"); goto end; }
|
||||
g(FcPatternGetString, FC_FILE, out);
|
||||
g(FcPatternGetInteger, FC_INDEX, ans->index);
|
||||
g(FcPatternGetInteger, FC_HINT_STYLE, ans->hintstyle);
|
||||
g(FcPatternGetBool, FC_HINTING, ans->hinting);
|
||||
#undef g
|
||||
ans->path = strdup((char*)out);
|
||||
if (!ans->path) { PyErr_NoMemory(); goto end; }
|
||||
ok = true;
|
||||
end:
|
||||
if (match != NULL) FcPatternDestroy(match);
|
||||
if (pat != NULL) FcPatternDestroy(pat);
|
||||
return ans;
|
||||
return ok;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -50,8 +50,3 @@ right_shift_canvas(pixel *canvas, size_t width, size_t height, size_t amt) {
|
||||
zero_at_ptr_count(src, amt);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifndef __APPLE__
|
||||
const char* file_path_for_font(const char *family, bool bold, bool italic);
|
||||
#endif
|
||||
|
||||
@ -252,6 +252,15 @@ face_from_descriptor(PyObject *descriptor, FONTS_DATA_HANDLE fg) {
|
||||
return (PyObject*)self;
|
||||
}
|
||||
|
||||
FT_Face
|
||||
native_face_from_path(const char *path, int index) {
|
||||
int error;
|
||||
FT_Face ans;
|
||||
error = FT_New_Face(library, path, index, &ans);
|
||||
if (error) { set_freetype_error("Failed to load face, with error:", error); return NULL; }
|
||||
return ans;
|
||||
}
|
||||
|
||||
PyObject*
|
||||
face_from_path(const char *path, int index, FONTS_DATA_HANDLE fg) {
|
||||
Face *ans = (Face*)Face_Type.tp_alloc(&Face_Type, 0);
|
||||
|
||||
@ -5,16 +5,54 @@
|
||||
* Distributed under terms of the GPL3 license.
|
||||
*/
|
||||
|
||||
#include "data-types.h"
|
||||
#include "fonts.h"
|
||||
#include "freetype_render_ui_text.h"
|
||||
#include <hb.h>
|
||||
#include <hb-ft.h>
|
||||
|
||||
typedef struct FamilyInformation {
|
||||
char *name;
|
||||
bool bold, italic;
|
||||
} FamilyInformation;
|
||||
|
||||
FT_Face main_face = NULL;
|
||||
FontConfigFace main_face_information = {0};
|
||||
FamilyInformation main_face_family = {0};
|
||||
|
||||
|
||||
static void
|
||||
cleanup(void) {
|
||||
if (main_face) FT_Done_Face(main_face);
|
||||
main_face = NULL;
|
||||
free(main_face_information.path); main_face_information.path = NULL;
|
||||
free(main_face_family.name);
|
||||
memset(&main_face_family, 0, sizeof(FamilyInformation));
|
||||
}
|
||||
|
||||
void
|
||||
set_main_face_family(const char *family, bool bold, bool italic) {
|
||||
cleanup();
|
||||
main_face_family.name = strdup(family);
|
||||
main_face_family.bold = bold; main_face_family.italic = italic;
|
||||
}
|
||||
|
||||
static bool
|
||||
ensure_state(void) {
|
||||
if (main_face) return false;
|
||||
if (!information_for_font_family(main_face_family.name, main_face_family.bold, main_face_family.italic, &main_face_information)) return false;
|
||||
main_face = native_face_from_path(main_face_information.path, main_face_information.index);
|
||||
return !!main_face;
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
path_for_font(PyObject *self UNUSED, PyObject *args) {
|
||||
(void)ensure_state;
|
||||
const char *family = NULL; int bold = 0, italic = 0;
|
||||
if (!PyArg_ParseTuple(args, "|zpp", &family, &bold, &italic)) return NULL;
|
||||
const char *ans = file_path_for_font(family, bold, italic);
|
||||
if (!ans) return NULL;
|
||||
return PyUnicode_FromString(ans);
|
||||
FontConfigFace f;
|
||||
if (!information_for_font_family(family, bold, italic, &f)) return NULL;
|
||||
PyObject *ret = Py_BuildValue("{ss si si si}", "path", f.path, "index", f.index, "hinting", f.hinting, "hintstyle", f.hintstyle);
|
||||
free(f.path);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static PyMethodDef module_methods[] = {
|
||||
@ -27,5 +65,9 @@ static PyMethodDef module_methods[] = {
|
||||
bool
|
||||
init_freetype_render_ui_text(PyObject *module) {
|
||||
if (PyModule_AddFunctions(module, module_methods) != 0) return false;
|
||||
if (Py_AtExit(cleanup) != 0) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "Failed to register the fontconfig library at exit handler");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
23
kitty/freetype_render_ui_text.h
Normal file
23
kitty/freetype_render_ui_text.h
Normal file
@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Kovid Goyal <kovid at kovidgoyal.net>
|
||||
*
|
||||
* Distributed under terms of the GPL3 license.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "data-types.h"
|
||||
#include <hb-ft.h>
|
||||
|
||||
typedef struct FontConfigFace {
|
||||
char *path;
|
||||
int index;
|
||||
int hinting;
|
||||
int hintstyle;
|
||||
} FontConfigFace;
|
||||
|
||||
bool information_for_font_family(const char *family, bool bold, bool italic, FontConfigFace *ans);
|
||||
FT_Face native_face_from_path(const char *path, int index);
|
||||
|
||||
|
||||
void set_main_face_family(const char *family, bool bold, bool italic);
|
||||
Loading…
x
Reference in New Issue
Block a user