diff --git a/include/gdi.h b/include/gdi.h index cd184bbd..5f012b5d 100644 --- a/include/gdi.h +++ b/include/gdi.h @@ -13025,8 +13025,6 @@ MG_EXPORT BOOL GUIAPI GetLayoutLineSize(LAYOUTLINE* line, * * \return The number of lines laid out. * - * \sa CreateLayoutInfo, DestroyLayoutInfo, LayoutNextLine - * * \note The position coordinates of the first line are * with respect to the top-left corner of the output rectangle * if the writing mode is GRF_WRITING_MODE_HORIZONTAL_TB or @@ -13035,6 +13033,8 @@ MG_EXPORT BOOL GUIAPI GetLayoutLineSize(LAYOUTLINE* line, * the top-right corner if the writing mode is * GRF_WRITING_MODE_VERTICAL_RL. * + * \sa CreateLayoutInfo, DestroyLayoutInfo, LayoutNextLine + * * Since 3.4.0 */ MG_EXPORT int GUIAPI CalcLayoutBoundingRect(LAYOUTINFO* layout_info, @@ -13076,7 +13076,7 @@ MG_EXPORT BOOL DrawShapedGlyph(HDC hdc, /** * \fn DrawLayoutLine(HDC hdc, const LAYOUTLINE* line, - * int x, int y, RECT* bounding) + * int x, int y) * \brief Draw a laid out line at the specific position. * * This function draws a laied out line at the specified position. @@ -13095,12 +13095,20 @@ MG_EXPORT BOOL DrawShapedGlyph(HDC hdc, * * \return The number of glyphs drawn. * + * \note The position coordinates of the first line are + * with respect to the top-left corner of the output rectangle + * if the writing mode is GRF_WRITING_MODE_HORIZONTAL_TB or + * GRF_WRITING_MODE_VERTICAL_LR, the bottom-left corner if + * the writing mode is GRF_WRITING_MODE_HORIZONTAL_BT, + * the top-right corner if the writing mode is + * GRF_WRITING_MODE_VERTICAL_RL. + * * \sa CreateLayoutInfo, DestroyLayoutInfo, LayoutNextLine * * Since 3.4.0 */ MG_EXPORT int DrawLayoutLine(HDC hdc, const LAYOUTLINE* line, - int* x, int* y, RECT* bounding); + int x, int y); #ifdef _MGDEVEL_MODE typedef struct _TextRun TEXTRUN; diff --git a/src/font/devfont.c b/src/font/devfont.c index 77c3f556..86546b0a 100644 --- a/src/font/devfont.c +++ b/src/font/devfont.c @@ -993,7 +993,12 @@ DEVFONT* GUIAPI LoadDevFontFromFile(const char *devfont_name, void GUIAPI DestroyDynamicDevFont (DEVFONT** devfont) { - font_DelDevFont ((*devfont)->name); + char font_name [LEN_UNIDEVFONT_NAME + 1]; + + memset(font_name, 0, LEN_UNIDEVFONT_NAME + 1); + strncpy(font_name, (*devfont)->name, LEN_UNIDEVFONT_NAME); + + font_DelDevFont (font_name); *devfont = NULL; } diff --git a/src/newgdi/glyph-shaped.c b/src/newgdi/glyph-shaped.c index 413a1b40..5e6b2e55 100644 --- a/src/newgdi/glyph-shaped.c +++ b/src/newgdi/glyph-shaped.c @@ -56,6 +56,7 @@ #include "cursor.h" #include "drawtext.h" #include "glyph.h" +#include "layoutinfo.h" #ifdef _MGCHARSET_UNICODE @@ -71,12 +72,9 @@ BOOL DrawShapedGlyph(HDC hdc, Glyph32 gv, render_data->uc_index); if (glyph_pos->suppressed == 0 && glyph_pos->whitespace == 0) { - Uint32 old_ta; PLOGFONT old_lf = NULL; gal_pixel fg_pixel, bg_pixel; - old_ta = SetTextAlign(hdc, TA_LEFT | TA_TOP | TA_UPDATECP); - old_lf = SelectFont(hdc, render_data->logfont); fg_color = GetTextColorInTextRuns(render_data->truninfo, @@ -93,12 +91,11 @@ BOOL DrawShapedGlyph(HDC hdc, Glyph32 gv, SetBkMode(hdc, BM_TRANSPARENT); } - DrawGlyph(hdc, glyph_pos->x, glyph_pos->y, gv, NULL, NULL); + DrawGlyph(hdc, glyph_pos->x + glyph_pos->x_off, + glyph_pos->y + glyph_pos->y_off, gv, NULL, NULL); if (old_lf) SelectFont(hdc, old_lf); - - SetTextAlign(hdc, old_ta); } else if (glyph_pos->whitespace && bg_color) { // TODO: draw background for whitespace. @@ -107,10 +104,81 @@ BOOL DrawShapedGlyph(HDC hdc, Glyph32 gv, return TRUE; } -int DrawLayoutLine(HDC hdc, const LAYOUTLINE* line, - int* x, int* y, RECT* bounding) +int DrawLayoutLine(HDC hdc, const LAYOUTLINE* line, int x, int y) { - return 0; + int n, log_x = 0, log_y = 0; + struct list_head* i; + const TEXTRUNSINFO* truninfo; + const LAYOUTINFO* layout; + Uint32 old_ta; + PLOGFONT old_lf = NULL; + + if (line == NULL) + return 0; + + layout = line->layout; + truninfo = layout->truninfo; + + if ((layout->rf & GRF_WRITING_MODE_MASK) == + GRF_WRITING_MODE_HORIZONTAL_BT) + old_ta = SetTextAlign(hdc, TA_LEFT | TA_BOTTOM | TA_NOUPDATECP); + else if ((layout->rf & GRF_WRITING_MODE_MASK) == + GRF_WRITING_MODE_VERTICAL_RL) + old_ta = SetTextAlign(hdc, TA_RIGHT | TA_TOP | TA_NOUPDATECP); + else + old_ta = SetTextAlign(hdc, TA_LEFT | TA_TOP | TA_NOUPDATECP); + old_lf = GetCurFont(hdc); + + list_for_each(i, &line->gruns) { + GlyphRun* run = (GlyphRun*)i; + int j; + + SelectFont(hdc, run->lrun->lf); + for (j = 0; j < run->gstr->nr_glyphs; j++) { + int dev_x, dev_y; + + ShapedGlyph* gi = run->gstr->glyphs + j; + int log_index = run->lrun->si + run->gstr->log_clusters[j]; + RGBCOLOR bg_color, fg_color; + + // We might use an interator to optimize the color settings. + fg_color = GetTextColorInTextRuns(truninfo, log_index); + bg_color = GetBackgroundColorInTextRuns(truninfo, log_index); + SetTextColor(hdc, DWORD2Pixel(hdc, fg_color)); + if (bg_color) { + SetBkColor(hdc, DWORD2Pixel(hdc, bg_color)); + SetBkMode(hdc, BM_OPAQUE); + } + else { + SetBkMode(hdc, BM_TRANSPARENT); + } + + if (run->lrun->dir == GLYPH_RUN_DIR_TTB || + run->lrun->dir == GLYPH_RUN_DIR_BTT) { + dev_y = log_x + gi->x_off; + dev_x = log_y + gi->y_off; + } + else { + dev_x = log_x + gi->x_off; + dev_y = log_y + gi->y_off; + } + + if ((run->lrun->flags & LAYOUTRUN_FLAG_NO_SHAPING) && + gi->width > 0 && bg_color) { + // FIXME: draw background here + } + else { + DrawGlyph(hdc, x + dev_x, y + dev_y, gi->gv, NULL, NULL); + n++; + } + + log_x += gi->width; + } + } + + SelectFont(hdc, old_lf); + SetTextAlign(hdc, old_ta); + return n; } #if 0 diff --git a/src/newgdi/glyph.c b/src/newgdi/glyph.c index 47224eba..2aeea5f4 100644 --- a/src/newgdi/glyph.c +++ b/src/newgdi/glyph.c @@ -2275,7 +2275,7 @@ int _font_get_glyph_advance (LOGFONT* logfont, DEVFONT* devfont, REAL_GLYPH(glyph_value), &tmp_x, &tmp_y); if (!direction) { - if (bbox) bbox->x -= (bold + ch_extra + adv_len); + bbox_x -= (bold + ch_extra + adv_len); } if (direction) { diff --git a/src/newgdi/glyph.h b/src/newgdi/glyph.h index 8d5fcecc..8e8f7c94 100644 --- a/src/newgdi/glyph.h +++ b/src/newgdi/glyph.h @@ -53,6 +53,9 @@ int _font_get_glyph_advance (LOGFONT* logfont, DEVFONT* devfont, Glyph32 glyph_value, BOOL direction, int ch_extra, int x, int y, int* adv_x, int* adv_y, BBOX* bbox); +int _font_get_glyph_metrics(LOGFONT* logfont, + Glyph32 gv, int* adv_x, int* adv_y, BBOX* bbox); + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/src/newgdi/layout-utils.c b/src/newgdi/layout-utils.c index a2c5b647..c8f3dc6e 100644 --- a/src/newgdi/layout-utils.c +++ b/src/newgdi/layout-utils.c @@ -186,7 +186,8 @@ static void resolve_layout_run_dir(const LAYOUTINFO* layout, break; } - if (LAYOUT_GRAVITY_IS_VERTICAL(layout->grv_base)) + if (LAYOUT_GRAVITY_IS_VERTICAL(layout->grv_base) && + lrun->ort == GLYPH_ORIENT_UPRIGHT) lrun->flags |= LAYOUTRUN_FLAG_CENTERED_BASELINE; } diff --git a/src/newgdi/layoutinfo.c b/src/newgdi/layoutinfo.c index 54ce429d..dd9f7a23 100644 --- a/src/newgdi/layoutinfo.c +++ b/src/newgdi/layoutinfo.c @@ -1754,11 +1754,17 @@ static int traverse_line_glyphs(const LAYOUTINFO* layout, glyph_info = run->gstr->glyphs + j; - pos.x = line_adv; - pos.y = 0; - pos.x_off = glyph_info->x_off; - pos.y_off = glyph_info->y_off; - pos.advance = glyph_info->width; + if (run->lrun->dir == GLYPH_RUN_DIR_TTB || + run->lrun->dir == GLYPH_RUN_DIR_BTT) { + pos.x = glyph_info->x_off; + pos.y = line_adv + glyph_info->y_off; + pos.advance = glyph_info->height; + } + else { + pos.x = line_adv + glyph_info->x_off; + pos.y = glyph_info->y_off; + pos.advance = glyph_info->width; + } pos.suppressed = 0; pos.whitespace = 0; diff --git a/src/newgdi/shape-glyphs-basic.c b/src/newgdi/shape-glyphs-basic.c index 237ec6a0..a08c225a 100644 --- a/src/newgdi/shape-glyphs-basic.c +++ b/src/newgdi/shape-glyphs-basic.c @@ -188,10 +188,23 @@ static BOOL shape_layout_run(SEInstance* inst, gs->glyphs[j].width = 0; } else { - gs->glyphs[j].x_off = 0; - gs->glyphs[j].y_off = 0; - gs->glyphs[j].width - = _font_get_glyph_log_width(run->lf, gv); + if (run->flags & LAYOUTRUN_FLAG_CENTERED_BASELINE) { + BBOX bbox; + int width = _font_get_glyph_metrics(run->lf, gv, + NULL, NULL, &bbox); + + gs->glyphs[j].width = run->lf->size; + gs->glyphs[j].height = width; + gs->glyphs[j].x_off = (width - bbox.w) / 2; + gs->glyphs[j].y_off = 0; + } + else { + gs->glyphs[j].x_off = 0; + gs->glyphs[j].y_off = 0; + gs->glyphs[j].width + = _font_get_glyph_log_width(run->lf, gv); + gs->glyphs[j].height = run->lf->size; + } } gs->log_clusters[j] = i; @@ -203,16 +216,31 @@ static BOOL shape_layout_run(SEInstance* inst, gs->glyphs[j].gv = gv; gs->glyphs[j].is_cluster_start = 0; - gs->glyphs[j].x_off = 0; - gs->glyphs[j].y_off = 0; - gs->glyphs[j].width - = _font_get_glyph_log_width(run->lf, gv); + if (run->flags & LAYOUTRUN_FLAG_CENTERED_BASELINE) { + BBOX bbox; + int width = _font_get_glyph_metrics(run->lf, gv, + NULL, NULL, &bbox); + + gs->glyphs[j].width = run->lf->size; + gs->glyphs[j].height = width; + gs->glyphs[j].x_off = (width - bbox.w) / 2; + gs->glyphs[j].y_off = 0; + } + else { + gs->glyphs[j].x_off = 0; + gs->glyphs[j].y_off = 0; + gs->glyphs[j].width + = _font_get_glyph_log_width(run->lf, gv); + gs->glyphs[j].height = run->lf->size; + } gs->log_clusters[j] = i; j++; } + } + gs->nr_glyphs = j; if (ar_props && ar_props != local_ar_props) { diff --git a/src/newgdi/simple-glyph-renderer.c b/src/newgdi/simple-glyph-renderer.c index 1df57d95..dc8c2d62 100644 --- a/src/newgdi/simple-glyph-renderer.c +++ b/src/newgdi/simple-glyph-renderer.c @@ -143,7 +143,7 @@ static BOOL is_horizontal_only_script(Uchar32 uc) return TRUE; } -static int font_get_glyph_metrics(LOGFONT* logfont, +int _font_get_glyph_metrics(LOGFONT* logfont, Glyph32 gv, int* adv_x, int* adv_y, BBOX* bbox) { int bold = 0; @@ -151,7 +151,7 @@ static int font_get_glyph_metrics(LOGFONT* logfont, int tmp_y = 0; int bbox_x = 0, bbox_y = 0; int bbox_w = 0, bbox_h = 0; - int gbt; + int gbt, width;; DEVFONT* devfont = SELECT_DEVFONT_BY_GLYPH(logfont, gv); gbt = devfont->font_ops->get_glyph_bmptype (logfont, devfont) @@ -174,21 +174,22 @@ static int font_get_glyph_metrics(LOGFONT* logfont, bbox->h = bbox_h; } - devfont->font_ops->get_glyph_advance (logfont, devfont, REAL_GLYPH(gv), - &tmp_x, &tmp_y); + width = devfont->font_ops->get_glyph_advance (logfont, devfont, + REAL_GLYPH(gv), &tmp_x, &tmp_y); tmp_x += bold; if (gbt == DEVFONTGLYPHTYPE_MONOBMP) { if ((logfont->style & FS_RENDER_MASK) == FS_RENDER_GREY || (logfont->style & FS_DECORATE_OUTLINE)) { - tmp_x += 1; + tmp_x++; + width++; } } if (adv_x) *adv_x = tmp_x; if (adv_y) *adv_y = tmp_y; - return 0; + return width; } static void normalize_glyph_metrics(LOGFONT* logfont, @@ -909,7 +910,7 @@ static int get_glyph_extent_info(MYGLYPHARGS* args, Glyph32 gv, } } - font_get_glyph_metrics(logfont, gv, &adv_x, &adv_y, &bbox); + _font_get_glyph_metrics(logfont, gv, &adv_x, &adv_y, &bbox); normalize_glyph_metrics(logfont, args->rf, &bbox, &adv_x, &adv_y, &line_adv, &args->lw);