mirror of
https://github.com/kovidgoyal/kitty
synced 2026-06-15 21:17:49 +02:00
Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7f61f1f9f3 | ||
|
|
bb3b5df99a | ||
|
|
ab26d2204f | ||
|
|
2e2caa167a | ||
|
|
4ba6d02ab6 | ||
|
|
b9dc48b798 | ||
|
|
37f842d06a | ||
|
|
2cdabdfebd | ||
|
|
63ffa2606c | ||
|
|
f66ee68834 | ||
|
|
494892c7e4 | ||
|
|
6c1a83ffd7 | ||
|
|
e531791f79 | ||
|
|
5b587060a4 | ||
|
|
4ad8d30751 |
@@ -116,7 +116,7 @@ Build-time dependencies:
|
||||
- ``libssl-dev``
|
||||
- ``libpython3-dev``
|
||||
- ``libxxhash-dev``
|
||||
- ``libsmide-dev``
|
||||
- ``libsimde-dev``
|
||||
|
||||
|
||||
Build and run from source with Nix
|
||||
|
||||
@@ -50,6 +50,15 @@ consumption to do the same tasks.
|
||||
Detailed list of changes
|
||||
-------------------------------------
|
||||
|
||||
0.34.1 [2024-04-19]
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
- Wayland KDE: Fix window background blur not adapting when window is grown. Also fix turning it on and off not working. (:iss:`7351`)
|
||||
|
||||
- Wayland GNOME: Draw the titlebar buttons without using a font (:iss:`7349`)
|
||||
|
||||
- Fix a regression in the previous release that caused incorrect font selection when using variable fonts on Linux (:iss:`7361`)
|
||||
|
||||
0.34.0 [2024-04-15]
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
||||
@@ -465,9 +465,9 @@ for tmux refusing to support images.
|
||||
If you use any of the advanced features that kitty has innovated, such as
|
||||
:doc:`styled underlines </underlines>`, :doc:`desktop notifications
|
||||
</desktop-notifications>`, :doc:`extended keyboard support
|
||||
</keyboard-protocol>`, :doc:`file transfer </kittens/transfer>`, etc.
|
||||
they may or may not work, depending on the whims of tmux's maintainer,
|
||||
your version of tmux, etc.
|
||||
</keyboard-protocol>`, :doc:`file transfer </kittens/transfer>`, :doc:`the ssh
|
||||
kitten </kittens/ssh>`, etc. they may or may not work,
|
||||
depending on the whims of tmux's maintainer, your version of tmux, etc.
|
||||
|
||||
|
||||
I opened and closed a lot of windows/tabs and top shows kitty's memory usage is very high?
|
||||
|
||||
176
glfw/wl_client_side_decorations.c
vendored
176
glfw/wl_client_side_decorations.c
vendored
@@ -171,6 +171,158 @@ csd_initialize_metrics(_GLFWwindow *window) {
|
||||
decs.metrics.vertical = decs.metrics.width + decs.metrics.top;
|
||||
}
|
||||
|
||||
static void
|
||||
patch_titlebar_with_alpha_mask(uint32_t *dest, uint8_t *src, unsigned height, unsigned dest_stride, unsigned src_width, unsigned dest_left, uint32_t bg, uint32_t fg) {
|
||||
for (unsigned y = 0; y < height; y++, src += src_width, dest += dest_stride) {
|
||||
uint32_t *d = dest + dest_left;
|
||||
for (unsigned i = 0; i < src_width; i++) {
|
||||
const uint8_t alpha = src[i], calpha = 255 - alpha;
|
||||
// Blend the red and blue components
|
||||
uint32_t ans = ((bg & 0xff00ff) * calpha + (fg & 0xff00ff) * alpha) & 0xff00ff00;
|
||||
// Blend the green component
|
||||
ans += ((bg & 0xff00) * calpha + (fg & 0xff00) * alpha) & 0xff0000;
|
||||
ans >>= 8;
|
||||
d[i] = ans | 0xff000000;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
render_hline(uint8_t *out, unsigned width, unsigned thickness, unsigned bottom, unsigned left, unsigned right) {
|
||||
for (unsigned y = bottom - thickness; y < bottom; y++) {
|
||||
uint8_t *dest = out + width * y;
|
||||
for (unsigned x = left; x < right; x++) dest[x] = 255;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
render_vline(uint8_t *out, unsigned width, unsigned thickness, unsigned left, unsigned top, unsigned bottom) {
|
||||
for (unsigned y = top; y < bottom; y++) {
|
||||
uint8_t *dest = out + width * y;
|
||||
for (unsigned x = left; x < left + thickness; x++) dest[x] = 255;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
scale(unsigned thickness, float factor) {
|
||||
return (unsigned)(roundf(thickness * factor));
|
||||
}
|
||||
|
||||
static void
|
||||
render_minimize(uint8_t *out, unsigned width, unsigned height) {
|
||||
memset(out, 0, width * height);
|
||||
unsigned thickness = height / 12;
|
||||
unsigned baseline = height - thickness * 2;
|
||||
unsigned side_margin = (int)roundf(thickness * 3.8f);
|
||||
if (!thickness || width <= side_margin || height < baseline + 2 * thickness) return;
|
||||
render_hline(out, width, thickness, baseline, side_margin, width - side_margin);
|
||||
}
|
||||
|
||||
static void
|
||||
render_maximize(uint8_t *out, unsigned width, unsigned height) {
|
||||
memset(out, 0, width * height);
|
||||
unsigned thickness = height / 12, half_thickness = thickness / 2;
|
||||
unsigned baseline = height - thickness * 2;
|
||||
unsigned side_margin = scale(thickness, 3.0f);
|
||||
unsigned top = 4 * thickness;
|
||||
if (!half_thickness || width <= side_margin || height < baseline + 2 * thickness || top >= baseline) return;
|
||||
render_hline(out, width, half_thickness, baseline, side_margin, width - side_margin);
|
||||
render_hline(out, width, thickness, top + thickness, side_margin, width - side_margin);
|
||||
render_vline(out, width, half_thickness, side_margin, top, baseline);
|
||||
render_vline(out, width, half_thickness, width - side_margin, top, baseline);
|
||||
}
|
||||
|
||||
static void
|
||||
render_restore(uint8_t *out, unsigned width, unsigned height) {
|
||||
memset(out, 0, width * height);
|
||||
unsigned thickness = height / 12, half_thickness = thickness / 2;
|
||||
unsigned baseline = height - thickness * 2;
|
||||
unsigned side_margin = scale(thickness, 3.0f);
|
||||
unsigned top = 4 * thickness;
|
||||
if (!half_thickness || width <= side_margin || height < baseline + 2 * thickness || top >= baseline) return;
|
||||
unsigned box_height = ((baseline - top) * 3) / 4;
|
||||
if (box_height < 2*thickness) return;
|
||||
unsigned box_width = ((width - 2 * side_margin) * 3) / 4;
|
||||
// bottom box
|
||||
unsigned box_top = baseline - box_height, left = side_margin, right = side_margin + box_width, bottom = baseline;
|
||||
render_hline(out, width, thickness, box_top + thickness, left, right);
|
||||
render_hline(out, width, half_thickness, bottom, left, right);
|
||||
render_vline(out, width, half_thickness, left, box_top, bottom);
|
||||
render_vline(out, width, half_thickness, side_margin + box_width, baseline - box_height, baseline);
|
||||
// top box
|
||||
unsigned box_x_shift = 2 * thickness, box_y_shift = 2 * thickness;
|
||||
box_x_shift = MIN(width - right, box_x_shift);
|
||||
box_y_shift = MIN(box_top, box_y_shift);
|
||||
unsigned left2 = left + box_x_shift, right2 = right + box_x_shift, top2 = box_top - box_y_shift, bottom2 = bottom - box_y_shift;
|
||||
render_hline(out, width, thickness, top2 + thickness, left2, right2);
|
||||
render_vline(out, width, half_thickness, right2, top2, bottom2);
|
||||
render_hline(out, width, half_thickness, bottom2, right, right2);
|
||||
render_vline(out, width, half_thickness, left2, top2, box_top);
|
||||
}
|
||||
|
||||
static void
|
||||
render_line(uint8_t *buf, unsigned width, unsigned height, unsigned thickness, int x1, int y1, int x2, int y2) {
|
||||
float m = (y2 - y1) / (float)(x2 - x1);
|
||||
float c = y1 - m * x1;
|
||||
unsigned delta = thickness / 2, extra = thickness % 2;
|
||||
for (int x = MAX(0, MIN(x1, x2)); x < MIN((int)width, MAX(x1, x2) + 1); x++) {
|
||||
float ly = m * x + c;
|
||||
for (int y = MAX(0, (int)(ly - delta)); y < MIN((int)height, (int)(ly + delta + extra + 1)); y++) buf[x + y * width] = 255;
|
||||
}
|
||||
for (int y = MAX(0, MIN(y1, y2)); y < MIN((int)height, MAX(y1, y2) + 1); y++) {
|
||||
float lx = (y - c) / m;
|
||||
for (int x = MAX(0, (int)(lx - delta)); x < MIN((int)width, (int)(lx + delta + extra + 1)); x++) buf[x + y * width] = 255;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
render_close(uint8_t *out, unsigned width, unsigned height) {
|
||||
memset(out, 0, width * height);
|
||||
unsigned thickness = height / 12;
|
||||
unsigned baseline = height - thickness * 2;
|
||||
unsigned side_margin = scale(thickness, 3.3f);
|
||||
int top = baseline - (width - 2 * side_margin);
|
||||
if (top <= 0) return;
|
||||
unsigned line_thickness = scale(thickness, 1.5f);
|
||||
render_line(out, width, height, line_thickness, side_margin, top, width - side_margin, baseline);
|
||||
render_line(out, width, height, line_thickness, side_margin, baseline, width - side_margin, top);
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
average_intensity_in_src(uint8_t *src, unsigned src_width, unsigned src_x, unsigned src_y, unsigned factor) {
|
||||
uint32_t ans = 0;
|
||||
for (unsigned y = src_y; y < src_y + factor; y++) {
|
||||
uint8_t *s = src + src_width * y;
|
||||
for (unsigned x = src_x; x < src_x + factor; x++) ans += s[x];
|
||||
}
|
||||
return ans / (factor * factor);
|
||||
}
|
||||
|
||||
static void
|
||||
downsample(uint8_t *dest, uint8_t *src, unsigned dest_width, unsigned dest_height, unsigned factor) {
|
||||
unsigned src_width = factor * dest_width;
|
||||
for (unsigned y = 0; y < dest_height; y++) {
|
||||
uint8_t *d = dest + dest_width * y;
|
||||
for (unsigned x = 0; x < dest_width; x++) {
|
||||
d[x] = MIN(255u, (uint32_t)d[x] + average_intensity_in_src(src, src_width, x * factor, y * factor, factor));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
render_button(void(*which)(uint8_t *, unsigned, unsigned), bool antialias, uint32_t *dest, uint8_t *src, unsigned height, unsigned dest_stride, unsigned src_width, unsigned dest_left, uint32_t bg, uint32_t fg) {
|
||||
if (antialias) {
|
||||
static const unsigned factor = 4;
|
||||
uint8_t *big_src = malloc(factor * factor * height * src_width);
|
||||
if (big_src) {
|
||||
which(big_src, src_width * factor, height * factor);
|
||||
memset(src, 0, src_width * height);
|
||||
downsample(src, big_src, src_width, height, factor);
|
||||
free(big_src);
|
||||
} else which(src, src_width, height);
|
||||
} else which(src, src_width, height);
|
||||
patch_titlebar_with_alpha_mask(dest, src, height, dest_stride, src_width, dest_left, bg, fg);
|
||||
}
|
||||
|
||||
static void
|
||||
render_title_bar(_GLFWwindow *window, bool to_front_buffer) {
|
||||
@@ -194,7 +346,7 @@ render_title_bar(_GLFWwindow *window, bool to_front_buffer) {
|
||||
uint8_t *output = to_front_buffer ? decs.titlebar.buffer.data.front : decs.titlebar.buffer.data.back;
|
||||
|
||||
// render text part
|
||||
int button_size = (int)roundf(decs.metrics.visible_titlebar_height * decs.for_window_state.fscale);
|
||||
int button_size = decs.titlebar.buffer.height;
|
||||
int num_buttons = 1;
|
||||
if (window->wl.wm_capabilities.maximize) num_buttons++;
|
||||
if (window->wl.wm_capabilities.minimize) num_buttons++;
|
||||
@@ -207,16 +359,20 @@ render_title_bar(_GLFWwindow *window, bool to_front_buffer) {
|
||||
render_buttons:
|
||||
decs.maximize.width = 0; decs.minimize.width = 0; decs.close.width = 0;
|
||||
if (!button_size) return;
|
||||
|
||||
uint8_t *alpha_mask = malloc(button_size * button_size);
|
||||
int left = decs.titlebar.buffer.width - num_buttons * button_size;
|
||||
#define draw(which, text, hover_bg) { \
|
||||
_glfw.callbacks.draw_text((GLFWwindow*)window, text, fg_color, decs.which.hovered ? hover_bg : bg_color, output, decs.titlebar.buffer.width, \
|
||||
decs.titlebar.buffer.height, /*x=*/left, /*y=*/0, /*right_margin=*/decs.titlebar.buffer.width - left - button_size, true); \
|
||||
decs.which.left = left; decs.which.width = button_size; left += button_size; \
|
||||
}
|
||||
if (window->wl.wm_capabilities.minimize) draw(minimize, "🗕", hover_bg);
|
||||
if (window->wl.wm_capabilities.maximize) draw(maximize, is_maximized ? "🗗" : "🗖", hover_bg);
|
||||
draw(close, "🗙", is_dark ? 0xff880000: 0xffc80000);
|
||||
#undef draw
|
||||
if (!alpha_mask || left <= 0) return;
|
||||
#define drawb(which, antialias, func, hover_bg) { \
|
||||
render_button(func, antialias, (uint32_t*)output, alpha_mask, button_size, decs.titlebar.buffer.width, button_size, left, decs.which.hovered ? hover_bg : bg_color, fg_color); decs.which.left = left; decs.which.width = button_size; left += button_size; }
|
||||
|
||||
if (window->wl.wm_capabilities.minimize) drawb(minimize, false, render_minimize, hover_bg);
|
||||
if (window->wl.wm_capabilities.maximize) {
|
||||
if (is_maximized) { drawb(maximize, false, render_restore, hover_bg); } else { drawb(maximize, false, render_maximize, hover_bg); }
|
||||
}
|
||||
drawb(close, true, render_close, is_dark ? 0xff880000: 0xffc80000);
|
||||
free(alpha_mask);
|
||||
#undef drawb
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
28
glfw/wl_init.c
vendored
28
glfw/wl_init.c
vendored
@@ -633,17 +633,31 @@ GLFWAPI GLFWColorScheme glfwGetCurrentSystemColorTheme(void) {
|
||||
return glfw_current_system_color_theme();
|
||||
}
|
||||
|
||||
static pid_t
|
||||
get_socket_peer_pid(int fd) {
|
||||
#ifdef __linux__
|
||||
struct ucred ucred;
|
||||
socklen_t len = sizeof(struct ucred);
|
||||
return (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &len) == -1) ? -1 : ucred.pid;
|
||||
#elif defined(LOCAL_PEERCRED) && defined(XUCRED_VERSION)
|
||||
struct xucred peercred;
|
||||
socklen_t peercredlen = sizeof(peercred);
|
||||
return (getsockopt(c->fd, LOCAL_PEERCRED, 1, (void *)&peercred, &peercredlen) == 0 && peercred.cr_version == XUCRED_VERSION) ? peercred.cr_pid : -1;
|
||||
#elif defined(LOCAL_PEERPID)
|
||||
pid_t pid;
|
||||
socklen_t pid_size = sizeof(pid);
|
||||
return getsockopt(client, SOL_LOCAL, LOCAL_PEERPID, &pid, &pid_size) == -1 ? -1 : pid;
|
||||
#else
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
GLFWAPI pid_t glfwWaylandCompositorPID(void) {
|
||||
if (!_glfw.wl.display) return -1;
|
||||
int fd = wl_display_get_fd(_glfw.wl.display);
|
||||
if (fd < 0) return -1;
|
||||
struct ucred ucred;
|
||||
socklen_t len = sizeof(struct ucred);
|
||||
if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &len) == -1) {
|
||||
perror("getsockopt failed");
|
||||
return -1;
|
||||
}
|
||||
return ucred.pid;
|
||||
return get_socket_peer_pid(fd);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
34
glfw/wl_window.c
vendored
34
glfw/wl_window.c
vendored
@@ -316,20 +316,30 @@ checkScaleChange(_GLFWwindow* window) {
|
||||
|
||||
static void
|
||||
update_regions(_GLFWwindow* window) {
|
||||
if (window->wl.transparent && !window->wl.org_kde_kwin_blur) return;
|
||||
struct wl_region* region = wl_compositor_create_region(_glfw.wl.compositor);
|
||||
if (!region) return;
|
||||
wl_region_add(region, 0, 0, window->wl.width, window->wl.height);
|
||||
// Makes the surface considered as XRGB instead of ARGB.
|
||||
if (!window->wl.transparent) wl_surface_set_opaque_region(window->wl.surface, region);
|
||||
|
||||
if (!window->wl.transparent) {
|
||||
struct wl_region* region = wl_compositor_create_region(_glfw.wl.compositor);
|
||||
if (!region) return;
|
||||
wl_region_add(region, 0, 0, window->wl.width, window->wl.height);
|
||||
// Makes the surface considered as XRGB instead of ARGB.
|
||||
wl_surface_set_opaque_region(window->wl.surface, region);
|
||||
wl_region_destroy(region);
|
||||
}
|
||||
// Set blur region
|
||||
if (window->wl.org_kde_kwin_blur) {
|
||||
org_kde_kwin_blur_set_region(window->wl.org_kde_kwin_blur, window->wl.has_blur ? region: NULL);
|
||||
org_kde_kwin_blur_commit(window->wl.org_kde_kwin_blur);
|
||||
if (_glfw.wl.org_kde_kwin_blur_manager) {
|
||||
if (window->wl.has_blur) {
|
||||
if (!window->wl.org_kde_kwin_blur)
|
||||
window->wl.org_kde_kwin_blur = org_kde_kwin_blur_manager_create(_glfw.wl.org_kde_kwin_blur_manager, window->wl.surface);
|
||||
if (window->wl.org_kde_kwin_blur) {
|
||||
// NULL means entire window
|
||||
org_kde_kwin_blur_set_region(window->wl.org_kde_kwin_blur, NULL);
|
||||
org_kde_kwin_blur_commit(window->wl.org_kde_kwin_blur);
|
||||
}
|
||||
} else {
|
||||
org_kde_kwin_blur_manager_unset(_glfw.wl.org_kde_kwin_blur_manager, window->wl.surface);
|
||||
if (window->wl.org_kde_kwin_blur) { org_kde_kwin_blur_release(window->wl.org_kde_kwin_blur); window->wl.org_kde_kwin_blur = NULL; }
|
||||
}
|
||||
}
|
||||
|
||||
wl_region_destroy(region);
|
||||
}
|
||||
|
||||
int
|
||||
@@ -2618,8 +2628,6 @@ _glfwPlatformSetWindowBlur(_GLFWwindow *window, int blur_radius) {
|
||||
bool has_blur = window->wl.has_blur;
|
||||
bool new_has_blur = blur_radius > 0;
|
||||
if (new_has_blur != has_blur) {
|
||||
if (!window->wl.org_kde_kwin_blur)
|
||||
window->wl.org_kde_kwin_blur = org_kde_kwin_blur_manager_create(_glfw.wl.org_kde_kwin_blur_manager, window->wl.surface);
|
||||
window->wl.has_blur = new_has_blur;
|
||||
update_regions(window);
|
||||
}
|
||||
|
||||
@@ -438,9 +438,12 @@ cocoa_send_notification(PyObject *self UNUSED, PyObject *args) {
|
||||
}
|
||||
@end
|
||||
|
||||
|
||||
static void
|
||||
schedule_notification(const char *identifier, const char *title, const char *body, const char *subtitle) {
|
||||
static UNUserNotificationCenter*
|
||||
get_notification_center_safely(void) {
|
||||
NSBundle *b = [NSBundle mainBundle];
|
||||
// when bundleIdentifier is nil currentNotificationCenter crashes instead
|
||||
// of returning nil. Apple...purveyor of shiny TOYS
|
||||
if (!b || !b.bundleIdentifier) return nil;
|
||||
UNUserNotificationCenter *center = nil;
|
||||
@try {
|
||||
center = [UNUserNotificationCenter currentNotificationCenter];
|
||||
@@ -448,6 +451,12 @@ schedule_notification(const char *identifier, const char *title, const char *bod
|
||||
log_error("Failed to get current UNUserNotificationCenter object with error: %s (%s)",
|
||||
[[e name] UTF8String], [[e reason] UTF8String]);
|
||||
}
|
||||
return center;
|
||||
}
|
||||
|
||||
static void
|
||||
schedule_notification(const char *identifier, const char *title, const char *body, const char *subtitle) {
|
||||
UNUserNotificationCenter *center = get_notification_center_safely();
|
||||
if (!center) return;
|
||||
// Configure the notification's payload.
|
||||
UNMutableNotificationContent* content = [[UNMutableNotificationContent alloc] init];
|
||||
@@ -509,13 +518,7 @@ cocoa_send_notification(PyObject *self UNUSED, PyObject *args) {
|
||||
char *identifier = NULL, *title = NULL, *body = NULL, *subtitle = NULL;
|
||||
if (!PyArg_ParseTuple(args, "zsz|z", &identifier, &title, &body, &subtitle)) return NULL;
|
||||
|
||||
UNUserNotificationCenter *center = nil;
|
||||
@try {
|
||||
center = [UNUserNotificationCenter currentNotificationCenter];
|
||||
} @catch (NSException *e) {
|
||||
log_error("Failed to get current UNUserNotificationCenter object with error: %s (%s)",
|
||||
[[e name] UTF8String], [[e reason] UTF8String]);
|
||||
}
|
||||
UNUserNotificationCenter *center = get_notification_center_safely();
|
||||
if (!center) Py_RETURN_NONE;
|
||||
if (!center.delegate) center.delegate = [[NotificationDelegate alloc] init];
|
||||
queue_notification(identifier, title, body, subtitle);
|
||||
|
||||
@@ -22,7 +22,7 @@ class Version(NamedTuple):
|
||||
|
||||
appname: str = 'kitty'
|
||||
kitty_face = '🐱'
|
||||
version: Version = Version(0, 34, 0)
|
||||
version: Version = Version(0, 34, 1)
|
||||
str_version: str = '.'.join(map(str, version))
|
||||
_plat = sys.platform.lower()
|
||||
is_macos: bool = 'darwin' in _plat
|
||||
|
||||
@@ -147,8 +147,6 @@ pyspacing(int val) {
|
||||
#undef S
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
pyindex(long x) { return PyLong_FromLong(x & 0xffff); }
|
||||
|
||||
static PyObject*
|
||||
pattern_as_dict(FcPattern *pat) {
|
||||
@@ -192,7 +190,7 @@ pattern_as_dict(FcPattern *pat) {
|
||||
I(FC_WIDTH, width)
|
||||
I(FC_SLANT, slant);
|
||||
I(FC_HINT_STYLE, hint_style);
|
||||
G(int, FcPatternGetInteger, FC_INDEX, pyindex, index);
|
||||
I(FC_INDEX, index);
|
||||
I(FC_RGBA, subpixel);
|
||||
I(FC_LCD_FILTER, lcdfilter);
|
||||
B(FC_HINTING, hinting);
|
||||
@@ -313,7 +311,6 @@ _native_fc_match(FcPattern *pat, FontConfigFace *ans) {
|
||||
#undef g
|
||||
ans->path = strdup((char*)out);
|
||||
if (!ans->path) { PyErr_NoMemory(); goto end; }
|
||||
ans->index &= 0xffff;
|
||||
ok = true;
|
||||
end:
|
||||
if (match != NULL) FcPatternDestroy(match);
|
||||
@@ -406,7 +403,7 @@ specialize_font_descriptor(PyObject *base_descriptor, FONTS_DATA_HANDLE fg) {
|
||||
if (pat == NULL) return PyErr_NoMemory();
|
||||
long face_idx = MAX(0, PyLong_AsLong(idx));
|
||||
AP(FcPatternAddString, FC_FILE, (const FcChar8*)PyUnicode_AsUTF8(p), "path");
|
||||
AP(FcPatternAddInteger, FC_INDEX, face_idx & 0xffff, "index");
|
||||
AP(FcPatternAddInteger, FC_INDEX, face_idx, "index");
|
||||
AP(FcPatternAddDouble, FC_SIZE, fg->font_sz_in_pts, "size");
|
||||
AP(FcPatternAddDouble, FC_DPI, (fg->logical_dpi_x + fg->logical_dpi_y) / 2.0, "dpi");
|
||||
ans = _fc_match(pat);
|
||||
|
||||
@@ -144,7 +144,7 @@ def cross(buf: BufType, width: int, height: int, a: int = 1, b: int = 1, c: int
|
||||
|
||||
|
||||
def downsample(src: BufType, dest: BufType, dest_width: int, dest_height: int, factor: int = 4) -> None:
|
||||
src_width = 4 * dest_width
|
||||
src_width = factor * dest_width
|
||||
|
||||
def average_intensity_in_src(dest_x: int, dest_y: int) -> int:
|
||||
src_y = dest_y * factor
|
||||
|
||||
@@ -19,13 +19,23 @@
|
||||
|
||||
#include FT_BITMAP_H
|
||||
#include FT_TRUETYPE_TABLES_H
|
||||
|
||||
typedef union FaceIndex {
|
||||
struct {
|
||||
FT_Long ttc_index : 16;
|
||||
FT_Long variation_index : 16;
|
||||
};
|
||||
FT_Long val;
|
||||
} FaceIndex;
|
||||
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
|
||||
FT_Face face;
|
||||
unsigned int units_per_EM;
|
||||
int ascender, descender, height, max_advance_width, max_advance_height, underline_position, underline_thickness, strikethrough_position, strikethrough_thickness;
|
||||
int hinting, hintstyle, index;
|
||||
int hinting, hintstyle;
|
||||
FaceIndex instance;
|
||||
bool is_scalable, has_color;
|
||||
float size_in_pts;
|
||||
FT_F26Dot6 char_width, char_height;
|
||||
@@ -205,7 +215,7 @@ init_ft_face(Face *self, PyObject *path, int hinting, int hintstyle, FONTS_DATA_
|
||||
|
||||
self->path = path;
|
||||
Py_INCREF(self->path);
|
||||
self->index = self->face->face_index & 0xFFFF;
|
||||
self->instance.val = self->face->face_index;
|
||||
self->space_glyph_id = glyph_id_for_codepoint((PyObject*)self, ' ');
|
||||
return true;
|
||||
}
|
||||
@@ -225,7 +235,7 @@ face_equals_descriptor(PyObject *face_, PyObject *descriptor) {
|
||||
if (!t) return false;
|
||||
if (PyObject_RichCompareBool(face->path, t, Py_EQ) != 1) return false;
|
||||
t = PyDict_GetItemString(descriptor, "index");
|
||||
if (t && PyLong_AsLong(t) != face->index) return false;
|
||||
if (t && PyLong_AsLong(t) != face->instance.val) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -288,10 +298,10 @@ static PyObject *
|
||||
repr(Face *self) {
|
||||
const char *ps_name = FT_Get_Postscript_Name(self->face);
|
||||
return PyUnicode_FromFormat(
|
||||
"Face(family=%s, style=%s, ps_name=%s, path=%S, index=%d, is_scalable=%S, has_color=%S, ascender=%i, descender=%i, height=%i, underline_position=%i, underline_thickness=%i, strikethrough_position=%i, strikethrough_thickness=%i)",
|
||||
"Face(family=%s, style=%s, ps_name=%s, path=%S, ttc_index=%d, variation_index=0x%x is_scalable=%S, has_color=%S, ascender=%i, descender=%i, height=%i, underline_position=%i, underline_thickness=%i, strikethrough_position=%i, strikethrough_thickness=%i)",
|
||||
self->face->family_name ? self->face->family_name : "", self->face->style_name ? self->face->style_name : "",
|
||||
ps_name ? ps_name: "",
|
||||
self->path, self->index, self->is_scalable ? Py_True : Py_False, self->has_color ? Py_True : Py_False,
|
||||
self->path, self->instance.ttc_index, self->instance.variation_index, self->is_scalable ? Py_True : Py_False, self->has_color ? Py_True : Py_False,
|
||||
self->ascender, self->descender, self->height, self->underline_position, self->underline_thickness, self->strikethrough_position, self->strikethrough_thickness
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user