Changeset 5713e5f in mainline for uspace/lib/draw/font.c


Ignore:
Timestamp:
2014-09-01T19:17:55Z (10 years ago)
Author:
Martin Sucha <sucha14@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
21365c0
Parents:
a4666a9 (diff), 00ddb40 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge improvements in the graphics stack.

  • Support for drawing proportional fonts (although no actual font file included yet)
  • Implementation of bilinear filter
File:
1 edited

Legend:

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

    ra4666a9 r5713e5f  
    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.