Improve rendering of fonts with descenders

- ags_drawString() returns a bounding box of the text so that callers
  can update the screen appropriately.
- Use total font height (not only ascent) for vertical positioning.
This commit is contained in:
kichikuou
2020-12-31 12:57:17 +09:00
parent 36a0e01dcd
commit ca41501f6d
9 changed files with 42 additions and 40 deletions
+4 -6
View File
@@ -383,16 +383,14 @@ void ags_delRegion(void *region) {
sdl_delRegion(region);
}
int ags_drawString(int x, int y, const char *src, int col) {
int w;
if (!check_param_xy(&x, &y)) return 0;
MyRectangle ags_drawString(int x, int y, const char *src, int col) {
if (!check_param_xy(&x, &y)) return (MyRectangle){};
char *utf8 = toUTF8(src);
w = sdl_drawString(x, y, utf8, col);
SDL_Rect r = sdl_drawString(x, y, utf8, col);
free(utf8);
return w;
return (MyRectangle){r.x, r.y, r.w, r.h};
}
agsurface_t *ags_drawStringToSurface(const char *str) {
+1 -1
View File
@@ -184,7 +184,7 @@ extern void ags_putRegion(void *region, int x, int y);
extern void ags_copyRegion(void *region, int sx, int sy, int w,int h,int dx,int dy);
extern void ags_delRegion(void *region);
extern int ags_drawString(int x, int y, const char *src, int col);
extern MyRectangle ags_drawString(int x, int y, const char *src, int col);
extern void ags_drawCg8bit(cgdata *cg, int x, int y);
extern void ags_drawCg16bit(cgdata *cg, int x, int y);
+15 -8
View File
@@ -119,6 +119,8 @@ static void sdl_drawAntiAlias_8bpp(int dstx, int dsty, SDL_Surface *src, unsigne
memset(cache, 0, 256);
for (int y = 0; y < src->h && dsty + y < sdl_dib->h; y++) {
if (dsty + y < 0)
continue;
BYTE *sp = (BYTE*)src->pixels + y * src->pitch;
BYTE *dp = (BYTE*)sdl_dib->pixels + (dsty + y) * sdl_dib->pitch + dstx;
for (int x = 0; x < src->w && dstx + x < sdl_dib->w; x++) {
@@ -149,15 +151,15 @@ static void sdl_drawAntiAlias_8bpp(int dstx, int dsty, SDL_Surface *src, unsigne
SDL_UnlockSurface(sdl_dib);
}
int font_draw_glyph(int x, int y, const char *str_utf8, int cl) {
SDL_Rect font_draw_glyph(int x, int y, const char *str_utf8, int cl) {
SDL_Surface *fs;
SDL_Rect r_src, r_dst;
SDL_Rect r_src, r_dst = {};
int w, h;
if (!*str_utf8)
return 0;
return r_dst;
if (!fontset)
return 0;
return r_dst;
if (this.antialiase_on) {
fs = TTF_RenderUTF8_Blended(fontset->id, str_utf8, sdl_col[cl]);
@@ -166,22 +168,27 @@ int font_draw_glyph(int x, int y, const char *str_utf8, int cl) {
}
if (!fs) {
WARNING("Text rendering failed: %s\n", TTF_GetError());
return 0;
return r_dst;
}
TTF_SizeUTF8(fontset->id, str_utf8, &w, &h);
y = max(0, y - (TTF_FontAscent(fontset->id) - fontset->size * 0.9));
// Center vertically to the box.
y -= (TTF_FontHeight(fontset->id) - fontset->size) / 2;
setRect(r_dst, x, y, w, h);
if (sdl_dib->format->BitsPerPixel == 8 && this.antialiase_on) {
sdl_drawAntiAlias_8bpp(x, y, fs, cl);
} else {
setRect(r_src, 0, 0, w, h);
setRect(r_dst, x, y, w, h);
SDL_BlitSurface(fs, &r_src, sdl_dib, &r_dst);
}
SDL_FreeSurface(fs);
return w;
if (r_dst.y < 0) {
r_dst.h += r_dst.y;
r_dst.y = 0;
}
return r_dst;
}
void font_init(void) {
+1 -1
View File
@@ -37,7 +37,7 @@ extern void font_set_antialias(boolean enable);
extern boolean font_get_antialias(void);
extern void font_select(int type, int size);
extern struct SDL_Surface *font_get_glyph(const char *str_utf8);
extern int font_draw_glyph(int x, int y, const char *str_utf8, int col);
extern SDL_Rect font_draw_glyph(int x, int y, const char *str_utf8, int col);
#ifdef __EMSCRIPTEN__
extern int load_mincho_font(void);
+14 -17
View File
@@ -111,7 +111,6 @@ void msg_setStringDecorationType(int type) {
}
void msg_putMessage(const char *m) {
int w;
MyRectangle adj;
if (nextLineIsAfterKaigyou) {
@@ -176,18 +175,21 @@ void msg_putMessage(const char *m) {
break;
}
w = ags_drawString(msgcur.x, msgcur.y, m, msg.MsgFontColor);
MyRectangle drawn = ags_drawString(msgcur.x, msgcur.y, m, msg.MsgFontColor);
msgcur.x += drawn.width;
drawn.x += adj.x;
drawn.y += adj.y;
drawn.width += adj.width;
drawn.height += adj.height;
if (nact->messagewait_enable && !nact->messagewait_cancelled && !msgskip_isSkipping()) {
int x;
for (x = 0; x < w + adj.width; x+=16) {
ags_updateArea(msgcur.x + adj.x + x, msgcur.y + adj.y,
16, msg.MsgFontSize + adj.height);
for (x = 0; x < drawn.width; x+=16) {
ags_updateArea(drawn.x + x, drawn.y, 16, drawn.height);
if (nact->messagewait_cancel) {
if (sys_getInputInfo()) {
nact->messagewait_cancelled = TRUE;
ags_updateArea(msgcur.x + adj.x, msgcur.y + adj.y,
w + adj.width, msg.MsgFontSize + adj.height);
ags_updateArea(drawn.x, drawn.y, drawn.width, drawn.height);
break;
}
sdl_sleep(nact->messagewait_time * 10);
@@ -195,10 +197,8 @@ void msg_putMessage(const char *m) {
nact->callback();
}
} else {
ags_updateArea(msgcur.x + adj.x, msgcur.y + adj.y,
w + adj.width, msg.MsgFontSize + adj.height);
ags_updateArea(drawn.x, drawn.y, drawn.width, drawn.height);
}
msgcur.x += w;
}
void msg_nextLine() {
@@ -327,18 +327,15 @@ void msg_getMessageLocation(MyPoint *loc) {
}
void msg_hitAnyKey() {
int w;
const char *prompt[CHARACTER_ENCODING_MAX + 1] = {
[SHIFT_JIS] = "\x81\xa5",
[UTF8] = "",
};
w = ags_drawString(msg.win->x + msg.win->width - msg.MsgFontSize,
msg.win->y + msg.win->height - msg.MsgFontSize,
prompt[nact->encoding], msg.HitAnyKeyMsgColor);
ags_updateArea(msg.win->x + msg.win->width - msg.MsgFontSize,
msg.win->y + msg.win->height - msg.MsgFontSize,
w, msg.MsgFontSize);
MyRectangle r = ags_drawString(msg.win->x + msg.win->width - msg.MsgFontSize,
msg.win->y + msg.win->height - msg.MsgFontSize,
prompt[nact->encoding], msg.HitAnyKeyMsgColor);
ags_updateArea(r.x, r.y, r.width, r.height);
}
static void drawLineFrame(Bcom_WindowInfo *i) {
+1 -1
View File
@@ -56,7 +56,7 @@ extern void sdl_setPalette(Palette256 *pal, int src, int cnt);
extern void sdl_drawRectangle(int x, int y, int w, int h, int cl);
extern void sdl_fillRectangle(int x, int y, int w, int h, unsigned long c);
extern void sdl_drawLine(int x1, int y1, int x2, int y2, unsigned long col);
extern int sdl_drawString(int x, int y, const char *str_utf8, unsigned long col);
extern SDL_Rect sdl_drawString(int x, int y, const char *str_utf8, unsigned long col);
extern void sdl_copyArea(int sx,int sy, int w, int h, int dx, int dy);
extern void sdl_drawTT(int x,int y,int w,int h,const char *bitmap,int ww, boolean antialiased);
extern void sdl_copyAreaSP(int sx, int sy, int w, int h, int dx, int dy, int sp);
+1 -1
View File
@@ -310,7 +310,7 @@ int sdl_nearest_color(int r, int g, int b) {
return col;
}
int sdl_drawString(int x, int y, const char *str_utf8, unsigned long col) {
SDL_Rect sdl_drawString(int x, int y, const char *str_utf8, unsigned long col) {
sdl_pal_check();
return font_draw_glyph(x, y, str_utf8, col);
}
+2 -2
View File
@@ -53,13 +53,13 @@ static void redraw() {
};
if (*input->text) {
int w = sdl_drawString(r.x, r.y, input->text, fgcolor);
int w = sdl_drawString(r.x, r.y, input->text, fgcolor).w;
r.x += w;
r.w -= w;
}
if (*input->composingText) {
int w = sdl_drawString(r.x, r.y, input->composingText, fgcolor);
int w = sdl_drawString(r.x, r.y, input->composingText, fgcolor).w;
ags_fillRectangle(r.x, r.y + r.h, w, 2, fgcolor); // underline
}
+3 -3
View File
@@ -276,7 +276,7 @@ static void init_selwindow() {
ags_setFont(FONT_GOTHIC, sel.MsgFontSize);
for (i = 0; i < regnum; i++) {
DEBUG_MESSAGE("%d:%s\n", i +1, elm[i]);
ags_drawString(r.x +2, r.y + i * (sel.MsgFontSize +2) +2, elm[i], sel.MsgFontColor);
ags_drawString(r.x +2, r.y + i * (sel.MsgFontSize +2) +1, elm[i], sel.MsgFontColor);
}
ags_updateArea(saveArea.x, saveArea.y, saveArea.width, saveArea.height);
@@ -364,7 +364,7 @@ static void encloseElement(int sw, int no) {
lineEncloseElement(r, sel.WinBackgroundColor, FALSE); break;
case 2:
ags_fillRectangle(r->x, r->y, r->width +2, r->height +2, sel.WinBackgroundColor);
ags_drawString(r->x +2, r->y +2, elm[no], sel.MsgFontColor);
ags_drawString(r->x +2, r->y +1, elm[no], sel.MsgFontColor);
ags_updateArea(r->x, r->y, r->width +2, r->height +2);
break;
default:
@@ -383,7 +383,7 @@ static void encloseElement(int sw, int no) {
lineEncloseElement(r, 255, FALSE); break;
case 2:
ags_fillRectangle(r->x, r->y, r->width +2, r->height +2, sel.MsgFontColor);
ags_drawString(r->x +2, r->y +2, elm[no], sel.WinBackgroundColor);
ags_drawString(r->x +2, r->y +1, elm[no], sel.WinBackgroundColor);
ags_updateArea(r->x, r->y, r->width +2, r->height +2);
break;
default: