Project

General

Profile

get-font-metrics.p

Roger Borrello, 03/18/2022 09:24 AM

Download (9.34 KB)

 
1
/*
2
** This program is free software: you can redistribute it and/or modify
3
** it under the terms of the GNU Affero General Public License as
4
** published by the Free Software Foundation, either version 3 of the
5
** License, or (at your option) any later version.
6
**
7
** This program is distributed in the hope that it will be useful,
8
** but WITHOUT ANY WARRANTY; without even the implied warranty of
9
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10
** GNU Affero General Public License for more details.
11
**
12
** You may find a copy of the GNU Affero GPL version 3 at the following
13
** location: https://www.gnu.org/licenses/agpl-3.0.en.html
14
** 
15
** Additional terms under GNU Affero GPL version 3 section 7:
16
** 
17
**   Under Section 7 of the GNU Affero GPL version 3, the following additional
18
**   terms apply to the works covered under the License.  These additional terms
19
**   are non-permissive additional terms allowed under Section 7 of the GNU
20
**   Affero GPL version 3 and may not be removed by you.
21
** 
22
**   0. Attribution Requirement.
23
** 
24
**     You must preserve all legal notices or author attributions in the covered
25
**     work or Appropriate Legal Notices displayed by works containing the covered
26
**     work.  You may not remove from the covered work any author or developer
27
**     credit already included within the covered work.
28
** 
29
**   1. No License To Use Trademarks.
30
** 
31
**     This license does not grant any license or rights to use the trademarks
32
**     Golden Code, FWD, any Golden Code or FWD logo, or any other trademarks
33
**     of Golden Code Development Corporation. You are not authorized to use the
34
**     name Golden Code, FWD, or the names of any author or contributor, for
35
**     publicity purposes without written authorization.
36
** 
37
**   2. No Misrepresentation of Affiliation.
38
** 
39
**     You may not represent yourself as Golden Code Development Corporation or FWD.
40
** 
41
**     You may not represent yourself for publicity purposes as associated with
42
**     Golden Code Development Corporation, FWD, or any author or contributor to
43
**     the covered work, without written authorization.
44
** 
45
**   3. No Misrepresentation of Source or Origin.
46
** 
47
**     You may not represent the covered work as solely your work.  All modified
48
**     versions of the covered work must be marked in a reasonable way to make it
49
**     clear that the modified work is not originating from Golden Code Development
50
**     Corporation or FWD.  All modified versions must contain the notices of
51
**     attribution required in this license.
52
*/
53
/*
54
Each line in the font file has this format: name,size,bold,italic,underline.
55
where:".
56
- name: is the font name (case insensitive)
57
- size: is the font size for which metrics will be captured, integer. if not specified, metrics from 1 to maxSize are captured
58
- bold: true if the bold metrics are captured. false otherwise
59
- italic: true if the italic metrics are captured. false otherwise
60
- underline: true if the underline metrics are captured. false otherwise
61

    
62
If any of the bold/italic/underline flags are missing, metrics for all combinations of flag set/unset are captured.
63
*/
64

    
65
def var maxSize as int init 20.
66
def stream fnames.
67
def stream frpt.
68
def var showdpiwarning as log init true.
69
def var asXml as log init true.
70
def var fontFile as char init "font-list.txt".
71

    
72
message "Enter the maximum font size (<= 1638):" update maxSize.
73
message "Enter the file name with the font list:" update fontFile format "x(32)".
74

    
75
file-info:file-name = fontFile.
76
if file-info:file-type = ? then do:
77
   message "File" fontFile "does not exist or is not accessible".
78
   return.
79
end.
80

    
81
procedure CreateFontIndirectA external "gdi32".
82
   def input param lplf as long.
83
   def return param hfont as long.
84
end.
85

    
86
procedure DeleteObject external "gdi32".
87
   def input param hgdiobj as long.
88
   def return param res as long.
89
end.
90

    
91
procedure SelectObject external "gdi32".
92
   def input param hdc as long.
93
   def input param hgdiobj as long.
94
   def return param res as long.
95
end.
96

    
97
procedure GetTextMetricsA external "gdi32".
98
   def input param hdc as long.
99
   def input param lptm as long.
100
   def return param returnvalue as long.
101
end.
102

    
103
procedure GetDC external "user32.dll".
104
   def input param ihwnd as long.
105
   def return param hdc as long.
106
end.
107

    
108
procedure ReleaseDC external "user32.dll".
109
   def input param ihwnd as long.
110
   def input param hdc as long.
111
   def return param res as long.
112
end.
113

    
114
procedure GetDeviceCaps external "gdi32".
115
   def input param hdc as long.
116
   def input param nindex as long.
117
   def return param res as long.
118
end.
119

    
120
procedure getMetrics.
121
   def input param fontname as char.
122
   def input param fontsize as int.
123
   def input-output param lp as memptr.
124
   def input param fbold as log.
125
   def input param fitalic as log.
126
   def input param funderline as log.
127

    
128
   def var res as int.
129
   def var hdc as integer.
130
   def var dpi as int.
131
   def var LOGPIXELSY as int init 90.
132
   def var err as log init false.
133
   
134
   run GetDc(input current-window:hwnd, output hdc).
135

    
136
   /* get DPI */
137
   run GetDeviceCaps(input hdc, input LOGPIXELSY, output dpi).
138
   if showdpiwarning and dpi <> 96
139
   then do:
140
      message "DPI is" dpi "instead of 96!" view-as alert-box.
141
      showdpiwarning = false.
142
   end.
143
   
144
   /* create font */
145
   def var hfont as int64.
146
   def var lplf as memptr.
