1 /*
2  * Copyright (C) 1997-2005, R3vis Corporation.
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
17  * USA, or visit http://www.gnu.org/copyleft/lgpl.html.
18  *
19  * Original Contributor:
20  *   Wes Bethel, R3vis Corporation, Marin County, California
21  * Additional Contributor(s):
22  *
23  * The OpenRM project is located at http://openrm.sourceforge.net/.
24  */
25 /*
26  * $Id: rmtext.c,v 1.5 2005/02/19 16:40:20 wes Exp $
27  * Version: $Name: OpenRM-1-6-0-2-RC2 $
28  * $Revision: 1.5 $
29  * $Log: rmtext.c,v $
30  * Revision 1.5  2005/02/19 16:40:20  wes
31  * Distro sync and consolidation.
32  * Repairs to fix memory leak associated with repeated calls to rmPipeNew,
33  * rmPipeMakeCurrent, rmPipeClose.
34  *
35  * Revision 1.4  2005/01/23 17:00:22  wes
36  * Copyright updated to 2005.
37  *
38  * Revision 1.3  2004/01/16 16:48:35  wes
39  * Updated copyright line for 2004.
40  *
41  * Revision 1.2  2003/02/02 02:07:16  wes
42  * Updated copyright to 2003.
43  *
44  * Revision 1.1.1.1  2003/01/28 02:15:23  wes
45  * Manual rebuild of rm150 repository.
46  *
47  * Revision 1.11  2003/01/16 22:21:17  wes
48  * Updated all source files to reflect new organization of header files:
49  * all header files formerly located in include/rmaux, include/rmi, include/rmv
50  * are now located in include/rm.
51  *
52  * Revision 1.10  2002/04/30 19:33:49  wes
53  * Updated copyright dates.
54  *
55  * Revision 1.9  2001/10/15 00:12:59  wes
56  * Added a routine to copy all salient fields from one RMtextProps
57  * object to another.
58  *
59  * Revision 1.8  2001/07/15 16:20:14  wes
60  * Fixed bug associated with font emboldening and italicization.
61  *
62  * Revision 1.7  2001/03/31 17:12:39  wes
63  * v1.4.0-alpha-2 checkin.
64  *
65  * Revision 1.6  2000/12/03 22:35:38  wes
66  * Mods for thread safety.
67  *
68  * Revision 1.5  2000/10/03 11:40:28  wes
69  * Contributions from jdb - prototype cleanups.
70  *
71  * Revision 1.4  2000/08/23 23:30:29  wes
72  * Changed embolden and italicization parms from ints to RMenums
73  * on rmTextPropsGetAttribs.
74  *
75  * Revision 1.3  2000/05/17 14:25:13  wes
76  * Fixed compile warnings on rmTextPropsSet/GetAttribs().
77  *
78  * Revision 1.2  2000/04/20 16:29:47  wes
79  * Documentation additions/enhancements, some code rearragement.
80  *
81  * Revision 1.1.1.1  2000/02/28 21:29:40  wes
82  * OpenRM 1.2 Checkin
83  *
84  * Revision 1.1.1.1  2000/02/28 17:18:48  wes
85  * Initial entry - pre-RM120 release, source base for OpenRM 1.2.
86  *
87  */
88 
89 #include <rm/rm.h>
90 #include "rmprivat.h"
91 
92 /*
93  * ----------------------------------------------------
94  * @Name rmTextPropsSetAttribs
95  @pstart
96  RMenum rmTextPropsSetAttribs (RMtextProps *toModify,
97 		               int fontEnum,
98 			       int sizeEnum,
99 			       RMenum boldEnum,
100 			       RMenum italicEnum,
101 			       RMenum hJustifyEnum,
102 			       RMenum vJustifyEnum)
103 
104  @pend
105 
106  @astart
107  RMtextProps *toModify - a handle to an RMtextProps object (modified).
108 
109  int fontEnum - an integer value that specifies a font. Must be one of
110     RM_FONT_SERIF, RM_FONT_SANS, RM_FONT_MONO, RM_FONT_SYMBOL or
111     RM_FONT_DINGBATS (input).
112 
113  int sizeEnum - an integer value that specifies a typeface size. Must
114     be one of RM_FONT_XXS, RM_FONT_XS, RM_FONT_S, RM_FONT_M,
115     RM_FONT_L, RM_FONT_XL or RM_FONT_XXL (input).
116 
117  RMenum boldEnum - an integer value that indicates if an emboldened
118     typeface should be used. Must be either RM_TRUE or RM_FALSE
119     (input).
120 
121  RMenum italicEnum - an integer value that specifies if an italicized
122     typeface should be used. Must be either RM_TRUE or RM_FALSE
123     (input).
124 
125  RMenum hJustifyEnum - an RMenum value that dicates a horizontal
126     justification policy for text. Must be one of RM_LEFT, RM_CENTER
127     or RM_RIGHT (input).
128 
129  RMenum vJustifyEnum - an RMenum value that dictates a vertical
130     justification policy for text. Must be one of RM_BOTTOM, RM_CENTER
131     or RM_TOP (input).
132  @aend
133 
134  @dstart
135 
136  Typeface properties in RM are specified by assiging an RMtextProps
137  object to a scene graph node as a scene parameter. All descendent
138  nodes that contain text will be rendered according to the
139  specifications contained in the RMtextProps object. The intent of
140  this object is to provide control over text rendering across all
141  supported platforms with a single set of parameters.
142 
143  This routine modifies an RMtextProps object to reflect the
144  caller-supplied parameters. RM_CHILL is returned upon success, or
145  RM_WHACKED upon failure.
146 
147  Use rmTextPropsNew to create a new RMtextProps object, or
148  rmTextPropsDelete to delete an old one that is no longer needed.
149 
150  fontEnum specifies a typeface family. On the X11 platform,
151  RM_FONT_SERIF corresponds to "adobe-times," RM_FONT_SANS to
152  "adobe-helvetica," RM_FONT_MONO to "adobe-courier," RM_FONT_SYMBOL to
153  "adobe-symbol" and RM_FONT_DINGBATS to "-*-*-zapfdingbats". On the
154  Win32 platform, the values of "times", "helvetica", "courier",
155  "symbol" and "zapfdingbats" are used.
156 
157  sizeEnum specifies a particular point size for the face. RM_FONT_XXS,
158  RM_FONT_XS, RM_FONT_S, RM_FONT_M, RM_FONT_L, RM_FONT_XL and
159  RM_FONT_XXL correspond to 8, 10, 12, 14, 18, 24 and 34 points,
160  respectively, on both Win32 and X11 platforms.
161 
162  boldEnum and italicEnum control emboldening and italicization of a
163  given typeface. These are specified with either RM_TRUE or RM_FALSE.
164  Specifying RM_TRUE turns on either emboldening or italicization,
165  while RM_FALSE turns them off.
166 
167  Justification control is provided in both the horizontal and vertical
168  directions. Text is positioned with the use of either a 2D or 3D
169  coordinate at the RMprimitive level. Justification controls where the
170  text string appears in relationship to the on-screen projection of
171  the vertex coordinate. Left-justified text will cause the text string
172  to appear to the right of the projected vertex. Right-justified text
173  will appear to the left of the project vertex. Similarly, RM_TOP will
174  cause the text string to appear below the projected vertex, and
175  RM_BOTTOM will cause the text string to appear above the projected
176  vertex.
177 
178  @dend
179  * ----------------------------------------------------
180  */
181 RMenum
rmTextPropsSetAttribs(RMtextProps * p,int font_enum,int size_enum,RMenum bold_enum,RMenum italic_enum,RMenum hJustify,RMenum vJustify)182 rmTextPropsSetAttribs (RMtextProps *p,
183 		       int font_enum,
184 		       int size_enum,
185 		       RMenum bold_enum,
186 		       RMenum italic_enum,
187 		       RMenum hJustify,
188 		       RMenum vJustify)
189 {
190    int    parmsOK = 1;
191    RMenum rstat = RM_CHILL;
192 
193    if (RM_ASSERT(p, "rmTextPropsSetAttribs() error: the input RMtextProps object pointer is NULL") == RM_WHACKED)
194       return(RM_WHACKED);
195 
196    if (!((font_enum == RM_FONT_SERIF) || (font_enum == RM_FONT_SANS) || (font_enum == RM_FONT_MONO) ||
197 	 (font_enum == RM_FONT_SYMBOL) || (font_enum == RM_FONT_DINGBATS)))
198       {
199 	 parmsOK = 0;
200 	 rmWarning("rmTextPropsSetAttribs error: the input font enumerator is not valid.");
201       }
202 
203    if (!((size_enum == RM_FONT_XXS) || (size_enum == RM_FONT_XS) || (size_enum == RM_FONT_S) || (size_enum == RM_FONT_M) ||
204 	 (size_enum == RM_FONT_L) || (size_enum == RM_FONT_L) || (size_enum == RM_FONT_XL) || (size_enum == RM_FONT_XXL)))
205       {
206 	 parmsOK = 0;
207 	 rmWarning("rmTextPropsSetAttribs error: the input size enumerator is not valid.");
208       }
209 
210    if (!((bold_enum == RM_TRUE) || (bold_enum == RM_FALSE)))
211       {
212 	 parmsOK = 0;
213 	 rmWarning("rmTextPropsSetAttribs error: the input embolden enumerator is neither RM_TRUE nor RM_FALSE.");
214       }
215 
216    if (!((italic_enum == RM_TRUE) || (italic_enum == RM_FALSE)))
217       {
218 	 parmsOK = 0;
219 	 rmWarning("rmTextPropsSetAttribs error: the input italicization enumerator is neither RM_TRUE nor RM_FALSE.");
220       }
221 
222    if (!((hJustify == RM_LEFT) || (hJustify == RM_CENTER) || (hJustify == RM_RIGHT)))
223       {
224 	 parmsOK = 0;
225 	 rmWarning("rmTextPropsSetAttribs error: the input horizontal justification enumerator is not one of RM_LEFT, RM_CENTER nor RM_FALSE.");
226       }
227 
228    if (!((vJustify == RM_TOP) || (vJustify == RM_CENTER) || (vJustify == RM_BOTTOM)))
229       {
230 	 parmsOK = 0;
231 	 rmWarning("rmTextPropsSetAttribs error: the input vertical justification enumerator is not one of RM_TOP, RM_CENTER nor RM_BOTTOM.");
232       }
233 
234    if (parmsOK == 1)
235       {
236 	 p->fontEnum = font_enum;
237 	 p->italicEnum = italic_enum;
238 	 p->boldEnum = bold_enum;
239 	 p->sizeEnum = size_enum;
240 	 p->hJustify = hJustify;
241 	 p->vJustify = vJustify;
242 	 rstat = RM_CHILL;
243       }
244    else
245       rstat = RM_WHACKED;
246 
247    return(rstat);
248 }
249 
250 
251 /*
252  * ----------------------------------------------------
253  * @Name rmTextPropsGetAttribs
254  @pstart
255  RMenum rmTextPropsGetAttribs (const RMtextProps *toQuery,
256 		               int *fontEnumReturn,
257 			       int *sizeEnumReturn,
258 			       RMenum *boldEnumReturn,
259 			       RMenum *italicEnumReturn,
260 			       RMenum *hJustifyReturn,
261 			       RMenum *vJustifyReturn)
262  @pend
263 
264  @astart
265  const RMtextProps *toQuery - a handle to an RMtextProps object
266     (input).
267 
268  int *fontEnumReturn, *sizeEnumReturn, *boldEnumReturn,
269     *italicEnumReturn - handles to return caller-supplied integers
270     (modified).
271 
272  RMenum hJustifyReturn, *vJustifyReturn - handles to return
273     caller-supplied RMenums (modified).  @aend
274 
275  @dstart
276 
277  Use this routine to obtain the current text properties from an
278  RMtextProps object. For each non-null RMenum parameter, the
279  corresponding attribute is copied from the RMtextProps object into
280  caller-supplied memory.
281 
282  Returns RM_CHILL upon success, or RM_WHACKED upon failure.
283 
284  See rmTextPropsSetAttributes for a description of the meaning of each
285  of the text property parameters.
286 
287  @dend
288  * ----------------------------------------------------
289  */
290 RMenum
rmTextPropsGetAttribs(const RMtextProps * p,int * font_enum,int * size_enum,RMenum * bold_enum,RMenum * italic_enum,RMenum * hJustify,RMenum * vJustify)291 rmTextPropsGetAttribs (const RMtextProps *p,
292 		       int *font_enum,
293 		       int *size_enum,
294 		       RMenum *bold_enum,
295 		       RMenum *italic_enum,
296 		       RMenum *hJustify,
297 		       RMenum *vJustify)
298 {
299     if (RM_ASSERT(p, "rmTextPropsGetAttribs() error: the input RMtextProps object pointer is NULL") == RM_WHACKED)
300 	return(RM_WHACKED);
301 
302     if (font_enum != NULL)
303 	*font_enum = p->fontEnum;
304 
305     if (size_enum != NULL)
306 	*size_enum = p->sizeEnum;
307 
308     if (bold_enum != NULL)
309 	*bold_enum = p->boldEnum;
310 
311     if (italic_enum != NULL)
312 	*italic_enum = p->italicEnum;
313 
314     if (hJustify != NULL)
315 	*hJustify = p->hJustify;
316 
317     if (vJustify != NULL)
318 	*vJustify = p->vJustify;
319 
320     return(RM_CHILL);
321 }
322 
323 
324 /*
325  *
326  * RM internal font registry info:
327  *
328  * there is a finite number of different fonts that are supported through
329  * the RM interface. The number is computed as the product of the
330  * number of font families with the number of font sizes and the number
331  * of font styles.
332  *
333  * The font registry is an array of length (font_styles * font_sizes *
334  *  font_styles). Each font registry object contains info about the
335  * font, once initialized. The info consists of an OpenGL display list
336  * base index and a boolean indicating whether or not the font has been
337  * "initialized" (OpenGL bitmap display lists built).
338  *
339  * The RM font registry represents the rectification between X11 and
340  * Win32 font handling. In Win32, the only way to render bitmap fonts
341  * in OpeNGL is via Wgl, and wgl won't let you have access to the
342  * raw bitmap data. Wgl encapsulates all rendered font bitmaps inside
343  * OpenGL display lists.
344  *
345  * the font registry mechanism is used by both X11 and Win32 versions
346  * of text rendering (and property querying) inside RM.
347  */
348 
349 /* PRIVATE */
350 RMfontRegistry *
private_rmFontRegistryNew(void)351 private_rmFontRegistryNew(void)
352 {
353    /* potential number of fonts available at once in RM */
354    int num = RM_NUM_FONT_FACES * RM_NUM_FONT_SIZES * RM_NUM_FONT_STYLES;
355    RMfontRegistry *f;
356 
357    f = (RMfontRegistry *)malloc(sizeof(RMfontRegistry)*num);
358 
359    if (f == NULL)
360        return(NULL);
361 
362    memset((void *)f, 0, sizeof(RMfontRegistry)*num);
363 
364    return(f);
365 }
366 
367 /* PRIVATE */
368 void
private_rmFontRegistryDelete(RMpipe * p,RMfontRegistry * fontRegistry)369 private_rmFontRegistryDelete(RMpipe *p,
370 			     RMfontRegistry *fontRegistry)
371 {
372     RMfontRegistry *fr;
373 #ifdef RM_WIN
374     HFONT           font;
375 #elif RM_X
376     Font            font;
377     XFontStruct     *xfs;
378 #endif
379     int             fontEnum;
380     int             sizeEnum;
381     int             italicEnum;
382     int             boldEnum;
383 
384     /* walk through all the font combinations, look for active fonts */
385     for (fontEnum=0; fontEnum<RM_NUM_FONT_FACES; fontEnum++)
386     {
387 	for (sizeEnum=0; sizeEnum<RM_NUM_FONT_SIZES; sizeEnum++)
388 	{
389 	    for (italicEnum=0; italicEnum<=1; italicEnum++)
390 	    {
391 		for (boldEnum=0; boldEnum<=1; boldEnum++)
392 		{
393 		    fr = private_rmFontRegistryEntry(fontEnum, sizeEnum,
394 						     italicEnum, boldEnum,
395 						     fontRegistry);
396 		    if (fr->initialized)
397 		    {
398 			glDeleteLists(fr->listbase, fr->listCount);
399 #ifdef RM_WIN
400 			font = (HFONT)(fr->fontinfo);
401 			DeleteObject(font);
402 #elif RM_X
403 			xfs = (XFontStruct *)(fr->fontinfo);
404 			font = xfs->fid;
405 			XFreeFont(rmxPipeGetDisplay(p), xfs);
406 #endif
407 		    }
408 		}
409 	    }
410 	}
411     }
412 
413    free(fontRegistry);
414 }
415 
416 /* PRIVATE */
417 int
private_rmFontRegistryIndex(int font_face,int font_size,int font_italic,int font_embolden)418 private_rmFontRegistryIndex (int font_face,
419 			     int font_size,
420 			     int font_italic,
421 			     int font_embolden)
422 {
423    /*
424     * compute an index into the font registry table from the input
425     * parms. this is a way of doing multidimensional array indexing.
426     */
427 
428     int i, indx, xsize, xysize;
429 
430     xsize = RM_NUM_FONT_STYLES;
431     xysize = xsize * RM_NUM_FONT_SIZES;
432 
433     i = 0;
434     if (font_italic == RM_TRUE)
435 	i |= 1;
436     if (font_embolden == RM_TRUE)
437         i |= 2;
438 
439     indx = (font_face * xysize) + (font_size * xsize) + i;
440     return(indx);
441 }
442 
443 
444 /* PRIVATE */
445 RMfontRegistry *
private_rmFontRegistryEntry(int font_face,int font_size,int font_italic,int font_embolden,RMfontRegistry * f)446 private_rmFontRegistryEntry (int font_face,
447 			     int font_size,
448 			     int font_italic,
449 			     int font_embolden,
450 			     RMfontRegistry *f)
451 {
452     int indx = private_rmFontRegistryIndex(font_face, font_size, font_italic, font_embolden);
453 
454     if (f == NULL)
455        return(NULL);
456 
457     return(f + indx);
458 }
459 
460 /* PRIVATE */
461 void
private_rmTextPropsCopy(const RMtextProps * s,RMtextProps * d)462 private_rmTextPropsCopy(const RMtextProps *s,
463 			RMtextProps *d)
464 {
465     d->fontEnum = s->fontEnum;
466     d->italicEnum = s->italicEnum;
467     d->boldEnum = s->boldEnum;
468     d->sizeEnum = s->sizeEnum;
469     d->hJustify = s->hJustify;
470     d->vJustify = s->vJustify;
471 }
472 /* EOF */
473