/* Copyright (C) 1991-2001 and beyond by Bungie Studios, Inc. and the "Aleph One" developers. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. This license is contained in the file "COPYING", which is included with this source code; it is available online at http://www.gnu.org/licenses/gpl.html */ /* * sdl_fonts.cpp - SDL font handling * * Written in 2000 by Christian Bauer */ #include "cseries.h" #include "sdl_fonts.h" #include "byte_swapping.h" #include "resource_manager.h" #include "FileHandler.h" #include "Logging.h" #include #include #include #ifndef NO_STD_NAMESPACE using std::vector; using std::pair; using std::map; #endif // Global variables typedef pair id_and_size_t; typedef map font_list_t; static font_list_t font_list; // List of all loaded fonts // From shell_sdl.cpp extern vector data_search_path; /* * Initialize font management */ void initialize_fonts(void) { logContext("initializing fonts"); // Open font resource files bool found = false; vector::const_iterator i = data_search_path.begin(), end = data_search_path.end(); while (i != end) { FileSpecifier fonts = *i + "Fonts"; if (open_res_file(fonts)) found = true; i++; } if (!found) { logFatal("Can't open font resource file"); /* vector::const_iterator i = data_search_path.begin(), end = data_search_path.end(); while (i != end) { FileSpecifier fonts = *i + "Fonts"; fdprintf(fonts.GetPath()); i++; } */ exit(1); } } /* * Load font from resources and allocate sdl_font_info */ sdl_font_info *load_font(const TextSpec &spec) { sdl_font_info *info = NULL; // Look for ID/size in list of loaded fonts id_and_size_t id_and_size(spec.font, spec.size); font_list_t::const_iterator it = font_list.find(id_and_size); if (it != font_list.end()) { // already loaded info = it->second; info->ref_count++; return info; } // Load font family resource LoadedResource fond; if (!get_resource(FOUR_CHARS_TO_INT('F', 'O', 'N', 'D'), spec.font, fond)) { fprintf(stderr, "Font family resource for font ID %d not found\n", spec.font); return NULL; } SDL_RWops *p = SDL_RWFromMem(fond.GetPointer(), (int)fond.GetLength()); assert(p); // Look for font size in association table SDL_RWseek(p, 52, SEEK_SET); int num_assoc = SDL_ReadBE16(p) + 1; while (num_assoc--) { int size = SDL_ReadBE16(p); SDL_ReadBE16(p); // skip style int id = SDL_ReadBE16(p); if (size == spec.size) { // Size found, load bitmap font resource info = new sdl_font_info; if (!get_resource(FOUR_CHARS_TO_INT('N', 'F', 'N', 'T'), id, info->rsrc)) get_resource(FOUR_CHARS_TO_INT('F', 'O', 'N', 'T'), id, info->rsrc); if (info->rsrc.IsLoaded()) { // Found, switch stream to font resource SDL_RWclose(p); p = SDL_RWFromMem(info->rsrc.GetPointer(), (int)info->rsrc.GetLength()); assert(p); void *font_ptr = info->rsrc.GetPointer(true); // Read font information SDL_RWseek(p, 2, SEEK_CUR); info->first_character = static_cast(SDL_ReadBE16(p)); info->last_character = static_cast(SDL_ReadBE16(p)); SDL_RWseek(p, 2, SEEK_CUR); info->maximum_kerning = SDL_ReadBE16(p); SDL_RWseek(p, 2, SEEK_CUR); info->rect_width = SDL_ReadBE16(p); info->rect_height = SDL_ReadBE16(p); SDL_RWseek(p, 2, SEEK_CUR); info->ascent = SDL_ReadBE16(p); info->descent = SDL_ReadBE16(p); info->leading = SDL_ReadBE16(p); int bytes_per_row = SDL_ReadBE16(p) * 2; //printf(" first %d, last %d, max_kern %d, rect_w %d, rect_h %d, ascent %d, descent %d, leading %d, bytes_per_row %d\n", // info->first_character, info->last_character, info->maximum_kerning, // info->rect_width, info->rect_height, info->ascent, info->descent, info->leading, bytes_per_row); // Convert bitmap to pixmap (1 byte/pixel) info->bytes_per_row = bytes_per_row * 8; uint8 *src = (uint8 *)font_ptr + SDL_RWtell(p); uint8 *dst = info->pixmap = (uint8 *)malloc(info->rect_height * info->bytes_per_row); assert(dst); for (int y=0; yrect_height; y++) { for (int x=0; xrect_height * bytes_per_row, SEEK_CUR); // Set table pointers int table_size = info->last_character - info->first_character + 3; // Tables contain 2 additional entries info->location_table = (uint16 *)((uint8 *)font_ptr + SDL_RWtell(p)); byte_swap_memory(info->location_table, _2byte, table_size); SDL_RWseek(p, table_size * 2, SEEK_CUR); info->width_table = (int8 *)font_ptr + SDL_RWtell(p); // Add font information to list of known fonts info->ref_count++; font_list[id_and_size] = info; } else { delete info; info = NULL; fprintf(stderr, "Bitmap font resource ID %d not found\n", id); } } } // Free resources SDL_RWclose(p); return info; } /* * Unload font, free sdl_font_info */ void unload_font(sdl_font_info *info) { // Look for font in list of loaded fonts font_list_t::const_iterator i = font_list.begin(), end = font_list.end(); while (i != end) { if (i->second == info) { // Found, decrement reference counter and delete info->ref_count--; if (info->ref_count <= 0) { delete info; font_list.erase(i->first); return; } } i++; } }