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