Page MenuHomePhabricator (Chris)

No OneTemporary

Authored By
Unknown
Size
95 KB
Referenced Files
None
Subscribers
None
diff --git a/.travis.yml b/.travis.yml.backup
similarity index 100%
rename from .travis.yml
rename to .travis.yml.backup
diff --git a/CMakeLists.txt b/CMakeLists.txt
index e4fbdf8..b78f1d2 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,182 +1,185 @@
Project (meandmyshadow)
CMake_Minimum_Required (VERSION 3.1)
Set (CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/")
Option (DEBUG_MODE "Compile the game with debug mode enabled" OFF)
Option (DISABLED_DEBUG_STUFF "Enable this you'll see a lot of annoying script debug messages which will lag the game." OFF)
#Find the required libraries.
Find_Package (SDL2 REQUIRED)
Find_Package (SDL2_image REQUIRED)
-Find_Package (SDL2_ttf REQUIRED)
+Find_Package (Freetype REQUIRED)
Find_Package (SDL2_mixer REQUIRED)
Find_Package (CURL REQUIRED)
Find_Package (LibArchive REQUIRED)
Find_Package (Lua REQUIRED)
if (NOT SDL2_FOUND)
message (FATAL_ERROR "SDL2 library could not be found!")
endif (NOT SDL2_FOUND)
if (NOT SDL2_IMAGE_FOUND)
message (FATAL_ERROR "SDL2_image library could not be found!")
endif (NOT SDL2_IMAGE_FOUND)
-if (NOT SDL2_TTF_FOUND)
- message (FATAL_ERROR "SDL2_ttf library could not be found!")
-endif (NOT SDL2_TTF_FOUND)
+if (NOT FREETYPE_FOUND)
+ message (FATAL_ERROR "Freetype library could not be found!")
+endif (NOT FREETYPE_FOUND)
if (NOT SDL2_MIXER_FOUND)
message (FATAL_ERROR "SDL2_mixer library could not be found!")
endif (NOT SDL2_MIXER_FOUND)
if (NOT CURL_FOUND)
message(FATAL_ERROR "CURL library could not be found!")
endif (NOT CURL_FOUND)
if (NOT LibArchive_FOUND)
message (FATAL_ERROR "LibArchive library could not be found!")
endif (NOT LibArchive_FOUND)
if (NOT LUA_FOUND)
message (FATAL_ERROR "Lua library could not be found!")
endif (NOT LUA_FOUND)
if (LUA_VERSION_STRING VERSION_LESS "5.2")
message (FATAL_ERROR "Lua version too old ${LUA_VERSION_STRING}, expected at least 5.2!")
endif ()
# check version from Globals.h
file(READ "${PROJECT_SOURCE_DIR}/src/Globals.h" GLOBALS_H)
string(REGEX MATCH "version[ ]*=[ ]*\"[^\"]*\"" MNMS_VERSION_STR ${GLOBALS_H})
string(REGEX REPLACE "^[^\"]*\"([^\"]*)\".*$" "\\1" MNMS_VERSION_STR ${MNMS_VERSION_STR})
message(STATUS "The version read from Globals.h is: ${MNMS_VERSION_STR}")
string(REGEX REPLACE "^V([0-9.]+).*$" "\\1" MNMS_VERSION_NUM ${MNMS_VERSION_STR})
set(MNMS_VERSION_NUM "${MNMS_VERSION_NUM}.0.0.0.0")
string(REGEX REPLACE "^([0-9]+)[.]([0-9]+)[.]([0-9]+)[.]([0-9]+).*$" "\\1,\\2,\\3,\\4" MNMS_VERSION_NUM ${MNMS_VERSION_NUM})
message(STATUS "which is: ${MNMS_VERSION_NUM}")
# check version from git
find_package(Git)
if(GIT_FOUND)
exec_program(${GIT_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR} ARGS "describe"
OUTPUT_VARIABLE MNMS_GIT_VERSION RETURN_VALUE GIT_RETURN_VALUE)
if(GIT_RETURN_VALUE STREQUAL "0")
set(MNMS_VERSION_STR "${MNMS_VERSION_STR} (${MNMS_GIT_VERSION})")
message(STATUS "The version read from git is: ${MNMS_GIT_VERSION}")
else()
# possibly there are no any tags
exec_program(${GIT_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR} ARGS "rev-parse --short HEAD"
OUTPUT_VARIABLE MNMS_GIT_VERSION RETURN_VALUE GIT_RETURN_VALUE)
if(GIT_RETURN_VALUE STREQUAL "0")
set(MNMS_VERSION_STR "${MNMS_VERSION_STR} (git ${MNMS_GIT_VERSION})")
message(STATUS "The version read from git is: ${MNMS_GIT_VERSION}")
endif()
endif()
endif()
# show version information on Windows
Set(WIN32_RESOURCES )
if(WIN32)
Configure_File (
"${PROJECT_SOURCE_DIR}/icons/windows-icon/res.rc.in"
"${PROJECT_BINARY_DIR}/res.rc"
)
Set(WIN32_RESOURCES ${PROJECT_BINARY_DIR}/res.rc)
Include_Directories(${PROJECT_SOURCE_DIR}/icons/windows-icon/)
SOURCE_GROUP("Source Files\\Resources" FILES ${WIN32_RESOURCES})
endif()
#Parse the configure file.
Configure_File (
"${PROJECT_SOURCE_DIR}/src/config.h.in"
"${PROJECT_BINARY_DIR}/config.h"
)
#Add some missing libraries to Windows.
if(WIN32)
include_directories(${PROJECT_SOURCE_DIR}/src/libs/dirent)
endif(WIN32)
#Disable some annoying warnings.
if(MSVC)
# warning C4996: '***': This function or variable may be unsafe
add_definitions(/wd4996)
else()
# Assume it's gcc or clang
# warning: '***' overrides a member function but is not marked 'override'
add_definitions(-Wno-inconsistent-missing-override)
endif()
#Define some debug stuff.
if(DEBUG_MODE)
add_definitions(-DDEBUG)
add_definitions(-D_DEBUG)
endif(DEBUG_MODE)
if(DISABLED_DEBUG_STUFF)
add_definitions(-DDISABLED_DEBUG_STUFF)
endif(DISABLED_DEBUG_STUFF)
#Add the include directories of the (found) libraries.
Include_Directories(
${PROJECT_BINARY_DIR}
${SDL2_INCLUDE_DIR}
${SDL2_IMAGE_INCLUDE_DIR}
- ${SDL2_TTF_INCLUDE_DIR}
+ ${FREETYPE_INCLUDE_DIRS}
${SDL2_MIXER_INCLUDE_DIR}
${CURL_INCLUDE_DIR}
${LibArchive_INCLUDE_DIR}
${LUA_INCLUDE_DIR}
${PROJECT_SOURCE_DIR}/src/libs
+ ${PROJECT_SOURCE_DIR}/src/libs/SDL2_ttf
)
#Set the output path and the source path.
Set (EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR})
Set (SRC_DIR ${PROJECT_SOURCE_DIR}/src)
#List the source files.
File (GLOB SOURCES ${SRC_DIR}/*.cpp)
File (GLOB TINYGETTEXT ${SRC_DIR}/libs/tinygettext/*.cpp)
File (GLOB FINDLOCALE ${SRC_DIR}/libs/findlocale/*.cpp)
+File (GLOB SDL2TTF ${SRC_DIR}/libs/SDL2_ttf/*.c)
#Always use SDL_iconv in tinygettext
add_definitions(-DHAVE_SDL)
SOURCE_GROUP("Source Files\\tinygettext" FILES ${TINYGETTEXT})
SOURCE_GROUP("Source Files\\findlocale" FILES ${FINDLOCALE})
+SOURCE_GROUP("Source Files\\SDL2_ttf" FILES ${SDL2TTF})
-Add_Executable (meandmyshadow ${SOURCES} ${TINYGETTEXT} ${FINDLOCALE} ${WIN32_RESOURCES})
+Add_Executable (meandmyshadow ${SOURCES} ${TINYGETTEXT} ${FINDLOCALE} ${WIN32_RESOURCES} ${SDL2TTF})
set_property(TARGET meandmyshadow PROPERTY CXX_STANDARD 11)
Target_Link_Libraries (
meandmyshadow
${SDL2_LIBRARY}
${SDL2_IMAGE_LIBRARY}
- ${SDL2_TTF_LIBRARY}
+ ${FREETYPE_LIBRARIES}
${SDL2_MIXER_LIBRARY}
${SDL2MAIN_LIBRARY}
${CURL_LIBRARY}
${LibArchive_LIBRARY}
${LUA_LIBRARIES}
)
#Path options
Set (BINDIR "bin" CACHE STRING "Where to install binaries")
Set (DATAROOTDIR "${CMAKE_INSTALL_PREFIX}/share" CACHE STRING "Sets the root of data directories to a non-default location")
Set (ICONDIR "${DATAROOTDIR}/icons" CACHE STRING "Sets the icon directory for desktop entry to a non-default location.")
Set (DESKTOPDIR "${DATAROOTDIR}/applications" CACHE STRING "Sets the desktop file directory for desktop entry to a non-default location.")
#Install locations
Install (DIRECTORY ${PROJECT_SOURCE_DIR}/data DESTINATION ${DATAROOTDIR}/meandmyshadow/)
Install (FILES AUTHORS DESTINATION ${DATAROOTDIR}/meandmyshadow/)
Install (TARGETS meandmyshadow RUNTIME DESTINATION ${BINDIR})
if ("${CMAKE_SYSTEM_NAME}" MATCHES "Linux")
Install (FILES meandmyshadow.desktop DESTINATION ${DESKTOPDIR})
Install (FILES icons/16x16/meandmyshadow.png DESTINATION ${ICONDIR}/hicolor/16x16/apps/)
Install (FILES icons/32x32/meandmyshadow.png DESTINATION ${ICONDIR}/hicolor/32x32/apps/)
Install (FILES icons/48x48/meandmyshadow.png DESTINATION ${ICONDIR}/hicolor/48x48/apps/)
Install (FILES icons/64x64/meandmyshadow.png DESTINATION ${ICONDIR}/hicolor/64x64/apps/)
endif ("${CMAKE_SYSTEM_NAME}" MATCHES "Linux")
diff --git a/appveyor.yml b/appveyor.yml.backup
similarity index 100%
rename from appveyor.yml
rename to appveyor.yml.backup
diff --git a/src/libs/SDL2_ttf/CHANGES.txt b/src/libs/SDL2_ttf/CHANGES.txt
new file mode 100644
index 0000000..d490554
--- /dev/null
+++ b/src/libs/SDL2_ttf/CHANGES.txt
@@ -0,0 +1,37 @@
+2.0.15:
+Sam Lantinga - Sun Sep 10 00:18:45 PDT 2017
+ * Text rendering functions now use the alpha component of the text colors
+Sam Lantinga - Sat Sep 9 22:21:55 PDT 2017
+ * Added support for characters greater than 0xFFFF (e.g. emoji) in the UTF-8 APIs
+
+2.0.14:
+Ryan Gordon - Fri Jan 29 12:53:29 PST 2016
+ * Deprecated TTF_GetFontKerningSize() which takes font glyph indices and added TTF_GetFontKerningSizeGlyphs() which takes characters
+
+2.0.13:
+Sylvain - Sat Jun 28 11:42:42 2014
+ * Fixed bug rendering text starting with a glyph with negative starting offset
+beuc - Sun Jun 15 18:27:28 2014
+ * Fixed regression loading non-scalable fonts
+Sam Lantinga - Sun Jun 15 18:21:04 PDT 2014
+ * TTF_GetFontKerningSize() gets kerning between two characters, not two glyph indices
+David Ludwig - Sun Apr 13 22:28:26 2014
+ * Added support for building for Windows RT and Windows Phone
+
+2.0.12:
+Sam Lantinga - Sat Jun 1 19:11:26 PDT 2013
+ * Updated for SDL 2.0 release
+
+2.0.11:
+Sam Lantinga - Sat Dec 31 10:49:42 EST 2011
+ * SDL_ttf is now under the zlib license
+Peter Kosyh - Mon Feb 28 14:57:03 PST 2011
+ * Improved font glyph caching for non-latin languages
+Erik Snoek - Wed Jan 12 09:10:15 PST 2011
+ * Added API to get kerning info: TTF_GetFontKerningSize()
+Sam Lantinga - Mon Jan 10 10:58:34 2011 -0800
+ * Added Android.mk to build on the Android platform
+
+2.0.10:
+Adam Strzelecki - Wed Oct 21 21:02:37 PDT 2009
+ * Find the Unicode or symbol character map if it's available in the font
diff --git a/src/libs/SDL2_ttf/COPYING.txt b/src/libs/SDL2_ttf/COPYING.txt
new file mode 100644
index 0000000..4a4e814
--- /dev/null
+++ b/src/libs/SDL2_ttf/COPYING.txt
@@ -0,0 +1,20 @@
+/*
+ SDL_ttf: A companion library to SDL for working with TrueType (tm) fonts
+ Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
diff --git a/src/libs/SDL2_ttf/README.txt b/src/libs/SDL2_ttf/README.txt
new file mode 100644
index 0000000..b75b3d7
--- /dev/null
+++ b/src/libs/SDL2_ttf/README.txt
@@ -0,0 +1,25 @@
+
+This library is a wrapper around the excellent FreeType 2.0 library,
+available at:
+ http://www.freetype.org/
+
+This library allows you to use TrueType fonts to render text in SDL
+applications.
+
+To make the library, first install the FreeType library, then type
+'./configure' then 'make' to build the SDL truetype library and the
+showfont and glfont example applications.
+
+Be careful when including fonts with your application, as many of them
+are copyrighted. The Microsoft fonts, for example, are not freely
+redistributable and even the free "web" fonts they provide are only
+redistributable in their special executable installer form (May 1998).
+There are plenty of freeware and shareware fonts available on the Internet
+though, and may suit your purposes.
+
+This library is under the zlib license, see the file "COPYING.txt" for details.
+
+Portions of this software are copyright © 2013 The FreeType Project (www.freetype.org). All rights reserved.
+
+Enjoy!
+ -Sam Lantinga <slouken@libsdl.org> (6/20/2001)
diff --git a/src/libs/SDL2_ttf/SDL_ttf.c b/src/libs/SDL2_ttf/SDL_ttf.c
new file mode 100644
index 0000000..681d966
--- /dev/null
+++ b/src/libs/SDL2_ttf/SDL_ttf.c
@@ -0,0 +1,2319 @@
+/*
+ SDL_ttf: A companion library to SDL for working with TrueType (tm) fonts
+ Copyright (C) 2001-2018 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+#include FT_OUTLINE_H
+#include FT_STROKER_H
+#include FT_GLYPH_H
+#include FT_TRUETYPE_IDS_H
+
+#include "SDL.h"
+#include "SDL_endian.h"
+#include "SDL_ttf.h"
+
+/* FIXME: Right now we assume the gray-scale renderer Freetype is using
+ supports 256 shades of gray, but we should instead key off of num_grays
+ in the result FT_Bitmap after the FT_Render_Glyph() call. */
+#define NUM_GRAYS 256
+
+/* Handy routines for converting from fixed point */
+#define FT_FLOOR(X) ((X & -64) / 64)
+#define FT_CEIL(X) (((X + 63) & -64) / 64)
+
+#define CACHED_METRICS 0x10
+#define CACHED_BITMAP 0x01
+#define CACHED_PIXMAP 0x02
+
+/* Cached glyph information */
+typedef struct cached_glyph {
+ int stored;
+ FT_UInt index;
+ FT_Bitmap bitmap;
+ FT_Bitmap pixmap;
+ int minx;
+ int maxx;
+ int miny;
+ int maxy;
+ int yoffset;
+ int advance;
+ Uint32 cached;
+} c_glyph;
+
+/* The structure used to hold internal font information */
+struct _TTF_Font {
+ /* Freetype2 maintains all sorts of useful info itself */
+ FT_Face face;
+
+ /* We'll cache these ourselves */
+ int height;
+ int ascent;
+ int descent;
+ int lineskip;
+
+ /* The font style */
+ int face_style;
+ int style;
+ int outline;
+
+ /* Whether kerning is desired */
+ int kerning;
+
+ /* Extra width in glyph bounds for text styles */
+ int glyph_overhang;
+ float glyph_italics;
+
+ /* Information in the font for underlining */
+ int underline_offset;
+ int underline_height;
+
+ /* Cache for style-transformed glyphs */
+ c_glyph *current;
+ c_glyph cache[257]; /* 257 is a prime */
+
+ /* We are responsible for closing the font stream */
+ SDL_RWops *src;
+ int freesrc;
+ FT_Open_Args args;
+
+ /* For non-scalable formats, we must remember which font index size */
+ int font_size_family;
+
+ /* really just flags passed into FT_Load_Glyph */
+ int hinting;
+};
+
+/* Handle a style only if the font does not already handle it */
+#define TTF_HANDLE_STYLE_BOLD(font) (((font)->style & TTF_STYLE_BOLD) && \
+ !((font)->face_style & TTF_STYLE_BOLD))
+#define TTF_HANDLE_STYLE_ITALIC(font) (((font)->style & TTF_STYLE_ITALIC) && \
+ !((font)->face_style & TTF_STYLE_ITALIC))
+#define TTF_HANDLE_STYLE_UNDERLINE(font) ((font)->style & TTF_STYLE_UNDERLINE)
+#define TTF_HANDLE_STYLE_STRIKETHROUGH(font) ((font)->style & TTF_STYLE_STRIKETHROUGH)
+
+/* Font styles that does not impact glyph drawing */
+#define TTF_STYLE_NO_GLYPH_CHANGE (TTF_STYLE_UNDERLINE | TTF_STYLE_STRIKETHROUGH)
+
+/* The FreeType font engine/library */
+static FT_Library library;
+static int TTF_initialized = 0;
+static int TTF_byteswapped = 0;
+
+#define TTF_CHECKPOINTER(p, errval) \
+ if (!TTF_initialized) { \
+ TTF_SetError("Library not initialized"); \
+ return errval; \
+ } \
+ if (!p) { \
+ TTF_SetError("Passed a NULL pointer"); \
+ return errval; \
+ }
+
+/* Gets the top row of the underline. The outline
+ is taken into account.
+*/
+static int TTF_underline_top_row(TTF_Font *font)
+{
+ /* With outline, the underline_offset is underline_offset+outline. */
+ /* So, we don't have to remove the top part of the outline height. */
+ return font->ascent - font->underline_offset - 1;
+}
+
+/* Gets the top row of the underline. for a given glyph. The outline
+ is taken into account.
+ Need to update row according to height difference between font and glyph:
+ font_value - font->ascent + glyph->maxy
+*/
+static int TTF_Glyph_underline_top_row(TTF_Font *font, c_glyph *glyph)
+{
+ return glyph->maxy - font->underline_offset - 1;
+}
+
+/* Gets the bottom row of the underline. The outline
+ is taken into account.
+*/
+static int TTF_underline_bottom_row(TTF_Font *font)
+{
+ int row = TTF_underline_top_row(font) + font->underline_height;
+ if (font->outline > 0) {
+ /* Add underline_offset outline offset and */
+ /* the bottom part of the outline. */
+ row += font->outline * 2;
+ }
+ return row;
+}
+
+/* Gets the bottom row of the underline. for a given glyph. The outline
+ is taken into account.
+ Need to update row according to height difference between font and glyph:
+ font_value - font->ascent + glyph->maxy
+*/
+static int TTF_Glyph_underline_bottom_row(TTF_Font *font, c_glyph *glyph)
+{
+ return TTF_underline_bottom_row(font) - font->ascent + glyph->maxy;
+}
+
+/* Gets the top row of the strikethrough. The outline
+ is taken into account.
+*/
+static int TTF_strikethrough_top_row(TTF_Font *font)
+{
+ /* With outline, the first text row is 'outline'. */
+ /* So, we don't have to remove the top part of the outline height. */
+ return font->height / 2;
+}
+
+/* Gets the top row of the strikethrough for a given glyph. The outline
+ is taken into account.
+ Need to update row according to height difference between font and glyph:
+ font_value - font->ascent + glyph->maxy
+*/
+static int TTF_Glyph_strikethrough_top_row(TTF_Font *font, c_glyph *glyph)
+{
+ return TTF_strikethrough_top_row(font) - font->ascent + glyph->maxy;
+}
+
+static void TTF_initLineMectrics(const TTF_Font *font, const SDL_Surface *textbuf, const int row, Uint8 **pdst, int *pheight)
+{
+ Uint8 *dst;
+ int height;
+
+ dst = (Uint8 *)textbuf->pixels;
+ if (row > 0) {
+ dst += row * textbuf->pitch;
+ }
+
+ height = font->underline_height;
+ /* Take outline into account */
+ if (font->outline > 0) {
+ height += font->outline * 2;
+ }
+ *pdst = dst;
+ *pheight = height;
+}
+
+/* Draw a solid line of underline_height (+ optional outline)
+ at the given row. The row value must take the
+ outline into account.
+*/
+static void TTF_drawLine_Solid(const TTF_Font *font, const SDL_Surface *textbuf, const int row)
+{
+ int line;
+ Uint8 *dst_check = (Uint8*)textbuf->pixels + textbuf->pitch * textbuf->h;
+ Uint8 *dst;
+ int height;
+
+ TTF_initLineMectrics(font, textbuf, row, &dst, &height);
+
+ /* Draw line */
+ for (line=height; line>0 && dst < dst_check; --line) {
+ /* 1 because 0 is the bg color */
+ SDL_memset(dst, 1, textbuf->w);
+ dst += textbuf->pitch;
+ }
+}
+
+/* Draw a shaded line of underline_height (+ optional outline)
+ at the given row. The row value must take the
+ outline into account.
+*/
+static void TTF_drawLine_Shaded(const TTF_Font *font, const SDL_Surface *textbuf, const int row)
+{
+ int line;
+ Uint8 *dst_check = (Uint8*)textbuf->pixels + textbuf->pitch * textbuf->h;
+ Uint8 *dst;
+ int height;
+
+ TTF_initLineMectrics(font, textbuf, row, &dst, &height);
+
+ /* Draw line */
+ for (line=height; line>0 && dst < dst_check; --line) {
+ SDL_memset(dst, NUM_GRAYS - 1, textbuf->w);
+ dst += textbuf->pitch;
+ }
+}
+
+/* Draw a blended line of underline_height (+ optional outline)
+ at the given row. The row value must take the
+ outline into account.
+*/
+static void TTF_drawLine_Blended(const TTF_Font *font, const SDL_Surface *textbuf, const int row, const Uint32 color)
+{
+ int line;
+ Uint32 *dst_check = (Uint32*)textbuf->pixels + textbuf->pitch/4 * textbuf->h;
+ Uint8 *dst8; /* destination, byte version */
+ Uint32 *dst;
+ int height;
+ int col;
+ Uint32 pixel = color | 0xFF000000; /* Amask */
+
+ TTF_initLineMectrics(font, textbuf, row, &dst8, &height);
+ dst = (Uint32 *) dst8;
+
+ /* Draw line */
+ for (line=height; line>0 && dst < dst_check; --line) {
+ for (col=0; col < textbuf->w; ++col) {
+ dst[col] = pixel;
+ }
+ dst += textbuf->pitch/4;
+ }
+}
+
+/* rcg06192001 get linked library's version. */
+const SDL_version *TTF_Linked_Version(void)
+{
+ static SDL_version linked_version;
+ SDL_TTF_VERSION(&linked_version);
+ return(&linked_version);
+}
+
+/* This function tells the library whether UNICODE text is generally
+ byteswapped. A UNICODE BOM character at the beginning of a string
+ will override this setting for that string.
+ */
+void TTF_ByteSwappedUNICODE(int swapped)
+{
+ TTF_byteswapped = swapped;
+}
+
+static void TTF_SetFTError(const char *msg, FT_Error error)
+{
+#ifdef USE_FREETYPE_ERRORS
+#undef FTERRORS_H
+#define FT_ERRORDEF(e, v, s) { e, s },
+ static const struct
+ {
+ int err_code;
+ const char* err_msg;
+ } ft_errors[] = {
+#include <freetype/fterrors.h>
+ };
+ int i;
+ const char *err_msg;
+ char buffer[1024];
+
+ err_msg = NULL;
+ for (i=0; i<((sizeof ft_errors)/(sizeof ft_errors[0])); ++i) {
+ if (error == ft_errors[i].err_code) {
+ err_msg = ft_errors[i].err_msg;
+ break;
+ }
+ }
+ if (!err_msg) {
+ err_msg = "unknown FreeType error";
+ }
+ TTF_SetError("%s: %s", msg, err_msg);
+#else
+ TTF_SetError("%s", msg);
+#endif /* USE_FREETYPE_ERRORS */
+}
+
+int TTF_Init(void)
+{
+ int status = 0;
+
+ if (!TTF_initialized) {
+ FT_Error error = FT_Init_FreeType(&library);
+ if (error) {
+ TTF_SetFTError("Couldn't init FreeType engine", error);
+ status = -1;
+ }
+ }
+ if (status == 0) {
+ ++TTF_initialized;
+ }
+ return status;
+}
+
+static unsigned long RWread(
+ FT_Stream stream,
+ unsigned long offset,
+ unsigned char* buffer,
+ unsigned long count
+)
+{
+ SDL_RWops *src;
+
+ src = (SDL_RWops *)stream->descriptor.pointer;
+ SDL_RWseek(src, (int)offset, RW_SEEK_SET);
+ if (count == 0) {
+ return 0;
+ }
+ return (unsigned long)SDL_RWread(src, buffer, 1, (int)count);
+}
+
+TTF_Font* TTF_OpenFontIndexRW(SDL_RWops *src, int freesrc, int ptsize, long index)
+{
+ TTF_Font* font;
+ FT_Error error;
+ FT_Face face;
+ FT_Fixed scale;
+ FT_Stream stream;
+ FT_CharMap found;
+ Sint64 position;
+ int i;
+
+ if (!TTF_initialized) {
+ TTF_SetError("Library not initialized");
+ if (src && freesrc) {
+ SDL_RWclose(src);
+ }
+ return NULL;
+ }
+
+ if (!src) {
+ TTF_SetError("Passed a NULL font source");
+ return NULL;
+ }
+
+ /* Check to make sure we can seek in this stream */
+ position = SDL_RWtell(src);
+ if (position < 0) {
+ TTF_SetError("Can't seek in stream");
+ if (freesrc) {
+ SDL_RWclose(src);
+ }
+ return NULL;
+ }
+
+ font = (TTF_Font*)SDL_malloc(sizeof *font);
+ if (font == NULL) {
+ TTF_SetError("Out of memory");
+ if (freesrc) {
+ SDL_RWclose(src);
+ }
+ return NULL;
+ }
+ SDL_memset(font, 0, sizeof(*font));
+
+ font->src = src;
+ font->freesrc = freesrc;
+
+ stream = (FT_Stream)SDL_malloc(sizeof(*stream));
+ if (stream == NULL) {
+ TTF_SetError("Out of memory");
+ TTF_CloseFont(font);
+ return NULL;
+ }
+ SDL_memset(stream, 0, sizeof(*stream));
+
+ stream->read = RWread;
+ stream->descriptor.pointer = src;
+ stream->pos = (unsigned long)position;
+ stream->size = (unsigned long)(SDL_RWsize(src) - position);
+
+ font->args.flags = FT_OPEN_STREAM;
+ font->args.stream = stream;
+
+ error = FT_Open_Face(library, &font->args, index, &font->face);
+ if (error) {
+ TTF_SetFTError("Couldn't load font file", error);
+ TTF_CloseFont(font);
+ return NULL;
+ }
+ face = font->face;
+
+ /* Set charmap for loaded font */
+ found = 0;
+#if 0 /* Font debug code */
+ for (i = 0; i < face->num_charmaps; i++) {
+ FT_CharMap charmap = face->charmaps[i];
+ printf("Found charmap: platform id %d, encoding id %d\n", charmap->platform_id, charmap->encoding_id);
+ }
+#endif
+ if (!found) {
+ for (i = 0; i < face->num_charmaps; i++) {
+ FT_CharMap charmap = face->charmaps[i];
+ if (charmap->platform_id == 3 && charmap->encoding_id == 10) { /* UCS-4 Unicode */
+ found = charmap;
+ break;
+ }
+ }
+ }
+ if (!found) {
+ for (i = 0; i < face->num_charmaps; i++) {
+ FT_CharMap charmap = face->charmaps[i];
+ if ((charmap->platform_id == 3 && charmap->encoding_id == 1) /* Windows Unicode */
+ || (charmap->platform_id == 3 && charmap->encoding_id == 0) /* Windows Symbol */
+ || (charmap->platform_id == 2 && charmap->encoding_id == 1) /* ISO Unicode */
+ || (charmap->platform_id == 0)) { /* Apple Unicode */
+ found = charmap;
+ break;
+ }
+ }
+ }
+ if (found) {
+ /* If this fails, continue using the default charmap */
+ FT_Set_Charmap(face, found);
+ }
+
+ /* Make sure that our font face is scalable (global metrics) */
+ if (FT_IS_SCALABLE(face)) {
+ /* Set the character size and use default DPI (72) */
+ error = FT_Set_Char_Size(font->face, 0, ptsize * 64, 0, 0);
+ if (error) {
+ TTF_SetFTError("Couldn't set font size", error);
+ TTF_CloseFont(font);
+ return NULL;
+ }
+
+ /* Get the scalable font metrics for this font */
+ scale = face->size->metrics.y_scale;
+ font->ascent = FT_CEIL(FT_MulFix(face->ascender, scale));
+ font->descent = FT_CEIL(FT_MulFix(face->descender, scale));
+ font->height = font->ascent - font->descent + /* baseline */ 1;
+ font->lineskip = FT_CEIL(FT_MulFix(face->height, scale));
+ font->underline_offset = FT_FLOOR(FT_MulFix(face->underline_position, scale));
+ font->underline_height = FT_FLOOR(FT_MulFix(face->underline_thickness, scale));
+
+ } else {
+ /* Non-scalable font case. ptsize determines which family
+ * or series of fonts to grab from the non-scalable format.
+ * It is not the point size of the font.
+ * */
+ if (ptsize >= font->face->num_fixed_sizes)
+ ptsize = font->face->num_fixed_sizes - 1;
+ font->font_size_family = ptsize;
+ error = FT_Set_Pixel_Sizes(face,
+ face->available_sizes[ptsize].width,
+ face->available_sizes[ptsize].height);
+
+ /* With non-scalale fonts, Freetype2 likes to fill many of the
+ * font metrics with the value of 0. The size of the
+ * non-scalable fonts must be determined differently
+ * or sometimes cannot be determined.
+ * */
+ font->ascent = face->available_sizes[ptsize].height;
+ font->descent = 0;
+ font->height = face->available_sizes[ptsize].height;
+ font->lineskip = FT_CEIL(font->ascent);
+ font->underline_offset = FT_FLOOR(face->underline_position);
+ font->underline_height = FT_FLOOR(face->underline_thickness);
+ }
+
+ if (font->underline_height < 1) {
+ font->underline_height = 1;
+ }
+
+#ifdef DEBUG_FONTS
+ printf("Font metrics:\n");
+ printf("\tascent = %d, descent = %d\n",
+ font->ascent, font->descent);
+ printf("\theight = %d, lineskip = %d\n",
+ font->height, font->lineskip);
+ printf("\tunderline_offset = %d, underline_height = %d\n",
+ font->underline_offset, font->underline_height);
+ printf("\tunderline_top_row = %d, strikethrough_top_row = %d\n",
+ TTF_underline_top_row(font), TTF_strikethrough_top_row(font));
+#endif
+
+ /* Initialize the font face style */
+ font->face_style = TTF_STYLE_NORMAL;
+ if (font->face->style_flags & FT_STYLE_FLAG_BOLD) {
+ font->face_style |= TTF_STYLE_BOLD;
+ }
+ if (font->face->style_flags & FT_STYLE_FLAG_ITALIC) {
+ font->face_style |= TTF_STYLE_ITALIC;
+ }
+
+ /* Set the default font style */
+ font->style = font->face_style;
+ font->outline = 0;
+ font->kerning = 1;
+ font->glyph_overhang = face->size->metrics.y_ppem / 10;
+ /* x offset = cos(((90.0-12)/360)*2*M_PI), or 12 degree angle */
+ font->glyph_italics = 0.207f;
+ font->glyph_italics *= font->height;
+
+ return font;
+}
+
+TTF_Font* TTF_OpenFontRW(SDL_RWops *src, int freesrc, int ptsize)
+{
+ return TTF_OpenFontIndexRW(src, freesrc, ptsize, 0);
+}
+
+TTF_Font* TTF_OpenFontIndex(const char *file, int ptsize, long index)
+{
+ SDL_RWops *rw = SDL_RWFromFile(file, "rb");
+ if (rw == NULL) {
+ return NULL;
+ }
+ return TTF_OpenFontIndexRW(rw, 1, ptsize, index);
+}
+
+TTF_Font* TTF_OpenFont(const char *file, int ptsize)
+{
+ return TTF_OpenFontIndex(file, ptsize, 0);
+}
+
+static void Flush_Glyph(c_glyph* glyph)
+{
+ glyph->stored = 0;
+ glyph->index = 0;
+ if (glyph->bitmap.buffer) {
+ SDL_free(glyph->bitmap.buffer);
+ glyph->bitmap.buffer = 0;
+ }
+ if (glyph->pixmap.buffer) {
+ SDL_free(glyph->pixmap.buffer);
+ glyph->pixmap.buffer = 0;
+ }
+ glyph->cached = 0;
+}
+
+static void Flush_Cache(TTF_Font* font)
+{
+ int i;
+ int size = sizeof(font->cache) / sizeof(font->cache[0]);
+
+ for (i = 0; i < size; ++i) {
+ if (font->cache[i].cached) {
+ Flush_Glyph(&font->cache[i]);
+ }
+
+ }
+}
+
+static FT_Error Load_Glyph(TTF_Font* font, Uint32 ch, c_glyph* cached, int want)
+{
+ FT_Face face;
+ FT_Error error;
+ FT_GlyphSlot glyph;
+ FT_Glyph_Metrics* metrics;
+ FT_Outline* outline;
+
+ if (!font || !font->face) {
+ return FT_Err_Invalid_Handle;
+ }
+
+ face = font->face;
+
+ /* Load the glyph */
+ if (!cached->index) {
+ cached->index = FT_Get_Char_Index(face, ch);
+ }
+ error = FT_Load_Glyph(face, cached->index, FT_LOAD_DEFAULT | font->hinting);
+ if (error) {
+ return error;
+ }
+
+ /* Get our glyph shortcuts */
+ glyph = face->glyph;
+ metrics = &glyph->metrics;
+ outline = &glyph->outline;
+
+ /* Get the glyph metrics if desired */
+ if ((want & CACHED_METRICS) && !(cached->stored & CACHED_METRICS)) {
+ if (FT_IS_SCALABLE(face)) {
+ /* Get the bounding box */
+ cached->minx = FT_FLOOR(metrics->horiBearingX);
+ cached->maxx = FT_CEIL(metrics->horiBearingX + metrics->width);
+ cached->maxy = FT_FLOOR(metrics->horiBearingY);
+ cached->miny = cached->maxy - FT_CEIL(metrics->height);
+ cached->yoffset = font->ascent - cached->maxy;
+ cached->advance = FT_CEIL(metrics->horiAdvance);
+ } else {
+ /* Get the bounding box for non-scalable format.
+ * Again, freetype2 fills in many of the font metrics
+ * with the value of 0, so some of the values we
+ * need must be calculated differently with certain
+ * assumptions about non-scalable formats.
+ * */
+ cached->minx = FT_FLOOR(metrics->horiBearingX);
+ cached->maxx = FT_CEIL(metrics->horiBearingX + metrics->width);
+ cached->maxy = FT_FLOOR(metrics->horiBearingY);
+ cached->miny = cached->maxy - FT_CEIL(face->available_sizes[font->font_size_family].height);
+ cached->yoffset = 0;
+ cached->advance = FT_CEIL(metrics->horiAdvance);
+ }
+
+ /* Adjust for bold and italic text */
+ if (TTF_HANDLE_STYLE_BOLD(font)) {
+ cached->maxx += font->glyph_overhang;
+ }
+ if (TTF_HANDLE_STYLE_ITALIC(font)) {
+ cached->maxx += (int)SDL_ceil(font->glyph_italics);
+ }
+ cached->stored |= CACHED_METRICS;
+ }
+
+ if (((want & CACHED_BITMAP) && !(cached->stored & CACHED_BITMAP)) ||
+ ((want & CACHED_PIXMAP) && !(cached->stored & CACHED_PIXMAP))) {
+ int mono = (want & CACHED_BITMAP);
+ int i;
+ FT_Bitmap* src;
+ FT_Bitmap* dst;
+ FT_Glyph bitmap_glyph = NULL;
+
+ /* Handle the italic style */
+ if (TTF_HANDLE_STYLE_ITALIC(font)) {
+ FT_Matrix shear;
+
+ shear.xx = 1 << 16;
+ shear.xy = (int) (font->glyph_italics * (1 << 16)) / font->height;
+ shear.yx = 0;
+ shear.yy = 1 << 16;
+
+ FT_Outline_Transform(outline, &shear);
+ }
+
+ /* Render as outline */
+ if ((font->outline > 0) && glyph->format != FT_GLYPH_FORMAT_BITMAP) {
+ FT_Stroker stroker;
+ FT_Get_Glyph(glyph, &bitmap_glyph);
+ error = FT_Stroker_New(library, &stroker);
+ if (error) {
+ return error;
+ }
+ FT_Stroker_Set(stroker, font->outline * 64, FT_STROKER_LINECAP_ROUND, FT_STROKER_LINEJOIN_ROUND, 0);
+ FT_Glyph_Stroke(&bitmap_glyph, stroker, 1 /* delete the original glyph */);
+ FT_Stroker_Done(stroker);
+ /* Render the glyph */
+ error = FT_Glyph_To_Bitmap(&bitmap_glyph, mono ? ft_render_mode_mono : ft_render_mode_normal, 0, 1);
+ if (error) {
+ FT_Done_Glyph(bitmap_glyph);
+ return error;
+ }
+ src = &((FT_BitmapGlyph)bitmap_glyph)->bitmap;
+ } else {
+ /* Render the glyph */
+ error = FT_Render_Glyph(glyph, mono ? ft_render_mode_mono : ft_render_mode_normal);
+ if (error) {
+ return error;
+ }
+ src = &glyph->bitmap;
+ }
+ /* Copy over information to cache */
+ if (mono) {
+ dst = &cached->bitmap;
+ } else {
+ dst = &cached->pixmap;
+ }
+ SDL_memcpy(dst, src, sizeof(*dst));
+
+ /* FT_Render_Glyph() and .fon fonts always generate a
+ * two-color (black and white) glyphslot surface, even
+ * when rendered in ft_render_mode_normal. */
+ /* FT_IS_SCALABLE() means that the font is in outline format,
+ * but does not imply that outline is rendered as 8-bit
+ * grayscale, because embedded bitmap/graymap is preferred
+ * (see FT_LOAD_DEFAULT section of FreeType2 API Reference).
+ * FT_Render_Glyph() canreturn two-color bitmap or 4/16/256-
+ * color graymap according to the format of embedded bitmap/
+ * graymap. */
+ if (src->pixel_mode == FT_PIXEL_MODE_MONO) {
+ dst->pitch *= 8;
+ } else if (src->pixel_mode == FT_PIXEL_MODE_GRAY2) {
+ dst->pitch *= 4;
+ } else if (src->pixel_mode == FT_PIXEL_MODE_GRAY4) {
+ dst->pitch *= 2;
+ }
+
+ /* Adjust for bold and italic text */
+ if (TTF_HANDLE_STYLE_BOLD(font)) {
+ int bump = font->glyph_overhang;
+ dst->pitch += bump;
+ dst->width += bump;
+ }
+ if (TTF_HANDLE_STYLE_ITALIC(font)) {
+ int bump = (int)SDL_ceil(font->glyph_italics);
+ dst->pitch += bump;
+ dst->width += bump;
+ }
+
+ if (dst->rows != 0) {
+ dst->buffer = (unsigned char *)SDL_malloc(dst->pitch * dst->rows);
+ if (!dst->buffer) {
+ return FT_Err_Out_Of_Memory;
+ }
+ SDL_memset(dst->buffer, 0, dst->pitch * dst->rows);
+
+ for (i = 0; i < src->rows; i++) {
+ int soffset = i * src->pitch;
+ int doffset = i * dst->pitch;
+ if (mono) {
+ unsigned char *srcp = src->buffer + soffset;
+ unsigned char *dstp = dst->buffer + doffset;
+ int j;
+ if (src->pixel_mode == FT_PIXEL_MODE_MONO) {
+ for (j = 0; j < src->width; j += 8) {
+ unsigned char c = *srcp++;
+ *dstp++ = (c&0x80) >> 7;
+ c <<= 1;
+ *dstp++ = (c&0x80) >> 7;
+ c <<= 1;
+ *dstp++ = (c&0x80) >> 7;
+ c <<= 1;
+ *dstp++ = (c&0x80) >> 7;
+ c <<= 1;
+ *dstp++ = (c&0x80) >> 7;
+ c <<= 1;
+ *dstp++ = (c&0x80) >> 7;
+ c <<= 1;
+ *dstp++ = (c&0x80) >> 7;
+ c <<= 1;
+ *dstp++ = (c&0x80) >> 7;
+ }
+ } else if (src->pixel_mode == FT_PIXEL_MODE_GRAY2) {
+ for (j = 0; j < src->width; j += 4) {
+ unsigned char c = *srcp++;
+ *dstp++ = (((c&0xA0) >> 6) >= 0x2) ? 1 : 0;
+ c <<= 2;
+ *dstp++ = (((c&0xA0) >> 6) >= 0x2) ? 1 : 0;
+ c <<= 2;
+ *dstp++ = (((c&0xA0) >> 6) >= 0x2) ? 1 : 0;
+ c <<= 2;
+ *dstp++ = (((c&0xA0) >> 6) >= 0x2) ? 1 : 0;
+ }
+ } else if (src->pixel_mode == FT_PIXEL_MODE_GRAY4) {
+ for (j = 0; j < src->width; j += 2) {
+ unsigned char c = *srcp++;
+ *dstp++ = (((c&0xF0) >> 4) >= 0x8) ? 1 : 0;
+ c <<= 4;
+ *dstp++ = (((c&0xF0) >> 4) >= 0x8) ? 1 : 0;
+ }
+ } else {
+ for (j = 0; j < src->width; j++) {
+ unsigned char c = *srcp++;
+ *dstp++ = (c >= 0x80) ? 1 : 0;
+ }
+ }
+ } else if (src->pixel_mode == FT_PIXEL_MODE_MONO) {
+ /* This special case wouldn't
+ * be here if the FT_Render_Glyph()
+ * function wasn't buggy when it tried
+ * to render a .fon font with 256
+ * shades of gray. Instead, it
+ * returns a black and white surface
+ * and we have to translate it back
+ * to a 256 gray shaded surface.
+ * */
+ unsigned char *srcp = src->buffer + soffset;
+ unsigned char *dstp = dst->buffer + doffset;
+ unsigned char c;
+ int j, k;
+ for (j = 0; j < src->width; j += 8) {
+ c = *srcp++;
+ for (k = 0; k < 8; ++k) {
+ if ((c&0x80) >> 7) {
+ *dstp++ = NUM_GRAYS - 1;
+ } else {
+ *dstp++ = 0x00;
+ }
+ c <<= 1;
+ }
+ }
+ } else if (src->pixel_mode == FT_PIXEL_MODE_GRAY2) {
+ unsigned char *srcp = src->buffer + soffset;
+ unsigned char *dstp = dst->buffer + doffset;
+ unsigned char c;
+ int j, k;
+ for (j = 0; j < src->width; j += 4) {
+ c = *srcp++;
+ for (k = 0; k < 4; ++k) {
+ if ((c&0xA0) >> 6) {
+ *dstp++ = NUM_GRAYS * ((c&0xA0) >> 6) / 3 - 1;
+ } else {
+ *dstp++ = 0x00;
+ }
+ c <<= 2;
+ }
+ }
+ } else if (src->pixel_mode == FT_PIXEL_MODE_GRAY4) {
+ unsigned char *srcp = src->buffer + soffset;
+ unsigned char *dstp = dst->buffer + doffset;
+ unsigned char c;
+ int j, k;
+ for (j = 0; j < src->width; j += 2) {
+ c = *srcp++;
+ for (k = 0; k < 2; ++k) {
+ if ((c&0xF0) >> 4) {
+ *dstp++ = NUM_GRAYS * ((c&0xF0) >> 4) / 15 - 1;
+ } else {
+ *dstp++ = 0x00;
+ }
+ c <<= 4;
+ }
+ }
+ } else {
+ SDL_memcpy(dst->buffer+doffset,
+ src->buffer+soffset, src->pitch);
+ }
+ }
+ }
+
+ /* Handle the bold style */
+ if (TTF_HANDLE_STYLE_BOLD(font)) {
+ int row;
+ int col;
+ int offset;
+ int pixel;
+ Uint8* pixmap;
+
+ /* The pixmap is a little hard, we have to add and clamp */
+ for (row = dst->rows - 1; row >= 0; --row) {
+ pixmap = (Uint8*) dst->buffer + row * dst->pitch;
+ for (offset=1; offset <= font->glyph_overhang; ++offset) {
+ for (col = dst->width - 1; col > 0; --col) {
+ if (mono) {
+ pixmap[col] |= pixmap[col-1];
+ } else {
+ pixel = (pixmap[col] + pixmap[col-1]);
+ if (pixel > NUM_GRAYS - 1) {
+ pixel = NUM_GRAYS - 1;
+ }
+ pixmap[col] = (Uint8) pixel;
+ }
+ }
+ }
+ }
+ }
+
+ /* Mark that we rendered this format */
+ if (mono) {
+ cached->stored |= CACHED_BITMAP;
+ } else {
+ cached->stored |= CACHED_PIXMAP;
+ }
+
+ /* Free outlined glyph */
+ if (bitmap_glyph) {
+ FT_Done_Glyph(bitmap_glyph);
+ }
+ }
+
+ /* We're done, mark this glyph cached */
+ cached->cached = ch;
+
+ return 0;
+}
+
+static FT_Error Find_Glyph(TTF_Font* font, Uint32 ch, int want)
+{
+ int retval = 0;
+ int hsize = sizeof(font->cache) / sizeof(font->cache[0]);
+
+ int h = ch % hsize;
+ font->current = &font->cache[h];
+
+ if (font->current->cached != ch)
+ Flush_Glyph(font->current);
+
+ if ((font->current->stored & want) != want) {
+ retval = Load_Glyph(font, ch, font->current, want);
+ }
+ return retval;
+}
+
+void TTF_CloseFont(TTF_Font* font)
+{
+ if (font) {
+ Flush_Cache(font);
+ if (font->face) {
+ FT_Done_Face(font->face);
+ }
+ if (font->args.stream) {
+ SDL_free(font->args.stream);
+ }
+ if (font->freesrc) {
+ SDL_RWclose(font->src);
+ }
+ SDL_free(font);
+ }
+}
+
+/* Gets the number of bytes needed to convert a Latin-1 string to UTF-8 */
+static size_t LATIN1_to_UTF8_len(const char *text)
+{
+ size_t bytes = 1;
+ while (*text) {
+ Uint8 ch = *(Uint8*)text++;
+ if (ch <= 0x7F) {
+ bytes += 1;
+ } else {
+ bytes += 2;
+ }
+ }
+ return bytes;
+}
+
+/* Gets the number of bytes needed to convert a UCS2 string to UTF-8 */
+static size_t UCS2_to_UTF8_len(const Uint16 *text)
+{
+ size_t bytes = 1;
+ while (*text) {
+ Uint16 ch = *text++;
+ if (ch <= 0x7F) {
+ bytes += 1;
+ } else if (ch <= 0x7FF) {
+ bytes += 2;
+ } else {
+ bytes += 3;
+ }
+ }
+ return bytes;
+}
+
+/* Convert a Latin-1 string to a UTF-8 string */
+static void LATIN1_to_UTF8(const char *src, Uint8 *dst)
+{
+ while (*src) {
+ Uint8 ch = *(Uint8*)src++;
+ if (ch <= 0x7F) {
+ *dst++ = ch;
+ } else {
+ *dst++ = 0xC0 | ((ch >> 6) & 0x1F);
+ *dst++ = 0x80 | (ch & 0x3F);
+ }
+ }
+ *dst = '\0';
+}
+
+/* Convert a UCS-2 string to a UTF-8 string */
+static void UCS2_to_UTF8(const Uint16 *src, Uint8 *dst)
+{
+ int swapped = TTF_byteswapped;
+
+ while (*src) {
+ Uint16 ch = *src++;
+ if (ch == UNICODE_BOM_NATIVE) {
+ swapped = 0;
+ continue;
+ }
+ if (ch == UNICODE_BOM_SWAPPED) {
+ swapped = 1;
+ continue;
+ }
+ if (swapped) {
+ ch = SDL_Swap16(ch);
+ }
+ if (ch <= 0x7F) {
+ *dst++ = (Uint8) ch;
+ } else if (ch <= 0x7FF) {
+ *dst++ = 0xC0 | (Uint8) ((ch >> 6) & 0x1F);
+ *dst++ = 0x80 | (Uint8) (ch & 0x3F);
+ } else {
+ *dst++ = 0xE0 | (Uint8) ((ch >> 12) & 0x0F);
+ *dst++ = 0x80 | (Uint8) ((ch >> 6) & 0x3F);
+ *dst++ = 0x80 | (Uint8) (ch & 0x3F);
+ }
+ }
+ *dst = '\0';
+}
+
+/* Gets a unicode value from a UTF-8 encoded string and advance the string */
+#define UNKNOWN_UNICODE 0xFFFD
+static Uint32 UTF8_getch(const char **src, size_t *srclen)
+{
+ const Uint8 *p = *(const Uint8**)src;
+ size_t left = 0;
+ SDL_bool overlong = SDL_FALSE;
+ SDL_bool underflow = SDL_FALSE;
+ Uint32 ch = UNKNOWN_UNICODE;
+
+ if (*srclen == 0) {
+ return UNKNOWN_UNICODE;
+ }
+ if (p[0] >= 0xFC) {
+ if ((p[0] & 0xFE) == 0xFC) {
+ if (p[0] == 0xFC && (p[1] & 0xFC) == 0x80) {
+ overlong = SDL_TRUE;
+ }
+ ch = (Uint32) (p[0] & 0x01);
+ left = 5;
+ }
+ } else if (p[0] >= 0xF8) {
+ if ((p[0] & 0xFC) == 0xF8) {
+ if (p[0] == 0xF8 && (p[1] & 0xF8) == 0x80) {
+ overlong = SDL_TRUE;
+ }
+ ch = (Uint32) (p[0] & 0x03);
+ left = 4;
+ }
+ } else if (p[0] >= 0xF0) {
+ if ((p[0] & 0xF8) == 0xF0) {
+ if (p[0] == 0xF0 && (p[1] & 0xF0) == 0x80) {
+ overlong = SDL_TRUE;
+ }
+ ch = (Uint32) (p[0] & 0x07);
+ left = 3;
+ }
+ } else if (p[0] >= 0xE0) {
+ if ((p[0] & 0xF0) == 0xE0) {
+ if (p[0] == 0xE0 && (p[1] & 0xE0) == 0x80) {
+ overlong = SDL_TRUE;
+ }
+ ch = (Uint32) (p[0] & 0x0F);
+ left = 2;
+ }
+ } else if (p[0] >= 0xC0) {
+ if ((p[0] & 0xE0) == 0xC0) {
+ if ((p[0] & 0xDE) == 0xC0) {
+ overlong = SDL_TRUE;
+ }
+ ch = (Uint32) (p[0] & 0x1F);
+ left = 1;
+ }
+ } else {
+ if ((p[0] & 0x80) == 0x00) {
+ ch = (Uint32) p[0];
+ }
+ }
+ ++*src;
+ --*srclen;
+ while (left > 0 && *srclen > 0) {
+ ++p;
+ if ((p[0] & 0xC0) != 0x80) {
+ ch = UNKNOWN_UNICODE;
+ break;
+ }
+ ch <<= 6;
+ ch |= (p[0] & 0x3F);
+ ++*src;
+ --*srclen;
+ --left;
+ }
+ if (left > 0) {
+ underflow = SDL_TRUE;
+ }
+ /* Technically overlong sequences are invalid and should not be interpreted.
+ However, it doesn't cause a security risk here and I don't see any harm in
+ displaying them. The application is responsible for any other side effects
+ of allowing overlong sequences (e.g. string compares failing, etc.)
+ See bug 1931 for sample input that triggers this.
+ */
+ /*if (overlong) return UNKNOWN_UNICODE;*/
+ if (underflow ||
+ (ch >= 0xD800 && ch <= 0xDFFF) ||
+ (ch == 0xFFFE || ch == 0xFFFF) || ch > 0x10FFFF) {
+ ch = UNKNOWN_UNICODE;
+ }
+ return ch;
+}
+
+int TTF_FontHeight(const TTF_Font *font)
+{
+ return(font->height);
+}
+
+int TTF_FontAscent(const TTF_Font *font)
+{
+ return(font->ascent);
+}
+
+int TTF_FontDescent(const TTF_Font *font)
+{
+ return(font->descent);
+}
+
+int TTF_FontLineSkip(const TTF_Font *font)
+{
+ return(font->lineskip);
+}
+
+int TTF_GetFontKerning(const TTF_Font *font)
+{
+ return(font->kerning);
+}
+
+void TTF_SetFontKerning(TTF_Font *font, int allowed)
+{
+ font->kerning = allowed;
+}
+
+long TTF_FontFaces(const TTF_Font *font)
+{
+ return(font->face->num_faces);
+}
+
+int TTF_FontFaceIsFixedWidth(const TTF_Font *font)
+{
+ return(FT_IS_FIXED_WIDTH(font->face));
+}
+
+char *TTF_FontFaceFamilyName(const TTF_Font *font)
+{
+ return(font->face->family_name);
+}
+
+char *TTF_FontFaceStyleName(const TTF_Font *font)
+{
+ return(font->face->style_name);
+}
+
+int TTF_GlyphIsProvided(const TTF_Font *font, Uint16 ch)
+{
+ return(FT_Get_Char_Index(font->face, ch));
+}
+
+int TTF_GlyphMetrics(TTF_Font *font, Uint16 ch,
+ int* minx, int* maxx, int* miny, int* maxy, int* advance)
+{
+ FT_Error error;
+
+ error = Find_Glyph(font, ch, CACHED_METRICS);
+ if (error) {
+ TTF_SetFTError("Couldn't find glyph", error);
+ return -1;
+ }
+
+ if (minx) {
+ *minx = font->current->minx;
+ }
+ if (maxx) {
+ *maxx = font->current->maxx;
+ if (TTF_HANDLE_STYLE_BOLD(font)) {
+ *maxx += font->glyph_overhang;
+ }
+ }
+ if (miny) {
+ *miny = font->current->miny;
+ }
+ if (maxy) {
+ *maxy = font->current->maxy;
+ }
+ if (advance) {
+ *advance = font->current->advance;
+ if (TTF_HANDLE_STYLE_BOLD(font)) {
+ *advance += font->glyph_overhang;
+ }
+ }
+ return 0;
+}
+
+int TTF_SizeText(TTF_Font *font, const char *text, int *w, int *h)
+{
+ int status = -1;
+ Uint8 *utf8;
+
+ TTF_CHECKPOINTER(text, -1);
+
+ utf8 = SDL_stack_alloc(Uint8, LATIN1_to_UTF8_len(text));
+ if (utf8) {
+ LATIN1_to_UTF8(text, utf8);
+ status = TTF_SizeUTF8(font, (char *)utf8, w, h);
+ SDL_stack_free(utf8);
+ } else {
+ SDL_OutOfMemory();
+ }
+ return status;
+}
+
+int TTF_SizeUTF8(TTF_Font *font, const char *text, int *w, int *h)
+{
+ int status;
+ int x, z;
+ int minx, maxx;
+ int miny, maxy;
+ c_glyph *glyph;
+ FT_Error error;
+ FT_Long use_kerning;
+ FT_UInt prev_index = 0;
+ int outline_delta = 0;
+ size_t textlen;
+
+ TTF_CHECKPOINTER(text, -1);
+
+ /* Initialize everything to 0 */
+ status = 0;
+ minx = maxx = 0;
+ miny = maxy = 0;
+
+ /* check kerning */
+ use_kerning = FT_HAS_KERNING(font->face) && font->kerning;
+
+ /* Init outline handling */
+ if (font->outline > 0) {
+ outline_delta = font->outline * 2;
+ }
+
+ /* Load each character and sum it's bounding box */
+ textlen = SDL_strlen(text);
+ x= 0;
+ while (textlen > 0) {
+ Uint32 c = UTF8_getch(&text, &textlen);
+ if (c == UNICODE_BOM_NATIVE || c == UNICODE_BOM_SWAPPED) {
+ continue;
+ }
+
+ error = Find_Glyph(font, c, CACHED_METRICS);
+ if (error) {
+ TTF_SetFTError("Couldn't find glyph", error);
+ return -1;
+ }
+ glyph = font->current;
+
+ /* handle kerning */
+ if (use_kerning && prev_index && glyph->index) {
+ FT_Vector delta;
+ FT_Get_Kerning(font->face, prev_index, glyph->index, ft_kerning_default, &delta);
+ x += delta.x >> 6;
+ }
+
+#if 0
+ if ((ch == text) && (glyph->minx < 0)) {
+ /* Fixes the texture wrapping bug when the first letter
+ * has a negative minx value or horibearing value. The entire
+ * bounding box must be adjusted to be bigger so the entire
+ * letter can fit without any texture corruption or wrapping.
+ *
+ * Effects: First enlarges bounding box.
+ * Second, xstart has to start ahead of its normal spot in the
+ * negative direction of the negative minx value.
+ * (pushes everything to the right).
+ *
+ * This will make the memory copy of the glyph bitmap data
+ * work out correctly.
+ * */
+ z -= glyph->minx;
+ }
+#endif
+
+ z = x + glyph->minx;
+ if (minx > z) {
+ minx = z;
+ }
+ if (TTF_HANDLE_STYLE_BOLD(font)) {
+ x += font->glyph_overhang;
+ }
+ if (glyph->advance > glyph->maxx) {
+ z = x + glyph->advance;
+ } else {
+ z = x + glyph->maxx;
+ }
+ if (maxx < z) {
+ maxx = z;
+ }
+ x += glyph->advance;
+
+ if (glyph->miny < miny) {
+ miny = glyph->miny;
+ }
+ if (glyph->maxy > maxy) {
+ maxy = glyph->maxy;
+ }
+ prev_index = glyph->index;
+ }
+
+ /* Fill the bounds rectangle */
+ if (w) {
+ /* Add outline extra width */
+ *w = (maxx - minx) + outline_delta;
+ }
+ if (h) {
+ /* Some fonts descend below font height (FletcherGothicFLF) */
+ /* Add outline extra height */
+ *h = (font->ascent - miny) + outline_delta;
+ if (*h < font->height) {
+ *h = font->height;
+ }
+ /* Update height according to the needs of the underline style */
+ if (TTF_HANDLE_STYLE_UNDERLINE(font)) {
+ int bottom_row = TTF_underline_bottom_row(font);
+ if (*h < bottom_row) {
+ *h = bottom_row;
+ }
+ }
+ }
+ return status;
+}
+
+int TTF_SizeUNICODE(TTF_Font *font, const Uint16 *text, int *w, int *h)
+{
+ int status = -1;
+ Uint8 *utf8;
+
+ TTF_CHECKPOINTER(text, -1);
+
+ utf8 = SDL_stack_alloc(Uint8, UCS2_to_UTF8_len(text));
+ if (utf8) {
+ UCS2_to_UTF8(text, utf8);
+ status = TTF_SizeUTF8(font, (char *)utf8, w, h);
+ SDL_stack_free(utf8);
+ } else {
+ SDL_OutOfMemory();
+ }
+ return status;
+}
+
+SDL_Surface *TTF_RenderText_Solid(TTF_Font *font,
+ const char *text, SDL_Color fg)
+{
+ SDL_Surface *surface = NULL;
+ Uint8 *utf8;
+
+ TTF_CHECKPOINTER(text, NULL);
+
+ utf8 = SDL_stack_alloc(Uint8, LATIN1_to_UTF8_len(text));
+ if (utf8) {
+ LATIN1_to_UTF8(text, utf8);
+ surface = TTF_RenderUTF8_Solid(font, (char *)utf8, fg);
+ SDL_stack_free(utf8);
+ } else {
+ SDL_OutOfMemory();
+ }
+ return surface;
+}
+
+SDL_Surface *TTF_RenderUTF8_Solid(TTF_Font *font,
+ const char *text, SDL_Color fg)
+{
+ int xstart;
+ int width;
+ int height;
+ SDL_Surface* textbuf;
+ SDL_Palette* palette;
+ Uint8* src;
+ Uint8* dst;
+ Uint8 *dst_check;
+ int row, col;
+ c_glyph *glyph;
+
+ FT_Bitmap *current;
+ FT_Error error;
+ FT_Long use_kerning;
+ FT_UInt prev_index = 0;
+ size_t textlen;
+
+ TTF_CHECKPOINTER(text, NULL);
+
+ /* Get the dimensions of the text surface */
+ if ((TTF_SizeUTF8(font, text, &width, &height) < 0) || !width) {
+ TTF_SetError("Text has zero width");
+ return NULL;
+ }
+
+ /* Create the target surface */
+ textbuf = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, 8, 0, 0, 0, 0);
+ if (textbuf == NULL) {
+ return NULL;
+ }
+
+ /* Adding bound checking to avoid all kinds of memory corruption errors
+ that may occur. */
+ dst_check = (Uint8*)textbuf->pixels + textbuf->pitch * textbuf->h;
+
+ /* Fill the palette with the foreground color */
+ palette = textbuf->format->palette;
+ palette->colors[0].r = 255 - fg.r;
+ palette->colors[0].g = 255 - fg.g;
+ palette->colors[0].b = 255 - fg.b;
+ palette->colors[1].r = fg.r;
+ palette->colors[1].g = fg.g;
+ palette->colors[1].b = fg.b;
+ palette->colors[1].a = fg.a ? fg.a : SDL_ALPHA_OPAQUE;
+ SDL_SetColorKey(textbuf, SDL_TRUE, 0);
+
+ /* check kerning */
+ use_kerning = FT_HAS_KERNING(font->face) && font->kerning;
+
+ /* Load and render each character */
+ textlen = SDL_strlen(text);
+ xstart = 0;
+ while (textlen > 0) {
+ Uint32 c = UTF8_getch(&text, &textlen);
+ if (c == UNICODE_BOM_NATIVE || c == UNICODE_BOM_SWAPPED) {
+ continue;
+ }
+
+ error = Find_Glyph(font, c, CACHED_METRICS|CACHED_BITMAP);
+ if (error) {
+ TTF_SetFTError("Couldn't find glyph", error);
+ SDL_FreeSurface(textbuf);
+ return NULL;
+ }
+ glyph = font->current;
+ current = &glyph->bitmap;
+ /* Ensure the width of the pixmap is correct. On some cases,
+ * freetype may report a larger pixmap than possible.*/
+ width = current->width;
+ if (font->outline <= 0 && width > glyph->maxx - glyph->minx) {
+ width = glyph->maxx - glyph->minx;
+ }
+ /* do kerning, if possible AC-Patch */
+ if (use_kerning && prev_index && glyph->index) {
+ FT_Vector delta;
+ FT_Get_Kerning(font->face, prev_index, glyph->index, ft_kerning_default, &delta);
+ xstart += delta.x >> 6;
+ }
+
+ for (row = 0; row < current->rows; ++row) {
+ /* Make sure we don't go either over, or under the limit */
+ if ((xstart + glyph->minx) < 0) {
+ xstart -= (xstart + glyph->minx);
+ }
+ if ((row + glyph->yoffset) < 0) {
+ continue;
+ }
+ if ((row + glyph->yoffset) >= textbuf->h) {
+ continue;
+ }
+ dst = (Uint8 *)textbuf->pixels +
+ (row+glyph->yoffset) * textbuf->pitch +
+ xstart + glyph->minx;
+ src = current->buffer + row * current->pitch;
+ for (col = width; col > 0 && dst < dst_check; --col) {
+ *dst++ |= *src++;
+ }
+ }
+
+ xstart += glyph->advance;
+ if (TTF_HANDLE_STYLE_BOLD(font)) {
+ xstart += font->glyph_overhang;
+ }
+ prev_index = glyph->index;
+ }
+
+ /* Handle the underline style */
+ if (TTF_HANDLE_STYLE_UNDERLINE(font)) {
+ row = TTF_underline_top_row(font);
+ TTF_drawLine_Solid(font, textbuf, row);
+ }
+
+ /* Handle the strikethrough style */
+ if (TTF_HANDLE_STYLE_STRIKETHROUGH(font)) {
+ row = TTF_strikethrough_top_row(font);
+ TTF_drawLine_Solid(font, textbuf, row);
+ }
+ return textbuf;
+}
+
+SDL_Surface *TTF_RenderUNICODE_Solid(TTF_Font *font,
+ const Uint16 *text, SDL_Color fg)
+{
+ SDL_Surface *surface = NULL;
+ Uint8 *utf8;
+
+ TTF_CHECKPOINTER(text, NULL);
+
+ utf8 = SDL_stack_alloc(Uint8, UCS2_to_UTF8_len(text));
+ if (utf8) {
+ UCS2_to_UTF8(text, utf8);
+ surface = TTF_RenderUTF8_Solid(font, (char *)utf8, fg);
+ SDL_stack_free(utf8);
+ } else {
+ SDL_OutOfMemory();
+ }
+ return surface;
+}
+
+SDL_Surface *TTF_RenderGlyph_Solid(TTF_Font *font, Uint16 ch, SDL_Color fg)
+{
+ Uint16 ucs2[2] = { ch, 0 };
+ Uint8 utf8[4];
+
+ UCS2_to_UTF8(ucs2, utf8);
+ return TTF_RenderUTF8_Solid(font, (char *)utf8, fg);
+}
+
+SDL_Surface *TTF_RenderText_Shaded(TTF_Font *font,
+ const char *text, SDL_Color fg, SDL_Color bg)
+{
+ SDL_Surface *surface = NULL;
+ Uint8 *utf8;
+
+ TTF_CHECKPOINTER(text, NULL);
+
+ utf8 = SDL_stack_alloc(Uint8, LATIN1_to_UTF8_len(text));
+ if (utf8) {
+ LATIN1_to_UTF8(text, utf8);
+ surface = TTF_RenderUTF8_Shaded(font, (char *)utf8, fg, bg);
+ SDL_stack_free(utf8);
+ } else {
+ SDL_OutOfMemory();
+ }
+ return surface;
+}
+
+/* Convert the UTF-8 text to UNICODE and render it
+*/
+SDL_Surface *TTF_RenderUTF8_Shaded(TTF_Font *font,
+ const char *text, SDL_Color fg, SDL_Color bg)
+{
+ int xstart;
+ int width;
+ int height;
+ SDL_Surface* textbuf;
+ SDL_Palette* palette;
+ int index;
+ int rdiff;
+ int gdiff;
+ int bdiff;
+ int adiff;
+ Uint8* src;
+ Uint8* dst;
+ Uint8* dst_check;
+ int row, col;
+ FT_Bitmap* current;
+ c_glyph *glyph;
+ FT_Error error;
+ FT_Long use_kerning;
+ FT_UInt prev_index = 0;
+ size_t textlen;
+
+ TTF_CHECKPOINTER(text, NULL);
+
+ /* Get the dimensions of the text surface */
+ if ((TTF_SizeUTF8(font, text, &width, &height) < 0) || !width) {
+ TTF_SetError("Text has zero width");
+ return NULL;
+ }
+
+ /* Create the target surface */
+ textbuf = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, 8, 0, 0, 0, 0);
+ if (textbuf == NULL) {
+ return NULL;
+ }
+
+ /* Adding bound checking to avoid all kinds of memory corruption errors
+ that may occur. */
+ dst_check = (Uint8*)textbuf->pixels + textbuf->pitch * textbuf->h;
+
+ /* Support alpha blending */
+ if (!fg.a) {
+ fg.a = SDL_ALPHA_OPAQUE;
+ }
+ if (!bg.a) {
+ bg.a = SDL_ALPHA_OPAQUE;
+ }
+ if (fg.a != SDL_ALPHA_OPAQUE || bg.a != SDL_ALPHA_OPAQUE) {
+ SDL_SetSurfaceBlendMode(textbuf, SDL_BLENDMODE_BLEND);
+ }
+
+ /* Fill the palette with NUM_GRAYS levels of shading from bg to fg */
+ palette = textbuf->format->palette;
+ rdiff = fg.r - bg.r;
+ gdiff = fg.g - bg.g;
+ bdiff = fg.b - bg.b;
+ adiff = fg.a - bg.a;
+
+ for (index = 0; index < NUM_GRAYS; ++index) {
+ palette->colors[index].r = bg.r + (index*rdiff) / (NUM_GRAYS-1);
+ palette->colors[index].g = bg.g + (index*gdiff) / (NUM_GRAYS-1);
+ palette->colors[index].b = bg.b + (index*bdiff) / (NUM_GRAYS-1);
+ palette->colors[index].a = bg.a + (index*adiff) / (NUM_GRAYS-1);
+ }
+
+ /* check kerning */
+ use_kerning = FT_HAS_KERNING(font->face) && font->kerning;
+
+ /* Load and render each character */
+ textlen = SDL_strlen(text);
+ xstart = 0;
+ while (textlen > 0) {
+ Uint32 c = UTF8_getch(&text, &textlen);
+ if (c == UNICODE_BOM_NATIVE || c == UNICODE_BOM_SWAPPED) {
+ continue;
+ }
+
+ error = Find_Glyph(font, c, CACHED_METRICS|CACHED_PIXMAP);
+ if (error) {
+ TTF_SetFTError("Couldn't find glyph", error);
+ SDL_FreeSurface(textbuf);
+ return NULL;
+ }
+ glyph = font->current;
+ /* Ensure the width of the pixmap is correct. On some cases,
+ * freetype may report a larger pixmap than possible.*/
+ width = glyph->pixmap.width;
+ if (font->outline <= 0 && width > glyph->maxx - glyph->minx) {
+ width = glyph->maxx - glyph->minx;
+ }
+ /* do kerning, if possible AC-Patch */
+ if (use_kerning && prev_index && glyph->index) {
+ FT_Vector delta;
+ FT_Get_Kerning(font->face, prev_index, glyph->index, ft_kerning_default, &delta);
+ xstart += delta.x >> 6;
+ }
+
+ current = &glyph->pixmap;
+ for (row = 0; row < current->rows; ++row) {
+ /* Make sure we don't go either over, or under the limit */
+ if ((xstart + glyph->minx) < 0) {
+ xstart -= (xstart + glyph->minx);
+ }
+ if ((row + glyph->yoffset) < 0) {
+ continue;
+ }
+ if ((row + glyph->yoffset) >= textbuf->h) {
+ continue;
+ }
+ dst = (Uint8 *)textbuf->pixels +
+ (row+glyph->yoffset) * textbuf->pitch +
+ xstart + glyph->minx;
+ src = current->buffer + row * current->pitch;
+ for (col = width; col > 0 && dst < dst_check; --col) {
+ *dst++ |= *src++;
+ }
+ }
+
+ xstart += glyph->advance;
+ if (TTF_HANDLE_STYLE_BOLD(font)) {
+ xstart += font->glyph_overhang;
+ }
+ prev_index = glyph->index;
+ }
+
+ /* Handle the underline style */
+ if (TTF_HANDLE_STYLE_UNDERLINE(font)) {
+ row = TTF_underline_top_row(font);
+ TTF_drawLine_Shaded(font, textbuf, row);
+ }
+
+ /* Handle the strikethrough style */
+ if (TTF_HANDLE_STYLE_STRIKETHROUGH(font)) {
+ row = TTF_strikethrough_top_row(font);
+ TTF_drawLine_Shaded(font, textbuf, row);
+ }
+ return textbuf;
+}
+
+SDL_Surface* TTF_RenderUNICODE_Shaded(TTF_Font* font,
+ const Uint16* text,
+ SDL_Color fg,
+ SDL_Color bg)
+{
+ SDL_Surface *surface = NULL;
+ Uint8 *utf8;
+
+ TTF_CHECKPOINTER(text, NULL);
+
+ utf8 = SDL_stack_alloc(Uint8, UCS2_to_UTF8_len(text));
+ if (utf8) {
+ UCS2_to_UTF8(text, utf8);
+ surface = TTF_RenderUTF8_Shaded(font, (char *)utf8, fg, bg);
+ SDL_stack_free(utf8);
+ } else {
+ SDL_OutOfMemory();
+ }
+ return surface;
+}
+
+SDL_Surface* TTF_RenderGlyph_Shaded(TTF_Font* font,
+ Uint16 ch,
+ SDL_Color fg,
+ SDL_Color bg)
+{
+ Uint16 ucs2[2] = { ch, 0 };
+ Uint8 utf8[4];
+
+ UCS2_to_UTF8(ucs2, utf8);
+ return TTF_RenderUTF8_Shaded(font, (char *)utf8, fg, bg);
+}
+
+SDL_Surface *TTF_RenderText_Blended(TTF_Font *font,
+ const char *text, SDL_Color fg)
+{
+ SDL_Surface *surface = NULL;
+ Uint8 *utf8;
+
+ TTF_CHECKPOINTER(text, NULL);
+
+ utf8 = SDL_stack_alloc(Uint8, LATIN1_to_UTF8_len(text));
+ if (utf8) {
+ LATIN1_to_UTF8(text, utf8);
+ surface = TTF_RenderUTF8_Blended(font, (char *)utf8, fg);
+ SDL_stack_free(utf8);
+ } else {
+ SDL_OutOfMemory();
+ }
+ return surface;
+}
+
+SDL_Surface *TTF_RenderUTF8_Blended(TTF_Font *font,
+ const char *text, SDL_Color fg)
+{
+ int i;
+ int xstart;
+ int width, height;
+ SDL_Surface *textbuf;
+ Uint8 alpha;
+ Uint8 alpha_table[256];
+ Uint32 pixel;
+ Uint8 *src;
+ Uint32 *dst;
+ Uint32 *dst_check;
+ int row, col;
+ c_glyph *glyph;
+ FT_Error error;
+ FT_Long use_kerning;
+ FT_UInt prev_index = 0;
+ size_t textlen;
+
+ TTF_CHECKPOINTER(text, NULL);
+
+ /* Get the dimensions of the text surface */
+ if ((TTF_SizeUTF8(font, text, &width, &height) < 0) || !width) {
+ TTF_SetError("Text has zero width");
+ return(NULL);
+ }
+
+ /* Create the target surface */
+ textbuf = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, 32,
+ 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000);
+ if (textbuf == NULL) {
+ return(NULL);
+ }
+
+ /* Adding bound checking to avoid all kinds of memory corruption errors
+ that may occur. */
+ dst_check = (Uint32*)textbuf->pixels + textbuf->pitch/4 * textbuf->h;
+
+ /* check kerning */
+ use_kerning = FT_HAS_KERNING(font->face) && font->kerning;
+
+ /* Support alpha blending */
+ if (!fg.a) {
+ fg.a = SDL_ALPHA_OPAQUE;
+ }
+ if (fg.a == SDL_ALPHA_OPAQUE) {
+ for (i = 0; i < SDL_arraysize(alpha_table); ++i) {
+ alpha_table[i] = (Uint8)i;
+ }
+ } else {
+ for (i = 0; i < SDL_arraysize(alpha_table); ++i) {
+ alpha_table[i] = (Uint8)(i * fg.a / 255);
+ }
+ SDL_SetSurfaceBlendMode(textbuf, SDL_BLENDMODE_BLEND);
+ }
+
+ /* Load and render each character */
+ textlen = SDL_strlen(text);
+ xstart = 0;
+ pixel = (fg.r<<16)|(fg.g<<8)|fg.b;
+ SDL_FillRect(textbuf, NULL, pixel); /* Initialize with fg and 0 alpha */
+ while (textlen > 0) {
+ Uint32 c = UTF8_getch(&text, &textlen);
+ if (c == UNICODE_BOM_NATIVE || c == UNICODE_BOM_SWAPPED) {
+ continue;
+ }
+
+ error = Find_Glyph(font, c, CACHED_METRICS|CACHED_PIXMAP);
+ if (error) {
+ TTF_SetFTError("Couldn't find glyph", error);
+ SDL_FreeSurface(textbuf);
+ return NULL;
+ }
+ glyph = font->current;
+ /* Ensure the width of the pixmap is correct. On some cases,
+ * freetype may report a larger pixmap than possible.*/
+ width = glyph->pixmap.width;
+ if (font->outline <= 0 && width > glyph->maxx - glyph->minx) {
+ width = glyph->maxx - glyph->minx;
+ }
+ /* do kerning, if possible AC-Patch */
+ if (use_kerning && prev_index && glyph->index) {
+ FT_Vector delta;
+ FT_Get_Kerning(font->face, prev_index, glyph->index, ft_kerning_default, &delta);
+ xstart += delta.x >> 6;
+ }
+
+ for (row = 0; row < glyph->pixmap.rows; ++row) {
+ /* Make sure we don't go either over, or under the limit */
+ if ((xstart + glyph->minx) < 0) {
+ xstart -= (xstart + glyph->minx);
+ }
+ if ((row + glyph->yoffset) < 0) {
+ continue;
+ }
+ if ((row + glyph->yoffset) >= textbuf->h) {
+ continue;
+ }
+ dst = (Uint32 *)textbuf->pixels +
+ (row+glyph->yoffset) * textbuf->pitch/4 +
+ xstart + glyph->minx;
+ src = (Uint8*)glyph->pixmap.buffer + row * glyph->pixmap.pitch;
+ for (col = width; col > 0 && dst < dst_check; --col) {
+ alpha = *src++;
+ *dst++ |= pixel | ((Uint32)alpha_table[alpha] << 24);
+ }
+ }
+
+ xstart += glyph->advance;
+ if (TTF_HANDLE_STYLE_BOLD(font)) {
+ xstart += font->glyph_overhang;
+ }
+ prev_index = glyph->index;
+ }
+
+ /* Handle the underline style */
+ if (TTF_HANDLE_STYLE_UNDERLINE(font)) {
+ row = TTF_underline_top_row(font);
+ TTF_drawLine_Blended(font, textbuf, row, pixel | (Uint32)fg.a << 24);
+ }
+
+ /* Handle the strikethrough style */
+ if (TTF_HANDLE_STYLE_STRIKETHROUGH(font)) {
+ row = TTF_strikethrough_top_row(font);
+ TTF_drawLine_Blended(font, textbuf, row, pixel | (Uint32)fg.a << 24);
+ }
+ return(textbuf);
+}
+
+SDL_Surface *TTF_RenderUNICODE_Blended(TTF_Font *font,
+ const Uint16 *text, SDL_Color fg)
+{
+ SDL_Surface *surface = NULL;
+ Uint8 *utf8;
+
+ TTF_CHECKPOINTER(text, NULL);
+
+ utf8 = SDL_stack_alloc(Uint8, UCS2_to_UTF8_len(text));
+ if (utf8) {
+ UCS2_to_UTF8(text, utf8);
+ surface = TTF_RenderUTF8_Blended(font, (char *)utf8, fg);
+ SDL_stack_free(utf8);
+ } else {
+ SDL_OutOfMemory();
+ }
+ return surface;
+}
+
+
+SDL_Surface *TTF_RenderText_Blended_Wrapped(TTF_Font *font, const char *text, SDL_Color fg, Uint32 wrapLength)
+{
+ SDL_Surface *surface = NULL;
+ Uint8 *utf8;
+
+ TTF_CHECKPOINTER(text, NULL);
+
+ utf8 = SDL_stack_alloc(Uint8, LATIN1_to_UTF8_len(text));
+ if (utf8) {
+ LATIN1_to_UTF8(text, utf8);
+ surface = TTF_RenderUTF8_Blended_Wrapped(font, (char *)utf8, fg, wrapLength);
+ SDL_stack_free(utf8);
+ } else {
+ SDL_OutOfMemory();
+ }
+ return surface;
+}
+
+static SDL_bool CharacterIsDelimiter(char c, const char *delimiters)
+{
+ while (*delimiters) {
+ if (c == *delimiters) {
+ return SDL_TRUE;
+ }
+ ++delimiters;
+ }
+ return SDL_FALSE;
+}
+
+/* Don't define this until we have a release where we can change font rendering
+#define TTF_USE_LINESKIP
+ */
+SDL_Surface *TTF_RenderUTF8_Blended_Wrapped(TTF_Font *font,
+ const char *text, SDL_Color fg, Uint32 wrapLength)
+{
+ int i;
+ int xstart;
+ int width, height;
+ SDL_Surface *textbuf;
+ Uint8 alpha;
+ Uint8 alpha_table[256];
+ Uint32 pixel;
+ Uint8 *src;
+ Uint32 *dst;
+ Uint32 *dst_check;
+ int row, col;
+ c_glyph *glyph;
+ FT_Error error;
+ FT_Long use_kerning;
+ FT_UInt prev_index = 0;
+#ifndef TTF_USE_LINESKIP
+ const int lineSpace = 2;
+#endif
+ int line, numLines, rowSize;
+ char *str, **strLines, **newLines;
+ size_t textlen;
+
+ TTF_CHECKPOINTER(text, NULL);
+
+ /* Get the dimensions of the text surface */
+ if ((TTF_SizeUTF8(font, text, &width, &height) < 0) || !width) {
+ TTF_SetError("Text has zero width");
+ return(NULL);
+ }
+
+ numLines = 1;
+ str = NULL;
+ strLines = NULL;
+ if (wrapLength > 0 && *text) {
+ const char *wrapDelims = " \t\r\n";
+ int w, h;
+ char *spot, *tok, *next_tok, *end;
+ char delim;
+ size_t str_len = SDL_strlen(text);
+
+ numLines = 0;
+
+ str = SDL_stack_alloc(char, str_len+1);
+ if (str == NULL) {
+ TTF_SetError("Out of memory");
+ return(NULL);
+ }
+
+ SDL_strlcpy(str, text, str_len+1);
+ tok = str;
+ end = str + str_len;
+ do {
+ newLines = (char **)SDL_realloc(strLines, (numLines+1)*sizeof(*strLines));
+ if (!newLines) {
+ TTF_SetError("Out of memory");
+ SDL_free(strLines);
+ SDL_stack_free(str);
+ return(NULL);
+ }
+ strLines = newLines;
+ strLines[numLines++] = tok;
+
+ /* Look for the end of the line */
+ if ((spot = SDL_strchr(tok, '\r')) != NULL ||
+ (spot = SDL_strchr(tok, '\n')) != NULL) {
+ if (*spot == '\r') {
+ ++spot;
+ }
+ if (*spot == '\n') {
+ ++spot;
+ }
+ } else {
+ spot = end;
+ }
+ next_tok = spot;
+
+ /* Get the longest string that will fit in the desired space */
+ for (; ;) {
+ /* Strip trailing whitespace */
+ while (spot > tok &&
+ CharacterIsDelimiter(spot[-1], wrapDelims)) {
+ --spot;
+ }
+ if (spot == tok) {
+ if (CharacterIsDelimiter(*spot, wrapDelims)) {
+ *spot = '\0';
+ }
+ break;
+ }
+ delim = *spot;
+ *spot = '\0';
+
+ TTF_SizeUTF8(font, tok, &w, &h);
+ if ((Uint32)w <= wrapLength) {
+ break;
+ } else {
+ /* Back up and try again... */
+ *spot = delim;
+ }
+
+ while (spot > tok &&
+ !CharacterIsDelimiter(spot[-1], wrapDelims)) {
+ --spot;
+ }
+ if (spot > tok) {
+ next_tok = spot;
+ }
+ }
+ tok = next_tok;
+ } while (tok < end);
+ }
+
+ /* Create the target surface */
+ textbuf = SDL_CreateRGBSurface(SDL_SWSURFACE,
+ (numLines > 1) ? wrapLength : width,
+#ifdef TTF_USE_LINESKIP
+ numLines * TTF_FontLineSkip(font),
+#else
+ height * numLines + (lineSpace * (numLines - 1)),
+#endif
+ 32, 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000);
+ if (textbuf == NULL) {
+ if (strLines) {
+ SDL_free(strLines);
+ SDL_stack_free(str);
+ }
+ return(NULL);
+ }
+
+#ifdef TTF_USE_LINESKIP
+ rowSize = textbuf->pitch/4 * TTF_FontLineSkip(font);
+#else
+ rowSize = textbuf->pitch/4 * height;
+#endif
+
+ /* Adding bound checking to avoid all kinds of memory corruption errors
+ that may occur. */
+ dst_check = (Uint32*)textbuf->pixels + textbuf->pitch/4 * textbuf->h;
+
+ /* check kerning */
+ use_kerning = FT_HAS_KERNING(font->face) && font->kerning;
+
+ /* Support alpha blending */
+ if (!fg.a) {
+ fg.a = SDL_ALPHA_OPAQUE;
+ }
+ if (fg.a == SDL_ALPHA_OPAQUE) {
+ for (i = 0; i < SDL_arraysize(alpha_table); ++i) {
+ alpha_table[i] = (Uint8)i;
+ }
+ } else {
+ for (i = 0; i < SDL_arraysize(alpha_table); ++i) {
+ alpha_table[i] = (Uint8)(i * fg.a / 255);
+ }
+ SDL_SetSurfaceBlendMode(textbuf, SDL_BLENDMODE_BLEND);
+ }
+
+ /* Load and render each character */
+ pixel = (fg.r<<16)|(fg.g<<8)|fg.b;
+ SDL_FillRect(textbuf, NULL, pixel); /* Initialize with fg and 0 alpha */
+
+ for (line = 0; line < numLines; line++) {
+ if (strLines) {
+ text = strLines[line];
+ }
+ textlen = SDL_strlen(text);
+ xstart = 0;
+ while (textlen > 0) {
+ Uint32 c = UTF8_getch(&text, &textlen);
+ if (c == UNICODE_BOM_NATIVE || c == UNICODE_BOM_SWAPPED) {
+ continue;
+ }
+
+ error = Find_Glyph(font, c, CACHED_METRICS|CACHED_PIXMAP);
+ if (error) {
+ TTF_SetFTError("Couldn't find glyph", error);
+ SDL_FreeSurface(textbuf);
+ if (strLines) {
+ SDL_free(strLines);
+ SDL_stack_free(str);
+ }
+ return NULL;
+ }
+ glyph = font->current;
+ /* Ensure the width of the pixmap is correct. On some cases,
+ * freetype may report a larger pixmap than possible.*/
+ width = glyph->pixmap.width;
+ if (font->outline <= 0 && width > glyph->maxx - glyph->minx) {
+ width = glyph->maxx - glyph->minx;
+ }
+ /* do kerning, if possible AC-Patch */
+ if (use_kerning && prev_index && glyph->index) {
+ FT_Vector delta;
+ FT_Get_Kerning(font->face, prev_index, glyph->index, ft_kerning_default, &delta);
+ xstart += delta.x >> 6;
+ }
+
+ for (row = 0; row < glyph->pixmap.rows; ++row) {
+ /* Make sure we don't go either over, or under the limit */
+ if ((xstart + glyph->minx) < 0) {
+ xstart -= (xstart + glyph->minx);
+ }
+ if ((row + glyph->yoffset) < 0) {
+ continue;
+ }
+ if ((row + glyph->yoffset) >= textbuf->h) {
+ continue;
+ }
+ dst = ((Uint32*)textbuf->pixels + rowSize * line) +
+ (row+glyph->yoffset) * textbuf->pitch/4 +
+ xstart + glyph->minx;
+ src = (Uint8*)glyph->pixmap.buffer + row * glyph->pixmap.pitch;
+ for (col = width; col > 0 && dst < dst_check; --col) {
+ alpha = *src++;
+ *dst++ |= pixel | ((Uint32)alpha_table[alpha] << 24);
+ }
+ }
+
+ xstart += glyph->advance;
+ if (TTF_HANDLE_STYLE_BOLD(font)) {
+ xstart += font->glyph_overhang;
+ }
+ prev_index = glyph->index;
+ }
+
+ /* Handle the underline style *
+ if (TTF_HANDLE_STYLE_UNDERLINE(font)) {
+ row = TTF_underline_top_row(font);
+ TTF_drawLine_Blended(font, textbuf, row, pixel | (Uint32)fg.a << 24);
+ }
+ */
+
+ /* Handle the strikethrough style *
+ if (TTF_HANDLE_STYLE_STRIKETHROUGH(font)) {
+ row = TTF_strikethrough_top_row(font);
+ TTF_drawLine_Blended(font, textbuf, row, pixel | (Uint32)fg.a << 24);
+ }
+ */
+ }
+
+ if (strLines) {
+ SDL_free(strLines);
+ SDL_stack_free(str);
+ }
+ return(textbuf);
+}
+
+SDL_Surface *TTF_RenderUNICODE_Blended_Wrapped(TTF_Font *font, const Uint16* text,
+ SDL_Color fg, Uint32 wrapLength)
+{
+ SDL_Surface *surface = NULL;
+ Uint8 *utf8;
+
+ TTF_CHECKPOINTER(text, NULL);
+
+ utf8 = SDL_stack_alloc(Uint8, UCS2_to_UTF8_len(text));
+ if (utf8) {
+ UCS2_to_UTF8(text, utf8);
+ surface = TTF_RenderUTF8_Blended_Wrapped(font, (char *)utf8, fg, wrapLength);
+ SDL_stack_free(utf8);
+ } else {
+ SDL_OutOfMemory();
+ }
+ return surface;
+}
+
+SDL_Surface *TTF_RenderGlyph_Blended(TTF_Font *font, Uint16 ch, SDL_Color fg)
+{
+ Uint16 ucs2[2] = { ch, 0 };
+ Uint8 utf8[4];
+
+ UCS2_to_UTF8(ucs2, utf8);
+ return TTF_RenderUTF8_Blended(font, (char *)utf8, fg);
+}
+
+void TTF_SetFontStyle(TTF_Font* font, int style)
+{
+ int prev_style = font->style;
+ font->style = style | font->face_style;
+
+ /* Flush the cache if the style has changed.
+ * Ignore UNDERLINE which does not impact glyph drawning.
+ * */
+ if ((font->style | TTF_STYLE_NO_GLYPH_CHANGE) != (prev_style | TTF_STYLE_NO_GLYPH_CHANGE)) {
+ Flush_Cache(font);
+ }
+}
+
+int TTF_GetFontStyle(const TTF_Font* font)
+{
+ return font->style;
+}
+
+void TTF_SetFontOutline(TTF_Font* font, int outline)
+{
+ font->outline = outline;
+ Flush_Cache(font);
+}
+
+int TTF_GetFontOutline(const TTF_Font* font)
+{
+ return font->outline;
+}
+
+void TTF_SetFontHinting(TTF_Font* font, int hinting)
+{
+ if (hinting == TTF_HINTING_LIGHT)
+ font->hinting = FT_LOAD_TARGET_LIGHT;
+ else if (hinting == TTF_HINTING_MONO)
+ font->hinting = FT_LOAD_TARGET_MONO;
+ else if (hinting == TTF_HINTING_NONE)
+ font->hinting = FT_LOAD_NO_HINTING;
+ else
+ font->hinting = 0;
+
+ Flush_Cache(font);
+}
+
+int TTF_GetFontHinting(const TTF_Font* font)
+{
+ if (font->hinting == FT_LOAD_TARGET_LIGHT)
+ return TTF_HINTING_LIGHT;
+ else if (font->hinting == FT_LOAD_TARGET_MONO)
+ return TTF_HINTING_MONO;
+ else if (font->hinting == FT_LOAD_NO_HINTING)
+ return TTF_HINTING_NONE;
+ return 0;
+}
+
+void TTF_Quit(void)
+{
+ if (TTF_initialized) {
+ if (--TTF_initialized == 0) {
+ FT_Done_FreeType(library);
+ }
+ }
+}
+
+int TTF_WasInit(void)
+{
+ return TTF_initialized;
+}
+
+/* don't use this function. It's just here for binary compatibility. */
+int TTF_GetFontKerningSize(TTF_Font* font, int prev_index, int index)
+{
+ FT_Vector delta;
+ FT_Get_Kerning(font->face, prev_index, index, ft_kerning_default, &delta);
+ return (delta.x >> 6);
+}
+
+int TTF_GetFontKerningSizeGlyphs(TTF_Font *font, Uint16 previous_ch, Uint16 ch)
+{
+ int error;
+ int glyph_index, prev_index;
+ FT_Vector delta;
+
+ if (ch == UNICODE_BOM_NATIVE || ch == UNICODE_BOM_SWAPPED) {
+ return 0;
+ }
+
+ if (previous_ch == UNICODE_BOM_NATIVE || previous_ch == UNICODE_BOM_SWAPPED) {
+ return 0;
+ }
+
+ error = Find_Glyph(font, ch, CACHED_METRICS);
+ if (error) {
+ TTF_SetFTError("Couldn't find glyph", error);
+ return -1;
+ }
+ glyph_index = font->current->index;
+
+ error = Find_Glyph(font, previous_ch, CACHED_METRICS);
+ if (error) {
+ TTF_SetFTError("Couldn't find glyph", error);
+ return -1;
+ }
+ prev_index = font->current->index;
+
+ error = FT_Get_Kerning(font->face, prev_index, glyph_index, ft_kerning_default, &delta);
+ if (error) {
+ TTF_SetFTError("Couldn't get glyph kerning", error);
+ return -1;
+ }
+ return (delta.x >> 6);
+}
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/src/libs/SDL2_ttf/SDL_ttf.h b/src/libs/SDL2_ttf/SDL_ttf.h
new file mode 100644
index 0000000..19fc9b9
--- /dev/null
+++ b/src/libs/SDL2_ttf/SDL_ttf.h
@@ -0,0 +1,294 @@
+/*
+ SDL_ttf: A companion library to SDL for working with TrueType (tm) fonts
+ Copyright (C) 2001-2018 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/* This library is a wrapper around the excellent FreeType 2.0 library,
+ available at:
+ http://www.freetype.org/
+*/
+
+/* Note: In many places, SDL_ttf will say "glyph" when it means "code point."
+ Unicode is hard, we learn as we go, and we apologize for adding to the
+ confusion. */
+
+#ifndef SDL_TTF_H_
+#define SDL_TTF_H_
+
+#include "SDL.h"
+#include "begin_code.h"
+
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Printable format: "%d.%d.%d", MAJOR, MINOR, PATCHLEVEL
+*/
+#define SDL_TTF_MAJOR_VERSION 2
+#define SDL_TTF_MINOR_VERSION 0
+#define SDL_TTF_PATCHLEVEL 14
+
+/* This macro can be used to fill a version structure with the compile-time
+ * version of the SDL_ttf library.
+ */
+#define SDL_TTF_VERSION(X) \
+{ \
+ (X)->major = SDL_TTF_MAJOR_VERSION; \
+ (X)->minor = SDL_TTF_MINOR_VERSION; \
+ (X)->patch = SDL_TTF_PATCHLEVEL; \
+}
+
+/* Backwards compatibility */
+#define TTF_MAJOR_VERSION SDL_TTF_MAJOR_VERSION
+#define TTF_MINOR_VERSION SDL_TTF_MINOR_VERSION
+#define TTF_PATCHLEVEL SDL_TTF_PATCHLEVEL
+#define TTF_VERSION(X) SDL_TTF_VERSION(X)
+
+/**
+ * This is the version number macro for the current SDL_net version.
+ */
+#define SDL_TTF_COMPILEDVERSION \
+ SDL_VERSIONNUM(SDL_TTF_MAJOR_VERSION, SDL_TTF_MINOR_VERSION, SDL_TTF_PATCHLEVEL)
+
+/**
+ * This macro will evaluate to true if compiled with SDL_net at least X.Y.Z.
+ */
+#define SDL_TTF_VERSION_ATLEAST(X, Y, Z) \
+ (SDL_TTF_COMPILEDVERSION >= SDL_VERSIONNUM(X, Y, Z))
+
+/* Make sure this is defined (only available in newer SDL versions) */
+#ifndef SDL_DEPRECATED
+#define SDL_DEPRECATED
+#endif
+
+/* This function gets the version of the dynamically linked SDL_ttf library.
+ it should NOT be used to fill a version structure, instead you should
+ use the SDL_TTF_VERSION() macro.
+ */
+extern DECLSPEC const SDL_version * SDLCALL TTF_Linked_Version(void);
+
+/* ZERO WIDTH NO-BREAKSPACE (Unicode byte order mark) */
+#define UNICODE_BOM_NATIVE 0xFEFF
+#define UNICODE_BOM_SWAPPED 0xFFFE
+
+/* This function tells the library whether UNICODE text is generally
+ byteswapped. A UNICODE BOM character in a string will override
+ this setting for the remainder of that string.
+*/
+extern DECLSPEC void SDLCALL TTF_ByteSwappedUNICODE(int swapped);
+
+/* The internal structure containing font information */
+typedef struct _TTF_Font TTF_Font;
+
+/* Initialize the TTF engine - returns 0 if successful, -1 on error */
+extern DECLSPEC int SDLCALL TTF_Init(void);
+
+/* Open a font file and create a font of the specified point size.
+ * Some .fon fonts will have several sizes embedded in the file, so the
+ * point size becomes the index of choosing which size. If the value
+ * is too high, the last indexed size will be the default. */
+extern DECLSPEC TTF_Font * SDLCALL TTF_OpenFont(const char *file, int ptsize);
+extern DECLSPEC TTF_Font * SDLCALL TTF_OpenFontIndex(const char *file, int ptsize, long index);
+extern DECLSPEC TTF_Font * SDLCALL TTF_OpenFontRW(SDL_RWops *src, int freesrc, int ptsize);
+extern DECLSPEC TTF_Font * SDLCALL TTF_OpenFontIndexRW(SDL_RWops *src, int freesrc, int ptsize, long index);
+
+/* Set and retrieve the font style */
+#define TTF_STYLE_NORMAL 0x00
+#define TTF_STYLE_BOLD 0x01
+#define TTF_STYLE_ITALIC 0x02
+#define TTF_STYLE_UNDERLINE 0x04
+#define TTF_STYLE_STRIKETHROUGH 0x08
+extern DECLSPEC int SDLCALL TTF_GetFontStyle(const TTF_Font *font);
+extern DECLSPEC void SDLCALL TTF_SetFontStyle(TTF_Font *font, int style);
+extern DECLSPEC int SDLCALL TTF_GetFontOutline(const TTF_Font *font);
+extern DECLSPEC void SDLCALL TTF_SetFontOutline(TTF_Font *font, int outline);
+
+/* Set and retrieve FreeType hinter settings */
+#define TTF_HINTING_NORMAL 0
+#define TTF_HINTING_LIGHT 1
+#define TTF_HINTING_MONO 2
+#define TTF_HINTING_NONE 3
+extern DECLSPEC int SDLCALL TTF_GetFontHinting(const TTF_Font *font);
+extern DECLSPEC void SDLCALL TTF_SetFontHinting(TTF_Font *font, int hinting);
+
+/* Get the total height of the font - usually equal to point size */
+extern DECLSPEC int SDLCALL TTF_FontHeight(const TTF_Font *font);
+
+/* Get the offset from the baseline to the top of the font
+ This is a positive value, relative to the baseline.
+ */
+extern DECLSPEC int SDLCALL TTF_FontAscent(const TTF_Font *font);
+
+/* Get the offset from the baseline to the bottom of the font
+ This is a negative value, relative to the baseline.
+ */
+extern DECLSPEC int SDLCALL TTF_FontDescent(const TTF_Font *font);
+
+/* Get the recommended spacing between lines of text for this font */
+extern DECLSPEC int SDLCALL TTF_FontLineSkip(const TTF_Font *font);
+
+/* Get/Set whether or not kerning is allowed for this font */
+extern DECLSPEC int SDLCALL TTF_GetFontKerning(const TTF_Font *font);
+extern DECLSPEC void SDLCALL TTF_SetFontKerning(TTF_Font *font, int allowed);
+
+/* Get the number of faces of the font */
+extern DECLSPEC long SDLCALL TTF_FontFaces(const TTF_Font *font);
+
+/* Get the font face attributes, if any */
+extern DECLSPEC int SDLCALL TTF_FontFaceIsFixedWidth(const TTF_Font *font);
+extern DECLSPEC char * SDLCALL TTF_FontFaceFamilyName(const TTF_Font *font);
+extern DECLSPEC char * SDLCALL TTF_FontFaceStyleName(const TTF_Font *font);
+
+/* Check wether a glyph is provided by the font or not */
+extern DECLSPEC int SDLCALL TTF_GlyphIsProvided(const TTF_Font *font, Uint16 ch);
+
+/* Get the metrics (dimensions) of a glyph
+ To understand what these metrics mean, here is a useful link:
+ http://freetype.sourceforge.net/freetype2/docs/tutorial/step2.html
+ */
+extern DECLSPEC int SDLCALL TTF_GlyphMetrics(TTF_Font *font, Uint16 ch,
+ int *minx, int *maxx,
+ int *miny, int *maxy, int *advance);
+
+/* Get the dimensions of a rendered string of text */
+extern DECLSPEC int SDLCALL TTF_SizeText(TTF_Font *font, const char *text, int *w, int *h);
+extern DECLSPEC int SDLCALL TTF_SizeUTF8(TTF_Font *font, const char *text, int *w, int *h);
+extern DECLSPEC int SDLCALL TTF_SizeUNICODE(TTF_Font *font, const Uint16 *text, int *w, int *h);
+
+/* Create an 8-bit palettized surface and render the given text at
+ fast quality with the given font and color. The 0 pixel is the
+ colorkey, giving a transparent background, and the 1 pixel is set
+ to the text color.
+ This function returns the new surface, or NULL if there was an error.
+*/
+extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderText_Solid(TTF_Font *font,
+ const char *text, SDL_Color fg);
+extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderUTF8_Solid(TTF_Font *font,
+ const char *text, SDL_Color fg);
+extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderUNICODE_Solid(TTF_Font *font,
+ const Uint16 *text, SDL_Color fg);
+
+/* Create an 8-bit palettized surface and render the given glyph at
+ fast quality with the given font and color. The 0 pixel is the
+ colorkey, giving a transparent background, and the 1 pixel is set
+ to the text color. The glyph is rendered without any padding or
+ centering in the X direction, and aligned normally in the Y direction.
+ This function returns the new surface, or NULL if there was an error.
+*/
+extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderGlyph_Solid(TTF_Font *font,
+ Uint16 ch, SDL_Color fg);
+
+/* Create an 8-bit palettized surface and render the given text at
+ high quality with the given font and colors. The 0 pixel is background,
+ while other pixels have varying degrees of the foreground color.
+ This function returns the new surface, or NULL if there was an error.
+*/
+extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderText_Shaded(TTF_Font *font,
+ const char *text, SDL_Color fg, SDL_Color bg);
+extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderUTF8_Shaded(TTF_Font *font,
+ const char *text, SDL_Color fg, SDL_Color bg);
+extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderUNICODE_Shaded(TTF_Font *font,
+ const Uint16 *text, SDL_Color fg, SDL_Color bg);
+
+/* Create an 8-bit palettized surface and render the given glyph at
+ high quality with the given font and colors. The 0 pixel is background,
+ while other pixels have varying degrees of the foreground color.
+ The glyph is rendered without any padding or centering in the X
+ direction, and aligned normally in the Y direction.
+ This function returns the new surface, or NULL if there was an error.
+*/
+extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderGlyph_Shaded(TTF_Font *font,
+ Uint16 ch, SDL_Color fg, SDL_Color bg);
+
+/* Create a 32-bit ARGB surface and render the given text at high quality,
+ using alpha blending to dither the font with the given color.
+ This function returns the new surface, or NULL if there was an error.
+*/
+extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderText_Blended(TTF_Font *font,
+ const char *text, SDL_Color fg);
+extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderUTF8_Blended(TTF_Font *font,
+ const char *text, SDL_Color fg);
+extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderUNICODE_Blended(TTF_Font *font,
+ const Uint16 *text, SDL_Color fg);
+
+
+/* Create a 32-bit ARGB surface and render the given text at high quality,
+ using alpha blending to dither the font with the given color.
+ Text is wrapped to multiple lines on line endings and on word boundaries
+ if it extends beyond wrapLength in pixels.
+ This function returns the new surface, or NULL if there was an error.
+*/
+extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderText_Blended_Wrapped(TTF_Font *font,
+ const char *text, SDL_Color fg, Uint32 wrapLength);
+extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderUTF8_Blended_Wrapped(TTF_Font *font,
+ const char *text, SDL_Color fg, Uint32 wrapLength);
+extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderUNICODE_Blended_Wrapped(TTF_Font *font,
+ const Uint16 *text, SDL_Color fg, Uint32 wrapLength);
+
+/* Create a 32-bit ARGB surface and render the given glyph at high quality,
+ using alpha blending to dither the font with the given color.
+ The glyph is rendered without any padding or centering in the X
+ direction, and aligned normally in the Y direction.
+ This function returns the new surface, or NULL if there was an error.
+*/
+extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderGlyph_Blended(TTF_Font *font,
+ Uint16 ch, SDL_Color fg);
+
+/* For compatibility with previous versions, here are the old functions */
+#define TTF_RenderText(font, text, fg, bg) \
+ TTF_RenderText_Shaded(font, text, fg, bg)
+#define TTF_RenderUTF8(font, text, fg, bg) \
+ TTF_RenderUTF8_Shaded(font, text, fg, bg)
+#define TTF_RenderUNICODE(font, text, fg, bg) \
+ TTF_RenderUNICODE_Shaded(font, text, fg, bg)
+
+/* Close an opened font file */
+extern DECLSPEC void SDLCALL TTF_CloseFont(TTF_Font *font);
+
+/* De-initialize the TTF engine */
+extern DECLSPEC void SDLCALL TTF_Quit(void);
+
+/* Check if the TTF engine is initialized */
+extern DECLSPEC int SDLCALL TTF_WasInit(void);
+
+/* Get the kerning size of two glyphs indices */
+/* DEPRECATED: this function requires FreeType font indexes, not glyphs,
+ by accident, which we don't expose through this API, so it could give
+ wildly incorrect results, especially with non-ASCII values.
+ Going forward, please use TTF_GetFontKerningSizeGlyphs() instead, which
+ does what you probably expected this function to do. */
+extern DECLSPEC int TTF_GetFontKerningSize(TTF_Font *font, int prev_index, int index) SDL_DEPRECATED;
+
+/* Get the kerning size of two glyphs */
+extern DECLSPEC int TTF_GetFontKerningSizeGlyphs(TTF_Font *font, Uint16 previous_ch, Uint16 ch);
+
+/* We'll use SDL for reporting errors */
+#define TTF_SetError SDL_SetError
+#define TTF_GetError SDL_GetError
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_TTF_H_ */
+
+/* vi: set ts=4 sw=4 expandtab: */

File Metadata

Mime Type
text/x-diff
Expires
Sat, May 16, 8:21 PM (1 d, 15 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
63547
Default Alt Text
(95 KB)

Event Timeline