@@ -16,15 +16,21 @@ LINK_FLAGS += $(DGL_LIBS) | |||||
OBJS = \ | OBJS = \ | ||||
src/App.cpp.o \ | src/App.cpp.o \ | ||||
src/Geometry.cpp.o \ | |||||
src/Image.cpp.o \ | src/Image.cpp.o \ | ||||
src/ImageAboutWindow.cpp.o \ | src/ImageAboutWindow.cpp.o \ | ||||
src/ImageButton.cpp.o \ | src/ImageButton.cpp.o \ | ||||
src/ImageKnob.cpp.o \ | src/ImageKnob.cpp.o \ | ||||
src/ImageSlider.cpp.o \ | src/ImageSlider.cpp.o \ | ||||
src/Geometry.cpp.o \ | |||||
src/Widget.cpp.o \ | src/Widget.cpp.o \ | ||||
src/Window.cpp.o | src/Window.cpp.o | ||||
# freetype-gl | |||||
OBJS += \ | |||||
src/freetype-gl/texture-atlas.c.o \ | |||||
src/freetype-gl/texture-font.c.o \ | |||||
src/freetype-gl/vector.c.o | |||||
ifeq ($(MACOS),true) | ifeq ($(MACOS),true) | ||||
OBJS += src/pugl/pugl_osx_extended.m.o | OBJS += src/pugl/pugl_osx_extended.m.o | ||||
endif | endif | ||||
@@ -53,6 +59,9 @@ all: $(TARGET) | |||||
# -------------------------------------------------------------- | # -------------------------------------------------------------- | ||||
%.c.o: %.c | |||||
$(CC) $< $(BUILD_C_FLAGS) -c -o $@ | |||||
%.cpp.o: %.cpp | %.cpp.o: %.cpp | ||||
$(CXX) $< $(BUILD_CXX_FLAGS) -c -o $@ | $(CXX) $< $(BUILD_CXX_FLAGS) -c -o $@ | ||||
@@ -0,0 +1,241 @@ | |||||
/* this macro is used to define an error */ | |||||
#define FT_ERRORDEF_( e, v, s ) \ | |||||
FT_ERRORDEF( FT_ERR_CAT( FT_ERR_PREFIX, e ), v + FT_ERR_BASE, s ) | |||||
/* this is only used for <module>_Err_Ok, which must be 0! */ | |||||
#define FT_NOERRORDEF_( e, v, s ) \ | |||||
FT_ERRORDEF( FT_ERR_CAT( FT_ERR_PREFIX, e ), v, s ) | |||||
FT_ERROR_START_LIST | |||||
/*******************************************************************/ | |||||
/*******************************************************************/ | |||||
/***** *****/ | |||||
/***** LIST OF ERROR CODES/MESSAGES *****/ | |||||
/***** *****/ | |||||
/*******************************************************************/ | |||||
/*******************************************************************/ | |||||
/* You need to define both FT_ERRORDEF_ and FT_NOERRORDEF_ before */ | |||||
/* including this file. */ | |||||
/* generic errors */ | |||||
FT_NOERRORDEF_( Ok, 0x00, \ | |||||
"no error" ) | |||||
FT_ERRORDEF_( Cannot_Open_Resource, 0x01, \ | |||||
"cannot open resource" ) | |||||
FT_ERRORDEF_( Unknown_File_Format, 0x02, \ | |||||
"unknown file format" ) | |||||
FT_ERRORDEF_( Invalid_File_Format, 0x03, \ | |||||
"broken file" ) | |||||
FT_ERRORDEF_( Invalid_Version, 0x04, \ | |||||
"invalid FreeType version" ) | |||||
FT_ERRORDEF_( Lower_Module_Version, 0x05, \ | |||||
"module version is too low" ) | |||||
FT_ERRORDEF_( Invalid_Argument, 0x06, \ | |||||
"invalid argument" ) | |||||
FT_ERRORDEF_( Unimplemented_Feature, 0x07, \ | |||||
"unimplemented feature" ) | |||||
FT_ERRORDEF_( Invalid_Table, 0x08, \ | |||||
"broken table" ) | |||||
FT_ERRORDEF_( Invalid_Offset, 0x09, \ | |||||
"broken offset within table" ) | |||||
FT_ERRORDEF_( Array_Too_Large, 0x0A, \ | |||||
"array allocation size too large" ) | |||||
FT_ERRORDEF_( Missing_Module, 0x0B, \ | |||||
"missing module" ) | |||||
FT_ERRORDEF_( Missing_Property, 0x0C, \ | |||||
"missing property" ) | |||||
/* glyph/character errors */ | |||||
FT_ERRORDEF_( Invalid_Glyph_Index, 0x10, \ | |||||
"invalid glyph index" ) | |||||
FT_ERRORDEF_( Invalid_Character_Code, 0x11, \ | |||||
"invalid character code" ) | |||||
FT_ERRORDEF_( Invalid_Glyph_Format, 0x12, \ | |||||
"unsupported glyph image format" ) | |||||
FT_ERRORDEF_( Cannot_Render_Glyph, 0x13, \ | |||||
"cannot render this glyph format" ) | |||||
FT_ERRORDEF_( Invalid_Outline, 0x14, \ | |||||
"invalid outline" ) | |||||
FT_ERRORDEF_( Invalid_Composite, 0x15, \ | |||||
"invalid composite glyph" ) | |||||
FT_ERRORDEF_( Too_Many_Hints, 0x16, \ | |||||
"too many hints" ) | |||||
FT_ERRORDEF_( Invalid_Pixel_Size, 0x17, \ | |||||
"invalid pixel size" ) | |||||
/* handle errors */ | |||||
FT_ERRORDEF_( Invalid_Handle, 0x20, \ | |||||
"invalid object handle" ) | |||||
FT_ERRORDEF_( Invalid_Library_Handle, 0x21, \ | |||||
"invalid library handle" ) | |||||
FT_ERRORDEF_( Invalid_Driver_Handle, 0x22, \ | |||||
"invalid module handle" ) | |||||
FT_ERRORDEF_( Invalid_Face_Handle, 0x23, \ | |||||
"invalid face handle" ) | |||||
FT_ERRORDEF_( Invalid_Size_Handle, 0x24, \ | |||||
"invalid size handle" ) | |||||
FT_ERRORDEF_( Invalid_Slot_Handle, 0x25, \ | |||||
"invalid glyph slot handle" ) | |||||
FT_ERRORDEF_( Invalid_CharMap_Handle, 0x26, \ | |||||
"invalid charmap handle" ) | |||||
FT_ERRORDEF_( Invalid_Cache_Handle, 0x27, \ | |||||
"invalid cache manager handle" ) | |||||
FT_ERRORDEF_( Invalid_Stream_Handle, 0x28, \ | |||||
"invalid stream handle" ) | |||||
/* driver errors */ | |||||
FT_ERRORDEF_( Too_Many_Drivers, 0x30, \ | |||||
"too many modules" ) | |||||
FT_ERRORDEF_( Too_Many_Extensions, 0x31, \ | |||||
"too many extensions" ) | |||||
/* memory errors */ | |||||
FT_ERRORDEF_( Out_Of_Memory, 0x40, \ | |||||
"out of memory" ) | |||||
FT_ERRORDEF_( Unlisted_Object, 0x41, \ | |||||
"unlisted object" ) | |||||
/* stream errors */ | |||||
FT_ERRORDEF_( Cannot_Open_Stream, 0x51, \ | |||||
"cannot open stream" ) | |||||
FT_ERRORDEF_( Invalid_Stream_Seek, 0x52, \ | |||||
"invalid stream seek" ) | |||||
FT_ERRORDEF_( Invalid_Stream_Skip, 0x53, \ | |||||
"invalid stream skip" ) | |||||
FT_ERRORDEF_( Invalid_Stream_Read, 0x54, \ | |||||
"invalid stream read" ) | |||||
FT_ERRORDEF_( Invalid_Stream_Operation, 0x55, \ | |||||
"invalid stream operation" ) | |||||
FT_ERRORDEF_( Invalid_Frame_Operation, 0x56, \ | |||||
"invalid frame operation" ) | |||||
FT_ERRORDEF_( Nested_Frame_Access, 0x57, \ | |||||
"nested frame access" ) | |||||
FT_ERRORDEF_( Invalid_Frame_Read, 0x58, \ | |||||
"invalid frame read" ) | |||||
/* raster errors */ | |||||
FT_ERRORDEF_( Raster_Uninitialized, 0x60, \ | |||||
"raster uninitialized" ) | |||||
FT_ERRORDEF_( Raster_Corrupted, 0x61, \ | |||||
"raster corrupted" ) | |||||
FT_ERRORDEF_( Raster_Overflow, 0x62, \ | |||||
"raster overflow" ) | |||||
FT_ERRORDEF_( Raster_Negative_Height, 0x63, \ | |||||
"negative height while rastering" ) | |||||
/* cache errors */ | |||||
FT_ERRORDEF_( Too_Many_Caches, 0x70, \ | |||||
"too many registered caches" ) | |||||
/* TrueType and SFNT errors */ | |||||
FT_ERRORDEF_( Invalid_Opcode, 0x80, \ | |||||
"invalid opcode" ) | |||||
FT_ERRORDEF_( Too_Few_Arguments, 0x81, \ | |||||
"too few arguments" ) | |||||
FT_ERRORDEF_( Stack_Overflow, 0x82, \ | |||||
"stack overflow" ) | |||||
FT_ERRORDEF_( Code_Overflow, 0x83, \ | |||||
"code overflow" ) | |||||
FT_ERRORDEF_( Bad_Argument, 0x84, \ | |||||
"bad argument" ) | |||||
FT_ERRORDEF_( Divide_By_Zero, 0x85, \ | |||||
"division by zero" ) | |||||
FT_ERRORDEF_( Invalid_Reference, 0x86, \ | |||||
"invalid reference" ) | |||||
FT_ERRORDEF_( Debug_OpCode, 0x87, \ | |||||
"found debug opcode" ) | |||||
FT_ERRORDEF_( ENDF_In_Exec_Stream, 0x88, \ | |||||
"found ENDF opcode in execution stream" ) | |||||
FT_ERRORDEF_( Nested_DEFS, 0x89, \ | |||||
"nested DEFS" ) | |||||
FT_ERRORDEF_( Invalid_CodeRange, 0x8A, \ | |||||
"invalid code range" ) | |||||
FT_ERRORDEF_( Execution_Too_Long, 0x8B, \ | |||||
"execution context too long" ) | |||||
FT_ERRORDEF_( Too_Many_Function_Defs, 0x8C, \ | |||||
"too many function definitions" ) | |||||
FT_ERRORDEF_( Too_Many_Instruction_Defs, 0x8D, \ | |||||
"too many instruction definitions" ) | |||||
FT_ERRORDEF_( Table_Missing, 0x8E, \ | |||||
"SFNT font table missing" ) | |||||
FT_ERRORDEF_( Horiz_Header_Missing, 0x8F, \ | |||||
"horizontal header (hhea) table missing" ) | |||||
FT_ERRORDEF_( Locations_Missing, 0x90, \ | |||||
"locations (loca) table missing" ) | |||||
FT_ERRORDEF_( Name_Table_Missing, 0x91, \ | |||||
"name table missing" ) | |||||
FT_ERRORDEF_( CMap_Table_Missing, 0x92, \ | |||||
"character map (cmap) table missing" ) | |||||
FT_ERRORDEF_( Hmtx_Table_Missing, 0x93, \ | |||||
"horizontal metrics (hmtx) table missing" ) | |||||
FT_ERRORDEF_( Post_Table_Missing, 0x94, \ | |||||
"PostScript (post) table missing" ) | |||||
FT_ERRORDEF_( Invalid_Horiz_Metrics, 0x95, \ | |||||
"invalid horizontal metrics" ) | |||||
FT_ERRORDEF_( Invalid_CharMap_Format, 0x96, \ | |||||
"invalid character map (cmap) format" ) | |||||
FT_ERRORDEF_( Invalid_PPem, 0x97, \ | |||||
"invalid ppem value" ) | |||||
FT_ERRORDEF_( Invalid_Vert_Metrics, 0x98, \ | |||||
"invalid vertical metrics" ) | |||||
FT_ERRORDEF_( Could_Not_Find_Context, 0x99, \ | |||||
"could not find context" ) | |||||
FT_ERRORDEF_( Invalid_Post_Table_Format, 0x9A, \ | |||||
"invalid PostScript (post) table format" ) | |||||
FT_ERRORDEF_( Invalid_Post_Table, 0x9B, \ | |||||
"invalid PostScript (post) table" ) | |||||
/* CFF, CID, and Type 1 errors */ | |||||
FT_ERRORDEF_( Syntax_Error, 0xA0, \ | |||||
"opcode syntax error" ) | |||||
FT_ERRORDEF_( Stack_Underflow, 0xA1, \ | |||||
"argument stack underflow" ) | |||||
FT_ERRORDEF_( Ignore, 0xA2, \ | |||||
"ignore" ) | |||||
FT_ERRORDEF_( No_Unicode_Glyph_Name, 0xA3, \ | |||||
"no Unicode glyph name found" ) | |||||
FT_ERRORDEF_( Glyph_Too_Big, 0xA4, \ | |||||
"glyph to big for hinting" ) | |||||
/* BDF errors */ | |||||
FT_ERRORDEF_( Missing_Startfont_Field, 0xB0, \ | |||||
"`STARTFONT' field missing" ) | |||||
FT_ERRORDEF_( Missing_Font_Field, 0xB1, \ | |||||
"`FONT' field missing" ) | |||||
FT_ERRORDEF_( Missing_Size_Field, 0xB2, \ | |||||
"`SIZE' field missing" ) | |||||
FT_ERRORDEF_( Missing_Fontboundingbox_Field, 0xB3, \ | |||||
"`FONTBOUNDINGBOX' field missing" ) | |||||
FT_ERRORDEF_( Missing_Chars_Field, 0xB4, \ | |||||
"`CHARS' field missing" ) | |||||
FT_ERRORDEF_( Missing_Startchar_Field, 0xB5, \ | |||||
"`STARTCHAR' field missing" ) | |||||
FT_ERRORDEF_( Missing_Encoding_Field, 0xB6, \ | |||||
"`ENCODING' field missing" ) | |||||
FT_ERRORDEF_( Missing_Bbx_Field, 0xB7, \ | |||||
"`BBX' field missing" ) | |||||
FT_ERRORDEF_( Bbx_Too_Big, 0xB8, \ | |||||
"`BBX' too big" ) | |||||
FT_ERRORDEF_( Corrupted_Font_Header, 0xB9, \ | |||||
"Font header corrupted or missing fields" ) | |||||
FT_ERRORDEF_( Corrupted_Font_Glyphs, 0xBA, \ | |||||
"Font glyphs corrupted or missing fields" ) | |||||
/* END */ | |||||
FT_ERROR_END_LIST |
@@ -0,0 +1,44 @@ | |||||
/* ============================================================================ | |||||
* Freetype GL - A C OpenGL Freetype engine | |||||
* Platform: Any | |||||
* WWW: http://code.google.com/p/freetype-gl/ | |||||
* ---------------------------------------------------------------------------- | |||||
* Copyright 2011,2012 Nicolas P. Rougier. All rights reserved. | |||||
* | |||||
* Redistribution and use in source and binary forms, with or without | |||||
* modification, are permitted provided that the following conditions are met: | |||||
* | |||||
* 1. Redistributions of source code must retain the above copyright notice, | |||||
* this list of conditions and the following disclaimer. | |||||
* | |||||
* 2. Redistributions in binary form must reproduce the above copyright | |||||
* notice, this list of conditions and the following disclaimer in the | |||||
* documentation and/or other materials provided with the distribution. | |||||
* | |||||
* THIS SOFTWARE IS PROVIDED BY NICOLAS P. ROUGIER ''AS IS'' AND ANY EXPRESS OR | |||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | |||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO | |||||
* EVENT SHALL NICOLAS P. ROUGIER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, | |||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||||
* | |||||
* The views and conclusions contained in the software and documentation are | |||||
* those of the authors and should not be interpreted as representing official | |||||
* policies, either expressed or implied, of Nicolas P. Rougier. | |||||
* ============================================================================ | |||||
*/ | |||||
#ifndef __FREETYPE_GL_H__ | |||||
#define __FREETYPE_GL_H__ | |||||
/* Mandatory */ | |||||
#include "opengl.h" | |||||
#include "vec234.h" | |||||
#include "vector.h" | |||||
#include "texture-atlas.h" | |||||
#include "texture-font.h" | |||||
#endif /* FREETYPE_GL_H */ |
@@ -0,0 +1,37 @@ | |||||
/* | |||||
* DISTRHO Plugin Framework (DPF) | |||||
* Copyright (C) 2012-2014 Filipe Coelho <falktx@falktx.com> | |||||
* | |||||
* Permission to use, copy, modify, and/or distribute this software for any purpose with | |||||
* or without fee is hereby granted, provided that the above copyright notice and this | |||||
* permission notice appear in all copies. | |||||
* | |||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD | |||||
* TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN | |||||
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL | |||||
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER | |||||
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | |||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |||||
*/ | |||||
#include "../../../distrho/src/DistrhoDefines.h" | |||||
/* GL includes */ | |||||
#ifdef DISTRHO_OS_MAC | |||||
# include <OpenGL/gl.h> | |||||
#else | |||||
# include <GL/gl.h> | |||||
#endif | |||||
/* missing GL defines */ | |||||
#if defined(GL_BGR_EXT) && ! defined(GL_BGR) | |||||
# define GL_BGR GL_BGR_EXT | |||||
#endif | |||||
#if defined(GL_BGRA_EXT) && ! defined(GL_BGRA) | |||||
# define GL_BGRA GL_BGRA_EXT | |||||
#endif | |||||
#ifndef GL_CLAMP_TO_BORDER | |||||
# define GL_CLAMP_TO_BORDER 0x812D | |||||
#endif |
@@ -0,0 +1,71 @@ | |||||
/* ============================================================================ | |||||
* Freetype GL - A C OpenGL Freetype engine | |||||
* Platform: Any | |||||
* WWW: http://code.google.com/p/freetype-gl/ | |||||
* ---------------------------------------------------------------------------- | |||||
* Copyright 2011,2012 Nicolas P. Rougier. All rights reserved. | |||||
* | |||||
* Redistribution and use in source and binary forms, with or without | |||||
* modification, are permitted provided that the following conditions are met: | |||||
* | |||||
* 1. Redistributions of source code must retain the above copyright notice, | |||||
* this list of conditions and the following disclaimer. | |||||
* | |||||
* 2. Redistributions in binary form must reproduce the above copyright | |||||
* notice, this list of conditions and the following disclaimer in the | |||||
* documentation and/or other materials provided with the distribution. | |||||
* | |||||
* THIS SOFTWARE IS PROVIDED BY NICOLAS P. ROUGIER ''AS IS'' AND ANY EXPRESS OR | |||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | |||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO | |||||
* EVENT SHALL NICOLAS P. ROUGIER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, | |||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||||
* | |||||
* The views and conclusions contained in the software and documentation are | |||||
* those of the authors and should not be interpreted as representing official | |||||
* policies, either expressed or implied, of Nicolas P. Rougier. | |||||
* ============================================================================ | |||||
*/ | |||||
#ifndef __PLATFORM_H__ | |||||
#define __PLATFORM_H__ | |||||
#include <stdlib.h> | |||||
//------------------------------------------------- | |||||
// stdint.h is not available on VS2008 or lower | |||||
//------------------------------------------------- | |||||
#ifdef _MSC_VER | |||||
typedef __int32 int32_t; | |||||
typedef unsigned __int32 uint32_t; | |||||
typedef __int64 int64_t; | |||||
typedef unsigned __int64 uint64_t; | |||||
#else | |||||
#include <stdint.h> | |||||
#endif // _MSC_VER | |||||
#ifdef __cplusplus | |||||
extern "C" { | |||||
#endif | |||||
#ifdef __APPLE__ | |||||
/* strndup() was only added in OSX lion */ | |||||
char * strndup( const char *s1, size_t n); | |||||
#elif defined(_WIN32) || defined(_WIN64) | |||||
/* does not exist on windows */ | |||||
char * strndup( const char *s1, size_t n); | |||||
# if !defined(_MSC_VER) || _MSC_VER < 1800 | |||||
double round(double v); | |||||
# endif // _MSC_VER | |||||
# pragma warning (disable: 4244) // suspend warnings | |||||
#endif // _WIN32 || _WIN64 | |||||
#ifdef __cplusplus | |||||
} | |||||
#endif // __cplusplus | |||||
#endif /* __PLATFORM_H__ */ |
@@ -0,0 +1,345 @@ | |||||
/* ============================================================================ | |||||
* Freetype GL - A C OpenGL Freetype engine | |||||
* Platform: Any | |||||
* WWW: http://code.google.com/p/freetype-gl/ | |||||
* ---------------------------------------------------------------------------- | |||||
* Copyright 2011,2012 Nicolas P. Rougier. All rights reserved. | |||||
* | |||||
* Redistribution and use in source and binary forms, with or without | |||||
* modification, are permitted provided that the following conditions are met: | |||||
* | |||||
* 1. Redistributions of source code must retain the above copyright notice, | |||||
* this list of conditions and the following disclaimer. | |||||
* | |||||
* 2. Redistributions in binary form must reproduce the above copyright | |||||
* notice, this list of conditions and the following disclaimer in the | |||||
* documentation and/or other materials provided with the distribution. | |||||
* | |||||
* THIS SOFTWARE IS PROVIDED BY NICOLAS P. ROUGIER ''AS IS'' AND ANY EXPRESS OR | |||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | |||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO | |||||
* EVENT SHALL NICOLAS P. ROUGIER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, | |||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||||
* | |||||
* The views and conclusions contained in the software and documentation are | |||||
* those of the authors and should not be interpreted as representing official | |||||
* policies, either expressed or implied, of Nicolas P. Rougier. | |||||
* ============================================================================ | |||||
*/ | |||||
#include <stdio.h> | |||||
#include <stdlib.h> | |||||
#include <string.h> | |||||
#include <assert.h> | |||||
#include <limits.h> | |||||
#include "opengl.h" | |||||
#include "texture-atlas.h" | |||||
// ------------------------------------------------------ texture_atlas_new --- | |||||
texture_atlas_t * | |||||
texture_atlas_new( const size_t width, | |||||
const size_t height, | |||||
const size_t depth ) | |||||
{ | |||||
texture_atlas_t *self = (texture_atlas_t *) malloc( sizeof(texture_atlas_t) ); | |||||
// We want a one pixel border around the whole atlas to avoid any artefact when | |||||
// sampling texture | |||||
ivec3 node = {{1,1,width-2}}; | |||||
assert( (depth == 1) || (depth == 3) || (depth == 4) ); | |||||
if( self == NULL) | |||||
{ | |||||
fprintf( stderr, | |||||
"line %d: No more memory for allocating data\n", __LINE__ ); | |||||
exit( EXIT_FAILURE ); | |||||
} | |||||
self->nodes = vector_new( sizeof(ivec3) ); | |||||
self->used = 0; | |||||
self->width = width; | |||||
self->height = height; | |||||
self->depth = depth; | |||||
self->id = 0; | |||||
vector_push_back( self->nodes, &node ); | |||||
self->data = (unsigned char *) | |||||
calloc( width*height*depth, sizeof(unsigned char) ); | |||||
if( self->data == NULL) | |||||
{ | |||||
fprintf( stderr, | |||||
"line %d: No more memory for allocating data\n", __LINE__ ); | |||||
exit( EXIT_FAILURE ); | |||||
} | |||||
return self; | |||||
} | |||||
// --------------------------------------------------- texture_atlas_delete --- | |||||
void | |||||
texture_atlas_delete( texture_atlas_t *self ) | |||||
{ | |||||
assert( self ); | |||||
vector_delete( self->nodes ); | |||||
if( self->data ) | |||||
{ | |||||
free( self->data ); | |||||
} | |||||
if( self->id ) | |||||
{ | |||||
glDeleteTextures( 1, &self->id ); | |||||
} | |||||
free( self ); | |||||
} | |||||
// ----------------------------------------------- texture_atlas_set_region --- | |||||
void | |||||
texture_atlas_set_region( texture_atlas_t * self, | |||||
const size_t x, | |||||
const size_t y, | |||||
const size_t width, | |||||
const size_t height, | |||||
const unsigned char * data, | |||||
const size_t stride ) | |||||
{ | |||||
size_t i; | |||||
size_t depth; | |||||
size_t charsize; | |||||
assert( self ); | |||||
assert( x > 0); | |||||
assert( y > 0); | |||||
assert( x < (self->width-1)); | |||||
assert( (x + width) <= (self->width-1)); | |||||
assert( y < (self->height-1)); | |||||
assert( (y + height) <= (self->height-1)); | |||||
depth = self->depth; | |||||
charsize = sizeof(char); | |||||
for( i=0; i<height; ++i ) | |||||
{ | |||||
memcpy( self->data+((y+i)*self->width + x ) * charsize * depth, | |||||
data + (i*stride) * charsize, width * charsize * depth ); | |||||
} | |||||
} | |||||
// ------------------------------------------------------ texture_atlas_fit --- | |||||
int | |||||
texture_atlas_fit( texture_atlas_t * self, | |||||
const size_t index, | |||||
const size_t width, | |||||
const size_t height ) | |||||
{ | |||||
ivec3 *node; | |||||
int x, y, width_left; | |||||
size_t i; | |||||
assert( self ); | |||||
node = (ivec3 *) (vector_get( self->nodes, index )); | |||||
x = node->x; | |||||
y = node->y; | |||||
width_left = width; | |||||
i = index; | |||||
if ( (x + width) > (self->width-1) ) | |||||
{ | |||||
return -1; | |||||
} | |||||
y = node->y; | |||||
while( width_left > 0 ) | |||||
{ | |||||
node = (ivec3 *) (vector_get( self->nodes, i )); | |||||
if( node->y > y ) | |||||
{ | |||||
y = node->y; | |||||
} | |||||
if( (y + height) > (self->height-1) ) | |||||
{ | |||||
return -1; | |||||
} | |||||
width_left -= node->z; | |||||
++i; | |||||
} | |||||
return y; | |||||
} | |||||
// ---------------------------------------------------- texture_atlas_merge --- | |||||
void | |||||
texture_atlas_merge( texture_atlas_t * self ) | |||||
{ | |||||
ivec3 *node, *next; | |||||
size_t i; | |||||
assert( self ); | |||||
for( i=0; i< self->nodes->size-1; ++i ) | |||||
{ | |||||
node = (ivec3 *) (vector_get( self->nodes, i )); | |||||
next = (ivec3 *) (vector_get( self->nodes, i+1 )); | |||||
if( node->y == next->y ) | |||||
{ | |||||
node->z += next->z; | |||||
vector_erase( self->nodes, i+1 ); | |||||
--i; | |||||
} | |||||
} | |||||
} | |||||
// ----------------------------------------------- texture_atlas_get_region --- | |||||
ivec4 | |||||
texture_atlas_get_region( texture_atlas_t * self, | |||||
const size_t width, | |||||
const size_t height ) | |||||
{ | |||||
int y, best_height, best_width, best_index; | |||||
ivec3 *node, *prev; | |||||
ivec4 region = {{0,0,width,height}}; | |||||
size_t i; | |||||
assert( self ); | |||||
best_height = INT_MAX; | |||||
best_index = -1; | |||||
best_width = INT_MAX; | |||||
for( i=0; i<self->nodes->size; ++i ) | |||||
{ | |||||
y = texture_atlas_fit( self, i, width, height ); | |||||
if( y >= 0 ) | |||||
{ | |||||
node = (ivec3 *) vector_get( self->nodes, i ); | |||||
if( ( (y + height) < best_height ) || | |||||
( ((y + height) == best_height) && (node->z < best_width)) ) | |||||
{ | |||||
best_height = y + height; | |||||
best_index = i; | |||||
best_width = node->z; | |||||
region.x = node->x; | |||||
region.y = y; | |||||
} | |||||
} | |||||
} | |||||
if( best_index == -1 ) | |||||
{ | |||||
region.x = -1; | |||||
region.y = -1; | |||||
region.width = 0; | |||||
region.height = 0; | |||||
return region; | |||||
} | |||||
node = (ivec3 *) malloc( sizeof(ivec3) ); | |||||
if( node == NULL) | |||||
{ | |||||
fprintf( stderr, | |||||
"line %d: No more memory for allocating data\n", __LINE__ ); | |||||
exit( EXIT_FAILURE ); | |||||
} | |||||
node->x = region.x; | |||||
node->y = region.y + height; | |||||
node->z = width; | |||||
vector_insert( self->nodes, best_index, node ); | |||||
free( node ); | |||||
for(i = best_index+1; i < self->nodes->size; ++i) | |||||
{ | |||||
node = (ivec3 *) vector_get( self->nodes, i ); | |||||
prev = (ivec3 *) vector_get( self->nodes, i-1 ); | |||||
if (node->x < (prev->x + prev->z) ) | |||||
{ | |||||
int shrink = prev->x + prev->z - node->x; | |||||
node->x += shrink; | |||||
node->z -= shrink; | |||||
if (node->z <= 0) | |||||
{ | |||||
vector_erase( self->nodes, i ); | |||||
--i; | |||||
} | |||||
else | |||||
{ | |||||
break; | |||||
} | |||||
} | |||||
else | |||||
{ | |||||
break; | |||||
} | |||||
} | |||||
texture_atlas_merge( self ); | |||||
self->used += width * height; | |||||
return region; | |||||
} | |||||
// ---------------------------------------------------- texture_atlas_clear --- | |||||
void | |||||
texture_atlas_clear( texture_atlas_t * self ) | |||||
{ | |||||
ivec3 node = {{1,1,1}}; | |||||
assert( self ); | |||||
assert( self->data ); | |||||
vector_clear( self->nodes ); | |||||
self->used = 0; | |||||
// We want a one pixel border around the whole atlas to avoid any artefact when | |||||
// sampling texture | |||||
node.z = self->width-2; | |||||
vector_push_back( self->nodes, &node ); | |||||
memset( self->data, 0, self->width*self->height*self->depth ); | |||||
} | |||||
// --------------------------------------------------- texture_atlas_upload --- | |||||
void | |||||
texture_atlas_upload( texture_atlas_t * self ) | |||||
{ | |||||
assert( self ); | |||||
assert( self->data ); | |||||
if( !self->id ) | |||||
{ | |||||
glGenTextures( 1, &self->id ); | |||||
} | |||||
glBindTexture( GL_TEXTURE_2D, self->id ); | |||||
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE ); | |||||
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE ); | |||||
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); | |||||
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); | |||||
if( self->depth == 4 ) | |||||
{ | |||||
#ifdef GL_UNSIGNED_INT_8_8_8_8_REV | |||||
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, self->width, self->height, | |||||
0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, self->data ); | |||||
#else | |||||
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, self->width, self->height, | |||||
0, GL_RGBA, GL_UNSIGNED_BYTE, self->data ); | |||||
#endif | |||||
} | |||||
else if( self->depth == 3 ) | |||||
{ | |||||
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, self->width, self->height, | |||||
0, GL_RGB, GL_UNSIGNED_BYTE, self->data ); | |||||
} | |||||
else | |||||
{ | |||||
glTexImage2D( GL_TEXTURE_2D, 0, GL_RED, self->width, self->height, | |||||
0, GL_RED, GL_UNSIGNED_BYTE, self->data ); | |||||
} | |||||
} | |||||
@@ -0,0 +1,225 @@ | |||||
/* ============================================================================ | |||||
* Freetype GL - A C OpenGL Freetype engine | |||||
* Platform: Any | |||||
* WWW: http://code.google.com/p/freetype-gl/ | |||||
* ---------------------------------------------------------------------------- | |||||
* Copyright 2011,2012 Nicolas P. Rougier. All rights reserved. | |||||
* | |||||
* Redistribution and use in source and binary forms, with or without | |||||
* modification, are permitted provided that the following conditions are met: | |||||
* | |||||
* 1. Redistributions of source code must retain the above copyright notice, | |||||
* this list of conditions and the following disclaimer. | |||||
* | |||||
* 2. Redistributions in binary form must reproduce the above copyright | |||||
* notice, this list of conditions and the following disclaimer in the | |||||
* documentation and/or other materials provided with the distribution. | |||||
* | |||||
* THIS SOFTWARE IS PROVIDED BY NICOLAS P. ROUGIER ''AS IS'' AND ANY EXPRESS OR | |||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | |||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO | |||||
* EVENT SHALL NICOLAS P. ROUGIER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, | |||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||||
* | |||||
* The views and conclusions contained in the software and documentation are | |||||
* those of the authors and should not be interpreted as representing official | |||||
* policies, either expressed or implied, of Nicolas P. Rougier. | |||||
* ============================================================================ | |||||
* | |||||
* This source is based on the article by Jukka Jylänki : | |||||
* "A Thousand Ways to Pack the Bin - A Practical Approach to | |||||
* Two-Dimensional Rectangle Bin Packing", February 27, 2010. | |||||
* | |||||
* More precisely, this is an implementation of the Skyline Bottom-Left | |||||
* algorithm based on C++ sources provided by Jukka Jylänki at: | |||||
* http://clb.demon.fi/files/RectangleBinPack/ | |||||
* | |||||
* ============================================================================ | |||||
*/ | |||||
#ifndef __TEXTURE_ATLAS_H__ | |||||
#define __TEXTURE_ATLAS_H__ | |||||
#include <stdlib.h> | |||||
#ifdef __cplusplus | |||||
extern "C" { | |||||
#endif | |||||
#include "vector.h" | |||||
#include "vec234.h" | |||||
/** | |||||
* @file texture-atlas.h | |||||
* @author Nicolas Rougier (Nicolas.Rougier@inria.fr) | |||||
* | |||||
* @defgroup texture-atlas Texture atlas | |||||
* | |||||
* A texture atlas is used to pack several small regions into a single texture. | |||||
* | |||||
* The actual implementation is based on the article by Jukka Jylänki : "A | |||||
* Thousand Ways to Pack the Bin - A Practical Approach to Two-Dimensional | |||||
* Rectangle Bin Packing", February 27, 2010. | |||||
* More precisely, this is an implementation of the Skyline Bottom-Left | |||||
* algorithm based on C++ sources provided by Jukka Jylänki at: | |||||
* http://clb.demon.fi/files/RectangleBinPack/ | |||||
* | |||||
* | |||||
* Example Usage: | |||||
* @code | |||||
* #include "texture-atlas.h" | |||||
* | |||||
* ... | |||||
* | |||||
* / Creates a new atlas of 512x512 with a depth of 1 | |||||
* texture_atlas_t * atlas = texture_atlas_new( 512, 512, 1 ); | |||||
* | |||||
* // Allocates a region of 20x20 | |||||
* ivec4 region = texture_atlas_get_region( atlas, 20, 20 ); | |||||
* | |||||
* // Fill region with some data | |||||
* texture_atlas_set_region( atlas, region.x, region.y, region.width, region.height, data, stride ) | |||||
* | |||||
* ... | |||||
* | |||||
* @endcode | |||||
* | |||||
* @{ | |||||
*/ | |||||
/** | |||||
* A texture atlas is used to pack several small regions into a single texture. | |||||
*/ | |||||
typedef struct texture_atlas_t | |||||
{ | |||||
/** | |||||
* Allocated nodes | |||||
*/ | |||||
vector_t * nodes; | |||||
/** | |||||
* Width (in pixels) of the underlying texture | |||||
*/ | |||||
size_t width; | |||||
/** | |||||
* Height (in pixels) of the underlying texture | |||||
*/ | |||||
size_t height; | |||||
/** | |||||
* Depth (in bytes) of the underlying texture | |||||
*/ | |||||
size_t depth; | |||||
/** | |||||
* Allocated surface size | |||||
*/ | |||||
size_t used; | |||||
/** | |||||
* Texture identity (OpenGL) | |||||
*/ | |||||
unsigned int id; | |||||
/** | |||||
* Atlas data | |||||
*/ | |||||
unsigned char * data; | |||||
} texture_atlas_t; | |||||
/** | |||||
* Creates a new empty texture atlas. | |||||
* | |||||
* @param width width of the atlas | |||||
* @param height height of the atlas | |||||
* @param depth bit depth of the atlas | |||||
* @return a new empty texture atlas. | |||||
* | |||||
*/ | |||||
texture_atlas_t * | |||||
texture_atlas_new( const size_t width, | |||||
const size_t height, | |||||
const size_t depth ); | |||||
/** | |||||
* Deletes a texture atlas. | |||||
* | |||||
* @param self a texture atlas structure | |||||
* | |||||
*/ | |||||
void | |||||
texture_atlas_delete( texture_atlas_t * self ); | |||||
/** | |||||
* Upload atlas to video memory. | |||||
* | |||||
* @param self a texture atlas structure | |||||
* | |||||
*/ | |||||
void | |||||
texture_atlas_upload( texture_atlas_t * self ); | |||||
/** | |||||
* Allocate a new region in the atlas. | |||||
* | |||||
* @param self a texture atlas structure | |||||
* @param width width of the region to allocate | |||||
* @param height height of the region to allocate | |||||
* @return Coordinates of the allocated region | |||||
* | |||||
*/ | |||||
ivec4 | |||||
texture_atlas_get_region( texture_atlas_t * self, | |||||
const size_t width, | |||||
const size_t height ); | |||||
/** | |||||
* Upload data to the specified atlas region. | |||||
* | |||||
* @param self a texture atlas structure | |||||
* @param x x coordinate the region | |||||
* @param y y coordinate the region | |||||
* @param width width of the region | |||||
* @param height height of the region | |||||
* @param data data to be uploaded into the specified region | |||||
* @param stride stride of the data | |||||
* | |||||
*/ | |||||
void | |||||
texture_atlas_set_region( texture_atlas_t * self, | |||||
const size_t x, | |||||
const size_t y, | |||||
const size_t width, | |||||
const size_t height, | |||||
const unsigned char *data, | |||||
const size_t stride ); | |||||
/** | |||||
* Remove all allocated regions from the atlas. | |||||
* | |||||
* @param self a texture atlas structure | |||||
*/ | |||||
void | |||||
texture_atlas_clear( texture_atlas_t * self ); | |||||
/** @} */ | |||||
#ifdef __cplusplus | |||||
} | |||||
#endif | |||||
#endif /* __TEXTURE_ATLAS_H__ */ |
@@ -0,0 +1,711 @@ | |||||
/* =========================================================================== | |||||
* Freetype GL - A C OpenGL Freetype engine | |||||
* Platform: Any | |||||
* WWW: http://code.google.com/p/freetype-gl/ | |||||
* ---------------------------------------------------------------------------- | |||||
* Copyright 2011,2012 Nicolas P. Rougier. All rights reserved. | |||||
* | |||||
* Redistribution and use in source and binary forms, with or without | |||||
* modification, are permitted provided that the following conditions are met: | |||||
* | |||||
* 1. Redistributions of source code must retain the above copyright notice, | |||||
* this list of conditions and the following disclaimer. | |||||
* | |||||
* 2. Redistributions in binary form must reproduce the above copyright | |||||
* notice, this list of conditions and the following disclaimer in the | |||||
* documentation and/or other materials provided with the distribution. | |||||
* | |||||
* THIS SOFTWARE IS PROVIDED BY NICOLAS P. ROUGIER ''AS IS'' AND ANY EXPRESS OR | |||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | |||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO | |||||
* EVENT SHALL NICOLAS P. ROUGIER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, | |||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||||
* | |||||
* The views and conclusions contained in the software and documentation are | |||||
* those of the authors and should not be interpreted as representing official | |||||
* policies, either expressed or implied, of Nicolas P. Rougier. | |||||
* ============================================================================ | |||||
*/ | |||||
#include "../freetype/FreeTypeAmalgam.c" | |||||
#include <stdint.h> | |||||
#include <stdlib.h> | |||||
#include <stdio.h> | |||||
#include <assert.h> | |||||
#include <math.h> | |||||
#include <wchar.h> | |||||
#include "texture-font.h" | |||||
#include "platform.h" | |||||
#define HRES 64 | |||||
#define HRESf 64.f | |||||
#define DPI 72 | |||||
#undef __FTERRORS_H__ | |||||
#define FT_ERRORDEF( e, v, s ) { e, s }, | |||||
#define FT_ERROR_START_LIST { | |||||
#define FT_ERROR_END_LIST { 0, 0 } }; | |||||
const struct { | |||||
int code; | |||||
const char* message; | |||||
} FT_Errors[] = | |||||
#include "freetype-errors.h" | |||||
// ------------------------------------------------- texture_font_load_face --- | |||||
static int | |||||
texture_font_load_face(texture_font_t *self, float size, | |||||
FT_Library *library, FT_Face *face) | |||||
{ | |||||
FT_Error error; | |||||
FT_Matrix matrix = { | |||||
(int)((1.0/HRES) * 0x10000L), | |||||
(int)((0.0) * 0x10000L), | |||||
(int)((0.0) * 0x10000L), | |||||
(int)((1.0) * 0x10000L)}; | |||||
assert(library); | |||||
assert(size); | |||||
/* Initialize library */ | |||||
error = FT_Init_FreeType(library); | |||||
if(error) { | |||||
fprintf(stderr, "FT_Error (0x%02x) : %s\n", | |||||
FT_Errors[error].code, FT_Errors[error].message); | |||||
return 0; | |||||
} | |||||
/* Load face */ | |||||
switch (self->location) { | |||||
case TEXTURE_FONT_FILE: | |||||
error = FT_New_Face(*library, self->filename, 0, face); | |||||
break; | |||||
case TEXTURE_FONT_MEMORY: | |||||
error = FT_New_Memory_Face(*library, | |||||
self->memory.base, self->memory.size, 0, face); | |||||
break; | |||||
} | |||||
if(error) { | |||||
fprintf(stderr, "FT_Error (line %d, code 0x%02x) : %s\n", | |||||
__LINE__, FT_Errors[error].code, FT_Errors[error].message); | |||||
FT_Done_FreeType(*library); | |||||
return 0; | |||||
} | |||||
/* Select charmap */ | |||||
error = FT_Select_Charmap(*face, FT_ENCODING_UNICODE); | |||||
if(error) { | |||||
fprintf(stderr, "FT_Error (line %d, code 0x%02x) : %s\n", | |||||
__LINE__, FT_Errors[error].code, FT_Errors[error].message); | |||||
FT_Done_Face(*face); | |||||
FT_Done_FreeType(*library); | |||||
return 0; | |||||
} | |||||
/* Set char size */ | |||||
error = FT_Set_Char_Size(*face, (int)(size * HRES), 0, DPI * HRES, DPI); | |||||
if(error) { | |||||
fprintf(stderr, "FT_Error (line %d, code 0x%02x) : %s\n", | |||||
__LINE__, FT_Errors[error].code, FT_Errors[error].message); | |||||
FT_Done_Face(*face); | |||||
FT_Done_FreeType(*library); | |||||
return 0; | |||||
} | |||||
/* Set transform matrix */ | |||||
FT_Set_Transform(*face, &matrix, NULL); | |||||
return 1; | |||||
} | |||||
static int | |||||
texture_font_get_face_with_size(texture_font_t *self, float size, | |||||
FT_Library *library, FT_Face *face) | |||||
{ | |||||
return texture_font_load_face(self, size, library, face); | |||||
} | |||||
static int | |||||
texture_font_get_face(texture_font_t *self, | |||||
FT_Library *library, FT_Face *face) | |||||
{ | |||||
return texture_font_get_face_with_size(self, self->size, library, face); | |||||
} | |||||
static int | |||||
texture_font_get_hires_face(texture_font_t *self, | |||||
FT_Library *library, FT_Face *face) | |||||
{ | |||||
return texture_font_get_face_with_size(self, | |||||
self->size * 100.f, library, face); | |||||
} | |||||
// ------------------------------------------------------ texture_glyph_new --- | |||||
texture_glyph_t * | |||||
texture_glyph_new(void) | |||||
{ | |||||
texture_glyph_t *self = (texture_glyph_t *) malloc( sizeof(texture_glyph_t) ); | |||||
if(self == NULL) { | |||||
fprintf( stderr, | |||||
"line %d: No more memory for allocating data\n", __LINE__); | |||||
return NULL; | |||||
} | |||||
self->id = 0; | |||||
self->width = 0; | |||||
self->height = 0; | |||||
self->outline_type = 0; | |||||
self->outline_thickness = 0.0; | |||||
self->offset_x = 0; | |||||
self->offset_y = 0; | |||||
self->advance_x = 0.0; | |||||
self->advance_y = 0.0; | |||||
self->s0 = 0.0; | |||||
self->t0 = 0.0; | |||||
self->s1 = 0.0; | |||||
self->t1 = 0.0; | |||||
self->kerning = vector_new( sizeof(kerning_t) ); | |||||
return self; | |||||
} | |||||
// --------------------------------------------------- texture_glyph_delete --- | |||||
void | |||||
texture_glyph_delete( texture_glyph_t *self ) | |||||
{ | |||||
assert( self ); | |||||
vector_delete( self->kerning ); | |||||
free( self ); | |||||
} | |||||
// ---------------------------------------------- texture_glyph_get_kerning --- | |||||
float | |||||
texture_glyph_get_kerning( const texture_glyph_t * self, | |||||
const wchar_t charcode ) | |||||
{ | |||||
size_t i; | |||||
assert( self ); | |||||
for( i=0; i<vector_size(self->kerning); ++i ) | |||||
{ | |||||
kerning_t * kerning = (kerning_t *) vector_get( self->kerning, i ); | |||||
if( kerning->charcode == charcode ) | |||||
{ | |||||
return kerning->kerning; | |||||
} | |||||
} | |||||
return 0; | |||||
} | |||||
// ------------------------------------------ texture_font_generate_kerning --- | |||||
void | |||||
texture_font_generate_kerning( texture_font_t *self ) | |||||
{ | |||||
size_t i, j; | |||||
FT_Library library; | |||||
FT_Face face; | |||||
FT_UInt glyph_index, prev_index; | |||||
texture_glyph_t *glyph, *prev_glyph; | |||||
FT_Vector kerning; | |||||
assert( self ); | |||||
/* Load font */ | |||||
if(!texture_font_get_face(self, &library, &face)) | |||||
return; | |||||
/* For each glyph couple combination, check if kerning is necessary */ | |||||
/* Starts at index 1 since 0 is for the special backgroudn glyph */ | |||||
for( i=1; i<self->glyphs->size; ++i ) | |||||
{ | |||||
glyph = *(texture_glyph_t **) vector_get( self->glyphs, i ); | |||||
glyph_index = FT_Get_Char_Index( face, glyph->charcode ); | |||||
vector_clear( glyph->kerning ); | |||||
for( j=1; j<self->glyphs->size; ++j ) | |||||
{ | |||||
prev_glyph = *(texture_glyph_t **) vector_get( self->glyphs, j ); | |||||
prev_index = FT_Get_Char_Index( face, prev_glyph->charcode ); | |||||
FT_Get_Kerning( face, prev_index, glyph_index, FT_KERNING_UNFITTED, &kerning ); | |||||
// printf("%c(%d)-%c(%d): %ld\n", | |||||
// prev_glyph->charcode, prev_glyph->charcode, | |||||
// glyph_index, glyph_index, kerning.x); | |||||
if( kerning.x ) | |||||
{ | |||||
kerning_t k = {prev_glyph->charcode, kerning.x / (float)(HRESf*HRESf)}; | |||||
vector_push_back( glyph->kerning, &k ); | |||||
} | |||||
} | |||||
} | |||||
FT_Done_Face( face ); | |||||
FT_Done_FreeType( library ); | |||||
} | |||||
// ------------------------------------------------------ texture_font_init --- | |||||
static int | |||||
texture_font_init(texture_font_t *self) | |||||
{ | |||||
FT_Library library; | |||||
FT_Face face; | |||||
FT_Size_Metrics metrics; | |||||
assert(self->atlas); | |||||
assert(self->size > 0); | |||||
assert((self->location == TEXTURE_FONT_FILE && self->filename) | |||||
|| (self->location == TEXTURE_FONT_MEMORY | |||||
&& self->memory.base && self->memory.size)); | |||||
self->glyphs = vector_new(sizeof(texture_glyph_t *)); | |||||
self->height = 0; | |||||
self->ascender = 0; | |||||
self->descender = 0; | |||||
self->outline_type = 0; | |||||
self->outline_thickness = 0.0; | |||||
self->hinting = 1; | |||||
self->kerning = 1; | |||||
self->filtering = 1; | |||||
// FT_LCD_FILTER_LIGHT is (0x00, 0x55, 0x56, 0x55, 0x00) | |||||
// FT_LCD_FILTER_DEFAULT is (0x10, 0x40, 0x70, 0x40, 0x10) | |||||
self->lcd_weights[0] = 0x10; | |||||
self->lcd_weights[1] = 0x40; | |||||
self->lcd_weights[2] = 0x70; | |||||
self->lcd_weights[3] = 0x40; | |||||
self->lcd_weights[4] = 0x10; | |||||
/* Get font metrics at high resolution */ | |||||
if (!texture_font_get_hires_face(self, &library, &face)) | |||||
return -1; | |||||
self->underline_position = face->underline_position / (float)(HRESf*HRESf) * self->size; | |||||
self->underline_position = round( self->underline_position ); | |||||
if( self->underline_position > -2 ) | |||||
{ | |||||
self->underline_position = -2.0; | |||||
} | |||||
self->underline_thickness = face->underline_thickness / (float)(HRESf*HRESf) * self->size; | |||||
self->underline_thickness = round( self->underline_thickness ); | |||||
if( self->underline_thickness < 1 ) | |||||
{ | |||||
self->underline_thickness = 1.0; | |||||
} | |||||
metrics = face->size->metrics; | |||||
self->ascender = (metrics.ascender >> 6) / 100.0; | |||||
self->descender = (metrics.descender >> 6) / 100.0; | |||||
self->height = (metrics.height >> 6) / 100.0; | |||||
self->linegap = self->height - self->ascender + self->descender; | |||||
FT_Done_Face( face ); | |||||
FT_Done_FreeType( library ); | |||||
/* -1 is a special glyph */ | |||||
texture_font_get_glyph( self, -1 ); | |||||
return 0; | |||||
} | |||||
// --------------------------------------------- texture_font_new_from_file --- | |||||
texture_font_t * | |||||
texture_font_new_from_file(texture_atlas_t *atlas, const float pt_size, | |||||
const char *filename) | |||||
{ | |||||
texture_font_t *self; | |||||
assert(filename); | |||||
self = calloc(1, sizeof(*self)); | |||||
if (!self) { | |||||
fprintf(stderr, | |||||
"line %d: No more memory for allocating data\n", __LINE__); | |||||
return NULL; | |||||
} | |||||
self->atlas = atlas; | |||||
self->size = pt_size; | |||||
self->location = TEXTURE_FONT_FILE; | |||||
self->filename = strdup(filename); | |||||
if (texture_font_init(self)) { | |||||
texture_font_delete(self); | |||||
return NULL; | |||||
} | |||||
return self; | |||||
} | |||||
// ------------------------------------------- texture_font_new_from_memory --- | |||||
texture_font_t * | |||||
texture_font_new_from_memory(texture_atlas_t *atlas, float pt_size, | |||||
const void *memory_base, size_t memory_size) | |||||
{ | |||||
texture_font_t *self; | |||||
assert(memory_base); | |||||
assert(memory_size); | |||||
self = calloc(1, sizeof(*self)); | |||||
if (!self) { | |||||
fprintf(stderr, | |||||
"line %d: No more memory for allocating data\n", __LINE__); | |||||
return NULL; | |||||
} | |||||
self->atlas = atlas; | |||||
self->size = pt_size; | |||||
self->location = TEXTURE_FONT_MEMORY; | |||||
self->memory.base = memory_base; | |||||
self->memory.size = memory_size; | |||||
if (texture_font_init(self)) { | |||||
texture_font_delete(self); | |||||
return NULL; | |||||
} | |||||
return self; | |||||
} | |||||
// ---------------------------------------------------- texture_font_delete --- | |||||
void | |||||
texture_font_delete( texture_font_t *self ) | |||||
{ | |||||
size_t i; | |||||
texture_glyph_t *glyph; | |||||
assert( self ); | |||||
if(self->location == TEXTURE_FONT_FILE && self->filename) | |||||
free( self->filename ); | |||||
for( i=0; i<vector_size( self->glyphs ); ++i) | |||||
{ | |||||
glyph = *(texture_glyph_t **) vector_get( self->glyphs, i ); | |||||
texture_glyph_delete( glyph); | |||||
} | |||||
vector_delete( self->glyphs ); | |||||
free( self ); | |||||
} | |||||
// ----------------------------------------------- texture_font_load_glyphs --- | |||||
size_t | |||||
texture_font_load_glyphs( texture_font_t * self, | |||||
const wchar_t * charcodes ) | |||||
{ | |||||
size_t i, j, x, y, width, height, depth, w, h; | |||||
FT_Library library; | |||||
FT_Error error; | |||||
FT_Face face; | |||||
FT_Glyph ft_glyph; | |||||
FT_GlyphSlot slot; | |||||
FT_Bitmap ft_bitmap; | |||||
FT_UInt glyph_index; | |||||
texture_glyph_t *glyph; | |||||
FT_Int32 flags = 0; | |||||
int ft_glyph_top = 0; | |||||
int ft_glyph_left = 0; | |||||
ivec4 region; | |||||
size_t missed = 0; | |||||
char pass; | |||||
assert( self ); | |||||
assert( charcodes ); | |||||
width = self->atlas->width; | |||||
height = self->atlas->height; | |||||
depth = self->atlas->depth; | |||||
if (!texture_font_get_face(self, &library, &face)) | |||||
return wcslen(charcodes); | |||||
/* Load each glyph */ | |||||
for( i=0; i<wcslen(charcodes); ++i ) { | |||||
pass = 0; | |||||
/* Check if charcode has been already loaded */ | |||||
for(j = 0; j < self->glyphs->size; ++j ) { | |||||
glyph = *(texture_glyph_t **) vector_get( self->glyphs, j ); | |||||
// If charcode is -1, we don't care about outline type or thickness | |||||
// if( (glyph->charcode == charcodes[i])) { | |||||
if( (glyph->charcode == charcodes[i]) && | |||||
((charcodes[i] == (wchar_t)(-1) ) || | |||||
((glyph->outline_type == self->outline_type) && | |||||
(glyph->outline_thickness == self->outline_thickness)) )) | |||||
{ | |||||
pass = 1; | |||||
break; | |||||
} | |||||
} | |||||
if(pass) | |||||
continue; // don't add the item | |||||
flags = 0; | |||||
ft_glyph_top = 0; | |||||
ft_glyph_left = 0; | |||||
glyph_index = FT_Get_Char_Index( face, charcodes[i] ); | |||||
// WARNING: We use texture-atlas depth to guess if user wants | |||||
// LCD subpixel rendering | |||||
if( self->outline_type > 0 ) | |||||
{ | |||||
flags |= FT_LOAD_NO_BITMAP; | |||||
} | |||||
else | |||||
{ | |||||
flags |= FT_LOAD_RENDER; | |||||
} | |||||
if( !self->hinting ) | |||||
{ | |||||
flags |= FT_LOAD_NO_HINTING | FT_LOAD_NO_AUTOHINT; | |||||
} | |||||
else | |||||
{ | |||||
flags |= FT_LOAD_FORCE_AUTOHINT; | |||||
} | |||||
if( depth == 3 ) | |||||
{ | |||||
FT_Library_SetLcdFilter( library, FT_LCD_FILTER_LIGHT ); | |||||
flags |= FT_LOAD_TARGET_LCD; | |||||
if( self->filtering ) | |||||
{ | |||||
FT_Library_SetLcdFilterWeights( library, self->lcd_weights ); | |||||
} | |||||
} | |||||
error = FT_Load_Glyph( face, glyph_index, flags ); | |||||
if( error ) | |||||
{ | |||||
fprintf( stderr, "FT_Error (line %d, code 0x%02x) : %s\n", | |||||
__LINE__, FT_Errors[error].code, FT_Errors[error].message ); | |||||
FT_Done_Face( face ); | |||||
FT_Done_FreeType( library ); | |||||
return wcslen(charcodes)-i; | |||||
} | |||||
if( self->outline_type == 0 ) | |||||
{ | |||||
slot = face->glyph; | |||||
ft_bitmap = slot->bitmap; | |||||
ft_glyph_top = slot->bitmap_top; | |||||
ft_glyph_left = slot->bitmap_left; | |||||
} | |||||
else | |||||
{ | |||||
FT_Stroker stroker; | |||||
FT_BitmapGlyph ft_bitmap_glyph; | |||||
error = FT_Stroker_New( library, &stroker ); | |||||
if( error ) | |||||
{ | |||||
fprintf(stderr, "FT_Error (0x%02x) : %s\n", | |||||
FT_Errors[error].code, FT_Errors[error].message); | |||||
FT_Done_Face( face ); | |||||
FT_Stroker_Done( stroker ); | |||||
FT_Done_FreeType( library ); | |||||
return 0; | |||||
} | |||||
FT_Stroker_Set(stroker, | |||||
(int)(self->outline_thickness * HRES), | |||||
FT_STROKER_LINECAP_ROUND, | |||||
FT_STROKER_LINEJOIN_ROUND, | |||||
0); | |||||
error = FT_Get_Glyph( face->glyph, &ft_glyph); | |||||
if( error ) | |||||
{ | |||||
fprintf(stderr, "FT_Error (0x%02x) : %s\n", | |||||
FT_Errors[error].code, FT_Errors[error].message); | |||||
FT_Done_Face( face ); | |||||
FT_Stroker_Done( stroker ); | |||||
FT_Done_FreeType( library ); | |||||
return 0; | |||||
} | |||||
if( self->outline_type == 1 ) | |||||
{ | |||||
error = FT_Glyph_Stroke( &ft_glyph, stroker, 1 ); | |||||
} | |||||
else if ( self->outline_type == 2 ) | |||||
{ | |||||
error = FT_Glyph_StrokeBorder( &ft_glyph, stroker, 0, 1 ); | |||||
} | |||||
else if ( self->outline_type == 3 ) | |||||
{ | |||||
error = FT_Glyph_StrokeBorder( &ft_glyph, stroker, 1, 1 ); | |||||
} | |||||
if( error ) | |||||
{ | |||||
fprintf(stderr, "FT_Error (0x%02x) : %s\n", | |||||
FT_Errors[error].code, FT_Errors[error].message); | |||||
FT_Done_Face( face ); | |||||
FT_Stroker_Done( stroker ); | |||||
FT_Done_FreeType( library ); | |||||
return 0; | |||||
} | |||||
if( depth == 1) | |||||
{ | |||||
error = FT_Glyph_To_Bitmap( &ft_glyph, FT_RENDER_MODE_NORMAL, 0, 1); | |||||
if( error ) | |||||
{ | |||||
fprintf(stderr, "FT_Error (0x%02x) : %s\n", | |||||
FT_Errors[error].code, FT_Errors[error].message); | |||||
FT_Done_Face( face ); | |||||
FT_Stroker_Done( stroker ); | |||||
FT_Done_FreeType( library ); | |||||
return 0; | |||||
} | |||||
} | |||||
else | |||||
{ | |||||
error = FT_Glyph_To_Bitmap( &ft_glyph, FT_RENDER_MODE_LCD, 0, 1); | |||||
if( error ) | |||||
{ | |||||
fprintf(stderr, "FT_Error (0x%02x) : %s\n", | |||||
FT_Errors[error].code, FT_Errors[error].message); | |||||
FT_Done_Face( face ); | |||||
FT_Stroker_Done( stroker ); | |||||
FT_Done_FreeType( library ); | |||||
return 0; | |||||
} | |||||
} | |||||
ft_bitmap_glyph = (FT_BitmapGlyph) ft_glyph; | |||||
ft_bitmap = ft_bitmap_glyph->bitmap; | |||||
ft_glyph_top = ft_bitmap_glyph->top; | |||||
ft_glyph_left = ft_bitmap_glyph->left; | |||||
FT_Stroker_Done(stroker); | |||||
} | |||||
// We want each glyph to be separated by at least one black pixel | |||||
// (for example for shader used in demo-subpixel.c) | |||||
w = ft_bitmap.width/depth + 1; | |||||
h = ft_bitmap.rows + 1; | |||||
region = texture_atlas_get_region( self->atlas, w, h ); | |||||
if ( region.x < 0 ) | |||||
{ | |||||
missed++; | |||||
fprintf( stderr, "Texture atlas is full (line %d)\n", __LINE__ ); | |||||
continue; | |||||
} | |||||
w = w - 1; | |||||
h = h - 1; | |||||
x = region.x; | |||||
y = region.y; | |||||
texture_atlas_set_region( self->atlas, x, y, w, h, | |||||
ft_bitmap.buffer, ft_bitmap.pitch ); | |||||
glyph = texture_glyph_new( ); | |||||
glyph->charcode = charcodes[i]; | |||||
glyph->width = w; | |||||
glyph->height = h; | |||||
glyph->outline_type = self->outline_type; | |||||
glyph->outline_thickness = self->outline_thickness; | |||||
glyph->offset_x = ft_glyph_left; | |||||
glyph->offset_y = ft_glyph_top; | |||||
glyph->s0 = x/(float)width; | |||||
glyph->t0 = y/(float)height; | |||||
glyph->s1 = (x + glyph->width)/(float)width; | |||||
glyph->t1 = (y + glyph->height)/(float)height; | |||||
// Discard hinting to get advance | |||||
FT_Load_Glyph( face, glyph_index, FT_LOAD_RENDER | FT_LOAD_NO_HINTING); | |||||
slot = face->glyph; | |||||
glyph->advance_x = slot->advance.x / HRESf; | |||||
glyph->advance_y = slot->advance.y / HRESf; | |||||
vector_push_back( self->glyphs, &glyph ); | |||||
if( self->outline_type > 0 ) | |||||
{ | |||||
FT_Done_Glyph( ft_glyph ); | |||||
} | |||||
} | |||||
FT_Done_Face( face ); | |||||
FT_Done_FreeType( library ); | |||||
texture_atlas_upload( self->atlas ); | |||||
texture_font_generate_kerning( self ); | |||||
return missed; | |||||
} | |||||
// ------------------------------------------------- texture_font_get_glyph --- | |||||
texture_glyph_t * | |||||
texture_font_get_glyph( texture_font_t * self, | |||||
wchar_t charcode ) | |||||
{ | |||||
size_t i; | |||||
wchar_t buffer[2] = {0,0}; | |||||
texture_glyph_t *glyph; | |||||
assert( self ); | |||||
assert( self ); | |||||
assert( self->filename ); | |||||
assert( self->atlas ); | |||||
/* Check if charcode has been already loaded */ | |||||
for( i=0; i<self->glyphs->size; ++i ) | |||||
{ | |||||
glyph = *(texture_glyph_t **) vector_get( self->glyphs, i ); | |||||
// If charcode is -1, we don't care about outline type or thickness | |||||
if( (glyph->charcode == charcode) && | |||||
((charcode == (wchar_t)(-1) ) || | |||||
((glyph->outline_type == self->outline_type) && | |||||
(glyph->outline_thickness == self->outline_thickness)) )) | |||||
{ | |||||
return glyph; | |||||
} | |||||
} | |||||
/* charcode -1 is special : it is used for line drawing (overline, | |||||
* underline, strikethrough) and background. | |||||
*/ | |||||
if( charcode == (wchar_t)(-1) ) | |||||
{ | |||||
size_t width = self->atlas->width; | |||||
size_t height = self->atlas->height; | |||||
ivec4 region = texture_atlas_get_region( self->atlas, 5, 5 ); | |||||
texture_glyph_t * glyph = texture_glyph_new( ); | |||||
static unsigned char data[4*4*3] = {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, | |||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, | |||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, | |||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1}; | |||||
if ( region.x < 0 ) | |||||
{ | |||||
fprintf( stderr, "Texture atlas is full (line %d)\n", __LINE__ ); | |||||
return NULL; | |||||
} | |||||
texture_atlas_set_region( self->atlas, region.x, region.y, 4, 4, data, 0 ); | |||||
glyph->charcode = (wchar_t)(-1); | |||||
glyph->s0 = (region.x+2)/(float)width; | |||||
glyph->t0 = (region.y+2)/(float)height; | |||||
glyph->s1 = (region.x+3)/(float)width; | |||||
glyph->t1 = (region.y+3)/(float)height; | |||||
vector_push_back( self->glyphs, &glyph ); | |||||
return glyph; //*(texture_glyph_t **) vector_back( self->glyphs ); | |||||
} | |||||
/* Glyph has not been already loaded */ | |||||
buffer[0] = charcode; | |||||
if( texture_font_load_glyphs( self, buffer ) == 0 ) | |||||
{ | |||||
return *(texture_glyph_t **) vector_back( self->glyphs ); | |||||
} | |||||
return NULL; | |||||
} |
@@ -0,0 +1,451 @@ | |||||
/* ============================================================================ | |||||
* Freetype GL - A C OpenGL Freetype engine | |||||
* Platform: Any | |||||
* WWW: http://code.google.com/p/freetype-gl/ | |||||
* ---------------------------------------------------------------------------- | |||||
* Copyright 2011,2012 Nicolas P. Rougier. All rights reserved. | |||||
* | |||||
* Redistribution and use in source and binary forms, with or without | |||||
* modification, are permitted provided that the following conditions are met: | |||||
* | |||||
* 1. Redistributions of source code must retain the above copyright notice, | |||||
* this list of conditions and the following disclaimer. | |||||
* | |||||
* 2. Redistributions in binary form must reproduce the above copyright | |||||
* notice, this list of conditions and the following disclaimer in the | |||||
* documentation and/or other materials provided with the distribution. | |||||
* | |||||
* THIS SOFTWARE IS PROVIDED BY NICOLAS P. ROUGIER ''AS IS'' AND ANY EXPRESS OR | |||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | |||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO | |||||
* EVENT SHALL NICOLAS P. ROUGIER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, | |||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||||
* | |||||
* The views and conclusions contained in the software and documentation are | |||||
* those of the authors and should not be interpreted as representing official | |||||
* policies, either expressed or implied, of Nicolas P. Rougier. | |||||
* ============================================================================ | |||||
*/ | |||||
#ifndef __TEXTURE_FONT_H__ | |||||
#define __TEXTURE_FONT_H__ | |||||
#include <stdlib.h> | |||||
#ifdef __cplusplus | |||||
extern "C" { | |||||
#endif | |||||
#include "vector.h" | |||||
#include "texture-atlas.h" | |||||
/** | |||||
* @file texture-font.h | |||||
* @author Nicolas Rougier (Nicolas.Rougier@inria.fr) | |||||
* | |||||
* @defgroup texture-font Texture font | |||||
* | |||||
* Texture font. | |||||
* | |||||
* Example Usage: | |||||
* @code | |||||
* #include "texture-font.h" | |||||
* | |||||
* int main( int arrgc, char *argv[] ) | |||||
* { | |||||
* return 0; | |||||
* } | |||||
* @endcode | |||||
* | |||||
* @{ | |||||
*/ | |||||
/** | |||||
* A structure that hold a kerning value relatively to a charcode. | |||||
* | |||||
* This structure cannot be used alone since the (necessary) right charcode is | |||||
* implicitely held by the owner of this structure. | |||||
*/ | |||||
typedef struct kerning_t | |||||
{ | |||||
/** | |||||
* Left character code in the kern pair. | |||||
*/ | |||||
wchar_t charcode; | |||||
/** | |||||
* Kerning value (in fractional pixels). | |||||
*/ | |||||
float kerning; | |||||
} kerning_t; | |||||
/* | |||||
* Glyph metrics: | |||||
* -------------- | |||||
* | |||||
* xmin xmax | |||||
* | | | |||||
* |<-------- width -------->| | |||||
* | | | |||||
* | +-------------------------+----------------- ymax | |||||
* | | ggggggggg ggggg | ^ ^ | |||||
* | | g:::::::::ggg::::g | | | | |||||
* | | g:::::::::::::::::g | | | | |||||
* | | g::::::ggggg::::::gg | | | | |||||
* | | g:::::g g:::::g | | | | |||||
* offset_x -|-------->| g:::::g g:::::g | offset_y | | |||||
* | | g:::::g g:::::g | | | | |||||
* | | g::::::g g:::::g | | | | |||||
* | | g:::::::ggggg:::::g | | | | |||||
* | | g::::::::::::::::g | | height | |||||
* | | gg::::::::::::::g | | | | |||||
* baseline ---*---------|---- gggggggg::::::g-----*-------- | | |||||
* / | | g:::::g | | | |||||
* origin | | gggggg g:::::g | | | |||||
* | | g:::::gg gg:::::g | | | |||||
* | | g::::::ggg:::::::g | | | |||||
* | | gg:::::::::::::g | | | |||||
* | | ggg::::::ggg | | | |||||
* | | gggggg | v | |||||
* | +-------------------------+----------------- ymin | |||||
* | | | |||||
* |------------- advance_x ---------->| | |||||
*/ | |||||
/** | |||||
* A structure that describe a glyph. | |||||
*/ | |||||
typedef struct texture_glyph_t | |||||
{ | |||||
/** | |||||
* Wide character this glyph represents | |||||
*/ | |||||
wchar_t charcode; | |||||
/** | |||||
* Glyph id (used for display lists) | |||||
*/ | |||||
unsigned int id; | |||||
/** | |||||
* Glyph's width in pixels. | |||||
*/ | |||||
size_t width; | |||||
/** | |||||
* Glyph's height in pixels. | |||||
*/ | |||||
size_t height; | |||||
/** | |||||
* Glyph's left bearing expressed in integer pixels. | |||||
*/ | |||||
int offset_x; | |||||
/** | |||||
* Glyphs's top bearing expressed in integer pixels. | |||||
* | |||||
* Remember that this is the distance from the baseline to the top-most | |||||
* glyph scanline, upwards y coordinates being positive. | |||||
*/ | |||||
int offset_y; | |||||
/** | |||||
* For horizontal text layouts, this is the horizontal distance (in | |||||
* fractional pixels) used to increment the pen position when the glyph is | |||||
* drawn as part of a string of text. | |||||
*/ | |||||
float advance_x; | |||||
/** | |||||
* For vertical text layouts, this is the vertical distance (in fractional | |||||
* pixels) used to increment the pen position when the glyph is drawn as | |||||
* part of a string of text. | |||||
*/ | |||||
float advance_y; | |||||
/** | |||||
* First normalized texture coordinate (x) of top-left corner | |||||
*/ | |||||
float s0; | |||||
/** | |||||
* Second normalized texture coordinate (y) of top-left corner | |||||
*/ | |||||
float t0; | |||||
/** | |||||
* First normalized texture coordinate (x) of bottom-right corner | |||||
*/ | |||||
float s1; | |||||
/** | |||||
* Second normalized texture coordinate (y) of bottom-right corner | |||||
*/ | |||||
float t1; | |||||
/** | |||||
* A vector of kerning pairs relative to this glyph. | |||||
*/ | |||||
vector_t * kerning; | |||||
/** | |||||
* Glyph outline type (0 = None, 1 = line, 2 = inner, 3 = outer) | |||||
*/ | |||||
int outline_type; | |||||
/** | |||||
* Glyph outline thickness | |||||
*/ | |||||
float outline_thickness; | |||||
} texture_glyph_t; | |||||
/** | |||||
* Texture font structure. | |||||
*/ | |||||
typedef struct texture_font_t | |||||
{ | |||||
/** | |||||
* Vector of glyphs contained in this font. | |||||
*/ | |||||
vector_t * glyphs; | |||||
/** | |||||
* Atlas structure to store glyphs data. | |||||
*/ | |||||
texture_atlas_t * atlas; | |||||
/** | |||||
* font location | |||||
*/ | |||||
enum { | |||||
TEXTURE_FONT_FILE = 0, | |||||
TEXTURE_FONT_MEMORY, | |||||
} location; | |||||
union { | |||||
/** | |||||
* Font filename, for when location == TEXTURE_FONT_FILE | |||||
*/ | |||||
char *filename; | |||||
/** | |||||
* Font memory address, for when location == TEXTURE_FONT_MEMORY | |||||
*/ | |||||
struct { | |||||
const void *base; | |||||
size_t size; | |||||
} memory; | |||||
}; | |||||
/** | |||||
* Font size | |||||
*/ | |||||
float size; | |||||
/** | |||||
* Whether to use autohint when rendering font | |||||
*/ | |||||
int hinting; | |||||
/** | |||||
* Outline type (0 = None, 1 = line, 2 = inner, 3 = outer) | |||||
*/ | |||||
int outline_type; | |||||
/** | |||||
* Outline thickness | |||||
*/ | |||||
float outline_thickness; | |||||
/** | |||||
* Whether to use our own lcd filter. | |||||
*/ | |||||
int filtering; | |||||
/** | |||||
* Whether to use kerning if available | |||||
*/ | |||||
int kerning; | |||||
/** | |||||
* LCD filter weights | |||||
*/ | |||||
unsigned char lcd_weights[5]; | |||||
/** | |||||
* This field is simply used to compute a default line spacing (i.e., the | |||||
* baseline-to-baseline distance) when writing text with this font. Note | |||||
* that it usually is larger than the sum of the ascender and descender | |||||
* taken as absolute values. There is also no guarantee that no glyphs | |||||
* extend above or below subsequent baselines when using this distance. | |||||
*/ | |||||
float height; | |||||
/** | |||||
* This field is the distance that must be placed between two lines of | |||||
* text. The baseline-to-baseline distance should be computed as: | |||||
* ascender - descender + linegap | |||||
*/ | |||||
float linegap; | |||||
/** | |||||
* The ascender is the vertical distance from the horizontal baseline to | |||||
* the highest 'character' coordinate in a font face. Unfortunately, font | |||||
* formats define the ascender differently. For some, it represents the | |||||
* ascent of all capital latin characters (without accents), for others it | |||||
* is the ascent of the highest accented character, and finally, other | |||||
* formats define it as being equal to bbox.yMax. | |||||
*/ | |||||
float ascender; | |||||
/** | |||||
* The descender is the vertical distance from the horizontal baseline to | |||||
* the lowest 'character' coordinate in a font face. Unfortunately, font | |||||
* formats define the descender differently. For some, it represents the | |||||
* descent of all capital latin characters (without accents), for others it | |||||
* is the ascent of the lowest accented character, and finally, other | |||||
* formats define it as being equal to bbox.yMin. This field is negative | |||||
* for values below the baseline. | |||||
*/ | |||||
float descender; | |||||
/** | |||||
* The position of the underline line for this face. It is the center of | |||||
* the underlining stem. Only relevant for scalable formats. | |||||
*/ | |||||
float underline_position; | |||||
/** | |||||
* The thickness of the underline for this face. Only relevant for scalable | |||||
* formats. | |||||
*/ | |||||
float underline_thickness; | |||||
} texture_font_t; | |||||
/** | |||||
* This function creates a new texture font from given filename and size. The | |||||
* texture atlas is used to store glyph on demand. Note the depth of the atlas | |||||
* will determine if the font is rendered as alpha channel only (depth = 1) or | |||||
* RGB (depth = 3) that correspond to subpixel rendering (if available on your | |||||
* freetype implementation). | |||||
* | |||||
* @param atlas A texture atlas | |||||
* @param pt_size Size of font to be created (in points) | |||||
* @param filename A font filename | |||||
* | |||||
* @return A new empty font (no glyph inside yet) | |||||
* | |||||
*/ | |||||
texture_font_t * | |||||
texture_font_new_from_file( texture_atlas_t * atlas, | |||||
const float pt_size, | |||||
const char * filename ); | |||||
/** | |||||
* This function creates a new texture font from a memory location and size. | |||||
* The texture atlas is used to store glyph on demand. Note the depth of the | |||||
* atlas will determine if the font is rendered as alpha channel only | |||||
* (depth = 1) or RGB (depth = 3) that correspond to subpixel rendering (if | |||||
* available on your freetype implementation). | |||||
* | |||||
* @param atlas A texture atlas | |||||
* @param pt_size Size of font to be created (in points) | |||||
* @param memory_base Start of the font file in memory | |||||
* @param memory_size Size of the font file memory region, in bytes | |||||
* | |||||
* @return A new empty font (no glyph inside yet) | |||||
* | |||||
*/ | |||||
texture_font_t * | |||||
texture_font_new_from_memory( texture_atlas_t *atlas, | |||||
float pt_size, | |||||
const void *memory_base, | |||||
size_t memory_size ); | |||||
/** | |||||
* Delete a texture font. Note that this does not delete the glyph from the | |||||
* texture atlas. | |||||
* | |||||
* @param self a valid texture font | |||||
*/ | |||||
void | |||||
texture_font_delete( texture_font_t * self ); | |||||
/** | |||||
* Request a new glyph from the font. If it has not been created yet, it will | |||||
* be. | |||||
* | |||||
* @param self A valid texture font | |||||
* @param charcode Character codepoint to be loaded. | |||||
* | |||||
* @return A pointer on the new glyph or 0 if the texture atlas is not big | |||||
* enough | |||||
* | |||||
*/ | |||||
texture_glyph_t * | |||||
texture_font_get_glyph( texture_font_t * self, | |||||
wchar_t charcode ); | |||||
/** | |||||
* Request the loading of several glyphs at once. | |||||
* | |||||
* @param self a valid texture font | |||||
* @param charcodes character codepoints to be loaded. | |||||
* | |||||
* @return Number of missed glyph if the texture is not big enough to hold | |||||
* every glyphs. | |||||
*/ | |||||
size_t | |||||
texture_font_load_glyphs( texture_font_t * self, | |||||
const wchar_t * charcodes ); | |||||
/** | |||||
* Get the kerning between two horizontal glyphs. | |||||
* | |||||
* @param self a valid texture glyph | |||||
* @param charcode codepoint of the peceding glyph | |||||
* | |||||
* @return x kerning value | |||||
*/ | |||||
float | |||||
texture_glyph_get_kerning( const texture_glyph_t * self, | |||||
const wchar_t charcode ); | |||||
/** | |||||
* Creates a new empty glyph | |||||
* | |||||
* @return a new empty glyph (not valid) | |||||
*/ | |||||
texture_glyph_t * | |||||
texture_glyph_new( void ); | |||||
/** @} */ | |||||
#ifdef __cplusplus | |||||
} | |||||
#endif | |||||
#endif /* __TEXTURE_FONT_H__ */ | |||||
@@ -0,0 +1,237 @@ | |||||
/* ============================================================================ | |||||
* Freetype GL - A C OpenGL Freetype engine | |||||
* Platform: Any | |||||
* WWW: http://code.google.com/p/freetype-gl/ | |||||
* ---------------------------------------------------------------------------- | |||||
* Copyright 2011,2012,2013 Nicolas P. Rougier. All rights reserved. | |||||
* | |||||
* Redistribution and use in source and binary forms, with or without | |||||
* modification, are permitted provided that the following conditions are met: | |||||
* | |||||
* 1. Redistributions of source code must retain the above copyright notice, | |||||
* this list of conditions and the following disclaimer. | |||||
* | |||||
* 2. Redistributions in binary form must reproduce the above copyright | |||||
* notice, this list of conditions and the following disclaimer in the | |||||
* documentation and/or other materials provided with the distribution. | |||||
* | |||||
* THIS SOFTWARE IS PROVIDED BY NICOLAS P. ROUGIER ''AS IS'' AND ANY EXPRESS OR | |||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | |||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO | |||||
* EVENT SHALL NICOLAS P. ROUGIER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, | |||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||||
* | |||||
* The views and conclusions contained in the software and documentation are | |||||
* those of the authors and should not be interpreted as representing official | |||||
* policies, either expressed or implied, of Nicolas P. Rougier. | |||||
* ============================================================================ | |||||
*/ | |||||
#ifndef __VEC234_H__ | |||||
#define __VEC234_H__ | |||||
#ifdef __cplusplus | |||||
extern "C" { | |||||
#endif | |||||
/** | |||||
* Tuple of 4 ints. | |||||
* | |||||
* Each field can be addressed using several aliases: | |||||
* - First component: <b>x</b>, <b>r</b>, <b>red</b> or <b>vstart</b> | |||||
* - Second component: <b>y</b>, <b>g</b>, <b>green</b> or <b>vcount</b> | |||||
* - Third component: <b>z</b>, <b>b</b>, <b>blue</b>, <b>width</b> or <b>istart</b> | |||||
* - Fourth component: <b>w</b>, <b>a</b>, <b>alpha</b>, <b>height</b> or <b>icount</b> | |||||
* | |||||
*/ | |||||
typedef union | |||||
{ | |||||
int data[4]; /**< All compoments at once */ | |||||
struct { | |||||
int x; /**< Alias for first component */ | |||||
int y; /**< Alias for second component */ | |||||
int z; /**< Alias for third component */ | |||||
int w; /**< Alias for fourht component */ | |||||
}; | |||||
struct { | |||||
int x_; /**< Alias for first component */ | |||||
int y_; /**< Alias for second component */ | |||||
int width; /**< Alias for third component */ | |||||
int height; /**< Alias for fourth component */ | |||||
}; | |||||
struct { | |||||
int r; /**< Alias for first component */ | |||||
int g; /**< Alias for second component */ | |||||
int b; /**< Alias for third component */ | |||||
int a; /**< Alias for fourth component */ | |||||
}; | |||||
struct { | |||||
int red; /**< Alias for first component */ | |||||
int green; /**< Alias for second component */ | |||||
int blue; /**< Alias for third component */ | |||||
int alpha; /**< Alias for fourth component */ | |||||
}; | |||||
struct { | |||||
int vstart; /**< Alias for first component */ | |||||
int vcount; /**< Alias for second component */ | |||||
int istart; /**< Alias for third component */ | |||||
int icount; /**< Alias for fourth component */ | |||||
}; | |||||
} ivec4; | |||||
/** | |||||
* Tuple of 3 ints. | |||||
* | |||||
* Each field can be addressed using several aliases: | |||||
* - First component: <b>x</b>, <b>r</b> or <b>red</b> | |||||
* - Second component: <b>y</b>, <b>g</b> or <b>green</b> | |||||
* - Third component: <b>z</b>, <b>b</b> or <b>blue</b> | |||||
* | |||||
*/ | |||||
typedef union | |||||
{ | |||||
int data[3]; /**< All compoments at once */ | |||||
struct { | |||||
int x; /**< Alias for first component */ | |||||
int y; /**< Alias for second component */ | |||||
int z; /**< Alias for third component */ | |||||
}; | |||||
struct { | |||||
int r; /**< Alias for first component */ | |||||
int g; /**< Alias for second component */ | |||||
int b; /**< Alias for third component */ | |||||
}; | |||||
struct { | |||||
int red; /**< Alias for first component */ | |||||
int green; /**< Alias for second component */ | |||||
int blue; /**< Alias for third component */ | |||||
}; | |||||
} ivec3; | |||||
/** | |||||
* Tuple of 2 ints. | |||||
* | |||||
* Each field can be addressed using several aliases: | |||||
* - First component: <b>x</b>, <b>s</b> or <b>start</b> | |||||
* - Second component: <b>y</b>, <b>t</b> or <b>end</b> | |||||
* | |||||
*/ | |||||
typedef union | |||||
{ | |||||
int data[2]; /**< All compoments at once */ | |||||
struct { | |||||
int x; /**< Alias for first component */ | |||||
int y; /**< Alias for second component */ | |||||
}; | |||||
struct { | |||||
int s; /**< Alias for first component */ | |||||
int t; /**< Alias for second component */ | |||||
}; | |||||
struct { | |||||
int start; /**< Alias for first component */ | |||||
int end; /**< Alias for second component */ | |||||
}; | |||||
} ivec2; | |||||
/** | |||||
* Tuple of 4 floats. | |||||
* | |||||
* Each field can be addressed using several aliases: | |||||
* - First component: <b>x</b>, <b>r</b> or <b>red</b> | |||||
* - Second component: <b>y</b>, <b>g</b> or <b>green</b> | |||||
* - Third component: <b>z</b>, <b>b</b>, <b>blue</b> or <b>width</b> | |||||
* - Fourth component: <b>w</b>, <b>a</b>, <b>alpha</b> or <b>height</b> | |||||
*/ | |||||
typedef union | |||||
{ | |||||
float data[4]; /**< All compoments at once */ | |||||
struct { | |||||
float x; /**< Alias for first component */ | |||||
float y; /**< Alias fo second component */ | |||||
float z; /**< Alias fo third component */ | |||||
float w; /**< Alias fo fourth component */ | |||||
}; | |||||
struct { | |||||
float x_; /**< Alias for first component */ | |||||
float y_; /**< Alias fo second component */ | |||||
float width; /**< Alias fo third component */ | |||||
float height; /**< Alias fo fourth component */ | |||||
}; | |||||
struct { | |||||
float r; /**< Alias for first component */ | |||||
float g; /**< Alias fo second component */ | |||||
float b; /**< Alias fo third component */ | |||||
float a; /**< Alias fo fourth component */ | |||||
}; | |||||
struct { | |||||
float red; /**< Alias for first component */ | |||||
float green; /**< Alias fo second component */ | |||||
float blue; /**< Alias fo third component */ | |||||
float alpha; /**< Alias fo fourth component */ | |||||
}; | |||||
} vec4; | |||||
/** | |||||
* Tuple of 3 floats | |||||
* | |||||
* Each field can be addressed using several aliases: | |||||
* - First component: <b>x</b>, <b>r</b> or <b>red</b> | |||||
* - Second component: <b>y</b>, <b>g</b> or <b>green</b> | |||||
* - Third component: <b>z</b>, <b>b</b> or <b>blue</b> | |||||
*/ | |||||
typedef union | |||||
{ | |||||
float data[3]; /**< All compoments at once */ | |||||
struct { | |||||
float x; /**< Alias for first component */ | |||||
float y; /**< Alias fo second component */ | |||||
float z; /**< Alias fo third component */ | |||||
}; | |||||
struct { | |||||
float r; /**< Alias for first component */ | |||||
float g; /**< Alias fo second component */ | |||||
float b; /**< Alias fo third component */ | |||||
}; | |||||
struct { | |||||
float red; /**< Alias for first component */ | |||||
float green; /**< Alias fo second component */ | |||||
float blue; /**< Alias fo third component */ | |||||
}; | |||||
} vec3; | |||||
/** | |||||
* Tuple of 2 floats | |||||
* | |||||
* Each field can be addressed using several aliases: | |||||
* - First component: <b>x</b> or <b>s</b> | |||||
* - Second component: <b>y</b> or <b>t</b> | |||||
*/ | |||||
typedef union | |||||
{ | |||||
float data[2]; /**< All components at once */ | |||||
struct { | |||||
float x; /**< Alias for first component */ | |||||
float y; /**< Alias for second component */ | |||||
}; | |||||
struct { | |||||
float s; /**< Alias for first component */ | |||||
float t; /**< Alias for second component */ | |||||
}; | |||||
} vec2; | |||||
#ifdef __cplusplus | |||||
} | |||||
#endif | |||||
#endif /* __VEC234_H__ */ |
@@ -0,0 +1,362 @@ | |||||
/* ========================================================================= | |||||
* Freetype GL - A C OpenGL Freetype engine | |||||
* Platform: Any | |||||
* WWW: http://code.google.com/p/freetype-gl/ | |||||
* ------------------------------------------------------------------------- | |||||
* Copyright 2011,2012 Nicolas P. Rougier. All rights reserved. | |||||
* | |||||
* Redistribution and use in source and binary forms, with or without | |||||
* modification, are permitted provided that the following conditions are met: | |||||
* | |||||
* 1. Redistributions of source code must retain the above copyright notice, | |||||
* this list of conditions and the following disclaimer. | |||||
* | |||||
* 2. Redistributions in binary form must reproduce the above copyright | |||||
* notice, this list of conditions and the following disclaimer in the | |||||
* documentation and/or other materials provided with the distribution. | |||||
* | |||||
* THIS SOFTWARE IS PROVIDED BY NICOLAS P. ROUGIER ''AS IS'' AND ANY EXPRESS OR | |||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | |||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO | |||||
* EVENT SHALL NICOLAS P. ROUGIER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, | |||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||||
* | |||||
* The views and conclusions contained in the software and documentation are | |||||
* those of the authors and should not be interpreted as representing official | |||||
* policies, either expressed or implied, of Nicolas P. Rougier. | |||||
* ========================================================================= */ | |||||
#include <assert.h> | |||||
#include <stdlib.h> | |||||
#include <string.h> | |||||
#include <stdio.h> | |||||
#include "vector.h" | |||||
// ------------------------------------------------------------- vector_new --- | |||||
vector_t * | |||||
vector_new( size_t item_size ) | |||||
{ | |||||
vector_t *self = (vector_t *) malloc( sizeof(vector_t) ); | |||||
assert( item_size ); | |||||
if( !self ) | |||||
{ | |||||
fprintf( stderr, | |||||
"line %d: No more memory for allocating data\n", __LINE__ ); | |||||
exit( EXIT_FAILURE ); | |||||
} | |||||
self->item_size = item_size; | |||||
self->size = 0; | |||||
self->capacity = 1; | |||||
self->items = malloc( self->item_size * self->capacity ); | |||||
return self; | |||||
} | |||||
// ---------------------------------------------------------- vector_delete --- | |||||
void | |||||
vector_delete( vector_t *self ) | |||||
{ | |||||
assert( self ); | |||||
free( self->items ); | |||||
free( self ); | |||||
} | |||||
// ------------------------------------------------------------- vector_get --- | |||||
const void * | |||||
vector_get( const vector_t *self, | |||||
size_t index ) | |||||
{ | |||||
assert( self ); | |||||
assert( self->size ); | |||||
assert( index < self->size ); | |||||
return (char*)(self->items) + index * self->item_size; | |||||
} | |||||
// ----------------------------------------------------------- vector_front --- | |||||
const void * | |||||
vector_front( const vector_t *self ) | |||||
{ | |||||
assert( self ); | |||||
assert( self->size ); | |||||
return vector_get( self, 0 ); | |||||
} | |||||
// ------------------------------------------------------------ vector_back --- | |||||
const void * | |||||
vector_back( const vector_t *self ) | |||||
{ | |||||
assert( self ); | |||||
assert( self->size ); | |||||
return vector_get( self, self->size-1 ); | |||||
} | |||||
// -------------------------------------------------------- vector_contains --- | |||||
int | |||||
vector_contains( const vector_t *self, | |||||
const void *item, | |||||
int (*cmp)(const void *, const void *) ) | |||||
{ | |||||
size_t i; | |||||
assert( self ); | |||||
for( i=0; i<self->size; ++i ) | |||||
{ | |||||
if( (*cmp)(item, vector_get(self,i) ) == 0 ) | |||||
{ | |||||
return 1; | |||||
} | |||||
} | |||||
return 0; | |||||
} | |||||
// ----------------------------------------------------------- vector_empty --- | |||||
int | |||||
vector_empty( const vector_t *self ) | |||||
{ | |||||
assert( self ); | |||||
return self->size == 0; | |||||
} | |||||
// ------------------------------------------------------------ vector_size --- | |||||
size_t | |||||
vector_size( const vector_t *self ) | |||||
{ | |||||
assert( self ); | |||||
return self->size; | |||||
} | |||||
// --------------------------------------------------------- vector_reserve --- | |||||
void | |||||
vector_reserve( vector_t *self, | |||||
const size_t size ) | |||||
{ | |||||
assert( self ); | |||||
if( self->capacity < size) | |||||
{ | |||||
self->items = realloc( self->items, size * self->item_size ); | |||||
self->capacity = size; | |||||
} | |||||
} | |||||
// -------------------------------------------------------- vector_capacity --- | |||||
size_t | |||||
vector_capacity( const vector_t *self ) | |||||
{ | |||||
assert( self ); | |||||
return self->capacity; | |||||
} | |||||
// ---------------------------------------------------------- vector_shrink --- | |||||
void | |||||
vector_shrink( vector_t *self ) | |||||
{ | |||||
assert( self ); | |||||
if( self->capacity > self->size ) | |||||
{ | |||||
self->items = realloc( self->items, self->size * self->item_size ); | |||||
} | |||||
self->capacity = self->size; | |||||
} | |||||
// ----------------------------------------------------------- vector_clear --- | |||||
void | |||||
vector_clear( vector_t *self ) | |||||
{ | |||||
assert( self ); | |||||
self->size = 0; | |||||
} | |||||
// ------------------------------------------------------------- vector_set --- | |||||
void | |||||
vector_set( vector_t *self, | |||||
const size_t index, | |||||
const void *item ) | |||||
{ | |||||
assert( self ); | |||||
assert( self->size ); | |||||
assert( index < self->size ); | |||||
memcpy( (char *)(self->items) + index * self->item_size, | |||||
item, self->item_size ); | |||||
} | |||||
// ---------------------------------------------------------- vector_insert --- | |||||
void | |||||
vector_insert( vector_t *self, | |||||
const size_t index, | |||||
const void *item ) | |||||
{ | |||||
assert( self ); | |||||
assert( index <= self->size); | |||||
if( self->capacity <= self->size ) | |||||
{ | |||||
vector_reserve(self, 2 * self->capacity ); | |||||
} | |||||
if( index < self->size ) | |||||
{ | |||||
memmove( (char *)(self->items) + (index + 1) * self->item_size, | |||||
(char *)(self->items) + (index + 0) * self->item_size, | |||||
(self->size - index) * self->item_size); | |||||
} | |||||
self->size++; | |||||
vector_set( self, index, item ); | |||||
} | |||||
// ----------------------------------------------------- vector_erase_range --- | |||||
void | |||||
vector_erase_range( vector_t *self, | |||||
const size_t first, | |||||
const size_t last ) | |||||
{ | |||||
assert( self ); | |||||
assert( first < self->size ); | |||||
assert( last < self->size+1 ); | |||||
assert( first < last ); | |||||
memmove( (char *)(self->items) + first * self->item_size, | |||||
(char *)(self->items) + last * self->item_size, | |||||
(self->size - last) * self->item_size); | |||||
self->size -= (last-first); | |||||
} | |||||
// ----------------------------------------------------------- vector_erase --- | |||||
void | |||||
vector_erase( vector_t *self, | |||||
const size_t index ) | |||||
{ | |||||
assert( self ); | |||||
assert( index < self->size ); | |||||
vector_erase_range( self, index, index+1 ); | |||||
} | |||||
// ------------------------------------------------------- vector_push_back --- | |||||
void | |||||
vector_push_back( vector_t *self, | |||||
const void *item ) | |||||
{ | |||||
vector_insert( self, self->size, item ); | |||||
} | |||||
// -------------------------------------------------------- vector_pop_back --- | |||||
void | |||||
vector_pop_back( vector_t *self ) | |||||
{ | |||||
assert( self ); | |||||
assert( self->size ); | |||||
self->size--; | |||||
} | |||||
// ---------------------------------------------------------- vector_resize --- | |||||
void | |||||
vector_resize( vector_t *self, | |||||
const size_t size ) | |||||
{ | |||||
assert( self ); | |||||
if( size > self->capacity) | |||||
{ | |||||
vector_reserve( self, size ); | |||||
self->size = self->capacity; | |||||
} | |||||
else | |||||
{ | |||||
self->size = size; | |||||
} | |||||
} | |||||
// -------------------------------------------------- vector_push_back_data --- | |||||
void | |||||
vector_push_back_data( vector_t *self, | |||||
const void * data, | |||||
const size_t count ) | |||||
{ | |||||
assert( self ); | |||||
assert( data ); | |||||
assert( count ); | |||||
if( self->capacity < (self->size+count) ) | |||||
{ | |||||
vector_reserve(self, self->size+count); | |||||
} | |||||
memmove( (char *)(self->items) + self->size * self->item_size, data, | |||||
count*self->item_size ); | |||||
self->size += count; | |||||
} | |||||
// ----------------------------------------------------- vector_insert_data --- | |||||
void | |||||
vector_insert_data( vector_t *self, | |||||
const size_t index, | |||||
const void * data, | |||||
const size_t count ) | |||||
{ | |||||
assert( self ); | |||||
assert( index < self->size ); | |||||
assert( data ); | |||||
assert( count ); | |||||
if( self->capacity < (self->size+count) ) | |||||
{ | |||||
vector_reserve(self, self->size+count); | |||||
} | |||||
memmove( (char *)(self->items) + (index + count ) * self->item_size, | |||||
(char *)(self->items) + (index ) * self->item_size, | |||||
count*self->item_size ); | |||||
memmove( (char *)(self->items) + index * self->item_size, data, | |||||
count*self->item_size ); | |||||
self->size += count; | |||||
} | |||||
// ------------------------------------------------------------ vector_sort --- | |||||
void | |||||
vector_sort( vector_t *self, | |||||
int (*cmp)(const void *, const void *) ) | |||||
{ | |||||
assert( self ); | |||||
assert( self->size ); | |||||
qsort(self->items, self->size, self->item_size, cmp); | |||||
} |
@@ -0,0 +1,353 @@ | |||||
/* ============================================================================ | |||||
* Freetype GL - A C OpenGL Freetype engine | |||||
* Platform: Any | |||||
* WWW: http://code.google.com/p/freetype-gl/ | |||||
* ---------------------------------------------------------------------------- | |||||
* Copyright 2011,2012 Nicolas P. Rougier. All rights reserved. | |||||
* | |||||
* Redistribution and use in source and binary forms, with or without | |||||
* modification, are permitted provided that the following conditions are met: | |||||
* | |||||
* 1. Redistributions of source code must retain the above copyright notice, | |||||
* this list of conditions and the following disclaimer. | |||||
* | |||||
* 2. Redistributions in binary form must reproduce the above copyright | |||||
* notice, this list of conditions and the following disclaimer in the | |||||
* documentation and/or other materials provided with the distribution. | |||||
* | |||||
* THIS SOFTWARE IS PROVIDED BY NICOLAS P. ROUGIER ''AS IS'' AND ANY EXPRESS OR | |||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | |||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO | |||||
* EVENT SHALL NICOLAS P. ROUGIER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, | |||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||||
* | |||||
* The views and conclusions contained in the software and documentation are | |||||
* those of the authors and should not be interpreted as representing official | |||||
* policies, either expressed or implied, of Nicolas P. Rougier. | |||||
* ============================================================================ | |||||
*/ | |||||
#ifndef __VECTOR_H__ | |||||
#define __VECTOR_H__ | |||||
#include <stdlib.h> | |||||
#ifdef __cplusplus | |||||
extern "C" { | |||||
#endif | |||||
#include <stddef.h> | |||||
/** | |||||
* @file vector.h | |||||
* @author Nicolas Rougier (Nicolas.Rougier@inria.fr) | |||||
* | |||||
* @defgroup vector Vector | |||||
* | |||||
* The vector structure and accompanying functions loosely mimic the STL C++ | |||||
* vector class. It is used by @ref texture-atlas (for storing nodes), @ref | |||||
* texture-font (for storing glyphs) and @ref font-manager (for storing fonts). | |||||
* More information at http://www.cppreference.com/wiki/container/vector/start | |||||
* | |||||
* <b>Example Usage</b>: | |||||
* @code | |||||
* #include "vector.h" | |||||
* | |||||
* int main( int arrgc, char *argv[] ) | |||||
* { | |||||
* int i,j = 1; | |||||
* vector_t * vector = vector_new( sizeof(int) ); | |||||
* vector_push_back( &i ); | |||||
* | |||||
* j = * (int *) vector_get( vector, 0 ); | |||||
* vector_delete( vector); | |||||
* | |||||
* return 0; | |||||
* } | |||||
* @endcode | |||||
* | |||||
* @{ | |||||
*/ | |||||
/** | |||||
* Generic vector structure. | |||||
* | |||||
* @memberof vector | |||||
*/ | |||||
typedef struct vector_t | |||||
{ | |||||
/** Pointer to dynamically allocated items. */ | |||||
void * items; | |||||
/** Number of items that can be held in currently allocated storage. */ | |||||
size_t capacity; | |||||
/** Number of items. */ | |||||
size_t size; | |||||
/** Size (in bytes) of a single item. */ | |||||
size_t item_size; | |||||
} vector_t; | |||||
/** | |||||
* Creates a new empty vector. | |||||
* | |||||
* @param item_size item size in bytes | |||||
* @return a new empty vector | |||||
* | |||||
*/ | |||||
vector_t * | |||||
vector_new( size_t item_size ); | |||||
/** | |||||
* Deletes a vector. | |||||
* | |||||
* @param self a vector structure | |||||
* | |||||
*/ | |||||
void | |||||
vector_delete( vector_t *self ); | |||||
/** | |||||
* Returns a pointer to the item located at specified index. | |||||
* | |||||
* @param self a vector structure | |||||
* @param index the index of the item to be returned | |||||
* @return pointer on the specified item | |||||
*/ | |||||
const void * | |||||
vector_get( const vector_t *self, | |||||
size_t index ); | |||||
/** | |||||
* Returns a pointer to the first item. | |||||
* | |||||
* @param self a vector structure | |||||
* @return pointer on the first item | |||||
*/ | |||||
const void * | |||||
vector_front( const vector_t *self ); | |||||
/** | |||||
* Returns a pointer to the last item | |||||
* | |||||
* @param self a vector structure | |||||
* @return pointer on the last item | |||||
*/ | |||||
const void * | |||||
vector_back( const vector_t *self ); | |||||
/** | |||||
* Check if an item is contained within the vector. | |||||
* | |||||
* @param self a vector structure | |||||
* @param item item to be searched in the vector | |||||
* @param cmp a pointer a comparison function | |||||
* @return 1 if item is contained within the vector, 0 otherwise | |||||
*/ | |||||
int | |||||
vector_contains( const vector_t *self, | |||||
const void *item, | |||||
int (*cmp)(const void *, const void *) ); | |||||
/** | |||||
* Checks whether the vector is empty. | |||||
* | |||||
* @param self a vector structure | |||||
* @return 1 if the vector is empty, 0 otherwise | |||||
*/ | |||||
int | |||||
vector_empty( const vector_t *self ); | |||||
/** | |||||
* Returns the number of items | |||||
* | |||||
* @param self a vector structure | |||||
* @return number of items | |||||
*/ | |||||
size_t | |||||
vector_size( const vector_t *self ); | |||||
/** | |||||
* Reserve storage such that it can hold at last size items. | |||||
* | |||||
* @param self a vector structure | |||||
* @param size the new storage capacity | |||||
*/ | |||||
void | |||||
vector_reserve( vector_t *self, | |||||
const size_t size ); | |||||
/** | |||||
* Returns current storage capacity | |||||
* | |||||
* @param self a vector structure | |||||
* @return storage capacity | |||||
*/ | |||||
size_t | |||||
vector_capacity( const vector_t *self ); | |||||
/** | |||||
* Decrease capacity to fit actual size. | |||||
* | |||||
* @param self a vector structure | |||||
*/ | |||||
void | |||||
vector_shrink( vector_t *self ); | |||||
/** | |||||
* Removes all items. | |||||
* | |||||
* @param self a vector structure | |||||
*/ | |||||
void | |||||
vector_clear( vector_t *self ); | |||||
/** | |||||
* Replace an item. | |||||
* | |||||
* @param self a vector structure | |||||
* @param index the index of the item to be replaced | |||||
* @param item the new item | |||||
*/ | |||||
void | |||||
vector_set( vector_t *self, | |||||
const size_t index, | |||||
const void *item ); | |||||
/** | |||||
* Erase an item. | |||||
* | |||||
* @param self a vector structure | |||||
* @param index the index of the item to be erased | |||||
*/ | |||||
void | |||||
vector_erase( vector_t *self, | |||||
const size_t index ); | |||||
/** | |||||
* Erase a range of items. | |||||
* | |||||
* @param self a vector structure | |||||
* @param first the index of the first item to be erased | |||||
* @param last the index of the last item to be erased | |||||
*/ | |||||
void | |||||
vector_erase_range( vector_t *self, | |||||
const size_t first, | |||||
const size_t last ); | |||||
/** | |||||
* Appends given item to the end of the vector. | |||||
* | |||||
* @param self a vector structure | |||||
* @param item the item to be inserted | |||||
*/ | |||||
void | |||||
vector_push_back( vector_t *self, | |||||
const void *item ); | |||||
/** | |||||
* Removes the last item of the vector. | |||||
* | |||||
* @param self a vector structure | |||||
*/ | |||||
void | |||||
vector_pop_back( vector_t *self ); | |||||
/** | |||||
* Resizes the vector to contain size items | |||||
* | |||||
* If the current size is less than size, additional items are appended and | |||||
* initialized with value. If the current size is greater than size, the | |||||
* vector is reduced to its first size elements. | |||||
* | |||||
* @param self a vector structure | |||||
* @param size the new size | |||||
*/ | |||||
void | |||||
vector_resize( vector_t *self, | |||||
const size_t size ); | |||||
/** | |||||
* Insert a single item at specified index. | |||||
* | |||||
* @param self a vector structure | |||||
* @param index location before which to insert item | |||||
* @param item the item to be inserted | |||||
*/ | |||||
void | |||||
vector_insert( vector_t *self, | |||||
const size_t index, | |||||
const void *item ); | |||||
/** | |||||
* Insert raw data at specified index. | |||||
* | |||||
* @param self a vector structure | |||||
* @param index location before which to insert item | |||||
* @param data a pointer to the items to be inserted | |||||
* @param count the number of items to be inserted | |||||
*/ | |||||
void | |||||
vector_insert_data( vector_t *self, | |||||
const size_t index, | |||||
const void * data, | |||||
const size_t count ); | |||||
/** | |||||
* Append raw data to the end of the vector. | |||||
* | |||||
* @param self a vector structure | |||||
* @param data a pointer to the items to be inserted | |||||
* @param count the number of items to be inserted | |||||
*/ | |||||
void | |||||
vector_push_back_data( vector_t *self, | |||||
const void * data, | |||||
const size_t count ); | |||||
/** | |||||
* Sort vector items according to cmp function. | |||||
* | |||||
* @param self a vector structure | |||||
* @param cmp a pointer a comparison function | |||||
*/ | |||||
void | |||||
vector_sort( vector_t *self, | |||||
int (*cmp)(const void *, const void *) ); | |||||
/** @} */ | |||||
#ifdef __cplusplus | |||||
} | |||||
#endif | |||||
#endif /* __VECTOR_H__ */ |