diff --git a/configs/stm3210e-eval/nxterm/defconfig b/configs/stm3210e-eval/nxterm/defconfig index ffb7dc3e2d..bbd18a5c01 100644 --- a/configs/stm3210e-eval/nxterm/defconfig +++ b/configs/stm3210e-eval/nxterm/defconfig @@ -666,7 +666,7 @@ CONFIG_SIG_SIGWORK=17 # POSIX Message Queue Options # CONFIG_PREALLOC_MQ_MSGS=8 -CONFIG_MQ_MAXMSGSIZE=32 +CONFIG_MQ_MAXMSGSIZE=64 # CONFIG_MODULE is not set # @@ -999,7 +999,7 @@ CONFIG_NXTERM=y # NxTerm Output Text/Graphics Options # CONFIG_NXTERM_BPP=16 -CONFIG_NXTERM_CURSORCHAR=137 +CONFIG_NXTERM_CURSORCHAR=95 CONFIG_NXTERM_MXCHARS=256 CONFIG_NXTERM_CACHESIZE=32 CONFIG_NXTERM_LINESEPARATION=0 diff --git a/configs/stm3240g-eval/nxterm/defconfig b/configs/stm3240g-eval/nxterm/defconfig index a83753f652..3b6215dd53 100644 --- a/configs/stm3240g-eval/nxterm/defconfig +++ b/configs/stm3240g-eval/nxterm/defconfig @@ -713,7 +713,7 @@ CONFIG_SIG_SIGWORK=17 # POSIX Message Queue Options # CONFIG_PREALLOC_MQ_MSGS=8 -CONFIG_MQ_MAXMSGSIZE=32 +CONFIG_MQ_MAXMSGSIZE=64 # CONFIG_MODULE is not set # @@ -1189,7 +1189,7 @@ CONFIG_NXTERM=y # NxTerm Output Text/Graphics Options # CONFIG_NXTERM_BPP=16 -CONFIG_NXTERM_CURSORCHAR=137 +CONFIG_NXTERM_CURSORCHAR=95 CONFIG_NXTERM_MXCHARS=256 CONFIG_NXTERM_CACHESIZE=32 CONFIG_NXTERM_LINESEPARATION=0 diff --git a/graphics/nxterm/nxterm.h b/graphics/nxterm/nxterm.h index 326a2ed5f9..49eded0c88 100644 --- a/graphics/nxterm/nxterm.h +++ b/graphics/nxterm/nxterm.h @@ -1,7 +1,7 @@ /**************************************************************************** * nuttx/graphics/nxterm/nxterm.h * - * Copyright (C) 2012, 2014 Gregory Nutt. All rights reserved. + * Copyright (C) 2012, 2014, 2017 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -33,8 +33,8 @@ * ****************************************************************************/ -#ifndef __GRAPHICS_NXTERM_NXTERM_INTERNAL_H -#define __GRAPHICS_NXTERM_NXTERM_INTERNAL_H +#ifndef __GRAPHICS_NXTERM_NXTERM_H +#define __GRAPHICS_NXTERM_NXTERM_H /**************************************************************************** * Included Files @@ -61,10 +61,6 @@ #define BMFLAGS_NOGLYPH (1 << 0) /* No glyph available, use space */ #define BM_ISSPACE(bm) (((bm)->flags & BMFLAGS_NOGLYPH) != 0) -/* Sizes and maximums */ - -#define MAX_USECNT 255 /* Limit to range of a uint8_t */ - /* Device path formats */ #define NX_DEVNAME_FORMAT "/dev/nxterm%d" @@ -81,6 +77,7 @@ /**************************************************************************** * Public Types ****************************************************************************/ + /* Identifies the state of the VT100 escape sequence processing */ enum nxterm_vt100state_e @@ -111,18 +108,6 @@ struct nxterm_operations_s unsigned int stride); }; -/* Describes one cached glyph bitmap */ - -struct nxterm_glyph_s -{ - uint8_t code; /* Character code */ - uint8_t height; /* Height of this glyph (in rows) */ - uint8_t width; /* Width of this glyph (in pixels) */ - uint8_t stride; /* Width of the glyph row (in bytes) */ - uint8_t usecnt; /* Use count */ - FAR uint8_t *bitmap; /* Allocated bitmap memory */ -}; - /* Describes on character on the display */ struct nxterm_bitmap_s @@ -138,8 +123,7 @@ struct nxterm_state_s { FAR const struct nxterm_operations_s *ops; /* Window operations */ FAR void *handle; /* The window handle */ - FAR struct nxterm_window_s wndo; /* Describes the window and font */ - NXHANDLE font; /* The current font handle */ + FAR struct nxterm_window_s wndo; /* Describes the window and font */ sem_t exclsem; /* Forces mutually exclusive access */ #ifdef CONFIG_DEBUG_FEATURES pid_t holder; /* Deadlock avoidance */ @@ -151,7 +135,6 @@ struct nxterm_state_s uint8_t fheight; /* Max height of a font in pixels */ uint8_t fwidth; /* Max width of a font in pixels */ uint8_t spwidth; /* The width of a space */ - uint8_t maxglyphs; /* Size of the glyph[] array */ uint16_t maxchars; /* Size of the bm[] array */ uint16_t nchars; /* Number of chars in the bm[] array */ @@ -165,13 +148,10 @@ struct nxterm_state_s /* Font cache data storage */ + FCACHE fcache; /* Font cache handle */ struct nxterm_bitmap_s cursor; struct nxterm_bitmap_s bm[CONFIG_NXTERM_MXCHARS]; - /* Glyph cache data storage */ - - struct nxterm_glyph_s glyph[CONFIG_NXTERM_CACHESIZE]; - /* Keyboard input support */ #ifdef CONFIG_NXTERM_NXKBDIN @@ -235,8 +215,8 @@ enum nxterm_vt100state_e nxterm_vt100(FAR struct nxterm_state_s *priv, char ch); void nxterm_home(FAR struct nxterm_state_s *priv); void nxterm_newline(FAR struct nxterm_state_s *priv); -FAR const struct nxterm_bitmap_s *nxterm_addchar(NXHANDLE hfont, - FAR struct nxterm_state_s *priv, uint8_t ch); +FAR const struct nxterm_bitmap_s *nxterm_addchar(FAR struct nxterm_state_s *priv, + uint8_t ch); int nxterm_hidechar(FAR struct nxterm_state_s *priv, FAR const struct nxterm_bitmap_s *bm); int nxterm_backspace(FAR struct nxterm_state_s *priv); @@ -251,4 +231,4 @@ void nxterm_hidecursor(FAR struct nxterm_state_s *priv); void nxterm_scroll(FAR struct nxterm_state_s *priv, int scrollheight); -#endif /* __GRAPHICS_NXTERM_NXTERM_INTERNAL_H */ +#endif /* __GRAPHICS_NXTERM_NXTERM_H */ diff --git a/graphics/nxterm/nxterm_font.c b/graphics/nxterm/nxterm_font.c index b3e95d220d..5002845989 100644 --- a/graphics/nxterm/nxterm_font.c +++ b/graphics/nxterm/nxterm_font.c @@ -48,294 +48,26 @@ #include "nxterm.h" -/**************************************************************************** - * Pre-processor Definitions - ****************************************************************************/ - -/* Select renderer -- Some additional logic would be required to support - * pixel depths that are not directly addressable (1,2,4, and 24). - */ - -#if CONFIG_NXTERM_BPP == 1 -# define RENDERER nxf_convert_1bpp -#elif CONFIG_NXTERM_BPP == 2 -# define RENDERER nxf_convert_2bpp -#elif CONFIG_NXTERM_BPP == 4 -# define RENDERER nxf_convert_4bpp -#elif CONFIG_NXTERM_BPP == 8 -# define RENDERER nxf_convert_8bpp -#elif CONFIG_NXTERM_BPP == 16 -# define RENDERER nxf_convert_16bpp -#elif CONFIG_NXTERM_BPP == 24 -# define RENDERER nxf_convert_24bpp -#elif CONFIG_NXTERM_BPP == 32 -# define RENDERER nxf_convert_32bpp -#else -# error "Unsupported CONFIG_NXTERM_BPP" -#endif - -/**************************************************************************** - * Private Types - ****************************************************************************/ - -/**************************************************************************** - * Private Function Prototypes - ****************************************************************************/ - -/**************************************************************************** - * Private Data - ****************************************************************************/ - -/**************************************************************************** - * Public Data - ****************************************************************************/ - /**************************************************************************** * Private Functions ****************************************************************************/ -/**************************************************************************** - * Name: nxterm_freeglyph - ****************************************************************************/ - -static void nxterm_freeglyph(FAR struct nxterm_glyph_s *glyph) -{ - if (glyph->bitmap) - { - kmm_free(glyph->bitmap); - } - memset(glyph, 0, sizeof(struct nxterm_glyph_s)); -} - -/**************************************************************************** - * Name: nxterm_allocglyph - ****************************************************************************/ - -static inline FAR struct nxterm_glyph_s * -nxterm_allocglyph(FAR struct nxterm_state_s *priv) -{ - FAR struct nxterm_glyph_s *glyph = NULL; - FAR struct nxterm_glyph_s *luglyph = NULL; - uint8_t luusecnt; - int i; - - /* Search through the glyph cache looking for an unused glyph. Also, keep - * track of the least used glyph as well. We need that if we have to replace - * a glyph in the cache. - */ - - for (i = 0; i < priv->maxglyphs; i++) - { - /* Is this glyph in use? */ - - glyph = &priv->glyph[i]; - if (!glyph->usecnt) - { - /* No.. return this glyph with a use count of one */ - - glyph->usecnt = 1; - return glyph; - } - - /* Yes.. check for the least recently used */ - - if (!luglyph || glyph->usecnt < luglyph->usecnt) - { - luglyph = glyph; - } - } - - /* If we get here, the glyph cache is full. We replace the least used - * glyph with the one we need now. (luglyph can't be NULL). - */ - - luusecnt = luglyph->usecnt; - nxterm_freeglyph(luglyph); - - /* But lets decrement all of the usecnts so that the new one one be so - * far behind in the counts as the older ones. - */ - - if (luusecnt > 1) - { - uint8_t decr = luusecnt - 1; - - for (i = 0; i < priv->maxglyphs; i++) - { - /* Is this glyph in use? */ - - glyph = &priv->glyph[i]; - if (glyph->usecnt > decr) - { - glyph->usecnt -= decr; - } - } - } - - /* Then return the least used glyph */ - - luglyph->usecnt = 1; - return luglyph; -} - -/**************************************************************************** - * Name: nxterm_findglyph - ****************************************************************************/ - -static FAR struct nxterm_glyph_s * -nxterm_findglyph(FAR struct nxterm_state_s *priv, uint8_t ch) -{ - int i; - - /* First, try to find the glyph in the cache of pre-rendered glyphs */ - - for (i = 0; i < priv->maxglyphs; i++) - { - FAR struct nxterm_glyph_s *glyph = &priv->glyph[i]; - if (glyph->usecnt > 0 && glyph->code == ch) - { - /* Increment the use count (unless it is already at the max) */ - - if (glyph->usecnt < MAX_USECNT) - { - glyph->usecnt++; - } - - /* And return the glyph that we found */ - - return glyph; - } - } - return NULL; -} - -/**************************************************************************** - * Name: nxterm_renderglyph - ****************************************************************************/ - -static inline FAR struct nxterm_glyph_s * -nxterm_renderglyph(FAR struct nxterm_state_s *priv, - FAR const struct nx_fontbitmap_s *fbm, uint8_t ch) -{ - FAR struct nxterm_glyph_s *glyph = NULL; - FAR nxgl_mxpixel_t *ptr; -#if CONFIG_NXTERM_BPP < 8 - nxgl_mxpixel_t pixel; -#endif - int bmsize; - int row; - int col; - int ret; - - /* Allocate the glyph (always succeeds) */ - - glyph = nxterm_allocglyph(priv); - glyph->code = ch; - - /* Get the dimensions of the glyph */ - - glyph->width = fbm->metric.width + fbm->metric.xoffset; - glyph->height = fbm->metric.height + fbm->metric.yoffset; - - /* Get the physical width of the glyph in bytes */ - - glyph->stride = (glyph->width * CONFIG_NXTERM_BPP + 7) / 8; - - /* Allocate memory to hold the glyph with its offsets */ - - bmsize = glyph->stride * glyph->height; - glyph->bitmap = (FAR uint8_t *)kmm_malloc(bmsize); - - if (glyph->bitmap) - { - /* Initialize the glyph memory to the background color using the - * hard-coded bits-per-pixel (BPP). - * - * TODO: The rest of NX is configured to support multiple devices - * with differing BPP. They logic should be extended to support - * differing BPP's as well. - */ - -#if CONFIG_NXTERM_BPP < 8 - pixel = priv->wndo.wcolor[0]; - -# if CONFIG_NXTERM_BPP == 1 - - /* Pack 1-bit pixels into a 2-bits */ - - pixel &= 0x01; - pixel = (pixel) << 1 | pixel; - -# endif -# if CONFIG_NXTERM_BPP < 4 - - /* Pack 2-bit pixels into a nibble */ - - pixel &= 0x03; - pixel = (pixel) << 2 | pixel; - -# endif - - /* Pack 4-bit nibbles into a byte */ - - pixel &= 0x0f; - pixel = (pixel) << 4 | pixel; - - ptr = (FAR nxgl_mxpixel_t *)glyph->bitmap; - for (row = 0; row < glyph->height; row++) - { - for (col = 0; col < glyph->stride; col++) - { - /* Transfer the packed bytes into the buffer */ - - *ptr++ = pixel; - } - } - -#elif CONFIG_NXTERM_BPP == 24 -# error "Additional logic is needed here for 24bpp support" - -#else /* CONFIG_NXTERM_BPP = {8,16,32} */ - - ptr = (FAR nxgl_mxpixel_t *)glyph->bitmap; - for (row = 0; row < glyph->height; row++) - { - /* Just copy the color value into the glyph memory */ - - for (col = 0; col < glyph->width; col++) - { - *ptr++ = priv->wndo.wcolor[0]; - } - } -#endif - - /* Then render the glyph into the allocated memory */ - - ret = RENDERER((FAR nxgl_mxpixel_t *)glyph->bitmap, - glyph->height, glyph->width, glyph->stride, - fbm, priv->wndo.fcolor[0]); - if (ret < 0) - { - /* Actually, the RENDERER never returns a failure */ - - gerr("ERROR: nxterm_renderglyph: RENDERER failed\n"); - nxterm_freeglyph(glyph); - glyph = NULL; - } - } - - return glyph; -} - /**************************************************************************** * Name: nxterm_fontsize ****************************************************************************/ -static int nxterm_fontsize(NXHANDLE hfont, uint8_t ch, FAR struct nxgl_size_s *size) +static int nxterm_fontsize(FAR struct nxterm_state_s *priv, uint8_t ch, + FAR struct nxgl_size_s *size) { FAR const struct nx_fontbitmap_s *fbm; + NXHANDLE hfont; - /* No, it is not cached... Does the code map to a font? */ + /* Get the handle of the font managed by the font cache */ + + hfont = nxf_cache_getfonthandle(priv->fcache); + DEBUGASSERT(hfont != NULL); + + /* Does the character code map to a font? */ fbm = nxf_getbitmap(hfont, ch); if (fbm) @@ -347,40 +79,7 @@ static int nxterm_fontsize(NXHANDLE hfont, uint8_t ch, FAR struct nxgl_size_s *s return OK; } - return ERROR; -} - -/**************************************************************************** - * Name: nxterm_getglyph - ****************************************************************************/ - -static FAR struct nxterm_glyph_s * -nxterm_getglyph(NXHANDLE hfont, FAR struct nxterm_state_s *priv, uint8_t ch) -{ - FAR struct nxterm_glyph_s *glyph; - FAR const struct nx_fontbitmap_s *fbm; - - /* First, try to find the glyph in the cache of pre-rendered glyphs */ - - glyph = nxterm_findglyph(priv, ch); - if (glyph) - { - /* We found it in the cache .. return the cached glyph */ - - return glyph; - } - - /* No, it is not cached... Does the code map to a font? */ - - fbm = nxf_getbitmap(hfont, ch); - if (fbm) - { - /* Yes.. render the glyph */ - - glyph = nxterm_renderglyph(priv, fbm, ch); - } - - return glyph; + return -ENOENT; } /**************************************************************************** @@ -397,10 +96,10 @@ nxterm_getglyph(NXHANDLE hfont, FAR struct nxterm_state_s *priv, uint8_t ch) ****************************************************************************/ FAR const struct nxterm_bitmap_s * -nxterm_addchar(NXHANDLE hfont, FAR struct nxterm_state_s *priv, uint8_t ch) +nxterm_addchar(FAR struct nxterm_state_s *priv, uint8_t ch) { FAR struct nxterm_bitmap_s *bm = NULL; - FAR struct nxterm_glyph_s *glyph; + FAR const struct nxfonts_glyph_s *glyph; /* Is there space for another character on the display? */ @@ -416,7 +115,7 @@ nxterm_addchar(NXHANDLE hfont, FAR struct nxterm_state_s *priv, uint8_t ch) /* Find (or create) the matching glyph */ - glyph = nxterm_getglyph(hfont, priv, ch); + glyph = nxf_cache_getglyph(priv->fcache, ch); if (!glyph) { /* No, there is no font for this code. Just mark this as a space. */ @@ -449,6 +148,7 @@ nxterm_addchar(NXHANDLE hfont, FAR struct nxterm_state_s *priv, uint8_t ch) * Erase a character from the window. * ****************************************************************************/ + int nxterm_hidechar(FAR struct nxterm_state_s *priv, FAR const struct nxterm_bitmap_s *bm) { @@ -461,7 +161,7 @@ int nxterm_hidechar(FAR struct nxterm_state_s *priv, * modification is required (not an error). */ - ret = nxterm_fontsize(priv->font, bm->code, &fsize); + ret = nxterm_fontsize(priv, bm->code, &fsize); if (ret < 0) { /* It was rendered as a space. */ @@ -572,10 +272,10 @@ void nxterm_newline(FAR struct nxterm_state_s *priv) ****************************************************************************/ void nxterm_fillchar(FAR struct nxterm_state_s *priv, - FAR const struct nxgl_rect_s *rect, - FAR const struct nxterm_bitmap_s *bm) + FAR const struct nxgl_rect_s *rect, + FAR const struct nxterm_bitmap_s *bm) { - FAR struct nxterm_glyph_s *glyph; + FAR const struct nxfonts_glyph_s *glyph; struct nxgl_rect_s bounds; struct nxgl_rect_s intersection; struct nxgl_size_s fsize; @@ -590,7 +290,7 @@ void nxterm_fillchar(FAR struct nxterm_state_s *priv, /* Get the size of the font glyph (which may not have been created yet) */ - ret = nxterm_fontsize(priv->font, bm->code, &fsize); + ret = nxterm_fontsize(priv, bm->code, &fsize); if (ret < 0) { /* This would mean that there is no bitmap for the character code and @@ -632,7 +332,7 @@ void nxterm_fillchar(FAR struct nxterm_state_s *priv, /* Find (or create) the glyph that goes with this font */ - glyph = nxterm_getglyph(priv->font, priv, bm->code); + glyph = nxf_cache_getglyph(priv->fcache, bm->code); if (!glyph) { /* Shouldn't happen */ @@ -648,4 +348,3 @@ void nxterm_fillchar(FAR struct nxterm_state_s *priv, DEBUGASSERT(ret >= 0); } } - diff --git a/graphics/nxterm/nxterm_putc.c b/graphics/nxterm/nxterm_putc.c index b0479404ca..1aea8559ec 100644 --- a/graphics/nxterm/nxterm_putc.c +++ b/graphics/nxterm/nxterm_putc.c @@ -142,7 +142,7 @@ void nxterm_putc(FAR struct nxterm_state_s *priv, uint8_t ch) * display. */ - bm = nxterm_addchar(priv->font, priv, ch); + bm = nxterm_addchar(priv, ch); if (bm) { nxterm_fillchar(priv, NULL, bm); diff --git a/graphics/nxterm/nxterm_register.c b/graphics/nxterm/nxterm_register.c index d1d99d16a4..a83e84cffc 100644 --- a/graphics/nxterm/nxterm_register.c +++ b/graphics/nxterm/nxterm_register.c @@ -1,7 +1,7 @@ /**************************************************************************** * nuttx/graphics/nxterm/nxterm_register.c * - * Copyright (C) 2012, 2016 Gregory Nutt. All rights reserved. + * Copyright (C) 2012, 2016-2017 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -66,7 +66,9 @@ FAR struct nxterm_state_s * FAR const struct nxterm_operations_s *ops, int minor) { FAR struct nxterm_state_s *priv; + FAR const struct nx_font_s *fontset; char devname[NX_DEVNAME_SIZE]; + NXHANDLE hfont; int ret; DEBUGASSERT(handle && wndo && ops && (unsigned)minor < 256); @@ -101,22 +103,33 @@ FAR struct nxterm_state_s * sem_setprotocol(&priv->waitsem, SEM_PRIO_NONE); #endif - /* Select the font */ + /* Connect to the font cache for the configured font characteristics */ - priv->font = nxf_getfonthandle(wndo->fontid); - if (!priv->font) + priv->fcache = nxf_cache_connect(wndo->fontid, wndo->fcolor[0], + wndo->wcolor[0], CONFIG_NXTERM_BPP, + CONFIG_NXTERM_CACHESIZE); + if (priv->fcache == NULL) { - gerr("ERROR: Failed to get font ID %d: %d\n", wndo->fontid, errno); + gerr("ERROR: Failed to connect to font cache for font ID %d: %d\n", + wndo->fontid, errno); goto errout; } - FAR const struct nx_font_s *fontset; + /* Get the handle of the font managed by the font cache */ + + hfont = nxf_cache_getfonthandle(priv->fcache); + if (hfont == NULL) + { + gerr("ERROR: Failed to get handlr for font ID %d: %d\n", + wndo->fontid, errno); + goto errout; + } /* Get information about the font set being used and save this in the * state structure */ - fontset = nxf_getfontset(priv->font); + fontset = nxf_getfontset(hfont); priv->fheight = fontset->mxheight; priv->fwidth = fontset->mxwidth; priv->spwidth = fontset->spwidth; @@ -125,10 +138,6 @@ FAR struct nxterm_state_s * priv->maxchars = CONFIG_NXTERM_MXCHARS; - /* Set up the font glyph bitmap cache */ - - priv->maxglyphs = CONFIG_NXTERM_CACHESIZE; - /* Set the initial display position */ nxterm_home(priv); @@ -146,6 +155,7 @@ FAR struct nxterm_state_s * { gerr("ERROR: Failed to register %s\n", devname); } + return (NXTERM)priv; errout: diff --git a/graphics/nxterm/nxterm_unregister.c b/graphics/nxterm/nxterm_unregister.c index e51e44c173..06ad464881 100644 --- a/graphics/nxterm/nxterm_unregister.c +++ b/graphics/nxterm/nxterm_unregister.c @@ -50,22 +50,6 @@ #include "nxterm.h" -/**************************************************************************** - * Pre-processor Definitions - ****************************************************************************/ - -/**************************************************************************** - * Private Function Prototypes - ****************************************************************************/ - -/**************************************************************************** - * Private Data - ****************************************************************************/ - -/**************************************************************************** - * Private Functions - ****************************************************************************/ - /**************************************************************************** * Public Functions ****************************************************************************/ @@ -89,7 +73,6 @@ void nxterm_unregister(NXTERM handle) { FAR struct nxterm_state_s *priv; char devname[NX_DEVNAME_SIZE]; - int i; DEBUGASSERT(handle); @@ -101,16 +84,9 @@ void nxterm_unregister(NXTERM handle) sem_destroy(&priv->waitsem); #endif - /* Free all allocated glyph bitmap */ + /* Free the font cache */ - for (i = 0; i < CONFIG_NXTERM_CACHESIZE; i++) - { - FAR struct nxterm_glyph_s *glyph = &priv->glyph[i]; - if (glyph->bitmap) - { - kmm_free(glyph->bitmap); - } - } + nxf_cache_disconnect(priv->fcache); /* Unregister the driver */ diff --git a/include/nuttx/nx/nxfonts.h b/include/nuttx/nx/nxfonts.h index aca51a0874..525a5f56a2 100644 --- a/include/nuttx/nx/nxfonts.h +++ b/include/nuttx/nx/nxfonts.h @@ -51,6 +51,7 @@ * Pre-processor definitions ****************************************************************************/ +/* Font Definitions *********************************************************/ /* Select the default font. If no fonts are selected, then a compilation * error is likely down the road. */ @@ -206,6 +207,7 @@ * Public Types ****************************************************************************/ +/* Font Types ***************************************************************/ /* Font IDs */ enum nx_fontid_e @@ -453,6 +455,25 @@ struct nx_fontpackage_s #endif }; +/* Font Cache ***************************************************************/ +/* Opaque handle used to reference a font cache */ + +typedef FAR void *FCACHE; + +/* Describes one cached font glyph */ + +struct nxfonts_glyph_s +{ + FAR struct nxfonts_glyph_s *flink; /* Implements a singly linked list */ + uint8_t code; /* Character code */ + uint8_t height; /* Height of this glyph (in rows) */ + uint8_t width; /* Width of this glyph (in pixels) */ + uint8_t stride; /* Width of the glyph row (in bytes) */ + FAR uint8_t bitmap[1]; /* Bitmap memory, actual size varies */ +}; + +#define SIZEOF_NXFONTS_GLYPH_S(b) (sizeof(struct nxfonts_glyph_s) + (b) - 1) + /**************************************************************************** * Public Data ****************************************************************************/ @@ -480,6 +501,9 @@ extern "C" * Input Parameters: * fontid: Identifies the font set to get * + * Returned Value: + * One success, a non-NULL font handle is returned. + * ****************************************************************************/ NXHANDLE nxf_getfonthandle(enum nx_fontid_e fontid); @@ -564,6 +588,87 @@ int nxf_convert_32bpp(FAR uint32_t *dest, uint16_t height, FAR const struct nx_fontbitmap_s *bm, nxgl_mxpixel_t color); +/**************************************************************************** + * Name: nxf_cache_connect + * + * Description: + * Create a new font cache for the provided 'fontid'. If the cache + * already, then just increment a reference count return the handle for + * the existing font cache. + * + * Input Parameters: + * fontid - Identifies the font supported by this cache + * fgcolor - Foreground color + * bgcolor - Background color + * bpp - Bits per pixel + * maxglyphs - Maximum number of glyphs permitted in the cache + * + * Returned value: + * On success a non-NULL handle is returned that then may sequently be + * used with nxf_getglyph() to extract fonts from the font cache. NULL + * returned on any failure with the errno value set to indicate the nature + * of the error. + * + ****************************************************************************/ + +FCACHE nxf_cache_connect(enum nx_fontid_e fontid, + nxgl_mxpixel_t fgcolor, nxgl_mxpixel_t bgcolor, + int bpp, int maxglyph); + +/**************************************************************************** + * Name: nxf_cache_disconnect + * + * Description: + * Decrement the reference count on the font cache and, if the reference + * count goes to zero, free all resources used by the font cache. The + * font handler is invalid upon return in either case. + * + * Input Parameters: + * fhandle - A font cache handler previously returned by nxf_cache_connect(); + * + * Returned value: + * None + * + ****************************************************************************/ + +void nxf_cache_disconnect(FCACHE fhandle); + +/**************************************************************************** + * Name: nxf_cache_getfonthandle + * + * Description: + * Return the handle to the font set used by this instance of the font + * cache. + * + * Input Parameters: + * fhandle - A font cache handle previously returned by nxf_cache_connect(); + * + * Returned value: + * Zero (OK) is returned if the metrics were + * + * Returned Value: + * One success, a non-NULL font handle is returned. + * + ****************************************************************************/ + +NXHANDLE nxf_cache_getfonthandle(FCACHE fhandle); + +/**************************************************************************** + * Name: nxf_cache_getglyph + * + * Description: + * Get the font glyph for the character code 'ch' from the font cache. If + * the glyph for that character code does not exist in the font cache, it + * be rendered. + * + * Returned Value: + * On success, a non-NULL pointer to the rendered glyph in the font cache + * is returned. NULL is returned on any failure. + * + ****************************************************************************/ + +FAR const struct nxfonts_glyph_s *nxf_cache_getglyph(FCACHE fhandle, uint8_t ch); + #undef EXTERN #if defined(__cplusplus) } diff --git a/libc/queue/sq_addfirst.c b/libc/queue/sq_addfirst.c index a00841cfaa..bbc9f26a9c 100644 --- a/libc/queue/sq_addfirst.c +++ b/libc/queue/sq_addfirst.c @@ -58,5 +58,6 @@ void sq_addfirst(FAR sq_entry_t *node, sq_queue_t *queue) { queue->tail = node; } + queue->head = node; } diff --git a/libc/queue/sq_remafter.c b/libc/queue/sq_remafter.c index a3527b7908..34685ae961 100644 --- a/libc/queue/sq_remafter.c +++ b/libc/queue/sq_remafter.c @@ -44,10 +44,10 @@ ****************************************************************************/ /**************************************************************************** - * Name: + * Name: sq_remafter * * Description: - * sq_remafter removes the entry following 'node; from the'queue' Returns + * sq_remafter removes the entry following 'node' from the'queue' Returns * a reference to the removed entry. * ****************************************************************************/ @@ -55,6 +55,7 @@ FAR sq_entry_t *sq_remafter(FAR sq_entry_t *node, sq_queue_t *queue) { FAR sq_entry_t *ret = node->flink; + if (queue->head && ret) { if (queue->tail == ret) diff --git a/libnx/nxfonts/Make.defs b/libnx/nxfonts/Make.defs index 9403f08bdd..fee5f77baa 100644 --- a/libnx/nxfonts/Make.defs +++ b/libnx/nxfonts/Make.defs @@ -37,7 +37,7 @@ ifeq ($(CONFIG_NX),y) -CSRCS += nxfonts_getfont.c +CSRCS += nxfonts_getfont.c nxfonts_cache.c CSRCS += nxfonts_convert_1bpp.c nxfonts_convert_2bpp.c CSRCS += nxfonts_convert_4bpp.c nxfonts_convert_8bpp.c CSRCS += nxfonts_convert_16bpp.c nxfonts_convert_24bpp.c diff --git a/libnx/nxfonts/nxfonts_cache.c b/libnx/nxfonts/nxfonts_cache.c new file mode 100644 index 0000000000..b74df1e0f2 --- /dev/null +++ b/libnx/nxfonts/nxfonts_cache.c @@ -0,0 +1,924 @@ +/**************************************************************************** + * libnx/nxfonts/nxfonts_cache.c + * + * Copyright (C) 2017 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include + +#include "nxcontext.h" + +/**************************************************************************** + * Private Types + ****************************************************************************/ +/* This describes a rendering function */ + +typedef CODE int (*nxf_renderer_t)(FAR nxgl_mxpixel_t *dest, uint16_t height, + uint16_t width, uint16_t stride, + FAR const struct nx_fontbitmap_s *bm, + nxgl_mxpixel_t color); + +/* This structure defines one font cache */ + +struct nxfonts_fcache_s +{ + FAR struct nxfonts_fcache_s *flink; /* Supports a singly linked list */ + NXHANDLE font; /* Font handle associated with fontid */ + sem_t fsem; /* Serializes access to the font cache */ + uint16_t fontid; /* ID of font in this cache */ + int16_t fclients; /* Number of connected clients */ + uint8_t maxglyphs; /* Maximum size of glyph[] array */ + uint8_t nglyphs; /* Current size of glyph[] array */ + uint8_t bpp; /* Bits per pixel */ + nxgl_mxpixel_t fgcolor; /* Foreground color */ + nxgl_mxpixel_t bgcolor; /* Background color */ + nxf_renderer_t renderer; /* Font renderer */ + + /* Glyph cache data storage */ + + FAR struct nxfonts_glyph_s *head; /* Head of the list of glyphs */ + FAR struct nxfonts_glyph_s *tail; /* Tail of the list of glyphs */ +}; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* Head of a list of font caches */ + +static FAR struct nxfonts_fcache_s *g_fcaches; +static sem_t g_cachesem = SEM_INITIALIZER(1); + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxf_list_lock and nxf_list_unlock + * + * Description: + * Get/relinquish exclusive access to the font cache list + * + ****************************************************************************/ + +static void nxf_list_lock(void) +{ + int ret; + + /* Get exclusive access to the font cache */ + + while ((ret = sem_wait(&g_cachesem)) < 0) + { + int errorcode = errno; + DEBUGASSERT(errorcode == EINTR || errorcode == ECANCELED); + UNUSED(errorcode); + } +} + +#define nxf_list_unlock() (sem_post(&g_cachesem)) + +/**************************************************************************** + * Name: nxf_removecache + * + * Description: + * Removes the entry 'glyph' from the font cache. + * + * Assumptions: + * The caller holds the font cache list semaphore. + * + ****************************************************************************/ + +static inline void nxf_removecache(FAR struct nxfonts_fcache_s *fcache, + FAR struct nxfonts_fcache_s *prev) +{ + /* Remove the cache for the list. First check for removal from the head */ + + if (prev == NULL) + { + /* Replace the head with the node following glyph */ + + g_fcaches = fcache->flink; + } + + /* No.. Remove from the head or from mid-list */ + + else + { + prev->flink = fcache->flink; + } + + fcache->flink = NULL; +} + +/**************************************************************************** + * Name: nxf_cache_lock and nxf_cache_unlock + * + * Description: + * Get/relinquish exclusive access to the font cache + * + ****************************************************************************/ + +static void nxf_cache_lock(FAR struct nxfonts_fcache_s *priv) +{ + int ret; + + /* Get exclusive access to the font cache */ + + while ((ret = sem_wait(&priv->fsem)) < 0) + { + int errorcode = errno; + DEBUGASSERT(errorcode == EINTR || errorcode == ECANCELED); + UNUSED(errorcode); + } +} + +#define nxf_cache_unlock(p) (sem_post(&priv->fsem)) + +/**************************************************************************** + * Name: nxf_removeglyph + * + * Description: + * Removes the entry 'glyph' from the font cache. + * + ****************************************************************************/ + +static inline void nxf_removeglyph(FAR struct nxfonts_fcache_s *priv, + FAR struct nxfonts_glyph_s *glyph, + FAR struct nxfonts_glyph_s *prev) +{ + ginfo("fcache=%p glyph=%p\n", priv, glyph); + + /* Remove the glyph for the list. First check for removal from the head */ + + if (prev == NULL) + { + /* Replace the head with the node following glyph */ + + priv->head = glyph->flink; + + /* If there is no node following glyph, then the list is empty */ + + if (priv->head == NULL) + { + priv->tail = NULL; + } + } + + /* Check for removal from the tail (we know that the list cannot become + * empty in either of the next two cases). + */ + + else if (glyph->flink == NULL) + { + priv->tail = prev; + prev->flink = NULL; + } + + /* No.. remove from mid-list */ + + else + { + prev->flink = glyph->flink; + } + + glyph->flink = NULL; + + /* Decrement the count of glyphs in the font cache */ + + DEBUGASSERT(priv->nglyphs > 0); + priv->nglyphs--; +} + +/**************************************************************************** + * Name: nxf_addglyph + * + * Description: + * Add the entry 'glyph' to the head font cache list. + * + ****************************************************************************/ + +static inline void nxf_addglyph(FAR struct nxfonts_fcache_s *priv, + FAR struct nxfonts_glyph_s *glyph) +{ + ginfo("fcache=%p glyph=%p\n", priv, glyph); + + /* Add the glyph to the head of the list */ + + glyph->flink = priv->head; + + if (priv->head == NULL) + { + priv->tail = glyph; + } + + priv->head = glyph; + + /* Increment the count of glyphs in the font cache. */ + + DEBUGASSERT(priv->nglyphs < priv->maxglyphs); + priv->nglyphs++; +} + +/**************************************************************************** + * Name: nxf_findglyph + * + * Description: + * Find the glyph for the specific character 'ch' in the list of pre- + * rendered fonts in the font cache. + * + * This is logically a part of nxf_cache_getglyph(). nxf_cache_getglyph() + * will attempt to find the cached glyph before rendering a new one. So + * this function has two unexpected side-effects: (1) If the font cache + * is full and the font is not found, then the least-recently-used glyph + * is deleted to make space for the new glyph that will be allocated. + * + * (2) If the glyph is found, then it is moved to the head of the list of + * glyphs since it is now the most recently used (leaving the least + * recently used glyph at the tail of the list). + * + * Assumptions: + * The caller has exclusive access to the font cache. + * + ****************************************************************************/ + +static FAR struct nxfonts_glyph_s * +nxf_findglyph(FAR struct nxfonts_fcache_s *priv, uint8_t ch) +{ + FAR struct nxfonts_glyph_s *glyph; + FAR struct nxfonts_glyph_s *prev; + + ginfo("fcache=%p ch=%c (%02x)\n", + priv, (ch >= 32 && ch < 128) ? ch : '.', ch); + + /* Try to find the glyph in the list of pre-rendered glyphs */ + + for (prev = NULL, glyph = priv->head; + glyph != NULL; + prev = glyph, glyph = glyph->flink) + { + /* Check if we found the the glyph for this character */ + + if (glyph->code == ch) + { + /* This is now the most recently used glyph. Move it to the head + * of the list. + */ + + nxf_removeglyph(priv, glyph, prev); + nxf_addglyph(priv, glyph); + + /* And return the glyph that we found */ + + return glyph; + } + + /* Is this the last glyph in the list? Has the cache reached its + * limited for the number of cached fonts? + */ + + if (glyph->flink == NULL && priv->nglyphs >= priv->maxglyphs) + { + /* Yes.. then remove it from the list and free the glyph memory. + * We do this because we have all of the information in hand now + * and we will surely need to have this space later. + */ + + nxf_removeglyph(priv, glyph, prev); + return NULL; + } + } + + return NULL; +} + +/**************************************************************************** + * Name: nxf_fillglyph + * + * Description: + * Fill the glyph memory with the background color + * + ****************************************************************************/ + +static inline void nxf_fillglyph(FAR struct nxfonts_fcache_s *priv, + FAR struct nxfonts_glyph_s *glyph) +{ + int row; + int col; + + /* Initialize the glyph memory to the background color. */ + +#if !defined(CONFIG_NX_DISABLE_1BPP) || !defined(CONFIG_NX_DISABLE_2BPP) || \ + !defined(CONFIG_NX_DISABLE_4BPP) || !defined(CONFIG_NX_DISABLE_8BPP) + + /* For pixel depths of 1, 2, 4, and 8, build up an 8-bit value containing + * multiple background colored pixels. + */ + + if (priv->bpp <= 8) + { + uint8_t pixel = (uint8_t)priv->bgcolor; + FAR uint8_t *ptr; + +#ifndef CONFIG_NX_DISABLE_1BPP + /* Pack a 1-bit pixel to 2 pixels */ + + if (priv->bpp < 2) + { + /* Pack 1-bit pixels into a 2-bits */ + + pixel &= 0x01; + pixel = (pixel) << 1 | pixel; + } +#endif + +#if !defined(CONFIG_NX_DISABLE_1BPP) || !defined(CONFIG_NX_DISABLE_2BPP) + /* Pack a 2-bit pixel to a 4-bit nibble */ + + if (priv->bpp < 4) + { + /* Pack 2-bit pixels into a nibble */ + + pixel &= 0x03; + pixel = (pixel) << 2 | pixel; + } +#endif + +#if !defined(CONFIG_NX_DISABLE_1BPP) || !defined(CONFIG_NX_DISABLE_2BPP) || \ + !defined(CONFIG_NX_DISABLE_4BPP) + /* Pack the 4-bit nibble into a byte */ + + if (priv->bpp < 8) + { + pixel &= 0x0f; + pixel = (pixel) << 4 | pixel; + } +#endif + + /* Then fill the glyph with the packed background color */ + + ptr = (FAR uint8_t *)glyph->bitmap; + for (row = 0; row < glyph->height; row++) + { + for (col = 0; col < glyph->stride; col++) + { + /* Transfer the packed bytes into the buffer */ + + *ptr++ = pixel; + } + } + } + else +#endif + +#if !defined(CONFIG_NX_DISABLE_16BPP) + if (priv->bpp == 16) + { + FAR uint16_t *ptr = (FAR uint16_t *)glyph->bitmap; + + for (row = 0; row < glyph->height; row++) + { + /* Just copy the color value into the glyph memory */ + + for (col = 0; col < glyph->width; col++) + { + *ptr++ = priv->bgcolor; + } + } + } + else +#endif + +#ifndef CONFIG_NX_DISABLE_24BPP + if (priv->bpp == 24) + { + FAR uint32_t *ptr = (FAR uint32_t *)glyph->bitmap; + FAR uint32_t pixel[3]; + + /* Get two 32-bit values for alternating 32 representations */ + + pixel[0] = (uint32_t)priv->bgcolor << 8 | (uint32_t)priv->bgcolor >> 16; + pixel[1] = (uint32_t)priv->bgcolor << 16 | (uint32_t)priv->bgcolor >> 8; + pixel[1] = (uint32_t)priv->bgcolor << 24 | (uint32_t)priv->bgcolor; + + for (row = 0; row < glyph->height; row++) + { + /* Copy the color value into the glyph memory */ + + col = 0; + for (; ; ) + { + *ptr++ = pixel[0]; + if (++col >= glyph->width) + { + break; + } + + *ptr++ = pixel[1]; + if (++col >= glyph->width) + { + break; + } + + *ptr++ = pixel[2]; + if (++col >= glyph->width) + { + break; + } + } + } + } + else +#endif + +#if !defined(CONFIG_NX_DISABLE_32BPP) + if (priv->bpp == 32) + { + FAR uint32_t *ptr = (FAR uint32_t *)glyph->bitmap; + + for (row = 0; row < glyph->height; row++) + { + /* Just copy the color value into the glyph memory */ + + for (col = 0; col < glyph->width; col++) + { + *ptr++ = priv->bgcolor; + } + } + } + else +#endif + { + PANIC(); + } +} + +/**************************************************************************** + * Name: nxf_renderglyph + * + * Description: + * Allocate memory for a new glyph and render the bitmap font into the + * allocated glyph memory. + * + * Assumptions: + * The caller holds the font cache semaphore. + * + ****************************************************************************/ + +static inline FAR struct nxfonts_glyph_s * +nxf_renderglyph(FAR struct nxfonts_fcache_s *priv, + FAR const struct nx_fontbitmap_s *fbm, uint8_t ch) +{ + FAR struct nxfonts_glyph_s *glyph = NULL; + size_t bmsize; + unsigned int height; + unsigned int width; + unsigned int stride; + int ret; + + ginfo("fcache=%p fbm=%p ch=%c (%02x)\n", + priv, fbm, (ch >= 32 && ch < 128) ? ch : '.', ch); + + /* Get the size of the glyph */ + + width = fbm->metric.width + fbm->metric.xoffset; + height = fbm->metric.height + fbm->metric.yoffset; + + /* Get the physical width of the glyph in bytes */ + + stride = (width * priv->bpp + 7) >> 3; + + /* Allocate the glyph (always succeeds) */ + + bmsize = stride * height; + glyph = (FAR struct nxfonts_glyph_s *)lib_malloc(SIZEOF_NXFONTS_GLYPH_S(bmsize)); + + if (glyph != NULL) + { + /* Save the character code, dimensions, and physcial width of the glyph */ + + glyph->code = ch; + glyph->width = width; + glyph->height = height; + glyph->stride = stride; + + /* Initialize the glyph memory to the background color. */ + + nxf_fillglyph(priv, glyph); + + /* Then render the glyph into the allocated, initialized memory */ + + ret = priv->renderer((FAR nxgl_mxpixel_t *)glyph->bitmap, + glyph->height, glyph->width, glyph->stride, + fbm, priv->fgcolor); + if (ret < 0) + { + /* Actually, the renderer never returns a failure */ + + gerr("ERROR: nxf_renderglyph: Renderer failed\n"); + lib_free(glyph); + return NULL; + } + + /* Add the new glyph to the font cache */ + + nxf_addglyph(priv, glyph); + } + + return glyph; +} + +/**************************************************************************** + * Name: nxf_findcache + * + * Description: + * Find a font cache tht matches the font charcteristics. + * + * Assumptions: + * The caller holds the font cache list semaphore. + * + ****************************************************************************/ + +static FAR struct nxfonts_fcache_s * +nxf_findcache(enum nx_fontid_e fontid, nxgl_mxpixel_t fgcolor, + nxgl_mxpixel_t bgcolor, int bpp) +{ + FAR struct nxfonts_fcache_s *fcache; + + ginfo("fontid=%p fgcolor=%u bgcolor=%u bpp=%d\n", + fontid, fgcolor, bgcolor, bpp); + + /* Search for a cache for this font characteristics */ + + for (fcache = g_fcaches; fcache != NULL; fcache = fcache->flink) + { + /* Does this font have the same characteristics? */ + + if (fcache->fontid == fontid && + fcache->fgcolor == fgcolor && + fcache->bgcolor == bgcolor && + fcache->bpp == bpp) + { + /* Yes... return it */ + + ginfo("Returning fcache=%p\n", fcache); + return fcache; + } + } + + ginfo("Not found\n"); + return NULL; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxf_cache_connect + * + * Description: + * Create a new font cache for the provided 'fontid'. If the cache + * already, then just increment a reference count return the handle for + * the existing font cache. + * + * Input Parameters: + * fontid - Identifies the font supported by this cache + * fgcolor - Foreground color + * bgcolor - Background color + * bpp - Bits per pixel + * maxglyphs - Maximum number of glyphs permitted in the cache + * + * Returned value: + * On success a non-NULL handle is returned that then may sequently be + * used with nxf_getglyph() to extract fonts from the font cache. NULL + * returned on any failure with the errno value set to indicate the nature + * of the error. + * + ****************************************************************************/ + +FCACHE nxf_cache_connect(enum nx_fontid_e fontid, + nxgl_mxpixel_t fgcolor, nxgl_mxpixel_t bgcolor, + int bpp, int maxglyphs) +{ + FAR struct nxfonts_fcache_s *priv; + int errcode; + + ginfo("fontid=%p fgcolor=%u bgcolor=%u bpp=%d maxglyphs=%d\n", + fontid, fgcolor, bgcolor, bpp, maxglyphs); + + /* Get exclusive access to the font cache list */ + + nxf_list_lock(); + + /* Find a font cache with the matching font characteristics */ + + priv = nxf_findcache(fontid, fgcolor, bgcolor, bpp); + if (priv == NULL) + { + /* There isn't one... we will have to create a new font cache for this + * client. + */ + + /* Allocate memory for the (empty) font cache */ + + priv = (FAR struct nxfonts_fcache_s *) + lib_zalloc(sizeof( struct nxfonts_fcache_s)); + + if (priv == NULL) + { + errcode = ENOMEM; + goto errout_with_lock; + } + + /* Initialize the font cache */ + + priv->maxglyphs = maxglyphs; + priv->fontid = fontid; + priv->fgcolor = fgcolor; + priv->bgcolor = bgcolor; + priv->bpp = bpp; + + /* Select the rendering function */ + + /* Select renderer -- Some additional logic would be required to + * support pixel depths that are not directly addressable (1,2,4, and + * 24). + */ + + switch (bpp) + { +#ifndef CONFIG_NX_DISABLE_1BPP + case 1: + priv->renderer = (nxf_renderer_t)nxf_convert_1bpp; + break; +#endif +#ifndef CONFIG_NX_DISABLE_2BPP + case 2: + priv->renderer = (nxf_renderer_t)nxf_convert_2bpp; + break; +#endif +#ifndef CONFIG_NX_DISABLE_4BPP + case 4: + priv->renderer = (nxf_renderer_t)nxf_convert_4bpp; + break; +#endif +#ifndef CONFIG_NX_DISABLE_8BPP + case 8: + priv->renderer = (nxf_renderer_t)nxf_convert_8bpp; + break; +#endif +#ifndef CONFIG_NX_DISABLE_16BPP + case 16: + priv->renderer = (nxf_renderer_t)nxf_convert_16bpp; + break; +#endif +#ifndef CONFIG_NX_DISABLE_24BPP + case 24: + priv->renderer = (nxf_renderer_t)nxf_convert_24bpp; + break; +#endif +#ifndef CONFIG_NX_DISABLE_32BPP + case 32: + priv->renderer = (nxf_renderer_t)nxf_convert_32bpp; + break; +#endif + default: + gerr("ERROR: Unsupported pixel depth: %d\n", bpp); + errcode = ENOSYS; + goto errout_with_fcache; + } + + /* Select the font */ + + priv->font = nxf_getfonthandle(fontid); + if (priv->font == NULL) + { + errcode = get_errno(); + gerr("ERROR: Failed to get font ID %d: %d\n", fontid, errcode); + goto errout_with_fcache; + } + + /* Initialize the mutual exclusion semaphore */ + + sem_init(&priv->fsem, 0, 1); + + /* Add the new font cache to the list of font caches */ + + priv->flink = g_fcaches; + g_fcaches = priv; + } + else + { + /* A font cache with these characteristics already exists. Just make + * sure that it is as least a big as the size requested. + */ + + if (priv->maxglyphs < maxglyphs) + { + priv->maxglyphs = maxglyphs; + } + } + + nxf_list_unlock(); + ginfo("fhandle=%p\n", priv); + return (FCACHE)priv; + +errout_with_fcache: + lib_free(priv); +errout_with_lock: + nxf_list_unlock(); + set_errno(errcode); + return NULL; +} + +/**************************************************************************** + * Name: nxf_cache_disconnect + * + * Description: + * Decrement the reference count on the font cache and, if the reference + * count goes to zero, free all resources used by the font cache. The + * font handle is invalid upon return in either case. + * + * Input Parameters: + * fhandle - A font cache handle previously returned by nxf_cache_connect(); + * + * Returned value: + * None + * + ****************************************************************************/ + +void nxf_cache_disconnect(FCACHE fhandle) +{ + FAR struct nxfonts_fcache_s *priv = (FAR struct nxfonts_fcache_s *)fhandle; + FAR struct nxfonts_fcache_s *fcache; + FAR struct nxfonts_fcache_s *prev; + FAR struct nxfonts_glyph_s *glyph; + FAR struct nxfonts_glyph_s *next; + + ginfo("fhandle=%p\n", fhandle); + + DEBUGASSERT(priv != NULL && priv->fclients > 0); + + /* Get exclusive access to the font cache */ + + nxf_cache_lock(priv); + + /* Is this the last client of the font cache? */ + + if (priv->fclients <= 1) + { + /* Get exclusive access to the font cache list */ + + nxf_list_lock(); + + /* Remove the font cache from the list of caches. This is a singly + * linked list, so we must do this the hard way. + */ + + for (prev = NULL, fcache = g_fcaches; + fcache != priv && fcache != NULL; + fcache = fcache->flink); + + ASSERT(fcache == priv); + nxf_removecache(fcache, prev); + nxf_list_unlock(); + + /* Free all allocated glyph memory */ + + for (glyph = priv->head; glyph != NULL; glyph = next) + { + next = glyph->flink; + lib_free(glyph); + } + + /* Destroy the serializing semaphore... while we are holding it? */ + + sem_destroy(&priv->fsem); + + /* Finally, free the font cache stucture itself */ + + lib_free(priv); + } + else + { + /* No.. just decrement the number of clients connected to the font + * cache. + */ + + priv->fclients--; + nxf_cache_unlock(priv); + } +} + +/**************************************************************************** + * Name: nxf_cache_getfonthandle + * + * Description: + * Return the handle to the font set used by this instance of the font + * cache. + * + * Input Parameters: + * fhandle - A font cache handle previously returned by nxf_cache_connect(); + * + * Returned value: + * Zero (OK) is returned if the metrics were + * + * Returned Value: + * One success, a non-NULL font handle is returned. + * + ****************************************************************************/ + +NXHANDLE nxf_cache_getfonthandle(FCACHE fhandle) +{ + FAR struct nxfonts_fcache_s *priv = (FAR struct nxfonts_fcache_s *)fhandle; + + DEBUGASSERT(priv != NULL && priv->font != NULL); + return priv->font; +} + +/**************************************************************************** + * Name: nxf_cache_getglyph + * + * Description: + * Get the font glyph for the character code 'ch' from the font cache. If + * the glyph for that character code does not exist in the font cache, it + * be rendered. + * + * Returned Value: + * On success, a non-NULL pointer to the rendered glyph in the font cache + * is returned. NULL is returned on any failure. + * + ****************************************************************************/ + +FAR const struct nxfonts_glyph_s *nxf_cache_getglyph(FCACHE fhandle, uint8_t ch) +{ + FAR struct nxfonts_fcache_s *priv = (FAR struct nxfonts_fcache_s *)fhandle; + FAR struct nxfonts_glyph_s *glyph; + FAR const struct nx_fontbitmap_s *fbm; + + ginfo("ch=%c (%02x)\n", (ch >= 32 && ch < 128) ? ch : '.', ch); + + /* Get exclusive access to the font cache */ + + nxf_cache_lock(priv); + + /* First, try to find the glyph in the cache of pre-rendered glyphs */ + + glyph = nxf_findglyph(priv, ch); + if (glyph == NULL) + { + /* No, it is not cached... Does the code map to a font? */ + + fbm = nxf_getbitmap(priv->font, ch); + if (fbm) + { + /* Yes.. render the glyph for the font */ + + glyph = nxf_renderglyph(priv, fbm, ch); + } + } + + nxf_cache_unlock(priv); + return glyph; +}