HelenOS sources
This source file includes following definitions.
- gfx_glyph_metrics_init
- gfx_glyph_create
- gfx_glyph_destroy
- gfx_glyph_get_metrics
- gfx_glyph_set_metrics
- gfx_glyph_set_pattern
- gfx_glyph_clear_pattern
- gfx_glyph_matches
- gfx_glyph_first_pattern
- gfx_glyph_next_pattern
- gfx_glyph_pattern_str
- gfx_glyph_render
- gfx_glyph_transfer
- gfx_glyph_metrics_load
- gfx_glyph_metrics_save
- gfx_glyph_patterns_load
- gfx_glyph_patterns_save
- gfx_glyph_rectangle_origin_load
- gfx_glyph_rectangle_origin_save
- gfx_glyph_load
- gfx_glyph_save
#include <assert.h>
#include <byteorder.h>
#include <errno.h>
#include <gfx/bitmap.h>
#include <gfx/font.h>
#include <gfx/glyph.h>
#include <io/pixelmap.h>
#include <mem.h>
#include <stdlib.h>
#include <str.h>
#include "../private/font.h"
#include "../private/glyph.h"
#include "../private/tpf_file.h"
void gfx_glyph_metrics_init(gfx_glyph_metrics_t *metrics)
{
memset(metrics, 0, sizeof(gfx_glyph_metrics_t));
}
errno_t gfx_glyph_create(gfx_font_t *font, gfx_glyph_metrics_t *metrics,
gfx_glyph_t **rglyph)
{
gfx_glyph_t *glyph;
gfx_glyph_t *last;
errno_t rc;
glyph = calloc(1, sizeof(gfx_glyph_t));
if (glyph == NULL)
return ENOMEM;
glyph->font = font;
rc = gfx_glyph_set_metrics(glyph, metrics);
if (rc != EOK) {
assert(rc == EINVAL);
free(glyph);
return rc;
}
last = gfx_font_last_glyph(font);
glyph->metrics = *metrics;
list_append(&glyph->lglyphs, &glyph->font->glyphs);
list_initialize(&glyph->patterns);
if (last != NULL)
glyph->rect.p0.x = last->rect.p1.x;
else
glyph->rect.p0.x = 0;
glyph->rect.p0.y = 0;
glyph->rect.p1.x = glyph->rect.p0.x;
glyph->rect.p1.y = glyph->rect.p1.y;
glyph->origin.x = glyph->rect.p0.x;
glyph->origin.y = glyph->rect.p0.y;
*rglyph = glyph;
return EOK;
}
void gfx_glyph_destroy(gfx_glyph_t *glyph)
{
list_remove(&glyph->lglyphs);
free(glyph);
}
void gfx_glyph_get_metrics(gfx_glyph_t *glyph, gfx_glyph_metrics_t *metrics)
{
*metrics = glyph->metrics;
}
errno_t gfx_glyph_set_metrics(gfx_glyph_t *glyph, gfx_glyph_metrics_t *metrics)
{
glyph->metrics = *metrics;
return EOK;
}
errno_t gfx_glyph_set_pattern(gfx_glyph_t *glyph, const char *pattern)
{
gfx_glyph_pattern_t *pat;
pat = gfx_glyph_first_pattern(glyph);
while (pat != NULL) {
if (str_cmp(pat->text, pattern) == 0) {
return EOK;
}
pat = gfx_glyph_next_pattern(pat);
}
pat = calloc(1, sizeof(gfx_glyph_pattern_t));
if (pat == NULL)
return ENOMEM;
pat->glyph = glyph;
pat->text = str_dup(pattern);
if (pat->text == NULL) {
free(pat);
return ENOMEM;
}
list_append(&pat->lpatterns, &glyph->patterns);
return EOK;
}
void gfx_glyph_clear_pattern(gfx_glyph_t *glyph, const char *pattern)
{
gfx_glyph_pattern_t *pat;
pat = gfx_glyph_first_pattern(glyph);
while (pat != NULL) {
if (str_cmp(pat->text, pattern) == 0) {
list_remove(&pat->lpatterns);
free(pat->text);
free(pat);
return;
}
pat = gfx_glyph_next_pattern(pat);
}
}
bool gfx_glyph_matches(gfx_glyph_t *glyph, const char *str, size_t *rsize)
{
gfx_glyph_pattern_t *pat;
pat = gfx_glyph_first_pattern(glyph);
while (pat != NULL) {
if (str_test_prefix(str, pat->text)) {
*rsize = str_size(pat->text);
return true;
}
pat = gfx_glyph_next_pattern(pat);
}
return false;
}
gfx_glyph_pattern_t *gfx_glyph_first_pattern(gfx_glyph_t *glyph)
{
link_t *link;
link = list_first(&glyph->patterns);
if (link == NULL)
return NULL;
return list_get_instance(link, gfx_glyph_pattern_t, lpatterns);
}
gfx_glyph_pattern_t *gfx_glyph_next_pattern(gfx_glyph_pattern_t *cur)
{
link_t *link;
link = list_next(&cur->lpatterns, &cur->glyph->patterns);
if (link == NULL)
return NULL;
return list_get_instance(link, gfx_glyph_pattern_t, lpatterns);
}
const char *gfx_glyph_pattern_str(gfx_glyph_pattern_t *pattern)
{
return pattern->text;
}
errno_t gfx_glyph_render(gfx_glyph_t *glyph, gfx_coord2_t *pos)
{
gfx_coord2_t offs;
gfx_coord2_subtract(pos, &glyph->origin, &offs);
return gfx_bitmap_render(glyph->font->bitmap, &glyph->rect, &offs);
}
errno_t gfx_glyph_transfer(gfx_glyph_t *glyph, gfx_coord_t offs,
gfx_bitmap_t *dbmp, gfx_rect_t *dbrect)
{
pixelmap_t smap;
pixelmap_t dmap;
gfx_bitmap_alloc_t salloc;
gfx_bitmap_alloc_t dalloc;
gfx_rect_t drect;
gfx_coord_t x, y;
gfx_coord2_t off2;
pixel_t pixel;
errno_t rc;
rc = gfx_bitmap_get_alloc(glyph->font->bitmap, &salloc);
if (rc != EOK)
return rc;
rc = gfx_bitmap_get_alloc(dbmp, &dalloc);
if (rc != EOK)
return rc;
smap.width = glyph->font->rect.p1.x;
smap.height = glyph->font->rect.p1.y;
smap.data = salloc.pixels;
dmap.width = dbrect->p1.x;
dmap.height = dbrect->p1.y;
dmap.data = dalloc.pixels;
off2.x = offs;
off2.y = 0;
gfx_rect_translate(&off2, &glyph->rect, &drect);
assert(gfx_rect_is_inside(&drect, dbrect));
for (y = drect.p0.y; y < drect.p1.y; y++) {
for (x = drect.p0.x; x < drect.p1.x; x++) {
pixel = pixelmap_get_pixel(&smap, x - offs, y);
pixelmap_put_pixel(&dmap, x, y, pixel);
}
}
return EOK;
}
static errno_t gfx_glyph_metrics_load(riff_rchunk_t *parent,
gfx_glyph_metrics_t *metrics)
{
errno_t rc;
riff_rchunk_t mtrck;
tpf_glyph_metrics_t tmetrics;
size_t nread;
rc = riff_rchunk_match(parent, CKID_gmtr, &mtrck);
if (rc != EOK)
return rc;
rc = riff_read(&mtrck, (void *) &tmetrics, sizeof(tmetrics), &nread);
if (rc != EOK || nread != sizeof(tmetrics))
return EIO;
rc = riff_rchunk_end(&mtrck);
if (rc != EOK)
return rc;
metrics->advance = uint16_t_le2host(tmetrics.advance);
return EOK;
}
static errno_t gfx_glyph_metrics_save(gfx_glyph_metrics_t *metrics,
riffw_t *riffw)
{
errno_t rc;
tpf_glyph_metrics_t tmetrics;
riff_wchunk_t mtrck;
tmetrics.advance = host2uint16_t_le(metrics->advance);
rc = riff_wchunk_start(riffw, CKID_gmtr, &mtrck);
if (rc != EOK)
return rc;
rc = riff_write(riffw, (void *) &tmetrics, sizeof(tmetrics));
if (rc != EOK)
return rc;
rc = riff_wchunk_end(riffw, &mtrck);
if (rc != EOK)
return rc;
return EOK;
}
static errno_t gfx_glyph_patterns_load(riff_rchunk_t *parent,
gfx_glyph_t *glyph)
{
errno_t rc;
riff_rchunk_t patck;
uint32_t cksize;
size_t i;
size_t nread;
char *buf = NULL;
rc = riff_rchunk_match(parent, CKID_gpat, &patck);
if (rc != EOK)
goto error;
cksize = riff_rchunk_size(&patck);
buf = malloc(cksize);
if (buf == NULL) {
rc = ENOMEM;
goto error;
}
rc = riff_read(&patck, buf, cksize, &nread);
if (rc != EOK || nread != cksize)
goto error;
i = 0;
while (i < cksize) {
rc = gfx_glyph_set_pattern(glyph, &buf[i]);
if (rc != EOK)
goto error;
i += str_size(&buf[i]) + 1;
}
rc = riff_rchunk_end(&patck);
if (rc != EOK)
goto error;
free(buf);
return EOK;
error:
if (buf != NULL)
free(buf);
return rc;
}
static errno_t gfx_glyph_patterns_save(gfx_glyph_t *glyph, riffw_t *riffw)
{
errno_t rc;
riff_wchunk_t patck;
gfx_glyph_pattern_t *pat;
const char *str;
rc = riff_wchunk_start(riffw, CKID_gpat, &patck);
if (rc != EOK)
return rc;
pat = gfx_glyph_first_pattern(glyph);
while (pat != NULL) {
str = gfx_glyph_pattern_str(pat);
rc = riff_write(riffw, (void *) str, 1 + str_size(str));
if (rc != EOK)
return rc;
pat = gfx_glyph_next_pattern(pat);
}
rc = riff_wchunk_end(riffw, &patck);
if (rc != EOK)
return rc;
return EOK;
}
static errno_t gfx_glyph_rectangle_origin_load(riff_rchunk_t *parent,
gfx_glyph_t *glyph)
{
errno_t rc;
tpf_glyph_ror_t tror;
riff_rchunk_t rorck;
size_t nread;
rc = riff_rchunk_match(parent, CKID_gror, &rorck);
if (rc != EOK)
return rc;
rc = riff_read(&rorck, (void *) &tror, sizeof(tror),
&nread);
if (rc != EOK || nread != sizeof(tror))
return EIO;
rc = riff_rchunk_end(&rorck);
if (rc != EOK)
return rc;
glyph->rect.p0.x = uint32_t_le2host(tror.p0x);
glyph->rect.p0.y = uint32_t_le2host(tror.p0y);
glyph->rect.p1.x = uint32_t_le2host(tror.p1x);
glyph->rect.p1.y = uint32_t_le2host(tror.p1y);
glyph->origin.x = uint32_t_le2host(tror.orig_x);
glyph->origin.y = uint32_t_le2host(tror.orig_y);
return EOK;
}
static errno_t gfx_glyph_rectangle_origin_save(gfx_glyph_t *glyph,
riffw_t *riffw)
{
errno_t rc;
tpf_glyph_ror_t tror;
riff_wchunk_t rorck;
tror.p0x = host2uint32_t_le(glyph->rect.p0.x);
tror.p0y = host2uint32_t_le(glyph->rect.p0.y);
tror.p1x = host2uint32_t_le(glyph->rect.p1.x);
tror.p1y = host2uint32_t_le(glyph->rect.p1.y);
tror.orig_x = host2uint32_t_le(glyph->origin.x);
tror.orig_y = host2uint32_t_le(glyph->origin.y);
rc = riff_wchunk_start(riffw, CKID_gror, &rorck);
if (rc != EOK)
return rc;
rc = riff_write(riffw, (void *) &tror, sizeof(tror));
if (rc != EOK)
return rc;
rc = riff_wchunk_end(riffw, &rorck);
if (rc != EOK)
return rc;
return EOK;
}
errno_t gfx_glyph_load(gfx_font_t *font, riff_rchunk_t *parent)
{
errno_t rc;
gfx_glyph_metrics_t metrics;
gfx_glyph_t *glyph = NULL;
riff_rchunk_t glyphck;
rc = riff_rchunk_list_match(parent, LTYPE_glph, &glyphck);
if (rc != EOK)
goto error;
rc = gfx_glyph_metrics_load(&glyphck, &metrics);
if (rc != EOK)
goto error;
rc = gfx_glyph_create(font, &metrics, &glyph);
if (rc != EOK)
goto error;
rc = gfx_glyph_patterns_load(&glyphck, glyph);
if (rc != EOK)
goto error;
rc = gfx_glyph_rectangle_origin_load(&glyphck, glyph);
if (rc != EOK)
goto error;
rc = riff_rchunk_end(&glyphck);
if (rc != EOK)
goto error;
return EOK;
error:
if (glyph != NULL)
gfx_glyph_destroy(glyph);
return rc;
}
errno_t gfx_glyph_save(gfx_glyph_t *glyph, riffw_t *riffw)
{
errno_t rc;
riff_wchunk_t glyphck;
rc = riff_wchunk_start(riffw, CKID_LIST, &glyphck);
if (rc != EOK)
return rc;
rc = riff_write_uint32(riffw, LTYPE_glph);
if (rc != EOK)
return rc;
rc = gfx_glyph_metrics_save(&glyph->metrics, riffw);
if (rc != EOK)
return rc;
rc = gfx_glyph_patterns_save(glyph, riffw);
if (rc != EOK)
return rc;
rc = gfx_glyph_rectangle_origin_save(glyph, riffw);
if (rc != EOK)
return rc;
rc = riff_wchunk_end(riffw, &glyphck);
if (rc != EOK)
return rc;
return EOK;
}
HelenOS homepage, sources at GitHub