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