1if not modules then modules = { } end modules ['lpdf-fnt'] = {
2 version = 1.001,
3 comment = "companion to lpdf-ini.mkiv",
4 author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
5 copyright = "PRAGMA ADE / ConTeXt Development Team",
6 license = "see context related readme files"
7}
8
9
10
11local match, gmatch = string.match, string.gmatch
12local tonumber, rawget = tonumber, rawget
13
14local pdfreserveobject = lpdf.reserveobject
15local pdfincludechar = lpdf.includechar
16local pdfincludefont = lpdf.includefont
17local pdfreference = lpdf.reference
18
19local pdfe = lpdf.epdf
20
21local tobemerged = { }
22local trace_merge = false trackers.register("graphics.fonts",function(v) trace_merge = v end)
23local report_merge = logs.reporter("graphics","fonts")
24
25local function register(usedname,cleanname)
26 local cleanname = cleanname or fonts.names.cleanname(usedname)
27 local fontid = fonts.definers.internal { name = cleanname }
28 if fontid then
29 local objref = pdfreserveobject()
30 pdfincludefont(fontid)
31 if trace_merge then
32 report_merge("registering %a with name %a, id %a and object %a",usedname,cleanname,fontid,objref)
33 end
34 return {
35 id = fontid,
36 reference = objref,
37 indices = { },
38 cleanname = cleanname,
39 }
40 end
41 return false
42end
43
44function lpdf.registerfont(usedname,cleanname)
45 local v = register(usedname,cleanname)
46 tobemerged[usedname] = v
47 return v
48end
49
50table.setmetatableindex(tobemerged,function(t,k)
51 return lpdf.registerfont(k)
52end)
53
54local function finalizefont(v)
55 local indextoslot = fonts.helpers.indextoslot
56 if v then
57 local id = v.id
58 local n = 0
59 for i in next, v.indices do
60 local u = indextoslot(id,i)
61
62 n = n + 1
63 end
64 v.n = n
65 end
66end
67
68statistics.register("merged fonts", function()
69 if next(tobemerged) then
70 local t = { }
71 for k, v in table.sortedhash(tobemerged) do
72 t[#t+1] = string.formatters["%s (+%i)"](k,v.n)
73 end
74 return table.concat(t," ")
75 end
76end)
77
78function lpdf.finalizefonts()
79 for k, v in next, tobemerged do
80 finalizefont(v)
81 end
82end
83
84callback.register("font_descriptor_objnum_provider",function(name)
85 local m = rawget(tobemerged,name)
86 if m then
87
88 local r = m.reference or 0
89 if trace_merge then
90 report_merge("using object %a for font descriptor of %a",r,name)
91 end
92 return r
93 end
94 return 0
95end)
96
97local function getunicodes1(str,indices)
98 for s in gmatch(str,"beginbfrange%s*(.-)%s*endbfrange") do
99 for first, last, offset in gmatch(s,"<([^>]+)>%s+<([^>]+)>%s+<([^>]+)>") do
100 for i=tonumber(first,16),tonumber(last,16) do
101 indices[i] = true
102 end
103 end
104 end
105 for s in gmatch(str,"beginbfchar%s*(.-)%s*endbfchar") do
106 for old, new in gmatch(s,"<([^>]+)>%s+<([^>]+)>") do
107 indices[tonumber(old,16)] = true
108 end
109 end
110end
111
112local function getunicodes2(widths,indices)
113 for i=1,#widths,2 do
114 local start = widths[i]
115 local count = #widths[i+1]
116 if start and count then
117 for i=start,start+count-1 do
118 indices[i] = true
119 end
120 end
121 end
122end
123
124local function checkedfonts(pdfdoc,xref,copied,page)
125 local list = page.Resources.Font
126 local done = { }
127 for k, somefont in pdfe.expanded(list) do
128 if somefont.Subtype == "Type0" and somefont.Encoding == "Identity-H" then
129 local descendants = somefont.DescendantFonts
130 if descendants then
131 for i=1,#descendants do
132 local d = descendants[i]
133 if d then
134 local subtype = d.Subtype
135 if subtype == "CIDFontType0" or subtype == "CIDFontType2" then
136 local basefont = somefont.BaseFont
137 if basefont then
138 local fontname = match(basefont,"^[A-Z]+%+(.+)$")
139 local fontdata = tobemerged[fontname]
140 if fontdata then
141 local descriptor = d.FontDescriptor
142 if descriptor then
143 local okay = false
144 local widths = d.W
145 if widths then
146 getunicodes2(widths,fontdata.indices)
147 okay = true
148 else
149 local tounicode = somefont.ToUnicode
150 if tounicode then
151 getunicodes1(tounicode(),fontdata.indices)
152 okay = true
153 end
154 end
155 if okay then
156 local r = xref[descriptor]
157 done[r] = fontdata.reference
158 end
159 end
160 end
161 end
162 end
163 end
164 end
165 end
166 end
167 end
168 return next(done) and done
169end
170
171if pdfincludefont then
172
173 function lpdf.epdf.plugin(pdfdoc,xref,copied,page)
174 local done = checkedfonts(pdfdoc,xref,copied,page)
175 if done then
176 return {
177 FontDescriptor = function(xref,copied,object,key,value,copyobject)
178 local r = value[3]
179 local d = done[r]
180 if d then
181 return pdfreference(d)
182 else
183 return copyobject(xref,copied,object,key,value)
184 end
185 end
186 }
187 end
188 end
189
190else
191
192 function lpdf.epdf.plugin() end
193
194end
195
196lpdf.registerdocumentfinalizer(lpdf.finalizefonts)
197
198
199
200
201
202
203 |