| @@ -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__ */ | |||