Changeset d63623f in mainline for uspace/lib/gfxfont


Ignore:
Timestamp:
2021-07-16T17:45:12Z (4 years ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
4afb6c9
Parents:
61bf9dd9
Message:

Seeking in entry text using mouse

Location:
uspace/lib/gfxfont
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/gfxfont/include/gfx/text.h

    r61bf9dd9 rd63623f  
    11/*
    2  * Copyright (c) 2020 Jiri Svoboda
     2 * Copyright (c) 2021 Jiri Svoboda
    33 * All rights reserved.
    44 *
     
    4646extern errno_t gfx_puttext(gfx_font_t *, gfx_coord2_t *, gfx_text_fmt_t *,
    4747    const char *);
     48extern void gfx_text_start_pos(gfx_font_t *, gfx_coord2_t *, gfx_text_fmt_t *,
     49    const char *, gfx_coord2_t *);
     50extern size_t gfx_text_find_pos(gfx_font_t *, gfx_coord2_t *, gfx_text_fmt_t *,
     51    const char *, gfx_coord2_t *);
    4852
    4953#endif
  • uspace/lib/gfxfont/src/text.c

    r61bf9dd9 rd63623f  
    11/*
    2  * Copyright (c) 2020 Jiri Svoboda
     2 * Copyright (c) 2021 Jiri Svoboda
    33 * All rights reserved.
    44 *
     
    167167}
    168168
    169 /** Render text.
     169/** Get text starting position.
    170170 *
    171171 * @param font Font
     
    173173 * @param fmt Text formatting
    174174 * @param str String
     175 * @param spos Place to store starting position
     176 * @return EOK on success or an error code
     177 */
     178void gfx_text_start_pos(gfx_font_t *font, gfx_coord2_t *pos,
     179    gfx_text_fmt_t *fmt, const char *str, gfx_coord2_t *spos)
     180{
     181        gfx_font_metrics_t fmetrics;
     182        gfx_coord2_t cpos;
     183        gfx_coord_t width;
     184
     185        *spos = *pos;
     186
     187        /* Adjust position for horizontal alignment */
     188        if (fmt->halign != gfx_halign_left) {
     189                width = gfx_text_width(font, str);
     190                switch (fmt->halign) {
     191                case gfx_halign_center:
     192                        spos->x -= width / 2;
     193                        break;
     194                case gfx_halign_right:
     195                        spos->x -= width - 1;
     196                        break;
     197                default:
     198                        break;
     199                }
     200        }
     201
     202        /* Adjust position for vertical alignment */
     203        gfx_font_get_metrics(font, &fmetrics);
     204
     205        if (fmt->valign != gfx_valign_baseline) {
     206                switch (fmt->valign) {
     207                case gfx_valign_top:
     208                        spos->y += fmetrics.ascent;
     209                        break;
     210                case gfx_valign_center:
     211                        spos->y += fmetrics.ascent / 2;
     212                        break;
     213                case gfx_valign_bottom:
     214                        cpos.y -= fmetrics.descent;
     215                        break;
     216                default:
     217                        break;
     218                }
     219        }
     220}
     221
     222/** Render text.
     223 *
     224 * @param font Font
     225 * @param pos Anchor position
     226 * @param fmt Text formatting
     227 * @param str String
    175228 * @return EOK on success or an error code
    176229 */
     
    178231    gfx_text_fmt_t *fmt, const char *str)
    179232{
    180         gfx_font_metrics_t fmetrics;
    181233        gfx_glyph_metrics_t gmetrics;
    182234        size_t stradv;
     
    184236        gfx_glyph_t *glyph;
    185237        gfx_coord2_t cpos;
    186         gfx_coord_t width;
    187238        errno_t rc;
    188239
    189         cpos = *pos;
    190 
    191         /* Adjust position for horizontal alignment */
    192         if (fmt->halign != gfx_halign_left) {
    193                 width = gfx_text_width(font, str);
    194                 switch (fmt->halign) {
    195                 case gfx_halign_center:
    196                         cpos.x -= width / 2;
    197                         break;
    198                 case gfx_halign_right:
    199                         cpos.x -= width - 1;
    200                         break;
    201                 default:
    202                         break;
    203                 }
    204         }
    205 
    206         /* Adjust position for vertical alignment */
    207         gfx_font_get_metrics(font, &fmetrics);
    208 
    209         if (fmt->valign != gfx_valign_baseline) {
    210                 switch (fmt->valign) {
    211                 case gfx_valign_top:
    212                         cpos.y += fmetrics.ascent;
    213                         break;
    214                 case gfx_valign_center:
    215                         cpos.y += fmetrics.ascent / 2;
    216                         break;
    217                 case gfx_valign_bottom:
    218                         cpos.y -= fmetrics.descent;
    219                         break;
    220                 default:
    221                         break;
    222                 }
    223         }
     240        gfx_text_start_pos(font, pos, fmt, str, &cpos);
    224241
    225242        /* Text mode */
     
    252269}
    253270
     271/** Find character position in string by X coordinate.
     272 *
     273 * @param font Font
     274 * @param pos Anchor position
     275 * @param fmt Text formatting
     276 * @param str String
     277 * @param fpos Position for which we need to find offset
     278 *
     279 * @return Byte offset in @a str of character corresponding to position
     280 *         @a fpos. Note that the position is rounded, that is,
     281 *         if it is before the center of character A, it will return
     282 *         offset of A, if it is after the center of A, it will return
     283 *         offset of the following character.
     284 */
     285size_t gfx_text_find_pos(gfx_font_t *font, gfx_coord2_t *pos,
     286    gfx_text_fmt_t *fmt, const char *str, gfx_coord2_t *fpos)
     287{
     288        gfx_glyph_metrics_t gmetrics;
     289        size_t stradv;
     290        const char *cp;
     291        gfx_glyph_t *glyph;
     292        gfx_coord2_t cpos;
     293        size_t off;
     294        size_t strsize;
     295        errno_t rc;
     296
     297        gfx_text_start_pos(font, pos, fmt, str, &cpos);
     298
     299        /* Text mode */
     300        if ((font->finfo->props.flags & gff_text_mode) != 0) {
     301                off = 0;
     302                strsize = str_size(str);
     303                while (off < strsize) {
     304                        if (fpos->x <= cpos.x)
     305                                return off;
     306                        (void) str_decode(str, &off, strsize);
     307                        cpos.x++;
     308                }
     309
     310                return off;
     311        }
     312
     313        cp = str;
     314        off = 0;
     315        while (*cp != '\0') {
     316                rc = gfx_font_search_glyph(font, cp, &glyph, &stradv);
     317                if (rc != EOK) {
     318                        ++cp;
     319                        continue;
     320                }
     321
     322                gfx_glyph_get_metrics(glyph, &gmetrics);
     323
     324                if (fpos->x < cpos.x + gmetrics.advance / 2)
     325                        return off;
     326
     327                cp += stradv;
     328                off += stradv;
     329                cpos.x += gmetrics.advance;
     330        }
     331
     332        return off;
     333}
     334
    254335/** @}
    255336 */
  • uspace/lib/gfxfont/test/text.c

    r61bf9dd9 rd63623f  
    3030#include <gfx/context.h>
    3131#include <gfx/font.h>
     32#include <gfx/glyph.h>
    3233#include <gfx/text.h>
    3334#include <gfx/typeface.h>
     
    144145        gfx_typeface_destroy(tface);
    145146        gfx_color_delete(color);
     147
     148        rc = gfx_context_delete(gc);
     149        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     150}
     151
     152/** gfx_text_start_pos() correctly computes text start position */
     153PCUT_TEST(text_start_pos)
     154{
     155        gfx_font_props_t props;
     156        gfx_font_metrics_t metrics;
     157        gfx_typeface_t *tface;
     158        gfx_font_t *font;
     159        gfx_context_t *gc;
     160        gfx_color_t *color;
     161        gfx_text_fmt_t fmt;
     162        gfx_coord2_t pos;
     163        test_gc_t tgc;
     164        errno_t rc;
     165
     166        rc = gfx_context_new(&test_ops, (void *)&tgc, &gc);
     167        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     168
     169        rc = gfx_color_new_rgb_i16(0, 0, 0, &color);
     170        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     171
     172        rc = gfx_typeface_create(gc, &tface);
     173        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     174
     175        gfx_font_props_init(&props);
     176        gfx_font_metrics_init(&metrics);
     177        metrics.ascent = 10; // XXX
     178        metrics.descent = 10; // XXX
     179        rc = gfx_font_create(tface, &props, &metrics, &font);
     180        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     181
     182        gfx_text_fmt_init(&fmt);
     183        fmt.color = color;
     184        pos.x = 0;
     185        pos.y = 0;
     186
     187        rc = gfx_puttext(font, &pos, &fmt, "Hello world!");
     188        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     189
     190        gfx_font_close(font);
     191        gfx_typeface_destroy(tface);
     192        gfx_color_delete(color);
     193
     194        rc = gfx_context_delete(gc);
     195        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     196}
     197
     198/** gfx_text_find_pos() finds position in text */
     199PCUT_TEST(text_find_pos)
     200{
     201        gfx_font_props_t props;
     202        gfx_font_metrics_t metrics;
     203        gfx_typeface_t *tface;
     204        gfx_font_t *font;
     205        gfx_glyph_metrics_t gmetrics;
     206        gfx_glyph_t *glyph1;
     207        gfx_glyph_t *glyph2;
     208        gfx_context_t *gc;
     209        gfx_text_fmt_t fmt;
     210        gfx_coord2_t anchor;
     211        gfx_coord2_t fpos;
     212        size_t off;
     213        test_gc_t tgc;
     214        errno_t rc;
     215
     216        rc = gfx_context_new(&test_ops, (void *)&tgc, &gc);
     217        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     218
     219        rc = gfx_typeface_create(gc, &tface);
     220        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     221
     222        gfx_font_props_init(&props);
     223        gfx_font_metrics_init(&metrics);
     224        rc = gfx_font_create(tface, &props, &metrics, &font);
     225        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     226
     227        /* Need to create some glyphs with metrics */
     228        gfx_glyph_metrics_init(&gmetrics);
     229        gmetrics.advance = 10;
     230
     231        rc = gfx_glyph_create(font, &gmetrics, &glyph1);
     232        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     233
     234        rc = gfx_glyph_set_pattern(glyph1, "A");
     235        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     236
     237        gfx_glyph_metrics_init(&gmetrics);
     238        gmetrics.advance = 1;
     239
     240        rc = gfx_glyph_create(font, &gmetrics, &glyph2);
     241        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     242
     243        rc = gfx_glyph_set_pattern(glyph2, "i");
     244        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     245
     246        gfx_text_fmt_init(&fmt);
     247        anchor.x = 10;
     248        anchor.y = 0;
     249
     250        fpos.x = 9;
     251        fpos.y = 0;
     252        off = gfx_text_find_pos(font, &anchor, &fmt, "Aii", &fpos);
     253        PCUT_ASSERT_INT_EQUALS(0, off);
     254
     255        fpos.x = 10;
     256        fpos.y = 0;
     257        off = gfx_text_find_pos(font, &anchor, &fmt, "Aii", &fpos);
     258        PCUT_ASSERT_INT_EQUALS(0, off);
     259
     260        fpos.x = 11;
     261        fpos.y = 0;
     262        off = gfx_text_find_pos(font, &anchor, &fmt, "Aii", &fpos);
     263        PCUT_ASSERT_INT_EQUALS(0, off);
     264
     265        fpos.x = 19;
     266        fpos.y = 0;
     267        off = gfx_text_find_pos(font, &anchor, &fmt, "Aii", &fpos);
     268        PCUT_ASSERT_INT_EQUALS(1, off);
     269
     270        fpos.x = 20;
     271        fpos.y = 0;
     272        off = gfx_text_find_pos(font, &anchor, &fmt, "Aii", &fpos);
     273        PCUT_ASSERT_INT_EQUALS(2, off);
     274
     275        fpos.x = 21;
     276        fpos.y = 0;
     277        off = gfx_text_find_pos(font, &anchor, &fmt, "Aii", &fpos);
     278        PCUT_ASSERT_INT_EQUALS(3, off);
     279
     280        fpos.x = 22;
     281        fpos.y = 0;
     282        off = gfx_text_find_pos(font, &anchor, &fmt, "Aii", &fpos);
     283        PCUT_ASSERT_INT_EQUALS(3, off);
     284
     285        gfx_glyph_destroy(glyph1);
     286        gfx_glyph_destroy(glyph2);
     287
     288        gfx_font_close(font);
     289        gfx_typeface_destroy(tface);
     290
     291        rc = gfx_context_delete(gc);
     292        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     293}
     294
     295/** gfx_text_find_pos() finds position in text in text mode */
     296PCUT_TEST(text_find_pos_text)
     297{
     298        gfx_typeface_t *tface;
     299        gfx_font_t *font;
     300        gfx_context_t *gc;
     301        test_gc_t tgc;
     302        size_t off;
     303        gfx_text_fmt_t fmt;
     304        gfx_coord2_t anchor;
     305        gfx_coord2_t fpos;
     306        errno_t rc;
     307
     308        rc = gfx_context_new(&test_ops, (void *)&tgc, &gc);
     309        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     310
     311        rc = gfx_typeface_create(gc, &tface);
     312        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     313
     314        rc = gfx_font_create_textmode(tface, &font);
     315        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     316
     317        anchor.x = 10;
     318        anchor.y = 0;
     319        gfx_text_fmt_init(&fmt);
     320
     321        fpos.x = 9;
     322        fpos.y = 0;
     323        off = gfx_text_find_pos(font, &anchor, &fmt, "Abc", &fpos);
     324        PCUT_ASSERT_INT_EQUALS(0, off);
     325
     326        fpos.x = 10;
     327        fpos.y = 0;
     328        off = gfx_text_find_pos(font, &anchor, &fmt, "Abc", &fpos);
     329        PCUT_ASSERT_INT_EQUALS(0, off);
     330
     331        fpos.x = 11;
     332        fpos.y = 0;
     333        off = gfx_text_find_pos(font, &anchor, &fmt, "Abc", &fpos);
     334        PCUT_ASSERT_INT_EQUALS(1, off);
     335
     336        fpos.x = 12;
     337        fpos.y = 0;
     338        off = gfx_text_find_pos(font, &anchor, &fmt, "Abc", &fpos);
     339        PCUT_ASSERT_INT_EQUALS(2, off);
     340
     341        fpos.x = 13;
     342        fpos.y = 0;
     343        off = gfx_text_find_pos(font, &anchor, &fmt, "Abc", &fpos);
     344        PCUT_ASSERT_INT_EQUALS(3, off);
     345
     346        fpos.x = 14;
     347        fpos.y = 0;
     348        off = gfx_text_find_pos(font, &anchor, &fmt, "Abc", &fpos);
     349        PCUT_ASSERT_INT_EQUALS(3, off);
     350
     351        gfx_font_close(font);
     352        gfx_typeface_destroy(tface);
    146353
    147354        rc = gfx_context_delete(gc);
Note: See TracChangeset for help on using the changeset viewer.