mirror of
https://github.com/kevinbentley/Descent3.git
synced 2025-01-22 11:28:56 +00:00
de0af3b10d
``` git grep -l mem_malloc | xargs perl -i -lpe 's{\((uint8_t) \*\)mem_malloc\((\S+)\)}{mem_rmalloc<$1>($2)}' ```
748 lines
21 KiB
C++
748 lines
21 KiB
C++
/*
|
|
* Descent 3
|
|
* Copyright (C) 2024 Parallax Software
|
|
*
|
|
* 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 3 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.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
--- HISTORICAL COMMENTS FOLLOW ---
|
|
|
|
* $Logfile: /DescentIII/Main/2dlib/font.cpp $
|
|
* $Revision: 15 $
|
|
* $Date: 4/17/99 6:15p $
|
|
* $Author: Samir $
|
|
*
|
|
* will load and manage a font's capabilities.
|
|
*
|
|
* $Log: /DescentIII/Main/2dlib/font.cpp $
|
|
*
|
|
* 15 4/17/99 6:15p Samir
|
|
* replaced gr.h with grdefs.h and fixed resulting compile bugs.
|
|
*
|
|
* 14 10/13/98 10:31a Sean
|
|
* Fixed a mem_free (free()) conflict
|
|
*
|
|
* 13 4/23/98 6:38p Jason
|
|
* made bitmaps use 1555 format
|
|
*
|
|
* 12 3/31/98 3:48p Jason
|
|
* added memory lib
|
|
*
|
|
* 11 12/19/97 12:31p Samir
|
|
* load font registration
|
|
*
|
|
* 10 12/12/97 6:40p Samir
|
|
* Some viewport font functions.
|
|
*
|
|
* 9 11/16/97 6:53p Samir
|
|
* Reinstated instance count for fonts.
|
|
*
|
|
* 8 11/16/97 4:41p Matt
|
|
* Commented-out an assert.
|
|
*
|
|
* 7 11/14/97 12:06p Samir
|
|
* When you use a font for the first time, load it. Never free font until
|
|
* game closes.
|
|
*
|
|
* 6 10/15/97 5:20p Jason
|
|
* did a HUGE overhaul of the bitmap system
|
|
*
|
|
* 5 9/26/97 2:53p Samir
|
|
* Delete old m_CharSurf if creating a new one.
|
|
*
|
|
* 4 9/19/97 5:37p Samir
|
|
* Software font coloring works.
|
|
*
|
|
* 3 8/07/97 3:15p Samir
|
|
* May have fixed horizontal left clipping problem.
|
|
*
|
|
* 22 6/25/97 10:10a Samir
|
|
* Removed unused code causing warning.
|
|
*
|
|
* 21 6/24/97 7:42p Matt
|
|
* Included bitmap.h instead of font.h
|
|
*
|
|
* 20 6/16/97 4:45p Samir
|
|
* Fixed transparency probs
|
|
*
|
|
* 19 6/16/97 3:01p Samir
|
|
* Changed font system to work better with renderer. Fonts are rendered
|
|
* on bitmaps of 128x128 at load time.
|
|
*
|
|
* 18 6/12/97 6:27p Samir
|
|
* DDGR v2.0 (GR v1.1) Changes to ddgr system reflected in 2d system
|
|
*
|
|
* 17 5/14/97 8:07p Samir
|
|
* some pathname problem which screwed up Mac.
|
|
*
|
|
* 16 3/07/97 4:01p Samir
|
|
* Took out malloc.h for ANSI compliance.
|
|
*
|
|
* 15 3/03/97 6:20p Matt
|
|
* Changed cfile functions to use D3 naming convention
|
|
*
|
|
* 14 2/28/97 3:17 PM Jeremy
|
|
* changed a call of strcmpi to stricmp
|
|
*
|
|
* 13 2/28/97 2:57p Samir
|
|
* Took out __cdecl from atexit
|
|
*
|
|
* 12 2/10/97 12:14p Samir
|
|
* Allow multiple font loading per viewport.
|
|
*
|
|
* 11 2/06/97 6:33p Samir
|
|
* Added clipping character functions for font.
|
|
*
|
|
* 10 2/06/97 12:43p Samir
|
|
* Mono fonts work.
|
|
*
|
|
* 9 2/05/97 12:19p Samir
|
|
* Stopped redundant increases in font reference count for same font
|
|
* object.
|
|
*
|
|
* 8 2/05/97 10:35a Samir
|
|
* Fixed text drawing at wrong location problem
|
|
*
|
|
* $NoKeywords: $
|
|
*/
|
|
|
|
#include <cstring>
|
|
#include <cstdlib>
|
|
|
|
#include "bitmap.h"
|
|
#include "cfile.h"
|
|
#include "gr.h"
|
|
#include "log.h"
|
|
#include "mem.h"
|
|
#include "pserror.h"
|
|
#include "renderer.h"
|
|
|
|
#define FT_COLOR 1
|
|
#define FT_PROPORTIONAL 2
|
|
#define FT_KERNED 4
|
|
#define FT_GRADIENT 8
|
|
|
|
#define GRFONT_SURFACE_WIDTH 128
|
|
#define GRFONT_SURFACE_HEIGHT 128
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// Macros for file io.
|
|
// ----------------------------------------------------------------------------
|
|
|
|
typedef CFILE *FONTFILE;
|
|
|
|
static inline int READ_FONT_INT(FONTFILE ffile);
|
|
static inline int16_t READ_FONT_SHORT(FONTFILE ffile);
|
|
static inline uint8_t READ_FONT_BYTE(FONTFILE ffile);
|
|
static inline int READ_FONT_DATA(FONTFILE ffile, void *buf, int size, int nelem);
|
|
static inline FONTFILE OPEN_FONT(const char *filename, bool &success);
|
|
static inline void CLOSE_FONT(FONTFILE ffile);
|
|
|
|
#define BITS_TO_BYTES(_c) (((_c) + 7) >> 3)
|
|
#define BITS_TO_SHORTS(_c) (((_c) + 15) >> 4)
|
|
|
|
inline int READ_FONT_INT(FONTFILE ffile) { return cf_ReadInt(ffile); }
|
|
|
|
inline int16_t READ_FONT_SHORT(FONTFILE ffile) { return cf_ReadShort(ffile); }
|
|
|
|
inline uint8_t READ_FONT_BYTE(FONTFILE ffile) { return (uint8_t)cf_ReadByte(ffile); }
|
|
|
|
inline int READ_FONT_DATA(FONTFILE ffile, void *buf, int size, int nelem) {
|
|
int i;
|
|
|
|
i = cf_ReadBytes((uint8_t *)buf, size * nelem, ffile);
|
|
|
|
ASSERT(i == (size * nelem));
|
|
|
|
return i;
|
|
}
|
|
|
|
inline FONTFILE OPEN_FONT(const char *filename, bool &success) {
|
|
FONTFILE fp;
|
|
int file_id;
|
|
|
|
success = false;
|
|
fp = (FONTFILE)cfopen(filename, "rb");
|
|
if (!fp)
|
|
return NULL;
|
|
|
|
file_id = READ_FONT_INT(fp);
|
|
if (file_id != 0xfeedbaba)
|
|
return (FONTFILE)(-1);
|
|
|
|
success = true;
|
|
return fp;
|
|
}
|
|
|
|
inline void CLOSE_FONT(FONTFILE ffile) { cfclose(ffile); }
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// static variables and functions
|
|
// ----------------------------------------------------------------------------
|
|
|
|
gr_font_record grFont::m_FontList[MAX_FONTS];
|
|
grMemorySurface *grFont::m_CharSurf = NULL;
|
|
|
|
void grFont::init_system() {
|
|
for (int i = 0; i < MAX_FONTS; i++) {
|
|
grFont::m_FontList[i].references = 0;
|
|
grFont::m_FontList[i].filename[0] = 0;
|
|
}
|
|
|
|
if (grFont::m_CharSurf) {
|
|
delete grFont::m_CharSurf;
|
|
grFont::m_CharSurf = NULL;
|
|
}
|
|
|
|
if (!grFont::m_CharSurf) {
|
|
grFont::m_CharSurf = new grMemorySurface;
|
|
grFont::m_CharSurf->init(0, 0, BPP_16, NULL, 0, 0, "char_surf");
|
|
}
|
|
|
|
atexit(grFont::close_system);
|
|
}
|
|
|
|
void grFont::close_system() {
|
|
if (grFont::m_CharSurf) {
|
|
delete grFont::m_CharSurf;
|
|
grFont::m_CharSurf = NULL;
|
|
}
|
|
|
|
// we should free any fonts currently allocated here.
|
|
LOG_DEBUG << "Freeing cached fonts...";
|
|
for (int i = 0; i < MAX_FONTS; i++) {
|
|
gr_font_record *ft;
|
|
if (grFont::m_FontList[i].references) {
|
|
ft = &grFont::m_FontList[i];
|
|
grFont::free_font(ft);
|
|
grFont::m_FontList[i].references = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
int grFont::register_font(char *fontname, char *filename) {
|
|
/* look for a slot with no fontname and place fontname in it */
|
|
ASSERT(fontname != NULL);
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < MAX_FONTS; i++) {
|
|
if (grFont::m_FontList[i].filename[0] == 0) {
|
|
strcpy(grFont::m_FontList[i].filename, filename);
|
|
strcpy(grFont::m_FontList[i].name, fontname);
|
|
grFont::load(m_FontList[i].filename, i);
|
|
grFont::m_FontList[i].references = 1;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (i == MAX_FONTS)
|
|
i = -1;
|
|
|
|
return i;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// constructor and destructor of font object
|
|
// ----------------------------------------------------------------------------
|
|
|
|
grFont::grFont() { m_FontHandle = -1; }
|
|
|
|
grFont::~grFont() {
|
|
if (m_FontHandle > -1)
|
|
grFont::free();
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// high level font initialization and cleanup routines
|
|
// ----------------------------------------------------------------------------
|
|
|
|
void grFont::init(const char *fontname) {
|
|
int i, slot = -1;
|
|
|
|
// Look for this font in the list, check if it has any references, and load it if
|
|
// there are none.
|
|
if (fontname == NULL) {
|
|
slot = 0;
|
|
} else {
|
|
for (i = 0; i < MAX_FONTS; i++) {
|
|
if (stricmp(grFont::m_FontList[i].name, fontname) == 0) {
|
|
slot = i;
|
|
|
|
if (grFont::m_FontList[i].references == 0) {
|
|
break;
|
|
} else {
|
|
m_FontHandle = slot;
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
ASSERT(slot != -1);
|
|
|
|
// clear up surface and bitmap lists
|
|
grFont::m_FontList[slot].ch_w = NULL;
|
|
grFont::m_FontList[slot].ch_h = NULL;
|
|
grFont::m_FontList[slot].ch_u = NULL;
|
|
grFont::m_FontList[slot].ch_v = NULL;
|
|
|
|
for (i = 0; i < MAX_FONT_BITMAPS; i++) {
|
|
grFont::m_FontList[slot].bmps[i] = -1;
|
|
grFont::m_FontList[slot].surfs[i] = NULL;
|
|
}
|
|
|
|
// We must load this font from the 'hogfile'
|
|
grFont::load(m_FontList[slot].filename, slot);
|
|
|
|
grFont::m_FontList[slot].references++;
|
|
}
|
|
|
|
m_FontHandle = slot;
|
|
}
|
|
|
|
void grFont::free() {
|
|
if (m_FontHandle == -1)
|
|
return;
|
|
|
|
return;
|
|
|
|
//!! Removed the following assert because there are bugs in the reference count system. Matt, 11-15-97.
|
|
//!! ASSERT(grFont::m_FontList[m_FontHandle].references > 0);
|
|
//@@
|
|
// free font if there was only one reference left.
|
|
//@@ if (grFont::m_FontList[m_FontHandle].references == 1) {
|
|
//@@ gr_font_record *ft;
|
|
//@@
|
|
//@@ // free up all memory allocated to this font.
|
|
//@@ ft = &grFont::m_FontList[m_FontHandle];
|
|
//@@
|
|
//@@ grFont::free_font(ft);
|
|
//@@ }
|
|
//@@
|
|
//@@ grFont::m_FontList[m_FontHandle].references--;
|
|
m_FontHandle = -1;
|
|
}
|
|
|
|
void grFont::free_font(gr_font_record *ft) {
|
|
int i;
|
|
|
|
// delete font surface info.
|
|
if (ft->ch_wf)
|
|
delete[] ft->ch_wf;
|
|
if (ft->ch_hf)
|
|
delete[] ft->ch_hf;
|
|
if (ft->ch_uf)
|
|
delete[] ft->ch_uf;
|
|
if (ft->ch_vf)
|
|
delete[] ft->ch_vf;
|
|
if (ft->ch_w)
|
|
delete[] ft->ch_w;
|
|
if (ft->ch_h)
|
|
delete[] ft->ch_h;
|
|
if (ft->ch_u)
|
|
delete[] ft->ch_u;
|
|
if (ft->ch_v)
|
|
delete[] ft->ch_v;
|
|
if (ft->ch_surf)
|
|
delete[] ft->ch_surf;
|
|
|
|
for (i = 0; i < MAX_FONT_BITMAPS; i++) {
|
|
if (ft->bmps[i] != -1)
|
|
bm_FreeBitmap(ft->bmps[i]);
|
|
if (ft->surfs[i])
|
|
delete ft->surfs[i];
|
|
}
|
|
|
|
// delete font file info.
|
|
if (ft->font.flags & FT_PROPORTIONAL) {
|
|
delete[] ft->font.char_widths;
|
|
}
|
|
|
|
::mem_free(ft->font.raw_data);
|
|
::mem_free(ft->font.char_data);
|
|
}
|
|
|
|
void grFont::load(char *filename, int slot) {
|
|
FONTFILE ff;
|
|
gr_font_file_record fnt, *ft;
|
|
char fontname[32];
|
|
int num_char;
|
|
int i;
|
|
|
|
ft = &fnt;
|
|
|
|
bool success;
|
|
ff = OPEN_FONT(filename, success);
|
|
if (!ff) {
|
|
Error("Unable to open font in file %s.\n", filename);
|
|
} else if (!success) {
|
|
Error("Illegal font file: %s.\n", filename);
|
|
}
|
|
|
|
ft->width = READ_FONT_SHORT(ff);
|
|
ft->height = READ_FONT_SHORT(ff);
|
|
ft->flags = READ_FONT_SHORT(ff);
|
|
ft->baseline = READ_FONT_SHORT(ff);
|
|
ft->min_ascii = READ_FONT_BYTE(ff);
|
|
ft->max_ascii = READ_FONT_BYTE(ff);
|
|
READ_FONT_DATA(ff, fontname, 32, 1);
|
|
|
|
num_char = ft->max_ascii - ft->min_ascii + 1;
|
|
|
|
// Read in all widths
|
|
if (ft->flags & FT_PROPORTIONAL) {
|
|
ft->char_widths = new int16_t[num_char];
|
|
for (i = 0; i < num_char; i++)
|
|
ft->char_widths[i] = READ_FONT_SHORT(ff);
|
|
} else {
|
|
ft->char_widths = NULL;
|
|
}
|
|
|
|
// Read in pixel data.
|
|
// for color fonts, read in byte count and then the data,
|
|
// generate character data pointer table
|
|
// for mono fonts, read in byte count, then the data, convert to bits and store
|
|
// generate character data pointer table
|
|
int bytesize = READ_FONT_INT(ff);
|
|
|
|
ft->raw_data = mem_rmalloc<uint8_t>(bytesize);
|
|
ft->char_data = mem_rmalloc<uint8_t *>(num_char);
|
|
|
|
READ_FONT_DATA(ff, ft->raw_data, bytesize, 1);
|
|
|
|
if (ft->flags & FT_COLOR) {
|
|
int off = 0;
|
|
for (i = 0; i < num_char; i++) {
|
|
ft->char_data[i] = ft->raw_data + off;
|
|
if (ft->flags & FT_PROPORTIONAL)
|
|
off += (ft->char_widths[i] * ft->height * BITS_TO_BYTES(BPP_16));
|
|
else
|
|
off += (ft->width * ft->height * BITS_TO_BYTES(BPP_16));
|
|
}
|
|
} else { // Monochrome
|
|
uint8_t *ptr = ft->raw_data;
|
|
for (i = 0; i < num_char; i++) {
|
|
ft->char_data[i] = ptr;
|
|
if (ft->flags & FT_PROPORTIONAL)
|
|
ptr += BITS_TO_BYTES(ft->char_widths[i]) * ft->height;
|
|
else
|
|
ptr += BITS_TO_BYTES(ft->width) * ft->height;
|
|
}
|
|
}
|
|
|
|
// Read in kerning data
|
|
ft->kern_data = NULL;
|
|
|
|
// Then read in
|
|
CLOSE_FONT(ff);
|
|
LOG_DEBUG.printf("%s font: <ht %d>::<min %d>::<max %d>::<base %d>::<proportional %d>::<color %d>",
|
|
grFont::m_FontList[slot].name, ft->height, ft->min_ascii, ft->max_ascii, ft->baseline,
|
|
ft->flags & FT_PROPORTIONAL, ft->flags & FT_COLOR);
|
|
|
|
grFont::m_FontList[slot].font = fnt;
|
|
|
|
// draw font to bitmaps, load into surfaces too.
|
|
grFont::translate_to_surfaces(slot);
|
|
}
|
|
|
|
// translates a font to surfaces
|
|
void grFont::translate_to_surfaces(int slot) {
|
|
gr_font_file_record *fntfile;
|
|
gr_font_record *fnt;
|
|
|
|
fnt = &grFont::m_FontList[slot];
|
|
fntfile = &grFont::m_FontList[slot].font;
|
|
|
|
// start creating font surfaces, map these surfaces onto bitmaps created via bitmap library
|
|
// this is needed for the renderer library.
|
|
// create a 128x128 surface first.
|
|
// draw each character into surface until we need to create another
|
|
// surface.
|
|
uint8_t u = 0, v = 0, w;
|
|
int ch, num_ch;
|
|
uint8_t surf_index = 0;
|
|
|
|
num_ch = fntfile->max_ascii - fntfile->min_ascii + 1;
|
|
|
|
// initialize memory
|
|
fnt->ch_w = new uint8_t[num_ch];
|
|
fnt->ch_h = new uint8_t[num_ch];
|
|
fnt->ch_u = new uint8_t[num_ch];
|
|
fnt->ch_v = new uint8_t[num_ch];
|
|
fnt->ch_surf = new uint8_t[num_ch];
|
|
fnt->ch_uf = new float[num_ch];
|
|
fnt->ch_vf = new float[num_ch];
|
|
fnt->ch_wf = new float[num_ch];
|
|
fnt->ch_hf = new float[num_ch];
|
|
|
|
fnt->bmps[surf_index] = bm_AllocBitmap(GRFONT_SURFACE_WIDTH, GRFONT_SURFACE_HEIGHT, 0);
|
|
if (fnt->bmps[surf_index] == -1)
|
|
Error("grFont::translate_to_surfaces <Bitmap allocation error>");
|
|
fnt->surfs[surf_index] = new grMemorySurface;
|
|
fnt->surfs[surf_index]->init(GRFONT_SURFACE_WIDTH, GRFONT_SURFACE_HEIGHT, BPP_16,
|
|
(char *)bm_data(fnt->bmps[surf_index], 0), GRFONT_SURFACE_WIDTH * BITS_TO_BYTES(BPP_16),
|
|
SURFFLAG_COLORKEY);
|
|
fnt->surfs[surf_index]->clear(TRANSPARENT_COLOR32);
|
|
surf_index++;
|
|
|
|
for (ch = 0; ch < num_ch; ch++) {
|
|
if (fntfile->flags & FT_PROPORTIONAL)
|
|
w = (int)fntfile->char_widths[ch];
|
|
else
|
|
w = (int)fntfile->width;
|
|
|
|
// blt each character
|
|
if (fntfile->flags & FT_COLOR) {
|
|
m_CharSurf->init(w, fntfile->height, BPP_16, (char *)fntfile->char_data[ch], w * BITS_TO_BYTES(BPP_16),
|
|
SURFFLAG_COLORKEY);
|
|
|
|
fnt->surfs[surf_index - 1]->blt(u, v, m_CharSurf);
|
|
} else { // font monochrome, convert bits to pixels
|
|
grFont::translate_mono_char(fnt->surfs[surf_index - 1], u, v, ch, fntfile, w);
|
|
}
|
|
|
|
fnt->ch_h[ch] = fntfile->height;
|
|
fnt->ch_w[ch] = w;
|
|
fnt->ch_u[ch] = u;
|
|
fnt->ch_v[ch] = v;
|
|
fnt->ch_surf[ch] = surf_index - 1;
|
|
fnt->ch_hf[ch] = ((float)fntfile->height) / ((float)GRFONT_SURFACE_HEIGHT);
|
|
fnt->ch_wf[ch] = ((float)w) / ((float)GRFONT_SURFACE_WIDTH);
|
|
fnt->ch_uf[ch] = ((float)u) / ((float)GRFONT_SURFACE_WIDTH);
|
|
fnt->ch_vf[ch] = ((float)v) / ((float)GRFONT_SURFACE_HEIGHT);
|
|
|
|
// check to adjust uv's if we are outside surface.
|
|
u += w;
|
|
if ((u + w) > GRFONT_SURFACE_WIDTH) {
|
|
u = 0;
|
|
v += fntfile->height;
|
|
if ((v + fntfile->height) > GRFONT_SURFACE_HEIGHT) {
|
|
if (surf_index == MAX_FONT_BITMAPS)
|
|
Int3();
|
|
fnt->bmps[surf_index] = bm_AllocBitmap(GRFONT_SURFACE_WIDTH, GRFONT_SURFACE_HEIGHT, 0);
|
|
if (fnt->bmps[surf_index] == -1)
|
|
Error("grFont::translate_to_surfaces <Bitmap allocation error>");
|
|
fnt->surfs[surf_index] = new grMemorySurface;
|
|
fnt->surfs[surf_index]->init(GRFONT_SURFACE_WIDTH, GRFONT_SURFACE_HEIGHT, BPP_16,
|
|
(char *)bm_data(fnt->bmps[surf_index], 0),
|
|
GRFONT_SURFACE_WIDTH * BITS_TO_BYTES(BPP_16), SURFFLAG_COLORKEY);
|
|
fnt->surfs[surf_index]->clear(TRANSPARENT_COLOR32);
|
|
surf_index++;
|
|
v = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// translate mono font data to the surface
|
|
void grFont::translate_mono_char(grSurface *sf, int x, int y, int index, gr_font_file_record *ft, int width) {
|
|
int row, col; // byte width of char
|
|
int rowsize;
|
|
uint8_t bit_mask = 0, byte = 0;
|
|
uint8_t *fp;
|
|
|
|
fp = ft->char_data[index];
|
|
|
|
switch (sf->bpp()) {
|
|
case BPP_16: {
|
|
/* draw one-bit one color. */
|
|
uint16_t *dest_ptr;
|
|
uint16_t col_w = GR_COLOR_TO_16(GR_RGB(255, 255, 255));
|
|
int rowsize_w;
|
|
|
|
dest_ptr = (uint16_t *)sf->lock(&rowsize);
|
|
rowsize_w = sf->rowsize() / 2;
|
|
dest_ptr += (y * rowsize_w) + x;
|
|
|
|
for (row = 0; row < ft->height; row++) {
|
|
bit_mask = 0;
|
|
for (col = 0; col < width; col++) {
|
|
if (bit_mask == 0) {
|
|
byte = *fp++;
|
|
bit_mask = 0x80;
|
|
}
|
|
|
|
if (byte & bit_mask)
|
|
dest_ptr[col] = col_w;
|
|
bit_mask >>= 1;
|
|
}
|
|
dest_ptr += rowsize_w;
|
|
}
|
|
|
|
sf->unlock();
|
|
break;
|
|
}
|
|
|
|
case BPP_32:
|
|
default:
|
|
Int3(); // NOT SUPPORTED YET
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// draw_char function
|
|
// give a viewport x,y and char
|
|
// ----------------------------------------------------------------------------
|
|
|
|
int grFont::draw_char(grSurface *sf, int x, int y, int ch, tCharProperties *chprop) {
|
|
gr_font_record *ft;
|
|
int next_x = 0, width, index;
|
|
|
|
ASSERT(m_FontHandle > -1);
|
|
if ((ch < min_ascii()) || (ch > max_ascii()))
|
|
return (next_x + 1);
|
|
|
|
// save current x and get this font
|
|
ft = &grFont::m_FontList[m_FontHandle];
|
|
next_x = x;
|
|
index = ch - ft->font.min_ascii;
|
|
|
|
// draw either a color bitmap or mono font.
|
|
if (ft->font.flags & FT_PROPORTIONAL) {
|
|
width = (int)ft->font.char_widths[index];
|
|
} else {
|
|
width = (int)ft->font.width;
|
|
}
|
|
|
|
// perform blt.
|
|
if (sf->get_flags() & SURFFLAG_RENDERER) {
|
|
rend_SetCharacterParameters(chprop->col[0], chprop->col[1], chprop->col[2], chprop->col[3]);
|
|
rend_DrawFontCharacter(ft->bmps[ft->ch_surf[index]], x, y, x + ft->ch_w[index] - 1, y + ft->ch_h[index] - 1,
|
|
ft->ch_uf[index], ft->ch_vf[index], ft->ch_wf[index], ft->ch_hf[index]);
|
|
} else if (ft->font.flags & FT_COLOR) {
|
|
sf->blt(x, y, ft->surfs[ft->ch_surf[index]], ft->ch_u[index], ft->ch_v[index], ft->ch_w[index], ft->ch_h[index]);
|
|
} else {
|
|
charblt16(sf, chprop->col[0], x, y, ft->surfs[ft->ch_surf[index]], ft->ch_u[index], ft->ch_v[index],
|
|
ft->ch_w[index], ft->ch_h[index]);
|
|
}
|
|
|
|
// adjust next x value with kerning and return it.
|
|
next_x += width;
|
|
|
|
return next_x;
|
|
}
|
|
|
|
int grFont::draw_char(grSurface *sf, int x, int y, int ch, int sx, int sy, int sw, int sh, tCharProperties *chprop) {
|
|
gr_font_record *ft;
|
|
int next_x = 0, width, index;
|
|
|
|
ASSERT(m_FontHandle > -1);
|
|
if ((ch < min_ascii()) || (ch > max_ascii()))
|
|
return (next_x + 1);
|
|
|
|
// save current x and get this font
|
|
ft = &grFont::m_FontList[m_FontHandle];
|
|
next_x = x;
|
|
index = ch - ft->font.min_ascii;
|
|
|
|
// draw either a color bitmap or mono font.
|
|
if (ft->font.flags & FT_PROPORTIONAL) {
|
|
width = (int)ft->font.char_widths[index];
|
|
} else {
|
|
width = (int)ft->font.width;
|
|
}
|
|
|
|
ASSERT(sx + sw <= width);
|
|
ASSERT(sy + sh <= ft->font.height);
|
|
|
|
// peform blt instead.
|
|
// perform blt.
|
|
if (sf->get_flags() & SURFFLAG_RENDERER) {
|
|
rend_SetCharacterParameters(chprop->col[0], chprop->col[1], chprop->col[2], chprop->col[3]);
|
|
|
|
rend_DrawFontCharacter(ft->bmps[ft->ch_surf[index]], x, y, x + sw - 1, y + sh - 1,
|
|
ft->ch_uf[index] + (((float)sx) / ((float)GRFONT_SURFACE_WIDTH)),
|
|
ft->ch_vf[index] + (((float)sy) / ((float)GRFONT_SURFACE_HEIGHT)),
|
|
((float)sw) / ((float)GRFONT_SURFACE_WIDTH), ((float)sh) / ((float)GRFONT_SURFACE_HEIGHT));
|
|
} else if (ft->font.flags & FT_COLOR) {
|
|
sf->blt(x, y, ft->surfs[ft->ch_surf[index]], ft->ch_u[index] + sx, ft->ch_v[index] + sy, sw, sh);
|
|
} else {
|
|
charblt16(sf, chprop->col[0], x, y, ft->surfs[ft->ch_surf[index]], ft->ch_u[index] + sx, ft->ch_v[index] + sy, sw,
|
|
sh);
|
|
}
|
|
|
|
// adjust next x value with kerning and return it.
|
|
next_x += sw;
|
|
|
|
return next_x;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// accessor functions
|
|
// ----------------------------------------------------------------------------
|
|
|
|
int grFont::get_char_info(int ch, int *width) {
|
|
gr_font_file_record *ft;
|
|
|
|
ASSERT(m_FontHandle > -1);
|
|
|
|
ft = &grFont::m_FontList[m_FontHandle].font;
|
|
|
|
if (ch < ft->min_ascii || ch > ft->max_ascii)
|
|
*width = 0;
|
|
else if (ft->flags & FT_PROPORTIONAL)
|
|
*width = ft->char_widths[ch - ft->min_ascii];
|
|
else
|
|
*width = ft->width;
|
|
|
|
return 0;
|
|
}
|
|
|
|
uint8_t *grFont::get_kern_info(uint8_t c1, uint8_t c2) {
|
|
// gr_font_file_record *ft;
|
|
// uint8_t *p;
|
|
|
|
// p = ft->kern_data;
|
|
// ft = &grFont::m_FontList[m_FontHandle].font;
|
|
// c2 = c2 - ft->min_ascii;
|
|
// c1 = c1 - ft->min_ascii;
|
|
|
|
// while (*p!=255)
|
|
// {
|
|
// if (p[0]==c1 && p[1]==c2) return p;
|
|
// else p+=3;
|
|
// }
|
|
|
|
return NULL;
|
|
}
|
|
|
|
void grFont::charblt16(grSurface *dsf, ddgr_color col, int dx, int dy, grSurface *ssf, int sx, int sy, int sw, int sh) {
|
|
uint16_t *dbits;
|
|
uint16_t *sbits;
|
|
int srowsize_w, drowsize_w, row, coln;
|
|
uint16_t scol = GR_COLOR_TO_16(col);
|
|
|
|
dbits = (uint16_t *)dsf->lock(&drowsize_w);
|
|
if (dbits) {
|
|
sbits = (uint16_t *)ssf->lock(&srowsize_w);
|
|
if (sbits) {
|
|
srowsize_w >>= 1; // rowsize in shorts
|
|
drowsize_w >>= 1;
|
|
dbits = dbits + (dy * drowsize_w) + dx;
|
|
sbits = sbits + (sy * srowsize_w) + sx;
|
|
|
|
for (row = 0; row < sh; row++) {
|
|
for (coln = 0; coln < sw; coln++) {
|
|
if (sbits[coln] & OPAQUE_FLAG16)
|
|
dbits[coln] = scol;
|
|
}
|
|
sbits += srowsize_w;
|
|
dbits += drowsize_w;
|
|
}
|
|
|
|
ssf->unlock();
|
|
}
|
|
dsf->unlock();
|
|
}
|
|
}
|