Changeset ea459d4 in mainline


Ignore:
Timestamp:
2020-09-24T14:25:21Z (4 years ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
120031a5
Parents:
aaf962e6
git-author:
Jiri Svoboda <jiri@…> (2020-09-22 17:25:10)
git-committer:
Jiri Svoboda <jiri@…> (2020-09-24 14:25:21)
Message:

Reading typeface from TPF file

Location:
uspace/lib
Files:
1 added
12 edited

Legend:

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

    raaf962e6 rea459d4  
    4848extern gfx_font_info_t *gfx_typeface_first_font(gfx_typeface_t *);
    4949extern gfx_font_info_t *gfx_typeface_next_font(gfx_font_info_t *);
     50extern errno_t gfx_typeface_open(gfx_context_t *, const char *,
     51    gfx_typeface_t **);
    5052extern errno_t gfx_typeface_save(gfx_typeface_t *, const char *);
    5153
  • uspace/lib/gfxfont/meson.build

    raaf962e6 rea459d4  
    4040        'test/glyph_bmp.c',
    4141        'test/main.c',
     42        'test/tpf.c',
    4243        'test/typeface.c',
    4344)
  • uspace/lib/gfxfont/private/font.h

    raaf962e6 rea459d4  
    5959        /** Containing typeface */
    6060        struct gfx_typeface *typeface;
     61        /** Containing font info */
     62        struct gfx_font_info *finfo;
    6163        /** Font metrics */
    6264        gfx_font_metrics_t metrics;
     
    8284        /** Font or @c NULL if font is not present in memory */
    8385        struct gfx_font *font;
     86        /** Font chunk from which font can be read */
     87        riff_rchunk_t fontck;
    8488};
    8589
    8690extern errno_t gfx_font_splice_at_glyph(gfx_font_t *, gfx_glyph_t *,
    8791    gfx_rect_t *);
     92extern errno_t gfx_font_info_load(gfx_typeface_t *, riff_rchunk_t *);
     93extern errno_t gfx_font_load(gfx_font_info_t *);
    8894extern errno_t gfx_font_save(gfx_font_info_t *, riffw_t *);
    8995
  • uspace/lib/gfxfont/private/glyph.h

    raaf962e6 rea459d4  
    7777extern errno_t gfx_glyph_transfer(gfx_glyph_t *, gfx_coord_t, gfx_bitmap_t *,
    7878    gfx_rect_t *);
     79extern errno_t gfx_glyph_load(gfx_font_t *, riff_rchunk_t *);
    7980extern errno_t gfx_glyph_save(gfx_glyph_t *, riffw_t *);
    8081
  • uspace/lib/gfxfont/private/typeface.h

    raaf962e6 rea459d4  
    4040#include <adt/list.h>
    4141#include <errno.h>
     42#include <riff/chunk.h>
    4243#include <types/gfx/bitmap.h>
    4344#include <types/gfx/context.h>
     
    5758        /** Fonts (of gfx_font_info_t) */
    5859        list_t fonts;
     60        /** RIFF reader of the open typeface file or @c NULL */
     61        riffr_t *riffr;
    5962};
    6063
  • uspace/lib/gfxfont/src/font.c

    raaf962e6 rea459d4  
    8181}
    8282
    83 /** Create font.
     83/** Create font with existing font info structure.
    8484 *
    8585 * @param tface Typeface
     86 * @param finfo Font info
    8687 * @param metrics Font metrics
    8788 * @param rfont Place to store pointer to new font
     
    9192 *         was lost
    9293 */
    93 errno_t gfx_font_create(gfx_typeface_t *tface, gfx_font_props_t *props,
    94     gfx_font_metrics_t *metrics, gfx_font_t **rfont)
    95 {
    96         gfx_font_info_t *finfo = NULL;
     94static errno_t gfx_font_create_with_info(gfx_typeface_t *tface,
     95    gfx_font_info_t *finfo, gfx_font_metrics_t *metrics, gfx_font_t **rfont)
     96{
    9797        gfx_font_t *font = NULL;
    9898        gfx_bitmap_params_t params;
    9999        errno_t rc;
    100 
    101         finfo = calloc(1, sizeof(gfx_font_info_t));
    102         if (finfo == NULL) {
    103                 rc = ENOMEM;
    104                 goto error;
    105         }
    106100
    107101        font = calloc(1, sizeof(gfx_font_t));
     
    110104                goto error;
    111105        }
    112 
    113         finfo->typeface = tface;
    114         finfo->props = *props;
    115         finfo->font = font;
    116 
    117106        font->typeface = tface;
     107        font->finfo = finfo;
    118108
    119109        font->rect.p0.x = 0;
     
    138128        font->metrics = *metrics;
    139129        list_initialize(&font->glyphs);
     130        *rfont = font;
     131        return EOK;
     132error:
     133        if (font != NULL)
     134                free(font);
     135        return rc;
     136}
     137
     138/** Create font.
     139 *
     140 * @param tface Typeface
     141 * @param props Font properties
     142 * @param metrics Font metrics
     143 * @param rfont Place to store pointer to new font
     144 *
     145 * @return EOK on success, EINVAL if parameters are invald,
     146 *         ENOMEM if insufficient resources, EIO if graphic device connection
     147 *         was lost
     148 */
     149errno_t gfx_font_create(gfx_typeface_t *tface, gfx_font_props_t *props,
     150    gfx_font_metrics_t *metrics, gfx_font_t **rfont)
     151{
     152        gfx_font_info_t *finfo = NULL;
     153        gfx_font_t *font = NULL;
     154        errno_t rc;
     155
     156        finfo = calloc(1, sizeof(gfx_font_info_t));
     157        if (finfo == NULL) {
     158                rc = ENOMEM;
     159                goto error;
     160        }
     161
     162        finfo->typeface = tface;
     163        finfo->props = *props;
     164
     165        rc = gfx_font_create_with_info(tface, finfo, metrics, &font);
     166        if (rc != EOK)
     167                goto error;
     168
     169        finfo->font = font;
    140170        list_append(&finfo->lfonts, &tface->fonts);
    141171        *rfont = font;
     
    144174        if (finfo != NULL)
    145175                free(finfo);
    146         if (font != NULL)
    147                 free(font);
    148176        return rc;
    149177}
     
    157185errno_t gfx_font_open(gfx_font_info_t *finfo, gfx_font_t **rfont)
    158186{
     187        errno_t rc;
     188
    159189        if (finfo->font == NULL) {
    160                 /*
    161                  * We cannot load an absent font yet.
    162                  * This should not happen.
    163                  */
    164                 assert(false);
    165                 return ENOTSUP;
     190                /* Load absent font from TPF file */
     191                rc = gfx_font_load(finfo);
     192                if (rc != EOK)
     193                        return rc;
     194
     195                assert(finfo->font != NULL);
     196                finfo->font->finfo = finfo;
    166197        }
    167198
     
    184215        }
    185216
     217        font->finfo->font = NULL;
    186218        free(font);
    187219}
     
    360392}
    361393
     394/** Load font properties from RIFF TPF file.
     395 *
     396 * @param parent Parent chunk
     397 * @param props Font properties
     398 * @return EOK on success or an error code
     399 */
     400static errno_t gfx_font_props_load(riff_rchunk_t *parent,
     401    gfx_font_props_t *props)
     402{
     403        errno_t rc;
     404        riff_rchunk_t propsck;
     405        size_t nread;
     406
     407        rc = riff_rchunk_match(parent, CKID_fprp, &propsck);
     408        if (rc != EOK)
     409                return rc;
     410
     411        rc = riff_read(&propsck, (void *) props, sizeof(*props), &nread);
     412        if (rc != EOK || nread != sizeof(*props))
     413                return EIO;
     414
     415        rc = riff_rchunk_end(&propsck);
     416        if (rc != EOK)
     417                return rc;
     418
     419        return EOK;
     420}
     421
    362422/** Save font properties to RIFF TPF file.
    363423 *
     
    386446}
    387447
     448/** Load font metrics from RIFF TPF file.
     449 *
     450 * @param parent Parent chunk
     451 * @param metrics Font metrics
     452 * @return EOK on success or an error code
     453 */
     454static errno_t gfx_font_metrics_load(riff_rchunk_t *parent,
     455    gfx_font_metrics_t *metrics)
     456{
     457        errno_t rc;
     458        riff_rchunk_t mtrck;
     459        size_t nread;
     460
     461        rc = riff_rchunk_match(parent, CKID_fmtr, &mtrck);
     462        if (rc != EOK)
     463                return rc;
     464
     465        rc = riff_read(&mtrck, (void *) metrics, sizeof(*metrics), &nread);
     466        if (rc != EOK || nread != sizeof(*metrics))
     467                return EIO;
     468
     469        rc = riff_rchunk_end(&mtrck);
     470        if (rc != EOK)
     471                return rc;
     472
     473        return EOK;
     474}
     475
    388476/** Save font metrics to RIFF TPF file.
    389477 *
     
    413501}
    414502
     503/** Load font bitmap from RIFF TPF file.
     504 *
     505 * @param parent Parent chunk
     506 * @param font Font
     507 * @return EOK on success or an error code
     508 */
     509static errno_t gfx_font_bitmap_load(riff_rchunk_t *parent, gfx_font_t *font)
     510{
     511        errno_t rc;
     512        riff_rchunk_t bmpck;
     513        gfx_bitmap_params_t params;
     514        gfx_bitmap_alloc_t alloc;
     515        gfx_bitmap_t *bitmap = NULL;
     516        uint32_t width;
     517        uint32_t height;
     518        uint32_t depth;
     519        size_t nread;
     520
     521        rc = riff_rchunk_match(parent, CKID_fbmp, &bmpck);
     522        if (rc != EOK)
     523                goto error;
     524
     525        rc = riff_read_uint32(&bmpck, &width);
     526        if (rc != EOK)
     527                goto error;
     528
     529        rc = riff_read_uint32(&bmpck, &height);
     530        if (rc != EOK)
     531                goto error;
     532
     533        rc = riff_read_uint32(&bmpck, &depth);
     534        if (rc != EOK)
     535                goto error;
     536
     537        if (depth != 8 * sizeof(uint32_t)) {
     538                rc = ENOTSUP;
     539                goto error;
     540        }
     541
     542        gfx_bitmap_params_init(&params);
     543        params.rect.p0.x = 0;
     544        params.rect.p0.y = 0;
     545        params.rect.p1.x = width;
     546        params.rect.p1.y = height;
     547
     548        rc = gfx_bitmap_create(font->typeface->gc, &params, NULL, &bitmap);
     549        if (rc != EOK)
     550                goto error;
     551
     552        rc = gfx_bitmap_get_alloc(bitmap, &alloc);
     553        if (rc != EOK)
     554                goto error;
     555
     556        rc = riff_read(&bmpck, (void *) alloc.pixels,
     557            width * height * sizeof(uint32_t), &nread);
     558        if (rc != EOK)
     559                goto error;
     560
     561        if (nread != width * height * sizeof(uint32_t)) {
     562                rc = EIO;
     563                goto error;
     564        }
     565
     566        rc = riff_rchunk_end(&bmpck);
     567        if (rc != EOK)
     568                goto error;
     569
     570        gfx_bitmap_destroy(font->bitmap);
     571        font->bitmap = bitmap;
     572        font->rect = params.rect;
     573        return EOK;
     574error:
     575        if (bitmap != NULL)
     576                gfx_bitmap_destroy(bitmap);
     577        return rc;
     578}
     579
    415580/** Save font bitmap to RIFF TPF file.
    416581 *
     
    457622}
    458623
     624/** Load font info from RIFF TPF file.
     625 *
     626 * @param tface Containing typeface
     627 * @param parent Parent chunk
     628 * @return EOK on success or an error code
     629 */
     630errno_t gfx_font_info_load(gfx_typeface_t *tface, riff_rchunk_t *parent)
     631{
     632        errno_t rc;
     633        riff_rchunk_t fontck;
     634        gfx_font_props_t props;
     635        gfx_font_info_t *finfo = NULL;
     636        gfx_font_t *font = NULL;
     637
     638        rc = riff_rchunk_list_match(parent, LTYPE_font, &fontck);
     639        if (rc != EOK)
     640                goto error;
     641
     642        finfo = calloc(1, sizeof(gfx_font_info_t));
     643        if (finfo == NULL) {
     644                rc = ENOMEM;
     645                goto error;
     646        }
     647
     648        finfo->fontck = fontck;
     649
     650        rc = gfx_font_props_load(&fontck, &props);
     651        if (rc != EOK)
     652                goto error;
     653
     654        rc = riff_rchunk_end(&fontck);
     655        if (rc != EOK)
     656                goto error;
     657
     658        finfo->typeface = tface;
     659        list_append(&finfo->lfonts, &tface->fonts);
     660        finfo->props = props;
     661        finfo->font = NULL;
     662
     663        return EOK;
     664error:
     665        if (finfo != NULL)
     666                free(finfo);
     667        if (font != NULL)
     668                gfx_font_close(font);
     669        return rc;
     670}
     671
     672/** Load font from RIFF TPF file.
     673 *
     674 * @param finfo Font information
     675 * @return EOK on success or an error code
     676 */
     677errno_t gfx_font_load(gfx_font_info_t *finfo)
     678{
     679        errno_t rc;
     680        gfx_font_metrics_t metrics;
     681        gfx_font_t *font = NULL;
     682
     683        /* Seek to beginning of chunk (just after list type) */
     684        rc = riff_rchunk_seek(&finfo->fontck, sizeof(uint32_t), SEEK_SET);
     685        if (rc != EOK)
     686                goto error;
     687
     688        rc = gfx_font_props_load(&finfo->fontck, &finfo->props);
     689        if (rc != EOK)
     690                goto error;
     691
     692        rc = gfx_font_metrics_load(&finfo->fontck, &metrics);
     693        if (rc != EOK)
     694                goto error;
     695
     696        rc = gfx_font_create_with_info(finfo->typeface, finfo, &metrics, &font);
     697        if (rc != EOK)
     698                goto error;
     699
     700        rc = gfx_font_bitmap_load(&finfo->fontck, font);
     701        if (rc != EOK)
     702                goto error;
     703
     704        while (true) {
     705                rc = gfx_glyph_load(font, &finfo->fontck);
     706                if (rc == ENOENT)
     707                        break;
     708                if (rc != EOK)
     709                        goto error;
     710        }
     711
     712        finfo->font = font;
     713        return EOK;
     714error:
     715        if (font != NULL)
     716                gfx_font_close(font);
     717        return rc;
     718}
     719
    459720/** Save font into RIFF TPF file.
    460721 *
    461722 * @param finfo Font info
    462723 * @param riffw RIFF writer
     724 * @return EOK on success or an error code
    463725 */
    464726errno_t gfx_font_save(gfx_font_info_t *finfo, riffw_t *riffw)
  • uspace/lib/gfxfont/src/glyph.c

    raaf962e6 rea459d4  
    315315}
    316316
     317/** Load glyph metrics from RIFF TPF file.
     318 *
     319 * @param parent Parent chunk
     320 * @param metrics Place to store glyph metrics
     321 * @return EOK on success or an error code
     322 */
     323static errno_t gfx_glyph_metrics_load(riff_rchunk_t *parent,
     324    gfx_glyph_metrics_t *metrics)
     325{
     326        errno_t rc;
     327        riff_rchunk_t mtrck;
     328        size_t nread;
     329
     330        rc = riff_rchunk_match(parent, CKID_gmtr, &mtrck);
     331        if (rc != EOK)
     332                return rc;
     333
     334        rc = riff_read(&mtrck, (void *) metrics, sizeof(*metrics), &nread);
     335        if (rc != EOK || nread != sizeof(*metrics))
     336                return EIO;
     337
     338        rc = riff_rchunk_end(&mtrck);
     339        if (rc != EOK)
     340                return rc;
     341
     342        return EOK;
     343}
     344
    317345/** Save glyph metrics to RIFF TPF file.
    318346 *
     
    342370}
    343371
     372/** Load glyph patterns from RIFF TPF file.
     373 *
     374 * @param parent Parent chunk
     375 * @param glyph Glyph
     376 * @return EOK on success or an error code
     377 */
     378static errno_t gfx_glyph_patterns_load(riff_rchunk_t *parent,
     379    gfx_glyph_t *glyph)
     380{
     381        errno_t rc;
     382        riff_rchunk_t patck;
     383        uint32_t cksize;
     384        size_t i;
     385        size_t nread;
     386        char *buf = NULL;
     387
     388        rc = riff_rchunk_match(parent, CKID_gpat, &patck);
     389        if (rc != EOK)
     390                goto error;
     391
     392        cksize = riff_rchunk_size(&patck);
     393        buf = malloc(cksize);
     394        if (buf == NULL) {
     395                rc = ENOMEM;
     396                goto error;
     397        }
     398
     399        rc = riff_read(&patck, buf, cksize, &nread);
     400        if (rc != EOK || nread != cksize)
     401                goto error;
     402
     403        i = 0;
     404        while (i < cksize) {
     405                rc = gfx_glyph_set_pattern(glyph, &buf[i]);
     406                if (rc != EOK)
     407                        goto error;
     408
     409                i += str_size(&buf[i]) + 1;
     410        }
     411
     412        rc = riff_rchunk_end(&patck);
     413        if (rc != EOK)
     414                goto error;
     415
     416        free(buf);
     417        return EOK;
     418error:
     419        if (buf != NULL)
     420                free(buf);
     421        return rc;
     422}
    344423/** Save glyph patterns to RIFF TPF file.
    345424 *
     
    377456}
    378457
     458/** Load glyph rectangle/origin from RIFF TPF file.
     459 *
     460 * @param parent Parent chunk
     461 * @param glyph Glyph
     462 * @return EOK on success or an error code
     463 */
     464static errno_t gfx_glyph_rectangle_origin_load(riff_rchunk_t *parent,
     465    gfx_glyph_t *glyph)
     466{
     467        errno_t rc;
     468        riff_rchunk_t rorck;
     469        size_t nread;
     470
     471        rc = riff_rchunk_match(parent, CKID_gror, &rorck);
     472        if (rc != EOK)
     473                return rc;
     474
     475        rc = riff_read(&rorck, (void *) &glyph->rect, sizeof(glyph->rect),
     476            &nread);
     477        if (rc != EOK || nread != sizeof(glyph->rect))
     478                return EIO;
     479
     480        rc = riff_read(&rorck, (void *) &glyph->origin, sizeof(glyph->origin),
     481            &nread);
     482        if (rc != EOK || nread != sizeof(glyph->origin))
     483                return EIO;
     484
     485        rc = riff_rchunk_end(&rorck);
     486        if (rc != EOK)
     487                return rc;
     488
     489        return EOK;
     490}
     491
    379492/** Save glyph rectangle/origin to RIFF TPF file.
    380493 *
     
    408521}
    409522
     523/** Load glyph from RIFF TPF file.
     524 *
     525 * @param font Containing font
     526 * @param parent Parent chunk
     527 * @return EOK on success or an error code
     528 */
     529errno_t gfx_glyph_load(gfx_font_t *font, riff_rchunk_t *parent)
     530{
     531        errno_t rc;
     532        gfx_glyph_metrics_t metrics;
     533        gfx_glyph_t *glyph = NULL;
     534        riff_rchunk_t glyphck;
     535
     536        rc = riff_rchunk_list_match(parent, LTYPE_glph, &glyphck);
     537        if (rc != EOK)
     538                goto error;
     539
     540        rc = gfx_glyph_metrics_load(&glyphck, &metrics);
     541        if (rc != EOK)
     542                goto error;
     543
     544        rc = gfx_glyph_create(font, &metrics, &glyph);
     545        if (rc != EOK)
     546                goto error;
     547
     548        rc = gfx_glyph_patterns_load(&glyphck, glyph);
     549        if (rc != EOK)
     550                goto error;
     551
     552        rc = gfx_glyph_rectangle_origin_load(&glyphck, glyph);
     553        if (rc != EOK)
     554                goto error;
     555
     556        rc = riff_rchunk_end(&glyphck);
     557        if (rc != EOK)
     558                goto error;
     559
     560        return EOK;
     561error:
     562        if (glyph != NULL)
     563                gfx_glyph_destroy(glyph);
     564        return rc;
     565}
     566
    410567/** Save glyph into RIFF TPF file.
    411568 *
    412569 * @param glyph Glyph
    413570 * @param riffw RIFF writer
     571 * @return EOK on success or an error code
    414572 */
    415573errno_t gfx_glyph_save(gfx_glyph_t *glyph, riffw_t *riffw)
  • uspace/lib/gfxfont/src/typeface.c

    raaf962e6 rea459d4  
    3838#include <errno.h>
    3939#include <gfx/bitmap.h>
     40#include <gfx/font.h>
    4041#include <gfx/glyph.h>
    4142#include <gfx/typeface.h>
     
    7879void gfx_typeface_destroy(gfx_typeface_t *tface)
    7980{
     81        gfx_font_info_t *finfo;
     82
     83        if (tface->riffr != NULL)
     84                (void) riff_rclose(tface->riffr);
     85
     86        finfo = gfx_typeface_first_font(tface);
     87        while (finfo != NULL) {
     88                if (finfo->font != NULL)
     89                        gfx_font_close(finfo->font);
     90                list_remove(&finfo->lfonts);
     91                free(finfo);
     92
     93                finfo = gfx_typeface_first_font(tface);
     94        }
     95
    8096        free(tface);
    8197}
     
    111127
    112128        return list_get_instance(link, gfx_font_info_t, lfonts);
     129}
     130
     131/** Open typeface from a TPF file.
     132 *
     133 * @param gc Graphic context
     134 * @param fname File name
     135 * @param rtface Place to store pointer to open typeface
     136 * @return EOK on success or an error code
     137 */
     138errno_t gfx_typeface_open(gfx_context_t *gc, const char *fname,
     139    gfx_typeface_t **rtface)
     140{
     141        riffr_t *riffr = NULL;
     142        gfx_typeface_t *tface = NULL;
     143        errno_t rc;
     144        riff_rchunk_t riffck;
     145        uint32_t format;
     146
     147        rc = gfx_typeface_create(gc, &tface);
     148        if (rc != EOK)
     149                goto error;
     150
     151        rc = riff_ropen(fname, &riffck, &riffr);
     152        if (rc != EOK)
     153                goto error;
     154
     155        rc = riff_read_uint32(&riffck, &format);
     156        if (rc != EOK)
     157                goto error;
     158
     159        if (format != FORM_TPFC) {
     160                rc = ENOTSUP;
     161                goto error;
     162        }
     163
     164        while (true) {
     165                rc = gfx_font_info_load(tface, &riffck);
     166                if (rc == ENOENT)
     167                        break;
     168
     169                if (rc != EOK)
     170                        goto error;
     171        }
     172
     173        rc = riff_rchunk_end(&riffck);
     174        if (rc != EOK)
     175                goto error;
     176
     177        tface->riffr = riffr;
     178        *rtface = tface;
     179        return EOK;
     180error:
     181        if (riffr != NULL)
     182                riff_rclose(riffr);
     183        if (tface != NULL)
     184                gfx_typeface_destroy(tface);
     185        return rc;
     186}
     187
     188/** Make sure all typeface fonts are loaded.
     189 *
     190 * @param tface Typeface
     191 * @return EOK on success or an error code
     192 */
     193static errno_t gfx_typeface_loadin(gfx_typeface_t *tface)
     194{
     195        gfx_font_t *font;
     196        gfx_font_info_t *finfo;
     197        errno_t rc;
     198
     199        finfo = gfx_typeface_first_font(tface);
     200        while (finfo != NULL) {
     201                /* Open font to make sure it is loaded */
     202                rc = gfx_font_open(finfo, &font);
     203                if (rc != EOK)
     204                        return rc;
     205
     206                /* Don't need this anymore */
     207                (void)font;
     208
     209                finfo = gfx_typeface_next_font(finfo);
     210        }
     211
     212        return EOK;
    113213}
    114214
     
    125225        gfx_font_info_t *finfo;
    126226        riff_wchunk_t riffck;
     227
     228        /*
     229         * Make sure all fonts are loaded before writing (in case
     230         * we are writing into our original backing file).
     231         */
     232        rc = gfx_typeface_loadin(tface);
     233        if (rc != EOK)
     234                return rc;
    127235
    128236        rc = riff_wopen(fname, &riffw);
  • uspace/lib/gfxfont/test/main.c

    raaf962e6 rea459d4  
    3434PCUT_IMPORT(glyph);
    3535PCUT_IMPORT(glyph_bmp);
     36PCUT_IMPORT(tpf);
    3637PCUT_IMPORT(typeface);
    3738
  • uspace/lib/riff/include/riff/chunk.h

    raaf962e6 rea459d4  
    5555extern errno_t riff_rchunk_list_match(riff_rchunk_t *, riff_ltype_t,
    5656    riff_rchunk_t *);
     57extern errno_t riff_rchunk_seek(riff_rchunk_t *, long, int);
    5758extern errno_t riff_rchunk_end(riff_rchunk_t *);
    5859extern errno_t riff_read(riff_rchunk_t *, void *, size_t, size_t *);
  • uspace/lib/riff/src/chunk.c

    raaf962e6 rea459d4  
    393393}
    394394
     395/** Seek to position in chunk.
     396 *
     397 * @param rchunk RIFF chunk
     398 * @param offset Offset
     399 * @param whence SEEK_SET, SEEK_CUR or SEEK_END
     400 * @return EOK on success or an error code
     401 */
     402errno_t riff_rchunk_seek(riff_rchunk_t *rchunk, long offset, int whence)
     403{
     404        long pos;
     405        long dest;
     406        int rv;
     407
     408        switch (whence) {
     409        case SEEK_SET:
     410                dest = rchunk->ckstart + offset;
     411                break;
     412        case SEEK_END:
     413                dest = rchunk->ckstart + rchunk->cksize + offset;
     414                break;
     415        case SEEK_CUR:
     416                pos = ftell(rchunk->riffr->f);
     417                if (pos < 0)
     418                        return EIO;
     419                dest = pos + offset;
     420                break;
     421        default:
     422                return EINVAL;
     423        }
     424
     425        if (dest < rchunk->ckstart || dest > rchunk->ckstart + rchunk->cksize)
     426                return ELIMIT;
     427
     428        rv = fseek(rchunk->riffr->f, dest, SEEK_SET);
     429        if (rv < 0)
     430                return EIO;
     431
     432        return EOK;
     433}
     434
    395435/** Return chunk data size.
    396436 *
     
    431471/** Finish reading RIFF chunk.
    432472 *
    433  * Seek to the first byte after end of chunk.
     473 * Seek to the first byte after end of chunk. It is allowed, though,
     474 * to return to the chunk later, e.g. using riff_rchunk_seek(@a rchunk, ..).
    434475 *
    435476 * @param rchunk Chunk structure
     
    444485                return EIO;
    445486
    446         rchunk->riffr = NULL;
    447487        return EOK;
    448488}
  • uspace/lib/riff/test/chunk.c

    raaf962e6 rea459d4  
    544544}
    545545
     546/** Seek back to different positions in a chunk */
     547PCUT_TEST(rchunk_seek)
     548{
     549        char fname[L_tmpnam];
     550        char *p;
     551        riffw_t *rw;
     552        riffr_t *rr;
     553        riff_wchunk_t wriffck;
     554        riff_wchunk_t wdatack;
     555        riff_rchunk_t rriffck;
     556        riff_rchunk_t rdatack;
     557        uint32_t rword;
     558        errno_t rc;
     559
     560        p = tmpnam(fname);
     561        PCUT_ASSERT_NOT_NULL(p);
     562
     563        /* Write RIFF file */
     564
     565        rc = riff_wopen(p, &rw);
     566        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     567        PCUT_ASSERT_NOT_NULL(rw);
     568
     569        rc = riff_wchunk_start(rw, CKID_RIFF, &wriffck);
     570        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     571
     572        /* Write data chunk */
     573
     574        rc = riff_wchunk_start(rw, CKID_dat1, &wdatack);
     575        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     576
     577        rc = riff_write_uint32(rw, 1);
     578        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     579
     580        rc = riff_write_uint32(rw, 2);
     581        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     582
     583        rc = riff_write_uint32(rw, 3);
     584        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     585
     586        rc = riff_write_uint32(rw, 4);
     587        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     588
     589        rc = riff_wchunk_end(rw, &wdatack);
     590        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     591
     592        rc = riff_wchunk_end(rw, &wriffck);
     593        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     594
     595        rc = riff_wclose(rw);
     596        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     597
     598        /* Read back RIFF file */
     599
     600        rc = riff_ropen(p, &rriffck, &rr);
     601        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     602        PCUT_ASSERT_NOT_NULL(rr);
     603
     604        PCUT_ASSERT_INT_EQUALS(CKID_RIFF, rriffck.ckid);
     605
     606        /* Read data chunk */
     607
     608        rc = riff_rchunk_start(&rriffck, &rdatack);
     609        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     610        PCUT_ASSERT_INT_EQUALS(CKID_dat1, rdatack.ckid);
     611
     612        rc = riff_read_uint32(&rdatack, &rword);
     613        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     614        PCUT_ASSERT_INT_EQUALS(1, rword);
     615
     616        rc = riff_rchunk_end(&rdatack);
     617        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     618
     619        /* Try reading first word of data chunk again */
     620
     621        rc = riff_rchunk_seek(&rdatack, 0, SEEK_SET);
     622        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     623
     624        rc = riff_read_uint32(&rdatack, &rword);
     625        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     626        PCUT_ASSERT_INT_EQUALS(1, rword);
     627
     628        /* Try reading last word of data chunk */
     629
     630        rc = riff_rchunk_seek(&rdatack, -4, SEEK_END);
     631        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     632
     633        rc = riff_read_uint32(&rdatack, &rword);
     634        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     635        PCUT_ASSERT_INT_EQUALS(4, rword);
     636
     637        /* Try reading previous word of data chunk */
     638
     639        rc = riff_rchunk_seek(&rdatack, -8, SEEK_CUR);
     640        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     641
     642        rc = riff_read_uint32(&rdatack, &rword);
     643        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     644        PCUT_ASSERT_INT_EQUALS(3, rword);
     645
     646        rc = riff_rclose(rr);
     647        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     648
     649        (void) remove(p);
     650}
     651
    546652PCUT_EXPORT(chunk);
Note: See TracChangeset for help on using the changeset viewer.