Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/gfxfont/src/text.c

    ra0aeb8f rf2d4a46  
    11/*
    2  * Copyright (c) 2021 Jiri Svoboda
     2 * Copyright (c) 2022 Jiri Svoboda
    33 * All rights reserved.
    44 *
     
    9797/** Print string using text characters in text mode.
    9898 *
    99  * @param font Font
    10099 * @param pos Position of top-left corner of text
    101  * @param color Text color
     100 * @param fmt Formatting
    102101 * @param str String
    103102 * @return EOK on success or an error code
    104103 */
    105 static errno_t gfx_puttext_textmode(gfx_font_t *font, gfx_coord2_t *pos,
    106     gfx_color_t *color, const char *str)
    107 {
    108         gfx_context_t *gc = font->typeface->gc;
     104static errno_t gfx_puttext_textmode(gfx_coord2_t *pos, gfx_text_fmt_t *fmt,
     105    const char *str)
     106{
     107        gfx_context_t *gc = fmt->font->typeface->gc;
    109108        gfx_bitmap_params_t params;
    110109        gfx_bitmap_t *bitmap;
    111110        gfx_bitmap_alloc_t alloc;
     111        gfx_coord_t width;
    112112        uint8_t attr;
    113113        pixelmap_t pmap;
    114114        gfx_coord_t x;
     115        gfx_coord_t rmargin;
    115116        pixel_t pixel;
    116117        char32_t c;
    117118        size_t off;
     119        bool ellipsis;
    118120        errno_t rc;
     121
     122        width = str_width(str);
     123        if (fmt->abbreviate && width > fmt->width) {
     124                ellipsis = true;
     125                width = fmt->width;
     126                if (width > 3)
     127                        rmargin = width - 3;
     128                else
     129                        rmargin = width;
     130        } else {
     131                ellipsis = false;
     132                rmargin = width;
     133        }
    119134
    120135        /*
     
    123138         */
    124139
    125         gfx_color_get_ega(color, &attr);
     140        gfx_color_get_ega(fmt->color, &attr);
    126141
    127142        gfx_bitmap_params_init(&params);
    128143        params.rect.p0.x = 0;
    129144        params.rect.p0.y = 0;
    130         params.rect.p1.x = str_width(str);
     145        params.rect.p1.x = width;
    131146        params.rect.p1.y = 1;
    132147
     
    151166
    152167        off = 0;
    153         for (x = 0; x < params.rect.p1.x; x++) {
     168        for (x = 0; x < rmargin; x++) {
    154169                c = str_decode(str, &off, STR_NO_LIMIT);
    155170                pixel = PIXEL(attr,
     
    160175        }
    161176
     177        if (ellipsis) {
     178                for (x = rmargin; x < params.rect.p1.x; x++) {
     179                        c = '.';
     180                        pixel = PIXEL(attr,
     181                            (c >> 16) & 0xff,
     182                            (c >> 8) & 0xff,
     183                            c & 0xff);
     184                        pixelmap_put_pixel(&pmap, x, 0, pixel);
     185                }
     186        }
     187
    162188        rc = gfx_bitmap_render(bitmap, NULL, pos);
    163189
     
    168194/** Get text starting position.
    169195 *
    170  * @param font Font
    171196 * @param pos Anchor position
    172197 * @param fmt Text formatting
     
    174199 * @param spos Place to store starting position
    175200 */
    176 void gfx_text_start_pos(gfx_font_t *font, gfx_coord2_t *pos,
    177     gfx_text_fmt_t *fmt, const char *str, gfx_coord2_t *spos)
     201void gfx_text_start_pos(gfx_coord2_t *pos, gfx_text_fmt_t *fmt,
     202    const char *str, gfx_coord2_t *spos)
    178203{
    179204        gfx_font_metrics_t fmetrics;
     
    184209        /* Adjust position for horizontal alignment */
    185210        if (fmt->halign != gfx_halign_left) {
    186                 width = gfx_text_width(font, str);
     211                /* Compute text width */
     212                width = gfx_text_width(fmt->font, str);
     213                if (fmt->abbreviate && width > fmt->width)
     214                        width = fmt->width;
     215
    187216                switch (fmt->halign) {
    188217                case gfx_halign_center:
     
    198227
    199228        /* Adjust position for vertical alignment */
    200         gfx_font_get_metrics(font, &fmetrics);
     229        gfx_font_get_metrics(fmt->font, &fmetrics);
    201230
    202231        if (fmt->valign != gfx_valign_baseline) {
     
    219248/** Render text.
    220249 *
    221  * @param font Font
    222250 * @param pos Anchor position
    223251 * @param fmt Text formatting
     
    225253 * @return EOK on success or an error code
    226254 */
    227 errno_t gfx_puttext(gfx_font_t *font, gfx_coord2_t *pos,
    228     gfx_text_fmt_t *fmt, const char *str)
     255errno_t gfx_puttext(gfx_coord2_t *pos, gfx_text_fmt_t *fmt, const char *str)
    229256{
    230257        gfx_glyph_metrics_t gmetrics;
     258        gfx_font_metrics_t fmetrics;
    231259        size_t stradv;
    232260        const char *cp;
    233261        gfx_glyph_t *glyph;
    234262        gfx_coord2_t cpos;
     263        gfx_coord2_t spos;
     264        gfx_rect_t rect;
     265        gfx_coord_t width;
     266        gfx_coord_t rmargin;
     267        bool ellipsis;
    235268        errno_t rc;
    236269
    237         gfx_text_start_pos(font, pos, fmt, str, &cpos);
     270        gfx_text_start_pos(pos, fmt, str, &spos);
    238271
    239272        /* Text mode */
    240         if ((font->finfo->props.flags & gff_text_mode) != 0)
    241                 return gfx_puttext_textmode(font, &cpos, fmt->color, str);
    242 
    243         rc = gfx_set_color(font->typeface->gc, fmt->color);
     273        if ((fmt->font->finfo->props.flags & gff_text_mode) != 0)
     274                return gfx_puttext_textmode(&spos, fmt, str);
     275
     276        rc = gfx_set_color(fmt->font->typeface->gc, fmt->color);
    244277        if (rc != EOK)
    245278                return rc;
    246279
     280        width = gfx_text_width(fmt->font, str);
     281
     282        if (fmt->abbreviate && width > fmt->width) {
     283                /* Need to append ellipsis */
     284                ellipsis = true;
     285                rmargin = spos.x + fmt->width - gfx_text_width(fmt->font, "...");
     286        } else {
     287                ellipsis = false;
     288                rmargin = spos.x + width;
     289        }
     290
     291        cpos = spos;
    247292        cp = str;
    248293        while (*cp != '\0') {
    249                 rc = gfx_font_search_glyph(font, cp, &glyph, &stradv);
     294                rc = gfx_font_search_glyph(fmt->font, cp, &glyph, &stradv);
    250295                if (rc != EOK) {
    251296                        ++cp;
     
    255300                gfx_glyph_get_metrics(glyph, &gmetrics);
    256301
     302                /* Stop if we would run over the right margin */
     303                if (fmt->abbreviate && cpos.x + gmetrics.advance > rmargin)
     304                        break;
     305
    257306                rc = gfx_glyph_render(glyph, &cpos);
    258307                if (rc != EOK)
     
    263312        }
    264313
     314        /* Text underlining */
     315        if (fmt->underline) {
     316                gfx_font_get_metrics(fmt->font, &fmetrics);
     317
     318                rect.p0.x = spos.x;
     319                rect.p0.y = spos.y + fmetrics.underline_y0;
     320                rect.p1.x = cpos.x;
     321                rect.p1.y = spos.y + fmetrics.underline_y1;
     322
     323                rc = gfx_fill_rect(fmt->font->typeface->gc, &rect);
     324                if (rc != EOK)
     325                        return rc;
     326        }
     327
     328        /* Render ellipsis, if required */
     329        if (ellipsis) {
     330                rc = gfx_font_search_glyph(fmt->font, ".", &glyph, &stradv);
     331                if (rc != EOK)
     332                        return EOK;
     333
     334                gfx_glyph_get_metrics(glyph, &gmetrics);
     335
     336                rc = gfx_glyph_render(glyph, &cpos);
     337                if (rc != EOK)
     338                        return rc;
     339
     340                cpos.x += gmetrics.advance;
     341
     342                rc = gfx_glyph_render(glyph, &cpos);
     343                if (rc != EOK)
     344                        return rc;
     345
     346                cpos.x += gmetrics.advance;
     347
     348                rc = gfx_glyph_render(glyph, &cpos);
     349                if (rc != EOK)
     350                        return rc;
     351        }
     352
    265353        return EOK;
    266354}
     
    268356/** Find character position in string by X coordinate.
    269357 *
    270  * @param font Font
    271358 * @param pos Anchor position
    272359 * @param fmt Text formatting
     
    280367 *         offset of the following character.
    281368 */
    282 size_t gfx_text_find_pos(gfx_font_t *font, gfx_coord2_t *pos,
    283     gfx_text_fmt_t *fmt, const char *str, gfx_coord2_t *fpos)
     369size_t gfx_text_find_pos(gfx_coord2_t *pos, gfx_text_fmt_t *fmt,
     370    const char *str, gfx_coord2_t *fpos)
    284371{
    285372        gfx_glyph_metrics_t gmetrics;
     
    292379        errno_t rc;
    293380
    294         gfx_text_start_pos(font, pos, fmt, str, &cpos);
     381        gfx_text_start_pos(pos, fmt, str, &cpos);
    295382
    296383        /* Text mode */
    297         if ((font->finfo->props.flags & gff_text_mode) != 0) {
     384        if ((fmt->font->finfo->props.flags & gff_text_mode) != 0) {
    298385                off = 0;
    299386                strsize = str_size(str);
     
    311398        off = 0;
    312399        while (*cp != '\0') {
    313                 rc = gfx_font_search_glyph(font, cp, &glyph, &stradv);
     400                rc = gfx_font_search_glyph(fmt->font, cp, &glyph, &stradv);
    314401                if (rc != EOK) {
    315402                        ++cp;
     
    337424 * to the same objects, respectively.
    338425 *
    339  * @param font Font
    340426 * @param pos Anchor position
    341427 * @param fmt Text formatting
     
    344430 * @param cfmt Place to store format for continuation
    345431 */
    346 void gfx_text_cont(gfx_font_t *font, gfx_coord2_t *pos,
    347     gfx_text_fmt_t *fmt, const char *str, gfx_coord2_t *cpos,
    348     gfx_text_fmt_t *cfmt)
     432void gfx_text_cont(gfx_coord2_t *pos, gfx_text_fmt_t *fmt, const char *str,
     433    gfx_coord2_t *cpos, gfx_text_fmt_t *cfmt)
    349434{
    350435        gfx_coord2_t spos;
     
    352437
    353438        /* Continuation should start where the current string ends */
    354         gfx_text_start_pos(font, pos, fmt, str, &spos);
    355         cpos->x = spos.x + gfx_text_width(font, str);
     439        gfx_text_start_pos(pos, fmt, str, &spos);
     440        cpos->x = spos.x + gfx_text_width(fmt->font, str);
    356441        cpos->y = spos.y;
    357442
     
    364449        tfmt.valign = gfx_valign_baseline;
    365450
     451        /* Remaining available width */
     452        tfmt.width = fmt->width - (cpos->x - spos.x);
     453
    366454        *cfmt = tfmt;
    367455}
     
    369457/** Get text bounding rectangle.
    370458 *
    371  * @param font Font
    372459 * @param pos Anchor position
    373460 * @param fmt Text formatting
     
    375462 * @param rect Place to store bounding rectangle
    376463 */
    377 void gfx_text_rect(gfx_font_t *font, gfx_coord2_t *pos,
    378     gfx_text_fmt_t *fmt, const char *str, gfx_rect_t *rect)
     464void gfx_text_rect(gfx_coord2_t *pos, gfx_text_fmt_t *fmt, const char *str,
     465    gfx_rect_t *rect)
    379466{
    380467        gfx_coord2_t spos;
    381 
    382         gfx_text_start_pos(font, pos, fmt, str, &spos);
     468        gfx_coord_t width;
     469
     470        gfx_text_start_pos(pos, fmt, str, &spos);
     471        width = gfx_text_width(fmt->font, str);
     472        if (fmt->abbreviate && width > fmt->width)
     473                width = fmt->width;
    383474
    384475        rect->p0.x = spos.x;
    385         rect->p0.y = spos.y - font->metrics.ascent;
    386         rect->p1.x = spos.x + gfx_text_width(font, str);
    387         rect->p1.y = spos.y + font->metrics.descent + 1;
     476        rect->p0.y = spos.y - fmt->font->metrics.ascent;
     477        rect->p1.x = spos.x + width;
     478        rect->p1.y = spos.y +  fmt->font->metrics.descent + 1;
    388479}
    389480
Note: See TracChangeset for help on using the changeset viewer.