diff --git a/src/newgdi/Makefile.am b/src/newgdi/Makefile.am index 63130143..23902c43 100644 --- a/src/newgdi/Makefile.am +++ b/src/newgdi/Makefile.am @@ -22,7 +22,7 @@ SRC_FILES = gdi.c attr.c clip.c map.c coor.c rect.c \ layoutinfo.c endif -HDR_FILES = drawtext.h mi.h midc.h mistruct.h miwideline.h \ +HDR_FILES = glyph.h drawtext.h mi.h midc.h mistruct.h miwideline.h \ pixel_ops.h mifillarc.h mispans.h polygon.h mifpoly.h \ textrunsinfo.h layoutinfo.h diff --git a/src/newgdi/drawtext.h b/src/newgdi/drawtext.h index 5e4fbf56..74a2de43 100644 --- a/src/newgdi/drawtext.h +++ b/src/newgdi/drawtext.h @@ -1,33 +1,33 @@ /* - * This file is part of MiniGUI, a mature cross-platform windowing + * This file is part of MiniGUI, a mature cross-platform windowing * and Graphics User Interface (GUI) support system for embedded systems * and smart IoT devices. - * + * * Copyright (C) 2002~2018, Beijing FMSoft Technologies Co., Ltd. * Copyright (C) 1998~2002, WEI Yongming - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . - * + * * Or, - * + * * As this program is a library, any link to this program must follow * GNU General Public License version 3 (GPLv3). If you cannot accept * GPLv3, you need to be licensed from FMSoft. - * + * * If you have got a commercial license of this program, please use it * under the terms and conditions of the commercial license. - * + * * For more information about the commercial license, please refer to * . */ @@ -38,6 +38,8 @@ #ifndef GUI_GDI_DRAWTEXT_H #define GUI_GDI_DRAWTEXT_H +#include "glyph.h" + #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ @@ -48,23 +50,13 @@ void _gdi_get_point_at_parallel(int x1, int y1, int x2, int y2, \ void _gdi_get_baseline_point (PDC pdc, int* x, int* y); -void _gdi_get_glyph_box_vertices (int x1, int y1, int x2, int y2, +void _gdi_get_glyph_box_vertices (int x1, int y1, int x2, int y2, POINT* pts, PDC pdc); void _gdi_start_new_line (PDC pdc); int _gdi_get_italic_added_width (LOGFONT* logfont); -typedef struct _BBOX -{ - int x, y; - int w, h; -} BBOX; - -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); - static inline int _gdi_get_glyph_advance (PDC pdc, Glyph32 glyph_value, BOOL direction, int x, int y, int* adv_x, int* adv_y, BBOX* bbox) { @@ -79,38 +71,38 @@ static inline int _gdi_get_glyph_advance (PDC pdc, Glyph32 glyph_value, int _gdi_draw_one_glyph (PDC pdc, Glyph32 glyph_value, BOOL direction, int x, int y, int* adv_x, int* adv_y); -int _gdi_get_null_glyph_advance (PDC pdc, int advance, BOOL direction, +int _gdi_get_null_glyph_advance (PDC pdc, int advance, BOOL direction, int x, int y, int* adv_x, int* adv_y); int _gdi_draw_null_glyph (PDC pdc, int advance, BOOL direction, int x, int y, int* adv_x, int* adv_y); -void _gdi_calc_glyphs_size_from_two_points (PDC pdc, int x0, int y0, +void _gdi_calc_glyphs_size_from_two_points (PDC pdc, int x0, int y0, int x1, int y1, SIZE* size); -typedef BOOL (*CB_ONE_GLYPH) (void* context, Glyph32 glyph_value, +typedef BOOL (*CB_ONE_GLYPH) (void* context, Glyph32 glyph_value, unsigned int char_type); -int _gdi_output_visual_achars(PDC pdc, Achar32* visual_achars, int nr_achars, +int _gdi_output_visual_achars(PDC pdc, Achar32* visual_achars, int nr_achars, BOOL direction, CB_ONE_GLYPH cb_one_glyph, void* context); -int _gdi_reorder_text (PDC pdc, const unsigned char* text, int text_len, +int _gdi_reorder_text (PDC pdc, const unsigned char* text, int text_len, BOOL ta_state, CB_ONE_GLYPH cb_one_glyph, void* context); -int _gdi_reorder_text_break (PDC pdc, const unsigned char* text, int text_len, +int _gdi_reorder_text_break (PDC pdc, const unsigned char* text, int text_len, BOOL direction, CB_ONE_GLYPH cb_one_glyph, void* context); -int _gdi_text_out (PDC pdc, int x, int y, +int _gdi_text_out (PDC pdc, int x, int y, const unsigned char* text, int len, POINT* cur_pos); -int _gdi_tabbed_text_out (PDC pdc, int x, int y, +int _gdi_tabbed_text_out (PDC pdc, int x, int y, const unsigned char* text, int len, int tab_width, BOOL only_extent, POINT* cur_pos, SIZE* size); -int _gdi_get_text_extent (PDC pdc, const unsigned char* text, int len, +int _gdi_get_text_extent (PDC pdc, const unsigned char* text, int len, SIZE* size); -int _gdi_get_drawtext_extent (PDC pdc, const unsigned char* text, int len, +int _gdi_get_drawtext_extent (PDC pdc, const unsigned char* text, int len, void* content, SIZE* size); BOOL InitTextBitmapBuffer (void); @@ -124,7 +116,7 @@ typedef struct _DRAWTEXTEX2_CTXT int tab_width; int line_height; - int x, y; + int x, y; int advance; int nFormat; diff --git a/src/newgdi/glyph.c b/src/newgdi/glyph.c index 402bd035..4e5687dd 100644 --- a/src/newgdi/glyph.c +++ b/src/newgdi/glyph.c @@ -2201,6 +2201,39 @@ void _gdi_get_baseline_point (PDC pdc, int* x, int* y) } } +int _font_get_glyph_log_width(LOGFONT* logfont, Glyph32 gv) +{ + int width, bold = 0; + int glyph_bmptype; + DEVFONT* devfont = SELECT_DEVFONT_BY_GLYPH(logfont, gv); + + gv = REAL_GLYPH(gv); + width = devfont->font_ops->get_glyph_advance(logfont, devfont, gv, + NULL, NULL); + + glyph_bmptype = devfont->font_ops->get_glyph_bmptype (logfont, devfont) + & DEVFONTGLYPHTYPE_MASK_BMPTYPE; + + // VincentWei: only use auto bold when the weight of devfont does not + // match the weight of logfont. + if (((int)(logfont->style & FS_WEIGHT_MASK) - + (int)(devfont->style & FS_WEIGHT_MASK)) > FS_WEIGHT_AUTOBOLD + && (glyph_bmptype == DEVFONTGLYPHTYPE_MONOBMP)) { + bold = GET_DEVFONT_SCALE (logfont, devfont); + } + + width += bold; + + if (glyph_bmptype == DEVFONTGLYPHTYPE_MONOBMP) { + if ((logfont->style & FS_RENDER_MASK) == FS_RENDER_GREY || + (logfont->style & FS_DECORATE_OUTLINE)) { + width++; + } + } + + return width; +} + 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) diff --git a/src/newgdi/glyph.h b/src/newgdi/glyph.h new file mode 100644 index 00000000..8d5fcecc --- /dev/null +++ b/src/newgdi/glyph.h @@ -0,0 +1,61 @@ +/* + * This file is part of MiniGUI, a mature cross-platform windowing + * and Graphics User Interface (GUI) support system for embedded systems + * and smart IoT devices. + * + * Copyright (C) 2002~2018, Beijing FMSoft Technologies Co., Ltd. + * Copyright (C) 1998~2002, WEI Yongming + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Or, + * + * As this program is a library, any link to this program must follow + * GNU General Public License version 3 (GPLv3). If you cannot accept + * GPLv3, you need to be licensed from FMSoft. + * + * If you have got a commercial license of this program, please use it + * under the terms and conditions of the commercial license. + * + * For more information about the commercial license, please refer to + * . + */ +/* +** glyph.h: The common glyph related routines. +*/ + +#ifndef _MG_NEWGDI_GLYPH_H + #define _MG_NEWGDI_GLYPH_H + +typedef struct _BBOX { + int x, y; + int w, h; +} BBOX; + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +int _font_get_glyph_log_width (LOGFONT* logfont, Glyph32 gv); + +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); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif // _MG_NEWGDI_GLYPH_H + diff --git a/src/newgdi/shape-glyphs-basic.c b/src/newgdi/shape-glyphs-basic.c index e1387d92..3fabd7e5 100644 --- a/src/newgdi/shape-glyphs-basic.c +++ b/src/newgdi/shape-glyphs-basic.c @@ -56,6 +56,7 @@ #include "devfont.h" #include "unicode-ops.h" #include "layoutinfo.h" +#include "glyph.h" /* Local array size, used for stack-based local arrays */ @@ -66,13 +67,13 @@ #endif -static void reverse_ucs (Uchar32* ucs, int len) +static void reverse_shaped_glyphs(SHAPEDGLYPH* glyphs, int len) { int i; for (i = 0; i < len / 2; i++) { - Uchar32 tmp = ucs[i]; - ucs[i] = ucs[len - 1 - i]; - ucs[len - 1 - i] = tmp; + SHAPEDGLYPH tmp = glyphs[i]; + glyphs[i] = glyphs[len - 1 - i]; + glyphs[len - 1 - i] = tmp; } } @@ -85,8 +86,8 @@ static BOOL shape_text_run(SEINSTANCE* inst, const Uchar32* logical_ucs = info->ucs + run->idx; int nr_ucs = run->len; - Uchar32 local_visual_ucs[LOCAL_ARRAY_SIZE]; - Uchar32* visual_ucs = NULL; + Uchar32 local_shaped_ucs[LOCAL_ARRAY_SIZE]; + Uchar32* shaped_ucs = NULL; BidiArabicProp local_ar_props[LOCAL_ARRAY_SIZE]; BidiArabicProp *ar_props = NULL; @@ -98,15 +99,15 @@ static BOOL shape_text_run(SEINSTANCE* inst, BidiLevel* els = NULL; if (nr_ucs < LOCAL_ARRAY_SIZE) - visual_ucs = local_visual_ucs; + shaped_ucs = local_shaped_ucs; else - visual_ucs = malloc(nr_ucs * sizeof(Uchar32)); + shaped_ucs = malloc(nr_ucs * sizeof(Uchar32)); - if (!visual_ucs) + if (!shaped_ucs) goto out; /* TODO: compose logical character here */ - memcpy(visual_ucs, logical_ucs, sizeof(Uchar32) * nr_ucs); + memcpy(shaped_ucs, logical_ucs, sizeof(Uchar32) * nr_ucs); if (nr_ucs < LOCAL_ARRAY_SIZE) els = local_els; @@ -144,7 +145,7 @@ static BOOL shape_text_run(SEINSTANCE* inst, UBidiJoinArabic(bidi_ts, els, nr_ucs, ar_props); UBidiShape(BIDI_FLAG_SHAPE_MIRRORING | BIDI_FLAG_SHAPE_ARAB_PRES | BIDI_FLAG_SHAPE_ARAB_LIGA, - els, nr_ucs, ar_props, visual_ucs); + els, nr_ucs, ar_props, shaped_ucs); if (bidi_ts && bidi_ts != local_bidi_ts) { free (bidi_ts); @@ -152,7 +153,7 @@ static BOOL shape_text_run(SEINSTANCE* inst, } } else if (BIDI_LEVEL_IS_RTL(run->el)) { - UBidiShapeMirroring(els, nr_ucs, visual_ucs); + UBidiShapeMirroring(els, nr_ucs, shaped_ucs); } if (els && els != local_els) { @@ -160,16 +161,16 @@ static BOOL shape_text_run(SEINSTANCE* inst, els = NULL; } - // reorder visual chars - if (BIDI_LEVEL_IS_RTL(run->el)) { - reverse_ucs(visual_ucs, nr_ucs); - } - // generate the glyphs gs->glyphs = malloc(sizeof(SHAPEDGLYPH) * nr_ucs); - gs->log_clusters = malloc(sizeof(int) * nr_ucs); - if (gs->glyphs == NULL || gs->log_clusters == NULL) + if (gs->glyphs == NULL) { goto out; + } + gs->log_clusters = malloc(sizeof(int) * nr_ucs); + if (gs->log_clusters == NULL) { + free(gs->glyphs); + goto out; + } j = 0; for (i = 0; i < nr_ucs; i++) { @@ -179,17 +180,33 @@ static BOOL shape_text_run(SEINSTANCE* inst, if (ar_props) { BidiArabicProp ar_prop = ar_props[i]; if (ar_prop & BIDI_MASK_LIGATURED) { + if (j > 0) { + gs->glyphs[j-1].is_cluster_start = 1; + } + else { + _WRN_PRINTF("ligatured at the first glyph?\n"); + } } else { - gv = GetGlyphValue(run->lf, UCHAR2ACHAR(visual_ucs[i])); + gv = GetGlyphValue(run->lf, UCHAR2ACHAR(shaped_ucs[i])); gs->glyphs[j].gv = gv; - j++; + gs->glyphs[j].is_cluster_start = 0; if (UCharIsArabicVowel(logical_ucs[i])) { // adjust offset + gs->glyphs[j].x_off = 0; + gs->glyphs[j].y_off -= run->lf->ascent; + 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); } + + gs->log_clusters[j] = i; + j++; } } } @@ -200,11 +217,16 @@ static BOOL shape_text_run(SEINSTANCE* inst, ar_props = NULL; } + // reorder glyphs + if (BIDI_LEVEL_IS_RTL(run->el)) { + reverse_shaped_glyphs(gs->glyphs, gs->nr_glyphs); + } + ok = TRUE; out: - if (visual_ucs && visual_ucs != local_visual_ucs) - free (visual_ucs); + if (shaped_ucs && shaped_ucs != local_shaped_ucs) + free (shaped_ucs); if (els && els != local_els) free (els);