1 /*
2 Copyright (C) 2017-2021, Dirk Krause
3 SPDX-License-Identifier: BSD-3-Clause
4 */
5
6 /*
7 WARNING: This file was generated by the dkct program (see
8 http://dktools.sourceforge.net/ for details).
9 Changes you make here will be lost if dkct is run again!
10 You should modify the original source and run dkct on it.
11 Original source: dk4fontc.ctr
12 */
13
14 /** @file dk4fontc.c The dk4fontc module.
15 */
16
17
18 #include "dk4conf.h"
19
20 #ifndef DK4FONTC_H_INCLUDED
21 #include <libdk4gra/dk4fontc.h>
22 #endif
23
24 #ifndef DK4MEM_H_INCLUDED
25 #include <libdk4base/dk4mem.h>
26 #endif
27
28 #ifndef DK4UNUSED_H_INCLUDED
29 #include <libdk4base/dk4unused.h>
30 #endif
31
32 #ifndef DK4MATH_H_INCLUDED
33 #include <libdk4c/dk4math.h>
34 #endif
35
36 #ifndef DK4NUMCO_H_INCLUDED
37 #include <libdk4base/dk4numco.h>
38 #endif
39
40 #if DK4_HAVE_MATH_H
41 #ifndef MATH_H_INCLUDED
42 #if DK4_ON_WINDOWS
43 #ifndef _USE_MATH_DEFINES
44 #define _USE_MATH_DEFINES 1
45 #endif
46 #endif
47 #include <math.h>
48 #define MATH_H_INCLUDED 1
49 #endif
50 #endif
51
52 #ifndef GRA_H_INCLUDED
53 #include <libdk4gra/gra.h>
54 #endif
55
56 #if DK4_HAVE_ASSERT_H
57 #ifndef ASSERT_H_INCLUDED
58 #include <assert.h>
59 #define ASSERT_H_INCLUDED 1
60 #endif
61 #endif
62
63
64 /** Minimum size difference required to see different font sizes.
65 */
66 #define FNT_EPS 1.0e-4
67
68
69
70
71
72
73 /** Initialize a font item.
74 @param ptr Item to initialize.
75 */
76 static
77 void
dk4fontc_item_init(dk4_font_item_t * ptr)78 dk4fontc_item_init(dk4_font_item_t *ptr)
79 {
80
81 #if DK4_USE_ASSERT
82 assert(NULL != ptr);
83 #endif
84 dk4mem_reset(ptr, sizeof(dk4_font_item_t), NULL);
85 ptr->fsz = 0.0;
86 ptr->nf = (size_t)0UL;
87 ptr->fno = DK4_FONT_TIMES_ROMAN;
88 ptr->fex = DK4_GRA_TF_NONE_NONE;
89
90 }
91
92
93
94 static
95 int
dk4_font_item_equal_fex(const dk4_font_item_t * pl,const dk4_font_item_t * pr)96 dk4_font_item_equal_fex(
97 const dk4_font_item_t *pl,
98 const dk4_font_item_t *pr
99 )
100 {
101 int back = 0;
102 if (DK4_GRA_TF_NONE_NONE != pl->fex) {
103 switch (pl->fex) {
104 case DK4_GRA_TF_NONE_NONE : {
105 /* Intentionally empty to avoid compiler warnings. */
106 } break;
107 case DK4_GRA_TF_EXACT_SIZE : case DK4_GRA_TF_SIMILAR_SIZE : {
108 if (pl->fno > pr->fno) {
109 back = 1;
110 }
111 else {
112 if (pl->fno < pr->fno) {
113 back = -1;
114 }
115 }
116 if (0 == back) {
117 if (isgreater(pl->fsz, (FNT_EPS + pr->fsz))) {
118 back = 1;
119 }
120 else {
121 if (isgreater(pr->fsz, (FNT_EPS + pl->fsz))) {
122 back = -1;
123 }
124 }
125 }
126 } break;
127 case DK4_GRA_TF_EXACT_NONE : case DK4_GRA_TF_SIMILAR_NONE : {
128 if (pl->fno > pr->fno) {
129 back = 1;
130 }
131 else {
132 if (pl->fno < pr->fno) {
133 back = -1;
134 }
135 }
136 } break;
137 default : { /* DK4_GRA_TF_NONE_SIZE */
138 if (isgreater(pl->fsz, (FNT_EPS + pr->fsz))) {
139 back = 1;
140 }
141 else {
142 if (isgreater(pr->fsz, (FNT_EPS + pl->fsz))) {
143 back = -1;
144 }
145 }
146 } break;
147 }
148 }
149 return back;
150 }
151
152
153
154 /** Compare two font items by font number or by font id.
155 @param l Left font item.
156 @param r Right font item.
157 @param cr Comparison criteria (1=by number,0=normal).
158 @return Comparison result.
159 */
160 static
161 int
dk4_font_item_compare_by_fontno_and_size(const void * l,const void * r,int cr)162 dk4_font_item_compare_by_fontno_and_size(
163 const void *l,
164 const void *r,
165 int cr
166 )
167 {
168 int back = 0;
169 const dk4_font_item_t *pl; /* Left object */
170 const dk4_font_item_t *pr; /* Right object */
171
172
173 pl = (const dk4_font_item_t *)l;
174 pr = (const dk4_font_item_t *)r;
175 if (NULL != pl) {
176 if (NULL != pr) {
177 switch (cr) {
178 case 1 : {
179 if (pl->nf > pr->nf) {
180 back = 1;
181 }
182 else {
183 if (pl->nf < pr->nf) {
184 back = -1;
185 }
186 }
187 } break;
188 default : {
189 /*
190 First check domain (exact font or similar font)
191 */
192 if (pl->fex > pr->fex) {
193 back = 1;
194 }
195 else {
196 if (pl->fex < pr->fex) {
197 back = -1;
198 }
199 }
200 if (0 == back) {
201 back = dk4_font_item_equal_fex(pl, pr);
202 }
203 } break;
204 }
205 }
206 else {
207 back = 1;
208 }
209 }
210 else {
211 if (NULL != pr) {
212 back = -1;
213 }
214 }
215
216 return back;
217 }
218
219
220
221 /** Initialize new font collector.
222 @param ptr Font collector to initialize.
223 */
224 static
225 void
dk4fontc_init(dk4_font_collector_t * ptr)226 dk4fontc_init(dk4_font_collector_t *ptr)
227 {
228
229 #if DK4_USE_ASSERT
230 assert(NULL != ptr);
231 #endif
232 ptr->s_fo = ptr->s_fn = NULL;
233 ptr->i_fo = ptr->i_fn = NULL;
234 ptr->nfonts = 0;
235
236 }
237
238
239
240 void
dk4fontc_close(dk4_font_collector_t * fc)241 dk4fontc_close(
242 dk4_font_collector_t *fc
243 )
244 {
245 dk4_font_item_t *fi; /* Current font item to release */
246
247
248 #if DK4_USE_ASSERT
249 assert(NULL != fc);
250 #endif
251 if (NULL != fc) {
252 /*
253 s_fn only contains copy
254 */
255 if (NULL != fc->s_fn) {
256 if (NULL != fc->i_fn) {
257 dk4sto_it_close(fc->i_fn);
258 }
259 dk4sto_close(fc->s_fn);
260 }
261 fc->s_fn = NULL;
262 fc->i_fn = NULL;
263 /*
264 s_fo contains the real data, we must delete here
265 */
266 if (NULL != fc->s_fo) {
267 if (NULL != fc->i_fo) {
268 dk4sto_it_reset(fc->i_fo);
269 do {
270 fi = (dk4_font_item_t *)dk4sto_it_next(fc->i_fo);
271 if (NULL != fi) {
272
273 dk4mem_free(fi);
274 }
275 } while(NULL != fi);
276 }
277 dk4sto_close(fc->s_fo);
278 }
279 fc->s_fo = NULL;
280 fc->i_fo = NULL;
281 dk4fontc_init(fc);
282 dk4mem_free(fc);
283 }
284
285 }
286
287
288
289 dk4_font_collector_t *
dk4fontc_open(dk4_er_t * erp)290 dk4fontc_open(
291 dk4_er_t *erp
292 )
293 {
294 dk4_font_collector_t *back = NULL;
295 int ok = 0;
296
297
298 back = dk4mem_new(dk4_font_collector_t,1,erp);
299 if (NULL != back) {
300 dk4fontc_init(back);
301 back->s_fo = dk4sto_open(erp);
302 back->s_fn = dk4sto_open(erp);
303 if ((NULL != back->s_fo) && (NULL != back->s_fn)) {
304 dk4sto_set_comp(
305 back->s_fo, dk4_font_item_compare_by_fontno_and_size, 0
306 );
307 dk4sto_set_comp(
308 back->s_fn, dk4_font_item_compare_by_fontno_and_size, 1
309 );
310 back->i_fo = dk4sto_it_open(back->s_fo, erp);
311 back->i_fn = dk4sto_it_open(back->s_fn, erp);
312 if ((NULL != back->i_fo) && (NULL != back->i_fn)) {
313 ok = 1;
314 }
315 }
316 if (0 == ok) {
317 dk4fontc_close(back);
318 back = NULL;
319 }
320 }
321
322 return back;
323 }
324
325
326
327 int
dk4fontc_add_font(size_t * pdst,dk4_font_collector_t * fc,int fno,double fsz,int fex,dk4_er_t * erp)328 dk4fontc_add_font(
329 size_t *pdst,
330 dk4_font_collector_t *fc,
331 int fno,
332 double fsz,
333 int fex,
334 dk4_er_t *erp
335 )
336 {
337 dk4_font_item_t tv; /* Test value */
338 dk4_font_item_t *ptr; /* Item found */
339 dk4_font_number_t rfno; /* Real font number */
340 int back = 0; /* Function result */
341
342
343 #if DK4_USE_ASSERT
344 assert(NULL != fc);
345 assert(NULL != pdst);
346 assert(0 <= fno);
347 assert(0.0 < fsz);
348 #endif
349 /*
350 Check command line arguments
351 */
352 if ((NULL == pdst) || (NULL == fc) || (0 > fno) || (0.0 >= fsz)) {
353 dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
354 }
355 else {
356 /* Initialize search record
357 */
358 dk4fontc_item_init(&tv);
359 tv.fsz = fsz;
360 tv.nf = 0;
361 tv.fex = fex;
362 rfno = dk4font_number_from_int(fno);
363 switch (fex) {
364 case DK4_GRA_TF_SIMILAR_NONE : case DK4_GRA_TF_SIMILAR_SIZE : {
365 tv.fno = dk4font_get_features(rfno);
366 } break;
367 default : {
368 tv.fno = fno;
369 } break;
370 }
371 /*
372 Search
373 */
374 ptr = (dk4_font_item_t *)dk4sto_it_find_like(fc->i_fo, &tv, 0);
375 /*
376 Success if found, otherwise create new entry
377 */
378 if (NULL != ptr) {
379 back = 1;
380 *pdst = ptr->nf;
381 }
382 else {
383 if (SIZE_MAX > fc->nfonts) {
384 ptr = dk4mem_new(dk4_font_item_t,1,erp);
385 if (NULL != ptr) {
386 DK4_MEMCPY(ptr,&tv,sizeof(dk4_font_item_t));
387 ptr->nf = fc->nfonts;
388 if (0 != dk4sto_add(fc->s_fo, ptr, erp)) {
389 fc->nfonts += 1;
390 if (0 != dk4sto_add(fc->s_fn, ptr, erp)) {
391 back = 1;
392 *pdst = ptr->nf;
393 }
394 }
395 else {
396 dk4mem_free(ptr);
397 }
398 }
399 }
400 else {
401 dk4error_set_simple_error_code(erp, DK4_E_MATH_OVERFLOW);
402 }
403 }
404 }
405
406 return back;
407 }
408
409
410 /* vim: set ai sw=4 ts=4 : */
411