Example #1
0
static void do_glyphs(deark *c, lctx *d)
{
	struct de_bitmap_font *font = NULL;
	de_byte *font_data = NULL;
	de_int64 i;
	de_int64 glyph_rowspan;

	font = de_create_bitmap_font(c);
	font->has_nonunicode_codepoints = 1;
	font->nominal_width = (int)d->glyph_width;
	font->nominal_height = (int)d->glyph_height;
	font->num_chars = d->num_glyphs; // This may increase later
	glyph_rowspan = (d->glyph_width+7)/8;

	d->num_chars_alloc = d->num_glyphs;
	if(d->read_extra_codepoints)
		d->num_chars_alloc += MAX_EXTRA_CODEPOINTS;

	d->index_of_first_extra_codepoint = d->num_glyphs;
	d->num_extra_codepoints = 0;

	font->char_array = de_malloc(c, d->num_chars_alloc * sizeof(struct de_bitmap_font_char));

	font_data = de_malloc(c, d->font_data_size);
	de_read(font_data, d->headersize, d->font_data_size);

	for(i=0; i<d->num_chars_alloc; i++) {
		font->char_array[i].width = font->nominal_width;
		font->char_array[i].height = font->nominal_height;
		font->char_array[i].rowspan = glyph_rowspan;
		if(i<d->num_glyphs)
			font->char_array[i].codepoint_nonunicode = (de_int32)i;
		else
			font->char_array[i].codepoint_nonunicode = DE_INVALID_CODEPOINT;
		font->char_array[i].codepoint_unicode = DE_INVALID_CODEPOINT;
		if(i<d->num_glyphs)
			font->char_array[i].bitmap = &font_data[i*d->bytes_per_glyph];
	}

	if(d->has_unicode_table) {
		if(d->version==2)
			do_psf2_unicode_table(c, d, font);
		else
			do_psf1_unicode_table(c, d, font);
	}

	if(d->num_extra_codepoints>0) {
		font->num_chars = d->index_of_first_extra_codepoint + d->num_extra_codepoints;
		de_dbg(c, "codepoints aliases: %d\n", (int)d->num_extra_codepoints);
		de_dbg(c, "total characters: %d\n", (int)font->num_chars);
	}

	de_font_bitmap_font_to_image(c, font, NULL, 0);

	if(font) {
		de_free(c, font->char_array);
		de_destroy_bitmap_font(c, font);
	}
	de_free(c, font_data);
}
Example #2
0
static void de_run_unifont_hex(deark *c, de_module_params *mparams)
{
	struct de_bitmap_font *font = NULL;
	i64 char_array_numalloc = 0;
	char linebuf[256];
	struct de_linereader *lr = NULL;
	int ok = 0;

	font = de_create_bitmap_font(c);
	font->has_unicode_codepoints = 1;
	font->prefer_unicode = 1;
	font->nominal_height = 16;
	char_array_numalloc = 1024;
	font->char_array = de_mallocarray(c, char_array_numalloc, sizeof(struct de_bitmap_font_char));

	lr = de_linereader_create(c, c->infile);

	while(de_linereader_readnextline(c, lr, linebuf, sizeof(linebuf), 0)) {
		i64 idx;
		struct de_bitmap_font_char *ch;
		i64 fdata_len;
		char *dptr; // Pointer into linebuf, to the char after the ":"

		if(font->num_chars>=17*65536) goto done;

		idx = font->num_chars;
		if(idx >= char_array_numalloc) {
			i64 new_numalloc = char_array_numalloc*2;
			font->char_array = de_reallocarray(c, font->char_array,
				char_array_numalloc, sizeof(struct de_bitmap_font_char),
				new_numalloc);
			char_array_numalloc = new_numalloc;
		}
		ch = &font->char_array[idx];

		dptr = de_strchr(linebuf, ':');
		if(!dptr) goto done;
		*dptr = '\0';
		dptr++;

		fdata_len = (i64)de_strlen(dptr);
		ch->codepoint_unicode = (i32)de_strtoll(linebuf, NULL, 16);
		if(ch->codepoint_unicode<0 || ch->codepoint_unicode>=17*65536) goto done;

		ch->width = (int)((fdata_len/32)*8);
		ch->height = 16;
		de_dbg2(c, "char[%d] U+%04X %d"DE_CHAR_TIMES"%d",
			(int)font->num_chars, (unsigned int)ch->codepoint_unicode,
			ch->width, ch->height);
		if(ch->width<8 || ch->width>32) goto done;
		ch->rowspan = (ch->width+7)/8;
		ch->bitmap = de_malloc(c, ch->rowspan * ch->height);
		decode_fontdata(c, dptr, ch);

		font->num_chars++;
		if(ch->width > font->nominal_width) {
			font->nominal_width = ch->width;
		}
	}

	de_dbg(c, "number of characters: %d", (int)font->num_chars);
	if(font->num_chars<1) goto done;
	if(font->nominal_width<1) goto done;

	de_font_bitmap_font_to_image(c, font, NULL, 0);
	ok = 1;

done:
	if(!ok) {
		de_err(c, "Error parsing HEX font file (offset %"I64_FMT")", lr->f_pos);
	}
	de_linereader_destroy(c, lr);
	if(font) {
		if(font->char_array) {
			i64 k;
			for(k=0; k<font->num_chars; k++) {
				de_free(c, font->char_array[k].bitmap);
			}
			de_free(c, font->char_array);
		}
		font->char_array = NULL;
		de_destroy_bitmap_font(c, font);
	}
}
Example #3
0
void de_font_bitmap_font_to_image(deark *c, struct de_bitmap_font *font1, de_finfo *fi,
	unsigned int createflags)
{
	struct font_render_ctx *fctx = NULL;
	i64 i, j, k;
	de_bitmap *img = NULL;
	i64 xpos, ypos;
	i64 img_leftmargin, img_topmargin;
	i64 img_rightmargin, img_bottommargin;
	i64 img_vpixelsperchar;
	i64 img_width, img_height;
	i64 num_table_rows_to_display;
	i64 num_table_rows_total;
	i64 last_valid_row;
	struct de_bitmap_font *dfont = NULL;
	i64 chars_per_row = 32;
	const char *s;
	struct row_info_struct *row_info = NULL;
	struct col_info_struct *col_info = NULL;
	int unicode_req = 0;
	i64 label_stride;
	i64 rownum, colnum;
	i64 curpos;
	unsigned int dnflags;

	fctx = de_malloc(c, sizeof(struct font_render_ctx));
	fctx->font = font1;

	if(fctx->font->num_chars<1) goto done;
	if(fctx->font->num_chars>17*65536) goto done;
	if(fctx->font->nominal_width>512 || fctx->font->nominal_height>512) {
		de_err(c, "Font size too big (%d"DE_CHAR_TIMES"%d). Not supported.",
			(int)fctx->font->nominal_width, (int)fctx->font->nominal_height);
		goto done;
	}

	// -1 = "no preference"
	unicode_req = de_get_ext_option_bool(c, "font:tounicode", -1);

	if(unicode_req==0 &&
		(fctx->font->has_nonunicode_codepoints || !fctx->font->has_unicode_codepoints))
	{
		; // Render as nonunicode.
	}
	else if(fctx->font->has_unicode_codepoints &&
		(unicode_req>0 || fctx->font->prefer_unicode || !fctx->font->has_nonunicode_codepoints))
	{
		fctx->render_as_unicode = 1;
	}

	s = de_get_ext_option(c, "font:charsperrow");
	if(s) {
		chars_per_row = de_atoi64(s);
		if(chars_per_row<1) chars_per_row=1;
	}

	dfont = make_digit_font(c);

	fctx->codepoint_tmp = de_mallocarray(c, fctx->font->num_chars, sizeof(i32));
	fixup_codepoints(c, fctx);

	get_min_max_codepoint(fctx);
	if(fctx->num_valid_chars<1) goto done;
	num_table_rows_total = fctx->max_codepoint/chars_per_row+1;

	// TODO: Clean up these margin calculations, and make it more general.
	if(fctx->render_as_unicode) {
		img_leftmargin = dfont->nominal_width * 5 + 6;
	}
	else {
		if(fctx->max_codepoint >= 1000)
			img_leftmargin = dfont->nominal_width * 5 + 6;
		else
			img_leftmargin = dfont->nominal_width * 3 + 6;
	}
	img_topmargin = dfont->nominal_height + 6;
	img_rightmargin = 1;
	img_bottommargin = 1;

	// Scan the characters, and record relevant information.
	row_info = de_mallocarray(c, num_table_rows_total, sizeof(struct row_info_struct));
	col_info = de_mallocarray(c, chars_per_row, sizeof(struct col_info_struct));
	for(i=0; i<chars_per_row; i++) {
#define MIN_CHAR_CELL_WIDTH 5
		col_info[i].display_width = MIN_CHAR_CELL_WIDTH;
	}

	for(k=0; k<fctx->font->num_chars; k++) {
		i64 char_display_width;

		if(fctx->codepoint_tmp[k] == DE_CODEPOINT_INVALID) continue;
		if(!is_valid_char(&fctx->font->char_array[k])) continue;
		rownum = fctx->codepoint_tmp[k] / chars_per_row;
		colnum = fctx->codepoint_tmp[k] % chars_per_row;
		if(rownum<0 || rownum>=num_table_rows_total) {
			de_err(c, "internal: bad rownum");
			de_fatalerror(c);
		}

		// Remember that there is at least one valid character in this character's row.
		row_info[rownum].is_visible = 1;

		// Track the maximum width of any character in this character's column.
		char_display_width = (i64)(fctx->font->char_array[k].width +
				(int)fctx->font->char_array[k].extraspace_l +
				(int)fctx->font->char_array[k].extraspace_r);
		if(char_display_width > col_info[colnum].display_width) {
			col_info[colnum].display_width = char_display_width;
		}
	}

	img_vpixelsperchar = fctx->font->nominal_height + 1;

	// Figure out how many rows are used, and where to draw them.
	num_table_rows_to_display = 0;
	last_valid_row = -1;
	curpos = img_topmargin;
	for(j=0; j<num_table_rows_total; j++) {
		if(!row_info[j].is_visible) continue;

		// If we skipped one or more rows, leave some extra vertical space.
		if(num_table_rows_to_display>0 && !row_info[j-1].is_visible) curpos+=3;

		last_valid_row = j;
		row_info[j].display_pos = curpos;
		curpos += img_vpixelsperchar;
		num_table_rows_to_display++;
	}
	if(num_table_rows_to_display<1) goto done;

	// Figure out the positions of the columns.
	curpos = img_leftmargin;
	for(i=0; i<chars_per_row; i++) {
		col_info[i].display_pos = curpos;
		curpos += col_info[i].display_width + 1;
	}

	img_width = col_info[chars_per_row-1].display_pos +
		col_info[chars_per_row-1].display_width + img_rightmargin;
	img_height = row_info[last_valid_row].display_pos +
		img_vpixelsperchar -1 + img_bottommargin;

	img = de_bitmap_create(c, img_width, img_height, 1);

	// Clear the image
	for(j=0; j<img->height; j++) {
		for(i=0; i<img->width; i++) {
			de_bitmap_setpixel_gray(img, i, j, 128);
		}
	}

	// Draw/clear the cell backgrounds
	for(j=0; j<num_table_rows_total; j++) {
		if(!row_info[j].is_visible) continue;
		ypos = row_info[j].display_pos;

		for(i=0; i<chars_per_row; i++) {
			i64 ii, jj;

			xpos = col_info[i].display_pos;
			for(jj=0; jj<img_vpixelsperchar-1; jj++) {
				for(ii=0; ii<col_info[i].display_width; ii++) {
					de_bitmap_setpixel_gray(img, xpos+ii, ypos+jj, (ii/2+jj/2)%2 ? 176 : 192);
				}
			}
		}
	}

	// Draw the labels in the top margin.

	// TODO: Better label spacing logic.
	if(fctx->font->nominal_width <= 12)
		label_stride = 2;
	else
		label_stride = 1;

	for(i=0; i<chars_per_row; i++) {
		if(i%label_stride != 0) continue;
		xpos = col_info[i].display_pos + col_info[i].display_width/2;
		ypos = img_topmargin - 3;

		dnflags = DNFLAG_HCENTER;
		if(fctx->render_as_unicode) dnflags |= DNFLAG_HEX;

		draw_number(c, img, dfont, i, xpos, ypos, dnflags);
	}

	// Draw the labels in the left margin.
	for(j=0; j<num_table_rows_total; j++) {
		if(!row_info[j].is_visible) continue;
		xpos = img_leftmargin - 3;
		ypos = row_info[j].display_pos + (img_vpixelsperchar + dfont->nominal_height + 1)/2;

		dnflags = 0;
		if(fctx->render_as_unicode) dnflags |= DNFLAG_HEX | DNFLAG_LEADING_ZEROES;

		draw_number(c, img, dfont, j*chars_per_row, xpos, ypos, dnflags);
	}

	// Render the glyphs.
	for(k=0; k<fctx->font->num_chars; k++) {
		if(fctx->codepoint_tmp[k] == DE_CODEPOINT_INVALID) continue;
		if(!is_valid_char(&fctx->font->char_array[k])) continue;

		rownum = fctx->codepoint_tmp[k] / chars_per_row;
		colnum = fctx->codepoint_tmp[k] % chars_per_row;
		if(rownum<0 || rownum>=num_table_rows_total) {
			de_err(c, "internal: bad rownum");
			de_fatalerror(c);
		}

		xpos = col_info[colnum].display_pos;
		ypos = row_info[rownum].display_pos;

		de_font_paint_character_idx(c, img, fctx->font, k, xpos, ypos,
			DE_STOCKCOLOR_BLACK, DE_STOCKCOLOR_WHITE, 0);
	}

	de_bitmap_write_to_file_finfo(img, fi, createflags);

done:
	if(dfont) {
		de_free(c, dfont->char_array);
		de_destroy_bitmap_font(c, dfont);
	}
	de_bitmap_destroy(img);
	de_free(c, row_info);
	de_free(c, col_info);
	if(fctx) {
		de_free(c, fctx->codepoint_tmp);
		de_free(c, fctx);
	}
}
Example #4
0
// create bitmap_font object
static void do_make_image(deark *c, lctx *d)
{
	struct de_bitmap_font *font = NULL;
	de_int64 i;
	de_int64 pos;

	font = de_create_bitmap_font(c);

	font->has_nonunicode_codepoints = 1;
	if(d->encoding!=DE_ENCODING_UNKNOWN)
		font->has_unicode_codepoints = 1;
	font->prefer_unicode = 0;

	font->nominal_width = (int)d->nominal_char_width;
	font->nominal_height = (int)d->char_height;
	font->num_chars = d->num_chars_stored;
	font->char_array = de_malloc(c, font->num_chars * sizeof(struct de_bitmap_font_char));

	for(i=0; i<d->num_chars_stored; i++) {
		de_int64 char_width;
		de_int64 char_offset;
		de_int32 char_index;
		de_int64 num_tiles;
		de_int64 tile;
		de_int64 row;

		pos = d->hdrsize + d->char_entry_size*i;
		char_width = de_getui16le(pos);
		if(d->char_entry_size==6)
			char_offset = de_getui32le(pos+2);
		else
			char_offset = de_getui16le(pos+2);
		de_dbg2(c, "char[%d] width=%d offset=%d\n", (int)(d->first_char + i), (int)char_width, (int)char_offset);

		num_tiles = (char_width+7)/8;

		if(i == d->num_chars_stored-1) {
			// Arbitrarily put the "absolute space" char at codepoint 256,
			// and U+2002 EN SPACE (best I can do).
			font->char_array[i].codepoint_nonunicode = 256;
			font->char_array[i].codepoint_unicode = 0x2002;
		}
		else {
			char_index = (de_int32)d->first_char + (de_int32)i;

			font->char_array[i].codepoint_nonunicode = char_index;

			if(font->has_unicode_codepoints) {
				if(char_index<32 && d->dfCharSet==0) {
					// This kind of font usually doesn't have glyphs below 32.
					// If it does, assume that they are VT100 line drawing characters.
					font->char_array[i].codepoint_unicode =
						de_char_to_unicode(c, 95+char_index, DE_ENCODING_DEC_SPECIAL_GRAPHICS);
				}
				else {
					font->char_array[i].codepoint_unicode =
						de_char_to_unicode(c, char_index, d->encoding);
				}
			}
		}

		font->char_array[i].width = (int)char_width;
		font->char_array[i].height = (int)d->char_height;
		font->char_array[i].rowspan = num_tiles;
		font->char_array[i].bitmap = de_malloc(c, d->char_height * num_tiles);

		for(row=0; row<d->char_height; row++) {
			for(tile=0; tile<num_tiles; tile++) {
				font->char_array[i].bitmap[row * font->char_array[i].rowspan + tile] =
					de_getbyte(char_offset + tile*d->char_height + row);
			}
		}
	}

	de_font_bitmap_font_to_image(c, font, d->fi, 0);

	if(font) {
		if(font->char_array) {
			for(i=0; i<font->num_chars; i++) {
				de_free(c, font->char_array[i].bitmap);
			}
			de_free(c, font->char_array);
		}
		de_destroy_bitmap_font(c, font);
	}
}