You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于GTK+Cairo的文本渲染滚动性能优化求助

GTK+Cairo文本渲染性能优化问题
// gcc `pkg-config --cflags gtk+-3.0` main.c `pkg-config --libs gtk+-3.0 cairo`

#include <gtk/gtk.h>
#include <cairo.h>
#include <stdlib.h>
#include <string.h>

#define MAX_LINE_LENGTH 1024
#define LINE_SPACING 5
#define FONT_SIZE 20

typedef struct {
    char **lines;
    int line_count;
    int max_line_length;
} AppData;

static gboolean on_draw_event(GtkWidget *widget, cairo_t *cr, AppData *data) {
    cairo_select_font_face(cr, "Monospace", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
    cairo_set_font_size(cr, FONT_SIZE);
    cairo_set_source_rgb(cr, 0, 0, 0);

    for (int i = 0; i < data->line_count; i++) {
        cairo_move_to(cr, 0, FONT_SIZE + i * (FONT_SIZE + LINE_SPACING));
        cairo_show_text(cr, data->lines[i]);
    }

    return FALSE;
}

static void on_destroy(GtkWidget *widget, gpointer data) {
    gtk_main_quit();
}

int main(int argc, char *argv[]) {
    if (argc < 2) {
        g_printerr("Usage: %s <filename>\n", argv[0]);
        return EXIT_FAILURE;
    }

    gtk_init(&argc, &argv);

    FILE *file = fopen(argv[1], "r");
    if (!file) {
        g_printerr("Could not open file: %s\n", argv[1]);
        return EXIT_FAILURE;
    }

    AppData data;
    data.lines = NULL;
    data.line_count = 0;
    data.max_line_length = 0;

    char line[MAX_LINE_LENGTH];
    while (fgets(line, sizeof(line), file)) {
        data.lines = realloc(data.lines, sizeof(char *) * (data.line_count + 1));
        if (data.lines == NULL) {
            g_printerr("Memory allocation error.\n");
            fclose(file);
            return EXIT_FAILURE;
        }
        data.lines[data.line_count] = strdup(line);
        if (strlen(line) > data.max_line_length) {
            data.max_line_length = strlen(line);
        }
        data.line_count++;
    }
    fclose(file);

    GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_window_set_title(GTK_WINDOW(window), "Text Renderer");
    gtk_window_set_default_size(GTK_WINDOW(window), 400, 300);
    gtk_window_set_decorated(GTK_WINDOW(window), TRUE);
    g_signal_connect(window, "destroy", G_CALLBACK(on_destroy), NULL);

    GtkWidget *scrolled_window = gtk_scrolled_window_new(NULL, NULL);
    GtkWidget *drawing_area = gtk_drawing_area_new();

    int height = data.line_count * (FONT_SIZE + LINE_SPACING);
    int width = data.max_line_length * (FONT_SIZE / 2);

    gtk_widget_set_size_request(drawing_area, width, height);
    gtk_widget_set_margin_top(drawing_area, 0);
    gtk_widget_set_margin_bottom(drawing_area, 0);
    gtk_widget_set_margin_start(drawing_area, 0);
    gtk_widget_set_margin_end(drawing_area, 0);

    gtk_container_add(GTK_CONTAINER(scrolled_window), drawing_area);
    gtk_container_add(GTK_CONTAINER(window), scrolled_window);

    g_signal_connect(G_OBJECT(drawing_area), "draw", G_CALLBACK(on_draw_event), &data);

    gtk_widget_show_all(window);
    gtk_main();

    return EXIT_SUCCESS;
}

上述基于GTK+Cairo实现的文本渲染程序,在加载仅2M大小的文本文件时,滚动性能表现极差。

我知晓Gtk.TextView组件的存在,但由于项目需求(如开发带多光标功能的编辑器、终端模拟器,也了解VTE),加上出于学习目的,希望专注于优化渲染性能(推测渲染是性能瓶颈),而非文件读取性能。

目前想到两个优化思路:

  • 仅渲染可视区域附近的文本块,但不确定是否可行;
  • 改用OpenGL替代Cairo进行渲染,但认为提升效果有限。

测试用的随机文本文件生成命令:

dd if=/dev/urandom bs=1 count=2M | tr -dc '[:print:]\n' > random_text.txt

恳请各位提供优化建议。

内容的提问来源于stack exchange,提问作者xXxAirSnifferxXx

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 19:03:21