147
   set-size(lplf) = 5 * 4 + 8 * 1 + 1 * 32.
148
   def var i as int.
149
   do i = 1 to get-size(lplf):
150
     put-byte(lplf, i) = 0.
151
   end.
152
   put-long(lplf, (1 - 1) * 4 + 1) = -1 * int64(round(fontsize * dpi / 72.0, 2)).
153
   put-long(lplf, (5 - 1) * 4 + 1) = (if fbold then 700 else 0).
154
   put-byte(lplf, 5 * 4 + 1) = (if fitalic then 1 else 0).
155
   put-byte(lplf, 5 * 4 + 2) = (if funderline then 1 else 0).
156
   put-string(lplf, 5 * 4 + 8 + 1) = fontname.
157
   run CreateFontIndirectA(input get-pointer-value(lplf), output hfont).
158

    
159
   /* select font */
160
   def var foohdc as integer.
161
   run SelectObject(input hdc, input hfont, output foohdc).
162

    
163
   /* get metrics */
164
   set-size(lp) = 15 * 4 + 5 + 10.
165
   run GetTextMetricsA(input hdc, input get-pointer-value(lp), output res).
166
   if res = 0 then err = yes.
167

    
168
   /* delete hfont */
169
   run DeleteObject(input hfont, output res).
170
   if res = 0 then err = yes.
171

    
172
   run ReleaseDC(input current-window:hwnd, input hdc, output res).
173
   if res = 0 then err = yes.
174
   
175
   /* delete the lplf */
176
   set-size(lplf) = 0.
177
   
178
   if err
179
   then do:
180
      message "GetTextMetrics failed for" fontname fontsize ". Memory leak?".
181
      quit.
182
   end.
183
   
184
end.
185

    
186
procedure recordMetrics.
187
   def input param fname as char.
188
   def input param sz as int.
189
   def input param fbold as log.
190
   def input param fitalic as log.
191
   def input param funderline as log.
192
   
193
   def var lp as memptr.
194
   def var h as int.
195
   def var avgWidth as int.
196
   def var maxWidth as int.
197

    
198
   run getMetrics(fname, sz, input-output lp, fbold, fitalic, funderline).
199
   h = get-long(lp, 1).
200
   avgWidth = get-long(lp, 5 * 4 + 1).
201
   maxWidth = get-long(lp, 6 * 4 + 1).
202

    
203
   if asXml then do:
204
     put stream frpt unformatted space(3)
205
     '<font name="' fname '" '
206
           'size="' sz '" '
207
           'bold="' trim(string(fbold, "true/false")) '" '
208
           'italic="' trim(string(fitalic, "true/false")) '" '
209
           'underline="' trim(string(funderline, "true/false")) '" '
210
           'width="' avgWidth '" '
211
           'max-width="' maxWidth '" '
212
           'height="' h '"/>'  skip.
213
   end.
214
   else do:
215
     put stream frpt unformatted 
216
        fname space(1) 
217
        sz    space(1) 
218
        trim(string(fbold, "true/false")) space(1) 
219
        trim(string(fitalic, "true/false")) space(1) 
220
        trim(string(funderline, "true/false")) space(1) 
221
        avgWidth space(1) 
222
        h skip.
223
   end.
224
   /* delete the lp */
225
   set-size(lp) = 0.
226
end.
227

    
228
def var sz as int.
229
def var fname as char.
230
def var fxmlname as char.
231
fxmlname = (if asXml then "font-metrics.xml" else "font-metrics.csv").
232

    
233
form fname label "Font Name" sz label "Size" with frame fstate down.
234

    
235
output stream frpt to value(fxmlname).
236
input stream fnames from value(fontFile).
237

    
238
if asXml 
239
then do:
240
   put stream frpt unformatted '<?xml version="1.0" encoding="UTF-8"?>' skip.
241
   put stream frpt unformatted '<!DOCTYPE font-list SYSTEM "font-metrics.dtd">' skip.
242
   put stream frpt unformatted "<font-list>" skip.
243
end.
244

    
245
repeat:
246
   def var fsize as int.
247
   def var fbold as log.
248
   def var fitalic as log.
249
   def var funder as log.
250

    
251
   fname = ?.
252
   fsize = ?.
253
   fbold = ?.
254
   fitalic = ?.
255
   funder = ?.
256

    
257
   import stream fnames delimiter "," fname fsize fbold fitalic funder no-error.
258
   if error-status:error then leave.
259

    
260
   do sz = (if fsize = ? or fsize = 0 then 1 else fsize) to (if fsize = ? or fsize = 0 then maxSize else fsize):
261
     display fname sz with frame fstate.
262

    
263
     def var i as int.
264
     do i = 1 to 8:
265
        def var cbold as log.
266
        def var citalic as log.
267
        def var cunder as log.
268

    
269
        cbold = (i > 4).
270
        citalic = (i = 3 or i = 4 or i = 7 or i = 8).
271
        cunder = i mod 2 = 0.
272

    
273
        if (fbold   = ? or fbold   = cbold)  and
274
           (fitalic = ? or fitalic = citalic)and
275
           (funder  = ? or funder  = cunder)
276
        then run recordMetrics(fname, sz, cbold, citalic, cunder).
277
     end.
278
   end.
279

    
280
   down 1 with frame fstate.
281

    
282
   /* force a flush */
283
   output stream frpt close.
284
   output stream frpt to value(fxmlname) append.
285
end.
286

    
287
if asXml then put stream frpt unformatted "</font-list>" skip.
288

    
289
output stream frpt close.
290
input stream fnames close.
291

    
292
message "The metrics were captured in file:" fxmlname.