Skip to content

Commit d30e9f7

Browse files
committed
feat(pandagl): calculate baseline position based on Ascender and BBox
1 parent 26641aa commit d30e9f7

File tree

7 files changed

+737
-776
lines changed

7 files changed

+737
-776
lines changed

lib/pandagl/include/pandagl/font.h

+5-5
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,12 @@ typedef struct pd_font_bitmap_t {
4141
int width; /**< 位图宽度 */
4242
int rows; /**< 位图行数 */
4343
int pitch;
44-
unsigned char *buffer; /**< 字体位图数据 */
45-
short num_grays;
46-
char pixel_mode;
44+
uint8_t *buffer; /**< 字体位图数据 */
4745
struct {
48-
int x, y;
49-
} advance;
46+
int hori_advance, vert_advance;
47+
int bbox_width, bbox_height;
48+
int ascender;
49+
} metrics;
5050
} pd_font_bitmap_t;
5151

5252
typedef struct font_engine_t font_engine_t;

lib/pandagl/include/pandagl/text.h

-1
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,6 @@ typedef enum pd_text_eol_t {
6868
typedef struct pd_text_line_t {
6969
int width; /**< 宽度 */
7070
int height; /**< 高度 */
71-
int text_height; /**< 当前行中最大字体的高度 */
7271
int length; /**< 该行文本长度 */
7372
pd_char_t **string; /**< 该行文本的数据 */
7473
pd_text_eol_t eol; /**< 行尾结束类型 */

lib/pandagl/src/font/freetype.c

+8-4
Original file line numberDiff line numberDiff line change
@@ -107,13 +107,17 @@ static size_t convert_glyph(pd_font_bitmap_t *bmp, FT_GlyphSlot slot, int mode)
107107
* 此情况的处理。
108108
* */
109109
bmp->top = bitmap_glyph->top;
110-
bmp->left = slot->metrics.horiBearingX >> 6;
110+
bmp->left = bitmap_glyph->left;
111111
bmp->rows = bitmap_glyph->bitmap.rows;
112112
bmp->width = bitmap_glyph->bitmap.width;
113-
bmp->advance.x = slot->metrics.horiAdvance >> 6; /* 水平跨距 */
114-
bmp->advance.y = slot->metrics.vertAdvance >> 6; /* 垂直跨距 */
113+
bmp->pitch = bmp->width * sizeof(uint8_t);
114+
bmp->metrics.ascender = slot->face->size->metrics.ascender >> 6;
115+
bmp->metrics.bbox_width = slot->face->size->metrics.max_advance >> 6;
116+
bmp->metrics.bbox_height = slot->face->size->metrics.height >> 6;
117+
bmp->metrics.hori_advance = slot->metrics.horiAdvance >> 6; /* 水平跨距 */
118+
bmp->metrics.vert_advance = slot->metrics.vertAdvance >> 6; /* 垂直跨距 */
115119
/* 分配内存,用于保存字体位图 */
116-
size = bmp->rows * bmp->width * sizeof(uint8_t);
120+
size = bmp->rows * bmp->pitch;
117121
bmp->buffer = (uint8_t *)malloc(size);
118122
if (!bmp->buffer) {
119123
FT_Done_Glyph(glyph);

lib/pandagl/src/font/inconsolata.c

+682-673
Large diffs are not rendered by default.

lib/pandagl/src/text/text.c

+40-92
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,22 @@
11
/*
22
* lib/pandagl/src/text/text.c
33
*
4-
* Copyright (c) 2023, Liu Chao <i@lc-soft.io> All rights reserved.
4+
* Copyright (c) 2018-2023, Liu Chao <i@lc-soft.io> All rights reserved.
55
*
66
* SPDX-License-Identifier: MIT
77
*
88
* This file is part of LCUI, distributed under the MIT License found in the
99
* LICENSE.TXT file in the root directory of this source tree.
1010
*/
1111

12-
/*
13-
* textlayer.c -- text layout and rendering module.
14-
*
15-
* copyright (c) 2018, liu chao <lc-soft@live.cn> all rights reserved.
16-
*
17-
* redistribution and use in source and binary forms, with or without
18-
* modification, are permitted provided that the following conditions are met:
19-
*
20-
* * redistributions of source code must retain the above copyright notice,
21-
* this list of conditions and the following disclaimer.
22-
* * redistributions in binary form must reproduce the above copyright
23-
* notice, this list of conditions and the following disclaimer in the
24-
* documentation and/or other materials provided with the distribution.
25-
* * neither the name of lcui nor the names of its contributors may be used
26-
* to endorse or promote products derived from this software without
27-
* specific prior written permission.
28-
*
29-
* this software is provided by the copyright holders and contributors "as is"
30-
* and any express or implied warranties, including, but not limited to, the
31-
* implied warranties of merchantability and fitness for a particular purpose
32-
* are disclaimed. in no event shall the copyright owner or contributors be
33-
* liable for any direct, indirect, incidental, special, exemplary, or
34-
* consequential damages (including, but not limited to, procurement of
35-
* substitute goods or services; loss of use, data, or profits; or business
36-
* interruption) however caused and on any theory of liability, whether in
37-
* contract, strict liability, or tort (including negligence or otherwise)
38-
* arising in any way out of the use of this software, even if advised of the
39-
* possibility of such damage.
40-
*/
41-
4212
#include <stdlib.h>
4313
#include <wctype.h>
4414
#include <pandagl.h>
15+
#include <math.h>
4516

4617
typedef enum { PD_TEXT_ACTION_INSERT, PD_TEXT_ACTION_APPEND } pd_text_action_t;
4718

48-
#define get_default_line_height(h) y_iround(h * 1.42857143)
19+
#define DEFAULT_LINE_HEIGHT 1.42857143
4920
#define isalpha(ch) (ch >= 'a' && ch <= 'z') || (ch >= 'a' && ch <= 'z')
5021

5122
static void pd_text_line_init(pd_text_line_t *line)
@@ -55,7 +26,6 @@ static void pd_text_line_init(pd_text_line_t *line)
5526
line->length = 0;
5627
line->string = NULL;
5728
line->eol = PD_TEXT_EOL_NONE;
58-
line->text_height = 0;
5929
}
6030

6131
static void pd_text_line_destroy(pd_text_line_t *line)
@@ -69,7 +39,6 @@ static void pd_text_line_destroy(pd_text_line_t *line)
6939
line->width = 0;
7040
line->height = 0;
7141
line->length = 0;
72-
line->text_height = 0;
7342
if (line->string) {
7443
free(line->string);
7544
}
@@ -134,24 +103,24 @@ PD_INLINE pd_text_line_t *pd_text_get_line(pd_text_t *text, int line_num)
134103
static void pd_text_update_line_size(pd_text_t *text, pd_text_line_t *line)
135104
{
136105
int i;
137-
pd_char_t *txtchar;
106+
int text_height = text->default_style.pixel_size;
107+
pd_char_t *ch;
138108

139109
line->width = 0;
140-
line->text_height = text->default_style.pixel_size;
141110
for (i = 0; i < line->length; ++i) {
142-
txtchar = line->string[i];
143-
if (!txtchar->bitmap) {
111+
ch = line->string[i];
112+
if (!ch->bitmap) {
144113
continue;
145114
}
146-
line->width += txtchar->bitmap->advance.x;
147-
if (line->text_height < txtchar->bitmap->advance.y) {
148-
line->text_height = txtchar->bitmap->advance.y;
115+
line->width += ch->bitmap->metrics.hori_advance;
116+
if (text_height < ch->bitmap->metrics.vert_advance) {
117+
text_height = ch->bitmap->metrics.vert_advance;
149118
}
150119
}
151120
if (text->line_height > 0) {
152121
line->height = text->line_height;
153122
} else {
154-
line->height = get_default_line_height(line->text_height);
123+
line->height = (int)round(text_height * DEFAULT_LINE_HEIGHT);
155124
}
156125
}
157126

@@ -386,14 +355,16 @@ static int pd_text_get_line_rect(pd_text_t *text, int line_num, int start_col,
386355
if (!line->string[i]->bitmap) {
387356
continue;
388357
}
389-
rect->x += line->string[i]->bitmap->advance.x;
358+
rect->x +=
359+
line->string[i]->bitmap->metrics.hori_advance;
390360
}
391361
rect->width = 0;
392362
for (i = start_col; i <= end_col && i < line->length; ++i) {
393363
if (!line->string[i]->bitmap) {
394364
continue;
395365
}
396-
rect->width += line->string[i]->bitmap->advance.x;
366+
rect->width +=
367+
line->string[i]->bitmap->metrics.hori_advance;
397368
}
398369
}
399370
if (rect->width <= 0 || rect->height <= 0) {
@@ -494,9 +465,10 @@ int pd_text_set_insert_pixel_position(pd_text_t *text, int x, int y)
494465
if (!txtchar->bitmap) {
495466
continue;
496467
}
497-
pixel_pos += txtchar->bitmap->advance.x;
468+
pixel_pos += txtchar->bitmap->metrics.hori_advance;
498469
/* 如果在当前字中心点的前面 */
499-
if (x <= pixel_pos - txtchar->bitmap->advance.x / 2) {
470+
if (x <=
471+
pixel_pos - txtchar->bitmap->metrics.hori_advance / 2) {
500472
ins_x = i;
501473
break;
502474
}
@@ -531,7 +503,7 @@ int pd_text_get_char_pixel_position(pd_text_t *text, int line_num, int col,
531503
if (!txtchar || !txtchar->bitmap) {
532504
continue;
533505
}
534-
pixel_x += txtchar->bitmap->advance.x;
506+
pixel_x += txtchar->bitmap->metrics.hori_advance;
535507
}
536508
pixel_pos->x = pixel_x;
537509
pixel_pos->y = pixel_y;
@@ -607,7 +579,7 @@ static void pd_text_typeset_line(pd_text_t *text, int line_num)
607579
continue;
608580
}
609581
/* 累加行宽度 */
610-
line_width += txtchar->bitmap->advance.x;
582+
line_width += txtchar->bitmap->metrics.hori_advance;
611583
/* 如果是当前行的第一个字符,或者行宽度没有超过宽度限制 */
612584
if (!autowrap || col < 1 || line_width <= max_width) {
613585
if (isalpha(txtchar->code)) {
@@ -851,7 +823,7 @@ int pd_text_get_width(pd_text_t *text)
851823
!line->string[i]->bitmap->buffer) {
852824
continue;
853825
}
854-
w += line->string[i]->bitmap->advance.x;
826+
w += line->string[i]->bitmap->metrics.hori_advance;
855827
}
856828
if (w > max_w) {
857829
max_w = w;
@@ -1196,58 +1168,34 @@ static void pd_text_render_line(pd_text_t *text, pd_rect_t *area,
11961168
pd_canvas_t *graph, pd_pos_t layer_pos,
11971169
pd_text_line_t *line, int y)
11981170
{
1199-
pd_char_t *txtchar;
1200-
pd_pos_t ch_pos;
1201-
int baseline, col, x;
1171+
pd_char_t *ch;
1172+
pd_pos_t pen;
1173+
int col, x;
12021174

1203-
baseline = line->text_height * 4 / 5;
12041175
x = pd_text_get_line_start_x(text, line) + text->offset_x;
1205-
/* 确定从哪个文字开始绘制 */
1206-
for (col = 0; col < line->length; ++col) {
1207-
txtchar = line->string[col];
1208-
/* 忽略无字体位图的文字 */
1209-
if (!txtchar->bitmap) {
1176+
for (col = 0; col < line->length && x < area->x + area->width; ++col) {
1177+
ch = line->string[col];
1178+
if (!ch->bitmap) {
12101179
continue;
12111180
}
1212-
x += txtchar->bitmap->advance.x;
1213-
if (x > area->x) {
1214-
x -= txtchar->bitmap->advance.x;
1215-
break;
1216-
}
1217-
}
1218-
/* 若一整行的文本都不在可绘制区域内 */
1219-
if (col >= line->length) {
1220-
y += line->height;
1221-
return;
1222-
}
1223-
/* 遍历该行的文字 */
1224-
for (; col < line->length; ++col) {
1225-
txtchar = line->string[col];
1226-
if (!txtchar->bitmap) {
1181+
if (x + ch->bitmap->metrics.hori_advance < area->x) {
12271182
continue;
12281183
}
1229-
/* 计算字体位图的绘制坐标 */
1230-
ch_pos.x = layer_pos.x + x;
1231-
ch_pos.y = layer_pos.y + y;
1232-
if (txtchar->style && txtchar->style->has_back_color) {
1184+
pen.x = layer_pos.x + x;
1185+
pen.y = layer_pos.y + y;
1186+
if (ch->style && ch->style->has_back_color) {
12331187
pd_rect_t rect;
1234-
rect.x = ch_pos.x;
1235-
rect.y = ch_pos.y;
1188+
rect.x = pen.x;
1189+
rect.y = pen.y;
12361190
rect.height = line->height;
1237-
rect.width = txtchar->bitmap->advance.x;
1238-
pd_canvas_fill_rect(graph, txtchar->style->back_color,
1239-
rect);
1240-
}
1241-
ch_pos.x += txtchar->bitmap->left;
1242-
ch_pos.y += baseline;
1243-
ch_pos.y += (line->height - baseline) / 2;
1244-
ch_pos.y -= txtchar->bitmap->top;
1245-
pd_text_render_char(text, txtchar, graph, ch_pos);
1246-
x += txtchar->bitmap->advance.x;
1247-
/* 如果超过绘制区域则不继续绘制该行文本 */
1248-
if (x > area->x + area->width) {
1249-
break;
1191+
rect.width = ch->bitmap->metrics.hori_advance;
1192+
pd_canvas_fill_rect(graph, ch->style->back_color, rect);
12501193
}
1194+
pen.x += ch->bitmap->left;
1195+
pen.y += (line->height - ch->bitmap->metrics.bbox_height) /
1196+
2 + ch->bitmap->metrics.ascender - ch->bitmap->top;
1197+
pd_text_render_char(text, ch, graph, pen);
1198+
x += ch->bitmap->metrics.hori_advance;
12511199
}
12521200
}
12531201

tests/run_tests.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818

1919
int main(int argc, char **argv)
2020
{
21-
logger_set_level(LOGGER_LEVEL_ERROR);
21+
logger_set_level(LOGGER_LEVEL_ALL);
2222
ctest_describe("test settings", test_settings);
2323
ctest_describe("test thread", test_thread);
2424
ctest_describe("test font load", test_font_load);

xmake.lua

+1
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ target("lcui_tests")
6363
table.insert(argv, "valgrind")
6464
table.insert(argv, "--leak-check=full")
6565
table.insert(argv, "--error-exitcode=42")
66+
table.insert(argv, "--num-callers=20")
6667
table.insert(argv, target:targetfile())
6768
os.execv("sudo", argv)
6869
end

0 commit comments

Comments
 (0)