]> git.pld-linux.org Git - packages/SDL_ttf.git/blob - SDL_ttf-ft2build_h.patch
- include ft2build.h befor freetype headers
[packages/SDL_ttf.git] / SDL_ttf-ft2build_h.patch
1 diff -durN SDL_ttf-2.0.6.orig/SDL_ttf.c SDL_ttf-2.0.6/SDL_ttf.c
2 --- SDL_ttf-2.0.6.orig/SDL_ttf.c        2003-02-21 17:38:15.000000000 +0000
3 +++ SDL_ttf-2.0.6/SDL_ttf.c     2004-12-29 11:18:02.473824704 +0000
4 @@ -39,6 +39,7 @@
5  #define FREEA(p) free(p)
6  #endif
7  
8 +#include <ft2build.h>
9  #include <freetype/freetype.h>
10  #include <freetype/ftoutln.h>
11  #include <freetype/ttnameid.h>
12 diff -durN SDL_ttf-2.0.6.orig/SDL_ttf.c~ SDL_ttf-2.0.6/SDL_ttf.c~
13 --- SDL_ttf-2.0.6.orig/SDL_ttf.c~       1970-01-01 00:00:00.000000000 +0000
14 +++ SDL_ttf-2.0.6/SDL_ttf.c~    2003-02-21 17:38:15.000000000 +0000
15 @@ -0,0 +1,1628 @@
16 +/*
17 +    SDL_ttf:  A companion library to SDL for working with TrueType (tm) fonts
18 +    Copyright (C) 1997, 1998, 1999, 2000, 2001  Sam Lantinga
19 +
20 +    This library is free software; you can redistribute it and/or
21 +    modify it under the terms of the GNU Library General Public
22 +    License as published by the Free Software Foundation; either
23 +    version 2 of the License, or (at your option) any later version.
24 +
25 +    This library is distributed in the hope that it will be useful,
26 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
27 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
28 +    Library General Public License for more details.
29 +
30 +    You should have received a copy of the GNU Library General Public
31 +    License along with this library; if not, write to the Free
32 +    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
33 +
34 +    Sam Lantinga
35 +    slouken@libsdl.org
36 +*/
37 +
38 +/* $Id$ */
39 +
40 +#include <math.h>
41 +#include <stdio.h>
42 +#include <stdlib.h>
43 +#include <string.h>
44 +
45 +#ifdef HAVE_ALLOCA_H
46 +#include <alloca.h>
47 +#endif
48 +
49 +#ifdef HAVE_ALLOCA
50 +#define ALLOCA(n) ((void*)alloca(n))
51 +#define FREEA(p)
52 +#else
53 +#define ALLOCA(n) malloc(n)
54 +#define FREEA(p) free(p)
55 +#endif
56 +
57 +#include <freetype/freetype.h>
58 +#include <freetype/ftoutln.h>
59 +#include <freetype/ttnameid.h>
60 +#include <freetype/internal/ftobjs.h>
61 +
62 +#include "SDL.h"
63 +#include "SDL_endian.h"
64 +#include "SDL_ttf.h"
65 +
66 +/* FIXME: Right now we assume the gray-scale renderer Freetype is using
67 +   supports 256 shades of gray, but we should instead key off of num_grays
68 +   in the result FT_Bitmap after the FT_Render_Glyph() call. */
69 +#define NUM_GRAYS       256
70 +
71 +/* Handy routines for converting from fixed point */
72 +#define FT_FLOOR(X)    ((X & -64) / 64)
73 +#define FT_CEIL(X)     (((X + 63) & -64) / 64)
74 +
75 +#define CACHED_METRICS 0x10
76 +#define CACHED_BITMAP  0x01
77 +#define CACHED_PIXMAP  0x02
78 +
79 +/* Cached glyph information */
80 +typedef struct cached_glyph {
81 +       int stored;
82 +       FT_UInt index;
83 +       FT_Bitmap bitmap;
84 +       FT_Bitmap pixmap;
85 +       int minx;
86 +       int maxx;
87 +       int miny;
88 +       int maxy;
89 +       int yoffset;
90 +       int advance;
91 +       Uint16 cached;
92 +} c_glyph;
93 +
94 +/* The structure used to hold internal font information */
95 +struct _TTF_Font {
96 +       /* Freetype2 maintains all sorts of useful info itself */
97 +       FT_Face face;
98 +
99 +       /* We'll cache these ourselves */
100 +       int height;
101 +       int ascent;
102 +       int descent;
103 +       int lineskip;
104 +
105 +       /* The font style */
106 +       int style;
107 +
108 +       /* Extra width in glyph bounds for text styles */
109 +       int glyph_overhang;
110 +       float glyph_italics;
111 +
112 +       /* Information in the font for underlining */
113 +       int underline_offset;
114 +       int underline_height;
115 +
116 +       /* Cache for style-transformed glyphs */
117 +       c_glyph *current;
118 +       c_glyph cache[256];
119 +       c_glyph scratch;
120 +
121 +       /* We are responsible for closing the font stream */
122 +       SDL_RWops *src;
123 +       int freesrc;
124 +       FT_Open_Args args;
125 +
126 +       /* For non-scalable formats, we must remember which font index size */
127 +       int font_size_family;
128 +};
129 +
130 +/* The FreeType font engine/library */
131 +static FT_Library library;
132 +static int TTF_initialized = 0;
133 +static int TTF_byteswapped = 0;
134 +
135 +/* UNICODE string utilities */
136 +static __inline__ int UNICODE_strlen(const Uint16 *text)
137 +{
138 +       int size = 0;
139 +       while ( *text++ ) {
140 +               ++size;
141 +       }
142 +       return size;
143 +}
144 +static __inline__ void UNICODE_strcpy(Uint16 *dst, const Uint16 *src, int swap)
145 +{
146 +       if ( swap ) {
147 +               while ( *src ) {
148 +                       *dst = SDL_Swap16(*src);
149 +                       ++src;
150 +                       ++dst;
151 +               }
152 +               *dst = '\0';
153 +       } else {
154 +               while ( *src ) {
155 +                       *dst = *src;
156 +                       ++src;
157 +                       ++dst;
158 +               }
159 +               *dst = '\0';
160 +       }
161 +}
162 +
163 +/* rcg06192001 get linked library's version. */
164 +const SDL_version *TTF_Linked_Version(void)
165 +{
166 +       static SDL_version linked_version;
167 +       TTF_VERSION(&linked_version);
168 +       return(&linked_version);
169 +}
170 +
171 +/* This function tells the library whether UNICODE text is generally
172 +   byteswapped.  A UNICODE BOM character at the beginning of a string
173 +   will override this setting for that string.
174 + */
175 +void TTF_ByteSwappedUNICODE(int swapped)
176 +{
177 +       TTF_byteswapped = swapped;
178 +}
179 +
180 +static void TTF_SetFTError(const char *msg, FT_Error error)
181 +{
182 +#ifdef USE_FREETYPE_ERRORS
183 +#undef FTERRORS_H
184 +#define FT_ERRORDEF( e, v, s )  { e, s },
185 +       static const struct
186 +       {
187 +         int          err_code;
188 +         const char*  err_msg;
189 +       } ft_errors[] = {
190 +#include <freetype/fterrors.h>
191 +       };
192 +       int i;
193 +       const char *err_msg;
194 +       char buffer[1024];
195 +
196 +       err_msg = NULL;
197 +       for ( i=0; i<((sizeof ft_errors)/(sizeof ft_errors[0])); ++i ) {
198 +               if ( error == ft_errors[i].err_code ) {
199 +                       err_msg = ft_errors[i].err_msg;
200 +                       break;
201 +               }
202 +       }
203 +       if ( ! err_msg ) {
204 +               err_msg = "unknown FreeType error";
205 +       }
206 +       sprintf(buffer, "%s: %s", msg, err_msg);
207 +       TTF_SetError(buffer);
208 +#else
209 +       TTF_SetError(msg);
210 +#endif /* USE_FREETYPE_ERRORS */
211 +}
212 +
213 +int TTF_Init( void )
214 +{
215 +       int status = 0;
216 +
217 +       if ( ! TTF_initialized ) {
218 +               FT_Error error = FT_Init_FreeType( &library );
219 +               if ( error ) {
220 +                       TTF_SetFTError("Couldn't init FreeType engine", error);
221 +                       status = -1;
222 +               }
223 +       }
224 +       if ( status == 0 ) {
225 +               ++TTF_initialized;
226 +       }
227 +       return status;
228 +}
229 +
230 +static unsigned long RWread(
231 +       FT_Stream stream,
232 +       unsigned long offset,
233 +       unsigned char* buffer,
234 +       unsigned long count
235 +)
236 +{
237 +       SDL_RWops *src;
238 +
239 +       src = (SDL_RWops *)stream->descriptor.pointer;
240 +       SDL_RWseek( src, (int)offset, SEEK_SET );
241 +       return SDL_RWread( src, buffer, 1, (int)count );
242 +}
243 +
244 +TTF_Font* TTF_OpenFontIndexRW( SDL_RWops *src, int freesrc, int ptsize, long index )
245 +{
246 +       TTF_Font* font;
247 +       FT_Error error;
248 +       FT_Face face;
249 +       FT_Fixed scale;
250 +       FT_Stream stream;
251 +       int position;
252 +
253 +       if ( ! TTF_initialized ) {
254 +               TTF_SetError( "Library not initialized" );
255 +               return NULL;
256 +       }
257 +
258 +       /* Check to make sure we can seek in this stream */
259 +       position = SDL_RWtell(src);
260 +       if ( position < 0 ) {
261 +               TTF_SetError( "Can't seek in stream" );
262 +               return NULL;
263 +       }
264 +
265 +       font = (TTF_Font*) malloc(sizeof *font);
266 +       if ( font == NULL ) {
267 +               TTF_SetError( "Out of memory" );
268 +               return NULL;
269 +       }
270 +       memset(font, 0, sizeof(*font));
271 +
272 +       font->src = src;
273 +       font->freesrc = freesrc;
274 +
275 +       stream = (FT_Stream)malloc(sizeof(*stream));
276 +       if ( stream == NULL ) {
277 +               TTF_SetError( "Out of memory" );
278 +               TTF_CloseFont( font );
279 +               return NULL;
280 +       }
281 +       memset(stream, 0, sizeof(*stream));
282 +
283 +       stream->memory = library->memory;
284 +       stream->read = RWread;
285 +       stream->descriptor.pointer = src;
286 +       stream->pos = (unsigned long)position;
287 +       SDL_RWseek(src, 0, SEEK_END);
288 +       stream->size = (unsigned long)(SDL_RWtell(src) - position);
289 +       SDL_RWseek(src, position, SEEK_SET);
290 +
291 +       font->args.flags = ft_open_stream;
292 +       font->args.stream = stream;
293 +
294 +       error = FT_Open_Face( library, &font->args, index, &font->face );
295 +       if( error ) {
296 +               TTF_SetFTError( "Couldn't load font file", error );
297 +               TTF_CloseFont( font );
298 +               return NULL;
299 +       }
300 +       face = font->face;
301 +
302 +       /* Make sure that our font face is scalable (global metrics) */
303 +       if ( FT_IS_SCALABLE(face) ) {
304 +
305 +               /* Set the character size and use default DPI (72) */
306 +               error = FT_Set_Char_Size( font->face, 0, ptsize * 64, 0, 0 );
307 +                       if( error ) {
308 +               TTF_SetFTError( "Couldn't set font size", error );
309 +               TTF_CloseFont( font );
310 +               return NULL;
311 +         }
312 +
313 +         /* Get the scalable font metrics for this font */
314 +         scale = face->size->metrics.y_scale;
315 +         font->ascent  = FT_CEIL(FT_MulFix(face->bbox.yMax, scale));
316 +         font->descent = FT_CEIL(FT_MulFix(face->bbox.yMin, scale));
317 +         font->height  = font->ascent - font->descent + /* baseline */ 1;
318 +         font->lineskip = FT_CEIL(FT_MulFix(face->height, scale));
319 +         font->underline_offset = FT_FLOOR(FT_MulFix(face->underline_position, scale));
320 +         font->underline_height = FT_FLOOR(FT_MulFix(face->underline_thickness, scale));
321 +
322 +       } else {
323 +               /* Non-scalable font case.  ptsize determines which family
324 +                * or series of fonts to grab from the non-scalable format.
325 +                * It is not the point size of the font.
326 +                * */
327 +               if ( ptsize >= font->face->num_fixed_sizes )
328 +                       ptsize = font->face->num_fixed_sizes - 1;
329 +               font->font_size_family = ptsize;
330 +               error = FT_Set_Pixel_Sizes( face,
331 +                               face->available_sizes[ptsize].height,
332 +                               face->available_sizes[ptsize].width );
333 +               /* With non-scalale fonts, Freetype2 likes to fill many of the
334 +                * font metrics with the value of 0.  The size of the
335 +                * non-scalable fonts must be determined differently
336 +                * or sometimes cannot be determined.
337 +                * */
338 +               font->ascent = face->available_sizes[ptsize].height;
339 +               font->descent = 0;
340 +               font->height = face->available_sizes[ptsize].height;
341 +               font->lineskip = FT_CEIL(font->ascent);
342 +               font->underline_offset = FT_FLOOR(face->underline_position);
343 +               font->underline_height = FT_FLOOR(face->underline_thickness);
344 +       }
345 +
346 +       if ( font->underline_height < 1 ) {
347 +               font->underline_height = 1;
348 +       }
349 +
350 +#ifdef DEBUG_FONTS
351 +       printf("Font metrics:\n");
352 +       printf("\tascent = %d, descent = %d\n",
353 +               font->ascent, font->descent);
354 +       printf("\theight = %d, lineskip = %d\n",
355 +               font->height, font->lineskip);
356 +       printf("\tunderline_offset = %d, underline_height = %d\n",
357 +               font->underline_offset, font->underline_height);
358 +#endif
359 +
360 +       /* Set the default font style */
361 +       font->style = TTF_STYLE_NORMAL;
362 +       font->glyph_overhang = face->size->metrics.y_ppem / 10;
363 +       /* x offset = cos(((90.0-12)/360)*2*M_PI), or 12 degree angle */
364 +       font->glyph_italics = 0.207f;
365 +       font->glyph_italics *= font->height;
366 +
367 +       return font;
368 +}
369 +
370 +TTF_Font* TTF_OpenFontRW( SDL_RWops *src, int freesrc, int ptsize )
371 +{
372 +       return TTF_OpenFontIndexRW(src, freesrc, ptsize, 0);
373 +}
374 +
375 +TTF_Font* TTF_OpenFontIndex( const char *file, int ptsize, long index )
376 +{
377 +       return TTF_OpenFontIndexRW(SDL_RWFromFile(file, "rb"), 1, ptsize, index);
378 +}
379 +
380 +TTF_Font* TTF_OpenFont( const char *file, int ptsize )
381 +{
382 +       return TTF_OpenFontIndex(file, ptsize, 0);
383 +}
384 +
385 +static void Flush_Glyph( c_glyph* glyph )
386 +{
387 +       glyph->stored = 0;
388 +       glyph->index = 0;
389 +       if( glyph->bitmap.buffer ) {
390 +               free( glyph->bitmap.buffer );
391 +               glyph->bitmap.buffer = 0;
392 +       }
393 +       if( glyph->pixmap.buffer ) {
394 +               free( glyph->pixmap.buffer );
395 +               glyph->pixmap.buffer = 0;
396 +       }
397 +       glyph->cached = 0;
398 +}
399 +       
400 +static void Flush_Cache( TTF_Font* font )
401 +{
402 +       int i;
403 +       int size = sizeof( font->cache ) / sizeof( font->cache[0] );
404 +
405 +       for( i = 0; i < size; ++i ) {
406 +               if( font->cache[i].cached ) {
407 +                       Flush_Glyph( &font->cache[i] );
408 +               }
409 +
410 +       }
411 +       if( font->scratch.cached ) {
412 +               Flush_Glyph( &font->scratch );
413 +       }
414 +
415 +}
416 +
417 +static FT_Error Load_Glyph( TTF_Font* font, Uint16 ch, c_glyph* cached, int want )
418 +{
419 +       FT_Face face;
420 +       FT_Error error;
421 +       FT_GlyphSlot glyph;
422 +       FT_Glyph_Metrics* metrics;
423 +       FT_Outline* outline;
424 +
425 +       if ( !font || !font->face ) {
426 +               return FT_Err_Invalid_Handle;
427 +       }
428 +
429 +       face = font->face;
430 +
431 +       /* Load the glyph */
432 +       if ( ! cached->index ) {
433 +               cached->index = FT_Get_Char_Index( face, ch );
434 +       }
435 +       error = FT_Load_Glyph( face, cached->index, FT_LOAD_DEFAULT );
436 +       if( error ) {
437 +               return error;
438 +       }
439 +
440 +       /* Get our glyph shortcuts */
441 +       glyph = face->glyph;
442 +       metrics = &glyph->metrics;
443 +       outline = &glyph->outline;
444 +
445 +       /* Get the glyph metrics if desired */
446 +       if ( (want & CACHED_METRICS) && !(cached->stored & CACHED_METRICS) ) {
447 +               if ( FT_IS_SCALABLE( face ) ) {
448 +                       /* Get the bounding box */
449 +                       cached->minx = FT_FLOOR(metrics->horiBearingX);
450 +                       cached->maxx = cached->minx + FT_CEIL(metrics->width);
451 +                       cached->maxy = FT_FLOOR(metrics->horiBearingY);
452 +                       cached->miny = cached->maxy - FT_CEIL(metrics->height);
453 +                       cached->yoffset = font->ascent - cached->maxy;
454 +                       cached->advance = FT_CEIL(metrics->horiAdvance);
455 +               } else {
456 +                       /* Get the bounding box for non-scalable format.
457 +                        * Again, freetype2 fills in many of the font metrics
458 +                        * with the value of 0, so some of the values we
459 +                        * need must be calculated differently with certain
460 +                        * assumptions about non-scalable formats.
461 +                        * */
462 +                       cached->minx = FT_FLOOR(metrics->horiBearingX);
463 +                       cached->maxx = cached->minx + FT_CEIL(metrics->horiAdvance);
464 +                       cached->maxy = FT_FLOOR(metrics->horiBearingY);
465 +                       cached->miny = cached->maxy - FT_CEIL(face->available_sizes[font->font_size_family].height);
466 +                       cached->yoffset = 0;
467 +                       cached->advance = FT_CEIL(metrics->horiAdvance);
468 +               }
469 +               
470 +               /* Adjust for bold and italic text */
471 +               if( font->style & TTF_STYLE_BOLD ) {
472 +                       cached->maxx += font->glyph_overhang;
473 +               }
474 +               if( font->style & TTF_STYLE_ITALIC ) {
475 +                       cached->maxx += (int)ceil(font->glyph_italics);
476 +               }
477 +               cached->stored |= CACHED_METRICS;
478 +       }
479 +
480 +       if ( ((want & CACHED_BITMAP) && !(cached->stored & CACHED_BITMAP)) ||
481 +            ((want & CACHED_PIXMAP) && !(cached->stored & CACHED_PIXMAP)) ) {
482 +               int mono = (want & CACHED_BITMAP);
483 +               int i;
484 +               FT_Bitmap* src;
485 +               FT_Bitmap* dst;
486 +
487 +               /* Handle the italic style */
488 +               if( font->style & TTF_STYLE_ITALIC ) {
489 +                       FT_Matrix shear;
490 +
491 +                       shear.xx = 1 << 16;
492 +                       shear.xy = (int) ( font->glyph_italics * ( 1 << 16 ) ) / font->height;
493 +                       shear.yx = 0;
494 +                       shear.yy = 1 << 16;
495 +
496 +                       FT_Outline_Transform( outline, &shear );
497 +               }
498 +
499 +               /* Render the glyph */
500 +               if ( mono ) {
501 +                       error = FT_Render_Glyph( glyph, ft_render_mode_mono );
502 +               } else {
503 +                       error = FT_Render_Glyph( glyph, ft_render_mode_normal );
504 +               }
505 +               if( error ) {
506 +                       return error;
507 +               }
508 +
509 +               /* Copy over information to cache */
510 +               src = &glyph->bitmap;
511 +               if ( mono ) {
512 +                       dst = &cached->bitmap;
513 +               } else {
514 +                       dst = &cached->pixmap;
515 +               }
516 +               memcpy( dst, src, sizeof( *dst ) );
517 +
518 +               /* FT_Render_Glyph() and .fon fonts always generate a
519 +                * two-color (black and white) glyphslot surface, even
520 +                * when rendered in ft_render_mode_normal.  This is probably
521 +                * a freetype2 bug because it is inconsistent with the
522 +                * freetype2 documentation under FT_Render_Mode section.
523 +                * */
524 +               if ( mono || !FT_IS_SCALABLE(face) ) {
525 +                       dst->pitch *= 8;
526 +               }
527 +
528 +               /* Adjust for bold and italic text */
529 +               if( font->style & TTF_STYLE_BOLD ) {
530 +                       int bump = font->glyph_overhang;
531 +                       dst->pitch += bump;
532 +                       dst->width += bump;
533 +               }
534 +               if( font->style & TTF_STYLE_ITALIC ) {
535 +                       int bump = (int)ceil(font->glyph_italics);
536 +                       dst->pitch += bump;
537 +                       dst->width += bump;
538 +               }
539 +
540 +               if (dst->rows != 0) {
541 +                       dst->buffer = malloc( dst->pitch * dst->rows );
542 +                       if( !dst->buffer ) {
543 +                               return FT_Err_Out_Of_Memory;
544 +                       }
545 +                       memset( dst->buffer, 0, dst->pitch * dst->rows );
546 +
547 +                       for( i = 0; i < src->rows; i++ ) {
548 +                               int soffset = i * src->pitch;
549 +                               int doffset = i * dst->pitch;
550 +                               if ( mono ) {
551 +                                       unsigned char *srcp = src->buffer + soffset;
552 +                                       unsigned char *dstp = dst->buffer + doffset;
553 +                                       int j;
554 +                                       for ( j = 0; j < src->width; j += 8 ) {
555 +                                               unsigned char ch = *srcp++;
556 +                                               *dstp++ = (ch&0x80) >> 7;
557 +                                               ch <<= 1;
558 +                                               *dstp++ = (ch&0x80) >> 7;
559 +                                               ch <<= 1;
560 +                                               *dstp++ = (ch&0x80) >> 7;
561 +                                               ch <<= 1;
562 +                                               *dstp++ = (ch&0x80) >> 7;
563 +                                               ch <<= 1;
564 +                                               *dstp++ = (ch&0x80) >> 7;
565 +                                               ch <<= 1;
566 +                                               *dstp++ = (ch&0x80) >> 7;
567 +                                               ch <<= 1;
568 +                                               *dstp++ = (ch&0x80) >> 7;
569 +                                               ch <<= 1;
570 +                                               *dstp++ = (ch&0x80) >> 7;
571 +                                       }
572 +                               } else if ( !FT_IS_SCALABLE(face) ) {
573 +                                       /* This special case wouldn't
574 +                                        * be here if the FT_Render_Glyph()
575 +                                        * function wasn't buggy when it tried
576 +                                        * to render a .fon font with 256
577 +                                        * shades of gray.  Instead, it
578 +                                        * returns a black and white surface
579 +                                        * and we have to translate it back
580 +                                        * to a 256 gray shaded surface. 
581 +                                        * */
582 +                                       unsigned char *srcp = src->buffer + soffset;
583 +                                       unsigned char *dstp = dst->buffer + doffset;
584 +                                       unsigned char ch;
585 +                                       int j, k;
586 +                                       for ( j = 0; j < src->width; j += 8) {
587 +                                               ch = *srcp++;
588 +                                               for (k = 0; k < 8; ++k) {
589 +                                                       if ((ch&0x80) >> 7) {
590 +                                                               *dstp++ = NUM_GRAYS - 1;
591 +                                                       } else {
592 +                                                               *dstp++ = 0x00;
593 +                                                       }
594 +                                                       ch <<= 1;
595 +                                               }
596 +                                       }
597 +                               } else {
598 +                                       memcpy(dst->buffer+doffset,
599 +                                              src->buffer+soffset, src->pitch);
600 +                               }
601 +                       }
602 +               }
603 +
604 +               /* Handle the bold style */
605 +               if ( font->style & TTF_STYLE_BOLD ) {
606 +                       int row;
607 +                       int col;
608 +                       int offset;
609 +                       int pixel;
610 +                       Uint8* pixmap;
611 +
612 +                       /* The pixmap is a little hard, we have to add and clamp */
613 +                       for( row = dst->rows - 1; row >= 0; --row ) {
614 +                               pixmap = (Uint8*) dst->buffer + row * dst->pitch;
615 +                               for( offset=1; offset <= font->glyph_overhang; ++offset ) {
616 +                                       for( col = dst->width - 1; col > 0; --col ) {
617 +                                               pixel = (pixmap[col] + pixmap[col-1]);
618 +                                               if( pixel > NUM_GRAYS - 1 ) {
619 +                                                       pixel = NUM_GRAYS - 1;
620 +                                               }
621 +                                               pixmap[col] = (Uint8) pixel;
622 +                                       }
623 +                               }
624 +                       }
625 +               }
626 +
627 +               /* Mark that we rendered this format */
628 +               if ( mono ) {
629 +                       cached->stored |= CACHED_BITMAP;
630 +               } else {
631 +                       cached->stored |= CACHED_PIXMAP;
632 +               }
633 +       }
634 +
635 +       /* We're done, mark this glyph cached */
636 +       cached->cached = ch;
637 +
638 +       return 0;
639 +}
640 +
641 +static FT_Error Find_Glyph( TTF_Font* font, Uint16 ch, int want )
642 +{
643 +       int retval = 0;
644 +
645 +       if( ch < 256 ) {
646 +               font->current = &font->cache[ch];
647 +       } else {
648 +               if ( font->scratch.cached != ch ) {
649 +                       Flush_Glyph( &font->scratch );
650 +               }
651 +               font->current = &font->scratch;
652 +       }
653 +       if ( (font->current->stored & want) != want ) {
654 +               retval = Load_Glyph( font, ch, font->current, want );
655 +       }
656 +       return retval;
657 +}
658 +
659 +void TTF_CloseFont( TTF_Font* font )
660 +{
661 +       Flush_Cache( font );
662 +       if ( font->face ) {
663 +               FT_Done_Face( font->face );
664 +       }
665 +       if ( font->args.stream ) {
666 +               free( font->args.stream );
667 +       }
668 +       if ( font->freesrc ) {
669 +               SDL_RWclose( font->src );
670 +       }
671 +       free( font );
672 +}
673 +
674 +static Uint16 *LATIN1_to_UNICODE(Uint16 *unicode, const char *text, int len)
675 +{
676 +       int i;
677 +
678 +       for ( i=0; i < len; ++i ) {
679 +               unicode[i] = ((const unsigned char *)text)[i];
680 +       }
681 +       unicode[i] = 0;
682 +
683 +       return unicode;
684 +}
685 +
686 +static Uint16 *UTF8_to_UNICODE(Uint16 *unicode, const char *utf8, int len)
687 +{
688 +       int i, j;
689 +       Uint16 ch;
690 +
691 +       for ( i=0, j=0; i < len; ++i, ++j ) {
692 +               ch = ((const unsigned char *)utf8)[i];
693 +               if ( ch >= 0xF0 ) {
694 +                       ch  =  (Uint16)(utf8[i]&0x07) << 18;
695 +                       ch |=  (Uint16)(utf8[++i]&0x3F) << 12;
696 +                       ch |=  (Uint16)(utf8[++i]&0x3F) << 6;
697 +                       ch |=  (Uint16)(utf8[++i]&0x3F);
698 +               } else
699 +               if ( ch >= 0xE0 ) {
700 +                       ch  =  (Uint16)(utf8[i]&0x3F) << 12;
701 +                       ch |=  (Uint16)(utf8[++i]&0x3F) << 6;
702 +                       ch |=  (Uint16)(utf8[++i]&0x3F);
703 +               } else
704 +               if ( ch >= 0xC0 ) {
705 +                       ch  =  (Uint16)(utf8[i]&0x3F) << 6;
706 +                       ch |=  (Uint16)(utf8[++i]&0x3F);
707 +               }
708 +               unicode[j] = ch;
709 +       }
710 +       unicode[j] = 0;
711 +
712 +       return unicode;
713 +}
714 +
715 +int TTF_FontHeight(TTF_Font *font)
716 +{
717 +       return(font->height);
718 +}
719 +
720 +int TTF_FontAscent(TTF_Font *font)
721 +{
722 +       return(font->ascent);
723 +}
724 +
725 +int TTF_FontDescent(TTF_Font *font)
726 +{
727 +       return(font->descent);
728 +}
729 +
730 +int TTF_FontLineSkip(TTF_Font *font)
731 +{
732 +       return(font->lineskip);
733 +}
734 +
735 +long TTF_FontFaces(TTF_Font *font)
736 +{
737 +       return(font->face->num_faces);
738 +}
739 +
740 +int TTF_FontFaceIsFixedWidth(TTF_Font *font)
741 +{
742 +       return(FT_IS_FIXED_WIDTH(font->face));
743 +}
744 +
745 +char *TTF_FontFaceFamilyName(TTF_Font *font)
746 +{
747 +       return(font->face->family_name);
748 +}
749 +
750 +char *TTF_FontFaceStyleName(TTF_Font *font)
751 +{
752 +       return(font->face->style_name);
753 +}
754 +
755 +int TTF_GlyphMetrics(TTF_Font *font, Uint16 ch,
756 +                     int* minx, int* maxx, int* miny, int* maxy, int* advance)
757 +{
758 +       FT_Error error;
759 +
760 +       error = Find_Glyph(font, ch, CACHED_METRICS);
761 +       if ( error ) {
762 +               TTF_SetFTError("Couldn't find glyph", error);
763 +               return -1;
764 +       }
765 +
766 +       if ( minx ) {
767 +               *minx = font->current->minx;
768 +       }
769 +       if ( maxx ) {
770 +               *maxx = font->current->maxx;
771 +       }
772 +       if ( miny ) {
773 +               *miny = font->current->miny;
774 +       }
775 +       if ( maxy ) {
776 +               *maxy = font->current->maxy;
777 +       }
778 +       if ( advance ) {
779 +               *advance = font->current->advance;
780 +       }
781 +       return 0;
782 +}
783 +
784 +int TTF_SizeText(TTF_Font *font, const char *text, int *w, int *h)
785 +{
786 +       Uint16 *unicode_text;
787 +       int unicode_len;
788 +       int status;
789 +
790 +       /* Copy the Latin-1 text to a UNICODE text buffer */
791 +       unicode_len = strlen(text);
792 +       unicode_text = (Uint16 *)ALLOCA((1+unicode_len+1)*(sizeof *unicode_text));
793 +       if ( unicode_text == NULL ) {
794 +               TTF_SetError("Out of memory");
795 +               return -1;
796 +       }
797 +       *unicode_text = UNICODE_BOM_NATIVE;
798 +       LATIN1_to_UNICODE(unicode_text+1, text, unicode_len);
799 +
800 +       /* Render the new text */
801 +       status = TTF_SizeUNICODE(font, unicode_text, w, h);
802 +
803 +       /* Free the text buffer and return */
804 +       FREEA(unicode_text);
805 +       return status;
806 +}
807 +
808 +int TTF_SizeUTF8(TTF_Font *font, const char *text, int *w, int *h)
809 +{
810 +       Uint16 *unicode_text;
811 +       int unicode_len;
812 +       int status;
813 +
814 +       /* Copy the UTF-8 text to a UNICODE text buffer */
815 +       unicode_len = strlen(text);
816 +       unicode_text = (Uint16 *)ALLOCA((1+unicode_len+1)*(sizeof *unicode_text));
817 +       if ( unicode_text == NULL ) {
818 +               TTF_SetError("Out of memory");
819 +               return -1;
820 +       }
821 +       *unicode_text = UNICODE_BOM_NATIVE;
822 +       UTF8_to_UNICODE(unicode_text+1, text, unicode_len);
823 +
824 +       /* Render the new text */
825 +       status = TTF_SizeUNICODE(font, unicode_text, w, h);
826 +
827 +       /* Free the text buffer and return */
828 +       FREEA(unicode_text);
829 +       return status;
830 +}
831 +
832 +int TTF_SizeUNICODE(TTF_Font *font, const Uint16 *text, int *w, int *h)
833 +{
834 +       int status;
835 +       const Uint16 *ch;
836 +       int swapped;
837 +       int x, z;
838 +       int minx, maxx;
839 +       int miny, maxy;
840 +       c_glyph *glyph;
841 +       FT_Error error;
842 +
843 +       /* Initialize everything to 0 */
844 +       if ( ! TTF_initialized ) {
845 +               TTF_SetError( "Library not initialized" );
846 +               return -1;
847 +       }
848 +       status = 0;
849 +       minx = maxx = 0;
850 +       miny = maxy = 0;
851 +       swapped = TTF_byteswapped;
852 +
853 +       /* Load each character and sum it's bounding box */
854 +       x= 0;
855 +       for ( ch=text; *ch; ++ch ) {
856 +               Uint16 c = *ch;
857 +               if ( c == UNICODE_BOM_NATIVE ) {
858 +                       swapped = 0;
859 +                       if ( text == ch ) {
860 +                               ++text;
861 +                       }
862 +                       continue;
863 +               }
864 +               if ( c == UNICODE_BOM_SWAPPED ) {
865 +                       swapped = 1;
866 +                       if ( text == ch ) {
867 +                               ++text;
868 +                       }
869 +                       continue;
870 +               }
871 +               if ( swapped ) {
872 +                       c = SDL_Swap16(c);
873 +               }
874 +
875 +               error = Find_Glyph(font, c, CACHED_METRICS);
876 +               if ( error ) {
877 +                       return -1;
878 +               }
879 +               glyph = font->current;
880 +
881 +               if ( (ch == text) && (glyph->minx < 0) ) {
882 +               /* Fixes the texture wrapping bug when the first letter
883 +                * has a negative minx value or horibearing value.  The entire
884 +                * bounding box must be adjusted to be bigger so the entire
885 +                * letter can fit without any texture corruption or wrapping.
886 +                *
887 +                * Effects: First enlarges bounding box.
888 +                * Second, xstart has to start ahead of its normal spot in the
889 +                * negative direction of the negative minx value.
890 +                * (pushes everything to the right).
891 +                *
892 +                * This will make the memory copy of the glyph bitmap data
893 +                * work out correctly.
894 +                * */
895 +                       z -= glyph->minx;
896 +                       
897 +               }
898 +               
899 +               z = x + glyph->minx;
900 +               if ( minx > z ) {
901 +                       minx = z;
902 +               }
903 +               if ( font->style & TTF_STYLE_BOLD ) {
904 +                       x += font->glyph_overhang;
905 +               }
906 +               if ( glyph->advance > glyph->maxx ) {
907 +                       z = x + glyph->advance;
908 +               } else {
909 +                       z = x + glyph->maxx;
910 +               }
911 +               if ( maxx < z ) {
912 +                       maxx = z;
913 +               }
914 +               x += glyph->advance;
915 +
916 +               if ( glyph->miny < miny ) {
917 +                       miny = glyph->miny;
918 +               }
919 +               if ( glyph->maxy > maxy ) {
920 +                       maxy = glyph->maxy;
921 +               }
922 +       }
923 +
924 +       /* Fill the bounds rectangle */
925 +       if ( w ) {
926 +               *w = (maxx - minx);
927 +       }
928 +       if ( h ) {
929 +#if 0 /* This is correct, but breaks many applications */
930 +               *h = (maxy - miny);
931 +#else
932 +               *h = font->height;
933 +#endif
934 +       }
935 +       return status;
936 +}
937 +
938 +/* Convert the Latin-1 text to UNICODE and render it
939 +*/
940 +SDL_Surface *TTF_RenderText_Solid(TTF_Font *font,
941 +                               const char *text, SDL_Color fg)
942 +{
943 +       SDL_Surface *textbuf;
944 +       Uint16 *unicode_text;
945 +       int unicode_len;
946 +
947 +       /* Copy the Latin-1 text to a UNICODE text buffer */
948 +       unicode_len = strlen(text);
949 +       unicode_text = (Uint16 *)ALLOCA((1+unicode_len+1)*(sizeof *unicode_text));
950 +       if ( unicode_text == NULL ) {
951 +               TTF_SetError("Out of memory");
952 +               return(NULL);
953 +       }
954 +       *unicode_text = UNICODE_BOM_NATIVE;
955 +       LATIN1_to_UNICODE(unicode_text+1, text, unicode_len);
956 +
957 +       /* Render the new text */
958 +       textbuf = TTF_RenderUNICODE_Solid(font, unicode_text, fg);
959 +
960 +       /* Free the text buffer and return */
961 +       FREEA(unicode_text);
962 +       return(textbuf);
963 +}
964 +
965 +/* Convert the UTF-8 text to UNICODE and render it
966 +*/
967 +SDL_Surface *TTF_RenderUTF8_Solid(TTF_Font *font,
968 +                               const char *text, SDL_Color fg)
969 +{
970 +       SDL_Surface *textbuf;
971 +       Uint16 *unicode_text;
972 +       int unicode_len;
973 +
974 +       /* Copy the UTF-8 text to a UNICODE text buffer */
975 +       unicode_len = strlen(text);
976 +       unicode_text = (Uint16 *)ALLOCA((1+unicode_len+1)*(sizeof *unicode_text));
977 +       if ( unicode_text == NULL ) {
978 +               TTF_SetError("Out of memory");
979 +               return(NULL);
980 +       }
981 +       *unicode_text = UNICODE_BOM_NATIVE;
982 +       UTF8_to_UNICODE(unicode_text, text, unicode_len);
983 +
984 +       /* Render the new text */
985 +       textbuf = TTF_RenderUNICODE_Solid(font, unicode_text, fg);
986 +
987 +       /* Free the text buffer and return */
988 +       FREEA(unicode_text);
989 +       return(textbuf);
990 +}
991 +
992 +SDL_Surface *TTF_RenderUNICODE_Solid(TTF_Font *font,
993 +                               const Uint16 *text, SDL_Color fg)
994 +{
995 +       int xstart;
996 +       int width;
997 +       int height;
998 +       SDL_Surface* textbuf;
999 +       SDL_Palette* palette;
1000 +       const Uint16* ch;
1001 +       Uint8* src;
1002 +       Uint8* dst;
1003 +       int swapped;
1004 +       int row, col;
1005 +       c_glyph *glyph;
1006 +       FT_Bitmap *current;
1007 +       FT_Error error;
1008 +
1009 +       /* Get the dimensions of the text surface */
1010 +       if( ( TTF_SizeUNICODE(font, text, &width, NULL) < 0 ) || !width ) {
1011 +               TTF_SetError( "Text has zero width" );
1012 +               return NULL;
1013 +       }
1014 +       height = font->height;
1015 +
1016 +       /* Create the target surface */
1017 +       textbuf = SDL_AllocSurface(SDL_SWSURFACE, width, height, 8, 0, 0, 0, 0);
1018 +       if( textbuf == NULL ) {
1019 +               return NULL;
1020 +       }
1021 +
1022 +       /* Fill the palette with the foreground color */
1023 +       palette = textbuf->format->palette;
1024 +       palette->colors[0].r = 255 - fg.r;
1025 +       palette->colors[0].g = 255 - fg.g;
1026 +       palette->colors[0].b = 255 - fg.b;
1027 +       palette->colors[1].r = fg.r;
1028 +       palette->colors[1].g = fg.g;
1029 +       palette->colors[1].b = fg.b;
1030 +       SDL_SetColorKey( textbuf, SDL_SRCCOLORKEY, 0 );
1031 +
1032 +       /* Load and render each character */
1033 +       xstart = 0;
1034 +       swapped = TTF_byteswapped;
1035 +       for( ch=text; *ch; ++ch ) {
1036 +               Uint16 c = *ch;
1037 +               if ( c == UNICODE_BOM_NATIVE ) {
1038 +                       swapped = 0;
1039 +                       if ( text == ch ) {
1040 +                               ++text;
1041 +                       }
1042 +                       continue;
1043 +               }
1044 +               if ( c == UNICODE_BOM_SWAPPED ) {
1045 +                       swapped = 1;
1046 +                       if ( text == ch ) {
1047 +                               ++text;
1048 +                       }
1049 +                       continue;
1050 +               }
1051 +               if ( swapped ) {
1052 +                       c = SDL_Swap16(c);
1053 +               }
1054 +
1055 +               error = Find_Glyph(font, c, CACHED_METRICS|CACHED_BITMAP);
1056 +               if( error ) {
1057 +                       SDL_FreeSurface( textbuf );
1058 +                       return NULL;
1059 +               }
1060 +               glyph = font->current;
1061 +               current = &glyph->bitmap;
1062 +               /* Compensate for wrap around bug with negative minx's */
1063 +               if ( (ch == text) && (glyph->minx < 0) ) {
1064 +                       xstart -= glyph->minx;
1065 +               }
1066 +               
1067 +               for( row = 0; row < current->rows; ++row ) {
1068 +                       /* Make sure we don't go over the limit */
1069 +                       if ( row+glyph->yoffset >= textbuf->h ) {
1070 +                               continue;
1071 +                       }
1072 +                       dst = (Uint8*) textbuf->pixels +
1073 +                               (row+glyph->yoffset) * textbuf->pitch +
1074 +                               xstart + glyph->minx;
1075 +                       src = current->buffer + row * current->pitch;
1076 +
1077 +                       for ( col=current->width; col>0; --col ) {
1078 +                               *dst++ |= *src++;
1079 +                       }
1080 +               }
1081 +
1082 +               xstart += glyph->advance;
1083 +               if ( font->style & TTF_STYLE_BOLD ) {
1084 +                       xstart += font->glyph_overhang;
1085 +               }
1086 +       }
1087 +
1088 +       /* Handle the underline style */
1089 +       if( font->style & TTF_STYLE_UNDERLINE ) {
1090 +               row = font->ascent - font->underline_offset - 1;
1091 +               if ( row >= textbuf->h) {
1092 +                       row = (textbuf->h-1) - font->underline_height;
1093 +               }
1094 +               dst = (Uint8 *)textbuf->pixels + row * textbuf->pitch;
1095 +               for ( row=font->underline_height; row>0; --row ) {
1096 +                       /* 1 because 0 is the bg color */
1097 +                       memset( dst, 1, textbuf->w );
1098 +                       dst += textbuf->pitch;
1099 +               }
1100 +       }
1101 +       return textbuf;
1102 +}
1103 +
1104 +SDL_Surface *TTF_RenderGlyph_Solid(TTF_Font *font, Uint16 ch, SDL_Color fg)
1105 +{
1106 +       SDL_Surface *textbuf;
1107 +       SDL_Palette *palette;
1108 +       Uint8 *src, *dst;
1109 +       int row;
1110 +       FT_Error error;
1111 +       c_glyph *glyph;
1112 +
1113 +       /* Get the glyph itself */
1114 +       error = Find_Glyph(font, ch, CACHED_METRICS|CACHED_BITMAP);
1115 +       if ( error ) {
1116 +               return(NULL);
1117 +       }
1118 +       glyph = font->current;
1119 +
1120 +       /* Create the target surface */
1121 +       textbuf = SDL_CreateRGBSurface( SDL_SWSURFACE,
1122 +                                       glyph->bitmap.pitch,
1123 +                                       glyph->bitmap.rows,
1124 +                                       8, 0, 0, 0, 0 );
1125 +       if ( ! textbuf ) {
1126 +               return(NULL);
1127 +       }
1128 +
1129 +       /* Fill the palette with the foreground color */
1130 +       palette = textbuf->format->palette;
1131 +       palette->colors[0].r = 255-fg.r;
1132 +       palette->colors[0].g = 255-fg.g;
1133 +       palette->colors[0].b = 255-fg.b;
1134 +       palette->colors[1].r = fg.r;
1135 +       palette->colors[1].g = fg.g;
1136 +       palette->colors[1].b = fg.b;
1137 +       SDL_SetColorKey(textbuf, SDL_SRCCOLORKEY, 0);
1138 +
1139 +       /* Copy the character from the pixmap */
1140 +       src = glyph->bitmap.buffer;
1141 +       dst = (Uint8*) textbuf->pixels;
1142 +       for ( row = 0; row < textbuf->h; ++row ) {
1143 +               memcpy( dst, src, glyph->bitmap.pitch );
1144 +               src += glyph->bitmap.pitch;
1145 +               dst += textbuf->pitch;
1146 +       }
1147 +
1148 +       /* Handle the underline style */
1149 +       if( font->style & TTF_STYLE_UNDERLINE ) {
1150 +               row = font->ascent - font->underline_offset - 1;
1151 +               if ( row >= textbuf->h) {
1152 +                       row = (textbuf->h-1) - font->underline_height;
1153 +               }
1154 +               dst = (Uint8 *)textbuf->pixels + row * textbuf->pitch;
1155 +               for ( row=font->underline_height; row>0; --row ) {
1156 +                       /* 1 because 0 is the bg color */
1157 +                       memset( dst, 1, textbuf->w );
1158 +                       dst += textbuf->pitch;
1159 +               }
1160 +       }
1161 +       return(textbuf);
1162 +}
1163 +
1164 +
1165 +/* Convert the Latin-1 text to UNICODE and render it
1166 +*/
1167 +SDL_Surface *TTF_RenderText_Shaded(TTF_Font *font,
1168 +                               const char *text, SDL_Color fg, SDL_Color bg)
1169 +{
1170 +       SDL_Surface *textbuf;
1171 +       Uint16 *unicode_text;
1172 +       int unicode_len;
1173 +
1174 +       /* Copy the Latin-1 text to a UNICODE text buffer */
1175 +       unicode_len = strlen(text);
1176 +       unicode_text = (Uint16 *)ALLOCA((1+unicode_len+1)*(sizeof *unicode_text));
1177 +       if ( unicode_text == NULL ) {
1178 +               TTF_SetError("Out of memory");
1179 +               return(NULL);
1180 +       }
1181 +       *unicode_text = UNICODE_BOM_NATIVE;
1182 +       LATIN1_to_UNICODE(unicode_text+1, text, unicode_len);
1183 +
1184 +       /* Render the new text */
1185 +       textbuf = TTF_RenderUNICODE_Shaded(font, unicode_text, fg, bg);
1186 +
1187 +       /* Free the text buffer and return */
1188 +       FREEA(unicode_text);
1189 +       return(textbuf);
1190 +}
1191 +
1192 +/* Convert the UTF-8 text to UNICODE and render it
1193 +*/
1194 +SDL_Surface *TTF_RenderUTF8_Shaded(TTF_Font *font,
1195 +                               const char *text, SDL_Color fg, SDL_Color bg)
1196 +{
1197 +       SDL_Surface *textbuf;
1198 +       Uint16 *unicode_text;
1199 +       int unicode_len;
1200 +
1201 +       /* Copy the UTF-8 text to a UNICODE text buffer */
1202 +       unicode_len = strlen(text);
1203 +       unicode_text = (Uint16 *)ALLOCA((1+unicode_len+1)*(sizeof *unicode_text));
1204 +       if ( unicode_text == NULL ) {
1205 +               TTF_SetError("Out of memory");
1206 +               return(NULL);
1207 +       }
1208 +       *unicode_text = UNICODE_BOM_NATIVE;
1209 +       UTF8_to_UNICODE(unicode_text+1, text, unicode_len);
1210 +
1211 +       /* Render the new text */
1212 +       textbuf = TTF_RenderUNICODE_Shaded(font, unicode_text, fg, bg);
1213 +
1214 +       /* Free the text buffer and return */
1215 +       FREEA(unicode_text);
1216 +       return(textbuf);
1217 +}
1218 +
1219 +SDL_Surface* TTF_RenderUNICODE_Shaded( TTF_Font* font,
1220 +                                      const Uint16* text,
1221 +                                      SDL_Color fg,
1222 +                                      SDL_Color bg )
1223 +{
1224 +       int xstart;
1225 +       int width;
1226 +       int height;
1227 +       SDL_Surface* textbuf;
1228 +       SDL_Palette* palette;
1229 +       int index;
1230 +       int rdiff;
1231 +       int gdiff;
1232 +       int bdiff;
1233 +       const Uint16* ch;
1234 +       Uint8* src;
1235 +       Uint8* dst;
1236 +       int swapped;
1237 +       int row, col;
1238 +       FT_Bitmap* current;
1239 +       c_glyph *glyph;
1240 +       FT_Error error;
1241 +
1242 +       /* Get the dimensions of the text surface */
1243 +       if( ( TTF_SizeUNICODE(font, text, &width, NULL) < 0 ) || !width ) {
1244 +               TTF_SetError("Text has zero width");
1245 +               return NULL;
1246 +       }
1247 +       height = font->height;
1248 +
1249 +       /* Create the target surface */
1250 +       textbuf = SDL_AllocSurface(SDL_SWSURFACE, width, height, 8, 0, 0, 0, 0);
1251 +       if( textbuf == NULL ) {
1252 +               return NULL;
1253 +       }
1254 +
1255 +       /* Fill the palette with NUM_GRAYS levels of shading from bg to fg */
1256 +       palette = textbuf->format->palette;
1257 +       rdiff = fg.r - bg.r;
1258 +       gdiff = fg.g - bg.g;
1259 +       bdiff = fg.b - bg.b;
1260 +
1261 +       for( index = 0; index < NUM_GRAYS; ++index ) {
1262 +               palette->colors[index].r = bg.r + (index*rdiff) / (NUM_GRAYS-1);
1263 +               palette->colors[index].g = bg.g + (index*gdiff) / (NUM_GRAYS-1);
1264 +               palette->colors[index].b = bg.b + (index*bdiff) / (NUM_GRAYS-1);
1265 +       }
1266 +
1267 +       /* Load and render each character */
1268 +       xstart = 0;
1269 +       swapped = TTF_byteswapped;
1270 +       for( ch = text; *ch; ++ch ) {
1271 +               Uint16 c = *ch;
1272 +               if ( c == UNICODE_BOM_NATIVE ) {
1273 +                       swapped = 0;
1274 +                       if ( text == ch ) {
1275 +                               ++text;
1276 +                       }
1277 +                       continue;
1278 +               }
1279 +               if ( c == UNICODE_BOM_SWAPPED ) {
1280 +                       swapped = 1;
1281 +                       if ( text == ch ) {
1282 +                               ++text;
1283 +                       }
1284 +                       continue;
1285 +               }
1286 +               if ( swapped ) {
1287 +                       c = SDL_Swap16(c);
1288 +               }
1289 +
1290 +               error = Find_Glyph(font, c, CACHED_METRICS|CACHED_PIXMAP);
1291 +               if( error ) {
1292 +                       SDL_FreeSurface( textbuf );
1293 +                       return NULL;
1294 +               }
1295 +               glyph = font->current;
1296 +               /* Compensate for the wrap around with negative minx's */
1297 +               if ( (ch == text) && (glyph->minx < 0) ) {
1298 +                       xstart -= glyph->minx;
1299 +               }
1300 +               
1301 +               current = &glyph->pixmap;
1302 +               for( row = 0; row < current->rows; ++row ) {
1303 +                       /* Make sure we don't go over the limit */
1304 +                       if ( row+glyph->yoffset >= textbuf->h ) {
1305 +                               continue;
1306 +                       }
1307 +                       dst = (Uint8*) textbuf->pixels +
1308 +                               (row+glyph->yoffset) * textbuf->pitch +
1309 +                               xstart + glyph->minx;
1310 +                       src = current->buffer + row * current->pitch;
1311 +                       for ( col=current->width; col>0; --col ) {
1312 +                               *dst++ |= *src++;
1313 +                       }
1314 +               }
1315 +
1316 +               xstart += glyph->advance;
1317 +               if( font->style & TTF_STYLE_BOLD ) {
1318 +                       xstart += font->glyph_overhang;
1319 +               }
1320 +       }
1321 +
1322 +       /* Handle the underline style */
1323 +       if( font->style & TTF_STYLE_UNDERLINE ) {
1324 +               row = font->ascent - font->underline_offset - 1;
1325 +               if ( row >= textbuf->h) {
1326 +                       row = (textbuf->h-1) - font->underline_height;
1327 +               }
1328 +               dst = (Uint8 *)textbuf->pixels + row * textbuf->pitch;
1329 +               for ( row=font->underline_height; row>0; --row ) {
1330 +                       memset( dst, NUM_GRAYS - 1, textbuf->w );
1331 +                       dst += textbuf->pitch;
1332 +               }
1333 +       }
1334 +       return textbuf;
1335 +}
1336 +
1337 +SDL_Surface* TTF_RenderGlyph_Shaded( TTF_Font* font,
1338 +                                    Uint16 ch,
1339 +                                    SDL_Color fg,
1340 +                                    SDL_Color bg )
1341 +{
1342 +       SDL_Surface* textbuf;
1343 +       SDL_Palette* palette;
1344 +       int index;
1345 +       int rdiff;
1346 +       int gdiff;
1347 +       int bdiff;
1348 +       Uint8* src;
1349 +       Uint8* dst;
1350 +       int row;
1351 +       FT_Error error;
1352 +       c_glyph* glyph;
1353 +
1354 +       /* Get the glyph itself */
1355 +       error = Find_Glyph(font, ch, CACHED_METRICS|CACHED_PIXMAP);
1356 +       if( error ) {
1357 +               return NULL;
1358 +       }
1359 +       glyph = font->current;
1360 +
1361 +       /* Create the target surface */
1362 +       textbuf = SDL_CreateRGBSurface( SDL_SWSURFACE,
1363 +                                       glyph->pixmap.width,
1364 +                                       glyph->pixmap.rows,
1365 +                                       8, 0, 0, 0, 0 );
1366 +       if( !textbuf ) {
1367 +               return NULL;
1368 +       }
1369 +
1370 +       /* Fill the palette with NUM_GRAYS levels of shading from bg to fg */
1371 +       palette = textbuf->format->palette;
1372 +       rdiff = fg.r - bg.r;
1373 +       gdiff = fg.g - bg.g;
1374 +       bdiff = fg.b - bg.b;
1375 +       for( index = 0; index < NUM_GRAYS; ++index ) {
1376 +               palette->colors[index].r = bg.r + (index*rdiff) / (NUM_GRAYS-1);
1377 +               palette->colors[index].g = bg.g + (index*gdiff) / (NUM_GRAYS-1);
1378 +               palette->colors[index].b = bg.b + (index*bdiff) / (NUM_GRAYS-1);
1379 +       }
1380 +
1381 +       /* Copy the character from the pixmap */
1382 +       src = glyph->pixmap.buffer;
1383 +       dst = (Uint8*) textbuf->pixels;
1384 +       for ( row = 0; row < textbuf->h; ++row ) {
1385 +               memcpy( dst, src, glyph->pixmap.pitch );
1386 +               src += glyph->pixmap.pitch;
1387 +               dst += textbuf->pitch;
1388 +       }
1389 +
1390 +       /* Handle the underline style */
1391 +       if( font->style & TTF_STYLE_UNDERLINE ) {
1392 +               row = font->ascent - font->underline_offset - 1;
1393 +               if ( row >= textbuf->h) {
1394 +                       row = (textbuf->h-1) - font->underline_height;
1395 +               }
1396 +               dst = (Uint8 *)textbuf->pixels + row * textbuf->pitch;
1397 +               for ( row=font->underline_height; row>0; --row ) {
1398 +                       memset( dst, NUM_GRAYS - 1, textbuf->w );
1399 +                       dst += textbuf->pitch;
1400 +               }
1401 +       }
1402 +       return textbuf;
1403 +}
1404 +
1405 +/* Convert the Latin-1 text to UNICODE and render it
1406 +*/
1407 +SDL_Surface *TTF_RenderText_Blended(TTF_Font *font,
1408 +                               const char *text, SDL_Color fg)
1409 +{
1410 +       SDL_Surface *textbuf;
1411 +       Uint16 *unicode_text;
1412 +       int unicode_len;
1413 +
1414 +       /* Copy the Latin-1 text to a UNICODE text buffer */
1415 +       unicode_len = strlen(text);
1416 +       unicode_text = (Uint16 *)ALLOCA((1+unicode_len+1)*(sizeof *unicode_text));
1417 +       if ( unicode_text == NULL ) {
1418 +               TTF_SetError("Out of memory");
1419 +               return(NULL);
1420 +       }
1421 +       *unicode_text = UNICODE_BOM_NATIVE;
1422 +       LATIN1_to_UNICODE(unicode_text+1, text, unicode_len);
1423 +
1424 +       /* Render the new text */
1425 +       textbuf = TTF_RenderUNICODE_Blended(font, unicode_text, fg);
1426 +
1427 +       /* Free the text buffer and return */
1428 +       FREEA(unicode_text);
1429 +       return(textbuf);
1430 +}
1431 +
1432 +/* Convert the UTF-8 text to UNICODE and render it
1433 +*/
1434 +SDL_Surface *TTF_RenderUTF8_Blended(TTF_Font *font,
1435 +                               const char *text, SDL_Color fg)
1436 +{
1437 +       SDL_Surface *textbuf;
1438 +       Uint16 *unicode_text;
1439 +       int unicode_len;
1440 +
1441 +       /* Copy the UTF-8 text to a UNICODE text buffer */
1442 +       unicode_len = strlen(text);
1443 +       unicode_text = (Uint16 *)ALLOCA((1+unicode_len+1)*(sizeof *unicode_text));
1444 +       if ( unicode_text == NULL ) {
1445 +               TTF_SetError("Out of memory");
1446 +               return(NULL);
1447 +       }
1448 +       *unicode_text = UNICODE_BOM_NATIVE;
1449 +       UTF8_to_UNICODE(unicode_text+1, text, unicode_len);
1450 +
1451 +       /* Render the new text */
1452 +       textbuf = TTF_RenderUNICODE_Blended(font, unicode_text, fg);
1453 +
1454 +       /* Free the text buffer and return */
1455 +       FREEA(unicode_text);
1456 +       return(textbuf);
1457 +}
1458 +
1459 +SDL_Surface *TTF_RenderUNICODE_Blended(TTF_Font *font,
1460 +                               const Uint16 *text, SDL_Color fg)
1461 +{
1462 +       int xstart;
1463 +       int width, height;
1464 +       SDL_Surface *textbuf;
1465 +       Uint32 alpha;
1466 +       Uint32 pixel;
1467 +       const Uint16 *ch;
1468 +       Uint8 *src;
1469 +       Uint32 *dst;
1470 +       int swapped;
1471 +       int row, col;
1472 +       c_glyph *glyph;
1473 +       FT_Error error;
1474 +
1475 +       /* Get the dimensions of the text surface */
1476 +       if ( (TTF_SizeUNICODE(font, text, &width, NULL) < 0) || !width ) {
1477 +               TTF_SetError("Text has zero width");
1478 +               return(NULL);
1479 +       }
1480 +       height = font->height;
1481 +
1482 +       textbuf = SDL_AllocSurface(SDL_SWSURFACE, width, height, 32,
1483 +                  0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000);
1484 +       if ( textbuf == NULL ) {
1485 +               return(NULL);
1486 +       }
1487 +
1488 +       /* Load and render each character */
1489 +       xstart = 0;
1490 +       swapped = TTF_byteswapped;
1491 +       pixel = (fg.r<<16)|(fg.g<<8)|fg.b;
1492 +       for ( ch=text; *ch; ++ch ) {
1493 +               Uint16 c = *ch;
1494 +               if ( c == UNICODE_BOM_NATIVE ) {
1495 +                       swapped = 0;
1496 +                       if ( text == ch ) {
1497 +                               ++text;
1498 +                       }
1499 +                       continue;
1500 +               }
1501 +               if ( c == UNICODE_BOM_SWAPPED ) {
1502 +                       swapped = 1;
1503 +                       if ( text == ch ) {
1504 +                               ++text;
1505 +                       }
1506 +                       continue;
1507 +               }
1508 +               if ( swapped ) {
1509 +                       c = SDL_Swap16(c);
1510 +               }
1511 +               error = Find_Glyph(font, c, CACHED_METRICS|CACHED_PIXMAP);
1512 +               if( error ) {
1513 +                       SDL_FreeSurface( textbuf );
1514 +                       return NULL;
1515 +               }
1516 +               glyph = font->current;
1517 +               width = glyph->pixmap.width;
1518 +               /* Compensate for the wrap around bug with negative minx's */
1519 +               if ( (ch == text) && (glyph->minx < 0) ) {
1520 +                       xstart -= glyph->minx;
1521 +               }
1522 +
1523 +               for ( row = 0; row < glyph->pixmap.rows; ++row ) {
1524 +                       /* Make sure we don't go over the limit */
1525 +                       if ( row+glyph->yoffset >= textbuf->h ) {
1526 +                               continue;
1527 +                       }
1528 +                       dst = (Uint32*) textbuf->pixels +
1529 +                               (row+glyph->yoffset) * textbuf->pitch/4 +
1530 +                               xstart + glyph->minx;
1531 +                       /* Added code to adjust src pointer for pixmaps to
1532 +                        * account for pitch.
1533 +                        * */
1534 +                       src = (Uint8*) (glyph->pixmap.buffer + glyph->pixmap.pitch * row);
1535 +                       for ( col = width; col>0; --col) {
1536 +                               alpha = *src++;
1537 +                               *dst++ |= pixel | (alpha << 24);
1538 +                       }
1539 +               }
1540 +
1541 +               xstart += glyph->advance;
1542 +               if ( font->style & TTF_STYLE_BOLD ) {
1543 +                       xstart += font->glyph_overhang;
1544 +               }
1545 +       }
1546 +
1547 +       /* Handle the underline style */
1548 +       if( font->style & TTF_STYLE_UNDERLINE ) {
1549 +               row = font->ascent - font->underline_offset - 1;
1550 +               if ( row >= textbuf->h) {
1551 +                       row = (textbuf->h-1) - font->underline_height;
1552 +               }
1553 +               dst = (Uint32 *)textbuf->pixels + row * textbuf->pitch/4;
1554 +               pixel |= 0xFF000000; /* Amask */
1555 +               for ( row=font->underline_height; row>0; --row ) {
1556 +                       for ( col=0; col < textbuf->w; ++col ) {
1557 +                               dst[col] = pixel;
1558 +                       }
1559 +                       dst += textbuf->pitch/4;
1560 +               }
1561 +       }
1562 +       return(textbuf);
1563 +}
1564 +
1565 +SDL_Surface *TTF_RenderGlyph_Blended(TTF_Font *font, Uint16 ch, SDL_Color fg)
1566 +{
1567 +       SDL_Surface *textbuf;
1568 +       Uint32 alpha;
1569 +       Uint32 pixel;
1570 +       Uint8 *src;
1571 +       Uint32 *dst;
1572 +       int row, col;
1573 +       FT_Error error;
1574 +       c_glyph *glyph;
1575 +
1576 +       /* Get the glyph itself */
1577 +       error = Find_Glyph(font, ch, CACHED_METRICS|CACHED_PIXMAP);
1578 +       if ( error ) {
1579 +               return(NULL);
1580 +       }
1581 +       glyph = font->current;
1582 +
1583 +       textbuf = SDL_CreateRGBSurface(SDL_SWSURFACE,
1584 +                     glyph->pixmap.width, glyph->pixmap.rows, 32,
1585 +                  0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000);
1586 +       if ( ! textbuf ) {
1587 +               return(NULL);
1588 +       }
1589 +
1590 +       /* Copy the character from the pixmap */
1591 +       pixel = (fg.r<<16)|(fg.g<<8)|fg.b;
1592 +       for ( row=0; row<textbuf->h; ++row ) {
1593 +               /* Changed src to take pitch into account, not just width */
1594 +               src = glyph->pixmap.buffer + row * glyph->pixmap.pitch;
1595 +               dst = (Uint32 *)textbuf->pixels + row * textbuf->pitch/4;
1596 +               for ( col=0; col<glyph->pixmap.width; ++col ) {
1597 +                       alpha = *src++;
1598 +                       *dst++ = pixel | (alpha << 24);
1599 +               }
1600 +       }
1601 +
1602 +       /* Handle the underline style */
1603 +       if( font->style & TTF_STYLE_UNDERLINE ) {
1604 +               row = font->ascent - font->underline_offset - 1;
1605 +               if ( row >= textbuf->h) {
1606 +                       row = (textbuf->h-1) - font->underline_height;
1607 +               }
1608 +               dst = (Uint32 *)textbuf->pixels + row * textbuf->pitch/4;
1609 +               pixel |= 0xFF000000; /* Amask */
1610 +               for ( row=font->underline_height; row>0; --row ) {
1611 +                       for ( col=0; col < textbuf->w; ++col ) {
1612 +                               dst[col] = pixel;
1613 +                       }
1614 +                       dst += textbuf->pitch/4;
1615 +               }
1616 +       }
1617 +       return(textbuf);
1618 +}
1619 +
1620 +void TTF_SetFontStyle( TTF_Font* font, int style )
1621 +{
1622 +       font->style = style;
1623 +       Flush_Cache( font );
1624 +}
1625 +
1626 +int TTF_GetFontStyle( TTF_Font* font )
1627 +{
1628 +       return font->style;
1629 +}
1630 +
1631 +void TTF_Quit( void )
1632 +{
1633 +       if ( TTF_initialized ) {
1634 +               if ( --TTF_initialized == 0 ) {
1635 +                       FT_Done_FreeType( library );
1636 +               }
1637 +       }
1638 +}
1639 +
1640 +int TTF_WasInit( void )
1641 +{
1642 +       return TTF_initialized;
1643 +}
This page took 1.66865 seconds and 4 git commands to generate.