#include #include #include void datedit_find_character(BITMAP *bmp, int *x, int *y, int *w, int *h) { int c1; int c2; if (bitmap_color_depth(bmp) == 8) { c1 = 255; c2 = 255; } else { c1 = makecol_depth(bitmap_color_depth(bmp), 255, 255, 0); c2 = makecol_depth(bitmap_color_depth(bmp), 0, 255, 255); } /* look for top left corner of character */ while ((getpixel(bmp, *x, *y) != c1) || (getpixel(bmp, *x+1, *y) != c2) || (getpixel(bmp, *x, *y+1) != c2) || (getpixel(bmp, *x+1, *y+1) == c1) || (getpixel(bmp, *x+1, *y+1) == c2)) { (*x)++; if (*x >= bmp->w) { *x = 0; (*y)++; if (*y >= bmp->h) { *w = 0; *h = 0; return; } } } /* look for right edge of character */ *w = 0; while ((getpixel(bmp, *x+*w+1, *y) == c2) && (getpixel(bmp, *x+*w+1, *y+1) != c2) && (*x+*w+1 <= bmp->w)) (*w)++; /* look for bottom edge of character */ *h = 0; while ((getpixel(bmp, *x, *y+*h+1) == c2) && (getpixel(bmp, *x+1, *y+*h+1) != c2) && (*y+*h+1 <= bmp->h)) (*h)++; } /* creates a new font object */ static void* makenew_font(long* size) { FONT *f; FONT_MONO_DATA* mf = 0, * mfread = font->data; f = _al_malloc(sizeof(FONT)); f->height = font->height; f->vtable = font->vtable; while(mfread) { int i; if(mf) { mf->next = _al_malloc(sizeof(FONT_MONO_DATA)); mf = mf->next; } else f->data = mf = _al_malloc(sizeof(FONT_MONO_DATA)); mf->begin = mfread->begin; mf->end = mfread->end; mf->next = 0; mf->glyphs = _al_malloc(sizeof(FONT_GLYPH*) * (mf->end - mf->begin)); for(i = mf->begin; i < mf->end; i++) { FONT_GLYPH *gsrc = mfread->glyphs[i - mf->begin], *gdest; int sz = ((gsrc->w + 7) / 8) * gsrc->h; gdest = _al_malloc(sizeof(FONT_GLYPH) + sz); gdest->w = gsrc->w; gdest->h = gsrc->h; memcpy(gdest->dat, gsrc->dat, sz); mf->glyphs[i - mf->begin] = gdest; } mfread = mfread->next; } return f; } /* state information for the bitmap font importer */ static BITMAP *import_bmp = NULL; static int import_x = 0; static int import_y = 0; /* import_bitmap_font_mono: * Helper for import_bitmap_font, below. */ static int import_bitmap_font_mono(FONT_GLYPH** gl, int num) { int w = 1, h = 1, i; for(i = 0; i < num; i++) { if(w > 0 && h > 0) datedit_find_character(import_bmp, &import_x, &import_y, &w, &h); if(w <= 0 || h <= 0) { int j; gl[i] = _al_malloc(sizeof(FONT_GLYPH) + 8); gl[i]->w = 8; gl[i]->h = 8; for(j = 0; j < 8; j++) gl[i]->dat[j] = 0; } else { int sx = ((w + 7) / 8), j, k; gl[i] = _al_malloc(sizeof(FONT_GLYPH) + sx * h); gl[i]->w = w; gl[i]->h = h; for(j = 0; j < sx * h; j++) gl[i]->dat[j] = 0; for(j = 0; j < h; j++) { for(k = 0; k < w; k++) { if(getpixel(import_bmp, import_x + k + 1, import_y + j + 1)) gl[i]->dat[(j * sx) + (k / 8)] |= 0x80 >> (k & 7); } } import_x += w; } } return 0; } /* import_bitmap_font_color: * Helper for import_bitmap_font, below. */ static int import_bitmap_font_color(BITMAP** bits, int num) { int w = 1, h = 1, i; for(i = 0; i < num; i++) { if(w > 0 && h > 0) datedit_find_character(import_bmp, &import_x, &import_y, &w, &h); if(w <= 0 || h <= 0) { bits[i] = create_bitmap_ex(8, 8, 8); if(!bits[i]) return -1; clear_to_color(bits[i], 255); } else { bits[i] = create_bitmap_ex(8, w, h); if(!bits[i]) return -1; blit(import_bmp, bits[i], import_x + 1, import_y + 1, 0, 0, w, h); import_x += w; } } return 0; } /* bitmap_font_ismono: * Helper for import_bitmap_font, below. */ static int bitmap_font_ismono(BITMAP *bmp) { int x, y, col = -1, pixel; for(y = 0; y < bmp->h; y++) { for(x = 0; x < bmp->w; x++) { pixel = getpixel(bmp, x, y); if(pixel == 0 || pixel == 255) continue; if(col > 0 && pixel != col) return 0; col = pixel; } } return 1; } /* upgrade_to_color, upgrade_to_color_data: * Helper functions. Upgrades a monochrome font to a color font. */ static FONT_COLOR_DATA* upgrade_to_color_data(FONT_MONO_DATA* mf) { FONT_COLOR_DATA* cf = _al_malloc(sizeof(FONT_COLOR_DATA)); BITMAP** bits = _al_malloc(sizeof(BITMAP*) * (mf->end - mf->begin)); int i; cf->begin = mf->begin; cf->end = mf->end; cf->bitmaps = bits; cf->next = 0; text_mode(-1); for(i = mf->begin; i < mf->end; i++) { FONT_GLYPH* g = mf->glyphs[i - mf->begin]; BITMAP* b = create_bitmap_ex(8, g->w, g->h); clear_to_color(b, 0); b->vtable->draw_glyph(b, g, 0, 0, 1); bits[i - mf->begin] = b; free(g); } free(mf->glyphs); free(mf); return cf; } static void upgrade_to_color(FONT* f) { FONT_MONO_DATA* mf = f->data; FONT_COLOR_DATA * cf, *cf_write = 0; if(f->vtable == font_vtable_color) return; f->vtable = font_vtable_color; while(mf) { FONT_MONO_DATA* mf_next = mf->next; cf = upgrade_to_color_data(mf); if(!cf_write) f->data = cf; else cf_write->next = cf; cf_write = cf; mf = mf_next; } } /* bitmap_font_count: * Helper for `import_bitmap_font', below. */ static int bitmap_font_count(BITMAP* bmp) { int x = 0, y = 0, w = 0, h = 0; int num = 0; while(1) { datedit_find_character(bmp, &x, &y, &w, &h); if (w <= 0 || h <= 0) break; num++; x += w; } return num; } /* import routine for the Allegro .pcx font format */ static FONT* import_bitmap_font(AL_CONST char* fname, int begin, int end, int cleanup) { /* NB: `end' is -1 if we want every glyph */ FONT *f; if(fname) { PALETTE junk; if(import_bmp) destroy_bitmap(import_bmp); import_bmp = load_bitmap(fname, junk); import_x = 0; import_y = 0; } if(!import_bmp) return 0; if(bitmap_color_depth(import_bmp) != 8) { destroy_bitmap(import_bmp); import_bmp = 0; return 0; } f = _al_malloc(sizeof(FONT)); if(end == -1) end = bitmap_font_count(import_bmp) + begin; if (bitmap_font_ismono(import_bmp)) { FONT_MONO_DATA* mf = _al_malloc(sizeof(FONT_MONO_DATA)); mf->glyphs = _al_malloc(sizeof(FONT_GLYPH*) * (end - begin)); if( import_bitmap_font_mono(mf->glyphs, end - begin) ) { free(mf->glyphs); free(mf); free(f); f = 0; } else { f->data = mf; f->vtable = font_vtable_mono; f->height = mf->glyphs[0]->h; mf->begin = begin; mf->end = end; mf->next = 0; } } else { FONT_COLOR_DATA* cf = _al_malloc(sizeof(FONT_COLOR_DATA)); cf->bitmaps = _al_malloc(sizeof(BITMAP*) * (end - begin)); if( import_bitmap_font_color(cf->bitmaps, end - begin) ) { free(cf->bitmaps); free(cf); free(f); f = 0; } else { f->data = cf; f->vtable = font_vtable_color; f->height = cf->bitmaps[0]->h; cf->begin = begin; cf->end = end; cf->next = 0; } } if(cleanup) { destroy_bitmap(import_bmp); import_bmp = 0; } return f; } /* helper for save_font, below */ static void save_mono_font(FONT* f, PACKFILE* pack) { FONT_MONO_DATA* mf = f->data; int i = 0; /* count number of ranges */ while(mf) { i++; mf = mf->next; } pack_mputw(i, pack); mf = f->data; while(mf) { /* mono, begin, end-1 */ pack_putc(1, pack); pack_mputl(mf->begin, pack); pack_mputl(mf->end - 1, pack); for(i = mf->begin; i < mf->end; i++) { FONT_GLYPH* g = mf->glyphs[i - mf->begin]; pack_mputw(g->w, pack); pack_mputw(g->h, pack); pack_fwrite(g->dat, ((g->w + 7) / 8) * g->h, pack); } mf = mf->next; } } /* helper for save_font, below */ static void save_color_font(FONT* f, PACKFILE* pack) { FONT_COLOR_DATA* cf = f->data; int i = 0; /* count number of ranges */ while(cf) { i++; cf = cf->next; } pack_mputw(i, pack); cf = f->data; while(cf) { /* mono, begin, end-1 */ pack_putc(0, pack); pack_mputl(cf->begin, pack); pack_mputl(cf->end - 1, pack); for(i = cf->begin; i < cf->end; i++) { BITMAP* g = cf->bitmaps[i - cf->begin]; int y; pack_mputw(g->w, pack); pack_mputw(g->h, pack); for(y = 0; y < g->h; y++) { pack_fwrite(g->line[y], g->w, pack); } } cf = cf->next; } } /* saves a font into a datafile */ static void save_font(DATAFILE* dat, int packed, int packkids, int strip, int verbose, int extra, PACKFILE* pack) { FONT* f = dat->dat; pack_mputw(0, pack); if(f->vtable == font_vtable_mono) save_mono_font(f, pack); else save_color_font(f, pack); } /* read_block: * Reads a block of size bytes from a file, allocating memory to store it. */ static void *read_block(PACKFILE *f, int size, int alloc_size) { void *p; p = malloc(MAX(size, alloc_size)); if (!p) { *allegro_errno = ENOMEM; return NULL; } pack_fread(p, size, f); if (pack_ferror(f)) { free(p); return NULL; } return p; } /* read_bitmap: * Reads a bitmap from a file, allocating memory to store it. */ static BITMAP *read_bitmap(PACKFILE *f, int bits, int allowconv) { int x, y, w, h, c, r, g, b, a; int destbits, dither8, prev_drawmode, rgba; unsigned short *p16; unsigned long *p32; BITMAP *bmp; if (bits < 0) { bits = -bits; rgba = TRUE; } else rgba = FALSE; if (allowconv) destbits = _color_load_depth(bits, rgba); else destbits = 8; if ((destbits == 8) && (bits > 8) && (_color_conv & COLORCONV_DITHER_PAL)) { destbits = bits; dither8 = TRUE; } else dither8 = FALSE; w = pack_mgetw(f); h = pack_mgetw(f); bmp = create_bitmap_ex(destbits, w, h); if (!bmp) { *allegro_errno = ENOMEM; return NULL; } prev_drawmode = _drawing_mode; _drawing_mode = DRAW_MODE_SOLID; switch (bits) { case 8: /* 256 color bitmap */ if (destbits == 8) { pack_fread(bmp->dat, w*h, f); } else { /* expand 256 colors into truecolor */ for (y=0; y> 11) & 0x1F]; g = _rgb_scale_6[(c >> 5) & 0x3F]; b = _rgb_scale_5[c & 0x1F]; bmp->line[y][x] = makecol8(r, g, b); } } break; #endif #ifdef ALLEGRO_COLOR16 case 15: /* load hicolor to a 15 bit hicolor bitmap */ for (y=0; yline[y]; for (x=0; x> 11) & 0x1F]; g = _rgb_scale_6[(c >> 5) & 0x3F]; b = _rgb_scale_5[c & 0x1F]; p16[x] = makecol15(r, g, b); } } break; case 16: /* load hicolor to a 16 bit hicolor bitmap */ for (y=0; yline[y]; for (x=0; x> 11) & 0x1F]; g = _rgb_scale_6[(c >> 5) & 0x3F]; b = _rgb_scale_5[c & 0x1F]; p16[x] = makecol16(r, g, b); } } break; #endif #ifdef ALLEGRO_COLOR24 case 24: /* load hicolor to a 24 bit truecolor bitmap */ for (y=0; y> 11) & 0x1F]; g = _rgb_scale_6[(c >> 5) & 0x3F]; b = _rgb_scale_5[c & 0x1F]; bmp->line[y][x*3+_rgb_r_shift_24/8] = r; bmp->line[y][x*3+_rgb_g_shift_24/8] = g; bmp->line[y][x*3+_rgb_b_shift_24/8] = b; } } break; #endif #ifdef ALLEGRO_COLOR32 case 32: /* load hicolor to a 32 bit truecolor bitmap */ for (y=0; yline[y]; for (x=0; x> 11) & 0x1F]; g = _rgb_scale_6[(c >> 5) & 0x3F]; b = _rgb_scale_5[c & 0x1F]; p32[x] = makecol32(r, g, b); } } break; #endif } break; case 24: case 32: /* truecolor */ switch (destbits) { #ifdef ALLEGRO_COLOR8 case 8: /* reduce truecolor to 256 colors */ for (y=0; yline[y][x] = makecol8(r, g, b); } } break; #endif #ifdef ALLEGRO_COLOR16 case 15: /* load truecolor to a 15 bit hicolor bitmap */ for (y=0; yline[y]; if (_color_conv & COLORCONV_DITHER_HI) { for (x=0; xline[y]; if (_color_conv & COLORCONV_DITHER_HI) { for (x=0; xline[y][x*3+_rgb_r_shift_24/8] = r; bmp->line[y][x*3+_rgb_g_shift_24/8] = g; bmp->line[y][x*3+_rgb_b_shift_24/8] = b; } } break; #endif #ifdef ALLEGRO_COLOR32 case 32: /* load truecolor to a 32 bit truecolor bitmap */ for (y=0; yline[y]; for (x=0; xw, bmp->h); if (!tmp) { destroy_bitmap(bmp); *allegro_errno = ENOMEM; return NULL; } blit(bmp, tmp, 0, 0, 0, 0, bmp->w, bmp->h); destroy_bitmap(bmp); bmp = tmp; } return bmp; } /* read_font_mono: * Helper for read_font, below */ static FONT_MONO_DATA *read_font_mono(PACKFILE *f, int *hmax) { FONT_MONO_DATA *mf = NULL; int max = 0, i = 0; FONT_GLYPH **gl = NULL; mf = malloc(sizeof(FONT_MONO_DATA)); if (!mf) { *allegro_errno = ENOMEM; return NULL; } mf->begin = pack_mgetl(f); mf->end = pack_mgetl(f) + 1; mf->next = NULL; max = mf->end - mf->begin; mf->glyphs = gl = malloc(sizeof(FONT_GLYPH *) * max); if (!gl) { free(mf); *allegro_errno = ENOMEM; return NULL; } for (i = 0; i < max; i++) { int w, h, sz; w = pack_mgetw(f); h = pack_mgetw(f); sz = ((w + 7) / 8) * h; if (h > *hmax) *hmax = h; gl[i] = malloc(sizeof(FONT_GLYPH) + sz); if (!gl[i]) { while (i) { i--; free(mf->glyphs[i]); } free(mf); free(mf->glyphs); *allegro_errno = ENOMEM; return NULL; } gl[i]->w = w; gl[i]->h = h; pack_fread(gl[i]->dat, sz, f); } return mf; } /* read_font_color: * Helper for read_font, below. */ static FONT_COLOR_DATA *read_font_color(PACKFILE *pack, int *hmax) { FONT_COLOR_DATA *cf = NULL; int max = 0, i = 0; BITMAP **bits = NULL; cf = malloc(sizeof(FONT_COLOR_DATA)); if (!cf) { *allegro_errno = ENOMEM; return NULL; } cf->begin = pack_mgetl(pack); cf->end = pack_mgetl(pack) + 1; cf->next = NULL; max = cf->end - cf->begin; cf->bitmaps = bits = malloc(sizeof(BITMAP *) * max); if (!bits) { free(cf); *allegro_errno = ENOMEM; return NULL; } for (i = 0; i < max; i++) { bits[i] = read_bitmap(pack, 8, FALSE); if (!bits[i]) { while (i) { i--; destroy_bitmap(bits[i]); } free(bits); free(cf); *allegro_errno = ENOMEM; return 0; } if (bits[i]->h > *hmax) *hmax = bits[i]->h; } return cf; } /* read_font: * Reads a new style, Unicode format font from a file. */ static FONT *read_font(PACKFILE *pack) { FONT *f = NULL; int num_ranges = 0; int height = 0; f = malloc(sizeof(FONT)); if (!f) { *allegro_errno = ENOMEM; return NULL; } f->data = NULL; num_ranges = pack_mgetw(pack); while (num_ranges--) { if (pack_getc(pack)) { FONT_MONO_DATA *mf = 0, *iter = (FONT_MONO_DATA *)f->data; f->vtable = font_vtable_mono; mf = read_font_mono(pack, &height); if (!mf) { destroy_font(f); return NULL; } if (!iter) f->data = mf; else { while (iter->next) iter = iter->next; iter->next = mf; } } else { FONT_COLOR_DATA *cf = NULL, *iter = (FONT_COLOR_DATA *)f->data; f->vtable = font_vtable_color; cf = read_font_color(pack, &height); if (!cf) { destroy_font(f); return NULL; } if (!iter) f->data = cf; else { while (iter->next) iter = iter->next; iter->next = cf; } } } f->height = height; return f; } int main(void){ FONT *f; PACKFILE *pack; allegro_init(); install_keyboard(); f=import_bitmap_font("0.pcx",0x20,0x7f,1); //pack=pack_fopen("0.fnt","r"); //f=read_font(pack); //pack_fclose(pack); set_color_depth(16); set_gfx_mode(GFX_AUTODETECT,800,600,0,0); textprintf(screen,f,0,0,0xffff,"Ahoj, ako sa ti dari? 0123456789",f); pack=pack_fopen("0.fnt","w"); save_mono_font(f,pack); pack_fclose(pack); destroy_font(f); readkey(); return(0); }