@@ -16,15 +16,21 @@ LINK_FLAGS += $(DGL_LIBS) | |||
OBJS = \ | |||
src/App.cpp.o \ | |||
src/Geometry.cpp.o \ | |||
src/Image.cpp.o \ | |||
src/ImageAboutWindow.cpp.o \ | |||
src/ImageButton.cpp.o \ | |||
src/ImageKnob.cpp.o \ | |||
src/ImageSlider.cpp.o \ | |||
src/Geometry.cpp.o \ | |||
src/Widget.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) | |||
OBJS += src/pugl/pugl_osx_extended.m.o | |||
endif | |||
@@ -53,6 +59,9 @@ all: $(TARGET) | |||
# -------------------------------------------------------------- | |||
%.c.o: %.c | |||
$(CC) $< $(BUILD_C_FLAGS) -c -o $@ | |||
%.cpp.o: %.cpp | |||
$(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__ */ |