You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
439 lines
9.2 KiB
439 lines
9.2 KiB
|
|
|
|
#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; |
|
bg->is_excluded_from_kerning = 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) |
|
{ |
|
static long last_encoding = 0xffffffff; |
|
static long biggest_x = -1; |
|
|
|
if ( x >= bg->bitmap_width || y >= bg->bitmap_height ) |
|
{ |
|
if ( last_encoding != bg->encoding ) |
|
{ |
|
biggest_x = x; |
|
printf("Glyph size problem: "); |
|
printf("encoding=%ld/0x%lx, ", bg->encoding, bg->encoding); |
|
printf("width=%d, height=%d, ", bg->bitmap_width, bg->bitmap_height); |
|
printf("requested position x=%d, y=%d (use BBX %d ...?)\n", x, y, x+1); |
|
last_encoding = bg->encoding; |
|
} |
|
else if ( biggest_x < x ) |
|
{ |
|
biggest_x = x; |
|
printf("Glyph size problem: "); |
|
printf("encoding=%ld/0x%lx, ", bg->encoding, bg->encoding); |
|
printf("width=%d, height=%d, ", bg->bitmap_width, bg->bitmap_height); |
|
printf("requested position x=%d, y=%d (use BBX %d ...?)\n", x, y, x+1); |
|
} |
|
} |
|
|
|
assert( x < ((bg->bitmap_width+7)/8)*8 ); |
|
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) |
|
{ |
|
//long w; |
|
/* 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 */ |
|
|
|
//w = bg->bbx.w; |
|
|
|
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--; |
|
} |
|
|
|
/* |
|
problem: pixel width calculation failes, because a blank at |
|
the end is not calculated correctly. |
|
analysis: |
|
- bbx.w is reduced to 0 |
|
- original bbx.w is sometimes identical to dwidth_x (6x10.bdf) |
|
or is 1 (helvR10.bdf) |
|
-the bdf file for helvR10.bdf does not contain any other information then |
|
delta x, so this should be used as bbx.w |
|
solution: |
|
Nothing done on the converter side, but handle this as a special case in the |
|
pixel width calculation |
|
|
|
*/ |
|
//if ( bg->bbx.w == 0 && bg->bbx.h == 0 ) |
|
//{ |
|
//printf("enc=%ld, new bbx,w=%ld, original width=%ld, dx=%ld\n", bg->encoding, bg->bbx.w, w, bg->dwidth_x); |
|
//printf("enc=%ld, new bbx.w=%ld, original width=%ld, dx=%ld\n", bg->encoding, bg->bbx.w, w, bg->dwidth_x); |
|
//} |
|
|
|
} |
|
|
|
/* |
|
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; |
|
} |