From 2612c20b725319833caeef36ccf4240f34e0e24b Mon Sep 17 00:00:00 2001 From: Tor Andersson Date: Wed, 14 Mar 2018 17:52:17 +0100 Subject: Add simple CJK font creation. Create a non-embedded CJK font using UTF-16 encoding. This can be used in mutool create like so: %%CJKFont Ming GB1 BT /Ming 10 Tf 100 100 Td <4F60 597D> Tj ET --- include/mupdf/pdf/font.h | 1 + include/mupdf/pdf/resource.h | 4 +- platform/java/mupdf_native.c | 22 ++++++ platform/java/mupdf_native.h | 16 ++++ platform/java/src/com/artifex/mupdf/fitz/Font.java | 5 ++ .../src/com/artifex/mupdf/fitz/PDFDocument.java | 1 + source/pdf/pdf-font.c | 89 +++++++++++++++++++++- source/pdf/pdf-resources.c | 3 +- source/tools/murun.c | 23 ++++++ source/tools/pdfcreate.c | 37 +++++++++ 10 files changed, 196 insertions(+), 5 deletions(-) diff --git a/include/mupdf/pdf/font.h b/include/mupdf/pdf/font.h index 10571f0b..730d3459 100644 --- a/include/mupdf/pdf/font.h +++ b/include/mupdf/pdf/font.h @@ -125,6 +125,7 @@ void pdf_run_glyph(fz_context *ctx, pdf_document *doc, pdf_obj *resources, fz_bu pdf_obj *pdf_add_simple_font(fz_context *ctx, pdf_document *doc, fz_font *font); pdf_obj *pdf_add_cid_font(fz_context *ctx, pdf_document *doc, fz_font *font); +pdf_obj *pdf_add_cjk_font(fz_context *ctx, pdf_document *doc, fz_font *font, int script); int pdf_font_writing_supported(fz_font *font); diff --git a/include/mupdf/pdf/resource.h b/include/mupdf/pdf/resource.h index 6bede024..885a404e 100644 --- a/include/mupdf/pdf/resource.h +++ b/include/mupdf/pdf/resource.h @@ -17,9 +17,9 @@ void pdf_empty_store(fz_context *ctx, pdf_document *doc); * the data, enabling rapid lookup. */ -enum { PDF_SIMPLE_FONT_RESOURCE=1, PDF_CID_FONT_RESOURCE=2 }; +enum { PDF_SIMPLE_FONT_RESOURCE=1, PDF_CID_FONT_RESOURCE=2, PDF_CJK_FONT_RESOURCE=3 }; -pdf_obj *pdf_find_font_resource(fz_context *ctx, pdf_document *doc, int type, fz_buffer *item, unsigned char md5[16]); +pdf_obj *pdf_find_font_resource(fz_context *ctx, pdf_document *doc, int type, int encoding, fz_buffer *item, unsigned char md5[16]); pdf_obj *pdf_insert_font_resource(fz_context *ctx, pdf_document *doc, unsigned char md5[16], pdf_obj *obj); pdf_obj *pdf_find_image_resource(fz_context *ctx, pdf_document *doc, fz_image *item, unsigned char md5[16]); pdf_obj *pdf_insert_image_resource(fz_context *ctx, pdf_document *doc, unsigned char md5[16], pdf_obj *obj); diff --git a/platform/java/mupdf_native.c b/platform/java/mupdf_native.c index 7235d50e..31f76d7b 100644 --- a/platform/java/mupdf_native.c +++ b/platform/java/mupdf_native.c @@ -7053,6 +7053,28 @@ FUN(PDFDocument_addFont)(JNIEnv *env, jobject self, jobject jfont) return to_PDFObject_safe_own(ctx, env, self, ind); } +JNIEXPORT jobject JNICALL +FUN(PDFDocument_addCJKFont)(JNIEnv *env, jobject self, jobject jfont, jint ordering) +{ + fz_context *ctx = get_context(env); + pdf_document *pdf = from_PDFDocument(env, self); + fz_font *font = from_Font(env, jfont); + pdf_obj *ind = NULL; + + if (!ctx || !pdf) return NULL; + if (!font) { jni_throw_arg(env, "font must not be null"); return NULL; } + + fz_try(ctx) + ind = pdf_add_cjk_font(ctx, pdf, font, ordering); + fz_catch(ctx) + { + jni_rethrow(env, ctx); + return NULL; + } + + return to_PDFObject_safe_own(ctx, env, self, ind); +} + JNIEXPORT jobject JNICALL FUN(PDFDocument_addSimpleFont)(JNIEnv *env, jobject self, jobject jfont) { diff --git a/platform/java/mupdf_native.h b/platform/java/mupdf_native.h index 8bfe3480..42d54345 100644 --- a/platform/java/mupdf_native.h +++ b/platform/java/mupdf_native.h @@ -889,6 +889,14 @@ extern "C" { #ifdef __cplusplus extern "C" { #endif +#undef com_artifex_mupdf_fitz_Font_CN +#define com_artifex_mupdf_fitz_Font_CN 0L +#undef com_artifex_mupdf_fitz_Font_TW +#define com_artifex_mupdf_fitz_Font_TW 1L +#undef com_artifex_mupdf_fitz_Font_JP +#define com_artifex_mupdf_fitz_Font_JP 2L +#undef com_artifex_mupdf_fitz_Font_KR +#define com_artifex_mupdf_fitz_Font_KR 3L /* * Class: com_artifex_mupdf_fitz_Font * Method: finalize @@ -1902,6 +1910,14 @@ JNIEXPORT jobject JNICALL Java_com_artifex_mupdf_fitz_PDFDocument_addImage JNIEXPORT jobject JNICALL Java_com_artifex_mupdf_fitz_PDFDocument_addSimpleFont (JNIEnv *, jobject, jobject); +/* + * Class: com_artifex_mupdf_fitz_PDFDocument + * Method: addCJKFont + * Signature: (Lcom/artifex/mupdf/fitz/Font;I)Lcom/artifex/mupdf/fitz/PDFObject; + */ +JNIEXPORT jobject JNICALL Java_com_artifex_mupdf_fitz_PDFDocument_addCJKFont + (JNIEnv *, jobject, jobject, jint); + /* * Class: com_artifex_mupdf_fitz_PDFDocument * Method: addFont diff --git a/platform/java/src/com/artifex/mupdf/fitz/Font.java b/platform/java/src/com/artifex/mupdf/fitz/Font.java index 9eb6f61a..2910d543 100644 --- a/platform/java/src/com/artifex/mupdf/fitz/Font.java +++ b/platform/java/src/com/artifex/mupdf/fitz/Font.java @@ -6,6 +6,11 @@ public class Font Context.init(); } + public static final int CN = 0; + public static final int TW = 1; + public static final int JP = 2; + public static final int KR = 3; + private long pointer; protected native void finalize(); diff --git a/platform/java/src/com/artifex/mupdf/fitz/PDFDocument.java b/platform/java/src/com/artifex/mupdf/fitz/PDFDocument.java index 945294f3..b650df52 100644 --- a/platform/java/src/com/artifex/mupdf/fitz/PDFDocument.java +++ b/platform/java/src/com/artifex/mupdf/fitz/PDFDocument.java @@ -97,6 +97,7 @@ public class PDFDocument extends Document public native void deletePage(int at); public native PDFObject addImage(Image image); public native PDFObject addSimpleFont(Font font); + public native PDFObject addCJKFont(Font font, int ordering); public native PDFObject addFont(Font font); public native boolean hasUnsavedChanges(); public native boolean canBeSavedIncrementally(); diff --git a/source/pdf/pdf-font.c b/source/pdf/pdf-font.c index 9e8a50dc..6be72250 100644 --- a/source/pdf/pdf-font.c +++ b/source/pdf/pdf-font.c @@ -2099,7 +2099,7 @@ pdf_add_cid_font(fz_context *ctx, pdf_document *doc, fz_font *font) /* Before we add this font as a resource check if the same font * already exists in our resources for this doc. If yes, then * hand back that reference */ - fref = pdf_find_font_resource(ctx, doc, PDF_CID_FONT_RESOURCE, font->buffer, digest); + fref = pdf_find_font_resource(ctx, doc, PDF_CID_FONT_RESOURCE, 0, font->buffer, digest); if (fref == NULL) { /* Set up desc, width, and font file */ @@ -2174,7 +2174,7 @@ pdf_add_simple_font(fz_context *ctx, pdf_document *doc, fz_font *font) /* Before we add this font as a resource check if the same font * already exists in our resources for this doc. If yes, then * hand back that reference */ - fref = pdf_find_font_resource(ctx, doc, PDF_SIMPLE_FONT_RESOURCE, font->buffer, digest); + fref = pdf_find_font_resource(ctx, doc, PDF_SIMPLE_FONT_RESOURCE, 0, font->buffer, digest); if (fref == NULL) { fobj = pdf_new_dict(ctx, doc, 10); @@ -2247,3 +2247,88 @@ pdf_font_writing_supported(fz_font *font) } return 0; } + +/* Add a non-embedded UTF16-encoded CID-font for the CJK scripts: CNS1, GB1, Japan1, or Korea1 */ +pdf_obj * +pdf_add_cjk_font(fz_context *ctx, pdf_document *doc, fz_font *fzfont, int script) +{ + pdf_obj *fref, *font, *subfont, *fontdesc; + pdf_obj *dfonts, *ros; + fz_rect bbox = { -200, -200, 1200, 1200 }; + unsigned char digest[16]; + + const char *basefont, *encoding, *ordering; + int supplement; + + switch (script) + { + case FZ_ADOBE_CNS_1: + basefont = "Song"; + encoding = "UniCNS-UTF16-H"; + ordering = "CNS1"; + supplement = 7; + break; + case FZ_ADOBE_GB_1: + basefont = "Ming"; + encoding = "UniGB-UTF16-H"; + ordering = "GB1"; + supplement = 5; + break; + default: + script = FZ_ADOBE_JAPAN_1; + /* fall through */ + case FZ_ADOBE_JAPAN_1: + basefont = "Mincho"; + encoding = "UniJIS-UTF16-H"; + ordering = "Japan1"; + supplement = 6; + break; + case FZ_ADOBE_KOREA_1: + basefont = "Batang"; + encoding = "UniKS-UTF16-H"; + ordering = "Korea1"; + supplement = 2; + break; + } + + fref = pdf_find_font_resource(ctx, doc, PDF_CJK_FONT_RESOURCE, script, fzfont->buffer, digest); + if (fref) + return fref; + + font = pdf_new_dict(ctx, doc, 5); + pdf_dict_put(ctx, font, PDF_NAME_Type, PDF_NAME_Font); + pdf_dict_put(ctx, font, PDF_NAME_Subtype, PDF_NAME_Type0); + pdf_dict_put_name(ctx, font, PDF_NAME_BaseFont, basefont); + pdf_dict_put_name(ctx, font, PDF_NAME_Encoding, encoding); + pdf_dict_put_drop(ctx, font, PDF_NAME_DescendantFonts, dfonts = pdf_new_array(ctx, doc, 1)); + subfont = pdf_new_dict(ctx, doc, 5); + { + pdf_dict_put(ctx, subfont, PDF_NAME_Type, PDF_NAME_Font); + pdf_dict_put(ctx, subfont, PDF_NAME_Subtype, PDF_NAME_CIDFontType0); + pdf_dict_put_name(ctx, subfont, PDF_NAME_BaseFont, basefont); + pdf_dict_put_drop(ctx, subfont, PDF_NAME_CIDSystemInfo, ros = pdf_new_dict(ctx, doc, 3)); + pdf_dict_put_text_string(ctx, ros, PDF_NAME_Registry, "Adobe"); + pdf_dict_put_text_string(ctx, ros, PDF_NAME_Ordering, ordering); + pdf_dict_put_int(ctx, ros, PDF_NAME_Supplement, supplement); + fontdesc = pdf_new_dict(ctx, doc, 8); + { + pdf_dict_put(ctx, fontdesc, PDF_NAME_Type, PDF_NAME_FontDescriptor); + pdf_dict_put_text_string(ctx, fontdesc, PDF_NAME_FontName, basefont); + pdf_dict_put_int(ctx, fontdesc, PDF_NAME_Flags, 0); + pdf_dict_put_rect(ctx, fontdesc, PDF_NAME_FontBBox, &bbox); + pdf_dict_put_int(ctx, fontdesc, PDF_NAME_ItalicAngle, 0); + pdf_dict_put_int(ctx, fontdesc, PDF_NAME_Ascent, 1000); + pdf_dict_put_int(ctx, fontdesc, PDF_NAME_Descent, -200); + pdf_dict_put_int(ctx, fontdesc, PDF_NAME_StemV, 80); + } + pdf_dict_put_drop(ctx, subfont, PDF_NAME_FontDescriptor, pdf_add_object_drop(ctx, doc, fontdesc)); + } + pdf_array_push_drop(ctx, dfonts, pdf_add_object_drop(ctx, doc, subfont)); + + fref = pdf_add_object_drop(ctx, doc, font); + + /* Add ref to our font resource hash table. */ + fref = pdf_insert_font_resource(ctx, doc, digest, fref); + + return fref; +} diff --git a/source/pdf/pdf-resources.c b/source/pdf/pdf-resources.c index 72adf081..720ee2b1 100644 --- a/source/pdf/pdf-resources.c +++ b/source/pdf/pdf-resources.c @@ -109,7 +109,7 @@ pdf_insert_image_resource(fz_context *ctx, pdf_document *doc, unsigned char dige * it may be more problematic. */ pdf_obj * -pdf_find_font_resource(fz_context *ctx, pdf_document *doc, int type, fz_buffer *item, unsigned char digest[16]) +pdf_find_font_resource(fz_context *ctx, pdf_document *doc, int type, int encoding, fz_buffer *item, unsigned char digest[16]) { fz_md5 state; unsigned char *data; @@ -124,6 +124,7 @@ pdf_find_font_resource(fz_context *ctx, pdf_document *doc, int type, fz_buffer * /* Create md5 and see if we have the item in our table */ fz_md5_init(&state); fz_md5_update(&state, (unsigned char*)&type, sizeof type); + fz_md5_update(&state, (unsigned char*)&encoding, sizeof encoding); fz_md5_update(&state, data, size); fz_md5_final(&state, digest); diff --git a/source/tools/murun.c b/source/tools/murun.c index bed686a7..911fcf35 100644 --- a/source/tools/murun.c +++ b/source/tools/murun.c @@ -3261,6 +3261,28 @@ static void ffi_PDFDocument_addSimpleFont(js_State *J) ffi_pushobj(J, ind); } +static void ffi_PDFDocument_addCJKFont(js_State *J) +{ + fz_context *ctx = js_getcontext(J); + pdf_document *pdf = js_touserdata(J, 0, "pdf_document"); + fz_font *font = js_touserdata(J, 1, "fz_font"); + const char *on = js_tostring(J, 2); + int ord = FZ_ADOBE_JAPAN_1; + pdf_obj *ind = NULL; + + if (!strcmp(on, "CNS1") || !strcmp(on, "CN")) ord = FZ_ADOBE_CNS_1; + else if (!strcmp(on, "GB1") || !strcmp(on, "TW")) ord = FZ_ADOBE_GB_1; + else if (!strcmp(on, "Korea1") || !strcmp(on, "KR") || !strcmp(on, "KO")) ord = FZ_ADOBE_KOREA_1; + else if (!strcmp(on, "Japan1") || !strcmp(on, "JP") || !strcmp(on, "JA")) ord = FZ_ADOBE_JAPAN_1; + + fz_try(ctx) + ind = pdf_add_cjk_font(ctx, pdf, font, ord); + fz_catch(ctx) + rethrow(J); + + ffi_pushobj(J, ind); +} + static void ffi_PDFDocument_addFont(js_State *J) { fz_context *ctx = js_getcontext(J); @@ -4676,6 +4698,7 @@ int murun_main(int argc, char **argv) jsB_propfun(J, "PDFDocument.addStream", ffi_PDFDocument_addStream, 2); jsB_propfun(J, "PDFDocument.addRawStream", ffi_PDFDocument_addRawStream, 2); jsB_propfun(J, "PDFDocument.addSimpleFont", ffi_PDFDocument_addSimpleFont, 1); + jsB_propfun(J, "PDFDocument.addCJKFont", ffi_PDFDocument_addCJKFont, 2); jsB_propfun(J, "PDFDocument.addFont", ffi_PDFDocument_addFont, 1); jsB_propfun(J, "PDFDocument.addImage", ffi_PDFDocument_addImage, 1); jsB_propfun(J, "PDFDocument.addPage", ffi_PDFDocument_addPage, 4); diff --git a/source/tools/pdfcreate.c b/source/tools/pdfcreate.c index b1649500..93dff5fb 100644 --- a/source/tools/pdfcreate.c +++ b/source/tools/pdfcreate.c @@ -22,6 +22,7 @@ static void usage(void) "\t%%%%MediaBox LLX LLY URX URY\n" "\t%%%%Rotate Angle\n" "\t%%%%Font Name Filename (or base 14 font name)\n" + "\t%%%%CJKFont Name Ordering (CNS1, GB1, Japan1, or Korea1)\n" "\t%%%%Image Name Filename\n\n" ); fputs(fz_pdf_write_options_usage, stderr); @@ -58,6 +59,36 @@ static void add_font_res(pdf_obj *resources, char *name, char *path) fz_drop_font(ctx, font); } +static void add_cjkfont_res(pdf_obj *resources, char *name, char *on) +{ + const unsigned char *data; + int size, index, ordering; + fz_font *font; + pdf_obj *subres, *ref; + + if (!strcmp(on, "CNS1") || !strcmp(on, "CN")) ordering = FZ_ADOBE_CNS_1; + else if (!strcmp(on, "GB1") || !strcmp(on, "TW")) ordering = FZ_ADOBE_GB_1; + else if (!strcmp(on, "Japan1") || !strcmp(on, "JP") || !strcmp(on, "JA")) ordering = FZ_ADOBE_JAPAN_1; + else if (!strcmp(on, "Korea1") || !strcmp(on, "KR") || !strcmp(on, "KO")) ordering = FZ_ADOBE_KOREA_1; + else ordering = FZ_ADOBE_JAPAN_1; + + data = fz_lookup_cjk_font(ctx, ordering, 0, 0, &size, &index); + font = fz_new_font_from_memory(ctx, NULL, data, size, index, 0); + + subres = pdf_dict_get(ctx, resources, PDF_NAME_Font); + if (!subres) + { + subres = pdf_new_dict(ctx, doc, 10); + pdf_dict_put_drop(ctx, resources, PDF_NAME_Font, subres); + } + + ref = pdf_add_cjk_font(ctx, doc, font, ordering); + pdf_dict_puts(ctx, subres, name, ref); + pdf_drop_obj(ctx, ref); + + fz_drop_font(ctx, font); +} + static void add_image_res(pdf_obj *resources, char *name, char *path) { fz_image *image; @@ -85,6 +116,7 @@ The input is a raw content stream, with commands embedded in comments: %%MediaBox LLX LLY URX URY %%Rotate Angle %%Font Name Filename (or base 14 font name) +%%CJKFont Name Ordering (CNS1, GB1, Japan1, or Korea1) %%Image Name Filename */ static void create_page(char *input) @@ -126,6 +158,11 @@ static void create_page(char *input) s = fz_strsep(&p, " "); add_font_res(resources, s, p); } + else if (!strcmp(s, "%%CJKFont")) + { + s = fz_strsep(&p, " "); + add_cjkfont_res(resources, s, p); + } else if (!strcmp(s, "%%Image")) { s = fz_strsep(&p, " "); -- cgit v1.2.3