packages feed

stb-truetype 0.1.1 → 0.1.2

raw patch · 3 files changed

+249/−117 lines, 3 files

Files

Graphics/Rendering/TrueType/STB.hs view
@@ -3,13 +3,10 @@ --   * rewrite the file loading so that it we do not depend on ByteString --   * automatic glyph indexing, texture creation ----- BUG in stb_truetype? ---   * compound contours not implemented yet... ---  -- -- Module      : Graphics.Rendering.TrueType.STB--- Version     : 0.1.1+-- Version     : 0.1.2 -- License     : Public Domain -- Author      : Balazs Komuves -- Maintainer  : bkomuves (plus) hackage (at) gmail (dot) com@@ -20,14 +17,13 @@  -- | This is a wrapper around Sean Barrett's TrueType font rasterizer code. -- The original can be found at <http://nothings.org/stb/stb_truetype.h>.--- The version of @stb-truetype@ used here is @0.2@.+-- The version of @stb-truetype@ used here is @0.3@. ----- Note: it seems that compound glyphs are not implemented yet!  {-# LANGUAGE CPP, ForeignFunctionInterface #-} {-# CFILES cbits/wrapper.c #-}  -- for Hugs (?) module Graphics.Rendering.TrueType.STB -  ( TrueType+  ( TrueType(..)   , Offset   , Font   , Glyph@@ -534,7 +530,8 @@   poke = error "TableLoc/poke: not implemented"  data CFontInfo = CFontInfo-  { _data      :: Ptr Word8+  { _userData  :: Ptr ()+  , _data      :: Ptr Word8   , _fontstart :: Int    , _numGlyphs :: Int   , _tableloc  :: TableLoc@@ -544,7 +541,7 @@    instance Storable CFontInfo where    alignment _ = alignment (undefined :: CInt)-  sizeOf _    = sizeOf (undefined :: Ptr Word8)+  sizeOf _    = 2 * sizeOf (undefined :: Ptr Word8)               + sizeOf (undefined :: TableLoc)               + 4 * sizeOf (undefined :: CInt)   peek = error "CFontInfo/peek: not implemented"            @@ -598,12 +595,27 @@  ------- +{-+-- stb_truetype v0.2 foreign import ccall unsafe "stb_truetype.h stbtt_FreeBitmap"   stbtt_FreeBitmap :: Ptr Word8 -> IO ()   foreign import ccall unsafe "stb_truetype.h &stbtt_FreeBitmap"   bitmapFinalizer :: FunPtr (Ptr Word8 -> IO ())-   +-}++-- stb_truetype v0.3, with "userdata"+foreign import ccall unsafe "stb_truetype.h stbtt_FreeBitmap"+  stbtt_FreeBitmap :: Ptr Word8 -> Ptr a -> IO () ++foreign import ccall "wrapper" mkFinPtr +  :: (Ptr Word8 -> IO ()) -> IO (FinalizerPtr Word8)++bitmapFinalizer :: FunPtr (Ptr Word8 -> IO ())+bitmapFinalizer = unsafePerformIO $ mkFinPtr $ \p -> stbtt_FreeBitmap p nullPtr+ +------+ {-  foreign import ccall unsafe "stb_truetype.h stbtt_GetCodepointBitmap"   stbtt_GetCodepointBitmap @@ -622,6 +634,8 @@     :: Ptr CFontInfo -> CCodepoint -> CFloat -> CFloat     -> Ptr CInt -> Ptr CInt -> Ptr CInt -> Ptr CInt -> IO () -}++------  foreign import ccall unsafe "stb_truetype.h stbtt_GetGlyphBitmap"   stbtt_GetGlyphBitmap 
cbits/stb_truetype.h view
@@ -1,4 +1,4 @@-// stb_truetype.h - v0.2 - public domain - 2009 Sean Barrett / RAD Game Tools+// stb_truetype.h - v0.3 - public domain - 2009 Sean Barrett / RAD Game Tools // //   This library processes TrueType files: //        parse files@@ -7,13 +7,20 @@ //        render glyphs to one-channel bitmaps with antialiasing (box filter) // //   Todo:+//        non-MS cmaps //        crashproof on bad data //        hinting //        subpixel positioning when rendering bitmap //        cleartype-style AA //+// ADDITIONAL CONTRIBUTORS+//+//   Mikko Mononen: compound shape support, more cmap formats+// // VERSIONS //+//   0.3 (2009-06-24) cmap fmt=12, compound shapes (MM)+//                    userdata, malloc-from-userdata, non-zero fill (STB) //   0.2 (2009-03-11) Fix unsigned/signed char warnings //   0.1 (2009-03-09) First public release //@@ -57,12 +64,12 @@ //   recommend it. // //-// SOURCE STATISTICS (based on v.1, 1700 LOC)+// SOURCE STATISTICS (based on v0.3, 1800 LOC) // //   Documentation & header file        350 LOC  \___ 500 LOC documentation //   Sample code                        140 LOC  /-//   Truetype parsing                   480 LOC  ---- 500 LOC TrueType-//   Software rasterization             240 LOC  \+//   Truetype parsing                   580 LOC  ---- 600 LOC TrueType+//   Software rasterization             240 LOC  \                           . //   Curve tesselation                  120 LOC   \__ 500 LOC Bitmap creation //   Bitmap management                   70 LOC   / //   Baked bitmap interface              70 LOC  /@@ -130,18 +137,18 @@ #define STB_TRUETYPE_IMPLEMENTATION  // force following include to generate implementation #include "stb_truetype.h" -char ttf_buffer[1<<20];+char ttf_buffer[1<<25]; -int main(int arg, char **argv)+int main(int argc, char **argv) {    stbtt_fontinfo font;    unsigned char *bitmap;-   int w,h,i,j;+   int w,h,i,j,c = (argc > 1 ? atoi(argv[1]) : 'a'), s = (argc > 2 ? atoi(argv[2]) : 20); -   fread(ttf_buffer, 1, 1000000, fopen("c:/windows/fonts/arialbd.ttf", "rb"));+   fread(ttf_buffer, 1, 1<<25, fopen(argc > 3 ? argv[3] : "c:/windows/fonts/arialbd.ttf", "rb")); -   stbtt_InitFont(&font, ttf_buffer, 0);-   bitmap = stbtt_GetCodepointBitmap(&font, 0,stbtt_ScaleForPixelHeight(&font, 20), 'a', &w, &h, 0,0);+   stbtt_InitFont(&font, ttf_buffer, stbtt_GetFontOffsetForIndex(ttf_buffer,0));+   bitmap = stbtt_GetCodepointBitmap(&font, 0,stbtt_ScaleForPixelHeight(&font, s), c, &w, &h, 0,0);     for (j=0; j < h; ++j) {       for (i=0; i < w; ++i)@@ -244,8 +251,8 @@    #if !defined(__APPLE__) // apple hack    #include <malloc.h>    #endif                  // apple hack-   #define STBTT_malloc(x)    malloc(x)-   #define STBTT_free(x)      free(x)+   #define STBTT_malloc(x,u)  malloc(x)+   #define STBTT_free(x,u)    free(x)    #endif     #ifndef STBTT_assert@@ -337,6 +344,7 @@ // the stack or as a global or etc. typedef struct {+   void           *userdata;    unsigned char  *data;         // pointer to .ttf file    int             fontstart;    // offset of start of font @@ -433,7 +441,7 @@ // returns # of vertices and fills *vertices with the pointer to them //   these are expressed in "unscaled" coordinates -extern void stbtt_FreeShape(stbtt_vertex *vertices);+extern void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *vertices); // frees the data allocated above  //////////////////////////////////////////////////////////////////////////////@@ -441,7 +449,7 @@ // BITMAP RENDERING // -extern void stbtt_FreeBitmap(unsigned char *bitmap);+extern void stbtt_FreeBitmap(unsigned char *bitmap, void *userdata); // frees the bitmap allocated below  extern unsigned char *stbtt_GetCodepointBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int codepoint, int *width, int *height, int *xoff, int *yoff);@@ -479,7 +487,7 @@    unsigned char *pixels; } stbtt__bitmap; -extern void stbtt_Rasterize(stbtt__bitmap *result, float flatness_in_pixels, stbtt_vertex *vertices, int num_verts, float scale_x, float scale_y, int x_off, int y_off, int invert);+extern void stbtt_Rasterize(stbtt__bitmap *result, float flatness_in_pixels, stbtt_vertex *vertices, int num_verts, float scale_x, float scale_y, int x_off, int y_off, int invert, void *userdata);  ////////////////////////////////////////////////////////////////////////////// //@@ -579,6 +587,7 @@ } #endif +#endif // __STB_INCLUDE_STB_TRUETYPE_H__  /////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////@@ -695,10 +704,16 @@    for (i=0; i < numTables; ++i) {       stbtt_uint32 encoding_record = cmap + 4 + 8 * i;       // find an encoding we understand:-      if (ttUSHORT(data+encoding_record) == 3 && ttUSHORT(data+encoding_record+2) == 1) {-         // MS/Unicode-         info->index_map = cmap + ttULONG(data+encoding_record+4);-         break;+      switch(ttUSHORT(data+encoding_record)) {+         case STBTT_PLATFORM_ID_MICROSOFT:+            switch (ttUSHORT(data+encoding_record+2)) {+               case STBTT_MS_EID_UNICODE_BMP:+               case STBTT_MS_EID_UNICODE_FULL:+                  // MS/Unicode+                  info->index_map = cmap + ttULONG(data+encoding_record+4);+                  break;+            }+            break;       }    }    if (info->index_map == 0)@@ -762,7 +777,7 @@       }       search += 2; -      item = (search - endCount) >> 1;+      item = (stbtt_uint16) ((search - endCount) >> 1);        STBTT_assert(unicode_codepoint <= ttUSHORT(data + endCount + 2*item));       start = ttUSHORT(data + index_map + 14 + segcount*2 + 2 + 2*item);@@ -775,6 +790,26 @@          return unicode_codepoint + ttSHORT(data + index_map + 14 + segcount*4 + 2 + 2*item);        return ttUSHORT(data + offset + (unicode_codepoint-start)*2 + index_map + 14 + segcount*6 + 2 + 2*item);+   } else if (format == 12) {+      stbtt_uint16 ngroups = ttUSHORT(data+index_map+6);+      stbtt_int32 low,high;+      stbtt_uint16 g = 0;+      low = 0; high = (stbtt_int32)ngroups;+      // Binary search the right group.+      while (low <= high) {+         stbtt_int32 mid = low + ((high-low) >> 1); // rounds down, so low <= mid < high+         stbtt_uint32 start_char = ttULONG(data+index_map+16+mid*12);+         stbtt_uint32 end_char = ttULONG(data+index_map+16+mid*12+4);+         if ((stbtt_uint32) unicode_codepoint < start_char)+            high = mid-1;+         else if ((stbtt_uint32) unicode_codepoint > end_char)+            low = mid+1;+         else {+            stbtt_uint32 start_glyph = ttULONG(data+index_map+16+mid*12+8);+            return start_glyph + unicode_codepoint-start_char;+         }+      }+      return 0; // not found    }    // @TODO    STBTT_assert(0);@@ -835,8 +870,8 @@    stbtt_int16 numberOfContours;    stbtt_uint8 *endPtsOfContours;    stbtt_uint8 *data = info->data;-   stbtt_vertex *vertices;-   int num_vertices;+   stbtt_vertex *vertices=0;+   int num_vertices=0;    int g = stbtt__GetGlyfOffset(info, glyph_index);     *pvertices = NULL;@@ -846,7 +881,7 @@    numberOfContours = ttSHORT(data + g);     if (numberOfContours > 0) {-      stbtt_uint8  flags,flagcount;+      stbtt_uint8 flags=0,flagcount;       stbtt_int32 ins, i,j=0,m,n, next_move, was_off=0, off;       stbtt_int16 x,y,cx,cy,sx,sy;       stbtt_uint8 *points;@@ -857,7 +892,7 @@       n = 1+ttUSHORT(endPtsOfContours + numberOfContours*2-2);        m = n + numberOfContours;  // a loose bound on how many vertices we might need-      vertices = (stbtt_vertex *) STBTT_malloc(m * sizeof(vertices[0]));+      vertices = (stbtt_vertex *) STBTT_malloc(m * sizeof(vertices[0]), info->userdata);       if (vertices == 0)          return 0; @@ -891,7 +926,7 @@             x += (flags & 16) ? dx : -dx; // ???          } else {             if (!(flags & 16)) {-               x += (stbtt_int16) (points[0]*256 + points[1]);+               x = x + (stbtt_int16) (points[0]*256 + points[1]);                points += 2;             }          }@@ -907,7 +942,7 @@             y += (flags & 32) ? dy : -dy; // ???          } else {             if (!(flags & 32)) {-               y += (stbtt_int16) (points[0]*256 + points[1]);+               y = y + (stbtt_int16) (points[0]*256 + points[1]);                points += 2;             }          }@@ -959,10 +994,89 @@          else             stbtt_setvertex(&vertices[num_vertices++], STBTT_vline,sx,sy,0,0);       }+   } else if (numberOfContours == -1) {+      // Compound shapes.+      int more = 1;+      stbtt_uint8 *comp = data + g + 10;+      num_vertices = 0;+      vertices = 0;+      while (more) {+         stbtt_uint16 flags, gidx;+         int comp_num_verts = 0, i;+         stbtt_vertex *comp_verts = 0, *tmp = 0;+         float mtx[6] = {1,0,0,1,0,0}, m, n;+         +         flags = ttSHORT(comp); comp+=2;+         gidx = ttSHORT(comp); comp+=2;++         if (flags & 2) { // XY values+            if (flags & 1) { // shorts+               mtx[4] = ttSHORT(comp); comp+=2;+               mtx[5] = ttSHORT(comp); comp+=2;+            } else {+               mtx[4] = ttCHAR(comp); comp+=1;+               mtx[5] = ttCHAR(comp); comp+=1;+            }+         }+         else {+            // @TODO handle matching point+            STBTT_assert(0);+         }+         if (flags & (1<<3)) { // WE_HAVE_A_SCALE+            mtx[0] = mtx[3] = ttSHORT(comp)/16384.0f; comp+=2;+            mtx[1] = mtx[2] = 0;+         } else if (flags & (1<<6)) { // WE_HAVE_AN_X_AND_YSCALE+            mtx[0] = ttSHORT(comp)/16384.0f; comp+=2;+            mtx[1] = mtx[2] = 0;+            mtx[3] = ttSHORT(comp)/16384.0f; comp+=2;+         } else if (flags & (1<<7)) { // WE_HAVE_A_TWO_BY_TWO+            mtx[0] = ttSHORT(comp)/16384.0f; comp+=2;+            mtx[1] = ttSHORT(comp)/16384.0f; comp+=2;+            mtx[2] = ttSHORT(comp)/16384.0f; comp+=2;+            mtx[3] = ttSHORT(comp)/16384.0f; comp+=2;+         }+         +         // Find transformation scales.+         m = (float) sqrt(mtx[0]*mtx[0] + mtx[1]*mtx[1]);+         n = (float) sqrt(mtx[2]*mtx[2] + mtx[3]*mtx[3]);++         // Get indexed glyph.+         comp_num_verts = stbtt_GetGlyphShape(info, gidx, &comp_verts);+         if (comp_num_verts > 0) {+            // Transform vertices.+            for (i = 0; i < comp_num_verts; ++i) {+               stbtt_vertex* v = &comp_verts[i];+               stbtt_vertex_type x,y;+               x=v->x; y=v->y;+               v->x = (stbtt_vertex_type)(m * (mtx[0]*x + mtx[2]*y + mtx[4]));+               v->y = (stbtt_vertex_type)(n * (mtx[1]*x + mtx[3]*y + mtx[5]));+               x=v->cx; y=v->cy;+               v->cx = (stbtt_vertex_type)(m * (mtx[0]*x + mtx[2]*y + mtx[4]));+               v->cy = (stbtt_vertex_type)(n * (mtx[1]*x + mtx[3]*y + mtx[5]));+            }+            // Append vertices.+            tmp = (stbtt_vertex*)STBTT_malloc((num_vertices+comp_num_verts)*sizeof(stbtt_vertex), info->userdata);+            if (!tmp) {+               if (vertices) STBTT_free(vertices, info->userdata);+               if (comp_verts) STBTT_free(comp_verts, info->userdata);+               return 0;+            }+            if (num_vertices > 0) memcpy(tmp, vertices, num_vertices*sizeof(stbtt_vertex));+            memcpy(tmp+num_vertices, comp_verts, comp_num_verts*sizeof(stbtt_vertex));+            if (vertices) STBTT_free(vertices, info->userdata);+            vertices = tmp;+            STBTT_free(comp_verts, info->userdata);+            num_vertices += comp_num_verts;+         }+         // More components ?+         more = flags & (1<<5);+      }    } else if (numberOfContours < 0) {-      // @TODO handle compound contours+      // @TODO other compound variations?       STBTT_assert(0);-   }  +   } else {+      // numberOfCounters == 0, do nothing+   }     *pvertices = vertices;    return num_vertices;@@ -1008,9 +1122,9 @@    return (float) height / fheight; } -void stbtt_FreeShape(stbtt_vertex *v)+void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *v) {-   STBTT_free(v);+   STBTT_free(v, info->userdata); }  //////////////////////////////////////////////////////////////////////////////@@ -1037,6 +1151,7 @@  typedef struct stbtt__edge {    float x0,y0, x1,y1;+   int invert; } stbtt__edge;  typedef struct stbtt__active_edge@@ -1051,9 +1166,9 @@ #define FIX        (1 << FIXSHIFT) #define FIXMASK    (FIX-1) -static stbtt__active_edge *new_active(stbtt__edge *e, int off_x, float start_point)+static stbtt__active_edge *new_active(stbtt__edge *e, int off_x, float start_point, void *userdata) {-   stbtt__active_edge *z = (stbtt__active_edge *) STBTT_malloc(sizeof(*z)); // @TODO: make a pool of these!!!+   stbtt__active_edge *z = (stbtt__active_edge *) STBTT_malloc(sizeof(*z), userdata); // @TODO: make a pool of these!!!    float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0);    STBTT_assert(e->y0 <= start_point);    if (!z) return z;@@ -1066,7 +1181,7 @@    z->x -= off_x * FIX;    z->ey = e->y1;    z->next = 0;-   z->valid = 1;+   z->valid = e->invert ? 1 : -1;    return z; } @@ -1075,46 +1190,47 @@ // are wrong, or if the user supplies a too-small bitmap static void stbtt__fill_active_edges(unsigned char *scanline, int len, stbtt__active_edge *e, int max_weight) {-   // @TODO: convert this from xor fill to non-zero winding-   while (e) {-      int x0,x1,i,j;--      x0 = e->x; e = e->next;-      if (!e)-         return; // unbalanced number of edges--      x1 = e->x; e = e->next;-      STBTT_assert(x1 >= x0);+   // non-zero winding fill+   int x0=0, w=0; -      i = x0 >> FIXSHIFT;-      j = x1 >> FIXSHIFT;+   while (e) {+      if (w == 0) {+         // if we're currently at zero, we need to record the edge start point+         x0 = e->x; w += e->valid;+      } else {+         int x1 = e->x; w += e->valid;+         // if we went to zero, we need to draw+         if (w == 0) {+            int i = x0 >> FIXSHIFT;+            int j = x1 >> FIXSHIFT; -      if (i < len && j >= 0) {-         if (i == j) {-            // x0,x1 are the same pixel, so compute combined coverage-            scanline[i] += (x1 - x0) * max_weight >> FIXSHIFT;-         } else {-            if (i >= 0) // add antialiasing for x0-               scanline[i] += ((FIX - (x0 & FIXMASK)) * max_weight) >> FIXSHIFT;-            else-               i = -1; // clip+            if (i < len && j >= 0) {+               if (i == j) {+                  // x0,x1 are the same pixel, so compute combined coverage+                  scanline[i] = scanline[i] + (stbtt_uint8) ((x1 - x0) * max_weight >> FIXSHIFT);+               } else {+                  if (i >= 0) // add antialiasing for x0+                     scanline[i] = scanline[i] + (stbtt_uint8) (((FIX - (x0 & FIXMASK)) * max_weight) >> FIXSHIFT);+                  else+                     i = -1; // clip -            if (j < len) // add antialiasing for x1-               scanline[j] += ((x1 & FIXMASK) * max_weight) >> FIXSHIFT;-            else-               j = len; // clip+                  if (j < len) // add antialiasing for x1+                     scanline[j] = scanline[j] + (stbtt_uint8) (((x1 & FIXMASK) * max_weight) >> FIXSHIFT);+                  else+                     j = len; // clip -            for (++i; i < j; ++i) // fill pixels between x0 and x1-               scanline[i] += max_weight;+                  for (++i; i < j; ++i) // fill pixels between x0 and x1+                     scanline[i] = scanline[i] + (stbtt_uint8) max_weight;+               }+            }          }       }--      if (!e)-         return;+      +      e = e->next;    } } -static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, int n, int vsubsample, int off_x, int off_y)+static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, int n, int vsubsample, int off_x, int off_y, void *userdata) {    stbtt__active_edge *active = NULL;    int y,j=0;@@ -1123,7 +1239,7 @@    unsigned char scanline_data[512], *scanline;     if (result->w > 512)-      scanline = (unsigned char *) STBTT_malloc(result->w);+      scanline = (unsigned char *) STBTT_malloc(result->w, userdata);    else       scanline = scanline_data; @@ -1145,7 +1261,7 @@                *step = z->next; // delete from list                STBTT_assert(z->valid);                z->valid = 0;-               STBTT_free(z);+               STBTT_free(z, userdata);             } else {                z->x += z->dx; // advance to position for current scanline                step = &((*step)->next); // advance through list@@ -1174,7 +1290,7 @@          // insert all edges that start before the center of this scanline -- omit ones that also end on this scanline          while (e->y0 <= scan_y) {             if (e->y1 > scan_y) {-               stbtt__active_edge *z = new_active(e, off_x, scan_y);+               stbtt__active_edge *z = new_active(e, off_x, scan_y, userdata);                // find insertion point                if (active == NULL)                   active = z;@@ -1208,11 +1324,11 @@    while (active) {       stbtt__active_edge *z = active;       active = active->next;-      STBTT_free(z);+      STBTT_free(z, userdata);    }     if (scanline != scanline_data)-      STBTT_free(scanline);+      STBTT_free(scanline, userdata); }  static int stbtt__edge_compare(const void *p, const void *q)@@ -1230,7 +1346,7 @@    float x,y; } stbtt__point; -static void stbtt__rasterize(stbtt__bitmap *result, stbtt__point *pts, int *wcount, int windings, float scale_x, float scale_y, int off_x, int off_y, int invert)+static void stbtt__rasterize(stbtt__bitmap *result, stbtt__point *pts, int *wcount, int windings, float scale_x, float scale_y, int off_x, int off_y, int invert, void *userdata) {    float y_scale_inv = invert ? -scale_y : scale_y;    stbtt__edge *e;@@ -1243,7 +1359,7 @@    for (i=0; i < windings; ++i)       n += wcount[i]; -   e = (stbtt__edge *) STBTT_malloc(sizeof(*e) * (n+1)); // add an extra one as a sentinel+   e = (stbtt__edge *) STBTT_malloc(sizeof(*e) * (n+1), userdata); // add an extra one as a sentinel    if (e == 0) return;    n = 0; @@ -1258,8 +1374,11 @@          if (p[j].y == p[k].y)             continue;          // add edge from j to k to the list-         if (invert ? p[j].y > p[k].y : p[j].y < p[k].y)+         e[n].invert = 0;+         if (invert ? p[j].y > p[k].y : p[j].y < p[k].y) {+            e[n].invert = 1;             a=j,b=k;+         }          e[n].x0 = p[a].x * scale_x;          e[n].y0 = p[a].y * y_scale_inv * vsubsample;          e[n].x1 = p[b].x * scale_x;@@ -1272,9 +1391,9 @@    STBTT_sort(e, n, sizeof(e[0]), stbtt__edge_compare);     // now, traverse the scanlines and find the intersections on each scanline, use xor winding rule-   stbtt__rasterize_sorted_edges(result, e, n, vsubsample, off_x, off_y);+   stbtt__rasterize_sorted_edges(result, e, n, vsubsample, off_x, off_y, userdata); -   STBTT_free(e);+   STBTT_free(e, userdata); }  static void stbtt__add_point(stbtt__point *points, int n, float x, float y)@@ -1306,7 +1425,7 @@ }  // returns number of contours-stbtt__point *stbtt_FlattenCurves(stbtt_vertex *vertices, int num_verts, float objspace_flatness, int **contour_lengths, int *num_contours)+stbtt__point *stbtt_FlattenCurves(stbtt_vertex *vertices, int num_verts, float objspace_flatness, int **contour_lengths, int *num_contours, void *userdata) {    stbtt__point *points=0;    int num_points=0;@@ -1322,7 +1441,7 @@    *num_contours = n;    if (n == 0) return 0; -   *contour_lengths = (int *) STBTT_malloc(sizeof(**contour_lengths) * n);+   *contour_lengths = (int *) STBTT_malloc(sizeof(**contour_lengths) * n, userdata);     if (*contour_lengths == 0) {       *num_contours = 0;@@ -1331,9 +1450,9 @@     // make two passes through the points so we don't need to realloc    for (pass=0; pass < 2; ++pass) {-      float x,y;+      float x=0,y=0;       if (pass == 1) {-         points = (stbtt__point *) STBTT_malloc(num_points * sizeof(points[0]));+         points = (stbtt__point *) STBTT_malloc(num_points * sizeof(points[0]), userdata);          if (points == NULL) goto error;       }       num_points = 0;@@ -1368,28 +1487,28 @@     return points; error:-   STBTT_free(points);-   STBTT_free(*contour_lengths);+   STBTT_free(points, userdata);+   STBTT_free(*contour_lengths, userdata);    *contour_lengths = 0;    *num_contours = 0;    return NULL; } -void stbtt_Rasterize(stbtt__bitmap *result, float flatness_in_pixels, stbtt_vertex *vertices, int num_verts, float scale_x, float scale_y, int x_off, int y_off, int invert)+void stbtt_Rasterize(stbtt__bitmap *result, float flatness_in_pixels, stbtt_vertex *vertices, int num_verts, float scale_x, float scale_y, int x_off, int y_off, int invert, void *userdata) {    float scale = scale_x > scale_y ? scale_y : scale_x;    int winding_count, *winding_lengths;-   stbtt__point *windings = stbtt_FlattenCurves(vertices, num_verts, flatness_in_pixels / scale, &winding_lengths, &winding_count);+   stbtt__point *windings = stbtt_FlattenCurves(vertices, num_verts, flatness_in_pixels / scale, &winding_lengths, &winding_count, userdata);    if (windings) {-      stbtt__rasterize(result, windings, winding_lengths, winding_count, scale_x, scale_y, x_off, y_off, invert);-      STBTT_free(winding_lengths);-      STBTT_free(windings);+      stbtt__rasterize(result, windings, winding_lengths, winding_count, scale_x, scale_y, x_off, y_off, invert, userdata);+      STBTT_free(winding_lengths, userdata);+      STBTT_free(windings, userdata);    } } -void stbtt_FreeBitmap(unsigned char *bitmap)+void stbtt_FreeBitmap(unsigned char *bitmap, void *userdata) {-   STBTT_free(bitmap);+   STBTT_free(bitmap, userdata); }  unsigned char *stbtt_GetGlyphBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int glyph, int *width, int *height, int *xoff, int *yoff)@@ -1418,14 +1537,14 @@    if (yoff  ) *yoff   = iy0;        if (gbm.w && gbm.h) {-      gbm.pixels = (unsigned char *) STBTT_malloc(gbm.w * gbm.h);+      gbm.pixels = (unsigned char *) STBTT_malloc(gbm.w * gbm.h, info->userdata);       if (gbm.pixels) {          gbm.stride = gbm.w; -         stbtt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, ix0, iy0, 1);+         stbtt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, ix0, iy0, 1, info->userdata);       }    }-   STBTT_free(vertices);+   STBTT_free(vertices, info->userdata);    return gbm.pixels; }    @@ -1443,9 +1562,9 @@    gbm.stride = out_stride;     if (gbm.w && gbm.h)-      stbtt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, ix0,iy0, 1);+      stbtt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, ix0,iy0, 1, info->userdata); -   STBTT_free(vertices);+   STBTT_free(vertices, info->userdata); }  unsigned char *stbtt_GetCodepointBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int codepoint, int *width, int *height, int *xoff, int *yoff)@@ -1494,10 +1613,10 @@       STBTT_assert(x+gw < pw);       STBTT_assert(y+gh < ph);       stbtt_MakeGlyphBitmap(&f, pixels+x+y*pw, gw,gh,pw, scale,scale, g);-      chardata[i].x0 = x;-      chardata[i].y0 = y;-      chardata[i].x1 = x + gw;-      chardata[i].y1 = y + gh;+      chardata[i].x0 = (stbtt_int16) x;+      chardata[i].y0 = (stbtt_int16) y;+      chardata[i].x1 = (stbtt_int16) (x + gw);+      chardata[i].y1 = (stbtt_int16) (y + gh);       chardata[i].xadvance = scale * advance;       chardata[i].xoff     = (float) x0;       chardata[i].yoff     = (float) y0;@@ -1511,19 +1630,20 @@ void stbtt_GetBakedQuad(stbtt_bakedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int opengl_fillrule) {    float d3d_bias = opengl_fillrule ? 0 : -0.5f;+   float ipw = 1.0f / pw, iph = 1.0f / ph;    stbtt_bakedchar *b = chardata + char_index;    int round_x = STBTT_ifloor((*xpos + b->xoff) + 0.5);    int round_y = STBTT_ifloor((*ypos + b->yoff) + 0.5); -   q->x0 = round_x - 0.5f + d3d_bias;-   q->y0 = round_y - 0.5f + d3d_bias;-   q->x1 = round_x + b->x1 - b->x0 + 0.5f + d3d_bias;-   q->y1 = round_y + b->y1 - b->y0 + 0.5f + d3d_bias;+   q->x0 = round_x + d3d_bias;+   q->y0 = round_y + d3d_bias;+   q->x1 = round_x + b->x1 - b->x0 + d3d_bias;+   q->y1 = round_y + b->y1 - b->y0 + d3d_bias; -   q->s0 = (b->x0 - 0.5f) / pw;-   q->t0 = (b->y0 - 0.5f) / pw;-   q->s1 = (b->x1 + 0.5f) / ph;-   q->t1 = (b->y1 + 0.5f) / ph;+   q->s0 = b->x0 * ipw;+   q->t0 = b->y0 * ipw;+   q->s1 = b->x1 * iph;+   q->t1 = b->y1 * iph;     *xpos += b->xadvance; }@@ -1687,5 +1807,3 @@ }  #endif // STB_TRUETYPE_IMPLEMENTATION--#endif // __STB_INCLUDE_STB_TRUETYPE_H__
stb-truetype.cabal view
@@ -1,5 +1,5 @@ Name:                stb-truetype-Version:             0.1.1+Version:             0.1.2 Synopsis:            A wrapper around Sean Barrett's TrueType rasterizer library. Description:         A wrapper around Sean Barrett's TrueType rasterizer library. License:             PublicDomain