main.c revision 825c30bc
1/*	$NetBSD: main.c,v 1.5 2025/03/25 03:15:32 macallan Exp $	*/
2
3/*
4 * Copyright (c) 2011 Michael Lorenz
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28#include <stdio.h>
29#include <ctype.h>
30#include <fcntl.h>
31#include <unistd.h>
32#include <sys/stat.h>
33#include <dev/wscons/wsconsio.h>
34
35#include <ft2build.h>
36#include FT_FREETYPE_H
37
38char cvr[] = " .-+oaOX";
39FT_Library library;
40FT_Face face;
41int baseline, above = 0, below = 0, advance = 0;
42
43int push_size(int);
44
45int
46push_size(int letter)
47{
48	int glyph_index, error;
49	int new_above, new_below, new_advance;
50
51	glyph_index = FT_Get_Char_Index(face, letter);
52	printf("idx: %d\n", glyph_index);
53	error = FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT);
54	if (error) {
55		printf("wtf?!\n");
56		return -1;
57	}
58	FT_Render_Glyph(face->glyph, FT_RENDER_MODE_NORMAL);
59	printf("%d x %d\n", face->glyph->bitmap.width, face->glyph->bitmap.rows);
60	printf("offset: %d %d\n", face->glyph->bitmap_left, face->glyph->bitmap_top);
61	new_advance = (int)(face->glyph->advance.x >> 6);
62	if (face->glyph->bitmap.width >= new_advance)
63		new_advance = face->glyph->bitmap.width + 1;
64	printf("advance: %d\n", new_advance);
65	new_above = face->glyph->bitmap_top;
66	new_below = face->glyph->bitmap.rows - face->glyph->bitmap_top;
67	if (new_above > above) above = new_above;
68	if (new_below > below) below = new_below;
69	if (new_advance > advance) advance = new_advance;
70	return 0;
71}
72
73int
74main(int argc, char *argv[])
75{
76	int error, glyph_index;
77	int x, y, idx, width_in_bytes, height = 22, cell_height;
78	int width, datalen, didx, i, start, end, out;
79	FILE *output;
80	uint8_t *fontdata;
81	char fontname[128], filename[sizeof(fontname) + 4 /* .wsf */];
82
83	if (argc != 3) {
84		printf("usage: ttf2wsfont some_font.ttf height\n");
85		return 0;
86	}
87
88	sscanf(argv[2], "%d", &height);
89
90	error = FT_Init_FreeType( &library );
91	if (error) {
92		printf("Failed to initialize freefont2\n");
93		return -1;
94	}
95	error = FT_New_Face(library, argv[1], 0, &face );
96	if ( error == FT_Err_Unknown_File_Format ) {
97		printf("unsupported font format\n");
98		return -1;
99	}
100	error = FT_Set_Pixel_Sizes(face, /* handle to face object */
101				   0,    /* pixel_width */
102				   height - (height / 10) ); /* pixel_height */
103	if (error) {
104		printf("couldn't set character cell size\n");
105	}
106
107	push_size('W');
108	push_size('g');
109	push_size(']');
110	push_size('[');
111	push_size('^');
112	push_size(192);
113	printf("above: %d below: %d advance: %d\n", above, below, advance);
114	width = advance;
115	baseline = above;
116	cell_height = above + below;
117	datalen = 256 * width * cell_height;
118	fontdata = malloc(datalen);
119
120
121	for (i = 0; i < 256; i++) {
122		glyph_index = FT_Get_Char_Index(face, i);
123		FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT);
124		FT_Render_Glyph(face->glyph, FT_RENDER_MODE_NORMAL);
125		width_in_bytes =  face->glyph->bitmap.width;
126		start = baseline - face->glyph->bitmap_top;
127		end = start + face->glyph->bitmap.rows;
128		if (end > cell_height)
129			end = cell_height;
130		idx = 0;
131		if (start < 0) {
132			idx += (0 - start) * width_in_bytes;
133			start = 0;
134		}
135		didx = i * width * cell_height + /* character cell */
136		       start * width + /* pixels above baseline */
137		       face->glyph->bitmap_left; /* pixels left from border */
138		memset(&fontdata[i * width * cell_height], 0, width * cell_height);
139		for (y = start; y < end; y++) {
140			for (x = 0; x < width_in_bytes; x++) {
141				fontdata[didx + x] = face->glyph->bitmap.buffer[idx + x];
142			}
143			idx += width_in_bytes;
144			didx += width;
145		}
146	}
147
148	/* now output as a header file */
149	snprintf(fontname, sizeof(fontname), "%s_%dx%d", face->family_name,
150	    width, cell_height);
151	for (i = 0; i < strlen(fontname); i++) {
152		if (isblank((int)fontname[i]))
153			fontname[i]='_';
154	}
155	snprintf(filename, sizeof(filename), "%s.h", fontname);
156	if ((output = fopen(filename, "w")) == NULL) {
157		fprintf(stderr, "Can't open output file %s\n", filename);
158		return -1;
159	}
160	fprintf(output, "static u_char %s_data[];\n", fontname);
161	fprintf(output, "\n");
162	fprintf(output, "static struct wsdisplay_font %s = {\n", fontname);
163	fprintf(output, "\t\"%s\",\t\t\t/* typeface name */\n", face->family_name);
164	fprintf(output, "\t32,\t\t\t\t/* firstchar */\n");
165	fprintf(output, "\t256 - 32,\t\t\t/* numchar */\n");
166	fprintf(output, "\tWSDISPLAY_FONTENC_ISO,\t\t/* encoding */\n");
167	fprintf(output, "\t%d,\t\t\t\t/* width */\n", width);
168	fprintf(output, "\t%d,\t\t\t\t/* height */\n", cell_height);
169	fprintf(output, "\t%d,\t\t\t\t/* stride */\n", width);
170	fprintf(output, "\tWSDISPLAY_FONTORDER_L2R,\t/* bit order */\n");
171	fprintf(output, "\tWSDISPLAY_FONTORDER_L2R,\t/* byte order */\n");
172	fprintf(output, "\t%s_data\t\t/* data */\n", fontname);
173	fprintf(output, "};\n\n");
174	fprintf(output, "static u_char %s_data[] = {\n", fontname);
175	for (i = 32; i < 256; i++) {
176		fprintf(output, "\t/* %d */\n", i);
177		idx = i * width * cell_height;
178		for (y = 0; y < cell_height; y++) {
179			for (x = 0; x < width; x++) {
180				fprintf(output, "0x%02x, ",fontdata[idx + x]);
181			}
182			fprintf(output, "/* ");
183			for (x = 0; x < width; x++) {
184				fprintf(output, "%c",cvr[fontdata[idx + x] >> 5]);
185			}
186			fprintf(output, " */\n");
187
188			idx += width;
189		}
190	}
191	fprintf(output, "};\n");
192	fclose(output);
193	/* dump as binary */
194	snprintf(filename, sizeof(filename), "%s.wsf", fontname);
195	if ((out = open(filename, O_RDWR | O_CREAT | O_TRUNC, DEFFILEMODE)) > 0) {
196		char nbuf[64];
197		uint32_t foo;
198		write(out, "WSFT", 4);
199		memset(nbuf, 0, sizeof(nbuf));
200		strlcpy(nbuf, face->family_name, sizeof(nbuf));
201		write(out, nbuf, sizeof(nbuf));
202		/* firstchar */
203		foo = htole32(32);
204		write(out, &foo, 4);
205		/* numchar */
206		foo = htole32(256 - 32);
207		write(out, &foo, 4);
208		/* encoding */
209		foo = htole32(WSDISPLAY_FONTENC_ISO);
210		write(out, &foo, 4);
211		/* fontwidth */
212		foo = htole32(width);
213		write(out, &foo, 4);
214		/* fontheight */
215		foo = htole32(cell_height);
216		write(out, &foo, 4);
217		/* stride */
218		foo = htole32(width);
219		write(out, &foo, 4);
220		/* bitorder */
221		foo = htole32(WSDISPLAY_FONTORDER_L2R);
222		write(out, &foo, 4);
223		/* byteorder */
224		foo = htole32(WSDISPLAY_FONTORDER_L2R);
225		write(out, &foo, 4);
226		/* now the font data */
227		write(out, fontdata + (32 * width * cell_height),
228		           (256 - 32) * width * cell_height);
229		close(out);
230	}
231	free(fontdata);
232	FT_Done_Face(face);
233	FT_Done_FreeType(library);
234}
235