summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Drake <tlsa@netsurf-browser.org>2010-02-06 22:37:27 (GMT)
committer Michael Drake <tlsa@netsurf-browser.org>2010-02-06 22:37:27 (GMT)
commit588aa08774047cf23ce76ec1df39713781d8ecfa (patch)
tree972f6992f8ed9987231b318e4cd2b1fa8de97ecc
parentf8f2321ca670fd551d20c550fbf787fc9ef5c159 (diff)
downloadart-588aa08774047cf23ce76ec1df39713781d8ecfa.tar.gz
art-588aa08774047cf23ce76ec1df39713781d8ecfa.tar.bz2
Basic tool to convert the plain text font data to something useful for nsfb.
svn path=/trunk/art/; revision=9958
-rw-r--r--fonts/netsurf/tools/convert.c392
1 files changed, 392 insertions, 0 deletions
diff --git a/fonts/netsurf/tools/convert.c b/fonts/netsurf/tools/convert.c
new file mode 100644
index 0000000..b6eabc2
--- a/dev/null
+++ b/fonts/netsurf/tools/convert.c
@@ -0,0 +1,392 @@
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+enum font_style {
+ REGULAR = 0,
+ ITALIC = 1,
+ BOLD = 2,
+ ITALIC_BOLD = 3
+};
+
+struct glyph_offset {
+ int code;
+ long offset;
+};
+
+const int HEADER_MAX = 10000;
+
+int cp1252[256] = {
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
+ 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F,
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
+ 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F,
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
+ 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
+ 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F,
+ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
+ 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F,
+ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
+ 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F,
+ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
+ 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
+ 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F,
+ 0x20AC, 0xFFFD, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021,
+ 0x02C6, 0x2030, 0x0160, 0x2039, 0x0152, 0xFFFD, 0x017D, 0xFFFD,
+ 0xFFFD, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
+ 0x02DC, 0x2122, 0x0161, 0x203A, 0x0153, 0xFFFD, 0x017E, 0x0178,
+ 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7,
+ 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF,
+ 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7,
+ 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF,
+ 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7,
+ 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF,
+ 0x00D0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7,
+ 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF,
+ 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7,
+ 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF,
+ 0x00F0, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7,
+ 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x00FF};
+
+
+// Convert a hex digit to a number. e.g. 'A' --> 10
+int get_hex_digit_value(char c)
+{
+ if (c >= '0' && c <= '9')
+ return (c - '0');
+ else if (c >= 'A' && c <= 'F')
+ return (10 + c - 'A');
+ else {
+ printf("Bad hex value\n");
+ exit(EXIT_FAILURE);
+ }
+}
+
+
+// Convert Unicode codepoint to an int. e.g. "000F" --> 15
+int unicode_to_int(char* text)
+{
+ int result = 0;
+ int i;
+
+ for (i = 0; i < 4; i++)
+ result += get_hex_digit_value(text[i]) * pow(16, 3 - i);
+
+ return result;
+}
+
+
+// Numercical comparison function for qsort() and bsearch()
+int compare(const void *a, const void *b)
+{
+ return (*(int *)a - ((struct glyph_offset*)b)->code);
+}
+
+
+// Scan glyphs file for faults and populate table of glyph offsets
+bool prescan_glyphs(FILE *glyphs_file, struct glyph_offset **offsets, int *n)
+{
+ int count, c;
+ char code[5];
+ code[4] = '\0';
+ char p = '\0';
+ int previous = -1;
+
+ // Count glyphs in file
+ *n = 0;
+ c = fgetc(glyphs_file);
+ while (c != EOF) {
+ if (c == '+' && p == 'U') {
+ *n = *n + 1;
+ }
+ p = c;
+ c = fgetc(glyphs_file);
+ }
+
+ // Allocate space for offset table
+ *offsets = (struct glyph_offset*)
+ malloc(*n * sizeof(struct glyph_offset));
+ if (*offsets == NULL) {
+ printf("Couldn't allocate offsets memory.\n");
+ return false;
+ }
+
+ // Check glyphs in the file are in the correct order, and record
+ // offset to each glyph section
+ rewind(glyphs_file);
+ count = 0;
+ p = '\0';
+ c = fgetc(glyphs_file);
+ while (c != EOF) {
+ if (c == '+' && p == 'U') {
+ // Record offset to glyph entry
+ (*offsets)[count].offset = ftell(glyphs_file);
+ fread(code, 1, 4, glyphs_file);
+ if (previous >= unicode_to_int(code)) {
+ printf("Wrong order at: %s\n", code);
+ return false;
+ }
+ // Record which glyph it is
+ (*offsets)[count].code = unicode_to_int(code);
+ previous = unicode_to_int(code);
+ count++;
+ }
+ p = c;
+ c = fgetc(glyphs_file);
+ }
+
+ rewind(glyphs_file);
+
+ return true;
+}
+
+
+// Get a particular glyph from the glyphs file. Return true unless problem
+// encountered
+bool get_glyph(FILE *glyphs_file, char glyph_data[16][8], int n, int codepoint,
+ struct glyph_offset *offsets, enum font_style style)
+{
+ enum font_style output_style;
+ char code[5];
+ char buffer[16 * 45];
+ code[4] = '\0';
+ int c, i;
+ int x, y;
+ struct glyph_offset *glyph;
+ int count, position, start_pos;
+
+ bool italic = true;
+ bool bold = true;
+ bool italic_bold = true;
+
+ glyph = (struct glyph_offset*)bsearch(&codepoint, offsets, n,
+ sizeof(struct glyph_offset), compare);
+
+ if (glyph == NULL) {
+ // This codepoint isn't available in the glyph file.
+ return false;
+ }
+
+ // Move to the required glyph section in glyphs file
+ fseek(glyphs_file, glyph->offset, SEEK_SET);
+
+ // Check we're at the right place
+ fread(code, 1, 4, glyphs_file);
+ if (unicode_to_int(code) != glyph->code) {
+ printf("Error finding glyph %.4X, missmatches %s\n"
+ "Probably broken offset table.\n",
+ glyph->code, code);
+ exit(EXIT_FAILURE);
+ }
+
+ // Pass over rest of line
+ c = fgetc(glyphs_file);
+ while (c != EOF) {
+ if (c == '\n')
+ break;
+ c = fgetc(glyphs_file);
+ }
+
+ // Pass over separator line
+ fread(buffer, 1, 54, glyphs_file);
+ if (strncmp("- - - - - - - - - - - - - - - - - - - - - - - - - - -\n",
+ buffer, 54) != 0) {
+ printf("Glyph file formatting error around glyph U+%.4X\n",
+ glyph->code);
+ exit(EXIT_FAILURE);
+ }
+
+ // Read glyph data
+ fread(buffer, 1, 16 * 45, glyphs_file);
+
+ // Check glyph data formatting is valid and find which styles are
+ // present
+ count = 0;
+ while (buffer[count] != '\n') {
+ count++;
+ }
+ if (count != 11 && count != 22 && count != 33 && count != 44) {
+ printf("Glyph data formatting problem at glyph U+%.4X, "
+ "line 0\n"
+ "Possibly trailing whitespace.\n",
+ glyph->code);
+ exit(EXIT_FAILURE);
+ }
+
+ position = count;
+ for (i = 1; i < 16; i++) {
+ if (buffer[position] != '\n') {
+ printf("Glyph data formatting problem at glyph U+%.4X, "
+ "line %i\n"
+ "Possibly trailing whitespace.\n",
+ glyph->code, i);
+ exit(EXIT_FAILURE);
+ }
+ position += count + 1;
+ }
+ // TODO handle italic_bold available but not italic or bold
+ if (count < 44)
+ italic_bold = false;
+ if (count < 33)
+ bold = false;
+ if (count < 22)
+ italic = false;
+
+ // Set output_style depending on required style and style availability
+ switch (style) {
+ case REGULAR:
+ output_style = REGULAR;
+ break;
+ case ITALIC:
+ if (italic) {
+ output_style = ITALIC;
+ } else {
+ output_style = REGULAR;
+ printf("U+%.4X - Subst. regular for italic\n",
+ glyph->code);
+ }
+ break;
+ case BOLD:
+ if (bold) {
+ output_style = BOLD;
+ } else {
+ output_style = REGULAR;
+ printf("U+%.4X - Subst. regular for bold\n",
+ glyph->code);
+ }
+ break;
+ case ITALIC_BOLD:
+
+ if (italic_bold) {
+ output_style = ITALIC_BOLD;
+ } else if (italic) {
+ output_style = ITALIC;
+ printf("U+%.4X - Subst. italic for italic bold\n",
+ glyph->code);
+ } else {
+ output_style = REGULAR;
+ printf("U+%.4X - Subst. regular for italic bold\n",
+ glyph->code);
+ }
+ break;
+ default:
+ printf("Insane font style requested\n");
+ exit(EXIT_FAILURE);
+ }
+
+ // Populate output glyph data array with glyph
+ start_pos = 3 + output_style * (8 + 3);
+ for (y = 0; y < 16; y++) {
+ position = start_pos + (y * (count + 1));
+ for (x = 0; x < 8; x++) {
+ glyph_data[y][x] = buffer[position + x];
+ }
+ }
+
+ rewind(glyphs_file);
+ return true;
+}
+
+
+int main(int argc, char** argv)
+{
+ FILE *glyphs_file;
+ FILE *r_file, *i_file, *b_file, *ib_file;
+ char glyph_data[16][8];
+ struct glyph_offset *offsets;
+ int n, x, y, i;
+ int c, p = '\0';
+ char buffer[HEADER_MAX];
+
+ // Open glyph data file
+ if ((glyphs_file = fopen("BitmapFont", "r")) == NULL)
+ return EXIT_FAILURE;
+
+ // Scan glyphs file for problems and create table of pointers
+ // to each glyph's section in file
+ if (!prescan_glyphs(glyphs_file, &offsets, &n))
+ return EXIT_FAILURE;
+
+ /* Uncomment to print all available glyphs in the chosen style as text
+ // Go through the entire unicode range and print the glyph, if available
+ for (i = 0x0000; i <= 0xFFFF; i++) {
+ if (get_glyph(glyphs_file, glyph_data, n, i, offsets,
+ REGULAR)) {
+ printf("U+%.4X\n", i);
+ // Print glyph
+ for (y = 0; y < 16; y++) {
+ printf(" ");
+ for (x = 0; x < 8; x++) {
+ printf("%c", glyph_data[y][x]);
+ }
+ printf("\n");
+ }
+ printf("\n");
+ }
+ }
+ */
+
+ // Export CP1252 glyphs for framebuffer NetSurf
+ if ((r_file = fopen("r", "w")) == NULL)
+ return EXIT_FAILURE;
+
+ rewind(glyphs_file);
+ fread(buffer, 1, HEADER_MAX, glyphs_file);
+ i = 0;
+ while (i < HEADER_MAX - 1 && (buffer[i] != '\n' ||
+ (buffer[i+1] == '*' && buffer[i] == '\n'))) {
+ i++;
+ }
+ buffer[i + 1] = '\0';
+ fprintf(r_file, "/*\n%s */\n\n", buffer);
+
+ fprintf(r_file, "/* Don't edit this file, it was generated from the "
+ "plain text source data. */\n\n");
+
+ fprintf(r_file, "#include \"desktop/plotters.h\"\n"
+ "#include \"utils/utf8.h\"\n\n"
+ "#include \"framebuffer/font_internal.h\"\n\n"
+ "#define FONTDATAMAX 4096\n\n"
+ "static const uint32_t "
+ "fontdata_regular[FONTDATAMAX] = {\n");
+
+ for (i = 0; i < 256; i++) {
+ if (!get_glyph(glyphs_file, glyph_data, n, cp1252[i], offsets,
+ REGULAR)) {
+ printf("Glyph U+%.4x\n", cp1252[i]);
+ return EXIT_FAILURE;
+ }
+ fprintf(r_file, "\t");
+ for (y = 0; y < 16; y++) {
+ c = 0;
+ for (x = 0; x < 8; x++) {
+ if (glyph_data[y][x] == '#') {
+ c += 1 << (7 - x);
+ }
+ }
+ if (y == 7)
+ fprintf(r_file, "0x%.2X,\n\t", c);
+ else
+ fprintf(r_file, "0x%.2X, ", c);
+ }
+ fprintf(r_file, "\n");
+ }
+
+ fprintf(r_file, "};\n\n"
+ "const struct fb_font_desc font_regular = {\n"
+ "\t.name = \"NetSurf Regular\",\n"
+ "\t.width = 8,\n"
+ "\t.height = 16,\n"
+ "\t.encoding = \"CP1252\",\n"
+ "\t.data = fontdata_regular,\n"
+ "};", buffer);
+
+ free(offsets);
+ fclose(glyphs_file);
+ fclose(r_file);
+
+ return EXIT_SUCCESS;
+}