/* ufont.c */ #include "ufont.h" #include "oslib/osfile.h" #define MALLOC_CHUNK 256 struct ufont_font { font_f handle[65536]; char character[65536]; unsigned int handles_used; font_f handles[256]; }; os_error error_exists = { error_FONT_NOT_FOUND, "Fonts file not found" }; os_error error_memory = { error_FONT_NO_ROOM, "Insufficient memory for font" }; os_error error_size = { error_FONT_BAD_FONT_FILE, "Wrong size of font file" }; /* * UFont_FindFont * * => as Font_FindFont, but * font_name does not support '\' qualifiers * * <= as Font_FindFont, but * handle is 32-bit */ os_error * xufont_find_font(char const *font_name, int xsize, int ysize, int xres, int yres, struct ufont_font **font, int *xres_out, int *yres_out) { char *old_font; char *fonts_file; char file_name[256]; fileswitch_object_type obj_type; int code; int handle; unsigned int size; os_error *error; /* find size of Fonts file */ strcpy(file_name, font_name); strcat(file_name, ".Fonts"); error = xosfile_read_stamped_path(file_name, "UFont:", &obj_type, NULL, NULL, &size, NULL, NULL); if (error != NULL) return error; if (obj_type != fileswitch_IS_FILE) return &error_exists; /* allocate memory */ fonts_file = malloc(size); if (fonts_file == NULL) return &error_memory; *font = malloc(sizeof(struct ufont_font)); if (*font == NULL) return &error_memory; /* load Fonts */ error = xosfile_load_stamped_path(file_name, fonts_file, "UFont:", NULL, NULL, NULL, NULL, NULL); if (error != NULL) return error; /* open all fonts listed in Fonts */ for (old_font = fonts_file, handle = 0; old_font - fonts_file < size; old_font += strlen(old_font) + 1, handle++) { /* #ifdef DEBUG */ /* printf("%i %s: ", handle, old_font); */ /* #endif */ error = xfont_find_font(old_font, xsize, ysize, xres, yres, &(*font)->handles[handle], xres_out, yres_out); if (error != NULL) return error; /* #ifdef DEBUG */ /* printf("%i\n", (*font)->handles[handle]); */ /* #endif */ } (*font)->handles_used = handle; /* free Fonts */ free(fonts_file); /* load Data */ strcpy(file_name, font_name); strcat(file_name, ".Data"); error = xosfile_load_stamped_path(file_name, (byte *) (*font), "UFont:", NULL, NULL, NULL, &size, NULL); if (error != NULL) return error; if (size != 2*65536) return &error_size; /* change font indexes to font handles */ for (code = 0; code < 65536; code++) (*font)->handle[code] = (*font)->handles[(*font)->handle[code]]; return NULL; } /* * UFont_LoseFont * * => font handle as returned by UFont_FindFont */ os_error * xufont_lose_font(struct ufont_font *font) { unsigned int handle; os_error *error; /* close all fonts used */ for (handle = 0; handle < font->handles_used; handle++) { error = xfont_lose_font(font->handles[handle]); if (error != NULL) return error; } /* free font structure */ free(font); return NULL; } /* * UFont_Paint * * => font handle as returned by UFont_FindFont * string is unicode (2 byte characters), see UFont_Convert * other parameters as Font_Paint */ os_error * xufont_paint(struct ufont_font *font, wchar_t const *string, font_string_flags flags, int xpos, int ypos, font_paint_block const *block, os_trfm const *trfm, unsigned int length) { char *result; os_error *error; if ((flags & font_GIVEN_LENGTH) == 0) length = 0x7fffffff; error = xufont_convert(font, string, length, &result, NULL); if (error != NULL) return error; error = xfont_paint(result[1], result, (flags & (~font_GIVEN_LENGTH)) | font_GIVEN_FONT, xpos, ypos, block, trfm, 0); if (error != NULL) { free(result); return error; } free(result); return NULL; } /* * UFont_Convert * * => initial font * unicode string to convert * length to convert (characters) * * control sequences in string (all 2 byte): * * 9, dx_low, dx_middle, dx_high (each 2 byte, but maximum 255) * 11, dy_low, dy_middle, dy_high " * 19, r, g, b, R, G, B, max " * 25, underline_position, underline_thickness " * 26, font_handle (4 bytes, ie. 2 wide characters) * 27, m1, m2, m3, m4 (each matrix entry 4 bytes, * 28, m1, m2, m3, m4, m5, m6 ie. 2 wide characters) * * <= string converted to Font_Paint format * table of offsets in unicode string */ os_error * xufont_convert(struct ufont_font *font, wchar_t const *string, unsigned int length, char **presult, unsigned int **ptable) { char *result; unsigned int string_index = 0; unsigned int result_index = 0; unsigned int i; unsigned int current_size = MALLOC_CHUNK; unsigned int *table; font_f current_font = 0; result = malloc(MALLOC_CHUNK); if (result == NULL) return &error_memory; if (ptable != NULL) { table = malloc(MALLOC_CHUNK * sizeof(unsigned int)); if (table == NULL) return &error_memory; } while ((string[string_index] != 0) && (string_index < length)) { /* #ifdef DEBUG */ /* printf("0x%x ", string[string_index]); */ /* #endif */ if (result_index + 32 > current_size) { current_size += MALLOC_CHUNK; result = realloc(result, current_size); if (result == NULL) return &error_memory; if (ptable != NULL) { table = realloc(result, current_size * sizeof(unsigned int)); if (table == NULL) return &error_memory; } } if (ptable != NULL) table[result_index] = string_index; switch (string[string_index]) { case 9: case 11: { if (ptable != NULL) table[result_index + 1] = table[result_index + 2] = table[result_index + 3] = string_index; result[result_index++] = string[string_index++]; result[result_index++] = string[string_index++]; result[result_index++] = string[string_index++]; result[result_index++] = string[string_index++]; break; } case 19: { if (ptable != NULL) table[result_index + 1] = table[result_index + 2] = table[result_index + 3] = table[result_index + 4] = table[result_index + 5] = table[result_index + 6] = table[result_index + 7] = string_index; result[result_index++] = string[string_index++]; result[result_index++] = string[string_index++]; result[result_index++] = string[string_index++]; result[result_index++] = string[string_index++]; result[result_index++] = string[string_index++]; result[result_index++] = string[string_index++]; result[result_index++] = string[string_index++]; result[result_index++] = string[string_index++]; break; } case 25: { if (ptable != NULL) table[result_index + 1] = table[result_index + 2] = string_index; result[result_index++] = string[string_index++]; result[result_index++] = string[string_index++]; result[result_index++] = string[string_index++]; break; } case 26: { string_index++; font = (struct ufont_font *) ((string[string_index + 1] << 16) | string[string_index]); break; } case 27: { if (ptable != NULL) for (i = result_index + 1; i < ((result_index + 1 + 16 + 3) & (unsigned int) (~3)); i++) table[i] = string_index; result[result_index++] = string[string_index++]; result_index = (result_index + 3) & (unsigned int) (~3); for (i = 0; i < 8; i++) { result[result_index++] = string[string_index] & 0xff; result[result_index++] = string[string_index++] >> 8; } break; } case 28: { if (ptable != NULL) for (i = result_index + 1; i < ((result_index + 1 + 24 + 3) & (unsigned int) (~3)); i++) table[i] = string_index; result[result_index++] = string[string_index++]; result_index = (result_index + 3) & (unsigned int) (~3); for (i = 0; i < 12; i++) { result[result_index++] = string[string_index] & 0xff; result[result_index++] = string[string_index++] >> 8; } break; } default: { if (font->handle[(unsigned int) string[string_index]] != current_font) { if (ptable != NULL) table[result_index + 1] = table[result_index + 2] = string_index; result[result_index++] = 26; result[result_index++] = current_font = font->handle[(unsigned int) string[string_index]]; /* #ifdef DEBUG */ /* printf("{%i} ", current_font); */ /* #endif */ } result[result_index++] = font->character[(unsigned int) string[string_index++]]; /* #ifdef DEBUG */ /* printf("[0x%x] ", result[result_index - 1]); */ /* #endif */ break; } } } result[result_index] = 0; *presult = result; if (ptable != NULL) { table[result_index] = string_index; *ptable = table; } /* #ifdef DEBUG */ /* printf("\n"); */ /* for (result_index = 0; result[result_index] != 0; result_index++) */ /* printf("0x%x ", result[result_index]); */ /* printf("\n"); */ /* #endif */ return NULL; } /* * UFont_ScanString * * => font handle as returned by UFont_FindFont * string is unicode (2 byte characters), see UFont_Convert * split length is index in string, not pointer * other parameters as Font_ScanString * * <= as Font_ScanString */ extern os_error * xufont_scan_string(ufont_f font, wchar_t const *string, font_string_flags flags, int x, int y, font_scan_block const *block, os_trfm const *trfm, unsigned int length, int *split_length, int *x_out, int *y_out, int *length_out) { char *result; char *split_point; unsigned int *table; os_error *error; if ((flags & font_GIVEN_LENGTH) == 0) length = 0x7fffffff; error = xufont_convert(font, string, length, &result, &table); if (error != NULL) return error; /* #ifdef DEBUG */ /* { */ /* unsigned int i; */ /* for (i = 0; i < 200; i++) */ /* printf("%i ", table[i]); */ /* printf("\n"); */ /* } */ /* #endif */ error = xfont_scan_string((font_f) result[1], result, (flags & (~font_GIVEN_LENGTH)) | font_GIVEN_FONT, x, y, block, trfm, 0, &split_point, x_out, y_out, length_out); if (error != NULL) { free(result); return error; } if (split_length != NULL) *split_length = table[split_point - result]; free(result); free(table); return NULL; }