-
Notifications
You must be signed in to change notification settings - Fork 10
/
ttf_font.v
188 lines (167 loc) · 5.03 KB
/
ttf_font.v
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
module pdf
import x.ttf
import os
import strings
import compress.zlib
/******************************************************************************
*
* TTF font management
*
******************************************************************************/
@[heap]
struct TtfFontRsc {
pub mut:
id_font_file int
id_font int
id_font_desc int
tf ttf.TTF_File
font_name_id int
font_name string
full_name string
pdf_font_id int
pdf_font_descriptor_id int
pdf_ttffont_file_id int
flags u16
first_char int = 1
last_char int
widths []int
fontbbox []int
ascent int
descent int
}
/*
fn get_ttf_widths(mut tf ttf.TTF_File) []int {
count := tf.glyph_count()
mut widths := []int
for i in 0..count {
x_min, x_max, _, _ := tf.read_glyph_dim(i)
widths << (x_max - x_min) * 0
}
return widths
}
*/
fn render_ttf_files(mut res_c strings.Builder, tf TtfFontRsc) !int {
buf := zlib.compress(tf.tf.buf) or { return error('compress failed') }
res_c.write('${tf.id_font_file} 0 obj\n'.bytes())!
// mandatory fields in a compress obj stream
res_c.write('<</Lenght1 ${tf.tf.buf.len} /Length ${buf.len + 1} /Filter/FlateDecode>>\n'.bytes())!
res_c.write('stream\n'.bytes())!
res_c.write(buf)!
res_c.write('\nendstream\n'.bytes())!
res_c.write('endobj\n\n'.bytes())!
return int(res_c.len)
}
fn render_ttf_font(mut res_c strings.Builder, tf TtfFontRsc) !int {
widths := pdf_format_width(tf.widths)!
full_name := tf.full_name.replace(' ', '_')
res_c.write('${tf.id_font} 0 obj\n'.bytes())!
res_c.write('<<
/Type/Font
/Name/${tf.font_name}
/Subtype/TrueType
/BaseFont/${full_name}
/Encoding/WinAnsiEncoding
/FirstChar ${tf.first_char}
/LastChar ${tf.last_char}
/FontDescriptor ${tf.id_font_desc} 0 R
/Widths${widths}
>>
endobj\n
'.bytes())!
return int(res_c.len)
}
// /Widths${widths}
fn render_ttf_font_decriptor(mut res_c strings.Builder, tf TtfFontRsc) !int {
mut panose := ''
for p_val in tf.tf.panose_array {
panose += '${p_val} '
}
full_name := tf.full_name.replace(' ', '_')
fontbbox := pdf_format_width(tf.fontbbox)!
res_c.write('${tf.id_font_desc} 0 obj\n'.bytes())!
res_c.write('<<
/Type/FontDescriptor
/FontName/${full_name}
/FontBBox${fontbbox}
/Flags ${tf.flags}
/Ascent ${tf.ascent}
/Descent ${tf.descent}
/StemV 80
/ItalicAngle 0
/FontFile2 ${tf.id_font_file} 0 R
/Style << /Panose < ${panose} > >>
>>
endobj\n
'.bytes())!
return int(res_c.len)
}
fn pdf_format_width(w []int) !string {
mut bs := strings.new_builder(4096)
bs.write('['.bytes())!
for x in w {
bs.write(' ${x}'.bytes())!
}
bs.write(' ]'.bytes())!
return bs.str()
}
pub fn (mut p Pdf) load_ttf_font(font_path string, font_name string, width_scale f32) {
mut tf_rsc := TtfFontRsc{}
tf_rsc.id_font_file = p.id_count + 1
tf_rsc.id_font = p.id_count + 2
tf_rsc.id_font_desc = p.id_count + 3
p.id_count += 3
mut tf := ttf.TTF_File{}
tf.width_scale = width_scale
tf.buf = os.read_bytes(font_path) or { panic(err) }
// println('TrueTypeFont file [$font_path] len: $tf.buf.len')
tf.init()
tf_rsc.tf = tf
tf_rsc.flags = tf.flags
// println("desc:\n${tf}")
tf_rsc.fontbbox << int(tf.x_min)
tf_rsc.fontbbox << int(tf.y_min)
tf_rsc.fontbbox << int(tf.x_max)
tf_rsc.fontbbox << int(tf.y_max)
// println("FontBBox: ${tf_rsc.fontbbox}")
tf_rsc.ascent = tf.ascent
tf_rsc.descent = tf.descent
tf_rsc.widths, tf_rsc.first_char, tf_rsc.last_char = tf.get_ttf_widths()
// tf_rsc.first_char = 1
// tf_rsc.last_char = tf_rsc.widths.len
// println("Widths ${tf_rsc.widths.len} :${tf_rsc.widths}")
tf_rsc.font_name = font_name
tf_rsc.full_name = tf.full_name
p.ttf_font_used[font_name] = tf_rsc
// tf_rsc.render_font() or {println("Error")}
}
/*
pub fn (mut p TtfFontRsc) render_object() string {
return "
${pdf_font_id} 0 obj
<<
/LastChar 255
/BaseFont/GravitasOne
/Type/Font
/Subtype/TrueType
/Encoding/WinAnsiEncoding
/FirstChar 1
/Widths[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 369 445 468 722 863 908 911 268 478 478 509 522 399 524 396 461 878 572 802 797 751 809 824 750 817 824 396 399 398 526 398 752 1198 923 940 901 988 904 818 937 1093 604 641 1026 807 1078 911 952 901 952 991 863 849 924 878 1270 934 864 810 478 461 478 666 746 459 899 906 775 906 774 574 805 945 525 558 892 525 1356 945 824 920 906 773 761 604 932 765 1139 827 767 806 461 257 461 726 0 908 0 333 0 607 0 0 0 475 0 0 474 1290 0 0 0 0 333 333 602 602 475 637 1137 513 0 0 474 1189 0 0 0 369 445 775 895 674 864 257 724 459 873 582 743 617 524 873 459 466 523 542 515 459 932 678 396 459 408 558 743 955 1054 1015 752 923 923 923 923 923 923 1187 901 904 904 904 904 604 604 604 604 988 911 952 952 952 952 952 523 952 924 924 924 924 864 948 1013 899 899 899 899 899 899 1199 775 774 774 774 774 525 525 525 525 791 945 824 824 824 824 824 523 824 932 932 932 932 765 948 765]
/FontDescriptor ${pdf_font_descriptor_id} 0 R
>>
endobj
${pdf_font_descriptor_id} 0 obj
<<
/CapHeight 691
/FontBBox[-37 -326 1340 945]
/Type/FontDescriptor
/FontFile2 1 0 R
/Descent -326
/StemV 80
/Flags 32
/Ascent 945
/FontName/GravitasOne
/ItalicAngle 0
>>
"
}
*/