Browse Source

Add freetype-gl code

gh-pages
falkTX 9 years ago
parent
commit
586b9f9ea2
12 changed files with 3087 additions and 1 deletions
  1. +10
    -1
      dgl/Makefile
  2. +241
    -0
      dgl/src/freetype-gl/freetype-errors.h
  3. +44
    -0
      dgl/src/freetype-gl/freetype-gl.h
  4. +37
    -0
      dgl/src/freetype-gl/opengl.h
  5. +71
    -0
      dgl/src/freetype-gl/platform.h
  6. +345
    -0
      dgl/src/freetype-gl/texture-atlas.c
  7. +225
    -0
      dgl/src/freetype-gl/texture-atlas.h
  8. +711
    -0
      dgl/src/freetype-gl/texture-font.c
  9. +451
    -0
      dgl/src/freetype-gl/texture-font.h
  10. +237
    -0
      dgl/src/freetype-gl/vec234.h
  11. +362
    -0
      dgl/src/freetype-gl/vector.c
  12. +353
    -0
      dgl/src/freetype-gl/vector.h

+ 10
- 1
dgl/Makefile View File

@@ -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 $@



+ 241
- 0
dgl/src/freetype-gl/freetype-errors.h View File

@@ -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

+ 44
- 0
dgl/src/freetype-gl/freetype-gl.h View File

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

+ 37
- 0
dgl/src/freetype-gl/opengl.h View File

@@ -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

+ 71
- 0
dgl/src/freetype-gl/platform.h View File

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

+ 345
- 0
dgl/src/freetype-gl/texture-atlas.c View File

@@ -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 );
}
}

+ 225
- 0
dgl/src/freetype-gl/texture-atlas.h View File

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

+ 711
- 0
dgl/src/freetype-gl/texture-font.c View File

@@ -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;
}

+ 451
- 0
dgl/src/freetype-gl/texture-font.h View File

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