diff --git a/example/ex1.ug b/example/ex1.ug index 3e279d9..9c54c74 100644 --- a/example/ex1.ug +++ b/example/ex1.ug @@ -1,5 +1,5 @@ {@lang|en} -{@def|@font|{@quote|FreeSans|AR PL Kaiti M}} +{@def|@font|{@quote|FreeSans|AR PL UKai TW}} {@def|@fontsize|12} therapy of communication and pronounciation123%comment diff --git a/src/interp.jl b/src/interp.jl index 8d67125..b418600 100644 --- a/src/interp.jl +++ b/src/interp.jl @@ -1,5 +1,10 @@ module Interp using Match +using Fontconfig + +include("pdfoperating.jl") +using .PDFOperating + u = Main.uahgi c = Main.uahgi.Parsing.Passes.Classes @@ -25,8 +30,8 @@ function interp(ast, env, res_box, put_char=true) c.SEQ([c.ELE([c.ID("def")]), c.ELE([c.ID(id)]),val]) => begin - (val_evaled, env, res_box) = interp(val, env, res_box) - println("ID~~~", id, " VAL~~~", val_evaled) + (val_evaled, env, res_box) = interp(val, env, res_box, false) + #println("ID~~~", id, " VAL~~~", val_evaled) env[id] = val_evaled return (val_evaled, env, res_box) end @@ -34,7 +39,7 @@ function interp(ast, env, res_box, put_char=true) y...]) => begin list = map(x -> x[1], map(x -> interp(x, env, res_box), y)) - println("QUOTE", list) + #println("QUOTE", list) return (list, env, res_box) end @@ -45,16 +50,41 @@ function interp(ast, env, res_box, put_char=true) end c.CHAR(ch) => begin - ret = ch + atomic_ch = ch[1] + if put_char == true + + font_idx = 1 + font_family = string(env["font"][font_idx]) + font_family_length = length(font_family) + while !is_in_font(atomic_ch, font_family) + if font_idx <= font_family_length + font_idx += 1 + font_family = string(env["font"][font_idx]) + else + font_list = string(env["font"]) + throw("the chars $atomic_ch is not contained in all the fonts + listed in listed fonts: $font_list") + end + end + + + font_path = get_font_path(font_family) + font_size = parse(Int, env["fontsize"]) + glyph_metrics = PDFOperating.check_char_size( + atomic_ch, font_path, font_size) + + push!(res_box.eles[end].eles, - #=TODO: check single-char size - env[""] - =# - u.ChBox(ch, "foo", 20, 1, 2, 3)) + u.ChBox(ch, + font_path, + font_size, + glyph_metrics.ht, + glyph_metrics.dp, + glyph_metrics.wd)) end - return (ret, env, res_box) - end + return (ch, env, res_box) + end c.NL(nl) => return (nl, env, res_box) c.SPACE(sp) => return (sp, env, res_box) @@ -66,4 +96,54 @@ function interp(ast, env, res_box, put_char=true) end end +function get_font_path(font_family) + ptn = Fontconfig.Pattern(family=font_family) + matched = Fontconfig.match(ptn) + path = match(r"file=([^:]+)", string(matched))[1] + return path +end + +""" +check if the glyph of a char is contained by `font_family` +""" +function is_in_font(char, font_family) + ptn = Fontconfig.Pattern(family=font_family) + matched = Fontconfig.match(ptn) + charset = match(r"charset=([^:]+)", string(matched))[1] + splitted1 = split(charset, " ") + splitted2 = map(x -> split(x, "-"), splitted1) + + """aux function""" + regex_aux(x) = map(y -> padding_zero(y), x) + + x1 = map(x -> regex_aux(x), splitted2) + x2 = map(x -> length(x) == 1 ? "\\u" * x[1] : "\\u" * x[1] * "-\\u" * x[2] , x1) + regex_final = "[" * reduce((x,y)-> x*""*y, x2) * "]" + regex_final_wrapped = Regex(regex_final) + + if match(regex_final_wrapped, string(char)) !== nothing + return true + else + return false + + end +end + +""" +padding zero for a hex-digit string `i` to make it a 4-digit. +- "27" -> "0027" +- "8af" -> "08af" +""" +function padding_zero(i) + if length(i) == 2 + i="00"*i + end + if length(i)==3 + i="0"*i + end + return i +end + + + end \ No newline at end of file diff --git a/src/pdfoperating.jl b/src/pdfoperating.jl index 89f6592..3857ab5 100644 --- a/src/pdfoperating.jl +++ b/src/pdfoperating.jl @@ -9,14 +9,14 @@ using TeX-like metrics, in px - depth """ struct CharMetrics - height::Float64 - width::Float64 - depth::Float64 + ht::Float64 + dp::Float64 + wd::Float64 end #the default path is Noto Serif CJK Regular -default_font_path = "src/thirdParty/fonts/noto/NotoSerifTC-Regular.ttf" -#default_font_path = "src/thirdParty/fonts/linuxLibertine/LinLibertine_Rah.ttf" +#default_font_path = "src/thirdParty/fonts/noto/NotoSerifTC-Regular.ttf" +default_font_path = "src/thirdParty/fonts/linuxLibertine/LinLibertine_Rah.ttf" function createPDF() #=returns pdf=# @@ -93,7 +93,7 @@ function check_char_size(char, font_path, font_size, font_index=0) library = Vector{FT_Library}(undef, 1) error = FT_Init_FreeType(library) face = Ref{FT_Face}() - FT_New_Face(library[1], font_path, font_index, face); + FT_New_Face(library[1], string(font_path), 0, face) glyph_index = FT_Get_Char_Index(face[], char) FT_Load_Glyph(face[], glyph_index, FT_LOAD_NO_SCALE) faceRec = unsafe_load(face[]) @@ -107,11 +107,8 @@ function check_char_size(char, font_path, font_size, font_index=0) #from baseline down to the bottom of the glyph depth = metricToPx(metrics.height - metrics.horiBearingY, font_size) - println("width ", width, "px") - println("height ", height, "px") - println("depth ", depth, "px") - return CharMetrics(height, width, depth) + return CharMetrics(height, depth, width) end """ @@ -121,18 +118,18 @@ function metricToPx(metric, size_pt) return metric * size_pt / 750 end -pdf = createPDF() -page = addPage(pdf) -font = load_font(pdf, default_font_path) -put_text(page, "上下abc", font, 15, 100, 200) -put_text(page, "天地人", font, 15, 200, 200) +#pdf = createPDF() +#page = addPage(pdf) +#font = load_font(pdf, default_font_path) +#put_text(page, "上下abc", font, 15, 100, 200) +#put_text(page, "天地人", font, 15, 200, 200) -save_pdf(pdf, "text.pdf") +#save_pdf(pdf, "text.pdf") -println("PDF generated.") -check_char_size( - 'j', - default_font_path, - 20) +#println("PDF generated.") +#check_char_size( +# '安', +# default_font_path, +# 20) end \ No newline at end of file diff --git a/text.pdf b/text.pdf index 57ab996..44b6d22 100644 Binary files a/text.pdf and b/text.pdf differ