Ignore:
File:
1 edited

Legend:

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

    rf2d4a46 r9eb8d12  
    11/*
    2  * Copyright (c) 2022 Jiri Svoboda
     2 * Copyright (c) 2021 Jiri Svoboda
    33 * All rights reserved.
    44 *
     
    9797/** Print string using text characters in text mode.
    9898 *
     99 * @param font Font
    99100 * @param pos Position of top-left corner of text
    100  * @param fmt Formatting
     101 * @param color Text color
    101102 * @param str String
    102103 * @return EOK on success or an error code
    103104 */
    104 static 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;
     105static 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;
    108109        gfx_bitmap_params_t params;
    109110        gfx_bitmap_t *bitmap;
    110111        gfx_bitmap_alloc_t alloc;
    111         gfx_coord_t width;
    112         uint8_t attr;
     112        uint16_t r, g, b;
    113113        pixelmap_t pmap;
    114114        gfx_coord_t x;
    115         gfx_coord_t rmargin;
    116115        pixel_t pixel;
    117         char32_t c;
    118         size_t off;
    119         bool ellipsis;
    120116        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         }
    134117
    135118        /*
     
    138121         */
    139122
    140         gfx_color_get_ega(fmt->color, &attr);
     123        gfx_color_get_rgb_i16(color, &r, &g, &b);
     124
     125        /*
     126         * We are setting the *background* color, the foreground color
     127         * will be set to its complement.
     128         */
     129        r = 0xff ^ (r >> 8);
     130        g = 0xff ^ (g >> 8);
     131        b = 0xff ^ (b >> 8);
    141132
    142133        gfx_bitmap_params_init(&params);
    143134        params.rect.p0.x = 0;
    144135        params.rect.p0.y = 0;
    145         params.rect.p1.x = width;
     136        params.rect.p1.x = str_width(str);
    146137        params.rect.p1.y = 1;
    147138
     
    165156        pmap.data = alloc.pixels;
    166157
    167         off = 0;
    168         for (x = 0; x < rmargin; x++) {
    169                 c = str_decode(str, &off, STR_NO_LIMIT);
    170                 pixel = PIXEL(attr,
    171                     (c >> 16) & 0xff,
    172                     (c >> 8) & 0xff,
    173                     c & 0xff);
     158        for (x = 0; x < params.rect.p1.x; x++) {
     159                pixel = PIXEL(str[x], r, g, b);
    174160                pixelmap_put_pixel(&pmap, x, 0, pixel);
    175         }
    176 
    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                 }
    186161        }
    187162
     
    194169/** Get text starting position.
    195170 *
     171 * @param font Font
    196172 * @param pos Anchor position
    197173 * @param fmt Text formatting
     
    199175 * @param spos Place to store starting position
    200176 */
    201 void gfx_text_start_pos(gfx_coord2_t *pos, gfx_text_fmt_t *fmt,
    202     const char *str, gfx_coord2_t *spos)
     177void gfx_text_start_pos(gfx_font_t *font, gfx_coord2_t *pos,
     178    gfx_text_fmt_t *fmt, const char *str, gfx_coord2_t *spos)
    203179{
    204180        gfx_font_metrics_t fmetrics;
     181        gfx_coord2_t cpos;
    205182        gfx_coord_t width;
    206183
     
    209186        /* Adjust position for horizontal alignment */
    210187        if (fmt->halign != gfx_halign_left) {
    211                 /* Compute text width */
    212                 width = gfx_text_width(fmt->font, str);
    213                 if (fmt->abbreviate && width > fmt->width)
    214                         width = fmt->width;
    215 
     188                width = gfx_text_width(font, str);
    216189                switch (fmt->halign) {
    217190                case gfx_halign_center:
     
    219192                        break;
    220193                case gfx_halign_right:
    221                         spos->x -= width;
     194                        spos->x -= width - 1;
    222195                        break;
    223196                default:
     
    227200
    228201        /* Adjust position for vertical alignment */
    229         gfx_font_get_metrics(fmt->font, &fmetrics);
     202        gfx_font_get_metrics(font, &fmetrics);
    230203
    231204        if (fmt->valign != gfx_valign_baseline) {
     
    238211                        break;
    239212                case gfx_valign_bottom:
    240                         spos->y -= fmetrics.descent + 1;
     213                        cpos.y -= fmetrics.descent;
    241214                        break;
    242215                default:
     
    248221/** Render text.
    249222 *
     223 * @param font Font
    250224 * @param pos Anchor position
    251225 * @param fmt Text formatting
     
    253227 * @return EOK on success or an error code
    254228 */
    255 errno_t gfx_puttext(gfx_coord2_t *pos, gfx_text_fmt_t *fmt, const char *str)
     229errno_t gfx_puttext(gfx_font_t *font, gfx_coord2_t *pos,
     230    gfx_text_fmt_t *fmt, const char *str)
    256231{
    257232        gfx_glyph_metrics_t gmetrics;
    258         gfx_font_metrics_t fmetrics;
    259233        size_t stradv;
    260234        const char *cp;
    261235        gfx_glyph_t *glyph;
    262236        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;
    268237        errno_t rc;
    269238
    270         gfx_text_start_pos(pos, fmt, str, &spos);
     239        gfx_text_start_pos(font, pos, fmt, str, &cpos);
    271240
    272241        /* Text mode */
    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);
     242        if ((font->finfo->props.flags & gff_text_mode) != 0)
     243                return gfx_puttext_textmode(font, &cpos, fmt->color, str);
     244
     245        rc = gfx_set_color(font->typeface->gc, fmt->color);
    277246        if (rc != EOK)
    278247                return rc;
    279248
    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;
    292249        cp = str;
    293250        while (*cp != '\0') {
    294                 rc = gfx_font_search_glyph(fmt->font, cp, &glyph, &stradv);
     251                rc = gfx_font_search_glyph(font, cp, &glyph, &stradv);
    295252                if (rc != EOK) {
    296253                        ++cp;
     
    300257                gfx_glyph_get_metrics(glyph, &gmetrics);
    301258
    302                 /* Stop if we would run over the right margin */
    303                 if (fmt->abbreviate && cpos.x + gmetrics.advance > rmargin)
    304                         break;
    305 
    306259                rc = gfx_glyph_render(glyph, &cpos);
    307260                if (rc != EOK)
     
    312265        }
    313266
    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 
    353267        return EOK;
    354268}
     
    356270/** Find character position in string by X coordinate.
    357271 *
     272 * @param font Font
    358273 * @param pos Anchor position
    359274 * @param fmt Text formatting
     
    367282 *         offset of the following character.
    368283 */
    369 size_t gfx_text_find_pos(gfx_coord2_t *pos, gfx_text_fmt_t *fmt,
    370     const char *str, gfx_coord2_t *fpos)
     284size_t gfx_text_find_pos(gfx_font_t *font, gfx_coord2_t *pos,
     285    gfx_text_fmt_t *fmt, const char *str, gfx_coord2_t *fpos)
    371286{
    372287        gfx_glyph_metrics_t gmetrics;
     
    379294        errno_t rc;
    380295
    381         gfx_text_start_pos(pos, fmt, str, &cpos);
     296        gfx_text_start_pos(font, pos, fmt, str, &cpos);
    382297
    383298        /* Text mode */
    384         if ((fmt->font->finfo->props.flags & gff_text_mode) != 0) {
     299        if ((font->finfo->props.flags & gff_text_mode) != 0) {
    385300                off = 0;
    386301                strsize = str_size(str);
     
    398313        off = 0;
    399314        while (*cp != '\0') {
    400                 rc = gfx_font_search_glyph(fmt->font, cp, &glyph, &stradv);
     315                rc = gfx_font_search_glyph(font, cp, &glyph, &stradv);
    401316                if (rc != EOK) {
    402317                        ++cp;
     
    424339 * to the same objects, respectively.
    425340 *
     341 * @param font Font
    426342 * @param pos Anchor position
    427343 * @param fmt Text formatting
     
    430346 * @param cfmt Place to store format for continuation
    431347 */
    432 void 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)
     348void gfx_text_cont(gfx_font_t *font, gfx_coord2_t *pos,
     349    gfx_text_fmt_t *fmt, const char *str, gfx_coord2_t *cpos,
     350    gfx_text_fmt_t *cfmt)
    434351{
    435352        gfx_coord2_t spos;
     
    437354
    438355        /* Continuation should start where the current string ends */
    439         gfx_text_start_pos(pos, fmt, str, &spos);
    440         cpos->x = spos.x + gfx_text_width(fmt->font, str);
     356        gfx_text_start_pos(font, pos, fmt, str, &spos);
     357        cpos->x = spos.x + gfx_text_width(font, str);
    441358        cpos->y = spos.y;
    442359
     
    449366        tfmt.valign = gfx_valign_baseline;
    450367
    451         /* Remaining available width */
    452         tfmt.width = fmt->width - (cpos->x - spos.x);
    453 
    454368        *cfmt = tfmt;
    455369}
     
    457371/** Get text bounding rectangle.
    458372 *
     373 * @param font Font
    459374 * @param pos Anchor position
    460375 * @param fmt Text formatting
     
    462377 * @param rect Place to store bounding rectangle
    463378 */
    464 void gfx_text_rect(gfx_coord2_t *pos, gfx_text_fmt_t *fmt, const char *str,
    465     gfx_rect_t *rect)
     379void gfx_text_rect(gfx_font_t *font, gfx_coord2_t *pos,
     380    gfx_text_fmt_t *fmt, const char *str, gfx_rect_t *rect)
    466381{
    467382        gfx_coord2_t 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;
     383
     384        gfx_text_start_pos(font, pos, fmt, str, &spos);
    474385
    475386        rect->p0.x = spos.x;
    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;
     387        rect->p0.y = spos.y - font->metrics.ascent;
     388        rect->p1.x = spos.x + gfx_text_width(font, str);
     389        rect->p1.y = spos.y + font->metrics.descent + 1;
    479390}
    480391
Note: See TracChangeset for help on using the changeset viewer.