add the method to measure the char's metrics
Some checks are pending
CI / Julia 1.6 - ubuntu-latest - x64 (push) Waiting to run
CI / Julia 1.7 - ubuntu-latest - x64 (push) Waiting to run
CI / Julia pre - ubuntu-latest - x64 (push) Waiting to run

This commit is contained in:
Tan, Kian-ting 2025-01-29 16:07:26 +08:00
parent 5b8bf872a2
commit eb3f1967aa
4 changed files with 109 additions and 32 deletions

View file

@ -1,5 +1,5 @@
{@lang|en} {@lang|en}
{@def|@font|{@quote|FreeSans|AR PL Kaiti M}} {@def|@font|{@quote|FreeSans|AR PL UKai TW}}
{@def|@fontsize|12} {@def|@fontsize|12}
therapy of communication and pronounciation123%comment therapy of communication and pronounciation123%comment

View file

@ -1,5 +1,10 @@
module Interp module Interp
using Match using Match
using Fontconfig
include("pdfoperating.jl")
using .PDFOperating
u = Main.uahgi u = Main.uahgi
c = Main.uahgi.Parsing.Passes.Classes 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.SEQ([c.ELE([c.ID("def")]),
c.ELE([c.ID(id)]),val]) => c.ELE([c.ID(id)]),val]) =>
begin begin
(val_evaled, env, res_box) = interp(val, env, res_box) (val_evaled, env, res_box) = interp(val, env, res_box, false)
println("ID~~~", id, " VAL~~~", val_evaled) #println("ID~~~", id, " VAL~~~", val_evaled)
env[id] = val_evaled env[id] = val_evaled
return (val_evaled, env, res_box) return (val_evaled, env, res_box)
end end
@ -34,7 +39,7 @@ function interp(ast, env, res_box, put_char=true)
y...]) => begin y...]) => begin
list = map(x -> x[1], list = map(x -> x[1],
map(x -> interp(x, env, res_box), y)) map(x -> interp(x, env, res_box), y))
println("QUOTE", list) #println("QUOTE", list)
return (list, env, res_box) return (list, env, res_box)
end end
@ -45,16 +50,41 @@ function interp(ast, env, res_box, put_char=true)
end end
c.CHAR(ch) => begin c.CHAR(ch) => begin
ret = ch atomic_ch = ch[1]
if put_char == true 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, push!(res_box.eles[end].eles,
#=TODO: check single-char size u.ChBox(ch,
env[""] font_path,
=# font_size,
u.ChBox(ch, "foo", 20, 1, 2, 3)) glyph_metrics.ht,
glyph_metrics.dp,
glyph_metrics.wd))
end end
return (ret, env, res_box) return (ch, env, res_box)
end end
c.NL(nl) => return (nl, env, res_box) c.NL(nl) => return (nl, env, res_box)
c.SPACE(sp) => return (sp, 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
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 end

View file

@ -9,14 +9,14 @@ using TeX-like metrics, in px
- depth - depth
""" """
struct CharMetrics struct CharMetrics
height::Float64 ht::Float64
width::Float64 dp::Float64
depth::Float64 wd::Float64
end end
#the default path is Noto Serif CJK Regular #the default path is Noto Serif CJK Regular
default_font_path = "src/thirdParty/fonts/noto/NotoSerifTC-Regular.ttf" #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/linuxLibertine/LinLibertine_Rah.ttf"
function createPDF() function createPDF()
#=returns pdf=# #=returns pdf=#
@ -93,7 +93,7 @@ function check_char_size(char, font_path, font_size, font_index=0)
library = Vector{FT_Library}(undef, 1) library = Vector{FT_Library}(undef, 1)
error = FT_Init_FreeType(library) error = FT_Init_FreeType(library)
face = Ref{FT_Face}() 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) glyph_index = FT_Get_Char_Index(face[], char)
FT_Load_Glyph(face[], glyph_index, FT_LOAD_NO_SCALE) FT_Load_Glyph(face[], glyph_index, FT_LOAD_NO_SCALE)
faceRec = unsafe_load(face[]) 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 #from baseline down to the bottom of the glyph
depth = metricToPx(metrics.height - metrics.horiBearingY, font_size) 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 end
""" """
@ -121,18 +118,18 @@ function metricToPx(metric, size_pt)
return metric * size_pt / 750 return metric * size_pt / 750
end end
pdf = createPDF() #pdf = createPDF()
page = addPage(pdf) #page = addPage(pdf)
font = load_font(pdf, default_font_path) #font = load_font(pdf, default_font_path)
put_text(page, "上下abc", font, 15, 100, 200) #put_text(page, "上下abc", font, 15, 100, 200)
put_text(page, "天地人", font, 15, 200, 200) #put_text(page, "天地人", font, 15, 200, 200)
save_pdf(pdf, "text.pdf") #save_pdf(pdf, "text.pdf")
println("PDF generated.") #println("PDF generated.")
check_char_size( #check_char_size(
'j', # '安',
default_font_path, # default_font_path,
20) # 20)
end end

BIN
text.pdf

Binary file not shown.