summaryrefslogtreecommitdiff
path: root/riscos/ufont.c
diff options
context:
space:
mode:
Diffstat (limited to 'riscos/ufont.c')
-rw-r--r--riscos/ufont.c1273
1 files changed, 0 insertions, 1273 deletions
diff --git a/riscos/ufont.c b/riscos/ufont.c
deleted file mode 100644
index 9cedcd79a..000000000
--- a/riscos/ufont.c
+++ /dev/null
@@ -1,1273 +0,0 @@
-/* ufont.c
- * Licensed under the GNU General Public License,
- * http://www.opensource.org/licenses/gpl-license
- * Copyright 2000 James Bursa <bursa@users.sourceforge.net>
- * Copyright 2004 John Tytgat <John.Tytgat@aaug.net>
- */
-
-/** \file
- * UFont - Unicode wrapper for non-Unicode aware FontManager
- *
- * This code allows non-Unicode aware FontManager to be used for
- * displaying Unicode encoded text lines. It needs the !UFont
- * resource (accessed via UFont$Path).
- */
-
-#include <assert.h>
-#include <limits.h>
-#include <wchar.h>
-
-#include "oslib/osfile.h"
-
-#include "ufont.h"
-
-// #define DEBUG_UFONT
-// #define DEBUG_ACTIVATE_SANITY_CHECK
-// #define DEBUG_DUMP_INTERNALS
-
-#ifdef DEBUG_UFONT
-# define dbg_fprintf fprintf
-#else
-# define dbg_fprintf (1)?0:fprintf
-#endif
-#ifdef DEBUG_ACTIVATE_SANITY_CHECK
-# define do_sanity_check sanity_check
-#else
-# define do_sanity_check (1)?0:sanity_check
-#endif
-#define MALLOC_CHUNK 256
-
-typedef struct usage_chain_s usage_chain_t;
-typedef struct virtual_fh_s virtual_fh_t;
-/* Virtual font handle :
- */
-struct virtual_fh_s
- {
- const char *fontNameP; /* => malloc'ed block holding RISC OS font name */
- int xsize, ysize; /* font size */
- int xres, yres; /* requested or actual resolution */
- unsigned int usage; /* the higher, the more this font handle is used for setting its glyphs */
- unsigned int refCount; /* number of times this struct is refered from ufont_f element */
- usage_chain_t *usageP; /* Ptr to element usage chain; if non NULL, we have a RISC OS font handle allocated. When refCount is 0, this is not necessary NULL. */
- };
-#define kInitialFHArraySize 20
-static virtual_fh_t *oVirtualFHArrayP;
-static size_t oCurVirtualFHArrayElems;
-static size_t oMaxVirtualFHArrayElems;
-
-/* Usage chain (one element per open RISC OS font handle) :
- */
-struct usage_chain_s
- {
- usage_chain_t *nextP;
- usage_chain_t *prevP;
-
- size_t chainTimer; /* When equal to oChainTimer, you can not throw this element out the chain. */
- font_f ro_fhandle; /* RISC OS font handle (garanteed non zero) */
- virtual_fh_t *virFHP;
- };
-
-typedef struct ufont_map_s ufont_map_t;
-
-struct ufont_map_s
- {
- byte fontnr[65536]; /* Must be 1st (comes straight from 'Data' file). Each entry is an index in the virtual_font_index array. */
- byte character[65536]; /* Must be 2nd (comes straight from 'Data' file) */
-
- const char *uFontNameP; /* => malloc'ed block holding UFont name */
- unsigned int refCount;
- ufont_map_t *nextP;
- };
-static const ufont_map_t *oMapCollectionP;
-
-struct ufont_font
- {
- ufont_map_t *mapP;
- unsigned int virtual_handles_used; /* Number of filled virtual_font_index[] elements */
- size_t virtual_font_index[256]; /* Index in the oVirtualFHArrayP */
- };
-
-/* Walking the chain starting with oUsageChain->nextP and continuing via
- * ->nextP until reaching oUsageChain again, results in equal or
- * decreasing ->virFHP->usage values.
- * Also walking the chain starting with oUsageChain->prevP and continuing
- * via ->prevP until reaching oUsageChain again, results in equal or
- * increasing ->virFHP->usage values.
- */
-static usage_chain_t oUsageChain;
-static size_t oCurUsageChainElems;
-/* Maximum number of RISC OS handles open by UFont :
- */
-#define kMaxUsageChainElems 80
-static size_t oChainTimer;
-
-static os_error *create_map(const char *fontNameP, const ufont_map_t **mapPP);
-static os_error *delete_map(ufont_map_t *mapP);
-static int eat_utf8(wchar_t *pwc, const byte *s, int n);
-static os_error *addref_virtual_fonthandle(const char *fontNameP, int xsize, int ysize, int xres, int yres, int *xresOutP, int *yresOutP, size_t *offsetP);
-static os_error *deref_virtual_fonthandle(size_t offset);
-static os_error *activate_virtual_fh(virtual_fh_t *virFHP);
-static os_error *remove_usage_chain_elem(usage_chain_t *usageElemP);
-static void repos_usage_chain_elem(usage_chain_t *usageElemP);
-static const char *get_rofontname(font_f rofhandle);
-#ifdef DEBUG_DUMP_INTERNALS
-static void dump_internals(void);
-#endif
-static int sanity_check(const char *testMsgP);
-
-/* UFont error messages :
- */
-static os_error error_badparams = { error_BAD_PARAMETERS, "Bad parameters" };
-static os_error error_exists = { error_FONT_NOT_FOUND, "UFont Fonts/Data file not found" };
-static os_error error_memory = { error_FONT_NO_ROOM, "Insufficient memory for font" };
-static os_error error_size = { error_FONT_BAD_FONT_FILE, "Wrong size of font file" };
-static os_error error_fnt_corrupt = { 1 /** \todo */, "UFont is corrupt" };
-static os_error error_toomany_handles = { 2 /** \todo */, "Too many UFont handles are needed to fulfill current request" };
-static os_error error_noufont = { 3 /** \todo */, "Unable to find UFont font" };
-static os_error error_badrohandle = { 4 /** \todo */, "Invalid internal RISC OS font handle" };
-
-/*
- * UFont_FindFont
- *
- * => as Font_FindFont, but
- * font_name does not support '\' qualifiers
- *
- * <= as Font_FindFont, but
- * handle is 32-bit
- * Results from xres_out and yres_out are questionable because we
- * delay-loading the real font data.
- */
-os_error *
-xufont_find_font(char const *fontNameP,
- int xsize,
- int ysize,
- int xres,
- int yres,
- ufont_f *font,
- int *xresOutP,
- int *yresOutP)
-{
- ufont_f fontP;
- const char *old_font;
- char *fonts_file;
- char file_name[256]; // \todo: fixed size, i.e. not safe.
- fileswitch_object_type objType;
- int size;
- os_error *errorP;
-
-if (font == NULL)
- return &error_badparams;
-/* Be sure never to return garbage as result. */
-*font = NULL;
-
-/* Allocate memory for UFont font set */
-if ((fontP = (ufont_f)calloc(1, sizeof(struct ufont_font))) == NULL)
- return &error_memory;
-
-if ((errorP = create_map(fontNameP, &fontP->mapP)) != NULL)
- {
- (void)xufont_lose_font(fontP);
- return errorP;
- }
-if (fontP->mapP == NULL)
- {
- (void)xufont_lose_font(fontP);
- return &error_noufont;
- }
-
-/* Find size of Fonts file :
- */
-strcpy(file_name, fontNameP);
-strcat(file_name, ".Fonts");
-if ((errorP = xosfile_read_stamped_path(file_name, "UFont:", &objType, NULL, NULL, &size, NULL, NULL)) != NULL)
- {
- (void)xufont_lose_font(fontP);
- return errorP;
- }
-if (objType != fileswitch_IS_FILE)
- {
- (void)xufont_lose_font(fontP);
- return &error_exists;
- }
-
-if ((fonts_file = (char *)malloc(size)) == NULL)
- {
- (void)xufont_lose_font(fontP);
- return &error_memory;
- }
-
-/* Load Fonts :
- */
-if ((errorP = xosfile_load_stamped_path(file_name, fonts_file, "UFont:", NULL, NULL, NULL, NULL, NULL)) != NULL)
- {
- (void)xufont_lose_font(fontP);
- free((void *)fonts_file);
- return errorP;
- }
-
-/* Open all fonts listed in Fonts :
- */
-for (old_font = fonts_file, fontP->virtual_handles_used = 0;
- old_font - fonts_file < size;
- old_font += strlen(old_font) + 1, ++fontP->virtual_handles_used)
- {
- /* UFont can maximum have 256 real RISC OS fonts :
- */
- if (fontP->virtual_handles_used < 256)
- {
- dbg_fprintf(stderr, "%i %s: ", fontP->virtual_handles_used, old_font);
- errorP = addref_virtual_fonthandle(old_font, xsize, ysize, xres, yres, xresOutP, yresOutP, &fontP->virtual_font_index[fontP->virtual_handles_used]);
- }
- else
- errorP = &error_fnt_corrupt;
-
- if (errorP != NULL)
- {
- (void)xufont_lose_font(fontP);
- free((void *)fonts_file);
- return errorP;
- }
-
- dbg_fprintf(stderr, "%i\n", fontP->virtual_font_index[fontP->virtual_handles_used]);
- }
-
-/* free Fonts */
-free((void *)fonts_file); fonts_file = NULL;
-
-*font = fontP;
-if (xresOutP != NULL)
- *xresOutP = 96;
-if (yresOutP != NULL)
- *yresOutP = 96;
-return NULL;
-}
-
-
-/*
- * UFont_LoseFont
- *
- * => font handle as returned by UFont_FindFont
- * Even if there was an error returned, we tried to delete as much
- * as possible. The ufont_f is definately not reusable afterwards.
- */
-os_error *
-xufont_lose_font(ufont_f fontP)
-{
- unsigned int index;
- os_error *theErrorP;
-
-theErrorP = (fontP->mapP != NULL) ? delete_map(fontP->mapP) : NULL;
-
-/* Close all fonts used :
- */
-for (index = 0; index < fontP->virtual_handles_used; ++index)
- {
- os_error *errorP;
- dbg_fprintf(stderr, "About to deref virtual font handle %d\n", fontP->virtual_font_index[index]);
- if ((errorP = deref_virtual_fonthandle(fontP->virtual_font_index[index])) != NULL)
- theErrorP = errorP;
- }
-
-/* Free ufont structure :
- */
-free((void *)fontP);
-
-return theErrorP;
-}
-
-
-/*
- * UFont_Paint
- *
- * => font handle as returned by UFont_FindFont
- * string is Unicode UTF-8 encoded
- * other parameters as Font_Paint
- */
-os_error *
-xufont_paint(ufont_f fontP,
- unsigned char const *string,
- font_string_flags flags,
- int xpos,
- int ypos,
- font_paint_block const *block,
- os_trfm const *trfm,
- int length)
-{
- char *result;
- os_error *error;
-
- if ((flags & font_GIVEN_LENGTH) == 0)
- length = INT_MAX;
-
- dbg_fprintf(stderr, "xufont_paint() : size %d, consider len %d\n", strlen(string), length);
- if ((error = xufont_convert(fontP, string, length, &result, NULL)) != NULL)
- return error;
- if (result[0] == '\0')
- return NULL;
-
- assert(result[0] == font_COMMAND_FONT);
- error = xfont_paint(result[1], &result[2],
- (flags & (~font_GIVEN_LENGTH)) | font_GIVEN_FONT,
- xpos, ypos, block, trfm, 0);
- return error;
-}
-
-
-/*
- * UFont_ScanString
- *
- * => font handle as returned by UFont_FindFont
- * string is Unicode UTF-8 encoded
- * split length is index in string, not pointer
- * other parameters as Font_ScanString
- *
- * <= as Font_ScanString
- */
-os_error *
-xufont_scan_string(ufont_f fontP,
- unsigned char const *string,
- font_string_flags flags,
- int x,
- int y,
- font_scan_block const *block,
- os_trfm const *trfm,
- int length,
- unsigned char const **split_point,
- int *x_out,
- int *y_out,
- int *length_out)
-{
- char *result;
- char *split_point_i;
- unsigned int *table;
- os_error *error;
-
- if ((flags & font_GIVEN_LENGTH) == 0)
- length = INT_MAX;
-
- dbg_fprintf(stderr, "xufont_scan_string() : size %d, consider len %d\n", strlen(string), length);
- if ((error = xufont_convert(fontP, string, length, &result, &table)) != NULL)
- return error;
- if (result[0] == '\0')
- {
- if (split_point != NULL)
- *split_point = string;
- if (x_out != NULL)
- *x_out = 0;
- if (y_out != NULL)
- *y_out = 0;
- if (length_out != NULL)
- *length_out = 0;
- return NULL;
- }
-
- assert(result[0] == font_COMMAND_FONT);
- error = xfont_scan_string(result[1], &result[2],
- (flags & (~font_GIVEN_LENGTH)) | font_GIVEN_FONT,
- x, y, block, trfm, 0,
- (split_point) ? &split_point_i : NULL,
- x_out, y_out, length_out);
- if (error != NULL)
- return error;
-
- if (split_point != NULL)
- {
- dbg_fprintf(stderr, "RISC OS scan string split at offset %d (char %d)\n", split_point_i - result, *split_point_i);
- *split_point = &string[table[split_point_i - result]];
- dbg_fprintf(stderr, "UTF-8 Split offset at %d (char %d)\n", *split_point - string, **split_point);
- }
-
- return NULL;
-}
-
-
-/**
- * Given a text line, return the number of bytes which can be set using
- * one RISC OS font and the bounding box fitting that part of the text
- * only.
- *
- * \param font a ufont font handle, as returned by xufont_find_font().
- * \param string string text. Does not have to be NUL terminated.
- * \param flags FontManger flags to be used internally
- * \param length length in bytes of the text to consider.
- * \param width returned width of the text which can be set with one RISC OS font. If 0, then error happened or initial text length was 0.
- * \param rofontname returned name of the RISC OS font which can be used to set the text. If NULL, then error happened or initial text length was 0.
- * \param rotext returned string containing the characters in returned RISC OS font. Not necessary NUL terminated. free() after use. If NULL, then error happened or initial text length was 0.
- * \param rolength length of return rotext string. If 0, then error happened or initial text length was 0.
- * \param consumed number of bytes of the given text which can be set with one RISC OS font. If 0, then error happened or initial text length was 0.
- */
-os_error *xufont_txtenum(ufont_f fontP,
- unsigned char const *string,
- font_string_flags flags,
- size_t length,
- int *widthP,
- unsigned char const **rofontnameP,
- unsigned char const **rotextP,
- size_t *rolengthP,
- size_t *consumedP)
-{
- char *result, *end_result;
- unsigned int *table;
- os_error *errorP;
-
- int width;
- const char *rofontname;
- char *rotext;
- size_t rolength;
-
- *rotextP = *rofontnameP = NULL;
- *consumedP = *rolengthP = *widthP = 0;
-
- if ((flags & font_GIVEN_LENGTH) == 0)
- length = INT_MAX;
-
- if (length == 0)
- return NULL;
-
- if ((errorP = xufont_convert(fontP, string, length, &result, &table)) != NULL)
- return errorP;
- if (result[0] == '\0')
- return NULL;
- assert(result[0] == font_COMMAND_FONT);
-
- /* Find how many characters starting at <result + 2> onwards
- are set using the RISC OS font with handle <result + 1> */
- for (end_result = result + 2; *end_result != '\0' && *end_result != font_COMMAND_FONT; ++end_result)
- ;
-
- rolength = end_result - result - 2;
- if ((errorP = xfont_scan_string(result[1], &result[2],
- flags | font_GIVEN_LENGTH | font_GIVEN_FONT,
- 0x7fffffff, 0x7fffffff,
- NULL, NULL,
- rolength,
- NULL,
- &width, NULL,
- NULL)) != NULL)
- return errorP;
- if ((rofontname = get_rofontname(result[1])) == NULL)
- return &error_badrohandle;
- if ((rotext = malloc(rolength)) == NULL)
- return &error_memory;
- memcpy(rotext, result + 2, rolength);
-
- *widthP = width;
- *rofontnameP = rofontname;
- *rotextP = rotext;
- *rolengthP = rolength;
- *consumedP = table[end_result - result];
-
- return NULL;
-}
-
-
-/*
- * UFont_Convert
- *
- * => initial font
- * UTF-8 string to convert to RISC OS font numbers and codes.
- * max length to convert (characters) or NUL char terminated.
- *
- * <= string converted to Font_Paint format
- * table of offsets in UTF-8 string
- */
-os_error *
-xufont_convert(ufont_f fontP,
- unsigned char const *string,
- size_t length,
- char **presult, /* may not be NULL ! */
- size_t **ptable /* may be NULL */)
-{
- static char *resultP;
- static size_t *tableP;
- static size_t currentSize;
-
- size_t max_length;
- size_t string_index, new_string_index, result_index;
- virtual_fh_t *curVirFH = NULL;
-
-assert(presult != NULL);
-
-do_sanity_check("xufont_convert() : begin");
-
-/* Find upfront if we're NUL char terminated or length terminated. */
-for (max_length = 0; max_length < length && string[max_length] != '\0'; ++max_length)
- /* no body */;
-
-/* Increase timer so we can enforce a set of usage elements to remain active.
- */
-++oChainTimer;
-
-/* Ensure memory block.
- */
-if (resultP == NULL)
- {
- if ((resultP = (char *)malloc(MALLOC_CHUNK)) == NULL)
- return &error_memory;
- currentSize = MALLOC_CHUNK;
- }
-if (tableP == NULL && (tableP = (size_t *)malloc(MALLOC_CHUNK * sizeof(size_t))) == NULL)
- return &error_memory;
-
-dbg_fprintf(stderr, "xufont_convert() : ");
-for (string_index = 0, result_index = 0;
- string_index < max_length;
- string_index = new_string_index)
- {
- wchar_t wchar;
- int result = eat_utf8(&wchar, &string[string_index], max_length - string_index);
-
- if (result == 0)
- {
- /* Too few input bytes : abort conversion */
- fprintf(stderr, "eat_utf8() : too few input bytes\n");
- break;
- }
- else if (result < 0)
- {
- /* Corrupt UTF-8 stream : skip <-result> input characters. */
- fprintf(stderr, "eat_utf8() : error %d\n", result);
-fprintf(stderr, "String <%.*s> error pos %d\n", length, string, string_index);
- wchar = '?';
- new_string_index = string_index - result;
- }
- else
- {
- /* Normal case : one wchar_t produced, <result> bytes consumed. */
- if (wchar >= 0x10000)
- wchar = '?';
- new_string_index = string_index + result;
- }
-
- dbg_fprintf(stderr, "src offset 0x%x : 0x%x ", string_index, wchar);
-
- /* Reserve room for at least 32 more entries.
- */
- if (result_index + 32 > currentSize)
- {
- if ((resultP = realloc(resultP, currentSize*2)) == NULL
- || (tableP = realloc(tableP, currentSize*2 * sizeof(size_t))) == NULL)
- return &error_memory;
-
- currentSize *= 2;
- }
-
- {
- const byte fontnr = fontP->mapP->fontnr[wchar];
- virtual_fh_t *virFHP;
- usage_chain_t *usageP;
-
- assert(fontnr < fontP->virtual_handles_used);
- virFHP = &oVirtualFHArrayP[fontP->virtual_font_index[fontnr]];
-
- /* Check if current font is ok :
- */
- if (virFHP != curVirFH)
- {
- os_error *errorP;
-
- curVirFH = virFHP;
-
- /* Make sure we have a RISC OS font handle associated :
- */
- if ((errorP = activate_virtual_fh(virFHP)) != NULL)
- return errorP;
- usageP = virFHP->usageP;
- assert(usageP != NULL);
- assert(usageP->ro_fhandle != 0);
- tableP[result_index] = tableP[result_index + 1] = string_index;
- resultP[result_index++] = font_COMMAND_FONT;
- resultP[result_index++] = usageP->ro_fhandle;
-
- dbg_fprintf(stderr, "{%i} ", resultP[result_index - 1]);
- }
- else
- {
- usageP = virFHP->usageP;
- assert(usageP != NULL);
- }
-
- ++virFHP->usage;
- /* By increasing the usage counter, it might that the oUsageChain needs
- * reordering.
- */
- if (usageP != oUsageChain.nextP && virFHP->usage > usageP->prevP->virFHP->usage)
- repos_usage_chain_elem(usageP);
-
- tableP[result_index] = string_index;
- resultP[result_index++] = fontP->mapP->character[wchar];
- dbg_fprintf(stderr, "[0x%x] ", resultP[result_index - 1]);
- }
- }
-resultP[result_index] = 0;
-*presult = resultP;
-
-tableP[result_index] = string_index;
-if (ptable != NULL)
- *ptable = tableP;
-
-#ifdef DEBUG_UFONT
-fprintf(stderr, "\nRISC OS font string result:\n");
-
-for (result_index = 0; resultP[result_index] != 0; ++result_index)
- fprintf(stderr, " Dst offset %d : 0x%x (src offset %d)\n", result_index, resultP[result_index], tableP[result_index]);
-#endif
-
-do_sanity_check("xufont_convert() : end");
-
-dbg_fprintf(stderr, "--- After convert()\n");
-//dump_internals();
-
-return NULL;
-}
-
-
-/* Creates or reuses an existing ufont_map_t
- */
-static os_error *create_map(const char *uFontNameP, const ufont_map_t **mapPP)
-{
- ufont_map_t *curMapP;
- size_t uFontNameLen = strlen(uFontNameP);
- char *fileNameP;
- os_error *errorP;
-
-/* Make sure we never return garbage results.
- */
-*mapPP = NULL;
-
-if ((fileNameP = (char *)alloca(uFontNameLen + sizeof(".Data"))) == NULL)
- return &error_memory;
-memcpy(fileNameP, uFontNameP, uFontNameLen);
-do {
- fileswitch_object_type objType;
- int size;
-
- memcpy(&fileNameP[uFontNameLen], ".Data", sizeof(".Data"));
- if ((errorP = xosfile_read_stamped_path(fileNameP, "UFont:", &objType, NULL, NULL, &size, NULL, NULL)) != NULL)
- return errorP;
-
- if (objType == fileswitch_NOT_FOUND)
- {
- /* Look for the Data file one directory level up. */
- while (uFontNameLen != 0 && fileNameP[--uFontNameLen] != '.')
- /* no body */;
- if (uFontNameLen == 0)
- return &error_exists;
- }
- else if (objType == fileswitch_IS_FILE)
- {
- if (size != 2*65536)
- return &error_size;
- break;
- }
- else
- return &error_exists;
- } while (1);
-
-/* Try to reuse an existing map :
- */
-for (curMapP = oMapCollectionP; curMapP != NULL; curMapP = curMapP->nextP)
- {
- size_t curUFontNameLen = strlen(curMapP->uFontNameP);
-
- if (uFontNameLen != curUFontNameLen)
- continue;
-
- if (memcmp(fileNameP, curMapP->uFontNameP, curUFontNameLen) != 0)
- break;
- }
-if (curMapP != NULL)
- {
- ++curMapP->refCount;
- *mapPP = curMapP;
- return NULL;
- }
-
-/* We need to create & load new map into memory :
- */
-if ((curMapP = (ufont_map_t *)malloc(sizeof(ufont_map_t))) == NULL)
- return &error_memory;
-
-/* Load Data file :
- */
-if ((errorP = xosfile_load_stamped_path(fileNameP, (byte *)&curMapP->fontnr[0], "UFont:", NULL, NULL, NULL, NULL, NULL)) != NULL)
- {
- free((void *)curMapP);
- return errorP;
- }
-fileNameP[uFontNameLen] = '\0';
-if ((curMapP->uFontNameP = strdup(fileNameP)) == NULL)
- {
- free((void *)curMapP);
- return &error_memory;
- }
-curMapP->refCount = 1;
-curMapP->nextP = oMapCollectionP;
-oMapCollectionP = curMapP;
-
-*mapPP = curMapP;
-return NULL;
-}
-
-
-static os_error *delete_map(ufont_map_t *mapP)
-{
-assert(mapP->refCount > 0);
---mapP->refCount;
-/** \todo: we don't remove the map from the oMapCollection list. Should we ?
- */
-
-return NULL;
-}
-
-
-/**
- * Convert next sequence of UTF-8 bytes into wchar_t
- *
- * \param pwc resulting wchar_t result.
- * \param s ptr to UTF-8 encoded string
- * \param n maximum of bytes which can be consumed via s
- * \return
- * x > 0: number of bytes consumed at s, valid wchar_t returned at pwc[0]
- * x = 0: too few input bytes, pwc[0] is undefined
- * x < 0: illegal UTF-8 stream, skip -x characters at s, pwc[0] is undefined
- */
-static int eat_utf8(wchar_t *pwc, const byte *s, int n)
-{
- byte c;
- int i;
-
- if (n < 1)
- return 0; /* not enough input bytes */
- else if ((c = s[0]) < 0x80) {
- *pwc = c;
- return 1;
- } else if (c < 0xc2)
- goto do_sync;
- else if (c < 0xe0) {
- if (n < 2)
- return 0; /* not enough input bytes */
- if (!((s[1] ^ 0x80) < 0x40))
- goto do_sync;
- *pwc = ((wchar_t) (c & 0x1f) << 6) | (wchar_t) (s[1] ^ 0x80);
- return 2;
- } else if (c < 0xf0) {
- if (n < 3)
- return 0; /* not enough input bytes */
- if (!((s[1] ^ 0x80) < 0x40 && (s[2] ^ 0x80) < 0x40 && (c >= 0xe1 || s[1] >= 0xa0)))
- goto do_sync;
- *pwc = ((wchar_t) (c & 0x0f) << 12) | ((wchar_t) (s[1] ^ 0x80) << 6) | (wchar_t) (s[2] ^ 0x80);
- return 3;
- } else if (c < 0xf8) {
- if (n < 4)
- return 0; /* not enough input bytes */
- if (!((s[1] ^ 0x80) < 0x40 && (s[2] ^ 0x80) < 0x40 && (s[3] ^ 0x80) < 0x40 && (c >= 0xf1 || s[1] >= 0x90)))
- goto do_sync;
- *pwc = ((wchar_t) (c & 0x07) << 18) | ((wchar_t) (s[1] ^ 0x80) << 12) | ((wchar_t) (s[2] ^ 0x80) << 6) | (wchar_t) (s[3] ^ 0x80);
- return 4;
- } else if (c < 0xfc) {
- if (n < 5)
- return 0; /* not enough input bytes */
- if (!((s[1] ^ 0x80) < 0x40 && (s[2] ^ 0x80) < 0x40 && (s[3] ^ 0x80) < 0x40 && (s[4] ^ 0x80) < 0x40 && (c >= 0xf9 || s[1] >= 0x88)))
- goto do_sync;
- *pwc = ((wchar_t) (c & 0x03) << 24) | ((wchar_t) (s[1] ^ 0x80) << 18) | ((wchar_t) (s[2] ^ 0x80) << 12) | ((wchar_t) (s[3] ^ 0x80) << 6) | (wchar_t) (s[4] ^ 0x80);
- return 5;
- } else if (c < 0xfe) {
- if (n < 6)
- return 0; /* not enough input bytes */
- if (!((s[1] ^ 0x80) < 0x40 && (s[2] ^ 0x80) < 0x40 && (s[3] ^ 0x80) < 0x40 && (s[4] ^ 0x80) < 0x40 && (s[5] ^ 0x80) < 0x40 && (c >= 0xfd || s[1] >= 0x84)))
- goto do_sync;
- *pwc = ((wchar_t) (c & 0x01) << 30) | ((wchar_t) (s[1] ^ 0x80) << 24) | ((wchar_t) (s[2] ^ 0x80) << 18) | ((wchar_t) (s[3] ^ 0x80) << 12) | ((wchar_t) (s[4] ^ 0x80) << 6) | (wchar_t) (s[5] ^ 0x80);
- return 6;
- }
-
-do_sync:
- /* The UTF-8 sequence at s is illegal, skipping from s onwards
- * until first non top character is found or %11xxxxxx is found
- * (both valid UTF-8 *starts* - not necessary valid sequences).
- */
- for (i = 1; i < n && !((s[i] & 0x80) == 0x00 || (s[i] & 0xC0) == 0xC0); ++i)
- /* no body */;
- return -i;
-}
-
-
-/**
- * Adds the RISC OS font <fontNameP> to the oVirtualFHArrayP list and
- * returns the index in that array.
- * oVirtualFHArrayP can be reallocated (and all virFHP ptrs in oUsageChain).
- * Results in xresOutP and yresOutP are not always that meaningful because
- * of the delayed-loading of the real RISC OS font data.
- * xresOutP and/or yresOutP may be NULL.
- */
-static os_error *addref_virtual_fonthandle(const char *fontNameP, int xsize, int ysize, int xres, int yres, int *xresOutP, int *yresOutP, size_t *offsetP)
-{
- size_t curIndex;
- virtual_fh_t *unusedSlotP;
-
- assert(offsetP != NULL);
-
- do_sanity_check("addref_virtual_fonthandle() : begin");
-
- if (oVirtualFHArrayP == NULL) {
- if ((oVirtualFHArrayP = (virtual_fh_t *)calloc(kInitialFHArraySize, sizeof(virtual_fh_t))) == NULL)
- return &error_memory;
- /* oCurVirtualFHArrayElems = 0; Isn't really necessary because of static */
- oMaxVirtualFHArrayElems = kInitialFHArraySize;
- }
-
- /* Check for duplicate (and find first unused slot if any) :
- */
- for (unusedSlotP = NULL, curIndex = 0;
- curIndex < oCurVirtualFHArrayElems;
- ++curIndex) {
- virtual_fh_t *virFHP = &oVirtualFHArrayP[curIndex];
-
- if (virFHP->fontNameP != NULL /* case strdup(fontNameP) failed */
- && stricmp(virFHP->fontNameP, fontNameP) == 0
- && virFHP->xsize == xsize && virFHP->ysize == ysize) {
- if (xresOutP != NULL)
- *xresOutP = virFHP->xres;
- if (yresOutP != NULL)
- *yresOutP = virFHP->yres;
- ++virFHP->refCount;
- *offsetP = curIndex;
- do_sanity_check("addref_virtual_fonthandle() : case 1");
- return NULL;
- }
-
- if (virFHP->refCount == 0 && unusedSlotP == NULL)
- unusedSlotP = virFHP;
- }
-
- /* Can we reuse a slot ?
- * I.e. a virtual FH which refCount is zero.
- */
- if (unusedSlotP != NULL) {
- if (unusedSlotP->usageP != NULL) {
- os_error *errorP;
-
- /* This slot is refered in the usage chain, we have to unlink it.
- */
- if ((errorP = remove_usage_chain_elem(unusedSlotP->usageP)) != NULL)
- return errorP;
- }
-
- unusedSlotP->usage = 0;
- if (unusedSlotP->fontNameP != NULL)
- free((void *)unusedSlotP->fontNameP);
- if ((unusedSlotP->fontNameP = strdup(fontNameP)) == NULL)
- return &error_memory;
-
- unusedSlotP->xsize = xsize;
- unusedSlotP->ysize = ysize;
- unusedSlotP->xres = (xres > 1) ? xres : 96;
- if (xresOutP != NULL)
- *xresOutP = unusedSlotP->xres;
- unusedSlotP->yres = (yres > 1) ? yres : 96;
- if (yresOutP != NULL)
- *yresOutP = unusedSlotP->yres;
- unusedSlotP->refCount = 1;
- *offsetP = unusedSlotP - oVirtualFHArrayP;
- do_sanity_check("addref_virtual_fonthandle() : case 2");
- return NULL;
- }
-
- /* Add new entry :
- */
- if (oCurVirtualFHArrayElems == oMaxVirtualFHArrayElems) {
- virtual_fh_t *newVirtualFHArrayP;
- size_t extraOffset;
- usage_chain_t *usageP;
-
- /* Don't use realloc() as when that fails, we don't even have the original
- * memory block anymore.
- */
- if ((newVirtualFHArrayP = (virtual_fh_t *)calloc(2*oMaxVirtualFHArrayElems, sizeof(virtual_fh_t))) == NULL)
- return &error_memory;
- memcpy(newVirtualFHArrayP, oVirtualFHArrayP, oMaxVirtualFHArrayElems * sizeof(virtual_fh_t));
- free((void *)oVirtualFHArrayP);
- extraOffset = (const char *)newVirtualFHArrayP - (const char *)oVirtualFHArrayP;
- oVirtualFHArrayP = newVirtualFHArrayP;
- oMaxVirtualFHArrayElems *= 2;
-
- /* Update the virFHP pointers in the usage chain :
- */
- if (oUsageChain.nextP != NULL) {
- for (usageP = oUsageChain.nextP; usageP != &oUsageChain; usageP = usageP->nextP)
- usageP->virFHP = (virtual_fh_t *)&((char *)usageP->virFHP)[extraOffset];
- }
- }
-
- unusedSlotP = &oVirtualFHArrayP[oCurVirtualFHArrayElems];
- if ((unusedSlotP->fontNameP = (const char *)strdup(fontNameP)) == NULL)
- return &error_memory;
- unusedSlotP->xsize = xsize;
- unusedSlotP->ysize = ysize;
- unusedSlotP->xres = (xres > 1) ? xres : 96;
- if (xresOutP != NULL)
- *xresOutP = unusedSlotP->xres;
- unusedSlotP->yres = (yres > 1) ? yres : 96;
- if (yresOutP != NULL)
- *yresOutP = unusedSlotP->yres;
- unusedSlotP->refCount = 1;
- *offsetP = oCurVirtualFHArrayElems++;
-
- do_sanity_check("addref_virtual_fonthandle() : case 3");
- return NULL;
-}
-
-
-/**
- * Deref virtual_fh_t element in oVirtualFHArrayP array.
- */
-static os_error *deref_virtual_fonthandle(size_t offset)
-{
- assert(/* offset >= 0 && */ offset < oCurVirtualFHArrayElems);
- assert(oVirtualFHArrayP[offset].refCount > 0);
-
- /* When the refCount reaches 0, it will be reused by preference when a
- * new usageChain element is needed in addref_virtual_fonthandle().
- */
- --oVirtualFHArrayP[offset].refCount;
-
- do_sanity_check("deref_virtual_fonthandle()");
- return NULL;
-}
-
-
-/**
- * Virtual font handle <virFHP> needs to have a RISC OS font handle
- * associated via virFHP->usageP. For this we can throw out all other
- * usage chain elements which have a chainTimer different from oChainTimer.
- * However, we may not have more than kMaxUsageChainElems chain elements
- * active.
- * Afterwards: either an error, either virFHP->usageP points to an usage chain
- * element in the oUsageChain linked list and that usage chain element has
- * a valid RISC OS font handle associated.
- */
-static os_error *activate_virtual_fh(virtual_fh_t *virFHP)
-{
- usage_chain_t *usageP;
-
- dbg_fprintf(stderr, "+++ activate_virtual_fh(virFHP %p, usageP ? %p)\n", virFHP, virFHP->usageP);
- do_sanity_check("activate_virtual_fh() : begin");
-
- /* The easiest case : we already have a RISC OS font handle :
- */
- if ((usageP = virFHP->usageP) != NULL) {
- usageP->chainTimer = oChainTimer;
- assert(usageP->ro_fhandle != 0);
- assert(usageP->virFHP == virFHP);
- do_sanity_check("activate_virtual_fh() : case 1");
- dbg_fprintf(stderr, "--- done, activate_virtual_fh(), case 1\n");
- return NULL;
- }
-
- /* The second easiest case : we're still allowed to create an extra
- * chain element :
- */
- if (oCurUsageChainElems < kMaxUsageChainElems) {
- os_error *errorP;
-
- if ((usageP = (usage_chain_t *)malloc(sizeof(usage_chain_t))) == NULL)
- return &error_memory;
- usageP->chainTimer = oChainTimer;
-
- if ((errorP = xfont_find_font(virFHP->fontNameP,
- virFHP->xsize, virFHP->ysize,
- virFHP->xres, virFHP->yres,
- &usageP->ro_fhandle,
- &virFHP->xres, &virFHP->yres)) != NULL) {
- free((void *)usageP);
- return errorP;
- }
- usageP->virFHP = virFHP;
- virFHP->usageP = usageP;
- ++oCurUsageChainElems;
-
- /* Make sure oUsageChain nextP and prevP point to at least something (is
- * only executed once and should probably better be done in a global
- * init routine).
- */
- if (oUsageChain.nextP == NULL)
- oUsageChain.nextP = oUsageChain.prevP = &oUsageChain;
- }
- else {
- os_error *errorP;
-
- /* The more difficult one : we need to reuse a usage chain element.
- * Take the last one because that is least used but skip the onces
- * with chainTimer equal to the current oChainTimer because those
- * RISC OS font handles are still used in the font string we're
- * currently processing.
- */
- for (usageP = oUsageChain.prevP;
- usageP != &oUsageChain && usageP->chainTimer == oChainTimer;
- usageP = usageP->prevP)
- /* no body */;
- if (usageP == &oUsageChain) {
- /* Painful : all usage chain elements are in use and we already have the
- * maximum of chain elements reached.
- */
- return &error_toomany_handles;
- }
-
- usageP->chainTimer = oChainTimer;
- /* The virtual font handle currently in usageP->virFHP no longer has a real
- * RISC OS font handle anymore.
- */
- usageP->virFHP->usageP = NULL;
- if ((errorP = xfont_lose_font(usageP->ro_fhandle)) != NULL)
- return errorP;
- if ((errorP = xfont_find_font(virFHP->fontNameP,
- virFHP->xsize, virFHP->ysize,
- virFHP->xres, virFHP->yres,
- &usageP->ro_fhandle,
- &virFHP->xres, &virFHP->yres)) != NULL)
- return errorP;
- usageP->virFHP = virFHP;
- virFHP->usageP = usageP;
-
- /* Delink :
- */
- usageP->prevP->nextP = usageP->nextP;
- usageP->nextP->prevP = usageP->prevP;
- }
-
- /* Link usageP in the oUsageChain based on its current virFHP->usage value :
- */
- {
- const unsigned int usage = virFHP->usage;
- usage_chain_t *runUsageP;
-
- for (runUsageP = &oUsageChain;
- runUsageP != oUsageChain.nextP && runUsageP->prevP->virFHP->usage <= usage;
- runUsageP = runUsageP->prevP)
- /* no body */;
-
- /* We have to link usageP between runUsageP and runUsageP->prevP
- * because runUsageP->prevP has higher usage than the one we need to
- * link in -or- we're at the end/start.
- */
- usageP->nextP = runUsageP;
- usageP->prevP = runUsageP->prevP;
- runUsageP->prevP->nextP = usageP;
- runUsageP->prevP = usageP;
- }
- do_sanity_check("activate_virtual_fh() : case 2");
- dbg_fprintf(stderr, "--- done, activate_virtual_fh(), case 2\n");
-
- return NULL;
-}
-
-
-/**
- * Remove the usage_chaint_t element from the usage chain
- */
-static os_error *remove_usage_chain_elem(usage_chain_t *usageP)
-{
- os_error *errorP;
-
- assert(usageP != NULL);
- assert(oCurUsageChainElems > 0);
- assert(usageP->ro_fhandle != 0);
- assert(usageP->virFHP != NULL);
-
- if ((errorP = xfont_lose_font(usageP->ro_fhandle)) != NULL)
- return errorP;
-
- usageP->virFHP->usageP = NULL;
-
- /* Delink it :
- */
- usageP->prevP->nextP = usageP->nextP;
- usageP->nextP->prevP = usageP->prevP;
-
- --oCurUsageChainElems;
- free((void *)usageP);
-
- do_sanity_check("remove_usage_chain_elem() : end");
- return NULL;
-}
-
-
-/***
- * Should be called when the usage_chain_t element is no longer in the right
- * place in the chain based on its virFHP->usage value.
- *
- * usageP is no longer in the right place in the chain because its
- * ->virFHP->usage value increased. Reposition it towards prev
- * direction.
- */
-static void repos_usage_chain_elem(usage_chain_t *usageP)
-{
- usage_chain_t *prev1P, *prev2P;
- const unsigned int curUsage = usageP->virFHP->usage;
-
- dbg_fprintf(stderr, "+++ repos_usage_chain_elem(%p)\n", usageP);
-
- /* If this assert goes off, then it means that this routine shouldn't
- * have been called.
- */
- assert(curUsage > usageP->prevP->virFHP->usage);
-
- /* Delink :
- */
- usageP->prevP->nextP = usageP->nextP;
- usageP->nextP->prevP = usageP->prevP;
-
- /* Place usageElemP between prev1P and prev2P.
- */
- for (prev1P = usageP->prevP, prev2P = prev1P->prevP;
- prev2P != &oUsageChain && curUsage > prev2P->virFHP->usage;
- prev1P = prev2P, prev2P = prev2P->prevP) {
- dbg_fprintf(stderr, "> prev1P %p (%d), usageElemP %p (%d), prev2P %p (%d), dummy %p\n", prev1P, prev1P->virFHP->usage, usageP, usageP->virFHP->usage, prev2P, prev2P->virFHP->usage, &oUsageChain);
- assert(prev1P->virFHP->usage <= prev2P->virFHP->usage);
- }
-
- dbg_fprintf(stderr, "prev1P %p (%d), usageElemP %p (%d), prev2P %p (%d), dummy %p\n", prev1P, prev1P->virFHP->usage, usageP, usageP->virFHP->usage, prev2P, prev2P->virFHP->usage, &oUsageChain);
-
- /* Relink between prev1P and prev2P :
- */
- prev1P->prevP = usageP;
- usageP->prevP = prev2P;
- prev2P->nextP = usageP;
- usageP->nextP = prev1P;
-
- do_sanity_check("repos_usage_chain_elem() : end");
- dbg_fprintf(stderr, "--- done, repos_usage_chain_elem()\n");
-}
-
-
-/**
- * Retrieves the RISC OS font name of given RISC OS fonthandle.
- *
- * \param rofhandle RISC OS font handle
- */
-static const char *get_rofontname(font_f rofhandle)
-{
- usage_chain_t *usageP;
-
- if (oUsageChain.nextP == NULL)
- return NULL;
-
- for (usageP = oUsageChain.nextP; usageP != &oUsageChain; usageP = usageP->nextP)
- if (usageP->ro_fhandle == rofhandle)
- return usageP->virFHP->fontNameP;
-
- return NULL;
-}
-
-
-#ifdef DEBUG_DUMP_INTERNALS
-/**
- * Prints to stderr the complete internal state of UFont.
- */
-static void dump_internals(void)
-{
- fprintf(stderr, "Dump UFont internals:\n - Virtual font handle array at %p (length %d, max length %d)\n - Usage chain elements %d\n - Chain timer is %d\n Dump usage chain (first dummy at %p):\n", oVirtualFHArrayP, oCurVirtualFHArrayElems, oMaxVirtualFHArrayElems, oCurUsageChainElems, oChainTimer, &oUsageChain);
- if (oUsageChain.prevP == NULL || oUsageChain.nextP == NULL) {
- fprintf(stderr, " Empty usage chain\n");
- if (oUsageChain.prevP != oUsageChain.nextP)
- fprintf(stderr, " *** Corrupted empty usage chain: next %p, prev %p\n", oUsageChain.nextP, oUsageChain.prevP);
- if (oCurUsageChainElems != 0)
- fprintf(stderr, " *** Current usage chain length is wrong\n");
- }
- else {
- size_t usageCount;
- const usage_chain_t *usageP;
-
- for (usageCount = 0, usageP = oUsageChain.nextP; usageP != &oUsageChain; ++usageCount, usageP = usageP->nextP) {
- fprintf(stderr, " -%d- : cur %p, next %p, prev %p, timer %d, RISC OS font handle %d, virtual font %p (%d, %s), usage %d\n", usageCount, usageP, usageP->nextP, usageP->prevP, usageP->chainTimer, usageP->ro_fhandle, usageP->virFHP, usageP->virFHP - oVirtualFHArrayP, usageP->virFHP->fontNameP, usageP->virFHP->usage);
- if (usageP->nextP->prevP != usageP)
- fprintf(stderr, " *** Bad usageP->nextP->prevP != usageP\n");
- if (usageP->prevP->nextP != usageP)
- fprintf(stderr, " *** Bad usageP->prevP->nextP != usageP\n");
- if (usageP->virFHP < oVirtualFHArrayP || usageP->virFHP >= &oVirtualFHArrayP[oCurVirtualFHArrayElems])
- fprintf(stderr, " *** Bad virtual font handle\n");
- }
- if (usageCount != oCurUsageChainElems)
- fprintf(stderr, " *** Current usage chain length is wrong\n");
- if (usageCount > kMaxUsageChainElems)
- fprintf(stderr, " *** Current usage chain is too long\n");
- }
-
- if (oVirtualFHArrayP != NULL) {
- size_t fhIndex;
-
- fprintf(stderr, " Dump virtual font handles:\n");
- for (fhIndex = 0; fhIndex < oCurVirtualFHArrayElems; ++fhIndex) {
- const virtual_fh_t *virFHP = &oVirtualFHArrayP[fhIndex];
-
- fprintf(stderr, " -%d (%p)- : <%s>, size %d,%d, res %d,%d, usage %d, ref count %d, usage chain ptr %p\n", fhIndex, virFHP, virFHP->fontNameP, virFHP->xsize, virFHP->ysize, virFHP->xres, virFHP->yres, virFHP->usage, virFHP->refCount, virFHP->usageP);
- if (virFHP->usageP != NULL) {
- const usage_chain_t *usageP;
-
- for (usageP = oUsageChain.nextP;
- usageP != virFHP->usageP && usageP != &oUsageChain;
- usageP = usageP->nextP)
- /* no body */;
- if (usageP != virFHP->usageP)
- fprintf(stderr, " *** Usage chain ptr could not be found in usage chain\n");
- }
- }
- }
-}
-#endif
-
-
-/**
- * Does do a full sanity check of UFont internal datastructures.
- * Will assert() when something odd if found.
- */
-static int sanity_check(const char *testMsgP)
-{
- dbg_fprintf(stderr, "Sanity check <%s>\n", testMsgP);
- if (oUsageChain.prevP == NULL || oUsageChain.nextP == NULL) {
- assert(oUsageChain.prevP == oUsageChain.nextP);
- assert(oCurUsageChainElems == 0);
- }
- else {
- size_t usageCount;
- const usage_chain_t *usageP;
-
- /* We should see equal or decreasing usage values.
- */
- for (usageCount = 0, usageP = oUsageChain.nextP; usageP != &oUsageChain; ++usageCount, usageP = usageP->nextP) {
- assert(usageP->nextP->prevP == usageP);
- assert(usageP->prevP->nextP == usageP);
- assert(usageP->chainTimer <= oChainTimer);
- assert(usageP->ro_fhandle != 0);
- assert(oVirtualFHArrayP != NULL);
- assert(usageP->virFHP >= oVirtualFHArrayP && usageP->virFHP < &oVirtualFHArrayP[oCurVirtualFHArrayElems]);
- assert(usageP->virFHP->usageP == usageP);
- assert(usageP == oUsageChain.prevP || usageP->virFHP->usage >= usageP->nextP->virFHP->usage);
- }
- assert(usageCount == oCurUsageChainElems);
- assert(usageCount <= kMaxUsageChainElems);
- }
-
- if (oVirtualFHArrayP != NULL) {
- size_t fhIndex;
-
- for (fhIndex = 0; fhIndex < oCurVirtualFHArrayElems; ++fhIndex) {
- const virtual_fh_t *virFHP = &oVirtualFHArrayP[fhIndex];
-
- if (virFHP->usageP != NULL) {
- const usage_chain_t *usageP;
-
- assert(virFHP->fontNameP != NULL);
- assert(virFHP->xsize > 0 && virFHP->ysize > 0);
- assert(virFHP->xres > 0 && virFHP->yres > 0);
- for (usageP = oUsageChain.nextP;
- usageP != virFHP->usageP && usageP != &oUsageChain;
- usageP = usageP->nextP)
- /* no body */;
- assert(usageP == virFHP->usageP);
- }
- }
- }
-
- return 0;
-}