mirror of
https://github.com/olikraus/u8g2.git
synced 2026-07-28 04:16:07 +00:00
bdfconv
This commit is contained in:
@@ -0,0 +1,22 @@
|
||||
# works within ubuntu and min-gw (win7) environment
|
||||
# win7 exe uploaded on google drive
|
||||
|
||||
CFLAGS = -g -Wall
|
||||
#CFLAGS = -O4 -Wall
|
||||
|
||||
SRC = main.c bdf_font.c bdf_glyph.c bdf_parser.c bdf_map.c bdf_rle.c bdf_tga.c fd.c bdf_8x8.c
|
||||
|
||||
OBJ = $(SRC:.c=.o)
|
||||
ASM = $(SRC:.c=.s)
|
||||
|
||||
.c.s:
|
||||
$(CC) $(CFLAGS) -S -o $@ $<
|
||||
|
||||
bdfconv: $(OBJ) $(ASM)
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) $(OBJ) -o bdfconv
|
||||
|
||||
clean:
|
||||
-rm $(OBJ) $(ASM) bdfconv
|
||||
|
||||
test:
|
||||
./bdfconv
|
||||
@@ -0,0 +1,180 @@
|
||||
/*
|
||||
|
||||
bdf_8x8.c
|
||||
|
||||
unencoded font format for 8x8 pixel font
|
||||
|
||||
offset bytes desc
|
||||
0 1 first char
|
||||
1 2 last char
|
||||
2 n font data, n = (last char - first char + 1)*8
|
||||
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include "bdf_font.h"
|
||||
|
||||
|
||||
int bg_8x8_convert(bg_t *bg, bbx_t *bbx)
|
||||
{
|
||||
int x;
|
||||
int y;
|
||||
int d;
|
||||
|
||||
if ( bbx == NULL )
|
||||
bbx = &(bg->bbx);
|
||||
|
||||
bg_ClearTargetData(bg);
|
||||
|
||||
if ( bbx->w != 8 )
|
||||
return 0;
|
||||
if ( bbx->h != 8 )
|
||||
return 0;
|
||||
|
||||
|
||||
/*
|
||||
for( y = bbx->y+bbx->h-1; y >= bbx->y; y--)
|
||||
{
|
||||
d = 0;
|
||||
for( x = bbx->x; x < bbx->x + bbx->w; x++)
|
||||
{
|
||||
d <<= 1;
|
||||
if ( bg_GetBBXPixel(bg, x, y) != 0 )
|
||||
{
|
||||
d++;
|
||||
}
|
||||
}
|
||||
if ( bg_AddTargetData(bg, d) < 0 )
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
|
||||
for( x = bbx->x; x < bbx->x + bbx->w; x++)
|
||||
{
|
||||
d = 0;
|
||||
for( y = bbx->y+bbx->h-1; y >= bbx->y; y--)
|
||||
{
|
||||
d >>= 1;
|
||||
if ( bg_GetBBXPixel(bg, x, y) != 0 )
|
||||
{
|
||||
d |= 128;
|
||||
}
|
||||
}
|
||||
if ( bg_AddTargetData(bg, d) < 0 )
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
void bf_Generate8x8Font(bf_t *bf)
|
||||
{
|
||||
int i, j, k;
|
||||
bg_t *bg;
|
||||
int first, last;
|
||||
bbx_t local_bbx;
|
||||
int is_glyph_written;
|
||||
|
||||
/* Step 1: Generate 8x8 bitmap data */
|
||||
|
||||
for( i = 0; i < bf->glyph_cnt; i++ )
|
||||
{
|
||||
bg = bf->glyph_list[i];
|
||||
if ( bg->map_to >= 0 )
|
||||
{
|
||||
bf_copy_bbx_and_update_shift(bf, &local_bbx, bg);
|
||||
|
||||
if ( local_bbx.w != 8 )
|
||||
{
|
||||
bf_Log(bf, "Generate8x8Font: Error, glyph width is not 8, width=%d, encoding=%d", local_bbx.w, bg->encoding);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( local_bbx.h != 8 )
|
||||
{
|
||||
bf_Log(bf, "Generate8x8Font: Error, glyph height is not 8, height=%d, encoding=%d", local_bbx.h, bg->encoding);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( bg_8x8_convert(bg, &local_bbx) == 0 )
|
||||
{
|
||||
bf_Log(bf, "Generate8x8Font: Error, 8x8 conversion, encoding=%d", bg->target_cnt, bg->encoding);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Step 2: Calculate first and last char */
|
||||
|
||||
first = -1;
|
||||
last = -1;
|
||||
|
||||
for( j = 0; j < 256; j++ )
|
||||
{
|
||||
for( i = 0; i < bf->glyph_cnt; i++ )
|
||||
{
|
||||
bg = bf->glyph_list[i];
|
||||
if ( bg->map_to == j )
|
||||
{
|
||||
if ( bg->target_data != NULL )
|
||||
{
|
||||
|
||||
if ( bg->target_cnt != 8)
|
||||
{
|
||||
bf_Log(bf, "Generate8x8Font: Error, glyph size is not 8, size=%d, encoding=%d", bg->target_cnt, bg->encoding);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( first < 0 )
|
||||
first = j;
|
||||
last = j;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Step 3: Write font data */
|
||||
|
||||
bf_AddTargetData(bf, first);
|
||||
bf_AddTargetData(bf, last);
|
||||
|
||||
|
||||
for( j = first; j <= last; j++ )
|
||||
{
|
||||
is_glyph_written = 0;
|
||||
for( i = 0; i < bf->glyph_cnt; i++ )
|
||||
{
|
||||
bg = bf->glyph_list[i];
|
||||
if ( bg->map_to == j )
|
||||
{
|
||||
if ( bg->target_data != NULL )
|
||||
{
|
||||
|
||||
if ( bg->target_cnt == 8)
|
||||
{
|
||||
for( k = 0; k < bg->target_cnt; k++ )
|
||||
{
|
||||
bf_AddTargetData(bf, bg->target_data[k]);
|
||||
}
|
||||
is_glyph_written = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( is_glyph_written == 0 )
|
||||
{
|
||||
for( k = 0; k < 8; k++ )
|
||||
{
|
||||
bf_AddTargetData(bf, 0);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bf_Log(bf, "Generate8x8Font: Font size %d", bf->target_cnt);
|
||||
}
|
||||
@@ -0,0 +1,685 @@
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include "bdf_font.h"
|
||||
|
||||
void bf_Error(bf_t *bf, char *fmt, ...)
|
||||
{
|
||||
va_list va;
|
||||
va_start(va, fmt);
|
||||
vprintf(fmt, va);
|
||||
printf("\n");
|
||||
va_end(va);
|
||||
}
|
||||
|
||||
void bf_Log(bf_t *bf, char *fmt, ...)
|
||||
{
|
||||
va_list va;
|
||||
va_start(va, fmt);
|
||||
if ( bf->is_verbose != 0 )
|
||||
{
|
||||
vprintf(fmt, va);
|
||||
printf("\n");
|
||||
}
|
||||
va_end(va);
|
||||
}
|
||||
|
||||
/*
|
||||
bf_Open(0, BDF_BBX_MODE_MINIMAL)
|
||||
*/
|
||||
bf_t *bf_Open(int is_verbose, int bbx_mode)
|
||||
{
|
||||
bf_t *bf;
|
||||
bf = (bf_t *)malloc(sizeof(bf_t));
|
||||
if ( bf != NULL )
|
||||
{
|
||||
bf->is_verbose = is_verbose;
|
||||
bf->glyph_list = NULL;
|
||||
bf->glyph_cnt = 0;
|
||||
bf->glyph_max = 0;
|
||||
bf->str_font = NULL; /* argument for FONT in bdf file */
|
||||
bf->str_copyright = NULL; /* argument for COPYRIGHT in bdf file */
|
||||
bf->target_data = NULL;
|
||||
bf->target_max = 0;
|
||||
bf->target_cnt = 0;
|
||||
bf->selected_glyphs = 0;
|
||||
|
||||
bf->enc_w = 0;
|
||||
bf->enc_h = 0;
|
||||
bf->enc_x = 0;
|
||||
bf->enc_y = 0;
|
||||
|
||||
bf->bbx_mode = bbx_mode;
|
||||
|
||||
return bf;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void bf_Clear(bf_t *bf)
|
||||
{
|
||||
int i;
|
||||
for( i = 0; i < bf->glyph_cnt; i++ )
|
||||
{
|
||||
free( bf->glyph_list[i] );
|
||||
}
|
||||
bf->glyph_cnt = 0;
|
||||
|
||||
if ( bf->str_font != NULL )
|
||||
free(bf->str_font);
|
||||
bf->str_font = NULL;
|
||||
if ( bf->str_copyright != NULL )
|
||||
free(bf->str_copyright);
|
||||
bf->str_copyright = NULL;
|
||||
}
|
||||
|
||||
void bf_Close(bf_t *bf)
|
||||
{
|
||||
bf_Clear(bf);
|
||||
if ( bf->glyph_list != NULL )
|
||||
free(bf->glyph_list);
|
||||
if ( bf->target_data != NULL )
|
||||
free(bf->target_data);
|
||||
bf->glyph_list = NULL;
|
||||
bf->glyph_max = 0;
|
||||
free(bf);
|
||||
}
|
||||
|
||||
static int bf_extend(bf_t *bf)
|
||||
{
|
||||
int extend = 16;
|
||||
void *ptr;
|
||||
if ( bf->glyph_list == NULL )
|
||||
{
|
||||
ptr = malloc(extend*sizeof(bg_t *));
|
||||
bf->glyph_max = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
ptr = realloc(bf->glyph_list, (bf->glyph_max + extend)*sizeof(bg_t *));
|
||||
}
|
||||
if ( ptr == NULL )
|
||||
return 0;
|
||||
bf->glyph_max += extend;
|
||||
bf->glyph_list = (bg_t **)ptr;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* returns glyph position or -1 */
|
||||
int bf_AddGlyph(bf_t *bf)
|
||||
{
|
||||
while( bf->glyph_max <= bf->glyph_cnt )
|
||||
if ( bf_extend(bf) == 0 )
|
||||
return -1;
|
||||
bf->glyph_list[bf->glyph_cnt] = bg_Open();
|
||||
if ( bf->glyph_list[bf->glyph_cnt] == NULL )
|
||||
return -1;
|
||||
bf->glyph_list[bf->glyph_cnt]->bf = bf;
|
||||
bf->glyph_cnt++;
|
||||
return bf->glyph_cnt-1;
|
||||
}
|
||||
|
||||
|
||||
static int bf_extend_target_data(bf_t *bf)
|
||||
{
|
||||
int extend = 16;
|
||||
int i;
|
||||
void *ptr;
|
||||
if ( bf->target_data == NULL )
|
||||
{
|
||||
ptr = malloc(extend*sizeof(uint8_t));
|
||||
bf->target_max = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
ptr = realloc(bf->target_data, (bf->target_max + extend)*sizeof(uint8_t));
|
||||
}
|
||||
if ( ptr == NULL )
|
||||
return 0;
|
||||
bf->target_data = (uint8_t *)ptr;
|
||||
for( i = bf->target_max; i < bf->target_max + extend; i++ )
|
||||
bf->target_data[i] = 0;
|
||||
bf->target_max += extend;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int bf_AddTargetData(bf_t *bf, uint8_t data)
|
||||
{
|
||||
while( bf->target_max <= bf->target_cnt )
|
||||
if ( bf_extend_target_data(bf) == 0 )
|
||||
return -1;
|
||||
bf->target_data[bf->target_cnt] = data;
|
||||
bf->target_cnt++;
|
||||
return bf->target_cnt-1;
|
||||
}
|
||||
|
||||
void bf_ClearTargetData(bf_t *bf)
|
||||
{
|
||||
int i;
|
||||
for( i = 0; i < bf->target_max; i++ )
|
||||
bf->target_data[i] = 0;
|
||||
bf->target_cnt = 0;
|
||||
}
|
||||
|
||||
void bf_CalculateSelectedNumberOfGlyphs(bf_t *bf)
|
||||
{
|
||||
int i;
|
||||
bg_t *bg;
|
||||
bf->selected_glyphs = 0;
|
||||
|
||||
|
||||
for( i = 0; i < bf->glyph_cnt; i++ )
|
||||
{
|
||||
bg = bf->glyph_list[i];
|
||||
if ( bg->map_to >= 0 )
|
||||
{
|
||||
bf->selected_glyphs++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void bf_ReduceAllGlyph(bf_t *bf)
|
||||
{
|
||||
int i;
|
||||
bg_t *bg;
|
||||
int red_x, red_y;
|
||||
|
||||
bf_Log(bf, "Reduce: Start");
|
||||
|
||||
for( i = 0; i < bf->glyph_cnt; i++ )
|
||||
{
|
||||
bg = bf->glyph_list[i];
|
||||
if ( bg->map_to >= 0 )
|
||||
{
|
||||
bg_ReduceGlyph(bg);
|
||||
//bg_ShowBitmap(bg, &(bg->bbx));
|
||||
red_x = bg->bitmap_width - bg->bbx.w;
|
||||
red_y = bg->bitmap_height - bg->bbx.h;
|
||||
if ( red_x > 0 || red_y > 0 )
|
||||
{
|
||||
//bf_Log(bf, "Reduce: Encoding %ld, x by %d, y by %d", bg->encoding, red_x, red_y);
|
||||
}
|
||||
}
|
||||
}
|
||||
bf_Log(bf, "Reduce: End");
|
||||
|
||||
}
|
||||
|
||||
void bf_ShowAllGlyphs(bf_t *bf, bbx_t *bbx)
|
||||
{
|
||||
int i;
|
||||
bg_t *bg;
|
||||
for( i = 0; i < bf->glyph_cnt; i++ )
|
||||
{
|
||||
bg = bf->glyph_list[i];
|
||||
if ( bg->map_to >= 0 )
|
||||
{
|
||||
bg_ShowBitmap(bg, bbx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int bf_GetIndexByEncoding(bf_t *bf, long encoding)
|
||||
{
|
||||
int i;
|
||||
bg_t *bg;
|
||||
for( i = 0; i < bf->glyph_cnt; i++ )
|
||||
{
|
||||
bg = bf->glyph_list[i];
|
||||
if ( bg->encoding == encoding )
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void bf_CalculateMaxBBX(bf_t *bf)
|
||||
{
|
||||
int i;
|
||||
int is_first = 1;
|
||||
int enc_idx;
|
||||
bg_t *bg;
|
||||
|
||||
|
||||
for( i = 0; i < bf->glyph_cnt; i++ )
|
||||
{
|
||||
bg = bf->glyph_list[i];
|
||||
if ( bg->map_to >= 0 )
|
||||
{
|
||||
if ( is_first != 0 )
|
||||
{
|
||||
bf->max = bg->bbx;
|
||||
bf->enc_x = bg->encoding;
|
||||
bf->enc_y = bg->encoding;
|
||||
bf->enc_w = bg->encoding;
|
||||
bf->enc_h = bg->encoding;
|
||||
is_first = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
enc_idx = bg_Max(bg, &(bf->max));
|
||||
switch(enc_idx)
|
||||
{
|
||||
case 1:
|
||||
bf->enc_w = bg->encoding;
|
||||
break;
|
||||
case 2:
|
||||
bf->enc_h = bg->encoding;
|
||||
break;
|
||||
case 3:
|
||||
bf->enc_x = bg->encoding;
|
||||
break;
|
||||
case 4:
|
||||
bf->enc_y = bg->encoding;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( bf->bbx_mode == BDF_BBX_MODE_M8 )
|
||||
{
|
||||
bf->max.w = ( bf->max.w + 7 ) & ~7;
|
||||
bf->max.h = ( bf->max.h + 7 ) & ~7;
|
||||
}
|
||||
|
||||
|
||||
bf_Log(bf, "CalculateMaxBBX: x=%ld, y=%ld, w=%ld, h=%ld", bf->max.x, bf->max.y, bf->max.w, bf->max.h);
|
||||
bf_Log(bf, "CalculateMaxBBX: Encodings x=%ld, y=%ld, w=%ld, h=%ld", bf->enc_x, bf->enc_y, bf->enc_w, bf->enc_h);
|
||||
}
|
||||
|
||||
void bf_CalculateMinMaxDWidth(bf_t *bf)
|
||||
{
|
||||
int i;
|
||||
bg_t *bg;
|
||||
|
||||
bf->dx_min = 0x07fff;
|
||||
bf->dx_max = -0x07fff;
|
||||
|
||||
bf->x_min = 0x07fff;
|
||||
bf->x_max = -0x07fff;
|
||||
|
||||
for( i = 0; i < bf->glyph_cnt; i++ )
|
||||
{
|
||||
bg = bf->glyph_list[i];
|
||||
if ( bg->map_to >= 0 )
|
||||
{
|
||||
if ( bf->dx_min > bg->dwidth_x )
|
||||
bf->dx_min = bg->dwidth_x;
|
||||
if ( bf->dx_max < bg->dwidth_x )
|
||||
bf->dx_max = bg->dwidth_x;
|
||||
|
||||
if ( bf->x_min > bg->bbx.x )
|
||||
bf->x_min = bg->bbx.x;
|
||||
if ( bf->x_max < bg->bbx.x )
|
||||
bf->x_max = bg->bbx.x;
|
||||
|
||||
}
|
||||
}
|
||||
bf_Log(bf, "bf_CalculateMinMaxDWidth: dx_min=%ld, dx_max=%ld", bf->dx_min, bf->dx_max);
|
||||
bf_Log(bf, "bf_CalculateMinMaxDWidth: x_min=%ld, x_max=%ld", bf->x_min, bf->x_max);
|
||||
if ( bf->dx_min == bf->dx_max && bf->x_min >= 0 )
|
||||
{
|
||||
bf_Log(bf, "bf_CalculateMinMaxDWidth: Monospaced font."); /* not sufficient: also bbx.x must be >= 0 for all glyphs */
|
||||
/* for a monospaced font, dx must be identical to bbx.w */
|
||||
}
|
||||
}
|
||||
|
||||
int get_unsigned_bit_size(unsigned long v)
|
||||
{
|
||||
int i = 0;
|
||||
while( v != 0 )
|
||||
{
|
||||
v = v / 2;
|
||||
i++;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
int get_signed_bit_size(long v)
|
||||
{
|
||||
if ( v < 0 )
|
||||
return get_unsigned_bit_size(-v-1) + 1;
|
||||
return get_unsigned_bit_size(v) + 1;
|
||||
}
|
||||
|
||||
void bf_copy_bbx_and_update_shift(bf_t *bf, bbx_t *target_bbx, bg_t *bg)
|
||||
{
|
||||
/* modifing the following code requires update ind bdf_rle.c also */
|
||||
if ( bf->bbx_mode == BDF_BBX_MODE_MINIMAL )
|
||||
{
|
||||
*target_bbx = bg->bbx;
|
||||
}
|
||||
else if ( bf->bbx_mode == BDF_BBX_MODE_MAX )
|
||||
{
|
||||
*target_bbx = bf->max;
|
||||
target_bbx->x = 0;
|
||||
if ( bg->bbx.x < 0 )
|
||||
bg->shift_x = bg->bbx.x;
|
||||
if ( target_bbx->w < bg->dwidth_x )
|
||||
target_bbx->w = bg->dwidth_x;
|
||||
}
|
||||
else if ( bf->bbx_mode == BDF_BBX_MODE_M8 )
|
||||
{
|
||||
target_bbx->w = bf->max.w;
|
||||
if ( target_bbx->w < bg->dwidth_x )
|
||||
target_bbx->w = bg->dwidth_x;
|
||||
target_bbx->w = (target_bbx->w+7) & ~7;
|
||||
target_bbx->h = (bf->max.h+7) & ~7;
|
||||
target_bbx->x = bf->max.x;
|
||||
target_bbx->y = bf->max.y;
|
||||
target_bbx->x = 0;
|
||||
if ( bg->bbx.x < 0 )
|
||||
bg->shift_x = bg->bbx.x;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
*target_bbx = bf->max;
|
||||
target_bbx->w = bg->bbx.w;
|
||||
target_bbx->x = bg->bbx.x;
|
||||
target_bbx->x = 0;
|
||||
if ( bg->bbx.x < 0 )
|
||||
{
|
||||
/* e.g. "j" */
|
||||
target_bbx->w -= bg->bbx.x;
|
||||
bg->shift_x = bg->bbx.x;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* e.g. "B" */
|
||||
target_bbx->w += bg->bbx.x;
|
||||
//bg->shift_x = bg->bbx.x;
|
||||
}
|
||||
if ( target_bbx->w < bg->dwidth_x )
|
||||
target_bbx->w = bg->dwidth_x;
|
||||
}
|
||||
|
||||
bg->width_deviation = target_bbx->w - bg->bbx.w;
|
||||
}
|
||||
|
||||
void bf_CalculateMaxBitFieldSize(bf_t *bf)
|
||||
{
|
||||
int i;
|
||||
bg_t *bg;
|
||||
int bs;
|
||||
bbx_t local_bbx;
|
||||
bf->bbx_x_max_bit_size = 0;
|
||||
bf->bbx_y_max_bit_size = 0;
|
||||
bf->bbx_w_max_bit_size = 0;
|
||||
bf->bbx_h_max_bit_size = 0;
|
||||
bf->dx_max_bit_size = 0;
|
||||
for( i = 0; i < bf->glyph_cnt; i++ )
|
||||
{
|
||||
bg = bf->glyph_list[i];
|
||||
if ( bg->map_to >= 0 )
|
||||
{
|
||||
|
||||
bf_copy_bbx_and_update_shift(bf, &local_bbx, bg);
|
||||
#ifdef OLD_CLODE
|
||||
/* modifing the following code requires update ind bdf_rle.c also */
|
||||
if ( bf->bbx_mode == BDF_BBX_MODE_MINIMAL )
|
||||
{
|
||||
local_bbx = bg->bbx;
|
||||
}
|
||||
else if ( bf->bbx_mode == BDF_BBX_MODE_MAX )
|
||||
{
|
||||
local_bbx = bf->max;
|
||||
local_bbx.x = 0;
|
||||
if ( bg->bbx.x < 0 )
|
||||
bg->shift_x = bg->bbx.x;
|
||||
if ( local_bbx.w < bg->dwidth_x )
|
||||
local_bbx.w = bg->dwidth_x;
|
||||
}
|
||||
else if ( bf->bbx_mode == BDF_BBX_MODE_M8 )
|
||||
{
|
||||
local_bbx.w = bf->max.w;
|
||||
if ( local_bbx.w < bg->dwidth_x )
|
||||
local_bbx.w = bg->dwidth_x;
|
||||
local_bbx.w = (local_bbx.w+7) & ~7;
|
||||
local_bbx.h = (bf->max.h+7) & ~7;
|
||||
local_bbx.x = bf->max.x;
|
||||
local_bbx.y = bf->max.y;
|
||||
local_bbx.x = 0;
|
||||
if ( bg->bbx.x < 0 )
|
||||
bg->shift_x = bg->bbx.x;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
local_bbx = bf->max;
|
||||
local_bbx.w = bg->bbx.w;
|
||||
local_bbx.x = bg->bbx.x;
|
||||
local_bbx.x = 0;
|
||||
if ( bg->bbx.x < 0 )
|
||||
{
|
||||
/* e.g. "j" */
|
||||
local_bbx.w -= bg->bbx.x;
|
||||
bg->shift_x = bg->bbx.x;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* e.g. "B" */
|
||||
local_bbx.w += bg->bbx.x;
|
||||
//bg->shift_x = bg->bbx.x;
|
||||
}
|
||||
if ( local_bbx.w < bg->dwidth_x )
|
||||
local_bbx.w = bg->dwidth_x;
|
||||
}
|
||||
#endif
|
||||
bs = get_unsigned_bit_size(local_bbx.w);
|
||||
if ( bf->bbx_w_max_bit_size < bs )
|
||||
bf->bbx_w_max_bit_size = bs;
|
||||
|
||||
bs = get_unsigned_bit_size(local_bbx.h);
|
||||
if ( bf->bbx_h_max_bit_size < bs )
|
||||
bf->bbx_h_max_bit_size = bs;
|
||||
|
||||
//printf("%ld ", local_bbx.x);
|
||||
bs = get_signed_bit_size(local_bbx.x);
|
||||
if ( bf->bbx_x_max_bit_size < bs )
|
||||
bf->bbx_x_max_bit_size = bs;
|
||||
//printf("%d:%d ",(int)local_bbx->x, (int)bs);
|
||||
|
||||
bs = get_signed_bit_size(local_bbx.y);
|
||||
if ( bf->bbx_y_max_bit_size < bs )
|
||||
bf->bbx_y_max_bit_size = bs;
|
||||
|
||||
if ( bf->bbx_mode == BDF_BBX_MODE_MINIMAL )
|
||||
{
|
||||
bs = get_signed_bit_size(bg->dwidth_x);
|
||||
}
|
||||
else if ( bf->bbx_mode == BDF_BBX_MODE_MAX )
|
||||
{
|
||||
bs = get_signed_bit_size(local_bbx.w);
|
||||
}
|
||||
else
|
||||
{
|
||||
bs = get_signed_bit_size(local_bbx.w);
|
||||
}
|
||||
if ( bf->dx_max_bit_size < bs )
|
||||
bf->dx_max_bit_size = bs;
|
||||
|
||||
}
|
||||
}
|
||||
bf_Log(bf, "bf_CalculateMaxBitFieldSize: bbx.x=%d, bbx.y=%d, bbx.w=%d, bbx.h=%d, dwidth=%d",
|
||||
bf->bbx_x_max_bit_size, bf->bbx_y_max_bit_size, bf->bbx_w_max_bit_size, bf->bbx_h_max_bit_size, bf->dx_max_bit_size);
|
||||
|
||||
}
|
||||
|
||||
void bf_ShowMonospaceStatistics(bf_t *bf)
|
||||
{
|
||||
int i;
|
||||
bg_t *bg;
|
||||
long cnt = 0;
|
||||
long max = 0;
|
||||
long sum = 0;
|
||||
for( i = 0; i < bf->glyph_cnt; i++ )
|
||||
{
|
||||
bg = bf->glyph_list[i];
|
||||
if ( bg->map_to >= 0 )
|
||||
{
|
||||
if ( max < bg->width_deviation )
|
||||
max = bg->width_deviation;
|
||||
sum += bg->width_deviation;
|
||||
cnt++;
|
||||
}
|
||||
}
|
||||
if ( cnt == 0 )
|
||||
cnt++;
|
||||
bf_Log(bf, "Monospace Statistics: Max width extention %ld, average width extention %ld.%ld", max, sum/cnt, (sum*10/cnt) % 10 );
|
||||
/*
|
||||
Monospaced font: average width extention does not differ much between -b 1 and --b 2
|
||||
Variable width font: big difference for the average width extention between modes 1 and 2.
|
||||
|
||||
Examples:
|
||||
|
||||
./bdfconv -b 1 -v ../bdf/profont12.bdf
|
||||
Monospace Statistics: Max width extention 6, average width extention 1.7
|
||||
./bdfconv -b 2 -v ../bdf/profont12.bdf
|
||||
Monospace Statistics: Max width extention 6, average width extention 1.7
|
||||
--> profont12.bdf is a monospaced font
|
||||
|
||||
./bdfconv -b 1 -v ../bdf/helvR12.bdf
|
||||
Monospace Statistics: Max width extention 6, average width extention 1.9
|
||||
./bdfconv -b 2 -v ../bdf/helvR12.bdf
|
||||
Monospace Statistics: Max width extention 15, average width extention 8.0
|
||||
--> helvR12.bdf is not a monospaced font
|
||||
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
int bf_WriteUCGCByFP(bf_t *bf, FILE *out_fp, const char *fontname, const char *indent)
|
||||
{
|
||||
int i;
|
||||
int bytes_per_line = 16;
|
||||
|
||||
fprintf(out_fp, "/*\n");
|
||||
fprintf(out_fp, " Fontname: %s\n", bf->str_font);
|
||||
fprintf(out_fp, " Copyright: %s\n", bf->str_copyright);
|
||||
fprintf(out_fp, " Glyphs: %d/%d\n", (int)bf->selected_glyphs, (int)bf->glyph_cnt );
|
||||
fprintf(out_fp, " BBX Build Mode: %d\n", (int)bf->bbx_mode);
|
||||
fprintf(out_fp, "*/\n");
|
||||
fprintf(out_fp, "#include \"ucg.h\"\n");
|
||||
fprintf(out_fp, "const ucg_fntpgm_uint8_t %s[%d] UCG_FONT_SECTION(\"%s\") = {\n", fontname, bf->target_cnt, fontname);
|
||||
fprintf(out_fp, " ");
|
||||
|
||||
for( i = 0; i < bf->target_cnt; i++ )
|
||||
{
|
||||
fprintf(out_fp, "%d", bf->target_data[i]);
|
||||
if ( i+1 != bf->target_cnt )
|
||||
fprintf(out_fp, ",");
|
||||
if ( (i+1) % bytes_per_line == 0 )
|
||||
fprintf(out_fp, "\n%s", indent);
|
||||
}
|
||||
|
||||
fprintf(out_fp, "};\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
int bf_WriteU8G2CByFP(bf_t *bf, FILE *out_fp, const char *fontname, const char *indent)
|
||||
{
|
||||
int i;
|
||||
int bytes_per_line = 16;
|
||||
|
||||
fprintf(out_fp, "/*\n");
|
||||
fprintf(out_fp, " Fontname: %s\n", bf->str_font);
|
||||
fprintf(out_fp, " Copyright: %s\n", bf->str_copyright);
|
||||
fprintf(out_fp, " Glyphs: %d/%d\n", (int)bf->selected_glyphs, (int)bf->glyph_cnt );
|
||||
fprintf(out_fp, " BBX Build Mode: %d\n", (int)bf->bbx_mode);
|
||||
fprintf(out_fp, "*/\n");
|
||||
fprintf(out_fp, "#include \"u8g2.h\"\n");
|
||||
fprintf(out_fp, "const uint8_t %s[%d] U8G2_FONT_SECTION(\"%s\") = {\n", fontname, bf->target_cnt, fontname);
|
||||
fprintf(out_fp, " ");
|
||||
|
||||
for( i = 0; i < bf->target_cnt; i++ )
|
||||
{
|
||||
fprintf(out_fp, "%d", bf->target_data[i]);
|
||||
if ( i+1 != bf->target_cnt )
|
||||
fprintf(out_fp, ",");
|
||||
if ( (i+1) % bytes_per_line == 0 )
|
||||
fprintf(out_fp, "\n%s", indent);
|
||||
}
|
||||
|
||||
fprintf(out_fp, "};\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
int bf_WriteUCGCByFilename(bf_t *bf, const char *filename, const char *fontname, const char *indent)
|
||||
{
|
||||
FILE *fp;
|
||||
fp = fopen(filename, "wb");
|
||||
if ( fp == NULL )
|
||||
{
|
||||
bf_Log(bf, "bf_WriteUCGCByFilename: Open error '%s'", filename);
|
||||
return 0;
|
||||
}
|
||||
|
||||
bf_WriteUCGCByFP(bf, fp, fontname, indent);
|
||||
bf_Log(bf, "bf_WriteUCGCByFilename: Write file '%s'", filename);
|
||||
|
||||
fclose(fp);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int bf_WriteU8G2CByFilename(bf_t *bf, const char *filename, const char *fontname, const char *indent)
|
||||
{
|
||||
FILE *fp;
|
||||
fp = fopen(filename, "wb");
|
||||
if ( fp == NULL )
|
||||
{
|
||||
bf_Log(bf, "bf_WriteU8G2CByFilename: Open error '%s'", filename);
|
||||
return 0;
|
||||
}
|
||||
|
||||
bf_WriteU8G2CByFP(bf, fp, fontname, indent);
|
||||
bf_Log(bf, "bf_WriteU8G2CByFilename: Write file '%s'", filename);
|
||||
|
||||
fclose(fp);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bf_t *bf_OpenFromFile(const char *bdf_filename, int is_verbose, int bbx_mode, const char *map_str, int font_format)
|
||||
{
|
||||
bf_t *bf;
|
||||
|
||||
bf = bf_Open(is_verbose, bbx_mode);
|
||||
if ( bf != NULL )
|
||||
{
|
||||
|
||||
if ( bf_ParseFile(bf, bdf_filename) != 0 )
|
||||
{
|
||||
bf_Map(bf, map_str);
|
||||
bf_CalculateSelectedNumberOfGlyphs(bf);
|
||||
|
||||
bf_ReduceAllGlyph(bf);
|
||||
bf_CalculateMaxBBX(bf);
|
||||
//bf_ShowAllGlyphs(bf, &(bf->max));
|
||||
bf_CalculateMinMaxDWidth(bf);
|
||||
|
||||
bf_CalculateMaxBitFieldSize(bf);
|
||||
|
||||
|
||||
if ( font_format == 0 || font_format == 1 )
|
||||
{
|
||||
bf_RLECompressAllGlyphs(bf);
|
||||
}
|
||||
else
|
||||
{
|
||||
bf_Generate8x8Font(bf);
|
||||
}
|
||||
|
||||
if ( bf->bbx_mode != BDF_BBX_MODE_MINIMAL )
|
||||
bf_ShowMonospaceStatistics(bf); /* Show stats only for none minimal mode. For minimal mode it will always be zero */
|
||||
|
||||
return bf;
|
||||
}
|
||||
bf_Close(bf);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,146 @@
|
||||
|
||||
|
||||
#ifndef _BDF_FONT_H
|
||||
#define _BDF_FONT_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include "bdf_glyph.h"
|
||||
|
||||
#define BDF_LINE_LEN 1024
|
||||
|
||||
#define BDF_BBX_MODE_MINIMAL 0
|
||||
#define BDF_BBX_MODE_HEIGHT 1
|
||||
#define BDF_BBX_MODE_MAX 2
|
||||
#define BDF_BBX_MODE_M8 3
|
||||
|
||||
struct _bdf_font_struct
|
||||
{
|
||||
int is_verbose;
|
||||
|
||||
bg_t **glyph_list;
|
||||
int glyph_cnt;
|
||||
int glyph_max;
|
||||
|
||||
/* variables for the parser */
|
||||
char line_buf[BDF_LINE_LEN];
|
||||
int line_pos;
|
||||
int is_bitmap_parsing;
|
||||
|
||||
long encoding;
|
||||
|
||||
long dwidth_x;
|
||||
long dwidth_y;
|
||||
|
||||
long bbx_w;
|
||||
long bbx_h;
|
||||
long bbx_x;
|
||||
long bbx_y;
|
||||
|
||||
int bitmap_x; /* x position within bitmap parsing */
|
||||
int bitmap_y; /* y position within bitmap parsing */
|
||||
int glyph_pos; /* the position to which the glyph has been added in the list */
|
||||
FILE *fp;
|
||||
|
||||
char *str_font; /* argument for FONT in bdf file */
|
||||
char *str_copyright; /* argument for COPYRIGHT in bdf file */
|
||||
|
||||
long selected_glyphs; /* number of mapped glyphs */
|
||||
|
||||
int bbx_mode; /* bounding box mode, one of BDF_BBX_MODE_xxx */
|
||||
/* bf_CalculateMaxBBX */
|
||||
bbx_t max; /* max bbx, calculated from the mapped glyphs by bf_CalculateMaxBBX */
|
||||
|
||||
/* remember which encoding has caused the max value */
|
||||
long enc_w;
|
||||
long enc_h;
|
||||
long enc_x;
|
||||
long enc_y;
|
||||
|
||||
/* bf_CalculateMinMaxDWidth */
|
||||
long dx_min; /* calculated minimum and maximum dwidth value from the mapped glyphs by bf_CalculateMinMaxDWidth */
|
||||
long dx_max; /* it is a monospaced font if max and min values are identical */
|
||||
|
||||
/* bf_CalculateMinMaxDWidth */
|
||||
long x_min; /* calculated minimum and maximum bbx.x value from the mapped glyphs by bf_CalculateMinMaxDWidth */
|
||||
long x_max; /* it is a monospaced font if x_min >= 0 */
|
||||
|
||||
/* bf_CalculateMaxBitFieldSize */
|
||||
int bbx_x_max_bit_size;
|
||||
int bbx_y_max_bit_size;
|
||||
int bbx_w_max_bit_size;
|
||||
int bbx_h_max_bit_size;
|
||||
int dx_max_bit_size;
|
||||
|
||||
/* font target data */
|
||||
uint8_t *target_data;
|
||||
int target_max;
|
||||
int target_cnt;
|
||||
|
||||
|
||||
};
|
||||
|
||||
/* bdf_font.c */
|
||||
|
||||
|
||||
/* output error & log messages */
|
||||
void bf_Error(bf_t *bf, char *fmt, ...);
|
||||
void bf_Log(bf_t *bf, char *fmt, ...);
|
||||
|
||||
/* constructor/destructor */
|
||||
bf_t *bf_Open(int is_verbose, int bbx_mode);
|
||||
void bf_Close(bf_t *bf);
|
||||
|
||||
/* returns glyph position or -1 */
|
||||
int bf_AddGlyph(bf_t *bf);
|
||||
|
||||
/* add binary data */
|
||||
void bf_ClearTargetData(bf_t *bf);
|
||||
int bf_AddTargetData(bf_t *bf, uint8_t data);
|
||||
|
||||
void bf_CalculateSelectedNumberOfGlyphs(bf_t *bf);
|
||||
|
||||
void bf_ReduceAllGlyph(bf_t *bf);
|
||||
|
||||
int bf_GetIndexByEncoding(bf_t *bf, long encoding);
|
||||
|
||||
/* only shows glyphs, which will be mapped (call bf_Map() first) */
|
||||
void bf_ShowAllGlyphs(bf_t *bf, bbx_t *bbx);
|
||||
|
||||
void bf_ShowMonospaceStatistics(bf_t *bf);
|
||||
|
||||
|
||||
/* calculate the max bbx for all mapped glyphs (call bf_Map() first) */
|
||||
void bf_CalculateMaxBBX(bf_t *bf);
|
||||
|
||||
void bf_CalculateMinMaxDWidth(bf_t *bf);
|
||||
void bf_copy_bbx_and_update_shift(bf_t *bf, bbx_t *target_bbx, bg_t *bg);
|
||||
void bf_CalculateMaxBitFieldSize(bf_t *bf);
|
||||
void bf_RLECompressAllGlyphs(bf_t *bf);
|
||||
void bf_Generate8x8Font(bf_t *bf);
|
||||
|
||||
|
||||
int bf_WriteUCGCByFilename(bf_t *bf, const char *filename, const char *fontname, const char *indent);
|
||||
int bf_WriteU8G2CByFilename(bf_t *bf, const char *filename, const char *fontname, const char *indent);
|
||||
|
||||
bf_t *bf_OpenFromFile(const char *bdf_filename, int is_verbose, int bbx_mode, const char *map_str, int font_format);
|
||||
|
||||
|
||||
/* bdf_parser.c */
|
||||
int bf_ParseFile(bf_t *bf, const char *name);
|
||||
|
||||
/* bdf_map.c */
|
||||
void bf_Map(bf_t *bf, const char *map_cmd_list);
|
||||
|
||||
/* bdf_tga.c */
|
||||
int tga_init(uint16_t w, uint16_t h);
|
||||
void tga_set_pixel(uint16_t x, uint16_t y, uint8_t r, uint8_t g, uint8_t b);
|
||||
void tga_save(const char *name);
|
||||
void tga_set_font(uint8_t *font);
|
||||
uint8_t *tga_get_glyph_data(uint8_t encoding);
|
||||
int tga_get_char_width(void);
|
||||
int tga_get_char_height(void);
|
||||
unsigned tga_draw_glyph(unsigned x, unsigned y, uint8_t encoding, int is_hints);
|
||||
unsigned tga_draw_string(unsigned x, unsigned y, const char *s, int is_hints, unsigned max_dx);
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,392 @@
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include "bdf_glyph.h"
|
||||
|
||||
|
||||
bg_t *bg_Open(void)
|
||||
{
|
||||
bg_t *bg;
|
||||
|
||||
bg = (bg_t *)malloc(sizeof(bg_t));
|
||||
if ( bg != NULL )
|
||||
{
|
||||
bg->encoding = 0;
|
||||
bg->map_to = -1;
|
||||
bg->bitmap_data = NULL;
|
||||
bg->target_data = NULL;
|
||||
bg->target_max = 0;
|
||||
bg->target_cnt = 0;
|
||||
bg->shift_x = 0;
|
||||
|
||||
return bg;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void bg_Close(bg_t *bg)
|
||||
{
|
||||
if ( bg->bitmap_data != NULL )
|
||||
free(bg->bitmap_data);
|
||||
if ( bg->target_data != NULL )
|
||||
free(bg->target_data);
|
||||
bg->bitmap_data = NULL;
|
||||
bg->target_data =NULL;
|
||||
bg->target_max = 0;
|
||||
bg->target_cnt = 0;
|
||||
bg->target_bit_pos = 0;
|
||||
bg->encoding = 0;
|
||||
free(bg);
|
||||
}
|
||||
|
||||
static int bg_extend_target_data(bg_t *bg)
|
||||
{
|
||||
int extend = 16;
|
||||
int i;
|
||||
void *ptr;
|
||||
if ( bg->target_data == NULL )
|
||||
{
|
||||
ptr = malloc(extend*sizeof(uint8_t));
|
||||
bg->target_max = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
ptr = realloc(bg->target_data, (bg->target_max + extend)*sizeof(uint8_t));
|
||||
}
|
||||
if ( ptr == NULL )
|
||||
return 0;
|
||||
bg->target_data = (uint8_t *)ptr;
|
||||
for( i = bg->target_max; i < bg->target_max + extend; i++ )
|
||||
bg->target_data[i] = 0;
|
||||
bg->target_max += extend;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int bg_AddTargetData(bg_t *bg, uint8_t data)
|
||||
{
|
||||
while( bg->target_max <= bg->target_cnt )
|
||||
if ( bg_extend_target_data(bg) == 0 )
|
||||
return -1;
|
||||
bg->target_data[bg->target_cnt] = data;
|
||||
bg->target_cnt++;
|
||||
return bg->target_cnt-1;
|
||||
}
|
||||
|
||||
void bg_ClearTargetData(bg_t *bg)
|
||||
{
|
||||
int i;
|
||||
for( i = 0; i < bg->target_max; i++ )
|
||||
bg->target_data[i] = 0;
|
||||
bg->target_cnt = 0;
|
||||
bg->target_bit_pos = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
Desc:
|
||||
Output a field to the target bitstream. The field size in bits is given by "cnt" and
|
||||
the value of the field is "val".
|
||||
Args:
|
||||
cnt: Fieldsize in bits, must be lower or equal to 8
|
||||
val: The value (content) of the field. Side condition: val < (1<<cnt) && val >= 0
|
||||
*/
|
||||
int bg_AddTargetBits(bg_t *bg, unsigned cnt, unsigned val)
|
||||
{
|
||||
|
||||
assert( val < (1<<cnt) );
|
||||
|
||||
while( bg->target_max <= bg->target_cnt+1 )
|
||||
if ( bg_extend_target_data(bg) == 0 )
|
||||
return 0;
|
||||
|
||||
bg->target_data[bg->target_cnt] |= (val << bg->target_bit_pos);
|
||||
|
||||
if ( bg->target_bit_pos+cnt >= 8 )
|
||||
{
|
||||
bg->target_cnt++;
|
||||
|
||||
val >>= 8-bg->target_bit_pos;
|
||||
bg->target_data[bg->target_cnt] = val;
|
||||
|
||||
bg->target_bit_pos+=cnt;
|
||||
bg->target_bit_pos-=8;
|
||||
}
|
||||
else
|
||||
{
|
||||
bg->target_bit_pos+=cnt;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int bg_FlushTargetBits(bg_t *bg)
|
||||
{
|
||||
while( bg->target_bit_pos != 0 )
|
||||
if ( bg_AddTargetBits(bg, 1, 0) == 0 )
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int bg_SetBitmapSizeInBytes(bg_t *bg, size_t bytes)
|
||||
{
|
||||
if ( bg->bitmap_data != NULL )
|
||||
free(bg->bitmap_data);
|
||||
bg->bitmap_data = (uint8_t *)malloc(bytes);
|
||||
if ( bg->bitmap_data == NULL )
|
||||
return 0;
|
||||
memset(bg->bitmap_data, 0, bytes);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int bg_SetBitmapSize(bg_t *bg, int w, int h)
|
||||
{
|
||||
return bg_SetBitmapSizeInBytes(bg, w*h);
|
||||
}
|
||||
|
||||
void bg_SetBitmapPixel(bg_t *bg, int x, int y, int value)
|
||||
{
|
||||
assert( x < bg->bitmap_width );
|
||||
assert( y < bg->bitmap_height );
|
||||
assert( x >= 0 );
|
||||
assert( y >= 0 );
|
||||
bg->bitmap_data[y*bg->bitmap_width + x] = value;
|
||||
}
|
||||
|
||||
int bg_GetBitmapPixel(bg_t *bg, int x, int y)
|
||||
{
|
||||
if ( x >= bg->bitmap_width )
|
||||
return 0;
|
||||
|
||||
if ( y >= bg->bitmap_height )
|
||||
return 0;
|
||||
if ( x < 0 )
|
||||
return 0;
|
||||
if ( y < 0 )
|
||||
return 0;
|
||||
|
||||
return bg->bitmap_data[y*bg->bitmap_width + x];
|
||||
}
|
||||
|
||||
/*
|
||||
Return a pixel with the provided bbx
|
||||
Coordinates are within the bbx.
|
||||
*/
|
||||
int bg_GetBBXPixel(bg_t *bg, int x, int y)
|
||||
{
|
||||
/* glyph rectangle */
|
||||
long glyph_x0, glyph_x1, glyph_y0, glyph_y1;
|
||||
|
||||
/* local bitmap coordinates */
|
||||
long bitmap_x, bitmap_y;
|
||||
|
||||
/* perform x offset alignment (used in BDF_BBX_MODE_HEIGHT mode only)*/
|
||||
x += bg->shift_x;
|
||||
|
||||
/* calculate the rectangle for the glyph */
|
||||
glyph_x0 = bg->bbx.x;
|
||||
glyph_y0 = bg->bbx.y;
|
||||
glyph_x1 = bg->bbx.x+bg->bbx.w;
|
||||
glyph_y1 = bg->bbx.y+bg->bbx.h;
|
||||
|
||||
if ( x < glyph_x0 )
|
||||
return 0;
|
||||
if ( x >= glyph_x1 )
|
||||
return 0;
|
||||
|
||||
if ( y < glyph_y0 )
|
||||
return 0;
|
||||
if ( y >= glyph_y1 )
|
||||
return 0;
|
||||
|
||||
bitmap_x = x - glyph_x0;
|
||||
bitmap_y = bg->bbx.h - 1 - ( y - glyph_y0);
|
||||
|
||||
return bg_GetBitmapPixel( bg, bitmap_x, bitmap_y );
|
||||
|
||||
}
|
||||
|
||||
|
||||
void bg_ShowBitmap(bg_t *bg, bbx_t *bbx)
|
||||
{
|
||||
int x, y;
|
||||
|
||||
if ( bbx == NULL )
|
||||
bbx = &(bg->bbx);
|
||||
|
||||
printf("Encoding %ld, mapped to %ld, w=%ld, h=%ld, x=%ld, y=%ld\n", bg->encoding, bg->map_to, bg->bbx.w, bg->bbx.h, bg->bbx.x, bg->bbx.y);
|
||||
for( y = bbx->y+bbx->h-1; y >= bbx->y; y--)
|
||||
{
|
||||
printf("%03d ", y);
|
||||
for( x = bbx->x; x < bbx->x + bbx->w; x++)
|
||||
{
|
||||
if ( bg_GetBBXPixel(bg, x, y) == 0 )
|
||||
{
|
||||
printf(" .");
|
||||
}
|
||||
else
|
||||
{
|
||||
printf(" #");
|
||||
}
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
int bg_IsColZero(bg_t *bg, int x)
|
||||
{
|
||||
int y;
|
||||
for( y = 0; y < bg->bitmap_height; y++ )
|
||||
{
|
||||
if ( bg_GetBitmapPixel(bg, x, y) != 0 )
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int bg_IsRowZero(bg_t *bg, int y)
|
||||
{
|
||||
int x;
|
||||
for( x = 0; x < bg->bitmap_width; x++ )
|
||||
{
|
||||
if ( bg_GetBitmapPixel(bg, x, y) != 0 )
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void bg_DeleteFirstCol(bg_t *bg)
|
||||
{
|
||||
int x,y;
|
||||
for( y = 0; y < bg->bitmap_height; y++ )
|
||||
for( x = 0; x+1 < bg->bitmap_width; x++ )
|
||||
{
|
||||
bg_SetBitmapPixel(bg, x, y, bg_GetBitmapPixel(bg, x+1, y));
|
||||
}
|
||||
}
|
||||
|
||||
void bg_DeleteFirstRow(bg_t *bg)
|
||||
{
|
||||
int x,y;
|
||||
for( y = 0; y+1 < bg->bitmap_height; y++ )
|
||||
for( x = 0; x < bg->bitmap_width; x++ )
|
||||
{
|
||||
bg_SetBitmapPixel(bg, x, y, bg_GetBitmapPixel(bg, x, y+1));
|
||||
}
|
||||
}
|
||||
|
||||
void bg_ReduceGlyph(bg_t *bg)
|
||||
{
|
||||
/* assign bitmap dimension (should be done already) */
|
||||
|
||||
//bg->bbx.w = bg->bitmap_width;
|
||||
//bg->bbx.h = bg->bitmap_height;
|
||||
|
||||
/* do not assign x,y because they are already set correctly */
|
||||
|
||||
|
||||
while( bg->bbx.w > 0 )
|
||||
{
|
||||
if ( bg_IsColZero(bg, bg->bbx.w-1) == 0 )
|
||||
break;
|
||||
bg->bbx.w--;
|
||||
}
|
||||
|
||||
while( bg->bbx.h > 0 )
|
||||
{
|
||||
if ( bg_IsRowZero(bg, bg->bbx.h-1) == 0 )
|
||||
break;
|
||||
bg->bbx.y++;
|
||||
bg->bbx.h--;
|
||||
}
|
||||
|
||||
while( bg->bbx.w > 0)
|
||||
{
|
||||
if ( bg_IsColZero(bg, 0) == 0 )
|
||||
break;
|
||||
bg_DeleteFirstCol(bg);
|
||||
bg->bbx.x++;
|
||||
bg->bbx.w--;
|
||||
}
|
||||
|
||||
while( bg->bbx.h > 0 )
|
||||
{
|
||||
if ( bg_IsRowZero(bg, 0) == 0 )
|
||||
break;
|
||||
bg_DeleteFirstRow(bg);
|
||||
bg->bbx.h--;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
maximize the provided bbx so that the bbxof the glyph completly is covered by the max bbx
|
||||
*/
|
||||
int bg_Max(bg_t *bg, bbx_t *max)
|
||||
{
|
||||
int r = 0;
|
||||
|
||||
/* glyph rectangle */
|
||||
long glyph_x0, glyph_x1, glyph_y0, glyph_y1;
|
||||
|
||||
/* max rectangle */
|
||||
long max_x0, max_x1, max_y0, max_y1;
|
||||
|
||||
// printf("Encoding %ld, mapped to %ld, w=%ld, h=%ld, x=%ld, y=%ld\n", bg->encoding, bg->map_to, bg->bbx.w, bg->bbx.h, bg->bbx.x, bg->bbx.y);
|
||||
|
||||
|
||||
/* calculate the rectangle for the glyph */
|
||||
glyph_x0 = bg->bbx.x;
|
||||
glyph_y0 = bg->bbx.y;
|
||||
glyph_x1 = bg->bbx.x+bg->bbx.w;
|
||||
glyph_y1 = bg->bbx.y+bg->bbx.h;
|
||||
|
||||
/* calculate the rectangle for the max bbx */
|
||||
max_x0 = max->x;
|
||||
max_y0 = max->y;
|
||||
max_x1 = max->x+max->w;
|
||||
max_y1 = max->y+max->h;
|
||||
|
||||
/* maximize the max rectrangle so that the glyph rectangle full fits inside */
|
||||
if ( max_x0 > glyph_x0 )
|
||||
{
|
||||
max_x0 = glyph_x0;
|
||||
r = 3;
|
||||
}
|
||||
/* 28 Mar dwidth_x and x0???? */
|
||||
if ( max_x0 > bg->dwidth_x ) /* include dwidth_x into the box */
|
||||
{
|
||||
max_x0 = bg->dwidth_x; /* is this correct??? */
|
||||
r = 3;
|
||||
}
|
||||
|
||||
|
||||
if ( max_x1 < glyph_x1 )
|
||||
{
|
||||
r = 1;
|
||||
max_x1 = glyph_x1;
|
||||
}
|
||||
|
||||
if ( max_y0 > glyph_y0 )
|
||||
{
|
||||
r = 4;
|
||||
max_y0 = glyph_y0;
|
||||
}
|
||||
if ( max_y1 < glyph_y1 )
|
||||
{
|
||||
r = 2;
|
||||
max_y1 = glyph_y1;
|
||||
}
|
||||
|
||||
/* reconstruct the max bbx from the max rectangle */
|
||||
max->x = max_x0;
|
||||
max->y = max_y0;
|
||||
max->w = max_x1 - max->x;
|
||||
max->h = max_y1 - max->y;
|
||||
|
||||
return r;
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
|
||||
|
||||
#ifndef _BDF_GLYPH_H
|
||||
#define _BDF_GLYPH_H
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
/* forward def */
|
||||
typedef struct _bdf_font_struct bf_t;
|
||||
|
||||
|
||||
struct _bbx_struct
|
||||
{
|
||||
long w;
|
||||
long h;
|
||||
long x;
|
||||
long y;
|
||||
};
|
||||
typedef struct _bbx_struct bbx_t;
|
||||
|
||||
|
||||
struct _bdf_glyph_struct
|
||||
{
|
||||
bf_t *bf;
|
||||
|
||||
long encoding;
|
||||
long map_to;
|
||||
|
||||
long dwidth_x;
|
||||
long dwidth_y;
|
||||
|
||||
bbx_t bbx; /* x,y are delta x,y from glyph, w,h start wth bitmap dimension, but may be reduced */
|
||||
long shift_x; /* extra shift for BDF_BBX_MODE_HEIGHT alignment */
|
||||
|
||||
uint8_t *bitmap_data;
|
||||
int bitmap_width; /* the physical width within "bitmap_data", will be larger than or equal to bbx.w */
|
||||
int bitmap_height;
|
||||
|
||||
//int actual_bitmap_width; /* identical to bbx.w, maybe replace actual_bitmap_width by bbx.w */
|
||||
//int actual_bitmap_height; /* identical to bbx.h, maybe replace actual_bitmap_height by bbx.h */
|
||||
|
||||
uint8_t *target_data;
|
||||
int target_max;
|
||||
int target_cnt;
|
||||
int target_bit_pos;
|
||||
|
||||
/* rle data */
|
||||
|
||||
unsigned rle_bits_per_0;
|
||||
unsigned rle_bits_per_1;
|
||||
|
||||
int rle_is_first;
|
||||
unsigned rle_bitcnt;
|
||||
unsigned rle_last_0;
|
||||
unsigned rle_last_1;
|
||||
|
||||
long width_deviation; /* filled by bf_copy_bbx_and_update_shift for statistics */
|
||||
|
||||
};
|
||||
typedef struct _bdf_glyph_struct bg_t;
|
||||
|
||||
bg_t *bg_Open(void);
|
||||
void bg_Close(bg_t *bg);
|
||||
int bg_AddTargetData(bg_t *bg, uint8_t data);
|
||||
void bg_ClearTargetData(bg_t *bg);
|
||||
int bg_AddTargetBits(bg_t *bg, unsigned cnt, unsigned val);
|
||||
int bg_FlushTargetBits(bg_t *bg);
|
||||
|
||||
int bg_SetBitmapSizeInBytes(bg_t *bg, size_t bytes);
|
||||
int bg_SetBitmapSize(bg_t *bg, int w, int h);
|
||||
void bg_SetBitmapPixel(bg_t *bg, int x, int y, int value);
|
||||
int bg_GetBitmapPixel(bg_t *bg, int x, int y);
|
||||
int bg_GetBBXPixel(bg_t *bg, int x, int y);
|
||||
|
||||
void bg_ShowBitmap(bg_t *bg, bbx_t *bbx);
|
||||
void bg_ReduceGlyph(bg_t *bg);
|
||||
int bg_Max(bg_t *bg, bbx_t *max); /* returns idx which describes glyph expansion */
|
||||
|
||||
/* bdf_rle.c */
|
||||
int bg_rle_compress(bg_t *bg, bbx_t *bbx, unsigned rle_bits_per_0, unsigned rle_bits_per_1, int is_output);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,239 @@
|
||||
/*
|
||||
bdf_map.c
|
||||
|
||||
select and map glyphs
|
||||
|
||||
Syntax:
|
||||
maplist := <mapcmd> { "," <mapcmd> }
|
||||
mapcmd := <default> | <maprange> | <exclude>
|
||||
default := "*"
|
||||
maprange := <range> [ ">" <num> ]
|
||||
exclude := "~" <range>
|
||||
range := <num> [ "-" <num> ]
|
||||
num := <hexnum> | <decnum>
|
||||
hexnum := "$" <hexdigit> { <hexdigit> }
|
||||
decnum := <decdigit> { <decdigit> }
|
||||
decdigit := "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
|
||||
hexdigit := "a" | "b" | "c" | "d" | "e" | "f" | "A" | "B" | "C" | "D" | "E" | "F" | <decdigit>
|
||||
|
||||
{ }: zero, one ore more
|
||||
[ ]: zero or once
|
||||
|: alternative
|
||||
|
||||
*/
|
||||
|
||||
#include "bdf_font.h"
|
||||
|
||||
static long range_from;
|
||||
static long range_to;
|
||||
static int is_exclude;
|
||||
static long map_to;
|
||||
|
||||
static void skip_space(const char **s)
|
||||
{
|
||||
for(;;)
|
||||
{
|
||||
if ( **s == '\0' )
|
||||
break;
|
||||
if ( **s > ' ' )
|
||||
break;
|
||||
(*s)++;
|
||||
}
|
||||
}
|
||||
|
||||
static long get_dec(const char **s)
|
||||
{
|
||||
long v = 0;
|
||||
for(;;)
|
||||
{
|
||||
if ( (**s) >= '0' && (**s) <= '9' )
|
||||
{
|
||||
v*=10;
|
||||
v+= (**s)-'0';
|
||||
(*s)++;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
skip_space(s);
|
||||
return v;
|
||||
}
|
||||
|
||||
static long get_hex(const char **s)
|
||||
{
|
||||
long v = 0;
|
||||
for(;;)
|
||||
{
|
||||
if ( (**s) >= '0' && (**s) <= '9' )
|
||||
{
|
||||
v*=16;
|
||||
v+= (**s)-'0';
|
||||
(*s)++;
|
||||
}
|
||||
else if ( (**s) >= 'a' && (**s) <= 'f' )
|
||||
{
|
||||
v*=16;
|
||||
v+= (**s)-'a'+10;
|
||||
(*s)++;
|
||||
}
|
||||
else if ( (**s) >= 'A' && (**s) <= 'F' )
|
||||
{
|
||||
v*=16;
|
||||
v+= (**s)-'A'+10;
|
||||
(*s)++;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
skip_space(s);
|
||||
return v;
|
||||
}
|
||||
|
||||
static long get_num(const char **s)
|
||||
{
|
||||
if ( (**s) != '$' )
|
||||
return get_dec(s);
|
||||
(*s)++;
|
||||
skip_space(s);
|
||||
return get_hex(s);
|
||||
}
|
||||
|
||||
static long get_mul(const char **s)
|
||||
{
|
||||
long v;
|
||||
v = get_num(s);
|
||||
if ( (**s) == '*' )
|
||||
{
|
||||
(*s)++;
|
||||
skip_space(s);
|
||||
v *= get_num(s);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
static long get_add(const char **s)
|
||||
{
|
||||
long v;
|
||||
v = get_mul(s);
|
||||
if ( (**s) == '+' )
|
||||
{
|
||||
(*s)++;
|
||||
skip_space(s);
|
||||
v += get_mul(s);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
static void get_range(const char **s)
|
||||
{
|
||||
range_from = get_add(s);
|
||||
if ( **s != '-' )
|
||||
{
|
||||
range_to = range_from;
|
||||
}
|
||||
else
|
||||
{
|
||||
(*s)++;
|
||||
skip_space(s);
|
||||
range_to = get_add(s);
|
||||
}
|
||||
}
|
||||
|
||||
static void map_cmd(const char **s)
|
||||
{
|
||||
if ( **s == '*' )
|
||||
{
|
||||
range_from = 32;
|
||||
range_to = 255;
|
||||
map_to = 32;
|
||||
is_exclude = 0;
|
||||
|
||||
(*s)++;
|
||||
skip_space(s);
|
||||
}
|
||||
else if ( **s == '~' )
|
||||
{
|
||||
is_exclude = 1;
|
||||
map_to = 0; /*will be ignored */
|
||||
|
||||
(*s)++;
|
||||
skip_space(s);
|
||||
get_range(s);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
is_exclude = 0;
|
||||
get_range(s);
|
||||
map_to = range_from;
|
||||
if ( **s == '>')
|
||||
{
|
||||
(*s)++;
|
||||
skip_space(s);
|
||||
map_to = get_add(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void bf_map_cmd(bf_t *bf, const char **s)
|
||||
{
|
||||
int i;
|
||||
bg_t *bg;
|
||||
map_cmd(s);
|
||||
|
||||
bf_Log(bf, "Map: exclude=%d from=%ld to=%ld map=%ld", is_exclude, range_from, range_to, map_to);
|
||||
|
||||
for( i = 0; i < bf->glyph_cnt; i++ )
|
||||
{
|
||||
bg = bf->glyph_list[i];
|
||||
if ( bg->encoding >= range_from && bg->encoding <= range_to )
|
||||
{
|
||||
if ( is_exclude != 0 )
|
||||
{
|
||||
bg->map_to = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
bg->map_to = bg->encoding - range_from + map_to;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void bf_map_list(bf_t *bf, const char **s)
|
||||
{
|
||||
int i;
|
||||
bg_t *bg;
|
||||
|
||||
/* exclude everything first */
|
||||
for( i = 0; i < bf->glyph_cnt; i++ )
|
||||
{
|
||||
bg = bf->glyph_list[i];
|
||||
bg->map_to = -1;
|
||||
}
|
||||
|
||||
/* process the mapping list list */
|
||||
skip_space(s);
|
||||
for(;;)
|
||||
{
|
||||
bf_map_cmd(bf, s);
|
||||
if ( **s != ',' )
|
||||
break;
|
||||
(*s)++;
|
||||
skip_space(s);
|
||||
}
|
||||
}
|
||||
|
||||
void bf_Map(bf_t *bf, const char *map_cmd_list)
|
||||
{
|
||||
bf_Log(bf, "Map: map_cmd_list='%s'", map_cmd_list);
|
||||
bf_map_list(bf, &map_cmd_list);
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,472 @@
|
||||
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "bdf_font.h"
|
||||
|
||||
static int bf_curr(bf_t * bf)
|
||||
{
|
||||
if ( bf->line_pos >= BDF_LINE_LEN )
|
||||
return '\0';
|
||||
return bf->line_buf[bf->line_pos];
|
||||
}
|
||||
|
||||
static void bf_next(bf_t *bf)
|
||||
{
|
||||
if ( bf_curr(bf) == '\0' )
|
||||
return;
|
||||
if ( bf->line_pos >= BDF_LINE_LEN )
|
||||
return;
|
||||
bf->line_pos++;
|
||||
}
|
||||
|
||||
static void bf_skipspace(bf_t *bf)
|
||||
{
|
||||
int c;
|
||||
|
||||
for(;;)
|
||||
{
|
||||
c = bf_curr(bf);
|
||||
if ( c == '\0' )
|
||||
return;
|
||||
if ( c > ' ' )
|
||||
return;
|
||||
bf_next(bf);
|
||||
}
|
||||
}
|
||||
|
||||
static const char *bf_get_identifier(bf_t *bf)
|
||||
{
|
||||
static char buf[BDF_LINE_LEN];
|
||||
int c;
|
||||
int i = 0;
|
||||
buf[0] = '\0';
|
||||
for(;;)
|
||||
{
|
||||
c = bf_curr(bf);
|
||||
if ( c <= ' ' )
|
||||
break;
|
||||
if ( i >= BDF_LINE_LEN-2 )
|
||||
break;
|
||||
buf[i++] = c;
|
||||
buf[i] = '\0';
|
||||
bf_next(bf);
|
||||
}
|
||||
bf_skipspace(bf);
|
||||
return buf;
|
||||
}
|
||||
|
||||
static const char *bf_get_string(bf_t *bf)
|
||||
{
|
||||
static char buf[BDF_LINE_LEN];
|
||||
int i = 0;
|
||||
int c;
|
||||
|
||||
buf[0] = '\0';
|
||||
|
||||
if ( bf_curr(bf) != '\"' )
|
||||
return bf_get_identifier(bf);
|
||||
|
||||
bf_next(bf);
|
||||
|
||||
for(;;)
|
||||
{
|
||||
c = bf_curr(bf);
|
||||
if ( c == '\0' )
|
||||
break;
|
||||
if ( c == '\"' )
|
||||
break;
|
||||
if ( i >= BDF_LINE_LEN-2 )
|
||||
break;
|
||||
buf[i++] = c;
|
||||
buf[i] = '\0';
|
||||
bf_next(bf);
|
||||
}
|
||||
if ( bf_curr(bf) == '\"' )
|
||||
bf_next(bf);
|
||||
|
||||
bf_skipspace(bf);
|
||||
return buf;
|
||||
}
|
||||
|
||||
static const char *bf_get_eol_string(bf_t *bf)
|
||||
{
|
||||
static char buf[BDF_LINE_LEN];
|
||||
int i = 0;
|
||||
int c;
|
||||
|
||||
buf[0] = '\0';
|
||||
|
||||
if ( bf_curr(bf) == '\"' )
|
||||
return bf_get_string(bf);
|
||||
bf_next(bf);
|
||||
|
||||
for(;;)
|
||||
{
|
||||
c = bf_curr(bf);
|
||||
if ( c == '\0' )
|
||||
break;
|
||||
if ( c == '\n' || c == '\r' )
|
||||
break;
|
||||
if ( i >= BDF_LINE_LEN-2 )
|
||||
break;
|
||||
buf[i++] = c;
|
||||
buf[i] = '\0';
|
||||
bf_next(bf);
|
||||
}
|
||||
|
||||
bf_skipspace(bf);
|
||||
return buf;
|
||||
}
|
||||
|
||||
static long bf_get_long(bf_t *bf)
|
||||
{
|
||||
int c;
|
||||
long v = 0;
|
||||
long sign = 1;
|
||||
|
||||
if ( bf_curr(bf) == '-' )
|
||||
{
|
||||
sign = -1;
|
||||
bf_next(bf);
|
||||
bf_skipspace(bf);
|
||||
}
|
||||
|
||||
for(;;)
|
||||
{
|
||||
c = bf_curr(bf);
|
||||
if ( c < '0' )
|
||||
break;
|
||||
if ( c > '9' )
|
||||
break;
|
||||
v *= 10L;
|
||||
v += (long)(c-'0');
|
||||
bf_next(bf);
|
||||
}
|
||||
bf_skipspace(bf);
|
||||
|
||||
return v*sign;
|
||||
}
|
||||
|
||||
/*
|
||||
static long bf_get_mul(bf_t *bf)
|
||||
{
|
||||
long v;
|
||||
v = bf_get_long(bf);
|
||||
if ( bf_curr(bf) == '*' )
|
||||
{
|
||||
bf_next(bf);
|
||||
bf_skipspace(bf);
|
||||
v *= bf_get_long(bf);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
static long bf_get_add(bf_t *bf)
|
||||
{
|
||||
long v;
|
||||
v = bf_get_mul(bf);
|
||||
if ( bf_curr(bf) == '+' )
|
||||
{
|
||||
bf_next(bf);
|
||||
bf_skipspace(bf);
|
||||
v += bf_get_mul(bf);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
static int bf_add_glyph_to_list(bf_t *bf)
|
||||
{
|
||||
bg_t *bg;
|
||||
bf->glyph_pos = bf_AddGlyph(bf);
|
||||
if ( bf->glyph_pos < 0 )
|
||||
{
|
||||
bf_Error(bf, "Can not add glyph (memory error?)");
|
||||
return 0;
|
||||
}
|
||||
|
||||
bg = bf->glyph_list[bf->glyph_pos];
|
||||
|
||||
/* copy the values from the parser to the glyph record */
|
||||
bg->encoding = bf->encoding;
|
||||
bg->dwidth_x = bf->dwidth_x;
|
||||
bg->dwidth_y = bf->dwidth_y;
|
||||
bg->bbx.w = bf->bbx_w;
|
||||
bg->bbx.h = bf->bbx_h;
|
||||
bg->bbx.x = bf->bbx_x;
|
||||
bg->bbx.y = bf->bbx_y;
|
||||
|
||||
if ( bg_SetBitmapSize(bg, bf->bbx_w, bf->bbx_h) == 0 )
|
||||
{
|
||||
bf_Error(bf, "Can not create bitmap (memory error?)");
|
||||
return 0;
|
||||
}
|
||||
|
||||
bg->bitmap_width = bf->bbx_w;
|
||||
bg->bitmap_height = bf->bbx_h;
|
||||
|
||||
// bg->actual_bitmap_width = bf->bbx_w;
|
||||
// bg->actual_bitmap_height = bf->bbx_h;
|
||||
|
||||
//bf_Log(bf, "BDF File: Create glyph glyph_pos=%d bbx_w=%d bbx_h=%d bbx_x=%d bbx_y=%d", bf->glyph_pos, bf->bbx_w, bf->bbx_h, bf->bbx_x, bf->bbx_y);
|
||||
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void bf_set_pixel_by_halfbyte(bf_t *bf, int halfbyte)
|
||||
{
|
||||
int i;
|
||||
bg_t *bg;
|
||||
|
||||
assert( bf->glyph_list != NULL );
|
||||
|
||||
bg = bf->glyph_list[bf->glyph_pos];
|
||||
|
||||
for ( i = 0; i < 4; i++ )
|
||||
{
|
||||
if ( (halfbyte & 8) != 0 )
|
||||
{
|
||||
bg_SetBitmapPixel(bg, bf->bitmap_x, bf->bitmap_y, 1);
|
||||
}
|
||||
halfbyte<<=1;
|
||||
bf->bitmap_x++;
|
||||
}
|
||||
}
|
||||
|
||||
static void bf_set_pixel_by_hex_char(bf_t *bf, int hex)
|
||||
{
|
||||
if ( hex >= '0' && hex <= '9' )
|
||||
return bf_set_pixel_by_halfbyte(bf, hex-'0');
|
||||
if ( hex >= 'a' && hex <= 'f' )
|
||||
return bf_set_pixel_by_halfbyte(bf, hex-'a'+10);
|
||||
if ( hex >= 'A' && hex <= 'F' )
|
||||
return bf_set_pixel_by_halfbyte(bf, hex-'A'+10);
|
||||
return bf_set_pixel_by_halfbyte(bf, 0);
|
||||
}
|
||||
|
||||
static int bf_parse_line(bf_t *bf)
|
||||
{
|
||||
static char cmd[BDF_LINE_LEN];
|
||||
|
||||
bf->line_pos = 0;
|
||||
bf_skipspace(bf);
|
||||
|
||||
if ( bf->is_bitmap_parsing == 0 )
|
||||
{
|
||||
/* regular command */
|
||||
bf->bitmap_y = 0;
|
||||
strcpy(cmd, bf_get_string(bf));
|
||||
|
||||
if ( strcmp(cmd, "" ) == 0 )
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
else if ( strcmp(cmd, "STARTFONT" ) == 0 ) /* args: s */
|
||||
{
|
||||
}
|
||||
else if ( strcmp(cmd, "FONT" ) == 0 ) /* args: s */
|
||||
{
|
||||
if ( bf->str_font != NULL )
|
||||
free(bf->str_font);
|
||||
bf->str_font = strdup(bf_get_eol_string(bf));
|
||||
}
|
||||
else if ( strcmp(cmd, "SIZE" ) == 0 ) /* args: lll */
|
||||
{
|
||||
}
|
||||
else if ( strcmp(cmd, "FONTBOUNDINGBOX" ) == 0 ) /* args: llll */
|
||||
{
|
||||
}
|
||||
else if ( strcmp(cmd, "STARTPROPERTIES" ) == 0 ) /* args: l */
|
||||
{
|
||||
}
|
||||
else if ( strcmp(cmd, "FONTNAME_REGISTRY" ) == 0 ) /* args: s */
|
||||
{
|
||||
}
|
||||
else if ( strcmp(cmd, "FOUNDRY" ) == 0 ) /* args: s */
|
||||
{
|
||||
}
|
||||
else if ( strcmp(cmd, "FAMILY_NAME" ) == 0 ) /* args: s */
|
||||
{
|
||||
}
|
||||
else if ( strcmp(cmd, "WEIGHT_NAME" ) == 0 ) /* args: s */
|
||||
{
|
||||
}
|
||||
else if ( strcmp(cmd, "SLANT" ) == 0 ) /* args: s */
|
||||
{
|
||||
}
|
||||
else if ( strcmp(cmd, "SETWIDTH_NAME" ) == 0 ) /* args: s */
|
||||
{
|
||||
}
|
||||
else if ( strcmp(cmd, "ADD_STYLE_NAME" ) == 0 ) /* args: s */
|
||||
{
|
||||
}
|
||||
else if ( strcmp(cmd, "PIXEL_SIZE" ) == 0 ) /* args: l */
|
||||
{
|
||||
}
|
||||
else if ( strcmp(cmd, "POINT_SIZE" ) == 0 ) /* args: l */
|
||||
{
|
||||
}
|
||||
else if ( strcmp(cmd, "RESOLUTION_X" ) == 0 ) /* args: l */
|
||||
{
|
||||
}
|
||||
else if ( strcmp(cmd, "RESOLUTION_Y" ) == 0 ) /* args: l */
|
||||
{
|
||||
}
|
||||
else if ( strcmp(cmd, "SPACING" ) == 0 ) /* args: s */
|
||||
{
|
||||
}
|
||||
else if ( strcmp(cmd, "AVERAGE_WIDTH" ) == 0 ) /* args: l */
|
||||
{
|
||||
}
|
||||
else if ( strcmp(cmd, "CHARSET_REGISTRY" ) == 0 ) /* args: s */
|
||||
{
|
||||
}
|
||||
else if ( strcmp(cmd, "CHARSET_ENCODING" ) == 0 ) /* args: s */
|
||||
{
|
||||
}
|
||||
else if ( strcmp(cmd, "DESTINATION" ) == 0 ) /* args: l */
|
||||
{
|
||||
}
|
||||
else if ( strcmp(cmd, "COPYRIGHT" ) == 0 ) /* args: s */
|
||||
{
|
||||
if ( bf->str_copyright != NULL )
|
||||
free(bf->str_copyright);
|
||||
bf->str_copyright = strdup(bf_get_eol_string(bf));
|
||||
}
|
||||
else if ( strcmp(cmd, "_XMBDFED_INFO" ) == 0 ) /* args: s */
|
||||
{
|
||||
}
|
||||
else if ( strcmp(cmd, "CAP_HEIGHT" ) == 0 ) /* args: l */
|
||||
{
|
||||
}
|
||||
else if ( strcmp(cmd, "X_HEIGHT" ) == 0 ) /* args: l */
|
||||
{
|
||||
}
|
||||
else if ( strcmp(cmd, "WEIGHT" ) == 0 ) /* args: l */
|
||||
{
|
||||
}
|
||||
else if ( strcmp(cmd, "QUAD_WIDTH" ) == 0 ) /* args: l */
|
||||
{
|
||||
}
|
||||
else if ( strcmp(cmd, "DEFAULT_CHAR" ) == 0 ) /* args: l */
|
||||
{
|
||||
}
|
||||
else if ( strcmp(cmd, "FONT_DESCENT" ) == 0 ) /* args: l */
|
||||
{
|
||||
}
|
||||
else if ( strcmp(cmd, "FONT_ASCENT" ) == 0 ) /* args: l */
|
||||
{
|
||||
}
|
||||
else if ( strcmp(cmd, "ENDPROPERTIES" ) == 0 ) /* args: - */
|
||||
{
|
||||
}
|
||||
else if ( strcmp(cmd, "CHARS" ) == 0 ) /* args: l */
|
||||
{
|
||||
}
|
||||
else if ( strcmp(cmd, "STARTCHAR" ) == 0 ) /* args: s */
|
||||
{
|
||||
}
|
||||
else if ( strcmp(cmd, "ENCODING" ) == 0 ) /* args: l */
|
||||
{
|
||||
bf->encoding = bf_get_long(bf);
|
||||
//bf_Log(bf, "BDF File: ENCODING %d", bf->encoding);
|
||||
}
|
||||
else if ( strcmp(cmd, "SWIDTH" ) == 0 ) /* args: ll */
|
||||
{
|
||||
}
|
||||
else if ( strcmp(cmd, "DWIDTH" ) == 0 ) /* args: ll */
|
||||
{
|
||||
bf->dwidth_x = bf_get_long(bf);
|
||||
bf->dwidth_y = bf_get_long(bf);
|
||||
|
||||
}
|
||||
else if ( strcmp(cmd, "BBX" ) == 0 ) /* args: llll */
|
||||
{
|
||||
bf->bbx_w = bf_get_long(bf);
|
||||
bf->bbx_h = bf_get_long(bf);
|
||||
bf->bbx_x = bf_get_long(bf);
|
||||
bf->bbx_y = bf_get_long(bf);
|
||||
}
|
||||
else if ( strcmp(cmd, "BITMAP" ) == 0 ) /* args: - */
|
||||
{
|
||||
if ( bf_add_glyph_to_list(bf) == 0 )
|
||||
return 0;
|
||||
bf->is_bitmap_parsing = 1;
|
||||
}
|
||||
else if ( strcmp(cmd, "ENDCHAR" ) == 0 ) /* args: - */
|
||||
{
|
||||
bf_Error(bf, "Unexpected ENDCHAR found");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* a line of the glyph bitmap */
|
||||
int c;
|
||||
strcpy(cmd, bf_get_string(bf));
|
||||
if ( strcmp(cmd, "ENDCHAR" ) == 0 ) /* args: - */
|
||||
{
|
||||
bf->is_bitmap_parsing = 0;
|
||||
/* bg_ShowBitmap(bf->glyph_list[bf->glyph_pos]); */
|
||||
}
|
||||
else
|
||||
{
|
||||
bf->line_pos = 0;
|
||||
bf_skipspace(bf);
|
||||
|
||||
|
||||
bf->bitmap_x = 0;
|
||||
|
||||
|
||||
for(;;)
|
||||
{
|
||||
c = bf_curr(bf);
|
||||
if ( c < '0' )
|
||||
break;
|
||||
bf_set_pixel_by_hex_char(bf, c);
|
||||
bf_next(bf);
|
||||
}
|
||||
|
||||
bf->bitmap_y++;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int bf_parse_file(bf_t *bf)
|
||||
{
|
||||
long line_cnt = 0;
|
||||
bf->is_bitmap_parsing = 0;
|
||||
for(;;)
|
||||
{
|
||||
line_cnt++;
|
||||
if ( fgets(bf->line_buf, BDF_LINE_LEN, bf->fp) == NULL )
|
||||
break;
|
||||
if ( bf_parse_line(bf) == 0 )
|
||||
{
|
||||
bf_Error(bf, "perse error in line %ld", line_cnt);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int bf_ParseFile(bf_t *bf, const char *name)
|
||||
{
|
||||
int r;
|
||||
bf->fp = fopen(name, "r");
|
||||
if ( bf->fp == NULL )
|
||||
{
|
||||
bf_Error(bf, "Can not open bdf file '%s'", name);
|
||||
return 0;
|
||||
}
|
||||
r = bf_parse_file(bf);
|
||||
fclose(bf->fp);
|
||||
bf_Log(bf, "Parse File %s: %d glyph(s) found", name, bf->glyph_cnt);
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,773 @@
|
||||
/*
|
||||
|
||||
bdf_rle.c
|
||||
|
||||
run length glyph encoding
|
||||
|
||||
|
||||
size comparison with old and new font format
|
||||
4x6 1500 1469
|
||||
4x6r 734 726
|
||||
6x10 1866 2009
|
||||
6x10r 889 971
|
||||
7x13B 2172 2253
|
||||
7x13Br 1041 1017
|
||||
9x15 2959 2649
|
||||
9x15r 1427 1242
|
||||
10x20 3453 3053
|
||||
10x20r 1667 1417 85%
|
||||
courB12 3959 3312
|
||||
courB12r 1857 1538
|
||||
courB24 10502 6661
|
||||
courB24r 4775 3015 63%
|
||||
helvB24 10931 6904 63%
|
||||
helvB24r 4992 3166 63%
|
||||
logisoso50r 14375 5248 36%
|
||||
|
||||
|
||||
*/
|
||||
|
||||
/* font information */
|
||||
/*
|
||||
glyph_cnt = *font++;
|
||||
bits_per_0 = *font++;
|
||||
bits_per_1 = *font++;
|
||||
bits_per_char_width = *font++;
|
||||
bits_per_char_height = *font++;
|
||||
bits_per_char_x = *font++;
|
||||
bits_per_char_y = *font++;
|
||||
bits_per_delta_x = *font++;
|
||||
|
||||
*/
|
||||
|
||||
/* apply glyph information */
|
||||
/*
|
||||
~ encoding unsigned, 1 byte
|
||||
~ total size unsigned, 1 byte
|
||||
~ BBX width unsigned 5
|
||||
~ BBX height unsigned 5
|
||||
~ BBX xoffset signed 2
|
||||
~ BBX yoffset signed 5
|
||||
~ DWIDTH unsigned 3
|
||||
|
||||
|
||||
*/
|
||||
|
||||
#define BDF_RLE_FONT_GLYPH_START 21
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include "bdf_font.h"
|
||||
|
||||
#ifdef OLD_CODE
|
||||
|
||||
#define SCREEN_W 140
|
||||
#define SCREEN_H 140
|
||||
|
||||
uint8_t screen_buf[SCREEN_H][SCREEN_W];
|
||||
unsigned screen_max_y;
|
||||
|
||||
void screen_init(void)
|
||||
{
|
||||
unsigned x, y;
|
||||
screen_max_y = 0;
|
||||
for( y = 0; y < SCREEN_H; y++ )
|
||||
{
|
||||
for( x = 0; x < SCREEN_W; x++ )
|
||||
{
|
||||
screen_buf[y][x] = '.';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void screen_set_pixel(unsigned x, unsigned y, uint8_t c)
|
||||
{
|
||||
if ( screen_max_y < y)
|
||||
screen_max_y = y;
|
||||
screen_buf[y][x] = c;
|
||||
}
|
||||
|
||||
void screen_show(void)
|
||||
{
|
||||
unsigned x, y;
|
||||
printf("\n");
|
||||
for( y = 0; y <= screen_max_y; y++ )
|
||||
{
|
||||
for( x = 0; x < SCREEN_W; x++ )
|
||||
{
|
||||
printf("%c", screen_buf[y][x]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
/*===================================================*/
|
||||
|
||||
/* font decode */
|
||||
struct fd_struct
|
||||
{
|
||||
unsigned x; /* local coordinates, (0,0) is upper left */
|
||||
unsigned y;
|
||||
unsigned glyph_width;
|
||||
unsigned glyph_height;
|
||||
|
||||
|
||||
const uint8_t *decode_ptr; /* pointer to the compressed data */
|
||||
unsigned decode_bit_pos; /* bitpos inside a byte of the compressed data */
|
||||
|
||||
uint8_t bbx_x_max_bit_size;
|
||||
uint8_t bbx_y_max_bit_size;
|
||||
uint8_t bbx_w_max_bit_size;
|
||||
uint8_t bbx_h_max_bit_size;
|
||||
uint8_t dx_max_bit_size;
|
||||
|
||||
};
|
||||
typedef struct fd_struct fd_t;
|
||||
|
||||
/* increment x and consider line wrap (inc y)*/
|
||||
static void fd_inc(fd_t *f)
|
||||
{
|
||||
unsigned x = f->x;
|
||||
x++;
|
||||
if ( x == f->glyph_width )
|
||||
{
|
||||
x = 0;
|
||||
f->y++;
|
||||
}
|
||||
f->x = x;
|
||||
}
|
||||
|
||||
|
||||
static unsigned fd_get_unsigned_bits(fd_t *f, unsigned cnt)
|
||||
{
|
||||
unsigned val;
|
||||
unsigned bit_pos = f->decode_bit_pos;
|
||||
|
||||
val = *(f->decode_ptr);
|
||||
|
||||
val >>= bit_pos;
|
||||
if ( bit_pos + cnt >= 8 )
|
||||
{
|
||||
f->decode_ptr++;
|
||||
val |= *(f->decode_ptr) << (8-bit_pos);
|
||||
bit_pos -= 8;
|
||||
}
|
||||
val &= (1U<<cnt)-1;
|
||||
bit_pos += cnt;
|
||||
|
||||
f->decode_bit_pos = bit_pos;
|
||||
return val;
|
||||
}
|
||||
|
||||
/*
|
||||
2 bit --> cnt = 2
|
||||
-2,-1,0. 1
|
||||
|
||||
3 bit --> cnt = 3
|
||||
-2,-1,0. 1
|
||||
-4,-3,-2,-1,0,1,2,3
|
||||
|
||||
if ( x < 0 )
|
||||
r = bits(x-1)+1;
|
||||
else
|
||||
r = bits(x)+1;
|
||||
|
||||
*/
|
||||
static int fd_get_signed_bits(fd_t *t, int cnt)
|
||||
{
|
||||
return (int)fd_get_unsigned_bits(t, cnt) - ((1<<cnt)>>1);
|
||||
}
|
||||
|
||||
|
||||
static void fd_draw_pixel(fd_t *f)
|
||||
{
|
||||
screen_set_pixel(f->x, f->y, '#');
|
||||
}
|
||||
|
||||
static void fd_decode(bg_t *bg, bbx_t *bbx, fd_t *f, unsigned rle_bits_per_0, unsigned rle_bits_per_1)
|
||||
{
|
||||
unsigned a, b;
|
||||
unsigned i;
|
||||
|
||||
screen_init();
|
||||
|
||||
if ( bbx == NULL )
|
||||
bbx = &(bg->bbx);
|
||||
|
||||
/* init decode algorithm */
|
||||
f->decode_ptr = bg->target_data;
|
||||
f->decode_bit_pos = 0;
|
||||
f->glyph_width = bbx->w;
|
||||
f->glyph_height = bbx->h;
|
||||
|
||||
|
||||
/* read glyph info */
|
||||
f->decode_ptr += 2;
|
||||
|
||||
fd_get_unsigned_bits(f, f->bbx_w_max_bit_size);
|
||||
fd_get_unsigned_bits(f, f->bbx_h_max_bit_size);
|
||||
fd_get_signed_bits(f, f->bbx_x_max_bit_size);
|
||||
fd_get_signed_bits(f, f->bbx_y_max_bit_size);
|
||||
fd_get_signed_bits(f, f->dx_max_bit_size);
|
||||
|
||||
/* reset local x/y position */
|
||||
f->x = 0;
|
||||
f->y = 0;
|
||||
|
||||
//puts("");
|
||||
|
||||
/* decode glyph */
|
||||
for(;;)
|
||||
{
|
||||
a = fd_get_unsigned_bits(f, rle_bits_per_0);
|
||||
b = fd_get_unsigned_bits(f, rle_bits_per_1);
|
||||
//printf("[%u %u]", a, b);
|
||||
do
|
||||
{
|
||||
for( i = 0; i < a; i++ )
|
||||
{
|
||||
fd_inc(f);
|
||||
}
|
||||
|
||||
for( i = 0; i < b; i++ )
|
||||
{
|
||||
fd_draw_pixel(f);
|
||||
fd_inc(f);
|
||||
}
|
||||
|
||||
} while( fd_get_unsigned_bits(f, 1) != 0 );
|
||||
|
||||
if ( f->y >= f->glyph_height )
|
||||
break;
|
||||
}
|
||||
|
||||
screen_show();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*===================================================*/
|
||||
|
||||
|
||||
/*
|
||||
Desc:
|
||||
Output a and b to the stream.
|
||||
a and b must fit to the target size in bits.
|
||||
Additionally a repeat code r (one bit) is generated:
|
||||
It may look like this:
|
||||
r = 0: 0aaaabb
|
||||
or
|
||||
r = 1: 1
|
||||
If r is 0, then the number of zeros (a) and ones (b) will follow and both
|
||||
values must be stored as in the decoder.
|
||||
If r os 1, then the number of zeros and ones is repeated once
|
||||
Args:
|
||||
a: number of 0 bits, log2(a) must be smaller or equal to the fieldsize
|
||||
b: number of 1 bits, log2(b) must be smaller or equal to the fieldsize
|
||||
*/
|
||||
|
||||
static void bg_err(const char *s)
|
||||
{
|
||||
puts(s);
|
||||
}
|
||||
|
||||
static void bg_init_rle(bg_t *bg, unsigned rle_bits_per_0, unsigned rle_bits_per_1)
|
||||
{
|
||||
bg->rle_bitcnt = 0;
|
||||
bg->rle_is_first = 1;
|
||||
bg->rle_bits_per_0 = rle_bits_per_0;
|
||||
bg->rle_bits_per_1 = rle_bits_per_1;
|
||||
bg->rle_last_0 = 0;
|
||||
bg->rle_last_1 = 1;
|
||||
bg_ClearTargetData(bg);
|
||||
}
|
||||
|
||||
static int bg_01_rle(bg_t *bg, unsigned a, unsigned b)
|
||||
{
|
||||
if ( bg->rle_is_first == 0 && bg->rle_last_0 == a && bg->rle_last_1 == b )
|
||||
{
|
||||
bg->rle_bitcnt++;
|
||||
if ( bg_AddTargetBits(bg, 1, 1) == 0 )
|
||||
return bg_err("error in bg_01_rle 1 0"), 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( bg->rle_is_first == 0 )
|
||||
{
|
||||
if ( bg_AddTargetBits(bg, 1, 0) == 0 )
|
||||
return bg_err("error in bg_01_rle 1 0"), 0;
|
||||
bg->rle_bitcnt++;
|
||||
}
|
||||
if ( bg_AddTargetBits(bg, bg->rle_bits_per_0, a) == 0 )
|
||||
return bg_err("error in bg_01_rle 1 a"), 0;
|
||||
if ( bg_AddTargetBits(bg, bg->rle_bits_per_1, b) == 0 )
|
||||
return bg_err("error in bg_01_rle 1 b"), 0;
|
||||
|
||||
|
||||
/*
|
||||
if ( bg->encoding == ' ' )
|
||||
{
|
||||
printf("[%u %u]", a, b);
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
bg->rle_is_first = 0;
|
||||
bg->rle_bitcnt +=bg->rle_bits_per_0;
|
||||
bg->rle_bitcnt +=bg->rle_bits_per_1;
|
||||
bg->rle_last_0 = a;
|
||||
bg->rle_last_1 = b;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
Desc:
|
||||
Write the number of zeros and ones to the bit stream.
|
||||
There is no restriction on the size of a and b.
|
||||
Args:
|
||||
a: number of 0 bits
|
||||
b: number of 1 bits
|
||||
|
||||
*/
|
||||
static int bg_prepare_01_rle(bg_t *bg, unsigned a, unsigned b)
|
||||
{
|
||||
//printf("[%u %u]", a, b);
|
||||
while( a >= (1<<bg->rle_bits_per_0) -1 )
|
||||
{
|
||||
if ( bg_01_rle(bg, (1<<bg->rle_bits_per_0) -1, 0) == 0 )
|
||||
return 0;
|
||||
a -= (1<<bg->rle_bits_per_0) -1;
|
||||
}
|
||||
while( b >= (1<<bg->rle_bits_per_1) -1 )
|
||||
{
|
||||
if ( bg_01_rle(bg, a, (1<<bg->rle_bits_per_1) -1) == 0 )
|
||||
return 0;
|
||||
a = 0;
|
||||
b -= (1<<bg->rle_bits_per_1) -1;
|
||||
}
|
||||
if ( a != 0 || b != 0 )
|
||||
if ( bg_01_rle(bg, a, b) == 0 )
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int bg_rle_compress(bg_t *bg, bbx_t *bbx, unsigned rle_bits_per_0, unsigned rle_bits_per_1, int is_output)
|
||||
{
|
||||
int x;
|
||||
int y;
|
||||
int i;
|
||||
int bd_is_one; /* bit delta */
|
||||
int bd_curr_len;
|
||||
int bd_max_len;
|
||||
int bd_chg_cnt;
|
||||
|
||||
static int bd_list[1024*2];
|
||||
|
||||
if ( bbx == NULL )
|
||||
bbx = &(bg->bbx);
|
||||
|
||||
bg_init_rle(bg, rle_bits_per_0, rle_bits_per_1);
|
||||
|
||||
|
||||
/* step 0: output initial information */
|
||||
//printf("%ld %ld\n", (long)bg->encoding, (long)bg->map_to);
|
||||
if ( bg_AddTargetData(bg, bg->map_to) < 0 )
|
||||
return bg_err("error in bg_rle_compress"), 0;
|
||||
/* size, will be added later */
|
||||
if ( bg_AddTargetData(bg, 0) < 0 )
|
||||
return bg_err("error in bg_rle_compress"), 0;
|
||||
if ( bg_AddTargetBits(bg, bg->bf->bbx_w_max_bit_size, bbx->w) == 0 )
|
||||
return bg_err("error in bg_rle_compress"), 0;
|
||||
if ( bg_AddTargetBits(bg, bg->bf->bbx_h_max_bit_size, bbx->h) == 0 )
|
||||
return bg_err("error in bg_rle_compress"), 0;
|
||||
if ( bg_AddTargetBits(bg, bg->bf->bbx_x_max_bit_size, bbx->x + (1<<(bg->bf->bbx_x_max_bit_size-1))) == 0 )
|
||||
return bg_err("error in bg_rle_compress"), 0;
|
||||
if ( bg_AddTargetBits(bg, bg->bf->bbx_y_max_bit_size, bbx->y + (1<<(bg->bf->bbx_y_max_bit_size-1))) == 0 )
|
||||
return bg_err("error in bg_rle_compress"), 0;
|
||||
|
||||
if ( bg->bf->bbx_mode == BDF_BBX_MODE_MINIMAL )
|
||||
{
|
||||
if ( bg_AddTargetBits(bg, bg->bf->dx_max_bit_size, bg->dwidth_x + (1<<(bg->bf->dx_max_bit_size-1))) == 0 )
|
||||
return bg_err("error in bg_rle_compress"), 0;
|
||||
}
|
||||
else if ( bg->bf->bbx_mode == BDF_BBX_MODE_MAX )
|
||||
{
|
||||
if ( bg_AddTargetBits(bg, bg->bf->dx_max_bit_size, bbx->w+ (1<<(bg->bf->dx_max_bit_size-1))) == 0 )
|
||||
return bg_err("error in bg_rle_compress"), 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( bg_AddTargetBits(bg, bg->bf->dx_max_bit_size, bbx->w+ (1<<(bg->bf->dx_max_bit_size-1))) == 0 )
|
||||
return bg_err("error in bg_rle_compress"), 0;
|
||||
}
|
||||
|
||||
bd_is_one = 0;
|
||||
bd_curr_len = 0;
|
||||
bd_max_len = 0;
|
||||
bd_chg_cnt = 0;
|
||||
|
||||
/* step 1: build array with pairs of a (number of zero bits) and b (number of one bits) */
|
||||
|
||||
for( y = bbx->y+bbx->h-1; y >= bbx->y; y--)
|
||||
{
|
||||
for( x = bbx->x; x < bbx->x + bbx->w; x++)
|
||||
{
|
||||
if ( bg_GetBBXPixel(bg, x, y) == 0 )
|
||||
{
|
||||
if ( bd_is_one != 0 )
|
||||
{
|
||||
bd_list[bd_chg_cnt] = bd_curr_len;
|
||||
bd_is_one = 0;
|
||||
bd_chg_cnt++;
|
||||
bd_curr_len = 0;
|
||||
}
|
||||
bd_curr_len++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( bd_is_one == 0 )
|
||||
{
|
||||
bd_list[bd_chg_cnt] = bd_curr_len;
|
||||
bd_is_one = 1;
|
||||
bd_chg_cnt++;
|
||||
bd_curr_len = 0;
|
||||
}
|
||||
bd_curr_len++;
|
||||
}
|
||||
|
||||
if ( bd_max_len < bd_curr_len )
|
||||
bd_max_len = bd_curr_len;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bd_list[bd_chg_cnt] = bd_curr_len;
|
||||
bd_chg_cnt++;
|
||||
|
||||
if ( (bd_chg_cnt & 1) == 1 )
|
||||
{
|
||||
assert(bd_is_one == 0);
|
||||
bd_list[bd_chg_cnt] = 0;
|
||||
bd_chg_cnt++;
|
||||
}
|
||||
|
||||
//printf("01 pairs = %d\n", bd_chg_cnt/2);
|
||||
|
||||
/* step 2: convert the array into bit stream */
|
||||
|
||||
//if ( bg->encoding == ' ' )
|
||||
// printf("Encoding list, pairs = %d\n", bd_chg_cnt/2);
|
||||
|
||||
for( i = 0; i < bd_chg_cnt; i+=2 )
|
||||
{
|
||||
//if ( bg->encoding == ' ' )
|
||||
// printf("(%d %d)", bd_list[i], bd_list[i+1]);
|
||||
|
||||
if ( bg_prepare_01_rle(bg, bd_list[i], bd_list[i+1]) == 0 )
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//if ( bg->encoding == 'B' )
|
||||
// printf("\nEncoding list end\n");
|
||||
|
||||
if ( bg_AddTargetBits(bg, 1, 0) == 0 ) // ensure that there is a 0 bit at the end. This will simplify decoding loop
|
||||
return 0;
|
||||
|
||||
if ( bg_FlushTargetBits(bg) == 0 ) // finish the last byte and update bg->target_cnt
|
||||
return 0;
|
||||
|
||||
|
||||
bg->target_data[1] = bg->target_cnt;
|
||||
|
||||
/*
|
||||
{
|
||||
fd_t f;
|
||||
f.bbx_x_max_bit_size = bg->bf->bbx_x_max_bit_size;
|
||||
f.bbx_y_max_bit_size = bg->bf->bbx_y_max_bit_size;
|
||||
f.bbx_w_max_bit_size = bg->bf->bbx_w_max_bit_size;
|
||||
f.bbx_h_max_bit_size = bg->bf->bbx_h_max_bit_size;
|
||||
f.dx_max_bit_size = bg->bf->dx_max_bit_size;
|
||||
|
||||
fd_decode(bg, bbx, &f, rle_bits_per_0, rle_bits_per_1);
|
||||
}
|
||||
*/
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
unsigned long bf_RLECompressAllGlyphsWithFieldSize(bf_t *bf, int rle_0, int rle_1, int is_output)
|
||||
{
|
||||
int i;
|
||||
bg_t *bg;
|
||||
unsigned long total_bits = 0;
|
||||
bbx_t local_bbx;
|
||||
|
||||
for( i = 0; i < bf->glyph_cnt; i++ )
|
||||
{
|
||||
bg = bf->glyph_list[i];
|
||||
if ( bg->map_to >= 0 )
|
||||
{
|
||||
bf_copy_bbx_and_update_shift(bf, &local_bbx, bg);
|
||||
#ifdef OLD_CLODE
|
||||
/* modifing the following code requires update ind bdf_font.c also */
|
||||
|
||||
if ( bf->bbx_mode == BDF_BBX_MODE_MINIMAL )
|
||||
{
|
||||
local_bbx = bg->bbx;
|
||||
}
|
||||
else if ( bf->bbx_mode == BDF_BBX_MODE_MAX )
|
||||
{
|
||||
local_bbx = bf->max;
|
||||
local_bbx.x = 0;
|
||||
if ( bg->bbx.x < 0 )
|
||||
bg->shift_x = bg->bbx.x;
|
||||
if ( local_bbx.w < bg->dwidth_x )
|
||||
local_bbx.w = bg->dwidth_x;
|
||||
}
|
||||
else if ( bf->bbx_mode == BDF_BBX_MODE_M8 )
|
||||
{
|
||||
local_bbx.w = bf->max.w;
|
||||
if ( local_bbx.w < bg->dwidth_x )
|
||||
local_bbx.w = bg->dwidth_x;
|
||||
local_bbx.w = (local_bbx.w+7) & ~7;
|
||||
local_bbx.h = (bf->max.h+7) & ~7;
|
||||
local_bbx.x = bf->max.x;
|
||||
local_bbx.y = bf->max.y;
|
||||
local_bbx.x = 0;
|
||||
if ( bg->bbx.x < 0 )
|
||||
bg->shift_x = bg->bbx.x;
|
||||
}
|
||||
else
|
||||
{
|
||||
local_bbx = bf->max;
|
||||
local_bbx.w = bg->bbx.w;
|
||||
local_bbx.x = bg->bbx.x;
|
||||
|
||||
local_bbx.x = 0;
|
||||
if ( bg->bbx.x < 0 )
|
||||
{
|
||||
/* e.g. "j" */
|
||||
local_bbx.w -= bg->bbx.x;
|
||||
bg->shift_x = bg->bbx.x;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* e.g. "B" */
|
||||
local_bbx.w += bg->bbx.x;
|
||||
//bg->shift_x = bg->bbx.x;
|
||||
}
|
||||
if ( local_bbx.w < bg->dwidth_x )
|
||||
local_bbx.w = bg->dwidth_x;
|
||||
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
bg_rle_compress(bg, &local_bbx, rle_0, rle_1, is_output);
|
||||
total_bits += bg->target_cnt*8+bg->target_bit_pos;
|
||||
if ( is_output != 0 )
|
||||
{
|
||||
bf_Log(bf, "RLE Compress: Encoding %ld bits %u/%u", bg->encoding, bg->rle_bitcnt, bg->target_cnt*8+bg->target_bit_pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
//bf_Log(bf, "RLE Compress: zero bits %d, one bits %d, total bit size %lu", rle_0, rle_1, total_bits);
|
||||
return total_bits;
|
||||
}
|
||||
|
||||
|
||||
unsigned bf_RLE_get_glyph_data(bf_t *bf, uint8_t encoding)
|
||||
{
|
||||
uint8_t *font = bf->target_data;
|
||||
font += BDF_RLE_FONT_GLYPH_START;
|
||||
for(;;)
|
||||
{
|
||||
if ( font[1] == 0 )
|
||||
break;
|
||||
if ( font[0] == encoding )
|
||||
{
|
||||
return (font-bf->target_data)-BDF_RLE_FONT_GLYPH_START;
|
||||
}
|
||||
font += font[1];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void bf_RLECompressAllGlyphs(bf_t *bf)
|
||||
{
|
||||
int i, j;
|
||||
bg_t *bg;
|
||||
|
||||
int rle_0, rle_1;
|
||||
int best_rle_0=0, best_rle_1= 0;
|
||||
unsigned long total_bits = 0;
|
||||
unsigned long min_total_bits = 0xffffffff;
|
||||
|
||||
int idx_cap_a;
|
||||
int idx_cap_a_ascent;
|
||||
int idx_1;
|
||||
int idx_1_ascent;
|
||||
int idx_g;
|
||||
int idx_g_descent;
|
||||
int idx_para;
|
||||
int idx_para_ascent;
|
||||
int idx_para_descent;
|
||||
|
||||
unsigned pos;
|
||||
|
||||
idx_cap_a_ascent = 0;
|
||||
idx_cap_a = bf_GetIndexByEncoding(bf, 'A');
|
||||
if ( idx_cap_a >= 0 )
|
||||
{
|
||||
idx_cap_a_ascent = bf->glyph_list[idx_cap_a]->bbx.h+bf->glyph_list[idx_cap_a]->bbx.y;
|
||||
}
|
||||
|
||||
idx_1_ascent = 0;
|
||||
idx_1 = bf_GetIndexByEncoding(bf, '1');
|
||||
if ( idx_1 >= 0 )
|
||||
{
|
||||
idx_1_ascent = bf->glyph_list[idx_1]->bbx.h+bf->glyph_list[idx_1]->bbx.y;
|
||||
}
|
||||
|
||||
idx_g_descent = 0;
|
||||
idx_g = bf_GetIndexByEncoding(bf, 'g');
|
||||
if ( idx_g >= 0 )
|
||||
{
|
||||
idx_g_descent = bf->glyph_list[idx_g]->bbx.y;
|
||||
}
|
||||
|
||||
|
||||
idx_para_ascent = 0;
|
||||
idx_para = bf_GetIndexByEncoding(bf, '(');
|
||||
if ( idx_para >= 0 )
|
||||
{
|
||||
idx_para_ascent = bf->glyph_list[idx_para]->bbx.h+bf->glyph_list[idx_para]->bbx.y;
|
||||
idx_para_descent = bf->glyph_list[idx_para]->bbx.y;
|
||||
}
|
||||
else
|
||||
{
|
||||
idx_para_ascent = idx_cap_a_ascent;
|
||||
if ( idx_para_ascent == 0 )
|
||||
idx_para_ascent = idx_1_ascent;
|
||||
|
||||
idx_para_descent = idx_g_descent;
|
||||
}
|
||||
|
||||
|
||||
for( rle_0 = 2; rle_0 < 7; rle_0++ )
|
||||
{
|
||||
for( rle_1 = 2; rle_1 < 7; rle_1++ )
|
||||
{
|
||||
total_bits = bf_RLECompressAllGlyphsWithFieldSize(bf, rle_0, rle_1, 0);
|
||||
if ( min_total_bits > total_bits )
|
||||
{
|
||||
min_total_bits = total_bits;
|
||||
best_rle_0 = rle_0;
|
||||
best_rle_1 = rle_1;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
bf_Log(bf, "RLE Compress: best zero bits %d, one bits %d, total bit size %lu", best_rle_0, best_rle_1, min_total_bits);
|
||||
bf_RLECompressAllGlyphsWithFieldSize(bf, best_rle_0, best_rle_1, 0);
|
||||
|
||||
|
||||
bf_ClearTargetData(bf);
|
||||
|
||||
/*
|
||||
glyph_cnt = *font++;
|
||||
bits_per_0 = *font++;
|
||||
bits_per_1 = *font++;
|
||||
bits_per_char_width = *font++;
|
||||
bits_per_char_height = *font++;
|
||||
bits_per_char_x = *font++;
|
||||
bits_per_char_y = *font++;
|
||||
bits_per_delta_x = *font++;
|
||||
*/
|
||||
|
||||
bf_Log(bf, "RLE Compress: Font code generation, selected glyphs=%d, total glyphs=%d", bf->selected_glyphs, bf->glyph_cnt);
|
||||
|
||||
/* 0 */
|
||||
bf_AddTargetData(bf, bf->selected_glyphs);
|
||||
bf_AddTargetData(bf, bf->bbx_mode);
|
||||
bf_AddTargetData(bf, best_rle_0);
|
||||
bf_AddTargetData(bf, best_rle_1);
|
||||
|
||||
/* 4 */
|
||||
bf_AddTargetData(bf, bf->bbx_w_max_bit_size);
|
||||
bf_AddTargetData(bf, bf->bbx_h_max_bit_size);
|
||||
bf_AddTargetData(bf, bf->bbx_x_max_bit_size);
|
||||
bf_AddTargetData(bf, bf->bbx_y_max_bit_size);
|
||||
bf_AddTargetData(bf, bf->dx_max_bit_size);
|
||||
|
||||
/* 9 */
|
||||
bf_AddTargetData(bf, bf->max.w);
|
||||
bf_AddTargetData(bf, bf->max.h);
|
||||
bf_AddTargetData(bf, bf->max.x);
|
||||
bf_AddTargetData(bf, bf->max.y);
|
||||
|
||||
/* 13 */
|
||||
if ( idx_cap_a_ascent > 0 )
|
||||
bf_AddTargetData(bf, idx_cap_a_ascent);
|
||||
else
|
||||
bf_AddTargetData(bf, idx_1_ascent);
|
||||
bf_AddTargetData(bf, idx_g_descent);
|
||||
|
||||
/* 15 */
|
||||
bf_AddTargetData(bf, idx_para_ascent);
|
||||
bf_AddTargetData(bf, idx_para_descent);
|
||||
|
||||
/* 17 */
|
||||
bf_AddTargetData(bf, 0); /* start pos 'A', high/low */
|
||||
bf_AddTargetData(bf, 0);
|
||||
|
||||
/* 19 */
|
||||
bf_AddTargetData(bf, 0); /* start pos 'a', high/low */
|
||||
bf_AddTargetData(bf, 0);
|
||||
|
||||
for( i = 0; i < bf->glyph_cnt; i++ )
|
||||
{
|
||||
bg = bf->glyph_list[i];
|
||||
if ( bg->map_to >= 0 )
|
||||
{
|
||||
if ( bg->target_data != NULL )
|
||||
{
|
||||
|
||||
if ( bg->target_cnt >= 255 )
|
||||
{
|
||||
bf_Error(bf, "RLE Compress: Error, glyph too large, encoding=", bg->encoding);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
for( j = 0; j < bg->target_cnt; j++ )
|
||||
{
|
||||
bf_AddTargetData(bf, bg->target_data[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* add empty glyph as end of font marker */
|
||||
bf_AddTargetData(bf, 0);
|
||||
bf_AddTargetData(bf, 0);
|
||||
|
||||
pos = bf_RLE_get_glyph_data(bf, 'A');
|
||||
bf->target_data[17] = pos >> 8;
|
||||
bf->target_data[18] = pos & 255;
|
||||
|
||||
pos = bf_RLE_get_glyph_data(bf, 'a');
|
||||
bf->target_data[19] = pos >> 8;
|
||||
bf->target_data[20] = pos & 255;
|
||||
|
||||
bf_Log(bf, "RLE Compress: 'A' pos = %u, 'a' pos = %u", bf_RLE_get_glyph_data(bf, 'A'), bf_RLE_get_glyph_data(bf, 'a'));
|
||||
|
||||
bf_Log(bf, "RLE Compress: Font size %d", bf->target_cnt);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,561 @@
|
||||
/*
|
||||
|
||||
bdf_tga.c
|
||||
|
||||
|
||||
|
||||
Modes:
|
||||
BDF_BBX_MODE_MINIMAL 0
|
||||
BDF_BBX_MODE_MAX 1
|
||||
BDF_BBX_MODE_HEIGHT 2
|
||||
|
||||
For all modes, default reference should be the baseline.
|
||||
This is required for mode 0, but may be optional for 1 and 2
|
||||
|
||||
If (x,y) is the user provided baseline point for the glyph, then
|
||||
the decoding mus tbe start at
|
||||
(x..., y-h-descent)
|
||||
|
||||
|
||||
BDF_BBX_MODE_MINIMAL
|
||||
- exact space as intended by the font author
|
||||
- glyphs my overlap ("mj" with osb18)
|
||||
|
||||
BDF_BBX_MODE_MAX
|
||||
- extra space may be added
|
||||
- glyphs do not overlap
|
||||
|
||||
BDF_BBX_MODE_HEIGHT
|
||||
- extra space may be added
|
||||
- glyphs do not overlap
|
||||
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include "fd.h"
|
||||
|
||||
|
||||
static uint16_t tga_width;
|
||||
static uint16_t tga_height;
|
||||
static uint8_t *tga_data = NULL;
|
||||
|
||||
static uint8_t *tga_font;
|
||||
static int glyph_cnt;
|
||||
static int bits_per_0;
|
||||
static int bits_per_1;
|
||||
static int bits_per_char_width;
|
||||
static int bits_per_char_height;
|
||||
static int bits_per_char_x;
|
||||
static int bits_per_char_y;
|
||||
static int bits_per_delta_x;
|
||||
static int char_width;
|
||||
static int char_height;
|
||||
static int char_descent;
|
||||
|
||||
|
||||
int tga_get_char_width(void)
|
||||
{
|
||||
return char_width;
|
||||
}
|
||||
|
||||
int tga_get_char_height(void)
|
||||
{
|
||||
return char_height;
|
||||
}
|
||||
|
||||
int tga_init(uint16_t w, uint16_t h)
|
||||
{
|
||||
tga_width = 0;
|
||||
tga_height = 0;
|
||||
if ( tga_data != NULL )
|
||||
free(tga_data);
|
||||
tga_data = (uint8_t *)malloc((size_t)w*(size_t)h*3);
|
||||
if ( tga_data == NULL )
|
||||
return 0;
|
||||
tga_width = w;
|
||||
tga_height = h;
|
||||
memset(tga_data, 255, tga_width*tga_height*3);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void tga_set_pixel(uint16_t x, uint16_t y, uint8_t r, uint8_t g, uint8_t b)
|
||||
{
|
||||
uint8_t *p;
|
||||
if ( y>= tga_height)
|
||||
return;
|
||||
if ( x>= tga_width)
|
||||
return;
|
||||
p = tga_data + (tga_height-y-1)*(size_t)tga_width*3 + (size_t)x*3;
|
||||
*p++ = b;
|
||||
*p++ = g;
|
||||
*p++ = r;
|
||||
}
|
||||
|
||||
void tga_write_byte(FILE *fp, uint8_t byte)
|
||||
{
|
||||
fputc(byte, fp);
|
||||
}
|
||||
|
||||
void tga_write_word(FILE *fp, uint16_t word)
|
||||
{
|
||||
tga_write_byte(fp, word&255);
|
||||
tga_write_byte(fp, word>>8);
|
||||
}
|
||||
|
||||
void tga_save(const char *name)
|
||||
{
|
||||
FILE *fp;
|
||||
fp = fopen(name, "wb");
|
||||
if ( fp != NULL )
|
||||
{
|
||||
tga_write_byte(fp, 0); /* no ID */
|
||||
tga_write_byte(fp, 0); /* no color map */
|
||||
tga_write_byte(fp, 2); /* uncompressed true color */
|
||||
tga_write_word(fp, 0);
|
||||
tga_write_word(fp, 0);
|
||||
tga_write_byte(fp, 0);
|
||||
tga_write_word(fp, 0); /* x origin */
|
||||
tga_write_word(fp, 0); /* y origin */
|
||||
tga_write_word(fp, tga_width); /* width */
|
||||
tga_write_word(fp, tga_height); /* height */
|
||||
tga_write_byte(fp, 24); /* color depth */
|
||||
tga_write_byte(fp, 0);
|
||||
fwrite(tga_data, tga_width*tga_height*3, 1, fp);
|
||||
tga_write_word(fp, 0);
|
||||
tga_write_word(fp, 0);
|
||||
tga_write_word(fp, 0);
|
||||
tga_write_word(fp, 0);
|
||||
fwrite("TRUEVISION-XFILE.", 18, 1, fp);
|
||||
fclose(fp);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
font data:
|
||||
|
||||
offset bytes description
|
||||
0 1 glyph_cnt number of glyphs
|
||||
1 1 bbx_mode 0: proportional, 1: common height, 2: monospace, 3: multiple of 8
|
||||
2 1 bits_per_0 glyph rle parameter
|
||||
3 1 bits_per_1 glyph rle parameter
|
||||
|
||||
4 1 bits_per_char_width glyph rle parameter
|
||||
5 1 bits_per_char_height glyph rle parameter
|
||||
6 1 bits_per_char_x glyph rle parameter
|
||||
7 1 bits_per_char_y glyph rle parameter
|
||||
8 1 bits_per_delta_x glyph rle parameter
|
||||
|
||||
9 1 max_char_width
|
||||
10 1 max_char_height
|
||||
11 1 x offset
|
||||
12 1 y offset (descent)
|
||||
|
||||
13 1 ascent (capital A)
|
||||
14 1 descent (lower g)
|
||||
15 1 ascent '('
|
||||
16 1 descent ')'
|
||||
|
||||
17 1 start pos 'A' high byte
|
||||
18 1 start pos 'A' low byte
|
||||
|
||||
19 1 start pos 'a' high byte
|
||||
20 1 start pos 'a' low byte
|
||||
|
||||
*/
|
||||
|
||||
void tga_set_font(uint8_t *font)
|
||||
{
|
||||
glyph_cnt = *font++;
|
||||
font++; /* bbx mode */
|
||||
bits_per_0 = *font++;
|
||||
bits_per_1 = *font++;
|
||||
bits_per_char_width = *font++;
|
||||
bits_per_char_height = *font++;
|
||||
bits_per_char_x = *font++;
|
||||
bits_per_char_y = *font++;
|
||||
bits_per_delta_x = *font++;
|
||||
char_width = *font++;
|
||||
char_height = *font++;
|
||||
font++; /* x offset */
|
||||
char_descent = *(int8_t *)font;
|
||||
font++;
|
||||
|
||||
font++;
|
||||
font++;
|
||||
font++;
|
||||
font++;
|
||||
|
||||
font++;
|
||||
font++;
|
||||
font++;
|
||||
font++;
|
||||
|
||||
tga_font = font;
|
||||
|
||||
}
|
||||
|
||||
#ifdef OLD_CODE
|
||||
uint8_t *tga_get_glyph_data(uint8_t encoding)
|
||||
{
|
||||
int i;
|
||||
uint8_t *font = tga_font;
|
||||
for( i = 0; i < glyph_cnt; i++ )
|
||||
{
|
||||
if ( font[0] == encoding )
|
||||
{
|
||||
return font;
|
||||
}
|
||||
font += font[1];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
uint8_t *tga_get_glyph_data(uint8_t encoding)
|
||||
{
|
||||
uint8_t *font = tga_font;
|
||||
for(;;)
|
||||
{
|
||||
if ( font[1] == 0 )
|
||||
break;
|
||||
if ( font[0] == encoding )
|
||||
{
|
||||
return font;
|
||||
}
|
||||
font += font[1];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/* font decode */
|
||||
struct tga_fd_struct
|
||||
{
|
||||
unsigned target_x;
|
||||
unsigned target_y;
|
||||
unsigned is_transparent;
|
||||
|
||||
unsigned x; /* local coordinates, (0,0) is upper left */
|
||||
unsigned y;
|
||||
unsigned glyph_width;
|
||||
unsigned glyph_height;
|
||||
|
||||
|
||||
const uint8_t *decode_ptr; /* pointer to the compressed data */
|
||||
unsigned decode_bit_pos; /* bitpos inside a byte of the compressed data */
|
||||
|
||||
uint8_t bbx_x_max_bit_size;
|
||||
uint8_t bbx_y_max_bit_size;
|
||||
uint8_t bbx_w_max_bit_size;
|
||||
uint8_t bbx_h_max_bit_size;
|
||||
uint8_t dx_max_bit_size;
|
||||
|
||||
};
|
||||
typedef struct tga_fd_struct tga_fd_t;
|
||||
|
||||
/* increment x and consider line wrap (inc y)*/
|
||||
/* old procedure */
|
||||
void tga_fd_inc(tga_fd_t *f)
|
||||
{
|
||||
unsigned x = f->x;
|
||||
x++;
|
||||
if ( x == f->glyph_width )
|
||||
{
|
||||
x = 0;
|
||||
f->y++;
|
||||
}
|
||||
f->x = x;
|
||||
}
|
||||
|
||||
|
||||
unsigned tga_fd_get_unsigned_bits(tga_fd_t *f, unsigned cnt)
|
||||
{
|
||||
unsigned val;
|
||||
unsigned bit_pos = f->decode_bit_pos;
|
||||
|
||||
val = *(f->decode_ptr);
|
||||
|
||||
val >>= bit_pos;
|
||||
if ( bit_pos + cnt >= 8 )
|
||||
{
|
||||
f->decode_ptr++;
|
||||
val |= *(f->decode_ptr) << (8-bit_pos);
|
||||
bit_pos -= 8;
|
||||
}
|
||||
val &= (1U<<cnt)-1;
|
||||
bit_pos += cnt;
|
||||
|
||||
f->decode_bit_pos = bit_pos;
|
||||
return val;
|
||||
}
|
||||
|
||||
/*
|
||||
2 bit --> cnt = 2
|
||||
-2,-1,0. 1
|
||||
|
||||
3 bit --> cnt = 3
|
||||
-2,-1,0. 1
|
||||
-4,-3,-2,-1,0,1,2,3
|
||||
|
||||
if ( x < 0 )
|
||||
r = bits(x-1)+1;
|
||||
else
|
||||
r = bits(x)+1;
|
||||
|
||||
*/
|
||||
int tga_fd_get_signed_bits(tga_fd_t *t, int cnt)
|
||||
{
|
||||
return (int)tga_fd_get_unsigned_bits(t, cnt) - ((1<<cnt)>>1);
|
||||
}
|
||||
|
||||
|
||||
void tga_fd_draw_fg_pixel(tga_fd_t *f, unsigned cnt)
|
||||
{
|
||||
//printf("%d ", cnt);
|
||||
/* cnt can be zero */
|
||||
while( cnt > 0 )
|
||||
{
|
||||
cnt--;
|
||||
tga_set_pixel(f->target_x+f->x+cnt, f->target_y+f->y, 0,0,0);
|
||||
}
|
||||
}
|
||||
|
||||
void tga_fd_draw_bg_pixel(tga_fd_t *f, unsigned cnt)
|
||||
{
|
||||
//printf("%d ", cnt);
|
||||
/* cnt can be zero */
|
||||
while( cnt > 0 )
|
||||
{
|
||||
cnt--;
|
||||
if ( f->is_transparent == 0 )
|
||||
tga_set_pixel(f->target_x+f->x+cnt, f->target_y+f->y, 0x0e8,0x0e8,0x0e8);
|
||||
}
|
||||
}
|
||||
|
||||
void tga_draw_hline(unsigned x,unsigned y, unsigned cnt, unsigned is_foreground)
|
||||
{
|
||||
while( cnt > 0 )
|
||||
{
|
||||
cnt--;
|
||||
if ( is_foreground == 0 )
|
||||
tga_set_pixel(x+cnt, y, 0x0e8,0x0e8,0x0e8);
|
||||
else
|
||||
tga_set_pixel(x+cnt, y, 255,0,0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void tga_fd_draw_pixel(tga_fd_t *f, unsigned cnt, unsigned is_foreground)
|
||||
{
|
||||
if ( is_foreground )
|
||||
{
|
||||
tga_fd_draw_fg_pixel(f, cnt);
|
||||
}
|
||||
else
|
||||
{
|
||||
tga_fd_draw_bg_pixel(f, cnt);
|
||||
}
|
||||
}
|
||||
|
||||
void tga_fd_decode_len(tga_fd_t *f, unsigned len, unsigned is_foreground)
|
||||
{
|
||||
unsigned cnt, rem;
|
||||
cnt = len;
|
||||
for(;;)
|
||||
{
|
||||
rem = f->glyph_width;
|
||||
rem -= f->x;
|
||||
if ( cnt < rem )
|
||||
break;
|
||||
tga_fd_draw_pixel(f,rem, is_foreground);
|
||||
cnt -= rem;
|
||||
f->x = 0;
|
||||
f->y++;
|
||||
}
|
||||
tga_fd_draw_pixel(f, cnt, is_foreground);
|
||||
f->x += cnt;
|
||||
}
|
||||
|
||||
unsigned tga_fd_decode(tga_fd_t *f, uint8_t *glyph_data)
|
||||
{
|
||||
unsigned a, b;
|
||||
//unsigned cnt, rem;
|
||||
int x, y;
|
||||
unsigned d = 0;
|
||||
|
||||
f->decode_ptr = glyph_data;
|
||||
f->decode_bit_pos = 0;
|
||||
|
||||
f->decode_ptr += 1;
|
||||
f->decode_ptr += 1;
|
||||
|
||||
f->glyph_width = tga_fd_get_unsigned_bits(f, bits_per_char_width);
|
||||
f->glyph_height = tga_fd_get_unsigned_bits(f, bits_per_char_height);
|
||||
x = tga_fd_get_signed_bits(f, bits_per_char_x);
|
||||
y = tga_fd_get_signed_bits(f, bits_per_char_y);
|
||||
d = tga_fd_get_signed_bits(f, bits_per_delta_x);
|
||||
|
||||
if ( f->glyph_width > 0 )
|
||||
{
|
||||
|
||||
f->target_x += x;
|
||||
f->target_y -= f->glyph_height ;
|
||||
f->target_y -=y ;
|
||||
|
||||
/* reset local x/y position */
|
||||
f->x = 0;
|
||||
f->y = 0;
|
||||
|
||||
/* decode glyph */
|
||||
for(;;)
|
||||
{
|
||||
a = tga_fd_get_unsigned_bits(f, bits_per_0);
|
||||
b = tga_fd_get_unsigned_bits(f, bits_per_1);
|
||||
do
|
||||
{
|
||||
tga_fd_decode_len(f, a, 0);
|
||||
tga_fd_decode_len(f, b, 1);
|
||||
} while( tga_fd_get_unsigned_bits(f, 1) != 0 );
|
||||
|
||||
if ( f->y >= f->glyph_height )
|
||||
break;
|
||||
}
|
||||
}
|
||||
return d;
|
||||
}
|
||||
|
||||
unsigned tga_fd_decode_old(tga_fd_t *f, uint8_t *glyph_data)
|
||||
{
|
||||
unsigned a, b;
|
||||
unsigned i;
|
||||
int x, y;
|
||||
unsigned d = 0;
|
||||
//unsigned total;
|
||||
|
||||
|
||||
/* init decode algorithm */
|
||||
f->decode_ptr = glyph_data;
|
||||
f->decode_bit_pos = 0;
|
||||
|
||||
f->decode_ptr += 1;
|
||||
/* read glyph info */
|
||||
//total = *f->decode_ptr;
|
||||
f->decode_ptr += 1;
|
||||
|
||||
f->glyph_width = tga_fd_get_unsigned_bits(f, bits_per_char_width);
|
||||
f->glyph_height = tga_fd_get_unsigned_bits(f, bits_per_char_height);
|
||||
x = tga_fd_get_signed_bits(f, bits_per_char_x);
|
||||
y = tga_fd_get_signed_bits(f, bits_per_char_y);
|
||||
d = tga_fd_get_signed_bits(f, bits_per_delta_x);
|
||||
|
||||
|
||||
|
||||
if ( f->glyph_width > 0 )
|
||||
{
|
||||
|
||||
//printf("width: %d\n", f->glyph_width);
|
||||
//printf("height: %d\n", f->glyph_height);
|
||||
//printf("x: %d\n", x);
|
||||
//printf("y: %d\n", y);
|
||||
//printf("d: %d\n", d);
|
||||
|
||||
f->target_x += x;
|
||||
f->target_y -= f->glyph_height ;
|
||||
f->target_y -=y ;
|
||||
|
||||
|
||||
/* reset local x/y position */
|
||||
f->x = 0;
|
||||
f->y = 0;
|
||||
|
||||
//puts("");
|
||||
|
||||
//printf("start decode ");
|
||||
|
||||
/* decode glyph */
|
||||
for(;;)
|
||||
{
|
||||
a = tga_fd_get_unsigned_bits(f, bits_per_0);
|
||||
b = tga_fd_get_unsigned_bits(f, bits_per_1);
|
||||
do
|
||||
{
|
||||
|
||||
for( i = 0; i < a; i++ )
|
||||
{
|
||||
tga_fd_draw_bg_pixel(f,1);
|
||||
tga_fd_inc(f);
|
||||
}
|
||||
|
||||
/*
|
||||
while( a + f->x > f->glyph_width )
|
||||
{
|
||||
tga_fd_draw_bg_pixel(f,f->glyph_width-f->x);
|
||||
f->x = 0;
|
||||
f->y++;
|
||||
a -= f->glyph_width-f->x;
|
||||
}
|
||||
tga_fd_draw_bg_pixel(f,1);
|
||||
*/
|
||||
|
||||
for( i = 0; i < b; i++ )
|
||||
{
|
||||
tga_fd_draw_fg_pixel(f,1);
|
||||
tga_fd_inc(f);
|
||||
}
|
||||
|
||||
} while( tga_fd_get_unsigned_bits(f, 1) != 0 );
|
||||
|
||||
if ( f->y >= f->glyph_height )
|
||||
break;
|
||||
}
|
||||
}
|
||||
/*
|
||||
printf("\n");
|
||||
printf("[x=%u y=%u]\n", f->x, f->y);
|
||||
printf("cnt=%u total=%u\n", f->decode_ptr-glyph_data-2, total);
|
||||
printf("end decode\n");
|
||||
*/
|
||||
return d;
|
||||
}
|
||||
|
||||
unsigned tga_draw_glyph(unsigned x, unsigned y, uint8_t encoding, int is_hints)
|
||||
{
|
||||
unsigned dx = 0;
|
||||
tga_fd_t f;
|
||||
f.target_x = x;
|
||||
f.target_y = y;
|
||||
f.is_transparent = !is_hints;
|
||||
uint8_t *glyph_data = tga_get_glyph_data(encoding);
|
||||
if ( glyph_data != NULL )
|
||||
{
|
||||
dx = tga_fd_decode(&f, glyph_data);
|
||||
if ( is_hints )
|
||||
{
|
||||
tga_set_pixel(x+dx, y, 28,133,240); /* orange: reference point */
|
||||
tga_set_pixel(x, y, 255,164,0); /* blue: delta x (width) for this glyph */
|
||||
}
|
||||
}
|
||||
return dx;
|
||||
}
|
||||
|
||||
unsigned tga_draw_string(unsigned x, unsigned y, const char *s, int is_hints, unsigned max_dx)
|
||||
{
|
||||
unsigned dx = 0;
|
||||
while( *s != '\0' )
|
||||
{
|
||||
dx += tga_draw_glyph(x+dx,y,*s, is_hints);
|
||||
if ( max_dx > 0 )
|
||||
if ( dx > max_dx )
|
||||
break;
|
||||
s++;
|
||||
}
|
||||
return dx;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
|
||||
#ifndef _FD_H
|
||||
#define _FD_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/* font decode */
|
||||
struct fd_struct
|
||||
{
|
||||
unsigned target_x;
|
||||
unsigned target_y;
|
||||
unsigned is_transparent;
|
||||
|
||||
unsigned x; /* local coordinates, (0,0) is upper left */
|
||||
unsigned y;
|
||||
unsigned glyph_width;
|
||||
unsigned glyph_height;
|
||||
|
||||
const uint8_t *decode_ptr; /* pointer to the compressed data */
|
||||
unsigned decode_bit_pos; /* bitpos inside a byte of the compressed data */
|
||||
unsigned decode_byte;
|
||||
|
||||
uint8_t glyph_cnt;
|
||||
uint8_t bits_per_0;
|
||||
uint8_t bits_per_1;
|
||||
uint8_t bits_per_char_width;
|
||||
uint8_t bits_per_char_height;
|
||||
uint8_t bits_per_char_x;
|
||||
uint8_t bits_per_char_y;
|
||||
uint8_t bits_per_delta_x;
|
||||
uint8_t char_width;
|
||||
uint8_t char_height;
|
||||
uint8_t char_descent;
|
||||
unsigned capital_a_pos;
|
||||
unsigned small_a_pos;
|
||||
|
||||
uint8_t *font;
|
||||
|
||||
};
|
||||
typedef struct fd_struct fd_t;
|
||||
|
||||
void fd_init(fd_t *fd);
|
||||
void fd_set_font(fd_t *fd, uint8_t *font);
|
||||
unsigned fd_draw_glyph(fd_t *fd, unsigned x, unsigned y, uint8_t encoding);
|
||||
unsigned fd_draw_string(fd_t *fd, unsigned x, unsigned y, const char *s);
|
||||
|
||||
|
||||
|
||||
#endif /* _FD_H */
|
||||
@@ -0,0 +1,405 @@
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include "bdf_font.h"
|
||||
#include "fd.h"
|
||||
|
||||
/*================================================*/
|
||||
|
||||
int get_str_arg(char ***argv, int c, char **result)
|
||||
{
|
||||
if ( (**argv)[0] == '-' )
|
||||
{
|
||||
if ( (**argv)[1] == c )
|
||||
{
|
||||
if ( (**argv)[2] == '\0' )
|
||||
{
|
||||
(*argv)++;
|
||||
*result = **argv;
|
||||
}
|
||||
else
|
||||
{
|
||||
*result = (**argv)+2;
|
||||
}
|
||||
(*argv)++;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int get_num_arg(char ***argv, int c, unsigned long *result)
|
||||
{
|
||||
if ( (**argv)[0] == '-' )
|
||||
{
|
||||
if ( (**argv)[1] == c )
|
||||
{
|
||||
|
||||
if ( (**argv)[2] == '\0' )
|
||||
{
|
||||
if ( *((*argv)+1) != NULL )
|
||||
{
|
||||
(*argv)++;
|
||||
*result = strtoul((**argv), NULL, 10);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
*result = strtoul((**argv)+2, NULL, 10);
|
||||
}
|
||||
(*argv)++;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int is_arg(char ***argv, int c)
|
||||
{
|
||||
if ( (**argv)[0] == '-' )
|
||||
{
|
||||
if ( (**argv)[1] == c )
|
||||
{
|
||||
(*argv)++;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*================================================*/
|
||||
void help(void)
|
||||
{
|
||||
printf("bdfconv [options] filename\n");
|
||||
printf("-h Display this help\n");
|
||||
printf("-v Print log messages\n");
|
||||
printf("-b <n> Font build mode, 0: proportional, 1: common height, 2: monospace, 3: multiple of 8\n");
|
||||
printf("-f <n> Font format, 0: ucglib font, 1: u8g2 font, 2: u8g2 uncompressed 8x8 font (enforces -b 3)\n");
|
||||
printf("-m 'map' Unicode ASCII mapping\n");
|
||||
printf("-o <file> C output file\n");
|
||||
printf("-n <name> C indentifier (font name)\n");
|
||||
printf("-d <file> Overview picture: Enable generation of bdf.tga and assign BDF font <file> for description\n");
|
||||
printf("-l <margin> Overview picture: Set left margin\n");
|
||||
printf("-a Overview picture: Additional font information (background, orange&blue dot)\n");
|
||||
printf("-t Overview picture: Test string (Woven silk pyjamas exchanged for blue quartz.)\n");
|
||||
printf("-r Runtime test\n");
|
||||
printf("\n");
|
||||
|
||||
printf("map := <mapcmd> { \",\" <mapcmd> }\n");
|
||||
printf("mapcmd := <default> | <maprange> | <exclude>\n");
|
||||
printf("default := \"*\"\n");
|
||||
printf("maprange := <range> [ \">\" <addexpr> ] Move specified glyph <range> to target code <num>\n");
|
||||
printf("exclude := \"~\" <range> \n");
|
||||
printf("range := <addexpr> [ \"-\" <addexpr> ] Select glyphs within specified range\n");
|
||||
printf("addexpr := <mulexpr> [ \"+\" <mulexpr> ]\n");
|
||||
printf("mulexpr := <num> [ \"*\" <num> ]\n");
|
||||
printf("num := <hexnum> | <decnum>\n");
|
||||
printf("hexnum := \"$\" <hexdigit> { <hexdigit> }\n");
|
||||
printf("decnum := <decdigit> { <decdigit> }\n");
|
||||
printf("decdigit := \"0\" | \"1\" | \"2\" | \"3\" | \"4\" | \"5\" | \"6\" | \"7\" | \"8\" | \"9\"\n");
|
||||
printf("hexdigit := \"a\" | \"b\" | \"c\" | \"d\" | \"e\" | \"f\" | \"A\" | \"B\" | \"C\" | \"D\" | \"E\" | \"F\" | <decdigit>\n");
|
||||
|
||||
printf("{ } zero, one ore more, [ ] zero or once, | alternative\n");
|
||||
|
||||
printf("example:\n");
|
||||
printf(" -m '32-255' select gylphs from encoding 32 to 255\n");
|
||||
printf(" -m '32-255,~64' select gylphs from encoding 32 to 255, exclude '@'\n");
|
||||
printf(" -m '32,48-57' select space, '1', '2', ... '9'\n");
|
||||
printf("build modes:\n");
|
||||
printf(" -b 0: Most compact, glyph bitmap is minimal\n");
|
||||
printf(" -b 1: Like -b 0, but glyph bitmap is extended to the height of the largest glyph within the selected glyph list.\n");
|
||||
printf(" Also the width of the gylphs is extended to cover the delta x advance.\n");
|
||||
printf(" -b 2: Like -b 1, but glyph width is set to the width of the largest glyph within the selected gylph list.\n");
|
||||
printf(" -b 3: Like -b 2, but width and height are forced to be a multiple of 8.\n");
|
||||
|
||||
}
|
||||
|
||||
/*================================================*/
|
||||
|
||||
unsigned long left_margin = 1;
|
||||
unsigned long build_bbx_mode = 0;
|
||||
unsigned long font_format = 0;
|
||||
int font_picture_extra_info = 0;
|
||||
int font_picture_test_string = 0;
|
||||
int runtime_test = 0;
|
||||
char *c_filename = NULL;
|
||||
char *target_fontname = "bdf_font";
|
||||
|
||||
/*================================================*/
|
||||
|
||||
unsigned tga_get_line_height(bf_t *bf_desc_font, bf_t *bf)
|
||||
{
|
||||
unsigned h;
|
||||
tga_set_font(bf_desc_font->target_data);
|
||||
h = tga_get_char_height();
|
||||
tga_set_font(bf->target_data);
|
||||
if ( h < tga_get_char_height() )
|
||||
return tga_get_char_height();
|
||||
return h;
|
||||
}
|
||||
|
||||
unsigned tga_draw_font_line(unsigned y, long enc_start, bf_t *bf_desc_font, bf_t *bf)
|
||||
{
|
||||
long i;
|
||||
unsigned x;
|
||||
int is_empty;
|
||||
char pre[32];
|
||||
|
||||
is_empty = 1;
|
||||
for( i = 0; i< 16 && is_empty != 0; i++ )
|
||||
{
|
||||
if ( tga_get_glyph_data(i+enc_start) != NULL )
|
||||
is_empty = 0;
|
||||
}
|
||||
|
||||
if ( is_empty != 0 )
|
||||
return 0;
|
||||
|
||||
sprintf(pre, "%3ld/0x%02lx", enc_start, enc_start);
|
||||
|
||||
x = left_margin;
|
||||
if ( bf_desc_font != NULL )
|
||||
{
|
||||
if ( bf_desc_font->target_data != NULL )
|
||||
{
|
||||
tga_set_font(bf_desc_font->target_data);
|
||||
x += tga_draw_string(x, y, pre, 0, 0);
|
||||
}
|
||||
}
|
||||
x += 4;
|
||||
|
||||
tga_set_font(bf->target_data);
|
||||
for( i = 0; i< 16; i++ )
|
||||
{
|
||||
tga_draw_glyph(x + (tga_get_char_width()+2)*i,y,enc_start+i, font_picture_extra_info);
|
||||
}
|
||||
|
||||
return left_margin + x + (tga_get_char_width()+2)*16;
|
||||
}
|
||||
|
||||
unsigned tga_draw_font_info(unsigned y, const char *fontname, bf_t *bf_desc_font, bf_t *bf)
|
||||
{
|
||||
unsigned x;
|
||||
int cap_a, cap_a_height;
|
||||
static char s[256];
|
||||
|
||||
cap_a_height = 0;
|
||||
cap_a = bf_GetIndexByEncoding(bf, 'A');
|
||||
if ( cap_a >= 0 )
|
||||
{
|
||||
cap_a_height = bf->glyph_list[cap_a]->bbx.h+bf->glyph_list[cap_a]->bbx.y;
|
||||
}
|
||||
|
||||
if ( bf_desc_font != NULL )
|
||||
{
|
||||
if ( bf_desc_font->target_data != NULL )
|
||||
{
|
||||
|
||||
tga_set_font(bf_desc_font->target_data);
|
||||
|
||||
y += tga_get_char_height()+1;
|
||||
x = left_margin;
|
||||
x += tga_draw_string(x, y, fontname, 0, 0);
|
||||
|
||||
y += tga_get_char_height()+1;
|
||||
sprintf(s, "Max width %u, max height %u", tga_get_char_width(), tga_get_char_height());
|
||||
x = left_margin;
|
||||
x += tga_draw_string(x, y, s, 0, 0);
|
||||
|
||||
y += tga_get_char_height()+1;
|
||||
sprintf(s, "'A' height %d, font size %d ", cap_a_height, bf->target_cnt);
|
||||
x = left_margin;
|
||||
x += tga_draw_string(x, y, s, 0, 0);
|
||||
return (tga_get_char_height()+1)*3;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
unsigned tga_draw_font(unsigned y, const char *fontname, bf_t *bf_desc_font, bf_t *bf)
|
||||
{
|
||||
long i;
|
||||
unsigned x, xmax;
|
||||
xmax = 0;
|
||||
|
||||
y += tga_draw_font_info( y, fontname, bf_desc_font, bf);
|
||||
|
||||
y += tga_get_line_height(bf_desc_font, bf)+1;
|
||||
|
||||
|
||||
for( i = 0; i < 256; i+=16 )
|
||||
{
|
||||
x = tga_draw_font_line(y, i, bf_desc_font, bf);
|
||||
if ( x > 0 )
|
||||
{
|
||||
if ( xmax < x )
|
||||
xmax = x;
|
||||
y += tga_get_line_height(bf_desc_font, bf)+1;
|
||||
}
|
||||
}
|
||||
|
||||
tga_set_font(bf->target_data);
|
||||
|
||||
//tga_draw_string(0, y, "Woven silk pyjamas exchanged for blue quartz", 1, xmax);
|
||||
//y += tga_get_char_height()+1;
|
||||
if ( font_picture_test_string != 0 )
|
||||
{
|
||||
tga_draw_string(left_margin, y, "Woven silk pyjamas exchanged for blue quartz.", 0, xmax);
|
||||
y += tga_get_line_height(bf_desc_font, bf)+1;
|
||||
}
|
||||
return y;
|
||||
}
|
||||
|
||||
|
||||
/*================================================*/
|
||||
/* main */
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
bf_t *bf_desc_font;
|
||||
bf_t *bf;
|
||||
char *bdf_filename = NULL;
|
||||
int is_verbose = 0;
|
||||
char *map_str ="*";
|
||||
char *desc_font_str = "";
|
||||
unsigned y;
|
||||
|
||||
argv++;
|
||||
/*
|
||||
if ( *argv == NULL )
|
||||
{
|
||||
help();
|
||||
exit(1);
|
||||
}
|
||||
*/
|
||||
for(;;)
|
||||
{
|
||||
if ( *argv == NULL )
|
||||
break;
|
||||
if ( is_arg(&argv, 'h') != 0 )
|
||||
{
|
||||
help();
|
||||
exit(1);
|
||||
}
|
||||
else if ( is_arg(&argv, 'v') != 0 )
|
||||
{
|
||||
is_verbose = 1;
|
||||
}
|
||||
else if ( is_arg(&argv, 'a') != 0 )
|
||||
{
|
||||
font_picture_extra_info = 1;
|
||||
}
|
||||
else if ( is_arg(&argv, 't') != 0 )
|
||||
{
|
||||
font_picture_test_string = 1;
|
||||
}
|
||||
else if ( is_arg(&argv, 'r') != 0 )
|
||||
{
|
||||
runtime_test = 1;
|
||||
}
|
||||
else if ( get_num_arg(&argv, 'b', &build_bbx_mode) != 0 )
|
||||
{
|
||||
}
|
||||
else if ( get_num_arg(&argv, 'f', &font_format) != 0 )
|
||||
{
|
||||
}
|
||||
else if ( get_num_arg(&argv, 'l', &left_margin) != 0 )
|
||||
{
|
||||
}
|
||||
else if ( get_str_arg(&argv, 'd', &desc_font_str) != 0 )
|
||||
{
|
||||
}
|
||||
else if ( get_str_arg(&argv, 'o', &c_filename) != 0 )
|
||||
{
|
||||
}
|
||||
else if ( get_str_arg(&argv, 'n', &target_fontname) != 0 )
|
||||
{
|
||||
}
|
||||
else if ( get_str_arg(&argv, 'm', &map_str) != 0 )
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
bdf_filename = *argv;
|
||||
argv++;
|
||||
}
|
||||
}
|
||||
|
||||
if ( bdf_filename == NULL )
|
||||
{
|
||||
help();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
bf_desc_font = NULL;
|
||||
if ( desc_font_str[0] != '\0' )
|
||||
{
|
||||
bf_desc_font = bf_OpenFromFile(desc_font_str, 0, BDF_BBX_MODE_MINIMAL, "*", 0); /* assume format 0 for description */
|
||||
if ( bf_desc_font == NULL )
|
||||
{
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if ( font_format == 2 )
|
||||
{
|
||||
build_bbx_mode = BDF_BBX_MODE_M8;
|
||||
/* issue the following log message later, when there is a valid bf object */
|
||||
/* bf_Log(bf, "Font mode 1: BBX mode set to 3"); */
|
||||
}
|
||||
|
||||
bf = bf_OpenFromFile(bdf_filename, is_verbose, build_bbx_mode, map_str, font_format);
|
||||
|
||||
if ( bf == NULL )
|
||||
{
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if ( font_format == 2 )
|
||||
{
|
||||
/* now generate the log message */
|
||||
bf_Log(bf, "Note: For font format 1 BBX mode has been set to 3");
|
||||
}
|
||||
|
||||
if ( bf_desc_font != NULL )
|
||||
{
|
||||
tga_init(1024, 600);
|
||||
y = tga_draw_font(0, bdf_filename, bf_desc_font, bf);
|
||||
|
||||
if ( runtime_test != 0 )
|
||||
{
|
||||
long i;
|
||||
clock_t c = clock();
|
||||
fd_t fd;
|
||||
fd_init(&fd);
|
||||
fd_set_font(&fd, bf->target_data);
|
||||
for( i = 0; i < 10000; i++ )
|
||||
fd_draw_string(&fd, left_margin, y, "Woven silk pyjamas exchanged for blue quartz.");
|
||||
bf_Log(bf, "Runtime test: %.2lf sec", (double)(clock()-c)/(double)CLOCKS_PER_SEC);
|
||||
}
|
||||
|
||||
tga_save("bdf.tga");
|
||||
}
|
||||
|
||||
|
||||
if ( c_filename != NULL )
|
||||
{
|
||||
/* write the encoded data in bf->target_data */
|
||||
if ( font_format == 0 )
|
||||
{
|
||||
bf_WriteUCGCByFilename(bf, c_filename, target_fontname, " ");
|
||||
}
|
||||
else
|
||||
{
|
||||
/* font format >= 1 are for u8g2 */
|
||||
bf_WriteU8G2CByFilename(bf, c_filename, target_fontname, " ");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bf_Close(bf);
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user