diff --git a/book.c b/book.c index c92b05d..2e33dd5 100644 --- a/book.c +++ b/book.c @@ -198,6 +198,43 @@ static void entry_encode(json_t* entry_json, const Book_Entry* entry, int flags) } } +static void font_glyph_encode(json_t* glyph_json, const Book_Glyph* glyph) { + json_t* bitmap_json_array = json_array(); + for (unsigned i = 0; i < ARRSIZE(glyph->bitmap); ++i) { + json_array_append_new(bitmap_json_array, json_integer(glyph->bitmap[i])); + } + + json_object_set_new(glyph_json, "bitmap", bitmap_json_array); + json_object_set_new(glyph_json, "code", json_integer(glyph->code)); +} + +static void font_glyph_set_encode(json_t* glyph_set_json, const Book_Glyph_Set* glyph_set) { + json_t* glyph_json_array = json_array(); + for (int i = 0; i < glyph_set->count; ++i) { + json_t* glyph_json = json_object(); + font_glyph_encode(glyph_json, &glyph_set->glyphs[i]); + json_array_append_new(glyph_json_array, glyph_json); + } + + json_object_set_new(glyph_set_json, "glyphs", glyph_json_array); + json_object_set_new(glyph_set_json, "width", json_integer(glyph_set->width)); + json_object_set_new(glyph_set_json, "height", json_integer(glyph_set->height)); +} + +static void font_encode(json_t* font_json, const Book_Font* font) { + if (font->narrow.count > 0) { + json_t* narrow_json = json_object(); + font_glyph_set_encode(narrow_json, &font->narrow); + json_object_set_new(font_json, "narrow", narrow_json); + } + + if (font->wide.count > 0) { + json_t* wide_json = json_object(); + font_glyph_set_encode(wide_json, &font->wide); + json_object_set_new(font_json, "wide", wide_json); + } +} + static void subbook_encode(json_t* subbook_json, const Book_Subbook* subbook, int flags) { if (subbook->title != NULL) { json_object_set_new(subbook_json, "title", json_string(subbook->title)); @@ -212,6 +249,20 @@ static void subbook_encode(json_t* subbook_json, const Book_Subbook* subbook, in json_object_set_new(subbook_json, "copyrightOffset", json_integer(subbook->copyright.offset)); } + if (flags & FLAG_FONTS) { + json_t* font_json_array = json_array(); + for (unsigned i = 0; i < ARRSIZE(subbook->fonts); ++i) { + const Book_Font* font = subbook->fonts + i; + if (font->wide.count > 0 || font->narrow.count) { + json_t* font_json = json_object(); + font_encode(font_json, font); + json_array_append_new(font_json_array, font_json); + } + } + + json_object_set_new(subbook_json, "fonts", font_json_array); + } + json_t* entry_json_array = json_array(); for (int i = 0; i < subbook->entry_count; ++i) { json_t* entry_json = json_object(); @@ -270,7 +321,113 @@ static void subbook_entries_import(Book_Subbook* subbook, EB_Book* eb_book, EB_H while (hit_count > 0); } -static void subbook_import(Book_Subbook* subbook, EB_Book* eb_book, EB_Hookset* eb_hookset) { +static void subbook_font_import(Book_Font* font, EB_Book* eb_book, EB_Font_Code code) { + if (eb_set_font(eb_book, code) != EB_SUCCESS) { + return; + } + + do { + switch (code) { + case EB_FONT_16: + font->narrow.width = EB_WIDTH_NARROW_FONT_16; + font->narrow.height = EB_HEIGHT_FONT_16; + break; + case EB_FONT_24: + font->narrow.width = EB_WIDTH_NARROW_FONT_24; + font->narrow.height = EB_HEIGHT_FONT_24; + break; + case EB_FONT_30: + font->narrow.width = EB_WIDTH_NARROW_FONT_30; + font->narrow.height = EB_HEIGHT_FONT_30; + break; + case EB_FONT_48: + font->narrow.width = EB_WIDTH_NARROW_FONT_48; + font->narrow.height = EB_HEIGHT_FONT_48; + break; + } + + int font_code = 0; + if (eb_narrow_font_start(eb_book, &font_code) != EB_SUCCESS) { + break; + } + + int glyph_alloc = 256; + font->narrow.glyphs = malloc(sizeof(Book_Glyph) * glyph_alloc); + + for (;;) { + if (font->narrow.count == glyph_alloc) { + glyph_alloc *= 2; + font->narrow.glyphs = realloc(font->narrow.glyphs, glyph_alloc); + } + + Book_Glyph* glyph = &font->narrow.glyphs[font->narrow.count]; + glyph->code = font_code; + + if (eb_narrow_font_character_bitmap(eb_book, font_code, glyph->bitmap) != EB_SUCCESS) { + break; + } + + ++font->narrow.count; + + if (eb_forward_narrow_font_character(eb_book, 1, &font_code) != EB_SUCCESS) { + break; + } + } + } + while (0); + + do { + switch (code) { + case EB_FONT_16: + font->wide.width = EB_WIDTH_WIDE_FONT_16; + font->wide.height = EB_HEIGHT_FONT_16; + break; + case EB_FONT_24: + font->wide.width = EB_WIDTH_WIDE_FONT_24; + font->wide.height = EB_HEIGHT_FONT_24; + break; + case EB_FONT_30: + font->wide.width = EB_WIDTH_WIDE_FONT_30; + font->wide.height = EB_HEIGHT_FONT_30; + break; + case EB_FONT_48: + font->wide.width = EB_WIDTH_WIDE_FONT_48; + font->wide.height = EB_HEIGHT_FONT_48; + break; + } + + int font_code = 0; + if (eb_wide_font_start(eb_book, &font_code) != EB_SUCCESS) { + break; + } + + int glyph_alloc = 256; + font->wide.glyphs = malloc(sizeof(Book_Glyph) * glyph_alloc); + + for (;;) { + if (font->wide.count == glyph_alloc) { + glyph_alloc *= 2; + font->wide.glyphs = realloc(font->wide.glyphs, glyph_alloc); + } + + Book_Glyph* glyph = &font->wide.glyphs[font->wide.count]; + glyph->code = font_code; + + if (eb_wide_font_character_bitmap(eb_book, font_code, glyph->bitmap) != EB_SUCCESS) { + break; + } + + ++font->wide.count; + + if (eb_forward_wide_font_character(eb_book, 1, &font_code) != EB_SUCCESS) { + break; + } + } + } + while (0); +} + +static void subbook_import(Book_Subbook* subbook, EB_Book* eb_book, EB_Hookset* eb_hookset, int flags) { char title[EB_MAX_TITLE_LENGTH + 1]; if (eb_subbook_title(eb_book, title) == EB_SUCCESS) { subbook->title = eucjp_to_utf8(title); @@ -294,6 +451,14 @@ static void subbook_import(Book_Subbook* subbook, EB_Book* eb_book, EB_Hookset* if (eb_search_all_asis(eb_book) == EB_SUCCESS) { subbook_entries_import(subbook, eb_book, eb_hookset); } + + memset(subbook->fonts, 0, sizeof(subbook->fonts)); + if (flags & FLAG_FONTS) { + const EB_Font_Code codes[] = {EB_FONT_16, EB_FONT_24, EB_FONT_30, EB_FONT_48}; + for (unsigned i = 0; i < ARRSIZE(codes); ++i) { + subbook_font_import(&subbook->fonts[i], eb_book, codes[i]); + } + } } /* @@ -316,6 +481,12 @@ void book_free(Book* book) { free(entry->text.text); } + for (unsigned j = 0; j < ARRSIZE(subbook->fonts); ++j) { + const Book_Font* font = &subbook->fonts[j]; + free(font->narrow.glyphs); + free(font->wide.glyphs); + } + free(subbook->entries); } @@ -405,7 +576,7 @@ int book_import(Book* book, const char path[], int flags) { for (int i = 0; i < book->subbook_count; ++i) { Book_Subbook* subbook = book->subbooks + i; if ((error = eb_set_subbook(&eb_book, sub_codes[i])) == EB_SUCCESS) { - subbook_import(subbook, &eb_book, &eb_hookset); + subbook_import(subbook, &eb_book, &eb_hookset, flags); } else { fprintf(stderr, "error: failed to set subbook (%s)\n", eb_error_message(error)); diff --git a/book.h b/book.h index 447fea6..c0c4a32 100644 --- a/book.h +++ b/book.h @@ -42,14 +42,20 @@ typedef struct { } Book_Entry; typedef struct { - unsigned char bitmap[EB_SIZE_WIDE_FONT_48]; + char bitmap[EB_SIZE_WIDE_FONT_48]; + int code; } Book_Glyph; typedef struct { Book_Glyph* glyphs; - int glyph_count; - int glyph_size; - int glyph_wide; + int width; + int height; + int count; +} Book_Glyph_Set; + +typedef struct { + Book_Glyph_Set wide; + Book_Glyph_Set narrow; } Book_Font; typedef struct { @@ -60,8 +66,7 @@ typedef struct { int entry_count; int entry_alloc; - Book_Font* fonts; - int font_count; + Book_Font fonts[4]; } Book_Subbook; typedef struct { diff --git a/main.c b/main.c index 97dcafc..ccb4c6f 100644 --- a/main.c +++ b/main.c @@ -35,6 +35,7 @@ int main(int argc, char *argv[]) { { "pretty", no_argument, NULL, 'p' }, { "markup", no_argument, NULL, 'm' }, { "positions", no_argument, NULL, 's' }, + { "fonts", no_argument, NULL, 'f' }, { NULL, 0, NULL, 0 }, }; @@ -53,6 +54,9 @@ int main(int argc, char *argv[]) { case 's': flags |= FLAG_POSITIONS; break; + case 'f': + flags |= FLAG_FONTS; + break; default: return 1; } diff --git a/util.h b/util.h index 2003346..38c2c93 100644 --- a/util.h +++ b/util.h @@ -33,7 +33,7 @@ enum { FLAG_PRETTY_PRINT = 1 << 0, FLAG_HOOK_MARKUP = 1 << 1, FLAG_POSITIONS = 1 << 2, - FLAG_FONT_TAGS = 1 << 3, + FLAG_FONTS = 1 << 3, }; #endif /* UTIL_H */