Patch from Guillaume Cottenceau to add some missing functions
[sdlpango.git] / src / SDL_Pango.c
blobb969bc1fdc0dcfe59298627288f4a10f1a274062
1 /* SDL_Pango.c -- A companion library to SDL for working with Pango.
2 Copyright (C) 2004 NAKAMURA Ken'ichi
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
14 You should have received a copy of the GNU Lesser General Public
15 License along with this library; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
19 /*!
20 \mainpage
22 \section intro Introduction
24 Pango is the text rendering engine of GNOME 2.x. SDL_Pango connects the
25 engine to SDL. In Windows, pre-built binary package (MSI and merge module)
26 is provided.
28 \subsection dist Distribution
30 If you are a game software developer, you should know the difficulties of
31 distribution. So I will start to introduce SDL_Pango from the viewpoint
32 of distribution.
34 In Un*x, SDL_Pango is hard to use as system-independent module, because
35 it depends on fontconfig and Pango which are designed as system-singleton
36 modules. If you use SDL_Pango, your software will require those modules
37 installed to target system. If your software is shipped as shrink-wrap
38 package, it may cause much problem on your support desk. You should
39 carefully design your installation process.
41 In Windows, SDL_Pango is distributed as "merge module" which contains
42 fontconfig and Pango. Those binaries are modified as side-by-side components.
43 You should use Windows Installer and merge the module
44 on your MSI package. The merge module not only contains files, but also includes
45 custom action which must be run at installation.
47 \subsection api High-level API
49 From the viewpoint of text rendering, the heart of SDL_Pango is high-level API.
50 Other text rendering APIs, like DrawText() of Windows, font and text must be
51 specified separately. In SDL_Pango, font specification is embedded in text like
52 HTML:
54 \code
55 <span font_family="Courier New"><i>This is Courier New and italic.</i></span>
56 \endcode
58 Color, size, subscript/superscript, obliquing, weight, and other many features
59 are also available in same way.
61 \subsection i18n Internationalized Text
63 Internationalized text is another key feature. Text is specified by UTF-8. RTL
64 script (Arabic and Hebrew) and complicated rendering (Arabic, Indic and Thai) are
65 supported. You can see it with GNOME 2.x.
67 \section get Getting Started
69 \subsection getlatest Get latest files
71 Get latest files from http://sourceforge.net/projects/sdlpango/ .
73 \subsection install Install Header and Library
75 In Windows and VS2003, I strongly recommend you to install MSI package. It contains Pango
76 and fontconfig binaries which are modified as side-by-side components. It is
77 nearly impossible to build them. (I spent much time to build them...)
79 In MinGW, I recommend you to use VS2003. Otherwise you may run into the maze of
80 distribution. If you insist MinGW, you should use MinGW binary archive.
82 In Un*x, installation consists of:
84 \code
85 ./configure
86 make
87 make install
88 \endcode
90 \subsection inc Includes
92 To use SDL_Pango functions in a C/C++ source code file, you must use the SDL_Pango.h
93 include file:
95 \code
96 #include "SDL_Pango.h"
97 \endcode
99 In Windows, SDL_Pango.h is installed on \c \%ProgramFiles\%\\SDL_Pango \c Development\\include
100 (usually \c C:\\Program \c Files\\SDL_Pango \c Development\\include). You should add this
101 directory to include path.
103 \subsection comp Compiling
105 In Un*x, to link with SDL_Pango you should use sdl-config to get the required SDL
106 compilation options. After that, compiling with SDL_Pango is quite easy.
108 Note: Some systems may not have the SDL_Pango library and include file in the same
109 place as the SDL library and includes are located, in that case you will need to
110 add more -I and -L paths to these command lines.
112 Simple Example for compiling an object file:
114 \code
115 cc -c `sdl-config --cflags` mysource.c
116 \endcode
118 Simple Example for linking an object file:
120 \code
121 cc -o myprogram mysource.o `sdl-config --libs` -lSDL_Pango
122 \endcode
124 Now myprogram is ready to run.
126 You can see a sample of autoconfiscation in 'test' directory.
128 In Windows, MSI package installs many dlls to \c \%ProgramFiles\%\\SDL_Pango \c Development\\import_lib.
129 To link with SDL_Pango you should use SDL_Pango.lib.
131 SDL_Pango.dll depends on many dlls and other many files. Those dlls are installed on
132 \c \%ProgramFiles\%\\SDL_Pango \c Development\\bin. MSI package adds the directory to PATH environment
133 variable.
135 \section devel Development
137 \subsection font Font Handling
139 In Un*x, font handling depends on fontconfig of your system.
141 In Windows, local.conf of fontconfig is placed on \c \%ProgramFiles\%\\SDL_Pango \c Development\\etc\\fonts.
142 You should know about fontconfig's font cache mechanism.
144 \subsection example Step-by-step Example
146 The operation of SDL_Pango is done via context.
148 \code
149 SDLPango_Context *context = SDLPango_CreateContext();
150 \endcode
152 Specify default colors and minimum surface size.
154 \code
155 SDLPango_SetDefaultColor(context, MATRIX_TRANSPARENT_BACK_WHITE_LETTER);
156 SDLPango_SetMinimumSize(context, 640, 0);
157 \endcode
159 Set markup text.
161 \code
162 SDLPango_SetMarkup(context, "This is <i>markup</i> text.", -1);
163 \endcode
165 Now you can get the size of surface.
167 \code
168 int w = SDLPango_GetLayoutWidth(context);
169 int h = SDLPango_GetLayoutHeight(context);
170 \endcode
172 Create surface to draw.
174 \code
175 int margin_x = 10;
176 int margin_y = 10;
177 SDL_Surface *surface = SDL_CreateRGBSurface(SDL_SWSURFACE,
178 w + margin_x * 2, h + margin_y * 2,
179 32, (Uint32)(255 << (8 * 3)), (Uint32)(255 << (8 * 2)),
180 (Uint32)(255 << (8 * 1)), 255);
181 \endcode
183 And draw on it.
185 \code
186 SDLPango_Draw(context, surface, margin_x, margin_y);
187 \endcode
189 You must free the surface by yourself.
191 \code
192 SDL_FreeSurface(surface);
193 \endcode
195 Free context.
197 \code
198 SDLPango_FreeContext(context);
199 \endcode
201 You can see actual code in \c test/testbench.cpp.
203 \subsection pack Packaging
205 In Un*x, do it yourself.
207 In Windows, font files must be installed on apprication folder (usually
208 \c C:\\Program \c Files\\[Manufacturer]\\[ProductName]). The property of
209 apprication folder must be \c TARGETDIR (this is default setting of VS2003).
210 SDL.dll also must be installed on apprication folder. Add SDL_Pango.msm to
211 your MSI package.
213 \section ack Acknowledgment
215 SDL_Pango is developed with financial assistance of Information-technology Promotion Agency, Japan.
217 - NAKAMURA Ken'ichi <nakamura@sbp.fp.a.u-tokyo.ac.jp>
221 /*! @file
222 @brief Implementation of SDL_Pango
224 @author NAKAMURA Ken'ichi
225 @date 2004/12/07
226 $Revision: 1.6 $
229 #include <pango/pango.h>
230 #include <pango/pangoft2.h>
232 #include "SDL_Pango.h"
234 //! non-zero if initialized
235 static int IS_INITIALIZED = 0;
237 #define DEFAULT_FONT_FAMILY "Sans"
238 #define DEFAULT_FONT_SIZE 12
239 #define DEFAULT_DPI 96
240 #define _MAKE_FONT_NAME(family, size) family " " #size
241 #define MAKE_FONT_NAME(family, size) _MAKE_FONT_NAME(family, size)
242 #define DEFAULT_DEPTH 32
243 #define DEFAULT_RMASK (Uint32)(255 << (8 * 3))
244 #define DEFAULT_GMASK (Uint32)(255 << (8 * 2))
245 #define DEFAULT_BMASK (Uint32)(255 << (8 * 1))
246 #define DEFAULT_AMASK (Uint32)255
248 static FT_Bitmap *createFTBitmap(int width, int height);
250 static void freeFTBitmap(FT_Bitmap *bitmap);
252 static void getItemProperties (
253 PangoItem *item,
254 PangoUnderline *uline,
255 gboolean *strikethrough,
256 gint *rise,
257 PangoColor *fg_color,
258 gboolean *fg_set,
259 PangoColor *bg_color,
260 gboolean *bg_set,
261 gboolean *shape_set,
262 PangoRectangle *ink_rect,
263 PangoRectangle *logical_rect);
265 static void clearFTBitmap(FT_Bitmap *bitmap);
267 typedef struct _surfaceArgs {
268 Uint32 flags;
269 int depth;
270 Uint32 Rmask;
271 Uint32 Gmask;
272 Uint32 Bmask;
273 Uint32 Amask;
274 } surfaceArgs;
276 typedef struct _contextImpl {
277 PangoContext *context;
278 PangoFontMap *font_map;
279 PangoFontDescription *font_desc;
280 PangoLayout *layout;
281 surfaceArgs surface_args;
282 FT_Bitmap *tmp_ftbitmap;
283 SDLPango_Matrix color_matrix;
284 int min_width;
285 int min_height;
286 } contextImpl;
290 Initialize the Glib and Pango API.
291 This must be called before using other functions in this library,
292 excepting SDLPango_WasInit.
293 SDL does not have to be initialized before this call.
296 @return always 0.
299 SDLPango_Init()
301 g_type_init();
303 IS_INITIALIZED = -1;
305 return 0;
309 Query the initilization status of the Glib and Pango API.
310 You may, of course, use this before SDLPango_Init to avoid
311 initilizing twice in a row.
313 @return zero when already initialized.
314 non-zero when not initialized.
317 SDLPango_WasInit()
319 return IS_INITIALIZED;
323 Draw glyphs on rect.
325 @param *context [in] Context
326 @param *surface [out] Surface to draw on it
327 @param *color_matrix [in] Foreground and background color
328 @param *font [in] Innter variable of Pango
329 @param *glyphs [in] Innter variable of Pango
330 @param *rect [in] Draw on this area
331 @param baseline [in] Horizontal location of glyphs
333 static void
334 drawGlyphString(
335 SDLPango_Context *context,
336 SDL_Surface *surface,
337 SDLPango_Matrix *color_matrix,
338 PangoFont *font,
339 PangoGlyphString *glyphs,
340 SDL_Rect *rect,
341 int baseline)
343 pango_ft2_render(context->tmp_ftbitmap, font, glyphs, rect->x, rect->y + baseline);
345 SDLPango_CopyFTBitmapToSurface(
346 context->tmp_ftbitmap,
347 surface,
348 color_matrix,
349 rect);
351 clearFTBitmap(context->tmp_ftbitmap);
355 Draw horizontal line of a pixel.
357 @param *surface [out] Surface to draw on it
358 @param *color_matrix [in] Foreground and background color
359 @param y [in] Y location of line
360 @param start [in] Left of line
361 @param end [in] Right of line
363 static void drawHLine(
364 SDL_Surface *surface,
365 SDLPango_Matrix *color_matrix,
366 int y,
367 int start,
368 int end)
370 Uint8 *p;
371 Uint16 *p16;
372 Uint32 *p32;
373 Uint32 color;
374 int ix;
375 int pixel_bytes = surface->format->BytesPerPixel;
377 if (y < 0 || y >= surface->h)
378 return;
380 if (end <= 0 || start >= surface->w)
381 return;
383 if (start < 0)
384 start = 0;
386 if (end >= surface->w)
387 end = surface->w;
389 p = (Uint8 *)(surface->pixels) + y * surface->pitch + start * pixel_bytes;
390 color = SDL_MapRGBA(surface->format,
391 color_matrix->m[0][1],
392 color_matrix->m[1][1],
393 color_matrix->m[2][1],
394 color_matrix->m[3][1]);
396 switch(pixel_bytes) {
397 case 2:
398 p16 = (Uint16 *)p;
399 for (ix = 0; ix < end - start; ix++)
400 *p16++ = (Uint16)color;
401 break;
402 case 4:
403 p32 = (Uint32 *)p;
404 for (ix = 0; ix < end - start; ix++)
405 *p32++ = color;
406 break;
407 default:
408 SDL_SetError("surface->format->BytesPerPixel is invalid value");
409 break;
414 Draw a line.
416 @param *context [in] Context
417 @param *surface [out] Surface to draw on it
418 @param *line [in] Innter variable of Pango
419 @param x [in] X location of line
420 @param y [in] Y location of line
421 @param height [in] Height of line
422 @param baseline [in] Rise / sink of line (for super/subscript)
424 static void
425 drawLine(
426 SDLPango_Context *context,
427 SDL_Surface *surface,
428 PangoLayoutLine *line,
429 gint x,
430 gint y,
431 gint height,
432 gint baseline)
434 GSList *tmp_list = line->runs;
435 PangoColor fg_color, bg_color;
436 PangoRectangle logical_rect;
437 PangoRectangle ink_rect;
438 int x_off = 0;
440 while (tmp_list) {
441 SDLPango_Matrix color_matrix = context->color_matrix;
442 PangoUnderline uline = PANGO_UNDERLINE_NONE;
443 gboolean strike, fg_set, bg_set, shape_set;
444 gint rise, risen_y;
445 PangoLayoutRun *run = tmp_list->data;
446 SDL_Rect d_rect;
448 tmp_list = tmp_list->next;
450 getItemProperties(run->item,
451 &uline, &strike, &rise,
452 &fg_color, &fg_set, &bg_color, &bg_set,
453 &shape_set, &ink_rect, &logical_rect);
455 risen_y = y + baseline - PANGO_PIXELS (rise);
457 if(fg_set) {
458 color_matrix.m[0][1] = (Uint8)(fg_color.red >> 8);
459 color_matrix.m[1][1] = (Uint8)(fg_color.green >> 8);
460 color_matrix.m[2][1] = (Uint8)(fg_color.blue >> 8);
461 color_matrix.m[3][1] = 255;
462 if(color_matrix.m[3][0] == 0) {
463 color_matrix.m[0][0] = (Uint8)(fg_color.red >> 8);
464 color_matrix.m[1][0] = (Uint8)(fg_color.green >> 8);
465 color_matrix.m[2][0] = (Uint8)(fg_color.blue >> 8);
469 if (bg_set) {
470 color_matrix.m[0][0] = (Uint8)(bg_color.red >> 8);
471 color_matrix.m[1][0] = (Uint8)(bg_color.green >> 8);
472 color_matrix.m[2][0] = (Uint8)(bg_color.blue >> 8);
473 color_matrix.m[3][0] = 255;
476 if(! shape_set) {
477 if (uline == PANGO_UNDERLINE_NONE)
478 pango_glyph_string_extents (run->glyphs, run->item->analysis.font,
479 NULL, &logical_rect);
480 else
481 pango_glyph_string_extents (run->glyphs, run->item->analysis.font,
482 &ink_rect, &logical_rect);
484 d_rect.w = (Uint16)PANGO_PIXELS(logical_rect.width);
485 d_rect.h = (Uint16)height;
486 d_rect.x = (Uint16)(x + PANGO_PIXELS (x_off));
487 d_rect.y = (Uint16)(risen_y - baseline);
489 if((! context->tmp_ftbitmap) || d_rect.w + d_rect.x > context->tmp_ftbitmap->width
490 || d_rect.h + d_rect.y > context->tmp_ftbitmap->rows)
492 freeFTBitmap(context->tmp_ftbitmap);
493 context->tmp_ftbitmap = createFTBitmap(d_rect.w + d_rect.x, d_rect.h + d_rect.y);
496 drawGlyphString(context, surface,
497 &color_matrix,
498 run->item->analysis.font, run->glyphs, &d_rect, baseline);
500 switch (uline) {
501 case PANGO_UNDERLINE_NONE:
502 break;
503 case PANGO_UNDERLINE_DOUBLE:
504 drawHLine(surface, &color_matrix,
505 risen_y + 4,
506 x + PANGO_PIXELS (x_off + ink_rect.x),
507 x + PANGO_PIXELS (x_off + ink_rect.x + ink_rect.width));
508 /* Fall through */
509 case PANGO_UNDERLINE_SINGLE:
510 drawHLine(surface, &color_matrix,
511 risen_y + 2,
512 x + PANGO_PIXELS (x_off + ink_rect.x),
513 x + PANGO_PIXELS (x_off + ink_rect.x + ink_rect.width));
514 break;
515 case PANGO_UNDERLINE_ERROR:
517 int point_x;
518 int counter = 0;
519 int end_x = x + PANGO_PIXELS (x_off + ink_rect.x + ink_rect.width);
521 for (point_x = x + PANGO_PIXELS (x_off + ink_rect.x) - 1;
522 point_x <= end_x;
523 point_x += 2)
525 if (counter)
526 drawHLine(surface, &color_matrix,
527 risen_y + 2,
528 point_x, MIN (point_x + 1, end_x));
529 else
530 drawHLine(surface, &color_matrix,
531 risen_y + 3,
532 point_x, MIN (point_x + 1, end_x));
534 counter = (counter + 1) % 2;
537 break;
538 case PANGO_UNDERLINE_LOW:
539 drawHLine(surface, &color_matrix,
540 risen_y + PANGO_PIXELS (ink_rect.y + ink_rect.height),
541 x + PANGO_PIXELS (x_off + ink_rect.x),
542 x + PANGO_PIXELS (x_off + ink_rect.x + ink_rect.width));
543 break;
546 if (strike)
547 drawHLine(surface, &color_matrix,
548 risen_y + PANGO_PIXELS (logical_rect.y + logical_rect.height / 2),
549 x + PANGO_PIXELS (x_off + logical_rect.x),
550 x + PANGO_PIXELS (x_off + logical_rect.x + logical_rect.width));
552 x_off += logical_rect.width;
557 Innter function of Pango. Stolen from GDK.
559 @param *item [in] The item to get property
560 @param *uline [out] Kind of underline
561 @param *strikethrough [out] Strike-through line
562 @param *rise [out] Rise/sink of line (for super/subscript)
563 @param *fg_color [out] Color of foreground
564 @param *fg_set [out] True if fg_color set
565 @param *bg_color [out] Color of background
566 @param *bg_set [out] True if bg_color valid
567 @param *shape_set [out] True if ink_rect and logical_rect valid
568 @param *ink_rect [out] Ink rect
569 @param *logical_rect [out] Logical rect
571 static void
572 getItemProperties (
573 PangoItem *item,
574 PangoUnderline *uline,
575 gboolean *strikethrough,
576 gint *rise,
577 PangoColor *fg_color,
578 gboolean *fg_set,
579 PangoColor *bg_color,
580 gboolean *bg_set,
581 gboolean *shape_set,
582 PangoRectangle *ink_rect,
583 PangoRectangle *logical_rect)
585 GSList *tmp_list = item->analysis.extra_attrs;
587 if (strikethrough)
588 *strikethrough = FALSE;
590 if (fg_set)
591 *fg_set = FALSE;
593 if (bg_set)
594 *bg_set = FALSE;
596 if (shape_set)
597 *shape_set = FALSE;
599 if (rise)
600 *rise = 0;
602 while (tmp_list) {
603 PangoAttribute *attr = tmp_list->data;
605 switch (attr->klass->type) {
606 case PANGO_ATTR_UNDERLINE:
607 if (uline)
608 *uline = ((PangoAttrInt *)attr)->value;
609 break;
611 case PANGO_ATTR_STRIKETHROUGH:
612 if (strikethrough)
613 *strikethrough = ((PangoAttrInt *)attr)->value;
614 break;
616 case PANGO_ATTR_FOREGROUND:
617 if (fg_color)
618 *fg_color = ((PangoAttrColor *)attr)->color;
619 if (fg_set)
620 *fg_set = TRUE;
621 break;
623 case PANGO_ATTR_BACKGROUND:
624 if (bg_color)
625 *bg_color = ((PangoAttrColor *)attr)->color;
626 if (bg_set)
627 *bg_set = TRUE;
628 break;
630 case PANGO_ATTR_SHAPE:
631 if (shape_set)
632 *shape_set = TRUE;
633 if (logical_rect)
634 *logical_rect = ((PangoAttrShape *)attr)->logical_rect;
635 if (ink_rect)
636 *ink_rect = ((PangoAttrShape *)attr)->ink_rect;
637 break;
639 case PANGO_ATTR_RISE:
640 if (rise)
641 *rise = ((PangoAttrInt *)attr)->value;
642 break;
644 default:
645 break;
647 tmp_list = tmp_list->next;
652 Copy bitmap to surface.
653 From (x, y)-(w, h) to (x, y)-(w, h) of rect.
655 @param *bitmap [in] Grayscale bitmap
656 @param *surface [out] Surface
657 @param *matrix [in] Foreground and background color
658 @param *rect [in] Rect to copy
660 void
661 SDLPango_CopyFTBitmapToSurface(
662 const FT_Bitmap *bitmap,
663 SDL_Surface *surface,
664 const SDLPango_Matrix *matrix,
665 SDL_Rect *rect)
667 int i;
668 Uint8 *p_ft;
669 Uint8 *p_sdl;
670 int width = rect->w;
671 int height = rect->h;
672 int x = rect->x;
673 int y = rect->y;
675 if(x + width > surface->w) {
676 width = surface->w - x;
677 if(width <= 0)
678 return;
680 if(y + height > surface->h) {
681 height = surface->h - y;
682 if(height <= 0)
683 return;
686 if(SDL_LockSurface(surface)) {
687 SDL_SetError("surface lock failed");
688 SDL_FreeSurface(surface);
689 return;
692 p_ft = (Uint8 *)bitmap->buffer + (bitmap->pitch * y);
693 p_sdl = (Uint8 *)surface->pixels + (surface->pitch * y);
694 for(i = 0; i < height; i ++) {
695 int k;
696 for(k = 0; k < width; k ++) {
697 /* TODO: rewrite by matrix calculation library */
698 Uint8 pixel[4]; /* 4: RGBA */
699 int n;
701 for(n = 0; n < 4; n ++) {
702 Uint16 w;
703 w = ((Uint16)matrix->m[n][0] * (256 - p_ft[k + x])) + ((Uint16)matrix->m[n][1] * p_ft[k + x]);
704 pixel[n] = (Uint8)(w >> 8);
707 switch(surface->format->BytesPerPixel) {
708 case 2:
709 ((Uint16 *)p_sdl)[k + x] = (Uint16)SDL_MapRGBA(surface->format, pixel[0], pixel[1], pixel[2], pixel[3]);
710 break;
711 case 4:
712 ((Uint32 *)p_sdl)[k + x] = SDL_MapRGBA(surface->format, pixel[0], pixel[1], pixel[2], pixel[3]);
713 break;
714 default:
715 SDL_SetError("surface->format->BytesPerPixel is invalid value");
716 return;
719 p_ft += bitmap->pitch;
720 p_sdl += surface->pitch;
723 SDL_UnlockSurface(surface);
727 SDLPango_Context*
728 SDLPango_CreateContext_GivenFontDesc(const char* font_desc)
730 SDLPango_Context *context = g_malloc(sizeof(SDLPango_Context));
731 G_CONST_RETURN char *charset;
733 context->font_map = pango_ft2_font_map_new ();
734 pango_ft2_font_map_set_resolution (PANGO_FT2_FONT_MAP (context->font_map), DEFAULT_DPI, DEFAULT_DPI);
736 context->context = pango_ft2_font_map_create_context (PANGO_FT2_FONT_MAP (context->font_map));
738 g_get_charset(&charset);
739 pango_context_set_language (context->context, pango_language_from_string (charset));
740 pango_context_set_base_dir (context->context, PANGO_DIRECTION_LTR);
742 context->font_desc = pango_font_description_from_string(font_desc);
744 context->layout = pango_layout_new (context->context);
746 SDLPango_SetSurfaceCreateArgs(context, SDL_SWSURFACE | SDL_SRCALPHA, DEFAULT_DEPTH,
747 DEFAULT_RMASK, DEFAULT_GMASK, DEFAULT_BMASK, DEFAULT_AMASK);
749 context->tmp_ftbitmap = NULL;
751 context->color_matrix = *MATRIX_TRANSPARENT_BACK_BLACK_LETTER;
753 context->min_height = 0;
754 context->min_width = 0;
756 return context;
760 Create a context which contains Pango objects.
762 @return A pointer to the context as a SDLPango_Context*.
764 SDLPango_Context*
765 SDLPango_CreateContext()
767 SDLPango_CreateContext_GivenFontDesc(MAKE_FONT_NAME(DEFAULT_FONT_FAMILY, DEFAULT_FONT_SIZE));
771 Free a context.
773 @param *context [i/o] Context to be free
775 void
776 SDLPango_FreeContext(SDLPango_Context *context)
778 freeFTBitmap(context->tmp_ftbitmap);
780 g_object_unref (context->layout);
782 pango_font_description_free(context->font_desc);
784 g_object_unref(context->context);
786 g_object_unref(context->font_map);
788 g_free(context);
792 Specify Arguments when create a surface.
793 When SDL_Pango creates a surface, the arguments are used.
795 @param *context [i/o] Context
796 @param flags [in] Same as SDL_CreateRGBSurface()
797 @param depth [in] Same as SDL_CreateRGBSurface()
798 @param Rmask [in] Same as SDL_CreateRGBSurface()
799 @param Gmask [in] Same as SDL_CreateRGBSurface()
800 @param Bmask [in] Same as SDL_CreateRGBSurface()
801 @param Amask [in] Same as SDL_CreateRGBSurface()
803 void
804 SDLPango_SetSurfaceCreateArgs(
805 SDLPango_Context *context,
806 Uint32 flags,
807 int depth,
808 Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask)
810 context->surface_args.flags = flags;
811 context->surface_args.depth = depth;
812 context->surface_args.Rmask = Rmask;
813 context->surface_args.Gmask = Gmask;
814 context->surface_args.Bmask = Bmask;
815 context->surface_args.Amask = Amask;
819 Create a surface and draw text on it.
820 The size of surface is same as lauout size.
822 @param *context [in] Context
823 @return A newly created surface
825 SDL_Surface * SDLPango_CreateSurfaceDraw(
826 SDLPango_Context *context)
828 PangoRectangle logical_rect;
829 SDL_Surface *surface;
830 int width, height;
832 pango_layout_get_extents (context->layout, NULL, &logical_rect);
833 width = PANGO_PIXELS (logical_rect.width);
834 height = PANGO_PIXELS (logical_rect.height);
835 if(width < context->min_width)
836 width = context->min_width;
837 if(height < context->min_height)
838 height = context->min_height;
840 surface = SDL_CreateRGBSurface(
841 context->surface_args.flags,
842 width, height, context->surface_args.depth,
843 context->surface_args.Rmask,
844 context->surface_args.Gmask,
845 context->surface_args.Bmask,
846 context->surface_args.Amask);
848 SDLPango_Draw(context, surface, 0, 0);
850 return surface;
854 Draw text on a existing surface.
856 @param *context [in] Context
857 @param *surface [i/o] Surface to draw on it
858 @param x [in] X of left-top of drawing area
859 @param y [in] Y of left-top of drawing area
861 void
862 SDLPango_Draw(
863 SDLPango_Context *context,
864 SDL_Surface *surface,
865 int x, int y)
867 PangoLayoutIter *iter;
868 PangoRectangle logical_rect;
869 int width, height;
871 if(! surface) {
872 SDL_SetError("surface is NULL");
873 return;
876 iter = pango_layout_get_iter (context->layout);
878 pango_layout_get_extents (context->layout, NULL, &logical_rect);
879 width = PANGO_PIXELS (logical_rect.width);
880 height = PANGO_PIXELS (logical_rect.height);
882 SDL_FillRect(surface, NULL, SDL_MapRGBA(surface->format, 0, 0, 0, 0));
884 if((! context->tmp_ftbitmap) || context->tmp_ftbitmap->width < width
885 || context->tmp_ftbitmap->rows < height)
887 freeFTBitmap(context->tmp_ftbitmap);
888 context->tmp_ftbitmap = createFTBitmap(width, height);
891 do {
892 PangoLayoutLine *line;
893 int baseline;
895 line = pango_layout_iter_get_line (iter);
897 pango_layout_iter_get_line_extents (iter, NULL, &logical_rect);
898 baseline = pango_layout_iter_get_baseline (iter);
900 drawLine(
901 context,
902 surface,
903 line,
904 x + PANGO_PIXELS (logical_rect.x),
905 y + PANGO_PIXELS (logical_rect.y),
906 PANGO_PIXELS (logical_rect.height),
907 PANGO_PIXELS (baseline - logical_rect.y));
908 } while (pango_layout_iter_next_line (iter));
910 pango_layout_iter_free (iter);
914 Allocate buffer and create a FTBitmap object.
916 @param width [in] Width
917 @param height [in] Height
918 @return FTBitmap object
920 static FT_Bitmap *
921 createFTBitmap(
922 int width, int height)
924 FT_Bitmap *bitmap;
925 guchar *buf;
927 bitmap = g_malloc(sizeof(FT_Bitmap));
928 bitmap->width = width;
929 bitmap->rows = height;
930 bitmap->pitch = (width + 3) & ~3;
931 bitmap->num_grays = 256;
932 bitmap->pixel_mode = FT_PIXEL_MODE_GRAY;
933 buf = g_malloc (bitmap->pitch * bitmap->rows);
934 memset (buf, 0x00, bitmap->pitch * bitmap->rows);
935 bitmap->buffer = buf;
937 return bitmap;
941 Free a FTBitmap object.
943 @param *bitmap [i/o] FTbitmap to be free
945 static void
946 freeFTBitmap(
947 FT_Bitmap *bitmap)
949 if(bitmap) {
950 g_free(bitmap->buffer);
951 g_free(bitmap);
956 Clear a FTBitmap object.
958 @param *bitmap [i/o] FTbitmap to be clear
960 static void
961 clearFTBitmap(
962 FT_Bitmap *bitmap)
964 Uint8 *p = (Uint8 *)bitmap->buffer;
965 int length = bitmap->pitch * bitmap->rows;
967 memset(p, 0, length);
971 Specify minimum size of drawing rect.
973 @param *context [i/o] Context
974 @param width [in] Width. -1 means no wrapping mode.
975 @param height [in] Height. zero/minus value means non-specified.
977 void
978 SDLPango_SetMinimumSize(
979 SDLPango_Context *context,
980 int width, int height)
982 int pango_width;
983 if(width > 0)
984 pango_width = width * PANGO_SCALE;
985 else
986 pango_width = -1;
987 pango_layout_set_width(context->layout, pango_width);
989 context->min_width = width;
990 context->min_height = height;
994 Specify default color.
996 @param *context [i/o] Context
997 @param *color_matrix [in] Foreground and background color
999 void
1000 SDLPango_SetDefaultColor(
1001 SDLPango_Context *context,
1002 const SDLPango_Matrix *color_matrix)
1004 context->color_matrix = *color_matrix;
1008 Get layout width.
1010 @param *context [in] Context
1011 @return Width
1014 SDLPango_GetLayoutWidth(
1015 SDLPango_Context *context)
1017 PangoRectangle logical_rect;
1019 pango_layout_get_extents (context->layout, NULL, &logical_rect);
1021 return PANGO_PIXELS (logical_rect.width);
1025 Get layout height.
1027 @param *context [in] Context
1028 @return Height
1031 SDLPango_GetLayoutHeight(
1032 SDLPango_Context *context)
1034 PangoRectangle logical_rect;
1036 pango_layout_get_extents (context->layout, NULL, &logical_rect);
1038 return PANGO_PIXELS (logical_rect.height);
1042 Set markup text to context.
1043 Text must be utf-8.
1044 Markup format is same as pango.
1046 @param *context [i/o] Context
1047 @param *markup [in] Markup text
1048 @param length [in] Text length. -1 means NULL-terminated text.
1050 void
1051 SDLPango_SetMarkup(
1052 SDLPango_Context *context,
1053 const char *markup,
1054 int length)
1056 pango_layout_set_markup (context->layout, markup, length);
1057 pango_layout_set_auto_dir (context->layout, TRUE);
1058 pango_layout_set_alignment (context->layout, PANGO_ALIGN_LEFT);
1059 pango_layout_set_font_description (context->layout, context->font_desc);
1062 void
1063 SDLPango_SetText_GivenAlignment(
1064 SDLPango_Context *context,
1065 const char *text,
1066 int length,
1067 SDLPango_Alignment alignment)
1069 pango_layout_set_attributes(context->layout, NULL);
1070 pango_layout_set_text (context->layout, text, length);
1071 pango_layout_set_auto_dir (context->layout, TRUE);
1072 pango_layout_set_alignment (context->layout, alignment);
1073 pango_layout_set_font_description (context->layout, context->font_desc);
1077 Set plain text to context.
1078 Text must be utf-8.
1080 @param *context [i/o] Context
1081 @param *text [in] Plain text
1082 @param length [in] Text length. -1 means NULL-terminated text.
1084 void
1085 SDLPango_SetText(
1086 SDLPango_Context *context,
1087 const char *text,
1088 int length)
1090 SDLPango_SetText_GivenAlignment(context, text, length, SDLPANGO_ALIGN_LEFT);
1094 Set DPI to context.
1096 @param *context [i/o] Context
1097 @param dpi_x [in] X dpi
1098 @param dpi_y [in] Y dpi
1100 void
1101 SDLPango_SetDpi(
1102 SDLPango_Context *context,
1103 double dpi_x, double dpi_y)
1105 pango_ft2_font_map_set_resolution (PANGO_FT2_FONT_MAP (context->font_map), dpi_x, dpi_y);
1109 Set language to context.
1111 @param *context [i/o] Context
1112 @param *language_tag [in] A RFC-3066 format language tag
1114 void SDLCALL SDLPango_SetLanguage(
1115 SDLPango_Context *context,
1116 const char *language_tag)
1118 pango_context_set_language (context->context, pango_language_from_string (language_tag));
1122 Set base direction to context.
1124 @param *context [i/o] Context
1125 @param direction [in] Direction
1127 void SDLCALL SDLPango_SetBaseDirection(
1128 SDLPango_Context *context,
1129 SDLPango_Direction direction)
1131 PangoDirection pango_dir;
1133 switch(direction) {
1134 case SDLPANGO_DIRECTION_LTR:
1135 pango_dir = PANGO_DIRECTION_LTR;
1136 break;
1137 case SDLPANGO_DIRECTION_RTL:
1138 pango_dir = PANGO_DIRECTION_RTL;
1139 break;
1140 case SDLPANGO_DIRECTION_WEAK_LTR:
1141 pango_dir = PANGO_DIRECTION_WEAK_LTR;
1142 break;
1143 case SDLPANGO_DIRECTION_WEAK_RTL:
1144 pango_dir = PANGO_DIRECTION_WEAK_RTL;
1145 break;
1146 case SDLPANGO_DIRECTION_NEUTRAL:
1147 pango_dir = PANGO_DIRECTION_NEUTRAL;
1148 break;
1149 default:
1150 SDL_SetError("unknown direction value");
1151 return;
1154 pango_context_set_base_dir (context->context, pango_dir);
1158 Get font map from context.
1160 @param *context [in] Context
1161 @return Font map
1163 PangoFontMap* SDLCALL SDLPango_GetPangoFontMap(
1164 SDLPango_Context *context)
1166 return context->font_map;
1170 Get font description from context.
1172 @param *context [in] Context
1173 @return Font description
1175 PangoFontDescription* SDLCALL SDLPango_GetPangoFontDescription(
1176 SDLPango_Context *context)
1178 return context->font_desc;
1182 Get layout from context.
1184 @param *context [in] Context
1185 @return Layout
1187 PangoLayout* SDLCALL SDLPango_GetPangoLayout(
1188 SDLPango_Context *context)
1190 return context->layout;