Changeset 5713e5f in mainline for uspace/lib/draw


Ignore:
Timestamp:
2014-09-01T19:17:55Z (11 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
Location:
uspace/lib/draw
Files:
4 added
9 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/draw/Makefile

    ra4666a9 r5713e5f  
    3737        cursor/embedded.c \
    3838        font/embedded.c \
     39        font/bitmap_backend.c \
     40        font/pcf.c \
    3941        gfx/font-8x16.c \
    4042        gfx/cursor-11x18.c \
  • 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
  • uspace/lib/draw/font.h

    ra4666a9 r5713e5f  
    11/*
    22 * Copyright (c) 2012 Petr Koupy
     3 * Copyright (c) 2014 Martin Sucha
    34 * All rights reserved.
    45 *
     
    4546typedef struct drawctx drawctx_t;
    4647
    47 typedef enum {
    48         FONT_DECODER_EMBEDDED
    49 } font_decoder_type_t;
     48typedef int metric_t;
    5049
    5150typedef struct {
    52         void (*init)(char *, uint16_t *, void **);
    53         uint16_t (*resolve)(const wchar_t, void *);
    54         surface_t *(*render)(uint16_t, uint16_t);
     51        /* Horizontal distance between origin and left side of the glyph */
     52        metric_t left_side_bearing;
     53       
     54        /* Width of the actual glyph drawn */
     55        metric_t width;
     56       
     57        /* Horizontal distance between right side of the glyph and origin
     58           of the next glyph */
     59        metric_t right_side_bearing;
     60       
     61        /* Vertical distance between baseline and top of the glyph
     62           (positive to top) */
     63        metric_t ascender;
     64       
     65        /* Height of the actual glyph drawn */
     66        metric_t height;
     67} glyph_metrics_t;
     68
     69static inline metric_t glyph_metrics_get_descender(glyph_metrics_t *gm)
     70{
     71        return gm->height - gm->ascender;
     72}
     73
     74static inline metric_t glyph_metrics_get_advancement(glyph_metrics_t *gm)
     75{
     76        return gm->left_side_bearing + gm->width + gm->right_side_bearing;
     77}
     78
     79typedef struct {
     80        /* Distance between top of the line and baseline */
     81        metric_t ascender;
     82       
     83        /* Distance between baseline and bottom of the line */
     84        metric_t descender;
     85       
     86        /* Distance between bottom of the line and top of the next line */
     87        metric_t leading;
     88} font_metrics_t;
     89
     90typedef uint32_t glyph_id_t;
     91
     92typedef struct {
     93        int (*get_font_metrics)(void *, font_metrics_t *);
     94        int (*resolve_glyph)(void *, wchar_t, glyph_id_t *);
     95        int (*get_glyph_metrics)(void *, glyph_id_t, glyph_metrics_t *);
     96        int (*render_glyph)(void *, drawctx_t *, source_t *, sysarg_t,
     97            sysarg_t, glyph_id_t);
    5598        void (*release)(void *);
    56 } font_decoder_t;
     99} font_backend_t;
    57100
    58 typedef struct font {
    59         uint16_t points;
    60         uint16_t glyph_count;
    61         surface_t **glyphs;
    62         font_decoder_t *decoder;
    63         void *decoder_data;
     101typedef struct {
     102        font_backend_t *backend;
     103        void *backend_data;
    64104} font_t;
    65105
    66 extern void font_init(font_t *, font_decoder_type_t, char *, uint16_t);
     106extern font_t *font_create(font_backend_t *, void *);
     107extern int font_get_metrics(font_t *, font_metrics_t *);
     108extern int font_resolve_glyph(font_t *, wchar_t, glyph_id_t *);
     109extern int font_get_glyph_metrics(font_t *, glyph_id_t, glyph_metrics_t *);
     110extern int font_render_glyph(font_t *, drawctx_t *, source_t *,
     111    sysarg_t, sysarg_t, glyph_id_t);
    67112extern void font_release(font_t *);
    68113
    69 extern void font_get_box(font_t *, char *, sysarg_t *, sysarg_t *);
    70 extern void font_draw_text(font_t *, drawctx_t *, source_t *, const char *,
     114extern int font_get_box(font_t *, char *, sysarg_t *, sysarg_t *);
     115extern int font_draw_text(font_t *, drawctx_t *, source_t *, const char *,
    71116    sysarg_t, sysarg_t);
    72117
  • uspace/lib/draw/font/embedded.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 <sys/types.h>
    3838#include <malloc.h>
     39#include <errno.h>
    3940
    4041#include "../gfx/font-8x16.h"
    4142#include "embedded.h"
    4243#include "../drawctx.h"
     44#include "bitmap_backend.h"
    4345
    44 static void fde_init(char *path, uint16_t *glyph_count, void **data)
     46static int fde_resolve_glyph(void *unused, const wchar_t chr,
     47    glyph_id_t *glyph_id)
    4548{
    46         assert(glyph_count);
    47         assert(data);
    48 
    49         (*glyph_count) = FONT_GLYPHS;
    50         (*data) = NULL;
     49        bool found = false;
     50        uint16_t glyph = fb_font_glyph(chr, &found);
     51        if (!found)
     52                return ENOENT;
     53       
     54        *glyph_id = glyph;
     55        return EOK;
    5156}
    5257
    53 static uint16_t fde_resolve(const wchar_t chr, void *data)
     58static int fde_load_glyph_surface(void *unused, glyph_id_t glyph_id,
     59    surface_t **out_surface)
    5460{
    55         return fb_font_glyph(chr);
     61        surface_t *surface = surface_create(FONT_WIDTH, FONT_SCANLINES, NULL, 0);
     62        if (!surface)
     63                return ENOMEM;
     64       
     65        for (unsigned int y = 0; y < FONT_SCANLINES; ++y) {
     66                for (unsigned int x = 0; x < FONT_WIDTH; ++x) {
     67                        pixel_t p = (fb_font[glyph_id][y] & (1 << (7 - x))) ?
     68                            PIXEL(255, 0, 0, 0) : PIXEL(0, 0, 0, 0);
     69                        surface_put_pixel(surface, x, y, p);
     70                }
     71        }
     72       
     73        *out_surface = surface;
     74        return EOK;
    5675}
    5776
    58 static surface_t *fde_render(uint16_t glyph, uint16_t points)
     77static int fde_load_glyph_metrics(void *unused, glyph_id_t glyph_id,
     78    glyph_metrics_t *gm)
    5979{
    60         surface_t *template = surface_create(FONT_WIDTH, FONT_SCANLINES, NULL, 0);
    61         if (!template) {
    62                 return NULL;
    63         }
    64         for (unsigned int y = 0; y < FONT_SCANLINES; ++y) {
    65                 for (unsigned int x = 0; x < FONT_WIDTH; ++x) {
    66                         pixel_t p = (fb_font[glyph][y] & (1 << (7 - x))) ?
    67                             PIXEL(255, 0, 0, 0) : PIXEL(0, 0, 0, 0);
    68                         surface_put_pixel(template, x, y, p);
    69                 }
    70         }
    71 
    72         source_t source;
    73         source_init(&source);
    74         source_set_texture(&source, template, false);
    75 
    76         transform_t transform;
    77         transform_identity(&transform);
    78         if (points != FONT_SCANLINES) {
    79                 double ratio = ((double) points) / ((double) FONT_SCANLINES);
    80                 transform_scale(&transform, ratio, ratio);
    81                 source_set_transform(&source, transform);
    82         }
    83 
    84         double width = FONT_WIDTH;
    85         double height = FONT_SCANLINES;
    86         transform_apply_linear(&transform, &width, &height);
    87         surface_t *result =
    88             surface_create((sysarg_t) (width + 0.5), (sysarg_t) (height + 0.5), NULL, 0);
    89         if (!result) {
    90                 surface_destroy(template);
    91                 return NULL;
    92         }
    93 
    94         drawctx_t context;
    95         drawctx_init(&context, result);
    96         drawctx_set_source(&context, &source);
    97         drawctx_transfer(&context, 0, 0,
    98             (sysarg_t) (width + 0.5), (sysarg_t) (height + 0.5));
    99 
    100         surface_destroy(template);
    101 
    102         return result;
     80        /* This is simple monospaced font, so fill this data statically */
     81        gm->left_side_bearing = 0;
     82        gm->width = FONT_WIDTH;
     83        gm->right_side_bearing = 0;
     84        gm->ascender = FONT_ASCENDER;
     85        gm->height = FONT_SCANLINES;
     86       
     87        return EOK;
    10388}
    10489
     
    10893}
    10994
    110 font_decoder_t fd_embedded = {
    111         .init = fde_init,
    112         .resolve = fde_resolve,
    113         .render = fde_render,
     95bitmap_font_decoder_t fd_embedded = {
     96        .resolve_glyph = fde_resolve_glyph,
     97        .load_glyph_surface = fde_load_glyph_surface,
     98        .load_glyph_metrics = fde_load_glyph_metrics,
    11499        .release = fde_release
    115100};
    116101
     102font_metrics_t font_metrics = {
     103        .ascender = FONT_ASCENDER,
     104        .descender = (FONT_SCANLINES - FONT_ASCENDER),
     105        .leading = 0
     106};
     107
     108int embedded_font_create(font_t **font, uint16_t points)
     109{
     110        return bitmap_font_create(&fd_embedded, NULL, FONT_GLYPHS, font_metrics,
     111            points, font);
     112}
     113
    117114/** @}
    118115 */
  • uspace/lib/draw/font/embedded.h

    ra4666a9 r5713e5f  
    3939#include "../font.h"
    4040
    41 extern font_decoder_t fd_embedded;
     41extern int embedded_font_create(font_t **, uint16_t points);
    4242
    4343#endif
  • uspace/lib/draw/gfx/font-8x16.c

    ra4666a9 r5713e5f  
    4444 * mark glyph if no specific glyph exists.
    4545 *
     46 * If found is not null, indicate whether the glyph was found or not.
     47 *
    4648 */
    47 uint16_t fb_font_glyph(const wchar_t ch)
     49uint16_t fb_font_glyph(const wchar_t ch, bool *found)
    4850{
     51        if (found)
     52                *found = true;
     53       
    4954        if (ch == 0x0000)
    5055                return 0;
     
    361366        if (ch == 0xfeff)
    362367                return 2896;
     368       
     369        if (found)
     370                *found = false;
    363371       
    364372        return 2898;
  • uspace/lib/draw/gfx/font-8x16.h

    ra4666a9 r5713e5f  
    3737
    3838#include <sys/types.h>
     39#include <stdbool.h>
    3940
    4041#define FONT_GLYPHS     2899
    4142#define FONT_WIDTH      8
    4243#define FONT_SCANLINES  16
     44#define FONT_ASCENDER   12
    4345
    44 extern uint16_t fb_font_glyph(const wchar_t);
     46extern uint16_t fb_font_glyph(const wchar_t, bool *);
    4547extern uint8_t fb_font[FONT_GLYPHS][FONT_SCANLINES];
    4648
  • uspace/lib/draw/source.c

    ra4666a9 r5713e5f  
    4545        source->color = PIXEL(0, 0, 0, 0);
    4646        source->texture = NULL;
    47         source->texture_tile = false;
     47        source->texture_extend = PIXELMAP_EXTEND_TRANSPARENT_BLACK;
    4848
    4949        source->alpha = PIXEL(255, 0, 0, 0);
    5050        source->mask = NULL;
    51         source->mask_tile = false;
     51        source->mask_extend = PIXELMAP_EXTEND_TRANSPARENT_BLACK;
    5252}
    5353
     
    7373}
    7474
    75 void source_set_texture(source_t *source, surface_t *texture, bool tile)
     75void source_set_texture(source_t *source, surface_t *texture,
     76    pixelmap_extend_t extend)
    7677{
    7778        source->texture = texture;
    78         source->texture_tile = tile;
     79        source->texture_extend = extend;
    7980}
    8081
     
    8485}
    8586
    86 void source_set_mask(source_t *source, surface_t *mask, bool tile)
     87void source_set_mask(source_t *source, surface_t *mask,
     88    pixelmap_extend_t extend)
    8789{
    8890        source->mask = mask;
    89         source->mask_tile = tile;
     91        source->mask_extend = extend;
    9092}
    9193
     
    9597            (source->alpha == (pixel_t) PIXEL(255, 0, 0, 0)) &&
    9698            (source->texture != NULL) &&
    97             (source->texture_tile == false) &&
     99            (source->texture_extend == PIXELMAP_EXTEND_TRANSPARENT_BLACK) &&
    98100            (transform_is_fast(&source->transform)));
    99101}
     
    120122                mask_pix = source->filter(
    121123                    surface_pixmap_access(source->mask),
    122                     x, y, source->mask_tile);
     124                    x, y, source->mask_extend);
    123125        } else {
    124126                mask_pix = source->alpha;
     
    133135                texture_pix = source->filter(
    134136                    surface_pixmap_access(source->texture),
    135                     x, y, source->texture_tile);
     137                    x, y, source->texture_extend);
    136138        } else {
    137139                texture_pix = source->color;
  • uspace/lib/draw/source.h

    ra4666a9 r5713e5f  
    4242#include <transform.h>
    4343#include <filter.h>
     44#include <io/pixelmap.h>
    4445
    4546#include "surface.h"
     
    5152        pixel_t color;
    5253        surface_t *texture;
    53         bool texture_tile;
     54        pixelmap_extend_t texture_extend;
    5455
    5556        pixel_t alpha;
    5657        surface_t *mask;
    57         bool mask_tile;
     58        pixelmap_extend_t mask_extend;
    5859} source_t;
    5960
     
    6667
    6768extern void source_set_color(source_t *, pixel_t);
    68 extern void source_set_texture(source_t *, surface_t *, bool);
     69extern void source_set_texture(source_t *, surface_t *, pixelmap_extend_t);
    6970
    7071extern void source_set_alpha(source_t *, pixel_t);
    71 extern void source_set_mask(source_t *, surface_t *, bool);
     72extern void source_set_mask(source_t *, surface_t *, pixelmap_extend_t);
    7273
    7374extern bool source_is_fast(source_t *);
Note: See TracChangeset for help on using the changeset viewer.