Richard Boegli's CnC_Generals_Zero_Hour Fork WIP
This is documentation of Richard Boegil's Zero Hour Fork
 
Loading...
Searching...
No Matches
wwfont.cpp
Go to the documentation of this file.
1/*
2** Command & Conquer Generals Zero Hour(tm)
3** Copyright 2025 Electronic Arts Inc.
4**
5** This program is free software: you can redistribute it and/or modify
6** it under the terms of the GNU General Public License as published by
7** the Free Software Foundation, either version 3 of the License, or
8** (at your option) any later version.
9**
10** This program is distributed in the hope that it will be useful,
11** but WITHOUT ANY WARRANTY; without even the implied warranty of
12** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13** GNU General Public License for more details.
14**
15** You should have received a copy of the GNU General Public License
16** along with this program. If not, see <http://www.gnu.org/licenses/>.
17*/
18
19/***********************************************************************************************
20 *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
21 ***********************************************************************************************
22 * *
23 * Project Name : Command & Conquer *
24 * *
25 * $Archive:: /VSS_Sync/wwlib/wwfont.cpp $*
26 * *
27 * $Author:: Vss_sync $*
28 * *
29 * $Modtime:: 10/16/00 11:42a $*
30 * *
31 * $Revision:: 5 $*
32 * *
33 *---------------------------------------------------------------------------------------------*
34 * Functions: *
35 * WWFontClass::Print -- Print text to the surface specified. *
36 * WWFontClass::WWFontClass -- Constructor for a font class object. *
37 * WWFontClass::Char_Pixel_Width -- Fetch the pixel width of the character specified. *
38 * WWFontClass::String_Pixel_Width -- Determines the width of the string in pixels. *
39 * WWFontClass::Raw_Width -- Fetch the raw width of a character. *
40 * WWFontClass::Raw_Height -- Fetch the height of the font. *
41 * WWFontClass::Get_Width -- Get normalized width of the nominal font character. *
42 * WWFontClass::Get_Height -- Fetch the normalized height of the nominal font character. *
43 * WWFontClass::Set_XSpacing -- Set the X spacing override value. *
44 * WWFontClass::Set_YSpacing -- Set the vertical (Y) spacing override value. *
45 * Set_Font_Data -- Allow font data to be set after construction. *
46 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
47
48#include "always.h"
49#include "_convert.h"
50#include "wwfont.h"
51//#include <stdlib.h>
52
53
54#define FONTINFOMAXHEIGHT 4
55#define FONTINFOMAXWIDTH 5
56
57#define FUDGEDIV 16
58
59
60/***********************************************************************************************
61 * WWFontClass::WWFontClass -- Constructor for a font class object. *
62 * *
63 * This constructs a font object as it is based upon the font data output by the legacy *
64 * FONTMAKE.EXE utility. *
65 * *
66 * INPUT: fontdata -- Pointer to the data as output by the fontmake utility. *
67 * *
68 * isoutlined -- Is this font data available with outline pixels embedded? *
69 * *
70 * shadow -- Does the font data have shadow pixels embedded? *
71 * *
72 * OUTPUT: none *
73 * *
74 * WARNINGS: none *
75 * *
76 * HISTORY: *
77 * 05/26/1997 JLB : Created. *
78 *=============================================================================================*/
79WWFontClass::WWFontClass(void const * fontdata, bool isoutlined, int shadow, ConvertClass *convert, unsigned char *remap) :
80 IsOutlinedData(isoutlined),
81 Shadow(shadow),
82 Converter(convert),
83 RemapPalette(remap),
84 FontXSpacing(0),
85 FontYSpacing(0)
86{
87 Set_Font_Data(fontdata);
88}
89
90/***********************************************************************************************
91 * Set_Font_Data -- Allow font data to be set after construction. *
92 * *
93 * INPUT: *
94 * *
95 * OUTPUT: *
96 * *
97 * WARNINGS: *
98 * *
99 * HISTORY: *
100 * 01/24/2000 SKB : Created. *
101 *=============================================================================================*/
102void *WWFontClass::Set_Font_Data(void const * fontdata)
103{
104 void *old = (void *) FontData;
105
106 FontData = (FontType *)fontdata;
107 if (FontData) {
108 Set_XSpacing(FontXSpacing);
109 Set_YSpacing(FontYSpacing);
110 }
111 return(old);
112}
113
114
115/***********************************************************************************************
116 * WWFontClass::Char_Pixel_Width -- Fetch the pixel width of the character specified. *
117 * *
118 * This will return with the pixel width of the character specified. *
119 * *
120 * INPUT: c -- The character to determine the pixel width for. *
121 * *
122 * OUTPUT: Returns with the pixel width of the character. *
123 * *
124 * WARNINGS: The return width is the screen real estate width which may differ from the *
125 * actual pixels of the character. This difference is controlled by the font *
126 * X spacing. *
127 * *
128 * HISTORY: *
129 * 05/26/1997 JLB : Created. *
130 *=============================================================================================*/
132{
133 int raw = (*(((unsigned char *)FontData) + FontData->WidthBlockOffset + (unsigned char)c));
134 raw += FontXSpacing;
135 return(raw);
136}
137
138
139/***********************************************************************************************
140 * WWFontClass::String_Pixel_Width -- Determines the width of the string in pixels. *
141 * *
142 * This routine is used to determine how many pixels wide the string will be if it were *
143 * printed. *
144 * *
145 * INPUT: string -- The string to convert into its pixel width. *
146 * *
147 * OUTPUT: Returns with the number of pixels the string would span if it were printed. *
148 * *
149 * WARNINGS: This routine does not take into account clipping. *
150 * *
151 * HISTORY: *
152 * 05/26/1997 JLB : Created. *
153 *=============================================================================================*/
154int WWFontClass::String_Pixel_Width(char const * string) const
155{
156 if (string == NULL) return(0);
157 if (string[0] == 0) return 0;
158
159 int largest = 0; // Largest recorded width of the string.
160 int width = 0;
161 while (*string) {
162 if (*string == '\r' || *string == '\n') {
163 string++;
164 largest = MAX(largest, width);
165 width = 0;
166 } else {
167 width += Char_Pixel_Width(*string++); // add each char's width
168 }
169 }
170 largest = MAX(largest, width);
171 return(largest);
172}
173
174
175/***********************************************************************************************
176 * WWFontClass::Raw_Width -- Fetch the raw width of a character. *
177 * *
178 * This routine returns the nominal width of the font. This width is basically the width of *
179 * the widest character in the font. *
180 * *
181 * INPUT: none *
182 * *
183 * OUTPUT: Returns with the width of the widest character in the font. *
184 * *
185 * WARNINGS: none *
186 * *
187 * HISTORY: *
188 * 05/26/1997 JLB : Created. *
189 *=============================================================================================*/
190int WWFontClass::Raw_Width(void) const
191{
192 return(*(((unsigned char *)FontData) + FontData->InfoBlockOffset + FONTINFOMAXWIDTH));
193}
194
195
196/***********************************************************************************************
197 * WWFontClass::Raw_Height -- Fetch the height of the font. *
198 * *
199 * This returns the height of the font without regard for any Y spacing offsets. *
200 * *
201 * INPUT: none *
202 * *
203 * OUTPUT: Returns with the height of the font. *
204 * *
205 * WARNINGS: All characters in the font have the same logical height even if they actually *
206 * consume less pixels. *
207 * *
208 * HISTORY: *
209 * 05/26/1997 JLB : Created. *
210 *=============================================================================================*/
211int WWFontClass::Raw_Height(void) const
212{
213 return(*(((unsigned char *)FontData) + FontData->InfoBlockOffset + FONTINFOMAXHEIGHT));
214}
215
216
217/***********************************************************************************************
218 * WWFontClass::Get_Width -- Get normalized width of the nominal font character. *
219 * *
220 * This routine is used to fetch the width of the widest character in the font but the *
221 * width has been biased according to any X spacing override present. *
222 * *
223 * INPUT: none *
224 * *
225 * OUTPUT: Returns with the normalized width of the widest character in the font. *
226 * *
227 * WARNINGS: none *
228 * *
229 * HISTORY: *
230 * 05/26/1997 JLB : Created. *
231 *=============================================================================================*/
233{
234 return(Raw_Width() + ((FontXSpacing > 0) ? FontXSpacing : 0));
235}
236
237
238/***********************************************************************************************
239 * WWFontClass::Get_Height -- Fetch the normalized height of the nominal font character. *
240 * *
241 * This will return the height of the font but the returned height will be adjusted by any *
242 * Y spacing override present. *
243 * *
244 * INPUT: none *
245 * *
246 * OUTPUT: Returns with the height of the font normalized by any spacing overrides. *
247 * *
248 * WARNINGS: none *
249 * *
250 * HISTORY: *
251 * 05/26/1997 JLB : Created. *
252 *=============================================================================================*/
254{
255 return(Raw_Height() + ((FontYSpacing > 0) ? FontYSpacing : 0));
256}
257
258
259/***********************************************************************************************
260 * WWFontClass::Set_XSpacing -- Set the X spacing override value. *
261 * *
262 * Use this routine to control the horizontal spacing override for this font. If the value *
263 * is negative, the font becomes compressed. If the value is positive, then the font *
264 * becomes expanded. *
265 * *
266 * INPUT: x -- The X spacing override to use for this font. *
267 * *
268 * OUTPUT: Returns with the old X spacing override value. *
269 * *
270 * WARNINGS: none *
271 * *
272 * HISTORY: *
273 * 05/26/1997 JLB : Created. *
274 *=============================================================================================*/
276{
277 int old = FontXSpacing;
278 FontXSpacing = x;
279 if (IsOutlinedData) {
280 switch (Shadow) {
281 case 0:
282 FontXSpacing += -2;
283 break;
284
285 case 1:
286 FontXSpacing += -1;
287 break;
288
289 case 2:
290 FontXSpacing += -1;
291 break;
292 }
293 }
294 FontXSpacing += Get_Width() / FUDGEDIV;
295 return(old);
296}
297
298
299/***********************************************************************************************
300 * WWFontClass::Set_YSpacing -- Set the vertical (Y) spacing override value. *
301 * *
302 * Use this routine to control the "line spacing" of a font. If the Y spacing is negative *
303 * then the font becomes closer to the line above it. If value is positive, then more *
304 * space occurs between lines. *
305 * *
306 * INPUT: y -- The Y spacing override to use for this font. *
307 * *
308 * OUTPUT: Returns with the old Y spacing override value. *
309 * *
310 * WARNINGS: none *
311 * *
312 * HISTORY: *
313 * 05/26/1997 JLB : Created. *
314 *=============================================================================================*/
316{
317 int old = FontYSpacing;
318 FontYSpacing = y;
319 if (IsOutlinedData) {
320 switch (Shadow) {
321 case 0:
322 FontYSpacing += -2;
323 break;
324
325 case 1:
326 FontYSpacing += -1;
327 break;
328
329 case 2:
330 FontYSpacing += -1;
331 break;
332 }
333 }
334 FontYSpacing += Get_Height() / FUDGEDIV;
335 return(old);
336}
337
338
339/***********************************************************************************************
340 * WWFontClass::Print -- Print text to the surface specified. *
341 * *
342 * This displays text to the surface specified and with the attributes specified. *
343 * *
344 * INPUT: string -- The string to display to the surface. *
345 * *
346 * surface -- The surface to display the text upon. *
347 * *
348 * cliprect -- The clipping rectangle that both clips the text and biases the print *
349 * location to. *
350 * *
351 * point -- The draw position for the upper left corner of the first character. *
352 * *
353 * convert -- The pixel convert object that is used to draw the correct colors to *
354 * the destination surface. *
355 * *
356 * remap -- Auxiliary remap table for font colors. *
357 * *
358 * OUTPUT: Returns with the point where the next print should begin if it is to smoothly *
359 * continue where this print operation left off. *
360 * *
361 * WARNINGS: There are two separate drawing routines; one for old fonts and one for new *
362 * fonts. *
363 * *
364 * HISTORY: *
365 * 05/26/1997 JLB : Created. *
366 * 06/20/1887 BNA : Modified to handle new fonts. *
367 * 01/24/2000 SKB : Updated from C&C to include BNA code. *
368 * 01/24/2000 SKB : put in call for Get_Remap_Palette *
369 * 01/24/2000 SKB : Put in call for get converer. *
370 *=============================================================================================*/
371Point2D WWFontClass::Print(char const * string, Surface & surface, Rect const & cliprect, Point2D const & drawpoint, ConvertClass const & convertref, unsigned char const * remap) const
372{
373 if (string == NULL) return(drawpoint);
374
375 /*
376 ** Compute the surface relative coordinate for the print position.
377 */
378 Point2D point = drawpoint;
379 int xpos = point.Bias_To(cliprect).X;
380// int xpos = point.X + cliprect.X;
381 int ypos = point.Bias_To(cliprect).Y;
382// int ypos = point.Y + cliprect.Y;
383
384 int xspacing = FontXSpacing + Raw_Width()/FUDGEDIV;
385 int yspacing = FontYSpacing + Raw_Width()/FUDGEDIV;
386
387 // This font palette assumes that the font will be used as defined by converter.
388 static unsigned char const fontpalette[16] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
389 if (RemapPalette) {
390 remap = RemapPalette;
391 } else if (!remap) {
392 remap = &fontpalette[0];
393 }
394
395 // If there is a convert supplied with the font, use it as priority.
396 ConvertClass const *converter = Converter;
397 if (!converter) {
398 converter = &convertref;
399 }
400
401 /*
402 ** Verify that the clipping rectangle (if present) falls within the bounds of the surface.
403 */
404// Rect cliprect = surface->Get_Rect();
405// cliprect.X = 0;
406// cliprect.Y = 0;
407
408 /*
409 ** Trivially check to see if the print start position is outside the bounds of the clipping
410 ** rectangle.
411 */
412 if (xpos >= cliprect.X+cliprect.Width || ypos >= cliprect.Y+cliprect.Height) {
413 return(drawpoint);
414 }
415
416 /*
417 ** Check to see if access to the surface buffer is possible.
418 */
419 void * buffer = surface.Lock();
420 if (buffer != NULL) {
421 int startx = xpos;
422 unsigned char * fontwidth = ((unsigned char*)FontData) + FontData->WidthBlockOffset;
423 unsigned short * fontheight = (unsigned short*)(((unsigned char*)FontData) + FontData->HeightOffset);
424 unsigned short * fontoffset = (unsigned short*)(((unsigned char*)FontData) + FontData->OffsetBlockOffset);
425 int bbp = surface.Bytes_Per_Pixel();
426
427 /*
428 ** Process the whole string. Stop when the string reaches the right margin.
429 */
430 while (*string != '\0') {
431 unsigned char c = *string++;
432
433 /*
434 ** Certain control characters serve a formatting purpose. They merely
435 ** adjust the next draw position.
436 */
437 if (c == '\r') {
438 xpos = startx;
439 ypos += Raw_Height() + ((yspacing > 0) ? yspacing : 0);
440 continue;
441 }
442 if (c == '\n') {
443 xpos = cliprect.X;
444 ypos += Raw_Height() + ((yspacing > 0) ? yspacing : 0);
445 continue;
446 }
447
448 /*
449 ** Fetch working values for the character to display. These are used to
450 ** control the size of the character rectangle.
451 */
452 int width = fontwidth[c];
453 int dheight = fontheight[c] >> 8;
454 int firstrow = fontheight[c] & 0xFF;
455// int height = dheight+firstrow;
456
457 /*
458 ** Build the character rectangle (surface relative coordinates).
459 */
460 Rect crect(xpos, ypos, width+((xspacing > 0) ? xspacing : 0), *(((unsigned char *)FontData) + FontData->InfoBlockOffset + FONTINFOMAXHEIGHT) + ((yspacing > 0) ? yspacing : 0));
461
462 /*
463 ** Check to see if any part of this character would appear within the clipping
464 ** rectangle. If not, then don't process this character.
465 */
466 crect = crect.Intersect(cliprect);
467 if (crect.Is_Valid()) {
468
469 /*
470 ** Fill the background of the character if the background
471 ** color is not transparent.
472 */
473 if (remap[0] != 0) {
474 surface.Fill_Rect(crect, converter->Convert_Pixel(remap[0]));
475 }
476
477 /*
478 ** Loop through all data rows of this character and output the row
479 ** data with clipping.
480 */
481 if (FontData->FontCompress != (char) 2) { // if the font is the old style
482 unsigned char * dataptr = ((unsigned char *)FontData) + fontoffset[c];
483 void * drawbuff = (void*)(((char*)buffer) + ((ypos + firstrow) * surface.Stride()) + xpos * bbp);
484
485 for (int h = 0; h < dheight; h++) {
486
487 /*
488 ** If the current row to be drawn falls below the clipping rectangle, then
489 ** no further drawing for this character is needed -- bail out.
490 */
491 if (ypos + firstrow + h >= crect.Y + crect.Height) break;
492
493 /*
494 ** If the current row to be drawn falls above the clipping rectangle,
495 ** then skip the row and advance the source data pointer as well.
496 */
497 if (ypos + firstrow + h < crect.Y) {
498 drawbuff = (void*)(((char*)drawbuff) + surface.Stride());
499 dataptr = dataptr + ((width+1)/2);
500 } else {
501
502 /*
503 ** Process one row of character data. For simplicity reasons, just
504 ** loop through all pixels of this row and perform clipping at the
505 ** pixel level.
506 */
507 int dx = xpos;
508 int workwidth = width;
509 while (workwidth > 0) {
510
511 /*
512 ** Fetch the next two pixel values. Two pixel values must
513 ** be fetched at the same time since they are nibble packed.
514 */
515 int c1 = remap[*dataptr & 0x0F];
516 int c2 = remap[(*dataptr++ & 0xF0) >> 4];
517
518 /*
519 ** Draw the first pixel if it falls within the clipping
520 ** rectangle and is not transparent.
521 */
522 if (dx >= cliprect.X && dx < cliprect.X+cliprect.Width) {
523 if (c1 != 0) {
524 if (bbp == 2) {
525 *(short *)drawbuff = (short)converter->Convert_Pixel(c1);
526 } else {
527 *(char *)drawbuff = (char)converter->Convert_Pixel(c1);
528 }
529 }
530 }
531 dx += 1;
532 drawbuff = ((char*)drawbuff) + bbp;
533 workwidth -= 1;
534 if (workwidth == 0) break;
535
536 /*
537 ** Draw the second pixel if it falls within the clipping
538 ** rectangle and is not transparent.
539 */
540 if (dx >= cliprect.X && dx < cliprect.X+cliprect.Width) {
541 if (c2 != 0) {
542 if (bbp == 2) {
543 *(short *)drawbuff = (short)converter->Convert_Pixel(c2);
544 } else {
545 *(char *)drawbuff = (char)converter->Convert_Pixel(c2);
546 }
547 }
548 }
549 dx += 1;
550 drawbuff = ((char*)drawbuff) + bbp;
551 workwidth -= 1;
552 }
553
554 /*
555 ** Move the output pixel pointer to the next line down but at the
556 ** left margin of the character block.
557 */
558 drawbuff = (void*)((((char*)drawbuff) - (width*bbp)) + surface.Stride());
559 }
560 }
561 } else {
562 // the font is of the new type
563 unsigned char * dataptr = ((unsigned char *)FontData) + fontoffset[c] + FontData->DataBlockOffset;
564 void * drawbuff = (void*)(((char*)buffer) + ((ypos + firstrow) * surface.Stride()) + xpos * bbp);
565
566 for (int h = 0; h < dheight; h++) {
567
568 /*
569 ** If the current row to be drawn falls below the clipping rectangle, then
570 ** no further drawing for this character is needed -- bail out.
571 */
572 if (ypos + firstrow + h >= crect.Y + crect.Height) break;
573
574 /*
575 ** If the current row to be drawn falls above the clipping rectangle,
576 ** then skip the row and advance the source data pointer as well.
577 */
578 if (ypos + firstrow + h < crect.Y) {
579 drawbuff = (void*)(((char*)drawbuff) + surface.Stride());
580 dataptr = dataptr + width;
581 } else {
582
583 /*
584 ** Process one row of character data. For simplicity reasons, just
585 ** loop through all pixels of this row and perform clipping at the
586 ** pixel level.
587 */
588 int dx = xpos;
589 int workwidth = width;
590 while (workwidth > 0) {
591
592 /*
593 ** Fetch the next pixel value.
594 */
595 int c1 = remap[*dataptr++]; // no remapping
596
597 /*
598 ** Draw the pixel if it falls within the clipping
599 ** rectangle and is not transparent.
600 */
601 if (dx >= cliprect.X && dx < cliprect.X+cliprect.Width) {
602 if (c1 != 0) {
603 if (bbp == 2) {
604 *(short *)drawbuff = (short)converter->Convert_Pixel(c1);
605 } else {
606 *(char *)drawbuff = (char)converter->Convert_Pixel(c1);
607 }
608 }
609 }
610 dx += 1;
611 drawbuff = ((char*)drawbuff) + bbp;
612 workwidth -= 1;
613 }
614
615 /*
616 ** Move the output pixel pointer to the next line down but at the
617 ** left margin of the character block.
618 */
619 drawbuff = (void*)((((char*)drawbuff) - (width*bbp)) + surface.Stride());
620 }
621 }
622 }
623 }
624 xpos += Char_Pixel_Width(c);
625// xpos += width + xspacing;
626 }
627
628 point = Point2D(xpos - cliprect.X, ypos - cliprect.Y);
629 surface.Unlock();
630 }
631 return(point);
632}
#define NULL
Definition BaseType.h:92
TPoint2D< int > Point2D
Definition Point.h:114
#define MAX(a, b)
Definition always.h:185
int Convert_Pixel(int pixel) const
Definition Convert.h:94
virtual bool Unlock(void) const =0
virtual void * Lock(Point2D point=Point2D(0, 0)) const =0
virtual int Bytes_Per_Pixel(void) const =0
virtual bool Fill_Rect(Rect const &rect, int color)=0
virtual int Stride(void) const =0
TPoint2D< T > const Bias_To(TRect< T > const &rect) const
Definition trect.h:211
bool Is_Valid(void) const
Definition trect.h:82
T Width
Definition trect.h:115
T Y
Definition trect.h:109
T Height
Definition trect.h:116
TRect< T > const Intersect(TRect< T > const &rectangle, T *x=NULL, T *y=NULL) const
Definition trect.h:121
T X
Definition trect.h:108
virtual Point2D Print(char const *string, Surface &surface, Rect const &cliprect, Point2D const &point, ConvertClass const &converter, unsigned char const *remap=NULL) const
Definition wwfont.cpp:371
virtual int Get_Width(void) const
Definition wwfont.cpp:232
void * Set_Font_Data(void const *fontdata)
Definition wwfont.cpp:102
virtual int Set_YSpacing(int y)
Definition wwfont.cpp:315
virtual int Set_XSpacing(int x)
Definition wwfont.cpp:275
virtual int Get_Height(void) const
Definition wwfont.cpp:253
WWFontClass(void const *fontdata, bool isoutlined=false, int shadow=0, ConvertClass *convert=0, unsigned char *remap=0)
Definition wwfont.cpp:79
virtual int Char_Pixel_Width(char c) const
Definition wwfont.cpp:131
virtual int String_Pixel_Width(char const *string) const
Definition wwfont.cpp:154
TRect< int > Rect
Definition trect.h:221
#define FUDGEDIV
Definition wwfont.cpp:57
#define FONTINFOMAXWIDTH
Definition wwfont.cpp:55
#define FONTINFOMAXHEIGHT
Definition wwfont.cpp:54