1 /* GemRB - Infinity Engine Emulator
2 * Copyright (C) 2003 The GemRB Project
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program 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
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 //This class represents game fonts. Fonts are special .bam files.
22 //Each cycle stands for a letter.
29 #include "Interface.h"
35 unsigned int lastX
= 0;
37 #define PARAGRAPH_START_X 5;
39 static const Color black
= {0, 0, 0, 0};
41 inline size_t mystrlen(const char* string
)
46 const char* tmp
= string
;
49 if (( ( unsigned char ) * tmp
) >= 0xf0) {
59 Font::Font(int w
, int h
, Palette
* pal
)
68 tmpPixels
= (unsigned char*)malloc(width
*height
);
70 memset( xPos
, 0, sizeof( xPos
) );
71 memset( yPos
, 0, sizeof( yPos
) );
80 Video
*video
= core
->GetVideoDriver();
81 gamedata
->FreePalette( palette
);
82 video
->FreeSprite( sprBuffer
);
85 void Font::FinalizeSprite(bool cK
, int index
)
87 sprBuffer
= core
->GetVideoDriver()->CreateSprite8( width
, height
, 8, tmpPixels
, palette
? palette
->col
: 0, cK
, index
);
91 void Font::AddChar(unsigned char* spr
, int w
, int h
, short xPos
, short yPos
)
98 this->xPos
[count
] = 0;
99 this->yPos
[count
] = 0;
103 unsigned char * currPtr
= tmpPixels
+ lastX
;
104 unsigned char * srcPtr
= ( unsigned char * ) spr
;
105 for (int y
= 0; y
< h
; y
++) {
106 memcpy( currPtr
, srcPtr
, w
);
110 size
[count
].x
= lastX
;
114 this->xPos
[count
] = xPos
;
115 this->yPos
[count
] = yPos
;
120 void Font::PrintFromLine(int startrow
, Region rgn
, const unsigned char* string
,
121 Palette
* hicolor
, unsigned char Alignment
, Font
* initials
,
122 Sprite2D
* cursor
, unsigned int curpos
, bool NoColor
) const
124 bool enablecap
=false;
131 int initials_rows
= 0;
134 unsigned int psx
= PARAGRAPH_START_X
;
135 Palette
*pal
= hicolor
;
139 if (startrow
) enablecap
=false;
141 if (initials
==this) {
145 sprBuffer
->SetPalette( pal
);
146 size_t len
= strlen( ( char* ) string
);
147 char* tmp
= ( char* ) malloc( len
+ 1 );
148 memcpy( tmp
, ( char * ) string
, len
+ 1 );
149 SetupString( tmp
, rgn
.w
, NoColor
);
151 if (Alignment
& IE_FONT_SINGLE_LINE
) {
152 for (size_t i
= 0; i
< len
; i
++) {
153 int height
= yPos
[( unsigned char ) tmp
[i
] - 1];
160 if (!ystep
) ystep
= maxHeight
;
161 int x
= psx
, y
= ystep
;
162 int w
= CalcStringWidth( tmp
, NoColor
);
163 if (Alignment
& IE_FONT_ALIGN_CENTER
) {
164 x
= ( rgn
.w
- w
) / 2;
165 } else if (Alignment
& IE_FONT_ALIGN_RIGHT
) {
168 if (Alignment
& IE_FONT_ALIGN_MIDDLE
) {
170 for (size_t i
= 0; i
<= len
; i
++) {
171 if (( tmp
[i
] == 0 ) || ( tmp
[i
] == '\n' ))
175 y
+= ( rgn
.h
- h
) / 2;
176 } else if (Alignment
& IE_FONT_ALIGN_BOTTOM
) {
178 for (size_t i
= 0; i
<= len
; i
++) {
179 if (( tmp
[i
] == 0 ) || ( tmp
[i
] == '\n' ))
184 } else if (Alignment
& IE_FONT_ALIGN_TOP
) {
188 Video
* video
= core
->GetVideoDriver();
190 for (size_t i
= 0; i
< len
; i
++) {
191 if (( ( unsigned char ) tmp
[i
] ) == '[' && !NoColor
) {
196 for (int k
= 0; k
< 256 && i
<len
; k
++) {
204 if (strnicmp( tag
, "capital=",8)==0) {
205 sscanf( tag
, "capital=%d", &capital
);
206 if (capital
&& (row
>=startrow
) ) {
213 if (strnicmp( tag
, "color=", 6 ) == 0) {
215 if (sscanf( tag
, "color=%02X%02X%02X", &r
, &g
, &b
) != 3)
217 const Color c
= {(unsigned char) r
,(unsigned char)g
, (unsigned char)b
, 0};
218 Palette
* newPal
= core
->CreatePalette( c
, black
);
219 sprBuffer
->SetPalette( newPal
);
220 gamedata
->FreePalette( newPal
);
223 if (stricmp( tag
, "/color" ) == 0) {
224 sprBuffer
->SetPalette( pal
);
228 if (stricmp( "p", tag
) == 0) {
232 if (stricmp( "/p", tag
) == 0) {
233 psx
= PARAGRAPH_START_X
;
238 if (row
< startrow
) {
244 if (( tmp
[i
] == 0 ) || ( tmp
[i
] == '\n' )) {
247 int w
= CalcStringWidth( &tmp
[i
+ 1], NoColor
);
248 if (initials_rows
> 0) {
253 if (Alignment
& IE_FONT_ALIGN_CENTER
) {
254 x
= ( rgn
.w
- w
) / 2;
255 } else if (Alignment
& IE_FONT_ALIGN_RIGHT
) {
260 unsigned char currChar
= ( unsigned char ) tmp
[i
] - 1;
261 if (initials
&& capital
&& enablecap
) {
262 x
= initials
->PrintInitial( x
, y
, rgn
, currChar
);
265 //how many more lines to be indented (one was already indented)
266 initials_rows
= (initials
->maxHeight
-1)/maxHeight
;
270 video
->BlitSpriteRegion( sprBuffer
, size
[currChar
],
271 x
+ rgn
.x
, y
+ rgn
.y
- yPos
[currChar
], true, &rgn
);
272 if (cursor
&& ( i
== curpos
)) {
273 video
->BlitSprite( cursor
, x
+ rgn
.x
,
274 y
+ rgn
.y
, true, &rgn
);
276 x
+= size
[currChar
].w
;
278 if (cursor
&& ( curpos
== len
)) {
279 video
->BlitSprite( cursor
, x
+ rgn
.x
,
280 y
+ rgn
.y
, true, &rgn
);
285 void Font::Print(Region rgn
, const unsigned char* string
, Palette
* hicolor
,
286 unsigned char Alignment
, bool anchor
, Font
* initials
,
287 Sprite2D
* cursor
, unsigned int curpos
, bool NoColor
) const
289 Print(rgn
, rgn
, string
, hicolor
, Alignment
, anchor
, initials
, cursor
, curpos
, NoColor
);
292 void Font::Print(Region cliprgn
, Region rgn
, const unsigned char* string
,
293 Palette
* hicolor
, unsigned char Alignment
, bool anchor
, Font
* initials
,
294 Sprite2D
* cursor
, unsigned int curpos
, bool NoColor
) const
296 bool enablecap
=false;
304 unsigned int psx
= PARAGRAPH_START_X
;
305 Palette
* pal
= hicolor
;
309 if (initials
==this) {
313 sprBuffer
->SetPalette( pal
);
314 size_t len
= strlen( ( char* ) string
);
315 char* tmp
= ( char* ) malloc( len
+ 1 );
316 memcpy( tmp
, ( char * ) string
, len
+ 1 );
317 while (len
> 0 && (tmp
[len
- 1] == '\n' || tmp
[len
- 1] == '\r')) {
318 // ignore trailing newlines
323 SetupString( tmp
, rgn
.w
, NoColor
);
325 if (Alignment
& IE_FONT_SINGLE_LINE
) {
327 for (size_t i
= 0; i
< len
; i
++) {
328 if (tmp
[i
] == 0) continue;
329 int height
= yPos
[( unsigned char ) tmp
[i
] - 1];
336 if (!ystep
) ystep
= maxHeight
;
337 int x
= psx
, y
= ystep
;
338 Video
* video
= core
->GetVideoDriver();
340 if (Alignment
& IE_FONT_ALIGN_CENTER
) {
341 int w
= CalcStringWidth( tmp
, NoColor
);
342 x
= ( rgn
.w
- w
) / 2;
343 } else if (Alignment
& IE_FONT_ALIGN_RIGHT
) {
344 int w
= CalcStringWidth( tmp
, NoColor
);
348 if (Alignment
& IE_FONT_ALIGN_MIDDLE
) {
350 for (size_t i
= 0; i
<= len
; i
++) {
355 y
+= ( rgn
.h
- h
) / 2;
356 } else if (Alignment
& IE_FONT_ALIGN_BOTTOM
) {
358 for (size_t i
= 0; i
<= len
; i
++) {
364 } else if (Alignment
& IE_FONT_ALIGN_TOP
) {
367 for (size_t i
= 0; i
< len
; i
++) {
368 if (( ( unsigned char ) tmp
[i
] ) == '[' && !NoColor
) {
372 for (int k
= 0; k
< 256 && i
<len
; k
++) {
380 if (strnicmp( tag
, "capital=",8)==0) {
381 sscanf( tag
, "capital=%d", &capital
);
388 if (strnicmp( tag
, "color=", 6 ) == 0) {
390 if (sscanf( tag
, "color=%02X%02X%02X", &r
, &g
, &b
) != 3)
392 const Color c
= {(unsigned char) r
,(unsigned char) g
,(unsigned char) b
, 0};
393 Palette
* newPal
= core
->CreatePalette( c
, black
);
394 sprBuffer
->SetPalette( newPal
);
395 gamedata
->FreePalette( newPal
);
398 if (stricmp( tag
, "/color" ) == 0) {
399 sprBuffer
->SetPalette( pal
);
402 if (stricmp( "p", tag
) == 0) {
406 if (stricmp( "/p", tag
) == 0) {
407 psx
= PARAGRAPH_START_X
;
416 int w
= CalcStringWidth( &tmp
[i
+ 1], NoColor
);
417 if (Alignment
& IE_FONT_ALIGN_CENTER
) {
418 x
= ( rgn
.w
- w
) / 2;
419 } else if (Alignment
& IE_FONT_ALIGN_RIGHT
) {
424 unsigned char currChar
= ( unsigned char ) tmp
[i
] - 1;
425 if (initials
&& capital
) {
426 x
= initials
->PrintInitial( x
, y
, rgn
, currChar
);
430 video
->BlitSpriteRegion( sprBuffer
, size
[currChar
],
431 x
+ rgn
.x
, y
+ rgn
.y
- yPos
[currChar
],
433 if (cursor
&& ( curpos
== i
))
434 video
->BlitSprite( cursor
, x
+ rgn
.x
, y
+ rgn
.y
, anchor
, &cliprgn
);
435 x
+= size
[currChar
].w
;
437 if (cursor
&& ( curpos
== len
)) {
438 video
->BlitSprite( cursor
, x
+ rgn
.x
, y
+ rgn
.y
, anchor
, &cliprgn
);
443 int Font::PrintInitial(int x
, int y
, const Region
&rgn
, unsigned char currChar
) const
445 Video
*video
= core
->GetVideoDriver();
446 video
->BlitSpriteRegion( sprBuffer
, size
[currChar
],
447 x
+ rgn
.x
, y
+ rgn
.y
- yPos
[currChar
], true, &rgn
);
448 x
+= size
[currChar
].w
;
452 int Font::CalcStringWidth(const char* string
, bool NoColor
) const
454 size_t ret
= 0, len
= strlen( string
);
455 for (size_t i
= 0; i
< len
; i
++) {
456 if (( ( unsigned char ) string
[i
] ) == '[' && !NoColor
) {
462 for (k
= 0; k
< 256; k
++) {
463 if (string
[i
] == ']') {
467 tag
[k
] = string
[i
++];
471 ret
+= size
[( unsigned char ) string
[i
] - 1].w
;
476 void Font::SetupString(char* string
, unsigned int width
, bool NoColor
) const
478 size_t len
= strlen( string
);
479 unsigned int psx
= PARAGRAPH_START_X
;
481 unsigned int x
= psx
, wx
= 0;
482 bool endword
= false;
483 for (size_t pos
= 0; pos
< len
; pos
++) {
484 if (x
+ wx
> width
) {
485 if (!endword
&& ( x
== psx
))
486 lastpos
= ( int ) pos
;
491 if (string
[pos
] == 0) {
495 if (string
[pos
] == '\r')
497 if (string
[pos
] == '\n') {
501 lastpos
= ( int ) pos
;
505 if (( ( unsigned char ) string
[pos
] ) == '[' && !NoColor
) {
511 for (k
= 0; k
< 256; k
++) {
512 if (string
[pos
] == ']') {
516 tag
[k
] = string
[pos
++];
518 if (stricmp( "p", tag
) == 0) {
522 if (stricmp( "/p", tag
) == 0) {
523 psx
= PARAGRAPH_START_X
;
529 if (string
[pos
] && string
[pos
] != ' ') {
530 string
[pos
] = ( unsigned char ) (string
[pos
] - FirstChar
);
533 wx
+= size
[( unsigned char ) string
[pos
] - 1].w
;
534 if (( string
[pos
] == ' ' ) || ( string
[pos
] == '-' )) {
537 lastpos
= ( int ) pos
;
543 Palette
* Font::GetPalette() const
550 void Font::SetPalette(Palette
* pal
)
552 if (palette
) palette
->Release();
557 void Font::SetFirstChar( unsigned char first
)