Changeset 2cc1ec0 in mainline for uspace/lib/draw/font.c


Ignore:
Timestamp:
2014-08-27T21:23:01Z (10 years ago)
Author:
Martin Sucha <sucha14@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
a9763c6
Parents:
613d644
Message:

Refactor drawing of fonts into multiple layers.

This will need further work to split glyph resolution
process to separate functions in order to support ligatures,
addition of kerning support, separate text layout functions,
etc.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/draw/font.c

    r613d644 r2cc1ec0  
    11/*
    22 * Copyright (c) 2012 Petr Koupy
     3 * Copyright (c) 2014 Martin Sucha
    34 * All rights reserved.
    45 *
     
    3435 */
    3536
    36 #include <assert.h>
    3737#include <malloc.h>
     38#include <errno.h>
     39#include <str.h>
    3840
    3941#include "font.h"
     
    4143#include "drawctx.h"
    4244
    43 void font_init(font_t *font, font_decoder_type_t decoder, char *path, uint16_t points)
     45font_t *font_create(font_backend_t *backend, void *backend_data)
    4446{
    45         font->points = points;
    46 
    47         switch (decoder) {
    48         case FONT_DECODER_EMBEDDED:
    49                 font->decoder = &fd_embedded;
    50                 break;
    51         default:
    52                 font->decoder = NULL;
    53                 break;
    54         }
    55 
    56         if (font->decoder) {
    57                 font->decoder->init(path, &font->glyph_count, &font->decoder_data);
    58 
    59                 if (font->glyph_count > 0) {
    60                         font->glyphs = (surface_t **) malloc(sizeof(surface_t *) * font->glyph_count);
    61                 } else {
    62                         font->glyphs = NULL;
    63                 }
    64 
    65                 if (font->glyphs) {
    66                         for (size_t i = 0; i < font->glyph_count; ++i) {
    67                                 font->glyphs[i] = NULL;
    68                         }
    69                 } else {
    70                         font->glyph_count = 0;
    71                 }
    72         } else {
    73                 font->glyph_count = 0;
    74                 font->glyphs = NULL;
    75                 font->decoder_data = NULL;
    76         }
     47        font_t *font = malloc(sizeof(font_t));
     48        if (font == NULL)
     49                return NULL;
     50       
     51        font->backend = backend;
     52        font->backend_data = backend_data;
     53       
     54        return font;
    7755}
    7856
    7957void font_release(font_t *font)
    8058{
    81         if (font->glyphs) {
    82                 for (size_t i = 0; i < font->glyph_count; ++i) {
    83                         if (font->glyphs[i]) {
    84                                 surface_destroy(font->glyphs[i]);
     59        font->backend->release(font->backend_data);
     60}
     61
     62int font_get_metrics(font_t *font, font_metrics_t *metrics) {
     63        return font->backend->get_font_metrics(font->backend_data, metrics);
     64}
     65
     66int font_resolve_glyph(font_t *font, wchar_t c, glyph_id_t *glyph_id) {
     67        return font->backend->resolve_glyph(font->backend_data, c, glyph_id);
     68}
     69
     70int font_get_glyph_metrics(font_t *font, glyph_id_t glyph_id,
     71    glyph_metrics_t *glyph_metrics)
     72{
     73        return font->backend->get_glyph_metrics(font->backend_data,
     74            glyph_id, glyph_metrics);
     75}
     76
     77int font_render_glyph(font_t *font, drawctx_t *context, source_t *source,
     78    sysarg_t x, sysarg_t y, glyph_id_t glyph_id)
     79{
     80        return font->backend->render_glyph(font->backend_data, context, source,
     81            x, y, glyph_id);
     82}
     83
     84/* TODO this is bad interface */
     85int font_get_box(font_t *font, char *text, sysarg_t *width, sysarg_t *height)
     86{
     87        font_metrics_t fm;
     88        int rc = font_get_metrics(font, &fm);
     89        if (rc != EOK)
     90                return rc;
     91
     92        native_t x = 0;
     93
     94        size_t off = 0;
     95        while (true) {
     96                wchar_t c = str_decode(text, &off, STR_NO_LIMIT);
     97                if (c == 0)
     98                        break;
     99               
     100                glyph_id_t glyph_id;
     101                rc = font_resolve_glyph(font, c, &glyph_id);
     102                if (rc != EOK) {
     103                        int rc2 = font_resolve_glyph(font, U_SPECIAL, &glyph_id);
     104                        if (rc2 != EOK) {
     105                                return rc;
    85106                        }
    86107                }
    87                 free(font->glyphs);
     108               
     109                glyph_metrics_t glyph_metrics;
     110                rc = font_get_glyph_metrics(font, glyph_id, &glyph_metrics);
     111                if (rc != EOK)
     112                        return rc;
     113               
     114                x += glyph_metrics_get_advancement(&glyph_metrics);
    88115        }
    89        
    90         if (font->decoder) {
    91                 font->decoder->release(font->decoder_data);
    92         }
     116
     117        *width = x;
     118        *height = fm.ascender + fm.descender;
     119        return EOK;
    93120}
    94121
    95 void font_get_box(font_t *font, char *text, sysarg_t *width, sysarg_t *height)
     122/* TODO this is bad interface */
     123int font_draw_text(font_t *font, drawctx_t *context, source_t *source,
     124    const char *text, sysarg_t sx, sysarg_t sy)
    96125{
    97         assert(width);
    98         assert(height);
    99 
    100         (*width) = 0;
    101         (*height) = 0;
    102 
    103         if (!text) {
    104                 return;
    105         }
    106 
    107         while (*text) {
    108                 uint16_t glyph_idx = font->decoder->resolve(*text, font->decoder_data);
    109                 if (glyph_idx < font->glyph_count) {
    110                         if (!font->glyphs[glyph_idx]) {
    111                                 font->glyphs[glyph_idx] =
    112                                     font->decoder->render(glyph_idx, font->points);
    113                         }
    114 
    115                         surface_t *glyph = font->glyphs[glyph_idx];
    116                         if (glyph) {
    117                                 sysarg_t w;
    118                                 sysarg_t h;
    119                                 surface_get_resolution(glyph, &w, &h);
    120                                 (*width) += w;
    121                                 (*height) = (*height) < h ? h : (*height);
    122                         }
    123                 }
    124                 ++text;
    125         }
    126 }
    127 
    128 void font_draw_text(font_t *font, drawctx_t *context, source_t *source,
    129     const char *text, sysarg_t x, sysarg_t y)
    130 {
    131         assert(context);
    132         assert(source);
    133 
    134126        drawctx_save(context);
    135127        drawctx_set_compose(context, compose_over);
    136128
    137         while (*text) {
    138                 uint16_t glyph_idx = font->decoder->resolve(*text, font->decoder_data);
    139                 if (glyph_idx < font->glyph_count) {
    140                         if (!font->glyphs[glyph_idx]) {
    141                                 font->glyphs[glyph_idx] =
    142                                     font->decoder->render(glyph_idx, font->points);
    143                         }
     129        font_metrics_t fm;
     130        int rc = font_get_metrics(font, &fm);
     131        if (rc != EOK)
     132                return rc;
    144133
    145                         surface_t *glyph = font->glyphs[glyph_idx];
    146                         if (glyph) {
    147                                 sysarg_t w;
    148                                 sysarg_t h;
    149                                 surface_get_resolution(glyph, &w, &h);
     134        native_t baseline = sy + fm.ascender;
     135        native_t x = sx;
    150136
    151                                 transform_t transform;
    152                                 transform_identity(&transform);
    153                                 transform_translate(&transform, x, y);
    154                                 source_set_transform(source, transform);
    155                                 source_set_mask(source, glyph, false);
    156                                 drawctx_transfer(context, x, y, w, h);
    157 
    158                                 x += w;
     137        size_t off = 0;
     138        while (true) {
     139                wchar_t c = str_decode(text, &off, STR_NO_LIMIT);
     140                if (c == 0)
     141                        break;
     142               
     143                glyph_id_t glyph_id;
     144                rc = font_resolve_glyph(font, c, &glyph_id);
     145                if (rc != EOK) {
     146                        int rc2 = font_resolve_glyph(font, U_SPECIAL, &glyph_id);
     147                        if (rc2 != EOK) {
     148                                return rc;
    159149                        }
    160150                }
    161                 ++text;
     151               
     152                glyph_metrics_t glyph_metrics;
     153                rc = font_get_glyph_metrics(font, glyph_id, &glyph_metrics);
     154                if (rc != EOK)
     155                        return rc;
     156
     157                rc = font_render_glyph(font, context, source, x, baseline,
     158                    glyph_id);
     159                if (rc != EOK)
     160                        return rc;
     161
     162                x += glyph_metrics_get_advancement(&glyph_metrics);
     163
    162164        }
    163165
    164166        drawctx_restore(context);
    165167        source_set_mask(source, NULL, false);
     168
     169        return EOK;
    166170}
    167171
Note: See TracChangeset for help on using the changeset viewer.