# --- SDE-COPYRIGHT-NOTE-BEGIN --- # This copyright note is auto-generated by ./scripts/Create-CopyPatch. # # Filename: package/.../sdlpango/SDL_Pango_0.1.2-API-adds.patch # Copyright (C) 2006 The OpenSDE Project # # More information can be found in the files COPYING and README. # # This patch file is dual-licensed. It is available under the license the # patched project is licensed under, as long as it is an OpenSource license # as defined at http://www.opensource.org/ (e.g. BSD, X11) or under the terms # of the GNU General Public License as published by the Free Software # Foundation; either version 2 of the License, or (at your option) any later # version. # --- SDE-COPYRIGHT-NOTE-END --- --- SDL_Pango-0.1.2/src/SDL_Pango.h.original 2006-12-13 15:36:50.000000000 +0100 +++ SDL_Pango-0.1.2/src/SDL_Pango.h 2006-12-13 16:16:07.000000000 +0100 @@ -1,205 +1,219 @@ -/* SDL_Pango.h -- A companion library to SDL for working with Pango. - Copyright (C) 2004 NAKAMURA Ken'ichi - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. -*/ - -/*! @file - @brief Header file of SDL_Pango - - @author NAKAMURA Ken'ichi - @date 2004/08/26 - $Revision: 1.3 $ -*/ - -#ifndef SDL_PANGO_H -#define SDL_PANGO_H - -#include "SDL.h" - -#include "begin_code.h" - -#ifdef __cplusplus -extern "C" { -#endif - - - -typedef struct _contextImpl SDLPango_Context; - -/*! - General 4 X 4 matrix struct. -*/ -typedef struct _SDLPango_Matrix { - Uint8 m[4][4]; /*! Matrix variables */ -} SDLPango_Matrix; - -const SDLPango_Matrix _MATRIX_WHITE_BACK - = {255, 0, 0, 0, - 255, 0, 0, 0, - 255, 0, 0, 0, - 255, 255, 0, 0,}; - -/*! - Specifies white back and black letter. -*/ -const SDLPango_Matrix *MATRIX_WHITE_BACK = &_MATRIX_WHITE_BACK; - -const SDLPango_Matrix _MATRIX_BLACK_BACK - = {0, 255, 0, 0, - 0, 255, 0, 0, - 0, 255, 0, 0, - 255, 255, 0, 0,}; -/*! - Specifies black back and white letter. -*/ -const SDLPango_Matrix *MATRIX_BLACK_BACK = &_MATRIX_BLACK_BACK; - -const SDLPango_Matrix _MATRIX_TRANSPARENT_BACK_BLACK_LETTER - = {0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 255, 0, 0,}; -/*! - Specifies transparent back and black letter. -*/ -const SDLPango_Matrix *MATRIX_TRANSPARENT_BACK_BLACK_LETTER = &_MATRIX_TRANSPARENT_BACK_BLACK_LETTER; - -const SDLPango_Matrix _MATRIX_TRANSPARENT_BACK_WHITE_LETTER - = {255, 255, 0, 0, - 255, 255, 0, 0, - 255, 255, 0, 0, - 0, 255, 0, 0,}; -/*! - Specifies transparent back and white letter. -*/ -const SDLPango_Matrix *MATRIX_TRANSPARENT_BACK_WHITE_LETTER = &_MATRIX_TRANSPARENT_BACK_WHITE_LETTER; - -const SDLPango_Matrix _MATRIX_TRANSPARENT_BACK_TRANSPARENT_LETTER - = {255, 255, 0, 0, - 255, 255, 0, 0, - 255, 255, 0, 0, - 0, 0, 0, 0,}; -/*! - Specifies transparent back and transparent letter. - This is useful for KARAOKE like rendering. -*/ -const SDLPango_Matrix *MATRIX_TRANSPARENT_BACK_TRANSPARENT_LETTER = &_MATRIX_TRANSPARENT_BACK_TRANSPARENT_LETTER; - -/*! - Specifies direction of text. See Pango reference for detail -*/ -typedef enum { - SDLPANGO_DIRECTION_LTR, /*! Left to right */ - SDLPANGO_DIRECTION_RTL, /*! Right to left */ - SDLPANGO_DIRECTION_WEAK_LTR, /*! Left to right (weak) */ - SDLPANGO_DIRECTION_WEAK_RTL, /*! Right to left (weak) */ - SDLPANGO_DIRECTION_NEUTRAL /*! Neutral */ -} SDLPango_Direction; - - - -extern DECLSPEC int SDLCALL SDLPango_Init(); - -extern DECLSPEC int SDLCALL SDLPango_WasInit(); - -extern DECLSPEC SDLPango_Context* SDLCALL SDLPango_CreateContext(); - -extern DECLSPEC void SDLCALL SDLPango_FreeContext( - SDLPango_Context *context); - -extern DECLSPEC void SDLCALL SDLPango_SetSurfaceCreateArgs( - SDLPango_Context *context, - Uint32 flags, - int depth, - Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask); - -extern DECLSPEC SDL_Surface * SDLCALL SDLPango_CreateSurfaceDraw( - SDLPango_Context *context); - -extern DECLSPEC void SDLCALL SDLPango_Draw( - SDLPango_Context *context, - SDL_Surface *surface, - int x, int y); - -extern DECLSPEC void SDLCALL SDLPango_SetDpi( - SDLPango_Context *context, - double dpi_x, double dpi_y); - -extern DECLSPEC void SDLCALL SDLPango_SetMinimumSize( - SDLPango_Context *context, - int width, int height); - -extern DECLSPEC void SDLCALL SDLPango_SetDefaultColor( - SDLPango_Context *context, - const SDLPango_Matrix *color_matrix); - -extern DECLSPEC int SDLCALL SDLPango_GetLayoutWidth( - SDLPango_Context *context); - -extern DECLSPEC int SDLCALL SDLPango_GetLayoutHeight( - SDLPango_Context *context); - -extern DECLSPEC void SDLCALL SDLPango_SetMarkup( - SDLPango_Context *context, - const char *markup, - int length); - -extern DECLSPEC void SDLCALL SDLPango_SetText( - SDLPango_Context *context, - const char *markup, - int length); - -extern DECLSPEC void SDLCALL SDLPango_SetLanguage( - SDLPango_Context *context, - const char *language_tag); - -extern DECLSPEC void SDLCALL SDLPango_SetBaseDirection( - SDLPango_Context *context, - SDLPango_Direction direction); - - -#ifdef __FT2_BUILD_UNIX_H__ - -extern DECLSPEC void SDLCALL SDLPango_CopyFTBitmapToSurface( - const FT_Bitmap *bitmap, - SDL_Surface *surface, - const SDLPango_Matrix *matrix, - SDL_Rect *rect); - -#endif /* __FT2_BUILD_UNIX_H__ */ - - -#ifdef __PANGO_H__ - -extern DECLSPEC PangoFontMap* SDLCALL SDLPango_GetPangoFontMap( - SDLPango_Context *context); - -extern DECLSPEC PangoFontDescription* SDLCALL SDLPango_GetPangoFontDescription( - SDLPango_Context *context); - -extern DECLSPEC PangoLayout* SDLCALL SDLPango_GetPangoLayout( - SDLPango_Context *context); - -#endif /* __PANGO_H__ */ - - -#ifdef __cplusplus -} -#endif - -#include "close_code.h" - -#endif /* SDL_PANGO_H */ +/* SDL_Pango.h -- A companion library to SDL for working with Pango. + Copyright (C) 2004 NAKAMURA Ken'ichi + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +*/ + +/*! @file + @brief Header file of SDL_Pango + + @author NAKAMURA Ken'ichi + @date 2004/08/26 + $Revision: 1.3 $ +*/ + +#ifndef SDL_PANGO_H +#define SDL_PANGO_H + +#include "SDL.h" + +#include "begin_code.h" + +#ifdef __cplusplus +extern "C" { +#endif + + + +typedef struct _contextImpl SDLPango_Context; + +/*! + General 4 X 4 matrix struct. +*/ +typedef struct _SDLPango_Matrix { + Uint8 m[4][4]; /*! Matrix variables */ +} SDLPango_Matrix; + +const SDLPango_Matrix _MATRIX_WHITE_BACK + = {255, 0, 0, 0, + 255, 0, 0, 0, + 255, 0, 0, 0, + 255, 255, 0, 0,}; + +/*! + Specifies white back and black letter. +*/ +const SDLPango_Matrix *MATRIX_WHITE_BACK = &_MATRIX_WHITE_BACK; + +const SDLPango_Matrix _MATRIX_BLACK_BACK + = {0, 255, 0, 0, + 0, 255, 0, 0, + 0, 255, 0, 0, + 255, 255, 0, 0,}; +/*! + Specifies black back and white letter. +*/ +const SDLPango_Matrix *MATRIX_BLACK_BACK = &_MATRIX_BLACK_BACK; + +const SDLPango_Matrix _MATRIX_TRANSPARENT_BACK_BLACK_LETTER + = {0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 255, 0, 0,}; +/*! + Specifies transparent back and black letter. +*/ +const SDLPango_Matrix *MATRIX_TRANSPARENT_BACK_BLACK_LETTER = &_MATRIX_TRANSPARENT_BACK_BLACK_LETTER; + +const SDLPango_Matrix _MATRIX_TRANSPARENT_BACK_WHITE_LETTER + = {255, 255, 0, 0, + 255, 255, 0, 0, + 255, 255, 0, 0, + 0, 255, 0, 0,}; +/*! + Specifies transparent back and white letter. +*/ +const SDLPango_Matrix *MATRIX_TRANSPARENT_BACK_WHITE_LETTER = &_MATRIX_TRANSPARENT_BACK_WHITE_LETTER; + +const SDLPango_Matrix _MATRIX_TRANSPARENT_BACK_TRANSPARENT_LETTER + = {255, 255, 0, 0, + 255, 255, 0, 0, + 255, 255, 0, 0, + 0, 0, 0, 0,}; +/*! + Specifies transparent back and transparent letter. + This is useful for KARAOKE like rendering. +*/ +const SDLPango_Matrix *MATRIX_TRANSPARENT_BACK_TRANSPARENT_LETTER = &_MATRIX_TRANSPARENT_BACK_TRANSPARENT_LETTER; + +/*! + Specifies direction of text. See Pango reference for detail +*/ +typedef enum { + SDLPANGO_DIRECTION_LTR, /*! Left to right */ + SDLPANGO_DIRECTION_RTL, /*! Right to left */ + SDLPANGO_DIRECTION_WEAK_LTR, /*! Left to right (weak) */ + SDLPANGO_DIRECTION_WEAK_RTL, /*! Right to left (weak) */ + SDLPANGO_DIRECTION_NEUTRAL /*! Neutral */ +} SDLPango_Direction; + +/*! + Specifies alignment of text. See Pango reference for detail +*/ +typedef enum { + SDLPANGO_ALIGN_LEFT, + SDLPANGO_ALIGN_CENTER, + SDLPANGO_ALIGN_RIGHT +} SDLPango_Alignment; + +extern DECLSPEC int SDLCALL SDLPango_Init(); + +extern DECLSPEC int SDLCALL SDLPango_WasInit(); + +extern DECLSPEC SDLPango_Context* SDLCALL SDLPango_CreateContext_GivenFontDesc(const char* font_desc); +extern DECLSPEC SDLPango_Context* SDLCALL SDLPango_CreateContext(); + +extern DECLSPEC void SDLCALL SDLPango_FreeContext( + SDLPango_Context *context); + +extern DECLSPEC void SDLCALL SDLPango_SetSurfaceCreateArgs( + SDLPango_Context *context, + Uint32 flags, + int depth, + Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask); + +extern DECLSPEC SDL_Surface * SDLCALL SDLPango_CreateSurfaceDraw( + SDLPango_Context *context); + +extern DECLSPEC void SDLCALL SDLPango_Draw( + SDLPango_Context *context, + SDL_Surface *surface, + int x, int y); + +extern DECLSPEC void SDLCALL SDLPango_SetDpi( + SDLPango_Context *context, + double dpi_x, double dpi_y); + +extern DECLSPEC void SDLCALL SDLPango_SetMinimumSize( + SDLPango_Context *context, + int width, int height); + +extern DECLSPEC void SDLCALL SDLPango_SetDefaultColor( + SDLPango_Context *context, + const SDLPango_Matrix *color_matrix); + +extern DECLSPEC int SDLCALL SDLPango_GetLayoutWidth( + SDLPango_Context *context); + +extern DECLSPEC int SDLCALL SDLPango_GetLayoutHeight( + SDLPango_Context *context); + +extern DECLSPEC void SDLCALL SDLPango_SetMarkup( + SDLPango_Context *context, + const char *markup, + int length); + +extern DECLSPEC void SDLCALL SDLPango_SetText_GivenAlignment( + SDLPango_Context *context, + const char *text, + int length, + SDLPango_Alignment alignment); + +extern DECLSPEC void SDLCALL SDLPango_SetText( + SDLPango_Context *context, + const char *markup, + int length); + +extern DECLSPEC void SDLCALL SDLPango_SetLanguage( + SDLPango_Context *context, + const char *language_tag); + +extern DECLSPEC void SDLCALL SDLPango_SetBaseDirection( + SDLPango_Context *context, + SDLPango_Direction direction); + + +#ifdef __FT2_BUILD_UNIX_H__ + +extern DECLSPEC void SDLCALL SDLPango_CopyFTBitmapToSurface( + const FT_Bitmap *bitmap, + SDL_Surface *surface, + const SDLPango_Matrix *matrix, + SDL_Rect *rect); + +#endif /* __FT2_BUILD_UNIX_H__ */ + + +#ifdef __PANGO_H__ + +extern DECLSPEC PangoFontMap* SDLCALL SDLPango_GetPangoFontMap( + SDLPango_Context *context); + +extern DECLSPEC PangoFontDescription* SDLCALL SDLPango_GetPangoFontDescription( + SDLPango_Context *context); + +extern DECLSPEC PangoLayout* SDLCALL SDLPango_GetPangoLayout( + SDLPango_Context *context); + +#endif /* __PANGO_H__ */ + + +#ifdef __cplusplus +} +#endif + +#include "close_code.h" + +#endif /* SDL_PANGO_H */ --- SDL_Pango-0.1.2/src/SDL_Pango.c.original 2006-12-13 15:36:40.000000000 +0100 +++ SDL_Pango-0.1.2/src/SDL_Pango.c 2006-12-13 16:14:46.000000000 +0100 @@ -1,1175 +1,1190 @@ -/* SDL_Pango.c -- A companion library to SDL for working with Pango. - Copyright (C) 2004 NAKAMURA Ken'ichi - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. -*/ - -/*! - \mainpage - - \section intro Introduction - - Pango is the text rendering engine of GNOME 2.x. SDL_Pango connects the - engine to SDL. In Windows, pre-built binary package (MSI and merge module) - is provided. - - \subsection dist Distribution - - If you are a game software developer, you should know the difficulties of - distribution. So I will start to introduce SDL_Pango from the viewpoint - of distribution. - - In Un*x, SDL_Pango is hard to use as system-independent module, because - it depends on fontconfig and Pango which are designed as system-singleton - modules. If you use SDL_Pango, your software will require those modules - installed to target system. If your software is shipped as shrink-wrap - package, it may cause much problem on your support desk. You should - carefully design your installation process. - - In Windows, SDL_Pango is distributed as "merge module" which contains - fontconfig and Pango. Those binaries are modified as side-by-side components. - You should use Windows Installer and merge the module - on your MSI package. The merge module not only contains files, but also includes - custom action which must be run at installation. - - \subsection api High-level API - - From the viewpoint of text rendering, the heart of SDL_Pango is high-level API. - Other text rendering APIs, like DrawText() of Windows, font and text must be - specified separately. In SDL_Pango, font specification is embedded in text like - HTML: - - \code - This is Courier New and italic. - \endcode - - Color, size, subscript/superscript, obliquing, weight, and other many features - are also available in same way. - - \subsection i18n Internationalized Text - - Internationalized text is another key feature. Text is specified by UTF-8. RTL - script (Arabic and Hebrew) and complicated rendering (Arabic, Indic and Thai) are - supported. You can see it with GNOME 2.x. - - \section get Getting Started - - \subsection getlatest Get latest files - - Get latest files from http://sourceforge.net/projects/sdlpango/ . - - \subsection install Install Header and Library - - In Windows and VS2003, I strongly recommend you to install MSI package. It contains Pango - and fontconfig binaries which are modified as side-by-side components. It is - nearly impossible to build them. (I spent much time to build them...) - - In MinGW, I recommend you to use VS2003. Otherwise you may run into the maze of - distribution. If you insist MinGW, you should use MinGW binary archive. - - In Un*x, installation consists of: - - \code - ./configure - make - make install - \endcode - - \subsection inc Includes - - To use SDL_Pango functions in a C/C++ source code file, you must use the SDL_Pango.h - include file: - - \code - #include "SDL_Pango.h" - \endcode - - In Windows, SDL_Pango.h is installed on \c \%ProgramFiles\%\\SDL_Pango \c Development\\include - (usually \c C:\\Program \c Files\\SDL_Pango \c Development\\include). You should add this - directory to include path. - - \subsection comp Compiling - - In Un*x, to link with SDL_Pango you should use sdl-config to get the required SDL - compilation options. After that, compiling with SDL_Pango is quite easy. - - Note: Some systems may not have the SDL_Pango library and include file in the same - place as the SDL library and includes are located, in that case you will need to - add more -I and -L paths to these command lines. - - Simple Example for compiling an object file: - - \code - cc -c `sdl-config --cflags` mysource.c - \endcode - - Simple Example for linking an object file: - - \code - cc -o myprogram mysource.o `sdl-config --libs` -lSDL_Pango - \endcode - - Now myprogram is ready to run. - - You can see a sample of autoconfiscation in 'test' directory. - - In Windows, MSI package installs many dlls to \c \%ProgramFiles\%\\SDL_Pango \c Development\\import_lib. - To link with SDL_Pango you should use SDL_Pango.lib. - - SDL_Pango.dll depends on many dlls and other many files. Those dlls are installed on - \c \%ProgramFiles\%\\SDL_Pango \c Development\\bin. MSI package adds the directory to PATH environment - variable. - - \section devel Development - - \subsection font Font Handling - - In Un*x, font handling depends on fontconfig of your system. - - In Windows, local.conf of fontconfig is placed on \c \%ProgramFiles\%\\SDL_Pango \c Development\\etc\\fonts. - You should know about fontconfig's font cache mechanism. - - \subsection example Step-by-step Example - - The operation of SDL_Pango is done via context. - - \code - SDLPango_Context *context = SDLPango_CreateContext(); - \endcode - - Specify default colors and minimum surface size. - - \code - SDLPango_SetDefaultColor(context, MATRIX_TRANSPARENT_BACK_WHITE_LETTER); - SDLPango_SetMinimumSize(context, 640, 0); - \endcode - - Set markup text. - - \code - SDLPango_SetMarkup(context, "This is markup text.", -1); - \endcode - - Now you can get the size of surface. - - \code - int w = SDLPango_GetLayoutWidth(context); - int h = SDLPango_GetLayoutHeight(context); - \endcode - - Create surface to draw. - - \code - int margin_x = 10; - int margin_y = 10; - SDL_Surface *surface = SDL_CreateRGBSurface(SDL_SWSURFACE, - w + margin_x * 2, h + margin_y * 2, - 32, (Uint32)(255 << (8 * 3)), (Uint32)(255 << (8 * 2)), - (Uint32)(255 << (8 * 1)), 255); - \endcode - - And draw on it. - - \code - SDLPango_Draw(context, surface, margin_x, margin_y); - \endcode - - You must free the surface by yourself. - - \code - SDL_FreeSurface(surface); - \endcode - - Free context. - - \code - SDLPango_FreeContext(context); - \endcode - - You can see actual code in \c test/testbench.cpp. - - \subsection pack Packaging - - In Un*x, do it yourself. - - In Windows, font files must be installed on apprication folder (usually - \c C:\\Program \c Files\\[Manufacturer]\\[ProductName]). The property of - apprication folder must be \c TARGETDIR (this is default setting of VS2003). - SDL.dll also must be installed on apprication folder. Add SDL_Pango.msm to - your MSI package. - - \section ack Acknowledgment - - SDL_Pango is developed with financial assistance of Information-technology Promotion Agency, Japan. - -- NAKAMURA Ken'ichi - -*/ - -/*! @file - @brief Implementation of SDL_Pango - - @author NAKAMURA Ken'ichi - @date 2004/12/07 - $Revision: 1.6 $ -*/ - -#include -#include - -#include "SDL_Pango.h" - -//! non-zero if initialized -static int IS_INITIALIZED = 0; - -#define DEFAULT_FONT_FAMILY "Sans" -#define DEFAULT_FONT_SIZE 12 -#define DEFAULT_DPI 96 -#define _MAKE_FONT_NAME(family, size) family " " #size -#define MAKE_FONT_NAME(family, size) _MAKE_FONT_NAME(family, size) -#define DEFAULT_DEPTH 32 -#define DEFAULT_RMASK (Uint32)(255 << (8 * 3)) -#define DEFAULT_GMASK (Uint32)(255 << (8 * 2)) -#define DEFAULT_BMASK (Uint32)(255 << (8 * 1)) -#define DEFAULT_AMASK (Uint32)255 - -static FT_Bitmap *createFTBitmap(int width, int height); - -static void freeFTBitmap(FT_Bitmap *bitmap); - -static void getItemProperties ( - PangoItem *item, - PangoUnderline *uline, - gboolean *strikethrough, - gint *rise, - PangoColor *fg_color, - gboolean *fg_set, - PangoColor *bg_color, - gboolean *bg_set, - gboolean *shape_set, - PangoRectangle *ink_rect, - PangoRectangle *logical_rect); - -static void clearFTBitmap(FT_Bitmap *bitmap); - -typedef struct _surfaceArgs { - Uint32 flags; - int depth; - Uint32 Rmask; - Uint32 Gmask; - Uint32 Bmask; - Uint32 Amask; -} surfaceArgs; - -typedef struct _contextImpl { - PangoContext *context; - PangoFontMap *font_map; - PangoFontDescription *font_desc; - PangoLayout *layout; - surfaceArgs surface_args; - FT_Bitmap *tmp_ftbitmap; - SDLPango_Matrix color_matrix; - int min_width; - int min_height; -} contextImpl; - - -/*! - Initialize the Glib and Pango API. - This must be called before using other functions in this library, - excepting SDLPango_WasInit. - SDL does not have to be initialized before this call. - - - @return always 0. -*/ -int -SDLPango_Init() -{ - g_type_init(); - - IS_INITIALIZED = -1; - - return 0; -} - -/*! - Query the initilization status of the Glib and Pango API. - You may, of course, use this before SDLPango_Init to avoid - initilizing twice in a row. - - @return zero when already initialized. - non-zero when not initialized. -*/ -int -SDLPango_WasInit() -{ - return IS_INITIALIZED; -} - -/*! - Draw glyphs on rect. - - @param *context [in] Context - @param *surface [out] Surface to draw on it - @param *color_matrix [in] Foreground and background color - @param *font [in] Innter variable of Pango - @param *glyphs [in] Innter variable of Pango - @param *rect [in] Draw on this area - @param baseline [in] Horizontal location of glyphs -*/ -static void -drawGlyphString( - SDLPango_Context *context, - SDL_Surface *surface, - SDLPango_Matrix *color_matrix, - PangoFont *font, - PangoGlyphString *glyphs, - SDL_Rect *rect, - int baseline) -{ - pango_ft2_render(context->tmp_ftbitmap, font, glyphs, rect->x, rect->y + baseline); - - SDLPango_CopyFTBitmapToSurface( - context->tmp_ftbitmap, - surface, - color_matrix, - rect); - - clearFTBitmap(context->tmp_ftbitmap); -} - -/*! - Draw horizontal line of a pixel. - - @param *surface [out] Surface to draw on it - @param *color_matrix [in] Foreground and background color - @param y [in] Y location of line - @param start [in] Left of line - @param end [in] Right of line -*/ -static void drawHLine( - SDL_Surface *surface, - SDLPango_Matrix *color_matrix, - int y, - int start, - int end) -{ - Uint8 *p; - Uint16 *p16; - Uint32 *p32; - Uint32 color; - int ix; - int pixel_bytes = surface->format->BytesPerPixel; - - if (y < 0 || y >= surface->h) - return; - - if (end <= 0 || start >= surface->w) - return; - - if (start < 0) - start = 0; - - if (end >= surface->w) - end = surface->w; - - p = (Uint8 *)(surface->pixels) + y * surface->pitch + start * pixel_bytes; - color = SDL_MapRGBA(surface->format, - color_matrix->m[0][1], - color_matrix->m[1][1], - color_matrix->m[2][1], - color_matrix->m[3][1]); - - switch(pixel_bytes) { - case 2: - p16 = (Uint16 *)p; - for (ix = 0; ix < end - start; ix++) - *p16++ = (Uint16)color; - break; - case 4: - p32 = (Uint32 *)p; - for (ix = 0; ix < end - start; ix++) - *p32++ = color; - break; - default: - SDL_SetError("surface->format->BytesPerPixel is invalid value"); - break; - } -} - -/*! - Draw a line. - - @param *context [in] Context - @param *surface [out] Surface to draw on it - @param *line [in] Innter variable of Pango - @param x [in] X location of line - @param y [in] Y location of line - @param height [in] Height of line - @param baseline [in] Rise / sink of line (for super/subscript) -*/ -static void -drawLine( - SDLPango_Context *context, - SDL_Surface *surface, - PangoLayoutLine *line, - gint x, - gint y, - gint height, - gint baseline) -{ - GSList *tmp_list = line->runs; - PangoColor fg_color, bg_color; - PangoRectangle logical_rect; - PangoRectangle ink_rect; - int x_off = 0; - - while (tmp_list) { - SDLPango_Matrix color_matrix = context->color_matrix; - PangoUnderline uline = PANGO_UNDERLINE_NONE; - gboolean strike, fg_set, bg_set, shape_set; - gint rise, risen_y; - PangoLayoutRun *run = tmp_list->data; - SDL_Rect d_rect; - - tmp_list = tmp_list->next; - - getItemProperties(run->item, - &uline, &strike, &rise, - &fg_color, &fg_set, &bg_color, &bg_set, - &shape_set, &ink_rect, &logical_rect); - - risen_y = y + baseline - PANGO_PIXELS (rise); - - if(fg_set) { - color_matrix.m[0][1] = (Uint8)(fg_color.red >> 8); - color_matrix.m[1][1] = (Uint8)(fg_color.green >> 8); - color_matrix.m[2][1] = (Uint8)(fg_color.blue >> 8); - color_matrix.m[3][1] = 255; - if(color_matrix.m[3][0] == 0) { - color_matrix.m[0][0] = (Uint8)(fg_color.red >> 8); - color_matrix.m[1][0] = (Uint8)(fg_color.green >> 8); - color_matrix.m[2][0] = (Uint8)(fg_color.blue >> 8); - } - } - - if (bg_set) { - color_matrix.m[0][0] = (Uint8)(bg_color.red >> 8); - color_matrix.m[1][0] = (Uint8)(bg_color.green >> 8); - color_matrix.m[2][0] = (Uint8)(bg_color.blue >> 8); - color_matrix.m[3][0] = 255; - } - - if(! shape_set) { - if (uline == PANGO_UNDERLINE_NONE) - pango_glyph_string_extents (run->glyphs, run->item->analysis.font, - NULL, &logical_rect); - else - pango_glyph_string_extents (run->glyphs, run->item->analysis.font, - &ink_rect, &logical_rect); - - d_rect.w = (Uint16)PANGO_PIXELS(logical_rect.width); - d_rect.h = (Uint16)height; - d_rect.x = (Uint16)(x + PANGO_PIXELS (x_off)); - d_rect.y = (Uint16)(risen_y - baseline); - - if((! context->tmp_ftbitmap) || d_rect.w + d_rect.x > context->tmp_ftbitmap->width - || d_rect.h + d_rect.y > context->tmp_ftbitmap->rows) - { - freeFTBitmap(context->tmp_ftbitmap); - context->tmp_ftbitmap = createFTBitmap(d_rect.w + d_rect.x, d_rect.h + d_rect.y); - } - - drawGlyphString(context, surface, - &color_matrix, - run->item->analysis.font, run->glyphs, &d_rect, baseline); - } - switch (uline) { - case PANGO_UNDERLINE_NONE: - break; - case PANGO_UNDERLINE_DOUBLE: - drawHLine(surface, &color_matrix, - risen_y + 4, - x + PANGO_PIXELS (x_off + ink_rect.x), - x + PANGO_PIXELS (x_off + ink_rect.x + ink_rect.width)); - /* Fall through */ - case PANGO_UNDERLINE_SINGLE: - drawHLine(surface, &color_matrix, - risen_y + 2, - x + PANGO_PIXELS (x_off + ink_rect.x), - x + PANGO_PIXELS (x_off + ink_rect.x + ink_rect.width)); - break; - case PANGO_UNDERLINE_ERROR: - { - int point_x; - int counter = 0; - int end_x = x + PANGO_PIXELS (x_off + ink_rect.x + ink_rect.width); - - for (point_x = x + PANGO_PIXELS (x_off + ink_rect.x) - 1; - point_x <= end_x; - point_x += 2) - { - if (counter) - drawHLine(surface, &color_matrix, - risen_y + 2, - point_x, MIN (point_x + 1, end_x)); - else - drawHLine(surface, &color_matrix, - risen_y + 3, - point_x, MIN (point_x + 1, end_x)); - - counter = (counter + 1) % 2; - } - } - break; - case PANGO_UNDERLINE_LOW: - drawHLine(surface, &color_matrix, - risen_y + PANGO_PIXELS (ink_rect.y + ink_rect.height), - x + PANGO_PIXELS (x_off + ink_rect.x), - x + PANGO_PIXELS (x_off + ink_rect.x + ink_rect.width)); - break; - } - - if (strike) - drawHLine(surface, &color_matrix, - risen_y + PANGO_PIXELS (logical_rect.y + logical_rect.height / 2), - x + PANGO_PIXELS (x_off + logical_rect.x), - x + PANGO_PIXELS (x_off + logical_rect.x + logical_rect.width)); - - x_off += logical_rect.width; - } -} - -/*! - Innter function of Pango. Stolen from GDK. - - @param *item [in] The item to get property - @param *uline [out] Kind of underline - @param *strikethrough [out] Strike-through line - @param *rise [out] Rise/sink of line (for super/subscript) - @param *fg_color [out] Color of foreground - @param *fg_set [out] True if fg_color set - @param *bg_color [out] Color of background - @param *bg_set [out] True if bg_color valid - @param *shape_set [out] True if ink_rect and logical_rect valid - @param *ink_rect [out] Ink rect - @param *logical_rect [out] Logical rect -*/ -static void -getItemProperties ( - PangoItem *item, - PangoUnderline *uline, - gboolean *strikethrough, - gint *rise, - PangoColor *fg_color, - gboolean *fg_set, - PangoColor *bg_color, - gboolean *bg_set, - gboolean *shape_set, - PangoRectangle *ink_rect, - PangoRectangle *logical_rect) -{ - GSList *tmp_list = item->analysis.extra_attrs; - - if (strikethrough) - *strikethrough = FALSE; - - if (fg_set) - *fg_set = FALSE; - - if (bg_set) - *bg_set = FALSE; - - if (shape_set) - *shape_set = FALSE; - - if (rise) - *rise = 0; - - while (tmp_list) { - PangoAttribute *attr = tmp_list->data; - - switch (attr->klass->type) { - case PANGO_ATTR_UNDERLINE: - if (uline) - *uline = ((PangoAttrInt *)attr)->value; - break; - - case PANGO_ATTR_STRIKETHROUGH: - if (strikethrough) - *strikethrough = ((PangoAttrInt *)attr)->value; - break; - - case PANGO_ATTR_FOREGROUND: - if (fg_color) - *fg_color = ((PangoAttrColor *)attr)->color; - if (fg_set) - *fg_set = TRUE; - break; - - case PANGO_ATTR_BACKGROUND: - if (bg_color) - *bg_color = ((PangoAttrColor *)attr)->color; - if (bg_set) - *bg_set = TRUE; - break; - - case PANGO_ATTR_SHAPE: - if (shape_set) - *shape_set = TRUE; - if (logical_rect) - *logical_rect = ((PangoAttrShape *)attr)->logical_rect; - if (ink_rect) - *ink_rect = ((PangoAttrShape *)attr)->ink_rect; - break; - - case PANGO_ATTR_RISE: - if (rise) - *rise = ((PangoAttrInt *)attr)->value; - break; - - default: - break; - } - tmp_list = tmp_list->next; - } -} - -/*! - Copy bitmap to surface. - From (x, y)-(w, h) to (x, y)-(w, h) of rect. - - @param *bitmap [in] Grayscale bitmap - @param *surface [out] Surface - @param *matrix [in] Foreground and background color - @param *rect [in] Rect to copy -*/ -void -SDLPango_CopyFTBitmapToSurface( - const FT_Bitmap *bitmap, - SDL_Surface *surface, - const SDLPango_Matrix *matrix, - SDL_Rect *rect) -{ - int i; - Uint8 *p_ft; - Uint8 *p_sdl; - int width = rect->w; - int height = rect->h; - int x = rect->x; - int y = rect->y; - - if(x + width > surface->w) { - width = surface->w - x; - if(width <= 0) - return; - } - if(y + height > surface->h) { - height = surface->h - y; - if(height <= 0) - return; - } - - if(SDL_LockSurface(surface)) { - SDL_SetError("surface lock failed"); - SDL_FreeSurface(surface); - return; - } - - p_ft = (Uint8 *)bitmap->buffer + (bitmap->pitch * y); - p_sdl = (Uint8 *)surface->pixels + (surface->pitch * y); - for(i = 0; i < height; i ++) { - int k; - for(k = 0; k < width; k ++) { - /* TODO: rewrite by matrix calculation library */ - Uint8 pixel[4]; /* 4: RGBA */ - int n; - - for(n = 0; n < 4; n ++) { - Uint16 w; - w = ((Uint16)matrix->m[n][0] * (256 - p_ft[k + x])) + ((Uint16)matrix->m[n][1] * p_ft[k + x]); - pixel[n] = (Uint8)(w >> 8); - } - - switch(surface->format->BytesPerPixel) { - case 2: - ((Uint16 *)p_sdl)[k + x] = (Uint16)SDL_MapRGBA(surface->format, pixel[0], pixel[1], pixel[2], pixel[3]); - break; - case 4: - ((Uint32 *)p_sdl)[k + x] = SDL_MapRGBA(surface->format, pixel[0], pixel[1], pixel[2], pixel[3]); - break; - default: - SDL_SetError("surface->format->BytesPerPixel is invalid value"); - return; - } - } - p_ft += bitmap->pitch; - p_sdl += surface->pitch; - } - - SDL_UnlockSurface(surface); -} - -/*! - Create a context which contains Pango objects. - - @return A pointer to the context as a SDLPango_Context*. -*/ -SDLPango_Context* -SDLPango_CreateContext() -{ - SDLPango_Context *context = g_malloc(sizeof(SDLPango_Context)); - G_CONST_RETURN char *charset; - - context->font_map = pango_ft2_font_map_new (); - pango_ft2_font_map_set_resolution (PANGO_FT2_FONT_MAP (context->font_map), DEFAULT_DPI, DEFAULT_DPI); - - context->context = pango_ft2_font_map_create_context (PANGO_FT2_FONT_MAP (context->font_map)); - - g_get_charset(&charset); - pango_context_set_language (context->context, pango_language_from_string (charset)); - pango_context_set_base_dir (context->context, PANGO_DIRECTION_LTR); - - context->font_desc = pango_font_description_from_string( - MAKE_FONT_NAME (DEFAULT_FONT_FAMILY, DEFAULT_FONT_SIZE)); - - context->layout = pango_layout_new (context->context); - - SDLPango_SetSurfaceCreateArgs(context, SDL_SWSURFACE | SDL_SRCALPHA, DEFAULT_DEPTH, - DEFAULT_RMASK, DEFAULT_GMASK, DEFAULT_BMASK, DEFAULT_AMASK); - - context->tmp_ftbitmap = NULL; - - context->color_matrix = *MATRIX_TRANSPARENT_BACK_BLACK_LETTER; - - context->min_height = 0; - context->min_width = 0; - - return context; -} - -/*! - Free a context. - - @param *context [i/o] Context to be free -*/ -void -SDLPango_FreeContext(SDLPango_Context *context) -{ - freeFTBitmap(context->tmp_ftbitmap); - - g_object_unref (context->layout); - - pango_font_description_free(context->font_desc); - - g_object_unref(context->context); - - g_object_unref(context->font_map); - - g_free(context); -} - -/*! - Specify Arguments when create a surface. - When SDL_Pango creates a surface, the arguments are used. - - @param *context [i/o] Context - @param flags [in] Same as SDL_CreateRGBSurface() - @param depth [in] Same as SDL_CreateRGBSurface() - @param Rmask [in] Same as SDL_CreateRGBSurface() - @param Gmask [in] Same as SDL_CreateRGBSurface() - @param Bmask [in] Same as SDL_CreateRGBSurface() - @param Amask [in] Same as SDL_CreateRGBSurface() -*/ -void -SDLPango_SetSurfaceCreateArgs( - SDLPango_Context *context, - Uint32 flags, - int depth, - Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask) -{ - context->surface_args.flags = flags; - context->surface_args.depth = depth; - context->surface_args.Rmask = Rmask; - context->surface_args.Gmask = Gmask; - context->surface_args.Bmask = Bmask; - context->surface_args.Amask = Amask; -} - -/*! - Create a surface and draw text on it. - The size of surface is same as lauout size. - - @param *context [in] Context - @return A newly created surface -*/ -SDL_Surface * SDLPango_CreateSurfaceDraw( - SDLPango_Context *context) -{ - PangoRectangle logical_rect; - SDL_Surface *surface; - int width, height; - - pango_layout_get_extents (context->layout, NULL, &logical_rect); - width = PANGO_PIXELS (logical_rect.width); - height = PANGO_PIXELS (logical_rect.height); - if(width < context->min_width) - width = context->min_width; - if(height < context->min_height) - height = context->min_height; - - surface = SDL_CreateRGBSurface( - context->surface_args.flags, - width, height, context->surface_args.depth, - context->surface_args.Rmask, - context->surface_args.Gmask, - context->surface_args.Bmask, - context->surface_args.Amask); - - SDLPango_Draw(context, surface, 0, 0); - - return surface; -} - -/*! - Draw text on a existing surface. - - @param *context [in] Context - @param *surface [i/o] Surface to draw on it - @param x [in] X of left-top of drawing area - @param y [in] Y of left-top of drawing area -*/ -void -SDLPango_Draw( - SDLPango_Context *context, - SDL_Surface *surface, - int x, int y) -{ - PangoLayoutIter *iter; - PangoRectangle logical_rect; - int width, height; - - if(! surface) { - SDL_SetError("surface is NULL"); - return; - } - - iter = pango_layout_get_iter (context->layout); - - pango_layout_get_extents (context->layout, NULL, &logical_rect); - width = PANGO_PIXELS (logical_rect.width); - height = PANGO_PIXELS (logical_rect.height); - - SDL_FillRect(surface, NULL, SDL_MapRGBA(surface->format, 0, 0, 0, 0)); - - if((! context->tmp_ftbitmap) || context->tmp_ftbitmap->width < width - || context->tmp_ftbitmap->rows < height) - { - freeFTBitmap(context->tmp_ftbitmap); - context->tmp_ftbitmap = createFTBitmap(width, height); - } - - do { - PangoLayoutLine *line; - int baseline; - - line = pango_layout_iter_get_line (iter); - - pango_layout_iter_get_line_extents (iter, NULL, &logical_rect); - baseline = pango_layout_iter_get_baseline (iter); - - drawLine( - context, - surface, - line, - x + PANGO_PIXELS (logical_rect.x), - y + PANGO_PIXELS (logical_rect.y), - PANGO_PIXELS (logical_rect.height), - PANGO_PIXELS (baseline - logical_rect.y)); - } while (pango_layout_iter_next_line (iter)); - - pango_layout_iter_free (iter); -} - -/*! - Allocate buffer and create a FTBitmap object. - - @param width [in] Width - @param height [in] Height - @return FTBitmap object -*/ -static FT_Bitmap * -createFTBitmap( - int width, int height) -{ - FT_Bitmap *bitmap; - guchar *buf; - - bitmap = g_malloc(sizeof(FT_Bitmap)); - bitmap->width = width; - bitmap->rows = height; - bitmap->pitch = (width + 3) & ~3; - bitmap->num_grays = 256; - bitmap->pixel_mode = FT_PIXEL_MODE_GRAY; - buf = g_malloc (bitmap->pitch * bitmap->rows); - memset (buf, 0x00, bitmap->pitch * bitmap->rows); - bitmap->buffer = buf; - - return bitmap; -} - -/*! - Free a FTBitmap object. - - @param *bitmap [i/o] FTbitmap to be free -*/ -static void -freeFTBitmap( - FT_Bitmap *bitmap) -{ - if(bitmap) { - g_free(bitmap->buffer); - g_free(bitmap); - } -} - -/*! - Clear a FTBitmap object. - - @param *bitmap [i/o] FTbitmap to be clear -*/ -static void -clearFTBitmap( - FT_Bitmap *bitmap) -{ - Uint8 *p = (Uint8 *)bitmap->buffer; - int length = bitmap->pitch * bitmap->rows; - - memset(p, 0, length); -} - -/*! - Specify minimum size of drawing rect. - - @param *context [i/o] Context - @param width [in] Width. -1 means no wrapping mode. - @param height [in] Height. zero/minus value means non-specified. -*/ -void -SDLPango_SetMinimumSize( - SDLPango_Context *context, - int width, int height) -{ - int pango_width; - if(width > 0) - pango_width = width * PANGO_SCALE; - else - pango_width = -1; - pango_layout_set_width(context->layout, pango_width); - - context->min_width = width; - context->min_height = height; -} - -/*! - Specify default color. - - @param *context [i/o] Context - @param *color_matrix [in] Foreground and background color -*/ -void -SDLPango_SetDefaultColor( - SDLPango_Context *context, - const SDLPango_Matrix *color_matrix) -{ - context->color_matrix = *color_matrix; -} - -/*! - Get layout width. - - @param *context [in] Context - @return Width -*/ -int -SDLPango_GetLayoutWidth( - SDLPango_Context *context) -{ - PangoRectangle logical_rect; - - pango_layout_get_extents (context->layout, NULL, &logical_rect); - - return PANGO_PIXELS (logical_rect.width); -} - -/*! - Get layout height. - - @param *context [in] Context - @return Height -*/ -int -SDLPango_GetLayoutHeight( - SDLPango_Context *context) -{ - PangoRectangle logical_rect; - - pango_layout_get_extents (context->layout, NULL, &logical_rect); - - return PANGO_PIXELS (logical_rect.height); -} - -/*! - Set markup text to context. - Text must be utf-8. - Markup format is same as pango. - - @param *context [i/o] Context - @param *markup [in] Markup text - @param length [in] Text length. -1 means NULL-terminated text. -*/ -void -SDLPango_SetMarkup( - SDLPango_Context *context, - const char *markup, - int length) -{ - pango_layout_set_markup (context->layout, markup, length); - pango_layout_set_auto_dir (context->layout, TRUE); - pango_layout_set_alignment (context->layout, PANGO_ALIGN_LEFT); - pango_layout_set_font_description (context->layout, context->font_desc); -} - -/*! - Set plain text to context. - Text must be utf-8. - - @param *context [i/o] Context - @param *text [in] Plain text - @param length [in] Text length. -1 means NULL-terminated text. -*/ -void -SDLPango_SetText( - SDLPango_Context *context, - const char *text, - int length) -{ - pango_layout_set_attributes(context->layout, NULL); - pango_layout_set_text (context->layout, text, length); - pango_layout_set_auto_dir (context->layout, TRUE); - pango_layout_set_alignment (context->layout, PANGO_ALIGN_LEFT); - pango_layout_set_font_description (context->layout, context->font_desc); -} - -/*! - Set DPI to context. - - @param *context [i/o] Context - @param dpi_x [in] X dpi - @param dpi_y [in] Y dpi -*/ -void -SDLPango_SetDpi( - SDLPango_Context *context, - double dpi_x, double dpi_y) -{ - pango_ft2_font_map_set_resolution (PANGO_FT2_FONT_MAP (context->font_map), dpi_x, dpi_y); -} - -/*! - Set language to context. - - @param *context [i/o] Context - @param *language_tag [in] A RFC-3066 format language tag -*/ -void SDLCALL SDLPango_SetLanguage( - SDLPango_Context *context, - const char *language_tag) -{ - pango_context_set_language (context->context, pango_language_from_string (language_tag)); -} - -/*! - Set base direction to context. - - @param *context [i/o] Context - @param direction [in] Direction -*/ -void SDLCALL SDLPango_SetBaseDirection( - SDLPango_Context *context, - SDLPango_Direction direction) -{ - PangoDirection pango_dir; - - switch(direction) { - case SDLPANGO_DIRECTION_LTR: - pango_dir = PANGO_DIRECTION_LTR; - break; - case SDLPANGO_DIRECTION_RTL: - pango_dir = PANGO_DIRECTION_RTL; - break; - case SDLPANGO_DIRECTION_WEAK_LTR: - pango_dir = PANGO_DIRECTION_WEAK_LTR; - break; - case SDLPANGO_DIRECTION_WEAK_RTL: - pango_dir = PANGO_DIRECTION_WEAK_RTL; - break; - case SDLPANGO_DIRECTION_NEUTRAL: - pango_dir = PANGO_DIRECTION_NEUTRAL; - break; - default: - SDL_SetError("unknown direction value"); - return; - } - - pango_context_set_base_dir (context->context, pango_dir); -} - -/*! - Get font map from context. - - @param *context [in] Context - @return Font map -*/ -PangoFontMap* SDLCALL SDLPango_GetPangoFontMap( - SDLPango_Context *context) -{ - return context->font_map; -} - -/*! - Get font description from context. - - @param *context [in] Context - @return Font description -*/ -PangoFontDescription* SDLCALL SDLPango_GetPangoFontDescription( - SDLPango_Context *context) -{ - return context->font_desc; -} - -/*! - Get layout from context. - - @param *context [in] Context - @return Layout -*/ -PangoLayout* SDLCALL SDLPango_GetPangoLayout( - SDLPango_Context *context) -{ - return context->layout; -} +/* SDL_Pango.c -- A companion library to SDL for working with Pango. + Copyright (C) 2004 NAKAMURA Ken'ichi + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +*/ + +/*! + \mainpage + + \section intro Introduction + + Pango is the text rendering engine of GNOME 2.x. SDL_Pango connects the + engine to SDL. In Windows, pre-built binary package (MSI and merge module) + is provided. + + \subsection dist Distribution + + If you are a game software developer, you should know the difficulties of + distribution. So I will start to introduce SDL_Pango from the viewpoint + of distribution. + + In Un*x, SDL_Pango is hard to use as system-independent module, because + it depends on fontconfig and Pango which are designed as system-singleton + modules. If you use SDL_Pango, your software will require those modules + installed to target system. If your software is shipped as shrink-wrap + package, it may cause much problem on your support desk. You should + carefully design your installation process. + + In Windows, SDL_Pango is distributed as "merge module" which contains + fontconfig and Pango. Those binaries are modified as side-by-side components. + You should use Windows Installer and merge the module + on your MSI package. The merge module not only contains files, but also includes + custom action which must be run at installation. + + \subsection api High-level API + + From the viewpoint of text rendering, the heart of SDL_Pango is high-level API. + Other text rendering APIs, like DrawText() of Windows, font and text must be + specified separately. In SDL_Pango, font specification is embedded in text like + HTML: + + \code + This is Courier New and italic. + \endcode + + Color, size, subscript/superscript, obliquing, weight, and other many features + are also available in same way. + + \subsection i18n Internationalized Text + + Internationalized text is another key feature. Text is specified by UTF-8. RTL + script (Arabic and Hebrew) and complicated rendering (Arabic, Indic and Thai) are + supported. You can see it with GNOME 2.x. + + \section get Getting Started + + \subsection getlatest Get latest files + + Get latest files from http://sourceforge.net/projects/sdlpango/ . + + \subsection install Install Header and Library + + In Windows and VS2003, I strongly recommend you to install MSI package. It contains Pango + and fontconfig binaries which are modified as side-by-side components. It is + nearly impossible to build them. (I spent much time to build them...) + + In MinGW, I recommend you to use VS2003. Otherwise you may run into the maze of + distribution. If you insist MinGW, you should use MinGW binary archive. + + In Un*x, installation consists of: + + \code + ./configure + make + make install + \endcode + + \subsection inc Includes + + To use SDL_Pango functions in a C/C++ source code file, you must use the SDL_Pango.h + include file: + + \code + #include "SDL_Pango.h" + \endcode + + In Windows, SDL_Pango.h is installed on \c \%ProgramFiles\%\\SDL_Pango \c Development\\include + (usually \c C:\\Program \c Files\\SDL_Pango \c Development\\include). You should add this + directory to include path. + + \subsection comp Compiling + + In Un*x, to link with SDL_Pango you should use sdl-config to get the required SDL + compilation options. After that, compiling with SDL_Pango is quite easy. + + Note: Some systems may not have the SDL_Pango library and include file in the same + place as the SDL library and includes are located, in that case you will need to + add more -I and -L paths to these command lines. + + Simple Example for compiling an object file: + + \code + cc -c `sdl-config --cflags` mysource.c + \endcode + + Simple Example for linking an object file: + + \code + cc -o myprogram mysource.o `sdl-config --libs` -lSDL_Pango + \endcode + + Now myprogram is ready to run. + + You can see a sample of autoconfiscation in 'test' directory. + + In Windows, MSI package installs many dlls to \c \%ProgramFiles\%\\SDL_Pango \c Development\\import_lib. + To link with SDL_Pango you should use SDL_Pango.lib. + + SDL_Pango.dll depends on many dlls and other many files. Those dlls are installed on + \c \%ProgramFiles\%\\SDL_Pango \c Development\\bin. MSI package adds the directory to PATH environment + variable. + + \section devel Development + + \subsection font Font Handling + + In Un*x, font handling depends on fontconfig of your system. + + In Windows, local.conf of fontconfig is placed on \c \%ProgramFiles\%\\SDL_Pango \c Development\\etc\\fonts. + You should know about fontconfig's font cache mechanism. + + \subsection example Step-by-step Example + + The operation of SDL_Pango is done via context. + + \code + SDLPango_Context *context = SDLPango_CreateContext(); + \endcode + + Specify default colors and minimum surface size. + + \code + SDLPango_SetDefaultColor(context, MATRIX_TRANSPARENT_BACK_WHITE_LETTER); + SDLPango_SetMinimumSize(context, 640, 0); + \endcode + + Set markup text. + + \code + SDLPango_SetMarkup(context, "This is markup text.", -1); + \endcode + + Now you can get the size of surface. + + \code + int w = SDLPango_GetLayoutWidth(context); + int h = SDLPango_GetLayoutHeight(context); + \endcode + + Create surface to draw. + + \code + int margin_x = 10; + int margin_y = 10; + SDL_Surface *surface = SDL_CreateRGBSurface(SDL_SWSURFACE, + w + margin_x * 2, h + margin_y * 2, + 32, (Uint32)(255 << (8 * 3)), (Uint32)(255 << (8 * 2)), + (Uint32)(255 << (8 * 1)), 255); + \endcode + + And draw on it. + + \code + SDLPango_Draw(context, surface, margin_x, margin_y); + \endcode + + You must free the surface by yourself. + + \code + SDL_FreeSurface(surface); + \endcode + + Free context. + + \code + SDLPango_FreeContext(context); + \endcode + + You can see actual code in \c test/testbench.cpp. + + \subsection pack Packaging + + In Un*x, do it yourself. + + In Windows, font files must be installed on apprication folder (usually + \c C:\\Program \c Files\\[Manufacturer]\\[ProductName]). The property of + apprication folder must be \c TARGETDIR (this is default setting of VS2003). + SDL.dll also must be installed on apprication folder. Add SDL_Pango.msm to + your MSI package. + + \section ack Acknowledgment + + SDL_Pango is developed with financial assistance of Information-technology Promotion Agency, Japan. + +- NAKAMURA Ken'ichi + +*/ + +/*! @file + @brief Implementation of SDL_Pango + + @author NAKAMURA Ken'ichi + @date 2004/12/07 + $Revision: 1.6 $ +*/ + +#include +#include + +#include "SDL_Pango.h" + +//! non-zero if initialized +static int IS_INITIALIZED = 0; + +#define DEFAULT_FONT_FAMILY "Sans" +#define DEFAULT_FONT_SIZE 12 +#define DEFAULT_DPI 96 +#define _MAKE_FONT_NAME(family, size) family " " #size +#define MAKE_FONT_NAME(family, size) _MAKE_FONT_NAME(family, size) +#define DEFAULT_DEPTH 32 +#define DEFAULT_RMASK (Uint32)(255 << (8 * 3)) +#define DEFAULT_GMASK (Uint32)(255 << (8 * 2)) +#define DEFAULT_BMASK (Uint32)(255 << (8 * 1)) +#define DEFAULT_AMASK (Uint32)255 + +static FT_Bitmap *createFTBitmap(int width, int height); + +static void freeFTBitmap(FT_Bitmap *bitmap); + +static void getItemProperties ( + PangoItem *item, + PangoUnderline *uline, + gboolean *strikethrough, + gint *rise, + PangoColor *fg_color, + gboolean *fg_set, + PangoColor *bg_color, + gboolean *bg_set, + gboolean *shape_set, + PangoRectangle *ink_rect, + PangoRectangle *logical_rect); + +static void clearFTBitmap(FT_Bitmap *bitmap); + +typedef struct _surfaceArgs { + Uint32 flags; + int depth; + Uint32 Rmask; + Uint32 Gmask; + Uint32 Bmask; + Uint32 Amask; +} surfaceArgs; + +typedef struct _contextImpl { + PangoContext *context; + PangoFontMap *font_map; + PangoFontDescription *font_desc; + PangoLayout *layout; + surfaceArgs surface_args; + FT_Bitmap *tmp_ftbitmap; + SDLPango_Matrix color_matrix; + int min_width; + int min_height; +} contextImpl; + + +/*! + Initialize the Glib and Pango API. + This must be called before using other functions in this library, + excepting SDLPango_WasInit. + SDL does not have to be initialized before this call. + + + @return always 0. +*/ +int +SDLPango_Init() +{ + g_type_init(); + + IS_INITIALIZED = -1; + + return 0; +} + +/*! + Query the initilization status of the Glib and Pango API. + You may, of course, use this before SDLPango_Init to avoid + initilizing twice in a row. + + @return zero when already initialized. + non-zero when not initialized. +*/ +int +SDLPango_WasInit() +{ + return IS_INITIALIZED; +} + +/*! + Draw glyphs on rect. + + @param *context [in] Context + @param *surface [out] Surface to draw on it + @param *color_matrix [in] Foreground and background color + @param *font [in] Innter variable of Pango + @param *glyphs [in] Innter variable of Pango + @param *rect [in] Draw on this area + @param baseline [in] Horizontal location of glyphs +*/ +static void +drawGlyphString( + SDLPango_Context *context, + SDL_Surface *surface, + SDLPango_Matrix *color_matrix, + PangoFont *font, + PangoGlyphString *glyphs, + SDL_Rect *rect, + int baseline) +{ + pango_ft2_render(context->tmp_ftbitmap, font, glyphs, rect->x, rect->y + baseline); + + SDLPango_CopyFTBitmapToSurface( + context->tmp_ftbitmap, + surface, + color_matrix, + rect); + + clearFTBitmap(context->tmp_ftbitmap); +} + +/*! + Draw horizontal line of a pixel. + + @param *surface [out] Surface to draw on it + @param *color_matrix [in] Foreground and background color + @param y [in] Y location of line + @param start [in] Left of line + @param end [in] Right of line +*/ +static void drawHLine( + SDL_Surface *surface, + SDLPango_Matrix *color_matrix, + int y, + int start, + int end) +{ + Uint8 *p; + Uint16 *p16; + Uint32 *p32; + Uint32 color; + int ix; + int pixel_bytes = surface->format->BytesPerPixel; + + if (y < 0 || y >= surface->h) + return; + + if (end <= 0 || start >= surface->w) + return; + + if (start < 0) + start = 0; + + if (end >= surface->w) + end = surface->w; + + p = (Uint8 *)(surface->pixels) + y * surface->pitch + start * pixel_bytes; + color = SDL_MapRGBA(surface->format, + color_matrix->m[0][1], + color_matrix->m[1][1], + color_matrix->m[2][1], + color_matrix->m[3][1]); + + switch(pixel_bytes) { + case 2: + p16 = (Uint16 *)p; + for (ix = 0; ix < end - start; ix++) + *p16++ = (Uint16)color; + break; + case 4: + p32 = (Uint32 *)p; + for (ix = 0; ix < end - start; ix++) + *p32++ = color; + break; + default: + SDL_SetError("surface->format->BytesPerPixel is invalid value"); + break; + } +} + +/*! + Draw a line. + + @param *context [in] Context + @param *surface [out] Surface to draw on it + @param *line [in] Innter variable of Pango + @param x [in] X location of line + @param y [in] Y location of line + @param height [in] Height of line + @param baseline [in] Rise / sink of line (for super/subscript) +*/ +static void +drawLine( + SDLPango_Context *context, + SDL_Surface *surface, + PangoLayoutLine *line, + gint x, + gint y, + gint height, + gint baseline) +{ + GSList *tmp_list = line->runs; + PangoColor fg_color, bg_color; + PangoRectangle logical_rect; + PangoRectangle ink_rect; + int x_off = 0; + + while (tmp_list) { + SDLPango_Matrix color_matrix = context->color_matrix; + PangoUnderline uline = PANGO_UNDERLINE_NONE; + gboolean strike, fg_set, bg_set, shape_set; + gint rise, risen_y; + PangoLayoutRun *run = tmp_list->data; + SDL_Rect d_rect; + + tmp_list = tmp_list->next; + + getItemProperties(run->item, + &uline, &strike, &rise, + &fg_color, &fg_set, &bg_color, &bg_set, + &shape_set, &ink_rect, &logical_rect); + + risen_y = y + baseline - PANGO_PIXELS (rise); + + if(fg_set) { + color_matrix.m[0][1] = (Uint8)(fg_color.red >> 8); + color_matrix.m[1][1] = (Uint8)(fg_color.green >> 8); + color_matrix.m[2][1] = (Uint8)(fg_color.blue >> 8); + color_matrix.m[3][1] = 255; + if(color_matrix.m[3][0] == 0) { + color_matrix.m[0][0] = (Uint8)(fg_color.red >> 8); + color_matrix.m[1][0] = (Uint8)(fg_color.green >> 8); + color_matrix.m[2][0] = (Uint8)(fg_color.blue >> 8); + } + } + + if (bg_set) { + color_matrix.m[0][0] = (Uint8)(bg_color.red >> 8); + color_matrix.m[1][0] = (Uint8)(bg_color.green >> 8); + color_matrix.m[2][0] = (Uint8)(bg_color.blue >> 8); + color_matrix.m[3][0] = 255; + } + + if(! shape_set) { + if (uline == PANGO_UNDERLINE_NONE) + pango_glyph_string_extents (run->glyphs, run->item->analysis.font, + NULL, &logical_rect); + else + pango_glyph_string_extents (run->glyphs, run->item->analysis.font, + &ink_rect, &logical_rect); + + d_rect.w = (Uint16)PANGO_PIXELS(logical_rect.width); + d_rect.h = (Uint16)height; + d_rect.x = (Uint16)(x + PANGO_PIXELS (x_off)); + d_rect.y = (Uint16)(risen_y - baseline); + + if((! context->tmp_ftbitmap) || d_rect.w + d_rect.x > context->tmp_ftbitmap->width + || d_rect.h + d_rect.y > context->tmp_ftbitmap->rows) + { + freeFTBitmap(context->tmp_ftbitmap); + context->tmp_ftbitmap = createFTBitmap(d_rect.w + d_rect.x, d_rect.h + d_rect.y); + } + + drawGlyphString(context, surface, + &color_matrix, + run->item->analysis.font, run->glyphs, &d_rect, baseline); + } + switch (uline) { + case PANGO_UNDERLINE_NONE: + break; + case PANGO_UNDERLINE_DOUBLE: + drawHLine(surface, &color_matrix, + risen_y + 4, + x + PANGO_PIXELS (x_off + ink_rect.x), + x + PANGO_PIXELS (x_off + ink_rect.x + ink_rect.width)); + /* Fall through */ + case PANGO_UNDERLINE_SINGLE: + drawHLine(surface, &color_matrix, + risen_y + 2, + x + PANGO_PIXELS (x_off + ink_rect.x), + x + PANGO_PIXELS (x_off + ink_rect.x + ink_rect.width)); + break; + case PANGO_UNDERLINE_ERROR: + { + int point_x; + int counter = 0; + int end_x = x + PANGO_PIXELS (x_off + ink_rect.x + ink_rect.width); + + for (point_x = x + PANGO_PIXELS (x_off + ink_rect.x) - 1; + point_x <= end_x; + point_x += 2) + { + if (counter) + drawHLine(surface, &color_matrix, + risen_y + 2, + point_x, MIN (point_x + 1, end_x)); + else + drawHLine(surface, &color_matrix, + risen_y + 3, + point_x, MIN (point_x + 1, end_x)); + + counter = (counter + 1) % 2; + } + } + break; + case PANGO_UNDERLINE_LOW: + drawHLine(surface, &color_matrix, + risen_y + PANGO_PIXELS (ink_rect.y + ink_rect.height), + x + PANGO_PIXELS (x_off + ink_rect.x), + x + PANGO_PIXELS (x_off + ink_rect.x + ink_rect.width)); + break; + } + + if (strike) + drawHLine(surface, &color_matrix, + risen_y + PANGO_PIXELS (logical_rect.y + logical_rect.height / 2), + x + PANGO_PIXELS (x_off + logical_rect.x), + x + PANGO_PIXELS (x_off + logical_rect.x + logical_rect.width)); + + x_off += logical_rect.width; + } +} + +/*! + Innter function of Pango. Stolen from GDK. + + @param *item [in] The item to get property + @param *uline [out] Kind of underline + @param *strikethrough [out] Strike-through line + @param *rise [out] Rise/sink of line (for super/subscript) + @param *fg_color [out] Color of foreground + @param *fg_set [out] True if fg_color set + @param *bg_color [out] Color of background + @param *bg_set [out] True if bg_color valid + @param *shape_set [out] True if ink_rect and logical_rect valid + @param *ink_rect [out] Ink rect + @param *logical_rect [out] Logical rect +*/ +static void +getItemProperties ( + PangoItem *item, + PangoUnderline *uline, + gboolean *strikethrough, + gint *rise, + PangoColor *fg_color, + gboolean *fg_set, + PangoColor *bg_color, + gboolean *bg_set, + gboolean *shape_set, + PangoRectangle *ink_rect, + PangoRectangle *logical_rect) +{ + GSList *tmp_list = item->analysis.extra_attrs; + + if (strikethrough) + *strikethrough = FALSE; + + if (fg_set) + *fg_set = FALSE; + + if (bg_set) + *bg_set = FALSE; + + if (shape_set) + *shape_set = FALSE; + + if (rise) + *rise = 0; + + while (tmp_list) { + PangoAttribute *attr = tmp_list->data; + + switch (attr->klass->type) { + case PANGO_ATTR_UNDERLINE: + if (uline) + *uline = ((PangoAttrInt *)attr)->value; + break; + + case PANGO_ATTR_STRIKETHROUGH: + if (strikethrough) + *strikethrough = ((PangoAttrInt *)attr)->value; + break; + + case PANGO_ATTR_FOREGROUND: + if (fg_color) + *fg_color = ((PangoAttrColor *)attr)->color; + if (fg_set) + *fg_set = TRUE; + break; + + case PANGO_ATTR_BACKGROUND: + if (bg_color) + *bg_color = ((PangoAttrColor *)attr)->color; + if (bg_set) + *bg_set = TRUE; + break; + + case PANGO_ATTR_SHAPE: + if (shape_set) + *shape_set = TRUE; + if (logical_rect) + *logical_rect = ((PangoAttrShape *)attr)->logical_rect; + if (ink_rect) + *ink_rect = ((PangoAttrShape *)attr)->ink_rect; + break; + + case PANGO_ATTR_RISE: + if (rise) + *rise = ((PangoAttrInt *)attr)->value; + break; + + default: + break; + } + tmp_list = tmp_list->next; + } +} + +/*! + Copy bitmap to surface. + From (x, y)-(w, h) to (x, y)-(w, h) of rect. + + @param *bitmap [in] Grayscale bitmap + @param *surface [out] Surface + @param *matrix [in] Foreground and background color + @param *rect [in] Rect to copy +*/ +void +SDLPango_CopyFTBitmapToSurface( + const FT_Bitmap *bitmap, + SDL_Surface *surface, + const SDLPango_Matrix *matrix, + SDL_Rect *rect) +{ + int i; + Uint8 *p_ft; + Uint8 *p_sdl; + int width = rect->w; + int height = rect->h; + int x = rect->x; + int y = rect->y; + + if(x + width > surface->w) { + width = surface->w - x; + if(width <= 0) + return; + } + if(y + height > surface->h) { + height = surface->h - y; + if(height <= 0) + return; + } + + if(SDL_LockSurface(surface)) { + SDL_SetError("surface lock failed"); + SDL_FreeSurface(surface); + return; + } + + p_ft = (Uint8 *)bitmap->buffer + (bitmap->pitch * y); + p_sdl = (Uint8 *)surface->pixels + (surface->pitch * y); + for(i = 0; i < height; i ++) { + int k; + for(k = 0; k < width; k ++) { + /* TODO: rewrite by matrix calculation library */ + Uint8 pixel[4]; /* 4: RGBA */ + int n; + + for(n = 0; n < 4; n ++) { + Uint16 w; + w = ((Uint16)matrix->m[n][0] * (256 - p_ft[k + x])) + ((Uint16)matrix->m[n][1] * p_ft[k + x]); + pixel[n] = (Uint8)(w >> 8); + } + + switch(surface->format->BytesPerPixel) { + case 2: + ((Uint16 *)p_sdl)[k + x] = (Uint16)SDL_MapRGBA(surface->format, pixel[0], pixel[1], pixel[2], pixel[3]); + break; + case 4: + ((Uint32 *)p_sdl)[k + x] = SDL_MapRGBA(surface->format, pixel[0], pixel[1], pixel[2], pixel[3]); + break; + default: + SDL_SetError("surface->format->BytesPerPixel is invalid value"); + return; + } + } + p_ft += bitmap->pitch; + p_sdl += surface->pitch; + } + + SDL_UnlockSurface(surface); +} + +SDLPango_Context* +SDLPango_CreateContext_GivenFontDesc(const char* font_desc) +{ + SDLPango_Context *context = g_malloc(sizeof(SDLPango_Context)); + G_CONST_RETURN char *charset; + + context->font_map = pango_ft2_font_map_new (); + pango_ft2_font_map_set_resolution (PANGO_FT2_FONT_MAP (context->font_map), DEFAULT_DPI, DEFAULT_DPI); + + context->context = pango_ft2_font_map_create_context (PANGO_FT2_FONT_MAP (context->font_map)); + + g_get_charset(&charset); + pango_context_set_language (context->context, pango_language_from_string (charset)); + pango_context_set_base_dir (context->context, PANGO_DIRECTION_LTR); + + context->font_desc = pango_font_description_from_string(font_desc); + + context->layout = pango_layout_new (context->context); + + SDLPango_SetSurfaceCreateArgs(context, SDL_SWSURFACE | SDL_SRCALPHA, DEFAULT_DEPTH, + DEFAULT_RMASK, DEFAULT_GMASK, DEFAULT_BMASK, DEFAULT_AMASK); + + context->tmp_ftbitmap = NULL; + + context->color_matrix = *MATRIX_TRANSPARENT_BACK_BLACK_LETTER; + + context->min_height = 0; + context->min_width = 0; + + return context; +} + +/*! + Create a context which contains Pango objects. + + @return A pointer to the context as a SDLPango_Context*. +*/ +SDLPango_Context* +SDLPango_CreateContext() +{ + SDLPango_CreateContext_GivenFontDesc(MAKE_FONT_NAME(DEFAULT_FONT_FAMILY, DEFAULT_FONT_SIZE)); +} + +/*! + Free a context. + + @param *context [i/o] Context to be free +*/ +void +SDLPango_FreeContext(SDLPango_Context *context) +{ + freeFTBitmap(context->tmp_ftbitmap); + + g_object_unref (context->layout); + + pango_font_description_free(context->font_desc); + + g_object_unref(context->context); + + g_object_unref(context->font_map); + + g_free(context); +} + +/*! + Specify Arguments when create a surface. + When SDL_Pango creates a surface, the arguments are used. + + @param *context [i/o] Context + @param flags [in] Same as SDL_CreateRGBSurface() + @param depth [in] Same as SDL_CreateRGBSurface() + @param Rmask [in] Same as SDL_CreateRGBSurface() + @param Gmask [in] Same as SDL_CreateRGBSurface() + @param Bmask [in] Same as SDL_CreateRGBSurface() + @param Amask [in] Same as SDL_CreateRGBSurface() +*/ +void +SDLPango_SetSurfaceCreateArgs( + SDLPango_Context *context, + Uint32 flags, + int depth, + Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask) +{ + context->surface_args.flags = flags; + context->surface_args.depth = depth; + context->surface_args.Rmask = Rmask; + context->surface_args.Gmask = Gmask; + context->surface_args.Bmask = Bmask; + context->surface_args.Amask = Amask; +} + +/*! + Create a surface and draw text on it. + The size of surface is same as lauout size. + + @param *context [in] Context + @return A newly created surface +*/ +SDL_Surface * SDLPango_CreateSurfaceDraw( + SDLPango_Context *context) +{ + PangoRectangle logical_rect; + SDL_Surface *surface; + int width, height; + + pango_layout_get_extents (context->layout, NULL, &logical_rect); + width = PANGO_PIXELS (logical_rect.width); + height = PANGO_PIXELS (logical_rect.height); + if(width < context->min_width) + width = context->min_width; + if(height < context->min_height) + height = context->min_height; + + surface = SDL_CreateRGBSurface( + context->surface_args.flags, + width, height, context->surface_args.depth, + context->surface_args.Rmask, + context->surface_args.Gmask, + context->surface_args.Bmask, + context->surface_args.Amask); + + SDLPango_Draw(context, surface, 0, 0); + + return surface; +} + +/*! + Draw text on a existing surface. + + @param *context [in] Context + @param *surface [i/o] Surface to draw on it + @param x [in] X of left-top of drawing area + @param y [in] Y of left-top of drawing area +*/ +void +SDLPango_Draw( + SDLPango_Context *context, + SDL_Surface *surface, + int x, int y) +{ + PangoLayoutIter *iter; + PangoRectangle logical_rect; + int width, height; + + if(! surface) { + SDL_SetError("surface is NULL"); + return; + } + + iter = pango_layout_get_iter (context->layout); + + pango_layout_get_extents (context->layout, NULL, &logical_rect); + width = PANGO_PIXELS (logical_rect.width); + height = PANGO_PIXELS (logical_rect.height); + + SDL_FillRect(surface, NULL, SDL_MapRGBA(surface->format, 0, 0, 0, 0)); + + if((! context->tmp_ftbitmap) || context->tmp_ftbitmap->width < width + || context->tmp_ftbitmap->rows < height) + { + freeFTBitmap(context->tmp_ftbitmap); + context->tmp_ftbitmap = createFTBitmap(width, height); + } + + do { + PangoLayoutLine *line; + int baseline; + + line = pango_layout_iter_get_line (iter); + + pango_layout_iter_get_line_extents (iter, NULL, &logical_rect); + baseline = pango_layout_iter_get_baseline (iter); + + drawLine( + context, + surface, + line, + x + PANGO_PIXELS (logical_rect.x), + y + PANGO_PIXELS (logical_rect.y), + PANGO_PIXELS (logical_rect.height), + PANGO_PIXELS (baseline - logical_rect.y)); + } while (pango_layout_iter_next_line (iter)); + + pango_layout_iter_free (iter); +} + +/*! + Allocate buffer and create a FTBitmap object. + + @param width [in] Width + @param height [in] Height + @return FTBitmap object +*/ +static FT_Bitmap * +createFTBitmap( + int width, int height) +{ + FT_Bitmap *bitmap; + guchar *buf; + + bitmap = g_malloc(sizeof(FT_Bitmap)); + bitmap->width = width; + bitmap->rows = height; + bitmap->pitch = (width + 3) & ~3; + bitmap->num_grays = 256; + bitmap->pixel_mode = FT_PIXEL_MODE_GRAY; + buf = g_malloc (bitmap->pitch * bitmap->rows); + memset (buf, 0x00, bitmap->pitch * bitmap->rows); + bitmap->buffer = buf; + + return bitmap; +} + +/*! + Free a FTBitmap object. + + @param *bitmap [i/o] FTbitmap to be free +*/ +static void +freeFTBitmap( + FT_Bitmap *bitmap) +{ + if(bitmap) { + g_free(bitmap->buffer); + g_free(bitmap); + } +} + +/*! + Clear a FTBitmap object. + + @param *bitmap [i/o] FTbitmap to be clear +*/ +static void +clearFTBitmap( + FT_Bitmap *bitmap) +{ + Uint8 *p = (Uint8 *)bitmap->buffer; + int length = bitmap->pitch * bitmap->rows; + + memset(p, 0, length); +} + +/*! + Specify minimum size of drawing rect. + + @param *context [i/o] Context + @param width [in] Width. -1 means no wrapping mode. + @param height [in] Height. zero/minus value means non-specified. +*/ +void +SDLPango_SetMinimumSize( + SDLPango_Context *context, + int width, int height) +{ + int pango_width; + if(width > 0) + pango_width = width * PANGO_SCALE; + else + pango_width = -1; + pango_layout_set_width(context->layout, pango_width); + + context->min_width = width; + context->min_height = height; +} + +/*! + Specify default color. + + @param *context [i/o] Context + @param *color_matrix [in] Foreground and background color +*/ +void +SDLPango_SetDefaultColor( + SDLPango_Context *context, + const SDLPango_Matrix *color_matrix) +{ + context->color_matrix = *color_matrix; +} + +/*! + Get layout width. + + @param *context [in] Context + @return Width +*/ +int +SDLPango_GetLayoutWidth( + SDLPango_Context *context) +{ + PangoRectangle logical_rect; + + pango_layout_get_extents (context->layout, NULL, &logical_rect); + + return PANGO_PIXELS (logical_rect.width); +} + +/*! + Get layout height. + + @param *context [in] Context + @return Height +*/ +int +SDLPango_GetLayoutHeight( + SDLPango_Context *context) +{ + PangoRectangle logical_rect; + + pango_layout_get_extents (context->layout, NULL, &logical_rect); + + return PANGO_PIXELS (logical_rect.height); +} + +/*! + Set markup text to context. + Text must be utf-8. + Markup format is same as pango. + + @param *context [i/o] Context + @param *markup [in] Markup text + @param length [in] Text length. -1 means NULL-terminated text. +*/ +void +SDLPango_SetMarkup( + SDLPango_Context *context, + const char *markup, + int length) +{ + pango_layout_set_markup (context->layout, markup, length); + pango_layout_set_auto_dir (context->layout, TRUE); + pango_layout_set_alignment (context->layout, PANGO_ALIGN_LEFT); + pango_layout_set_font_description (context->layout, context->font_desc); +} + +void +SDLPango_SetText_GivenAlignment( + SDLPango_Context *context, + const char *text, + int length, + SDLPango_Alignment alignment) +{ + pango_layout_set_attributes(context->layout, NULL); + pango_layout_set_text (context->layout, text, length); + pango_layout_set_auto_dir (context->layout, TRUE); + pango_layout_set_alignment (context->layout, alignment); + pango_layout_set_font_description (context->layout, context->font_desc); +} + +/*! + Set plain text to context. + Text must be utf-8. + + @param *context [i/o] Context + @param *text [in] Plain text + @param length [in] Text length. -1 means NULL-terminated text. +*/ +void +SDLPango_SetText( + SDLPango_Context *context, + const char *text, + int length) +{ + SDLPango_SetText_GivenAlignment(context, text, length, SDLPANGO_ALIGN_LEFT); +} + +/*! + Set DPI to context. + + @param *context [i/o] Context + @param dpi_x [in] X dpi + @param dpi_y [in] Y dpi +*/ +void +SDLPango_SetDpi( + SDLPango_Context *context, + double dpi_x, double dpi_y) +{ + pango_ft2_font_map_set_resolution (PANGO_FT2_FONT_MAP (context->font_map), dpi_x, dpi_y); +} + +/*! + Set language to context. + + @param *context [i/o] Context + @param *language_tag [in] A RFC-3066 format language tag +*/ +void SDLCALL SDLPango_SetLanguage( + SDLPango_Context *context, + const char *language_tag) +{ + pango_context_set_language (context->context, pango_language_from_string (language_tag)); +} + +/*! + Set base direction to context. + + @param *context [i/o] Context + @param direction [in] Direction +*/ +void SDLCALL SDLPango_SetBaseDirection( + SDLPango_Context *context, + SDLPango_Direction direction) +{ + PangoDirection pango_dir; + + switch(direction) { + case SDLPANGO_DIRECTION_LTR: + pango_dir = PANGO_DIRECTION_LTR; + break; + case SDLPANGO_DIRECTION_RTL: + pango_dir = PANGO_DIRECTION_RTL; + break; + case SDLPANGO_DIRECTION_WEAK_LTR: + pango_dir = PANGO_DIRECTION_WEAK_LTR; + break; + case SDLPANGO_DIRECTION_WEAK_RTL: + pango_dir = PANGO_DIRECTION_WEAK_RTL; + break; + case SDLPANGO_DIRECTION_NEUTRAL: + pango_dir = PANGO_DIRECTION_NEUTRAL; + break; + default: + SDL_SetError("unknown direction value"); + return; + } + + pango_context_set_base_dir (context->context, pango_dir); +} + +/*! + Get font map from context. + + @param *context [in] Context + @return Font map +*/ +PangoFontMap* SDLCALL SDLPango_GetPangoFontMap( + SDLPango_Context *context) +{ + return context->font_map; +} + +/*! + Get font description from context. + + @param *context [in] Context + @return Font description +*/ +PangoFontDescription* SDLCALL SDLPango_GetPangoFontDescription( + SDLPango_Context *context) +{ + return context->font_desc; +} + +/*! + Get layout from context. + + @param *context [in] Context + @return Layout +*/ +PangoLayout* SDLCALL SDLPango_GetPangoLayout( + SDLPango_Context *context) +{ + return context->layout; +}