summaryrefslogtreecommitdiff
path: root/src/freetype2/raster
diff options
context:
space:
mode:
authorscuri <scuri>2009-10-20 17:20:18 +0000
committerscuri <scuri>2009-10-20 17:20:18 +0000
commit27a4f9c4ac45ff65f941964f7351b64b1e6a9f35 (patch)
tree2f68c5d9ce5bf6cbc320ac17aef0a65a3ceb99a1 /src/freetype2/raster
parent2b70507615b2611fce4294c65bec7264644e2665 (diff)
*** empty log message ***
Diffstat (limited to 'src/freetype2/raster')
-rw-r--r--src/freetype2/raster/ftmisc.h30
-rw-r--r--src/freetype2/raster/ftraster.c994
-rw-r--r--src/freetype2/raster/ftrend1.c46
-rw-r--r--src/freetype2/raster/ftrend1.h4
-rw-r--r--src/freetype2/raster/raster.c1
-rw-r--r--src/freetype2/raster/rastpic.c89
-rw-r--r--src/freetype2/raster/rastpic.h50
7 files changed, 796 insertions, 418 deletions
diff --git a/src/freetype2/raster/ftmisc.h b/src/freetype2/raster/ftmisc.h
index c5dbd50..f04b540 100644
--- a/src/freetype2/raster/ftmisc.h
+++ b/src/freetype2/raster/ftmisc.h
@@ -5,7 +5,7 @@
/* Miscellaneous macros for stand-alone rasterizer (specification */
/* only). */
/* */
-/* Copyright 2005 by */
+/* Copyright 2005, 2009 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used */
@@ -27,7 +27,8 @@
#ifndef __FTMISC_H__
#define __FTMISC_H__
-#include <string.h> /* memset */
+ /* memset */
+#include FT_CONFIG_STANDARD_LIBRARY_H
#define FT_BEGIN_HEADER
#define FT_END_HEADER
@@ -51,6 +52,31 @@
(FT_ULong)_x4 )
+ /* from include/freetype2/ftsystem.h */
+
+ typedef struct FT_MemoryRec_* FT_Memory;
+
+ typedef void* (*FT_Alloc_Func)( FT_Memory memory,
+ long size );
+
+ typedef void (*FT_Free_Func)( FT_Memory memory,
+ void* block );
+
+ typedef void* (*FT_Realloc_Func)( FT_Memory memory,
+ long cur_size,
+ long new_size,
+ void* block );
+
+ typedef struct FT_MemoryRec_
+ {
+ void* user;
+
+ FT_Alloc_Func alloc;
+ FT_Free_Func free;
+ FT_Realloc_Func realloc;
+
+ } FT_MemoryRec;
+
/* from src/ftcalc.c */
#include <inttypes.h>
diff --git a/src/freetype2/raster/ftraster.c b/src/freetype2/raster/ftraster.c
index 4cfca4e..23ad592 100644
--- a/src/freetype2/raster/ftraster.c
+++ b/src/freetype2/raster/ftraster.c
@@ -4,7 +4,7 @@
/* */
/* The FreeType glyph rasterizer (body). */
/* */
-/* Copyright 1996-2001, 2002, 2003, 2005, 2007 by */
+/* Copyright 1996-2001, 2002, 2003, 2005, 2007, 2008, 2009 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -49,6 +49,10 @@
#ifdef _STANDALONE_
+#define FT_CONFIG_STANDARD_LIBRARY_H <stdlib.h>
+
+#include <string.h> /* for memset */
+
#include "ftmisc.h"
#include "ftimage.h"
@@ -58,6 +62,8 @@
#include "ftraster.h"
#include FT_INTERNAL_CALC_H /* for FT_MulDiv only */
+#include "rastpic.h"
+
#endif /* !_STANDALONE_ */
@@ -72,13 +78,15 @@
/* profile is simply an array of scanline intersections on a given */
/* dimension. A profile's main attributes are */
/* */
- /* o its scanline position boundaries, i.e. `Ymin' and `Ymax'. */
+ /* o its scanline position boundaries, i.e. `Ymin' and `Ymax' */
/* */
/* o an array of intersection coordinates for each scanline */
- /* between `Ymin' and `Ymax'. */
+ /* between `Ymin' and `Ymax' */
/* */
/* o a direction, indicating whether it was built going `up' or */
- /* `down', as this is very important for filling rules. */
+ /* `down', as this is very important for filling rules */
+ /* */
+ /* o its drop-out mode */
/* */
/* 2 - Sweeping the target map's scanlines in order to compute segment */
/* `spans' which are then filled. Additionally, this pass */
@@ -88,15 +96,15 @@
/* built from the bottom of the render pool, used as a stack. The */
/* following graphics shows the profile list under construction: */
/* */
- /* ____________________________________________________________ _ _ */
- /* | | | | | */
- /* | profile | coordinates for | profile | coordinates for |--> */
- /* | 1 | profile 1 | 2 | profile 2 |--> */
- /* |_________|___________________|_________|_________________|__ _ _ */
+ /* __________________________________________________________ _ _ */
+ /* | | | | | */
+ /* | profile | coordinates for | profile | coordinates for |--> */
+ /* | 1 | profile 1 | 2 | profile 2 |--> */
+ /* |_________|_________________|_________|_________________|__ _ _ */
/* */
- /* ^ ^ */
- /* | | */
- /* start of render pool top */
+ /* ^ ^ */
+ /* | | */
+ /* start of render pool top */
/* */
/* The top of the profile stack is kept in the `top' variable. */
/* */
@@ -140,13 +148,11 @@
/*************************************************************************/
/* define DEBUG_RASTER if you want to compile a debugging version */
-#define xxxDEBUG_RASTER
+/* #define DEBUG_RASTER */
- /* undefine FT_RASTER_OPTION_ANTI_ALIASING if you do not want to support */
- /* 5-levels anti-aliasing */
-#ifdef FT_CONFIG_OPTION_5_GRAY_LEVELS
-#define FT_RASTER_OPTION_ANTI_ALIASING
-#endif
+ /* define FT_RASTER_OPTION_ANTI_ALIASING if you want to support */
+ /* 5-levels anti-aliasing */
+/* #define FT_RASTER_OPTION_ANTI_ALIASING */
/* The size of the two-lines intermediate bitmap used */
/* for anti-aliasing, in bytes. */
@@ -183,13 +189,13 @@
/* Disable the tracing mechanism for simplicity -- developers can */
/* activate it easily by redefining these two macros. */
#ifndef FT_ERROR
-#define FT_ERROR( x ) do ; while ( 0 ) /* nothing */
+#define FT_ERROR( x ) do { } while ( 0 ) /* nothing */
#endif
#ifndef FT_TRACE
-#define FT_TRACE( x ) do ; while ( 0 ) /* nothing */
-#define FT_TRACE1( x ) do ; while ( 0 ) /* nothing */
-#define FT_TRACE6( x ) do ; while ( 0 ) /* nothing */
+#define FT_TRACE( x ) do { } while ( 0 ) /* nothing */
+#define FT_TRACE1( x ) do { } while ( 0 ) /* nothing */
+#define FT_TRACE6( x ) do { } while ( 0 ) /* nothing */
#endif
#define Raster_Err_None 0
@@ -199,9 +205,22 @@
#define Raster_Err_Invalid -4
#define Raster_Err_Unsupported -5
-#define ft_memset memset
+#define ft_memset memset
+
+#define FT_DEFINE_RASTER_FUNCS( class_, glyph_format_, raster_new_, \
+ raster_reset_, raster_set_mode_, \
+ raster_render_, raster_done_ ) \
+ const FT_Raster_Funcs class_ = \
+ { \
+ glyph_format_, \
+ raster_new_, \
+ raster_reset_, \
+ raster_set_mode_, \
+ raster_render_, \
+ raster_done_ \
+ };
-#else /* _STANDALONE_ */
+#else /* !_STANDALONE_ */
#include FT_INTERNAL_OBJECTS_H
@@ -217,7 +236,7 @@
#define Raster_Err_Unsupported Raster_Err_Cannot_Render_Glyph
-#endif /* _STANDALONE_ */
+#endif /* !_STANDALONE_ */
#ifndef FT_MEM_SET
@@ -306,13 +325,10 @@
} TPoint;
- typedef enum TFlow_
- {
- Flow_None = 0,
- Flow_Up = 1,
- Flow_Down = -1
-
- } TFlow;
+ /* values for the `flags' bit field */
+#define Flow_Up 0x8
+#define Overshoot_Top 0x10
+#define Overshoot_Bottom 0x20
/* States of each line, arc, and profile */
@@ -331,18 +347,21 @@
struct TProfile_
{
- FT_F26Dot6 X; /* current coordinate during sweep */
- PProfile link; /* link to next profile - various purpose */
- PLong offset; /* start of profile's data in render pool */
- int flow; /* Profile orientation: Asc/Descending */
- long height; /* profile's height in scanlines */
- long start; /* profile's starting scanline */
-
- unsigned countL; /* number of lines to step before this */
- /* profile becomes drawable */
-
- PProfile next; /* next profile in same contour, used */
- /* during drop-out control */
+ FT_F26Dot6 X; /* current coordinate during sweep */
+ PProfile link; /* link to next profile (various purposes) */
+ PLong offset; /* start of profile's data in render pool */
+ unsigned flags; /* Bit 0-2: drop-out mode */
+ /* Bit 3: profile orientation (up/down) */
+ /* Bit 4: is top profile? */
+ /* Bit 5: is bottom profile? */
+ long height; /* profile's height in scanlines */
+ long start; /* profile's starting scanline */
+
+ unsigned countL; /* number of lines to step before this */
+ /* profile becomes drawable */
+
+ PProfile next; /* next profile in same contour, used */
+ /* during drop-out control */
};
typedef PProfile TProfileList;
@@ -372,10 +391,10 @@
#define RAS_VARS /* void */
#define RAS_VAR /* void */
-#define FT_UNUSED_RASTER do ; while ( 0 )
+#define FT_UNUSED_RASTER do { } while ( 0 )
-#else /* FT_STATIC_RASTER */
+#else /* !FT_STATIC_RASTER */
#define RAS_ARGS PWorker worker,
@@ -387,10 +406,10 @@
#define FT_UNUSED_RASTER FT_UNUSED( worker )
-#endif /* FT_STATIC_RASTER */
+#endif /* !FT_STATIC_RASTER */
- typedef struct TWorker_ TWorker, *PWorker;
+ typedef struct TWorker_ TWorker, *PWorker;
/* prototypes used for sweep function dispatch */
@@ -417,65 +436,68 @@
#define FRAC( x ) ( (x) & ( ras.precision - 1 ) )
#define SCALED( x ) ( ( (x) << ras.scale_shift ) - ras.precision_half )
- /* Note that I have moved the location of some fields in the */
- /* structure to ensure that the most used variables are used */
- /* at the top. Thus, their offset can be coded with less */
- /* opcodes, and it results in a smaller executable. */
+#define IS_BOTTOM_OVERSHOOT( x ) ( CEILING( x ) - x >= ras.precision_half )
+#define IS_TOP_OVERSHOOT( x ) ( x - FLOOR( x ) >= ras.precision_half )
+
+ /* The most used variables are positioned at the top of the structure. */
+ /* Thus, their offset can be coded with less opcodes, resulting in a */
+ /* smaller executable. */
struct TWorker_
{
- Int precision_bits; /* precision related variables */
- Int precision;
- Int precision_half;
- Long precision_mask;
- Int precision_shift;
- Int precision_step;
- Int precision_jitter;
-
- Int scale_shift; /* == precision_shift for bitmaps */
+ Int precision_bits; /* precision related variables */
+ Int precision;
+ Int precision_half;
+ Long precision_mask;
+ Int precision_shift;
+ Int precision_step;
+ Int precision_jitter;
+
+ Int scale_shift; /* == precision_shift for bitmaps */
/* == precision_shift+1 for pixmaps */
- PLong buff; /* The profiles buffer */
- PLong sizeBuff; /* Render pool size */
- PLong maxBuff; /* Profiles buffer size */
- PLong top; /* Current cursor in buffer */
+ PLong buff; /* The profiles buffer */
+ PLong sizeBuff; /* Render pool size */
+ PLong maxBuff; /* Profiles buffer size */
+ PLong top; /* Current cursor in buffer */
- FT_Error error;
+ FT_Error error;
- Int numTurns; /* number of Y-turns in outline */
+ Int numTurns; /* number of Y-turns in outline */
- TPoint* arc; /* current Bezier arc pointer */
+ TPoint* arc; /* current Bezier arc pointer */
- UShort bWidth; /* target bitmap width */
- PByte bTarget; /* target bitmap buffer */
- PByte gTarget; /* target pixmap buffer */
+ UShort bWidth; /* target bitmap width */
+ PByte bTarget; /* target bitmap buffer */
+ PByte gTarget; /* target pixmap buffer */
- Long lastX, lastY, minY, maxY;
+ Long lastX, lastY;
+ Long minY, maxY;
- UShort num_Profs; /* current number of profiles */
+ UShort num_Profs; /* current number of profiles */
- Bool fresh; /* signals a fresh new profile which */
- /* 'start' field must be completed */
- Bool joint; /* signals that the last arc ended */
+ Bool fresh; /* signals a fresh new profile which */
+ /* `start' field must be completed */
+ Bool joint; /* signals that the last arc ended */
/* exactly on a scanline. Allows */
/* removal of doublets */
- PProfile cProfile; /* current profile */
- PProfile fProfile; /* head of linked list of profiles */
- PProfile gProfile; /* contour's first profile in case */
+ PProfile cProfile; /* current profile */
+ PProfile fProfile; /* head of linked list of profiles */
+ PProfile gProfile; /* contour's first profile in case */
/* of impact */
- TStates state; /* rendering state */
+ TStates state; /* rendering state */
FT_Bitmap target; /* description of target bit/pixmap */
FT_Outline outline;
- Long traceOfs; /* current offset in target bitmap */
- Long traceG; /* current offset in target pixmap */
+ Long traceOfs; /* current offset in target bitmap */
+ Long traceG; /* current offset in target pixmap */
- Short traceIncr; /* sweep's increment in target bitmap */
+ Short traceIncr; /* sweep's increment in target bitmap */
- Short gray_min_x; /* current min x during gray rendering */
- Short gray_max_x; /* current max x during gray rendering */
+ Short gray_min_x; /* current min x during gray rendering */
+ Short gray_max_x; /* current max x during gray rendering */
/* dispatch variables */
@@ -484,31 +506,31 @@
Function_Sweep_Span* Proc_Sweep_Drop;
Function_Sweep_Step* Proc_Sweep_Step;
- Byte dropOutControl; /* current drop_out control method */
+ Byte dropOutControl; /* current drop_out control method */
- Bool second_pass; /* indicates whether a horizontal pass */
+ Bool second_pass; /* indicates whether a horizontal pass */
/* should be performed to control */
/* drop-out accurately when calling */
/* Render_Glyph. Note that there is */
/* no horizontal pass during gray */
/* rendering. */
- TPoint arcs[3 * MaxBezier + 1]; /* The Bezier stack */
+ TPoint arcs[3 * MaxBezier + 1]; /* The Bezier stack */
- TBand band_stack[16]; /* band stack used for sub-banding */
- Int band_top; /* band stack top */
+ TBand band_stack[16]; /* band stack used for sub-banding */
+ Int band_top; /* band stack top */
#ifdef FT_RASTER_OPTION_ANTI_ALIASING
- Byte* grays;
+ Byte* grays;
- Byte gray_lines[RASTER_GRAY_LINES];
+ Byte gray_lines[RASTER_GRAY_LINES];
/* Intermediate table used to render the */
/* graylevels pixmaps. */
/* gray_lines is a buffer holding two */
/* monochrome scanlines */
- Short gray_width; /* width in bytes of one monochrome */
+ Short gray_width; /* width in bytes of one monochrome */
/* intermediate scanline of gray_lines. */
/* Each gray pixel takes 2 bits long there */
@@ -520,47 +542,90 @@
};
- typedef struct TRaster_
+ typedef struct TRaster_
{
- char* buffer;
- long buffer_size;
- void* memory;
- PWorker worker;
- Byte grays[5];
- Short gray_width;
+ char* buffer;
+ long buffer_size;
+ void* memory;
+ PWorker worker;
+ Byte grays[5];
+ Short gray_width;
} TRaster, *PRaster;
#ifdef FT_STATIC_RASTER
- static TWorker cur_ras;
+ static TWorker cur_ras;
#define ras cur_ras
-#else
+#else /* !FT_STATIC_RASTER */
#define ras (*worker)
-#endif /* FT_STATIC_RASTER */
+#endif /* !FT_STATIC_RASTER */
+
+#ifdef FT_RASTER_OPTION_ANTI_ALIASING
-static const char count_table[256] =
-{
- 0 , 1 , 1 , 2 , 1 , 2 , 2 , 3 , 1 , 2 , 2 , 3 , 2 , 3 , 3 , 4,
- 1 , 2 , 2 , 3 , 2 , 3 , 3 , 4 , 2 , 3 , 3 , 4 , 3 , 4 , 4 , 5,
- 1 , 2 , 2 , 3 , 2 , 3 , 3 , 4 , 2 , 3 , 3 , 4 , 3 , 4 , 4 , 5,
- 2 , 3 , 3 , 4 , 3 , 4 , 4 , 5 , 3 , 4 , 4 , 5 , 4 , 5 , 5 , 6,
- 1 , 2 , 2 , 3 , 2 , 3 , 3 , 4 , 2 , 3 , 3 , 4 , 3 , 4 , 4 , 5,
- 2 , 3 , 3 , 4 , 3 , 4 , 4 , 5 , 3 , 4 , 4 , 5 , 4 , 5 , 5 , 6,
- 2 , 3 , 3 , 4 , 3 , 4 , 4 , 5 , 3 , 4 , 4 , 5 , 4 , 5 , 5 , 6,
- 3 , 4 , 4 , 5 , 4 , 5 , 5 , 6 , 4 , 5 , 5 , 6 , 5 , 6 , 6 , 7,
- 1 , 2 , 2 , 3 , 2 , 3 , 3 , 4 , 2 , 3 , 3 , 4 , 3 , 4 , 4 , 5,
- 2 , 3 , 3 , 4 , 3 , 4 , 4 , 5 , 3 , 4 , 4 , 5 , 4 , 5 , 5 , 6,
- 2 , 3 , 3 , 4 , 3 , 4 , 4 , 5 , 3 , 4 , 4 , 5 , 4 , 5 , 5 , 6,
- 3 , 4 , 4 , 5 , 4 , 5 , 5 , 6 , 4 , 5 , 5 , 6 , 5 , 6 , 6 , 7,
- 2 , 3 , 3 , 4 , 3 , 4 , 4 , 5 , 3 , 4 , 4 , 5 , 4 , 5 , 5 , 6,
- 3 , 4 , 4 , 5 , 4 , 5 , 5 , 6 , 4 , 5 , 5 , 6 , 5 , 6 , 6 , 7,
- 3 , 4 , 4 , 5 , 4 , 5 , 5 , 6 , 4 , 5 , 5 , 6 , 5 , 6 , 6 , 7,
- 4 , 5 , 5 , 6 , 5 , 6 , 6 , 7 , 5 , 6 , 6 , 7 , 6 , 7 , 7 , 8 };
+ /* A lookup table used to quickly count set bits in four gray 2x2 */
+ /* cells. The values of the table have been produced with the */
+ /* following code: */
+ /* */
+ /* for ( i = 0; i < 256; i++ ) */
+ /* { */
+ /* l = 0; */
+ /* j = i; */
+ /* */
+ /* for ( c = 0; c < 4; c++ ) */
+ /* { */
+ /* l <<= 4; */
+ /* */
+ /* if ( j & 0x80 ) l++; */
+ /* if ( j & 0x40 ) l++; */
+ /* */
+ /* j = ( j << 2 ) & 0xFF; */
+ /* } */
+ /* printf( "0x%04X", l ); */
+ /* } */
+ /* */
+
+ static const short count_table[256] =
+ {
+ 0x0000, 0x0001, 0x0001, 0x0002, 0x0010, 0x0011, 0x0011, 0x0012,
+ 0x0010, 0x0011, 0x0011, 0x0012, 0x0020, 0x0021, 0x0021, 0x0022,
+ 0x0100, 0x0101, 0x0101, 0x0102, 0x0110, 0x0111, 0x0111, 0x0112,
+ 0x0110, 0x0111, 0x0111, 0x0112, 0x0120, 0x0121, 0x0121, 0x0122,
+ 0x0100, 0x0101, 0x0101, 0x0102, 0x0110, 0x0111, 0x0111, 0x0112,
+ 0x0110, 0x0111, 0x0111, 0x0112, 0x0120, 0x0121, 0x0121, 0x0122,
+ 0x0200, 0x0201, 0x0201, 0x0202, 0x0210, 0x0211, 0x0211, 0x0212,
+ 0x0210, 0x0211, 0x0211, 0x0212, 0x0220, 0x0221, 0x0221, 0x0222,
+ 0x1000, 0x1001, 0x1001, 0x1002, 0x1010, 0x1011, 0x1011, 0x1012,
+ 0x1010, 0x1011, 0x1011, 0x1012, 0x1020, 0x1021, 0x1021, 0x1022,
+ 0x1100, 0x1101, 0x1101, 0x1102, 0x1110, 0x1111, 0x1111, 0x1112,
+ 0x1110, 0x1111, 0x1111, 0x1112, 0x1120, 0x1121, 0x1121, 0x1122,
+ 0x1100, 0x1101, 0x1101, 0x1102, 0x1110, 0x1111, 0x1111, 0x1112,
+ 0x1110, 0x1111, 0x1111, 0x1112, 0x1120, 0x1121, 0x1121, 0x1122,
+ 0x1200, 0x1201, 0x1201, 0x1202, 0x1210, 0x1211, 0x1211, 0x1212,
+ 0x1210, 0x1211, 0x1211, 0x1212, 0x1220, 0x1221, 0x1221, 0x1222,
+ 0x1000, 0x1001, 0x1001, 0x1002, 0x1010, 0x1011, 0x1011, 0x1012,
+ 0x1010, 0x1011, 0x1011, 0x1012, 0x1020, 0x1021, 0x1021, 0x1022,
+ 0x1100, 0x1101, 0x1101, 0x1102, 0x1110, 0x1111, 0x1111, 0x1112,
+ 0x1110, 0x1111, 0x1111, 0x1112, 0x1120, 0x1121, 0x1121, 0x1122,
+ 0x1100, 0x1101, 0x1101, 0x1102, 0x1110, 0x1111, 0x1111, 0x1112,
+ 0x1110, 0x1111, 0x1111, 0x1112, 0x1120, 0x1121, 0x1121, 0x1122,
+ 0x1200, 0x1201, 0x1201, 0x1202, 0x1210, 0x1211, 0x1211, 0x1212,
+ 0x1210, 0x1211, 0x1211, 0x1212, 0x1220, 0x1221, 0x1221, 0x1222,
+ 0x2000, 0x2001, 0x2001, 0x2002, 0x2010, 0x2011, 0x2011, 0x2012,
+ 0x2010, 0x2011, 0x2011, 0x2012, 0x2020, 0x2021, 0x2021, 0x2022,
+ 0x2100, 0x2101, 0x2101, 0x2102, 0x2110, 0x2111, 0x2111, 0x2112,
+ 0x2110, 0x2111, 0x2111, 0x2112, 0x2120, 0x2121, 0x2121, 0x2122,
+ 0x2100, 0x2101, 0x2101, 0x2102, 0x2110, 0x2111, 0x2111, 0x2112,
+ 0x2110, 0x2111, 0x2111, 0x2112, 0x2120, 0x2121, 0x2121, 0x2122,
+ 0x2200, 0x2201, 0x2201, 0x2202, 0x2210, 0x2211, 0x2211, 0x2212,
+ 0x2210, 0x2211, 0x2211, 0x2212, 0x2220, 0x2221, 0x2221, 0x2222
+ };
+
+#endif /* FT_RASTER_OPTION_ANTI_ALIASING */
@@ -579,7 +644,7 @@ static const char count_table[256] =
/* Set_High_Precision */
/* */
/* <Description> */
- /* Sets precision variables according to param flag. */
+ /* Set precision variables according to param flag. */
/* */
/* <Input> */
/* High :: Set to True for high precision (typically for ppem < 18), */
@@ -590,9 +655,9 @@ static const char count_table[256] =
{
if ( High )
{
- ras.precision_bits = 10;
- ras.precision_step = 128;
- ras.precision_jitter = 24;
+ ras.precision_bits = 12;
+ ras.precision_step = 256;
+ ras.precision_jitter = 50;
}
else
{
@@ -616,17 +681,21 @@ static const char count_table[256] =
/* New_Profile */
/* */
/* <Description> */
- /* Creates a new profile in the render pool. */
+ /* Create a new profile in the render pool. */
/* */
/* <Input> */
- /* aState :: The state/orientation of the new profile. */
+ /* aState :: The state/orientation of the new profile. */
+ /* */
+ /* overshoot :: Whether the profile's unrounded start position */
+ /* differs by at least a half pixel. */
/* */
/* <Return> */
/* SUCCESS on success. FAILURE in case of overflow or of incoherent */
/* profile. */
/* */
static Bool
- New_Profile( RAS_ARGS TStates aState )
+ New_Profile( RAS_ARGS TStates aState,
+ Bool overshoot )
{
if ( !ras.fProfile )
{
@@ -641,30 +710,36 @@ static const char count_table[256] =
return FAILURE;
}
+ ras.cProfile->flags = 0;
+ ras.cProfile->start = 0;
+ ras.cProfile->height = 0;
+ ras.cProfile->offset = ras.top;
+ ras.cProfile->link = (PProfile)0;
+ ras.cProfile->next = (PProfile)0;
+ ras.cProfile->flags = ras.dropOutControl;
+
switch ( aState )
{
case Ascending_State:
- ras.cProfile->flow = Flow_Up;
+ ras.cProfile->flags |= Flow_Up;
+ if ( overshoot )
+ ras.cProfile->flags |= Overshoot_Bottom;
+
FT_TRACE6(( "New ascending profile = %lx\n", (long)ras.cProfile ));
break;
case Descending_State:
- ras.cProfile->flow = Flow_Down;
+ if ( overshoot )
+ ras.cProfile->flags |= Overshoot_Top;
FT_TRACE6(( "New descending profile = %lx\n", (long)ras.cProfile ));
break;
default:
- FT_ERROR(( "New_Profile: invalid profile direction!\n" ));
+ FT_ERROR(( "New_Profile: invalid profile direction\n" ));
ras.error = Raster_Err_Invalid;
return FAILURE;
}
- ras.cProfile->start = 0;
- ras.cProfile->height = 0;
- ras.cProfile->offset = ras.top;
- ras.cProfile->link = (PProfile)0;
- ras.cProfile->next = (PProfile)0;
-
if ( !ras.gProfile )
ras.gProfile = ras.cProfile;
@@ -682,13 +757,17 @@ static const char count_table[256] =
/* End_Profile */
/* */
/* <Description> */
- /* Finalizes the current profile. */
+ /* Finalize the current profile. */
+ /* */
+ /* <Input> */
+ /* overshoot :: Whether the profile's unrounded end position differs */
+ /* by at least a half pixel. */
/* */
/* <Return> */
/* SUCCESS on success. FAILURE in case of overflow or incoherency. */
/* */
static Bool
- End_Profile( RAS_ARG )
+ End_Profile( RAS_ARGS Bool overshoot )
{
Long h;
PProfile oldProfile;
@@ -698,7 +777,7 @@ static const char count_table[256] =
if ( h < 0 )
{
- FT_ERROR(( "End_Profile: negative height encountered!\n" ));
+ FT_ERROR(( "End_Profile: negative height encountered\n" ));
ras.error = Raster_Err_Neg_Height;
return FAILURE;
}
@@ -708,15 +787,24 @@ static const char count_table[256] =
FT_TRACE6(( "Ending profile %lx, start = %ld, height = %ld\n",
(long)ras.cProfile, ras.cProfile->start, h ));
- oldProfile = ras.cProfile;
ras.cProfile->height = h;
- ras.cProfile = (PProfile)ras.top;
+ if ( overshoot )
+ {
+ if ( ras.cProfile->flags & Flow_Up )
+ ras.cProfile->flags |= Overshoot_Top;
+ else
+ ras.cProfile->flags |= Overshoot_Bottom;
+ }
+
+ oldProfile = ras.cProfile;
+ ras.cProfile = (PProfile)ras.top;
- ras.top += AlignProfileSize;
+ ras.top += AlignProfileSize;
ras.cProfile->height = 0;
ras.cProfile->offset = ras.top;
- oldProfile->next = ras.cProfile;
+
+ oldProfile->next = ras.cProfile;
ras.num_Profs++;
}
@@ -739,7 +827,7 @@ static const char count_table[256] =
/* Insert_Y_Turn */
/* */
/* <Description> */
- /* Inserts a salient into the sorted list placed on top of the render */
+ /* Insert a salient into the sorted list placed on top of the render */
/* pool. */
/* */
/* <Input> */
@@ -794,7 +882,7 @@ static const char count_table[256] =
/* Finalize_Profile_Table */
/* */
/* <Description> */
- /* Adjusts all links in the profiles list. */
+ /* Adjust all links in the profiles list. */
/* */
/* <Return> */
/* SUCCESS on success. FAILURE in case of overflow. */
@@ -808,10 +896,10 @@ static const char count_table[256] =
n = ras.num_Profs;
+ p = ras.fProfile;
- if ( n > 1 )
+ if ( n > 1 && p )
{
- p = ras.fProfile;
while ( n > 0 )
{
if ( n > 1 )
@@ -819,23 +907,21 @@ static const char count_table[256] =
else
p->link = NULL;
- switch ( p->flow )
+ if ( p->flags & Flow_Up )
+ {
+ bottom = (Int)p->start;
+ top = (Int)( p->start + p->height - 1 );
+ }
+ else
{
- case Flow_Down:
bottom = (Int)( p->start - p->height + 1 );
top = (Int)p->start;
p->start = bottom;
p->offset += p->height - 1;
- break;
-
- case Flow_Up:
- default:
- bottom = (Int)p->start;
- top = (Int)( p->start + p->height - 1 );
}
- if ( Insert_Y_Turn( RAS_VARS bottom ) ||
- Insert_Y_Turn( RAS_VARS top + 1 ) )
+ if ( Insert_Y_Turn( RAS_VARS bottom ) ||
+ Insert_Y_Turn( RAS_VARS top + 1 ) )
return FAILURE;
p = p->link;
@@ -855,7 +941,7 @@ static const char count_table[256] =
/* Split_Conic */
/* */
/* <Description> */
- /* Subdivides one conic Bezier into two joint sub-arcs in the Bezier */
+ /* Subdivide one conic Bezier into two joint sub-arcs in the Bezier */
/* stack. */
/* */
/* <Input> */
@@ -894,7 +980,7 @@ static const char count_table[256] =
/* Split_Cubic */
/* */
/* <Description> */
- /* Subdivides a third-order Bezier arc into two joint sub-arcs in the */
+ /* Subdivide a third-order Bezier arc into two joint sub-arcs in the */
/* Bezier stack. */
/* */
/* <Note> */
@@ -936,7 +1022,7 @@ static const char count_table[256] =
/* Line_Up */
/* */
/* <Description> */
- /* Computes the x-coordinates of an ascending line segment and stores */
+ /* Compute the x-coordinates of an ascending line segment and store */
/* them in the render pool. */
/* */
/* <Input> */
@@ -1075,8 +1161,8 @@ static const char count_table[256] =
/* Line_Down */
/* */
/* <Description> */
- /* Computes the x-coordinates of an descending line segment and */
- /* stores them in the render pool. */
+ /* Compute the x-coordinates of an descending line segment and store */
+ /* them in the render pool. */
/* */
/* <Input> */
/* x1 :: The x-coordinate of the segment's start point. */
@@ -1126,7 +1212,7 @@ static const char count_table[256] =
/* Bezier_Up */
/* */
/* <Description> */
- /* Computes the x-coordinates of an ascending Bezier arc and stores */
+ /* Compute the x-coordinates of an ascending Bezier arc and store */
/* them in the render pool. */
/* */
/* <Input> */
@@ -1227,7 +1313,7 @@ static const char count_table[256] =
}
else
{
- *top++ = arc[degree].x + FMulDiv( arc[0].x-arc[degree].x,
+ *top++ = arc[degree].x + FMulDiv( arc[0].x - arc[degree].x,
e - y1, y2 - y1 );
arc -= degree;
e += ras.precision;
@@ -1259,7 +1345,7 @@ static const char count_table[256] =
/* Bezier_Down */
/* */
/* <Description> */
- /* Computes the x-coordinates of an descending Bezier arc and stores */
+ /* Compute the x-coordinates of an descending Bezier arc and store */
/* them in the render pool. */
/* */
/* <Input> */
@@ -1308,7 +1394,7 @@ static const char count_table[256] =
/* Line_To */
/* */
/* <Description> */
- /* Injects a new line segment and adjusts Profiles list. */
+ /* Inject a new line segment and adjust the Profiles list. */
/* */
/* <Input> */
/* x :: The x-coordinate of the segment's end point (its start point */
@@ -1332,13 +1418,15 @@ static const char count_table[256] =
case Unknown_State:
if ( y > ras.lastY )
{
- if ( New_Profile( RAS_VARS Ascending_State ) )
+ if ( New_Profile( RAS_VARS Ascending_State,
+ IS_BOTTOM_OVERSHOOT( ras.lastY ) ) )
return FAILURE;
}
else
{
if ( y < ras.lastY )
- if ( New_Profile( RAS_VARS Descending_State ) )
+ if ( New_Profile( RAS_VARS Descending_State,
+ IS_TOP_OVERSHOOT( ras.lastY ) ) )
return FAILURE;
}
break;
@@ -1346,8 +1434,9 @@ static const char count_table[256] =
case Ascending_State:
if ( y < ras.lastY )
{
- if ( End_Profile( RAS_VAR ) ||
- New_Profile( RAS_VARS Descending_State ) )
+ if ( End_Profile( RAS_VARS IS_TOP_OVERSHOOT( ras.lastY ) ) ||
+ New_Profile( RAS_VARS Descending_State,
+ IS_TOP_OVERSHOOT( ras.lastY ) ) )
return FAILURE;
}
break;
@@ -1355,8 +1444,9 @@ static const char count_table[256] =
case Descending_State:
if ( y > ras.lastY )
{
- if ( End_Profile( RAS_VAR ) ||
- New_Profile( RAS_VARS Ascending_State ) )
+ if ( End_Profile( RAS_VARS IS_BOTTOM_OVERSHOOT( ras.lastY ) ) ||
+ New_Profile( RAS_VARS Ascending_State,
+ IS_BOTTOM_OVERSHOOT( ras.lastY ) ) )
return FAILURE;
}
break;
@@ -1371,13 +1461,13 @@ static const char count_table[256] =
{
case Ascending_State:
if ( Line_Up( RAS_VARS ras.lastX, ras.lastY,
- x, y, ras.minY, ras.maxY ) )
+ x, y, ras.minY, ras.maxY ) )
return FAILURE;
break;
case Descending_State:
if ( Line_Down( RAS_VARS ras.lastX, ras.lastY,
- x, y, ras.minY, ras.maxY ) )
+ x, y, ras.minY, ras.maxY ) )
return FAILURE;
break;
@@ -1398,7 +1488,7 @@ static const char count_table[256] =
/* Conic_To */
/* */
/* <Description> */
- /* Injects a new conic arc and adjusts the profile list. */
+ /* Inject a new conic arc and adjust the profile list. */
/* */
/* <Input> */
/* cx :: The x-coordinate of the arc's new control point. */
@@ -1428,8 +1518,10 @@ static const char count_table[256] =
ras.arc = ras.arcs;
ras.arc[2].x = ras.lastX;
ras.arc[2].y = ras.lastY;
- ras.arc[1].x = cx; ras.arc[1].y = cy;
- ras.arc[0].x = x; ras.arc[0].y = y;
+ ras.arc[1].x = cx;
+ ras.arc[1].y = cy;
+ ras.arc[0].x = x;
+ ras.arc[0].y = y;
do
{
@@ -1469,13 +1561,17 @@ static const char count_table[256] =
state_bez = y1 < y3 ? Ascending_State : Descending_State;
if ( ras.state != state_bez )
{
+ Bool o = state_bez == Ascending_State ? IS_BOTTOM_OVERSHOOT( y1 )
+ : IS_TOP_OVERSHOOT( y1 );
+
+
/* finalize current profile if any */
- if ( ras.state != Unknown_State &&
- End_Profile( RAS_VAR ) )
+ if ( ras.state != Unknown_State &&
+ End_Profile( RAS_VARS o ) )
goto Fail;
/* create a new profile */
- if ( New_Profile( RAS_VARS state_bez ) )
+ if ( New_Profile( RAS_VARS state_bez, o ) )
goto Fail;
}
@@ -1508,7 +1604,7 @@ static const char count_table[256] =
/* Cubic_To */
/* */
/* <Description> */
- /* Injects a new cubic arc and adjusts the profile list. */
+ /* Inject a new cubic arc and adjust the profile list. */
/* */
/* <Input> */
/* cx1 :: The x-coordinate of the arc's first new control point. */
@@ -1544,9 +1640,12 @@ static const char count_table[256] =
ras.arc = ras.arcs;
ras.arc[3].x = ras.lastX;
ras.arc[3].y = ras.lastY;
- ras.arc[2].x = cx1; ras.arc[2].y = cy1;
- ras.arc[1].x = cx2; ras.arc[1].y = cy2;
- ras.arc[0].x = x; ras.arc[0].y = y;
+ ras.arc[2].x = cx1;
+ ras.arc[2].y = cy1;
+ ras.arc[1].x = cx2;
+ ras.arc[1].y = cy2;
+ ras.arc[0].x = x;
+ ras.arc[0].y = y;
do
{
@@ -1598,11 +1697,16 @@ static const char count_table[256] =
/* detect a change of direction */
if ( ras.state != state_bez )
{
- if ( ras.state != Unknown_State &&
- End_Profile( RAS_VAR ) )
+ Bool o = state_bez == Ascending_State ? IS_BOTTOM_OVERSHOOT( y1 )
+ : IS_TOP_OVERSHOOT( y1 );
+
+
+ /* finalize current profile if any */
+ if ( ras.state != Unknown_State &&
+ End_Profile( RAS_VARS o ) )
goto Fail;
- if ( New_Profile( RAS_VARS state_bez ) )
+ if ( New_Profile( RAS_VARS state_bez, o ) )
goto Fail;
}
@@ -1646,7 +1750,7 @@ static const char count_table[256] =
/* Decompose_Curve */
/* */
/* <Description> */
- /* Scans the outline arrays in order to emit individual segments and */
+ /* Scan the outline arrays in order to emit individual segments and */
/* Beziers by calling Line_To() and Bezier_To(). It handles all */
/* weird cases, like when the first point is off the curve, or when */
/* there are simply no `on' points in the contour! */
@@ -1695,8 +1799,13 @@ static const char count_table[256] =
v_control = v_start;
point = points + first;
- tags = ras.outline.tags + first;
- tag = FT_CURVE_TAG( tags[0] );
+ tags = ras.outline.tags + first;
+
+ /* set scan mode if necessary */
+ if ( tags[0] & FT_CURVE_TAG_HAS_SCANMODE )
+ ras.dropOutControl = (Byte)tags[0] >> 5;
+
+ tag = FT_CURVE_TAG( tags[0] );
/* A contour cannot start with a cubic control point! */
if ( tag == FT_CURVE_TAG_CUBIC )
@@ -1867,7 +1976,7 @@ static const char count_table[256] =
/* Convert_Glyph */
/* */
/* <Description> */
- /* Converts a glyph into a series of segments and arcs and makes a */
+ /* Convert a glyph into a series of segments and arcs and make a */
/* profiles list with them. */
/* */
/* <Input> */
@@ -1902,27 +2011,36 @@ static const char count_table[256] =
for ( i = 0; i < ras.outline.n_contours; i++ )
{
+ Bool o;
+
+
ras.state = Unknown_State;
ras.gProfile = NULL;
if ( Decompose_Curve( RAS_VARS (unsigned short)start,
- ras.outline.contours[i],
- flipped ) )
+ ras.outline.contours[i],
+ flipped ) )
return FAILURE;
start = ras.outline.contours[i] + 1;
- /* We must now see whether the extreme arcs join or not */
+ /* we must now check whether the extreme arcs join or not */
if ( FRAC( ras.lastY ) == 0 &&
ras.lastY >= ras.minY &&
ras.lastY <= ras.maxY )
- if ( ras.gProfile && ras.gProfile->flow == ras.cProfile->flow )
+ if ( ras.gProfile &&
+ ( ras.gProfile->flags & Flow_Up ) ==
+ ( ras.cProfile->flags & Flow_Up ) )
ras.top--;
/* Note that ras.gProfile can be nil if the contour was too small */
/* to be drawn. */
lastProfile = ras.cProfile;
- if ( End_Profile( RAS_VAR ) )
+ if ( ras.cProfile->flags & Flow_Up )
+ o = IS_TOP_OVERSHOOT( ras.lastY );
+ else
+ o = IS_BOTTOM_OVERSHOOT( ras.lastY );
+ if ( End_Profile( RAS_VARS o ) )
return FAILURE;
/* close the `next profile in contour' linked list */
@@ -2042,7 +2160,7 @@ static const char count_table[256] =
while ( current )
{
current->X = *current->offset;
- current->offset += current->flow;
+ current->offset += current->flags & Flow_Up ? 1 : -1;
current->height--;
current = current->link;
}
@@ -2148,8 +2266,10 @@ static const char count_table[256] =
f1 = (Byte) ( 0xFF >> ( e1 & 7 ) );
f2 = (Byte) ~( 0x7F >> ( e2 & 7 ) );
- if ( ras.gray_min_x > c1 ) ras.gray_min_x = (short)c1;
- if ( ras.gray_max_x < c2 ) ras.gray_max_x = (short)c2;
+ if ( ras.gray_min_x > c1 )
+ ras.gray_min_x = (short)c1;
+ if ( ras.gray_max_x < c2 )
+ ras.gray_max_x = (short)c2;
target = ras.bTarget + ras.traceOfs + c1;
c2 -= c1;
@@ -2182,38 +2302,63 @@ static const char count_table[256] =
PProfile left,
PProfile right )
{
- Long e1, e2;
+ Long e1, e2, pxl;
Short c1, f1;
/* Drop-out control */
- e1 = CEILING( x1 );
- e2 = FLOOR ( x2 );
+ /* e2 x2 x1 e1 */
+ /* */
+ /* ^ | */
+ /* | | */
+ /* +-------------+---------------------+------------+ */
+ /* | | */
+ /* | v */
+ /* */
+ /* pixel contour contour pixel */
+ /* center center */
+
+ /* drop-out mode scan conversion rules (as defined in OpenType) */
+ /* --------------------------------------------------------------- */
+ /* 0 1, 2, 3 */
+ /* 1 1, 2, 4 */
+ /* 2 1, 2 */
+ /* 3 same as mode 2 */
+ /* 4 1, 2, 5 */
+ /* 5 1, 2, 6 */
+ /* 6, 7 same as mode 2 */
+
+ e1 = CEILING( x1 );
+ e2 = FLOOR ( x2 );
+ pxl = e1;
if ( e1 > e2 )
{
+ Int dropOutControl = left->flags & 7;
+
+
if ( e1 == e2 + ras.precision )
{
- switch ( ras.dropOutControl )
+ switch ( dropOutControl )
{
- case 1:
- e1 = e2;
+ case 0: /* simple drop-outs including stubs */
+ pxl = e2;
break;
- case 4:
- e1 = CEILING( (x1 + x2 + 1) / 2 );
+ case 4: /* smart drop-outs including stubs */
+ pxl = FLOOR( ( x1 + x2 - 1 ) / 2 + ras.precision_half );
break;
- case 2:
- case 5:
- /* Drop-out Control Rule #4 */
+ case 1: /* simple drop-outs excluding stubs */
+ case 5: /* smart drop-outs excluding stubs */
+
+ /* Drop-out Control Rules #4 and #6 */
- /* The spec is not very clear regarding rule #4. It */
- /* presents a method that is way too costly to implement */
- /* while the general idea seems to get rid of `stubs'. */
+ /* The specification neither provides an exact definition */
+ /* of a `stub' nor gives exact rules to exclude them. */
/* */
- /* Here, we only get rid of stubs recognized if: */
+ /* Here the constraints we use to recognize a stub. */
/* */
/* upper stub: */
/* */
@@ -2227,59 +2372,64 @@ static const char count_table[256] =
/* - P_Left is the successor of P_Right in that contour */
/* - y is the bottom of P_Left */
/* */
+ /* We draw a stub if the following constraints are met. */
+ /* */
+ /* - for an upper or lower stub, there is top or bottom */
+ /* overshoot, respectively */
+ /* - the covered interval is greater or equal to a half */
+ /* pixel */
+
+ /* upper stub test */
+ if ( left->next == right &&
+ left->height <= 0 &&
+ !( left->flags & Overshoot_Top &&
+ x2 - x1 >= ras.precision_half ) )
+ return;
- /* FIXXXME: uncommenting this line solves the disappearing */
- /* bit problem in the `7' of verdana 10pts, but */
- /* makes a new one in the `C' of arial 14pts */
-
-#if 0
- if ( x2 - x1 < ras.precision_half )
-#endif
- {
- /* upper stub test */
- if ( left->next == right && left->height <= 0 )
- return;
-
- /* lower stub test */
- if ( right->next == left && left->start == y )
- return;
- }
-
- /* check that the rightmost pixel isn't set */
-
- e1 = TRUNC( e1 );
-
- c1 = (Short)( e1 >> 3 );
- f1 = (Short)( e1 & 7 );
-
- if ( e1 >= 0 && e1 < ras.bWidth &&
- ras.bTarget[ras.traceOfs + c1] & ( 0x80 >> f1 ) )
+ /* lower stub test */
+ if ( right->next == left &&
+ left->start == y &&
+ !( left->flags & Overshoot_Bottom &&
+ x2 - x1 >= ras.precision_half ) )
return;
- if ( ras.dropOutControl == 2 )
- e1 = e2;
+ if ( dropOutControl == 1 )
+ pxl = e2;
else
- e1 = CEILING( ( x1 + x2 + 1 ) / 2 );
-
+ pxl = FLOOR( ( x1 + x2 - 1 ) / 2 + ras.precision_half );
break;
- default:
- return; /* unsupported mode */
+ default: /* modes 2, 3, 6, 7 */
+ return; /* no drop-out control */
}
+
+ /* check that the other pixel isn't set */
+ e1 = pxl == e1 ? e2 : e1;
+
+ e1 = TRUNC( e1 );
+
+ c1 = (Short)( e1 >> 3 );
+ f1 = (Short)( e1 & 7 );
+
+ if ( e1 >= 0 && e1 < ras.bWidth &&
+ ras.bTarget[ras.traceOfs + c1] & ( 0x80 >> f1 ) )
+ return;
}
else
return;
}
- e1 = TRUNC( e1 );
+ e1 = TRUNC( pxl );
if ( e1 >= 0 && e1 < ras.bWidth )
{
c1 = (Short)( e1 >> 3 );
f1 = (Short)( e1 & 7 );
- if ( ras.gray_min_x > c1 ) ras.gray_min_x = c1;
- if ( ras.gray_max_x < c1 ) ras.gray_max_x = c1;
+ if ( ras.gray_min_x > c1 )
+ ras.gray_min_x = c1;
+ if ( ras.gray_max_x < c1 )
+ ras.gray_max_x = c1;
ras.bTarget[ras.traceOfs + c1] |= (char)( 0x80 >> f1 );
}
@@ -2363,74 +2513,88 @@ static const char count_table[256] =
PProfile left,
PProfile right )
{
- Long e1, e2;
+ Long e1, e2, pxl;
PByte bits;
Byte f1;
/* During the horizontal sweep, we only take care of drop-outs */
- e1 = CEILING( x1 );
- e2 = FLOOR ( x2 );
+ /* e1 + <-- pixel center */
+ /* | */
+ /* x1 ---+--> <-- contour */
+ /* | */
+ /* | */
+ /* x2 <--+--- <-- contour */
+ /* | */
+ /* | */
+ /* e2 + <-- pixel center */
+
+ e1 = CEILING( x1 );
+ e2 = FLOOR ( x2 );
+ pxl = e1;
if ( e1 > e2 )
{
+ Int dropOutControl = left->flags & 7;
+
+
if ( e1 == e2 + ras.precision )
{
- switch ( ras.dropOutControl )
+ switch ( dropOutControl )
{
- case 1:
- e1 = e2;
+ case 0: /* simple drop-outs including stubs */
+ pxl = e2;
break;
- case 4:
- e1 = CEILING( ( x1 + x2 + 1 ) / 2 );
+ case 4: /* smart drop-outs including stubs */
+ pxl = FLOOR( ( x1 + x2 - 1 ) / 2 + ras.precision_half );
break;
- case 2:
- case 5:
-
- /* Drop-out Control Rule #4 */
-
- /* The spec is not very clear regarding rule #4. It */
- /* presents a method that is way too costly to implement */
- /* while the general idea seems to get rid of `stubs'. */
- /* */
+ case 1: /* simple drop-outs excluding stubs */
+ case 5: /* smart drop-outs excluding stubs */
+ /* see Vertical_Sweep_Drop for details */
/* rightmost stub test */
- if ( left->next == right && left->height <= 0 )
+ if ( left->next == right &&
+ left->height <= 0 &&
+ !( left->flags & Overshoot_Top &&
+ x2 - x1 >= ras.precision_half ) )
return;
/* leftmost stub test */
- if ( right->next == left && left->start == y )
+ if ( right->next == left &&
+ left->start == y &&
+ !( left->flags & Overshoot_Bottom &&
+ x2 - x1 >= ras.precision_half ) )
return;
- /* check that the rightmost pixel isn't set */
-
- e1 = TRUNC( e1 );
+ if ( dropOutControl == 1 )
+ pxl = e2;
+ else
+ pxl = FLOOR( ( x1 + x2 - 1 ) / 2 + ras.precision_half );
+ break;
- bits = ras.bTarget + ( y >> 3 );
- f1 = (Byte)( 0x80 >> ( y & 7 ) );
+ default: /* modes 2, 3, 6, 7 */
+ return; /* no drop-out control */
+ }
- bits -= e1 * ras.target.pitch;
- if ( ras.target.pitch > 0 )
- bits += ( ras.target.rows - 1 ) * ras.target.pitch;
+ /* check that the other pixel isn't set */
+ e1 = pxl == e1 ? e2 : e1;
- if ( e1 >= 0 &&
- e1 < ras.target.rows &&
- *bits & f1 )
- return;
+ e1 = TRUNC( e1 );
- if ( ras.dropOutControl == 2 )
- e1 = e2;
- else
- e1 = CEILING( ( x1 + x2 + 1 ) / 2 );
+ bits = ras.bTarget + ( y >> 3 );
+ f1 = (Byte)( 0x80 >> ( y & 7 ) );
- break;
+ bits -= e1 * ras.target.pitch;
+ if ( ras.target.pitch > 0 )
+ bits += ( ras.target.rows - 1 ) * ras.target.pitch;
- default:
- return; /* unsupported mode */
- }
+ if ( e1 >= 0 &&
+ e1 < ras.target.rows &&
+ *bits & f1 )
+ return;
}
else
return;
@@ -2439,7 +2603,7 @@ static const char count_table[256] =
bits = ras.bTarget + ( y >> 3 );
f1 = (Byte)( 0x80 >> ( y & 7 ) );
- e1 = TRUNC( e1 );
+ e1 = TRUNC( pxl );
if ( e1 >= 0 && e1 < ras.target.rows )
{
@@ -2509,10 +2673,10 @@ static const char count_table[256] =
static void
Vertical_Gray_Sweep_Step( RAS_ARG )
{
- Int c1, c2;
- PByte pix, bit, bit2;
- char* count = (char*)count_table;
- Byte* grays;
+ Int c1, c2;
+ PByte pix, bit, bit2;
+ short* count = (short*)count_table;
+ Byte* grays;
ras.traceOfs += ras.gray_width;
@@ -2524,10 +2688,10 @@ static const char count_table[256] =
if ( ras.gray_max_x >= 0 )
{
- Long last_pixel = ras.target.width - 1;
- Int last_cell = last_pixel >> 2;
- Int last_bit = last_pixel & 3;
- Bool over = 0;
+ Long last_pixel = ras.target.width - 1;
+ Int last_cell = last_pixel >> 2;
+ Int last_bit = last_pixel & 3;
+ Bool over = 0;
if ( ras.gray_max_x >= last_cell && last_bit != 3 )
@@ -2539,8 +2703,8 @@ static const char count_table[256] =
if ( ras.gray_min_x < 0 )
ras.gray_min_x = 0;
- bit = ras.bTarget + ras.gray_min_x;
- bit2 = bit + ras.gray_width;
+ bit = ras.bTarget + ras.gray_min_x;
+ bit2 = bit + ras.gray_width;
c1 = ras.gray_max_x - ras.gray_min_x;
@@ -2625,32 +2789,30 @@ static const char count_table[256] =
/* During the horizontal sweep, we only take care of drop-outs */
+
e1 = CEILING( x1 );
e2 = FLOOR ( x2 );
if ( e1 > e2 )
{
+ Int dropOutControl = left->flags & 7;
+
+
if ( e1 == e2 + ras.precision )
{
- switch ( ras.dropOutControl )
+ switch ( dropOutControl )
{
- case 1:
+ case 0: /* simple drop-outs including stubs */
e1 = e2;
break;
- case 4:
- e1 = CEILING( ( x1 + x2 + 1 ) / 2 );
+ case 4: /* smart drop-outs including stubs */
+ e1 = FLOOR( ( x1 + x2 - 1 ) / 2 + ras.precision_half );
break;
- case 2:
- case 5:
-
- /* Drop-out Control Rule #4 */
-
- /* The spec is not very clear regarding rule #4. It */
- /* presents a method that is way too costly to implement */
- /* while the general idea seems to get rid of `stubs'. */
- /* */
+ case 1: /* simple drop-outs excluding stubs */
+ case 5: /* smart drop-outs excluding stubs */
+ /* see Vertical_Sweep_Drop for details */
/* rightmost stub test */
if ( left->next == right && left->height <= 0 )
@@ -2660,15 +2822,15 @@ static const char count_table[256] =
if ( right->next == left && left->start == y )
return;
- if ( ras.dropOutControl == 2 )
+ if ( dropOutControl == 1 )
e1 = e2;
else
- e1 = CEILING( ( x1 + x2 + 1 ) / 2 );
+ e1 = FLOOR( ( x1 + x2 - 1 ) / 2 + ras.precision_half );
break;
- default:
- return; /* unsupported mode */
+ default: /* modes 2, 3, 6, 7 */
+ return; /* no drop-out control */
}
}
else
@@ -2720,7 +2882,7 @@ static const char count_table[256] =
TProfileList draw_left, draw_right;
- /* Init empty linked lists */
+ /* initialize empty linked lists */
Init_Linked( &waiting );
@@ -2740,8 +2902,10 @@ static const char count_table[256] =
bottom = (Short)P->start;
top = (Short)( P->start + P->height - 1 );
- if ( min_Y > bottom ) min_Y = bottom;
- if ( max_Y < top ) max_Y = top;
+ if ( min_Y > bottom )
+ min_Y = bottom;
+ if ( max_Y < top )
+ max_Y = top;
P->X = 0;
InsNew( &waiting, P );
@@ -2749,18 +2913,18 @@ static const char count_table[256] =
P = Q;
}
- /* Check the Y-turns */
+ /* check the Y-turns */
if ( ras.numTurns == 0 )
{
ras.error = Raster_Err_Invalid;
return FAILURE;
}
- /* Now inits the sweep */
+ /* now initialize the sweep */
ras.Proc_Sweep_Init( RAS_VARS &min_Y, &max_Y );
- /* Then compute the distance of each profile from min_Y */
+ /* then compute the distance of each profile from min_Y */
P = waiting;
@@ -2770,18 +2934,18 @@ static const char count_table[256] =
P = P->link;
}
- /* Let's go */
+ /* let's go */
y = min_Y;
y_height = 0;
- if ( ras.numTurns > 0 &&
+ if ( ras.numTurns > 0 &&
ras.sizeBuff[-ras.numTurns] == min_Y )
ras.numTurns--;
while ( ras.numTurns > 0 )
{
- /* look in the waiting list for new activations */
+ /* check waiting list for new activations */
P = waiting;
@@ -2793,22 +2957,16 @@ static const char count_table[256] =
{
DelOld( &waiting, P );
- switch ( P->flow )
- {
- case Flow_Up:
+ if ( P->flags & Flow_Up )
InsNew( &draw_left, P );
- break;
-
- case Flow_Down:
+ else
InsNew( &draw_right, P );
- break;
- }
}
P = Q;
}
- /* Sort the drawing lists */
+ /* sort the drawing lists */
Sort( &draw_left );
Sort( &draw_right );
@@ -2818,7 +2976,7 @@ static const char count_table[256] =
while ( y < y_change )
{
- /* Let's trace */
+ /* let's trace */
dropouts = 0;
@@ -2837,22 +2995,28 @@ static const char count_table[256] =
x2 = xs;
}
- if ( x2 - x1 <= ras.precision )
- {
- e1 = FLOOR( x1 );
- e2 = CEILING( x2 );
+ e1 = FLOOR( x1 );
+ e2 = CEILING( x2 );
- if ( ras.dropOutControl != 0 &&
- ( e1 > e2 || e2 == e1 + ras.precision ) )
+ if ( x2 - x1 <= ras.precision &&
+ e1 != x1 && e2 != x2 )
+ {
+ if ( e1 > e2 || e2 == e1 + ras.precision )
{
- /* a drop out was detected */
+ Int dropOutControl = P_Left->flags & 7;
+
+
+ if ( dropOutControl != 2 )
+ {
+ /* a drop-out was detected */
- P_Left ->X = x1;
- P_Right->X = x2;
+ P_Left ->X = x1;
+ P_Right->X = x2;
- /* mark profile for drop-out processing */
- P_Left->countL = 1;
- dropouts++;
+ /* mark profile for drop-out processing */
+ P_Left->countL = 1;
+ dropouts++;
+ }
goto Skip_To_Next;
}
@@ -2866,9 +3030,9 @@ static const char count_table[256] =
P_Right = P_Right->link;
}
- /* now perform the dropouts _after_ the span drawing -- */
- /* drop-outs processing has been moved out of the loop */
- /* for performance tuning */
+ /* handle drop-outs _after_ the span drawing -- */
+ /* drop-out processing has been moved out of the loop */
+ /* for performance tuning */
if ( dropouts > 0 )
goto Scan_DropOuts;
@@ -2885,7 +3049,7 @@ static const char count_table[256] =
}
}
- /* Now finalize the profiles that needs it */
+ /* now finalize the profiles that need it */
P = draw_left;
while ( P )
@@ -2906,7 +3070,7 @@ static const char count_table[256] =
}
}
- /* for gray-scaling, flushes the bitmap scanline cache */
+ /* for gray-scaling, flush the bitmap scanline cache */
while ( y <= max_Y )
{
ras.Proc_Sweep_Step( RAS_VAR );
@@ -2949,7 +3113,7 @@ static const char count_table[256] =
/* Render_Single_Pass */
/* */
/* <Description> */
- /* Performs one sweep with sub-banding. */
+ /* Perform one sweep with sub-banding. */
/* */
/* <Input> */
/* flipped :: If set, flip the direction of the outline. */
@@ -3024,7 +3188,7 @@ static const char count_table[256] =
/* Render_Glyph */
/* */
/* <Description> */
- /* Renders a glyph in a bitmap. Sub-banding if needed. */
+ /* Render a glyph in a bitmap. Sub-banding if needed. */
/* */
/* <Return> */
/* FreeType error code. 0 means success. */
@@ -3036,14 +3200,24 @@ static const char count_table[256] =
Set_High_Precision( RAS_VARS ras.outline.flags &
- FT_OUTLINE_HIGH_PRECISION );
- ras.scale_shift = ras.precision_shift;
- /* Drop-out mode 2 is hard-coded since this is the only mode used */
- /* on Windows platforms. Using other modes, as specified by the */
- /* font, results in misplaced pixels. */
- ras.dropOutControl = 2;
- ras.second_pass = (FT_Byte)( !( ras.outline.flags &
- FT_OUTLINE_SINGLE_PASS ) );
+ FT_OUTLINE_HIGH_PRECISION );
+ ras.scale_shift = ras.precision_shift;
+
+ if ( ras.outline.flags & FT_OUTLINE_IGNORE_DROPOUTS )
+ ras.dropOutControl = 2;
+ else
+ {
+ if ( ras.outline.flags & FT_OUTLINE_SMART_DROPOUTS )
+ ras.dropOutControl = 4;
+ else
+ ras.dropOutControl = 0;
+
+ if ( !( ras.outline.flags & FT_OUTLINE_INCLUDE_STUBS ) )
+ ras.dropOutControl += 1;
+ }
+
+ ras.second_pass = (FT_Byte)( !( ras.outline.flags &
+ FT_OUTLINE_SINGLE_PASS ) );
/* Vertical Sweep */
ras.Proc_Sweep_Init = Vertical_Sweep_Init;
@@ -3062,7 +3236,7 @@ static const char count_table[256] =
return error;
/* Horizontal Sweep */
- if ( ras.second_pass && ras.dropOutControl != 0 )
+ if ( ras.second_pass && ras.dropOutControl != 2 )
{
ras.Proc_Sweep_Init = Horizontal_Sweep_Init;
ras.Proc_Sweep_Span = Horizontal_Sweep_Span;
@@ -3083,14 +3257,13 @@ static const char count_table[256] =
#ifdef FT_RASTER_OPTION_ANTI_ALIASING
-
/*************************************************************************/
/* */
/* <Function> */
/* Render_Gray_Glyph */
/* */
/* <Description> */
- /* Renders a glyph with grayscaling. Sub-banding if needed. */
+ /* Render a glyph with grayscaling. Sub-banding if needed. */
/* */
/* <Return> */
/* FreeType error code. 0 means success. */
@@ -3103,13 +3276,23 @@ static const char count_table[256] =
Set_High_Precision( RAS_VARS ras.outline.flags &
- FT_OUTLINE_HIGH_PRECISION );
- ras.scale_shift = ras.precision_shift + 1;
- /* Drop-out mode 2 is hard-coded since this is the only mode used */
- /* on Windows platforms. Using other modes, as specified by the */
- /* font, results in misplaced pixels. */
- ras.dropOutControl = 2;
- ras.second_pass = !( ras.outline.flags & FT_OUTLINE_SINGLE_PASS );
+ FT_OUTLINE_HIGH_PRECISION );
+ ras.scale_shift = ras.precision_shift + 1;
+
+ if ( ras.outline.flags & FT_OUTLINE_IGNORE_DROPOUTS )
+ ras.dropOutControl = 2;
+ else
+ {
+ if ( ras.outline.flags & FT_OUTLINE_SMART_DROPOUTS )
+ ras.dropOutControl = 4;
+ else
+ ras.dropOutControl = 0;
+
+ if ( !( ras.outline.flags & FT_OUTLINE_INCLUDE_STUBS ) )
+ ras.dropOutControl += 1;
+ }
+
+ ras.second_pass = !( ras.outline.flags & FT_OUTLINE_SINGLE_PASS );
/* Vertical Sweep */
@@ -3137,7 +3320,7 @@ static const char count_table[256] =
return error;
/* Horizontal Sweep */
- if ( ras.second_pass && ras.dropOutControl != 0 )
+ if ( ras.second_pass && ras.dropOutControl != 2 )
{
ras.Proc_Sweep_Init = Horizontal_Sweep_Init;
ras.Proc_Sweep_Span = Horizontal_Gray_Sweep_Span;
@@ -3172,8 +3355,6 @@ static const char count_table[256] =
static void
ft_black_init( PRaster raster )
{
- FT_UNUSED( raster );
-
#ifdef FT_RASTER_OPTION_ANTI_ALIASING
FT_UInt n;
@@ -3183,7 +3364,8 @@ static const char count_table[256] =
raster->grays[n] = n * 255 / 4;
raster->gray_width = RASTER_GRAY_LINES / 2;
-
+#else
+ FT_UNUSED( raster );
#endif
}
@@ -3196,7 +3378,7 @@ static const char count_table[256] =
static int
- ft_black_new( void* memory,
+ ft_black_new( void* memory,
FT_Raster *araster )
{
static TRaster the_raster;
@@ -3254,9 +3436,9 @@ static const char count_table[256] =
static void
- ft_black_reset( PRaster raster,
- char* pool_base,
- long pool_size )
+ ft_black_reset( PRaster raster,
+ char* pool_base,
+ long pool_size )
{
if ( raster )
{
@@ -3281,9 +3463,9 @@ static const char count_table[256] =
static void
- ft_black_set_mode( PRaster raster,
- unsigned long mode,
- const char* palette )
+ ft_black_set_mode( PRaster raster,
+ unsigned long mode,
+ const char* palette )
{
#ifdef FT_RASTER_OPTION_ANTI_ALIASING
@@ -3319,14 +3501,18 @@ static const char count_table[256] =
if ( !raster || !raster->buffer || !raster->buffer_size )
return Raster_Err_Not_Ini;
+ if ( !outline )
+ return Raster_Err_Invalid;
+
/* return immediately if the outline is empty */
if ( outline->n_points == 0 || outline->n_contours <= 0 )
return Raster_Err_None;
- if ( !outline || !outline->contours || !outline->points )
+ if ( !outline->contours || !outline->points )
return Raster_Err_Invalid;
- if ( outline->n_points != outline->contours[outline->n_contours - 1] + 1 )
+ if ( outline->n_points !=
+ outline->contours[outline->n_contours - 1] + 1 )
return Raster_Err_Invalid;
worker = raster->worker;
@@ -3335,35 +3521,43 @@ static const char count_table[256] =
if ( params->flags & FT_RASTER_FLAG_DIRECT )
return Raster_Err_Unsupported;
- if ( !target_map || !target_map->buffer )
+ if ( !target_map )
return Raster_Err_Invalid;
- ras.outline = *outline;
- ras.target = *target_map;
+ /* nothing to do */
+ if ( !target_map->width || !target_map->rows )
+ return Raster_Err_None;
+
+ if ( !target_map->buffer )
+ return Raster_Err_Invalid;
- worker->buff = (PLong) raster->buffer;
- worker->sizeBuff = worker->buff +
- raster->buffer_size / sizeof ( Long );
+ ras.outline = *outline;
+ ras.target = *target_map;
+
+ worker->buff = (PLong) raster->buffer;
+ worker->sizeBuff = worker->buff +
+ raster->buffer_size / sizeof ( Long );
#ifdef FT_RASTER_OPTION_ANTI_ALIASING
- worker->grays = raster->grays;
- worker->gray_width = raster->gray_width;
+ worker->grays = raster->grays;
+ worker->gray_width = raster->gray_width;
+
+ FT_MEM_ZERO( worker->gray_lines, worker->gray_width * 2 );
#endif
- return ( ( params->flags & FT_RASTER_FLAG_AA )
- ? Render_Gray_Glyph( RAS_VAR )
- : Render_Glyph( RAS_VAR ) );
+ return ( params->flags & FT_RASTER_FLAG_AA )
+ ? Render_Gray_Glyph( RAS_VAR )
+ : Render_Glyph( RAS_VAR );
}
- const FT_Raster_Funcs ft_standard_raster =
- {
+ FT_DEFINE_RASTER_FUNCS( ft_standard_raster,
FT_GLYPH_FORMAT_OUTLINE,
(FT_Raster_New_Func) ft_black_new,
(FT_Raster_Reset_Func) ft_black_reset,
(FT_Raster_Set_Mode_Func)ft_black_set_mode,
(FT_Raster_Render_Func) ft_black_render,
(FT_Raster_Done_Func) ft_black_done
- };
+ )
/* END */
diff --git a/src/freetype2/raster/ftrend1.c b/src/freetype2/raster/ftrend1.c
index 3cc8d07..1ed8af6 100644
--- a/src/freetype2/raster/ftrend1.c
+++ b/src/freetype2/raster/ftrend1.c
@@ -21,6 +21,7 @@
#include FT_OUTLINE_H
#include "ftrend1.h"
#include "ftraster.h"
+#include "rastpic.h"
#include "rasterrs.h"
@@ -118,6 +119,7 @@
}
/* check rendering mode */
+#ifndef FT_CONFIG_OPTION_PIC
if ( mode != FT_RENDER_MODE_MONO )
{
/* raster1 is only capable of producing monochrome bitmaps */
@@ -130,6 +132,25 @@
if ( render->clazz == &ft_raster5_renderer_class )
return Raster_Err_Cannot_Render_Glyph;
}
+#else /* FT_CONFIG_OPTION_PIC */
+ /* When PIC is enabled, we cannot get to the class object */
+ /* so instead we check the final character in the class name */
+ /* ("raster5" or "raster1"). Yes this is a hack. */
+ /* The "correct" thing to do is have different render function */
+ /* for each of the classes. */
+ if ( mode != FT_RENDER_MODE_MONO )
+ {
+ /* raster1 is only capable of producing monochrome bitmaps */
+ if ( render->clazz->root.module_name[6] == '1' )
+ return Raster_Err_Cannot_Render_Glyph;
+ }
+ else
+ {
+ /* raster5 is only capable of producing 5-gray-levels bitmaps */
+ if ( render->clazz->root.module_name[6] == '5' )
+ return Raster_Err_Cannot_Render_Glyph;
+ }
+#endif /* FT_CONFIG_OPTION_PIC */
outline = &slot->outline;
@@ -208,10 +229,8 @@
}
- FT_CALLBACK_TABLE_DEF
- const FT_Renderer_Class ft_raster1_renderer_class =
- {
- {
+ FT_DEFINE_RENDERER(ft_raster1_renderer_class,
+
FT_MODULE_RENDERER,
sizeof( FT_RendererRec ),
@@ -224,7 +243,7 @@
(FT_Module_Constructor)ft_raster1_init,
(FT_Module_Destructor) 0,
(FT_Module_Requester) 0
- },
+ ,
FT_GLYPH_FORMAT_OUTLINE,
@@ -233,18 +252,17 @@
(FT_Renderer_GetCBoxFunc) ft_raster1_get_cbox,
(FT_Renderer_SetModeFunc) ft_raster1_set_mode,
- (FT_Raster_Funcs*) &ft_standard_raster
- };
+ (FT_Raster_Funcs*) &FT_STANDARD_RASTER_GET
+ )
/* This renderer is _NOT_ part of the default modules; you will need */
/* to register it by hand in your application. It should only be */
/* used for backwards-compatibility with FT 1.x anyway. */
/* */
- FT_CALLBACK_TABLE_DEF
- const FT_Renderer_Class ft_raster5_renderer_class =
- {
- {
+ FT_DEFINE_RENDERER(ft_raster5_renderer_class,
+
+
FT_MODULE_RENDERER,
sizeof( FT_RendererRec ),
@@ -257,7 +275,7 @@
(FT_Module_Constructor)ft_raster1_init,
(FT_Module_Destructor) 0,
(FT_Module_Requester) 0
- },
+ ,
FT_GLYPH_FORMAT_OUTLINE,
@@ -266,8 +284,8 @@
(FT_Renderer_GetCBoxFunc) ft_raster1_get_cbox,
(FT_Renderer_SetModeFunc) ft_raster1_set_mode,
- (FT_Raster_Funcs*) &ft_standard_raster
- };
+ (FT_Raster_Funcs*) &FT_STANDARD_RASTER_GET
+ )
/* END */
diff --git a/src/freetype2/raster/ftrend1.h b/src/freetype2/raster/ftrend1.h
index 76e9a5f..4cf1286 100644
--- a/src/freetype2/raster/ftrend1.h
+++ b/src/freetype2/raster/ftrend1.h
@@ -27,13 +27,13 @@
FT_BEGIN_HEADER
- FT_EXPORT_VAR( const FT_Renderer_Class ) ft_raster1_renderer_class;
+ FT_DECLARE_RENDERER( ft_raster1_renderer_class )
/* this renderer is _NOT_ part of the default modules, you'll need */
/* to register it by hand in your application. It should only be */
/* used for backwards-compatibility with FT 1.x anyway. */
/* */
- FT_EXPORT_VAR( const FT_Renderer_Class ) ft_raster5_renderer_class;
+ FT_DECLARE_RENDERER( ft_raster5_renderer_class )
FT_END_HEADER
diff --git a/src/freetype2/raster/raster.c b/src/freetype2/raster/raster.c
index f13a67a..1202a11 100644
--- a/src/freetype2/raster/raster.c
+++ b/src/freetype2/raster/raster.c
@@ -19,6 +19,7 @@
#define FT_MAKE_OPTION_SINGLE_OBJECT
#include <ft2build.h>
+#include "rastpic.c"
#include "ftraster.c"
#include "ftrend1.c"
diff --git a/src/freetype2/raster/rastpic.c b/src/freetype2/raster/rastpic.c
new file mode 100644
index 0000000..3c26487
--- /dev/null
+++ b/src/freetype2/raster/rastpic.c
@@ -0,0 +1,89 @@
+/***************************************************************************/
+/* */
+/* rastpic.c */
+/* */
+/* The FreeType position independent code services for raster module. */
+/* */
+/* Copyright 2009 by */
+/* Oran Agra and Mickey Gabel. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+#include FT_INTERNAL_OBJECTS_H
+#include "rastpic.h"
+
+#ifdef FT_CONFIG_OPTION_PIC
+
+ /* forward declaration of PIC init functions from ftraster.c */
+ void FT_Init_Class_ft_standard_raster(FT_Raster_Funcs*);
+
+ void
+ ft_raster1_renderer_class_pic_free( FT_Library library )
+ {
+ FT_PIC_Container* pic_container = &library->pic_container;
+ FT_Memory memory = library->memory;
+ if ( pic_container->raster )
+ {
+ RasterPIC* container = (RasterPIC*)pic_container->raster;
+ if(--container->ref_count)
+ return;
+ FT_FREE( container );
+ pic_container->raster = NULL;
+ }
+ }
+
+
+ FT_Error
+ ft_raster1_renderer_class_pic_init( FT_Library library )
+ {
+ FT_PIC_Container* pic_container = &library->pic_container;
+ FT_Error error = FT_Err_Ok;
+ RasterPIC* container;
+ FT_Memory memory = library->memory;
+
+ /* since this function also serve raster5 renderer,
+ it implements reference counting */
+ if(pic_container->raster)
+ {
+ ((RasterPIC*)pic_container->raster)->ref_count++;
+ return error;
+ }
+
+ /* allocate pointer, clear and set global container pointer */
+ if ( FT_ALLOC ( container, sizeof ( *container ) ) )
+ return error;
+ FT_MEM_SET( container, 0, sizeof(*container) );
+ pic_container->raster = container;
+ container->ref_count = 1;
+
+ /* initialize pointer table - this is how the module usually expects this data */
+ FT_Init_Class_ft_standard_raster(&container->ft_standard_raster);
+/*Exit:*/
+ if(error)
+ ft_raster1_renderer_class_pic_free(library);
+ return error;
+ }
+
+ /* re-route these init and free functions to the above functions */
+ FT_Error ft_raster5_renderer_class_pic_init(FT_Library library)
+ {
+ return ft_raster1_renderer_class_pic_init(library);
+ }
+ void ft_raster5_renderer_class_pic_free(FT_Library library)
+ {
+ ft_raster1_renderer_class_pic_free(library);
+ }
+
+#endif /* FT_CONFIG_OPTION_PIC */
+
+
+/* END */
diff --git a/src/freetype2/raster/rastpic.h b/src/freetype2/raster/rastpic.h
new file mode 100644
index 0000000..dcd82b8
--- /dev/null
+++ b/src/freetype2/raster/rastpic.h
@@ -0,0 +1,50 @@
+/***************************************************************************/
+/* */
+/* rastpic.h */
+/* */
+/* The FreeType position independent code services for raster module. */
+/* */
+/* Copyright 2009 by */
+/* Oran Agra and Mickey Gabel. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __RASTPIC_H__
+#define __RASTPIC_H__
+
+
+FT_BEGIN_HEADER
+
+#include FT_INTERNAL_PIC_H
+
+#ifndef FT_CONFIG_OPTION_PIC
+#define FT_STANDARD_RASTER_GET ft_standard_raster
+
+#else /* FT_CONFIG_OPTION_PIC */
+
+ typedef struct RasterPIC_
+ {
+ int ref_count;
+ FT_Raster_Funcs ft_standard_raster;
+ } RasterPIC;
+
+#define GET_PIC(lib) ((RasterPIC*)((lib)->pic_container.raster))
+#define FT_STANDARD_RASTER_GET (GET_PIC(library)->ft_standard_raster)
+
+#endif /* FT_CONFIG_OPTION_PIC */
+
+ /* */
+
+FT_END_HEADER
+
+#endif /* __RASTPIC_H__ */
+
+
+/* END */