Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
3002 leency 1
// stb_truetype.h - v0.6c - public domain
2
// authored from 2009-2012 by Sean Barrett / RAD Game Tools
3
//
4
//   This library processes TrueType files:
5
//        parse files
6
//        extract glyph metrics
7
//        extract glyph shapes
8
//        render glyphs to one-channel bitmaps with antialiasing (box filter)
9
//
10
//   Todo:
11
//        non-MS cmaps
12
//        crashproof on bad data
13
//        hinting? (no longer patented)
14
//        cleartype-style AA?
15
//        optimize: use simple memory allocator for intermediates
16
//        optimize: build edge-list directly from curves
17
//        optimize: rasterize directly from curves?
18
//
19
// ADDITIONAL CONTRIBUTORS
20
//
21
//   Mikko Mononen: compound shape support, more cmap formats
22
//   Tor Andersson: kerning, subpixel rendering
23
//
24
//   Bug/warning reports:
25
//       "Zer" on mollyrocket (with fix)
26
//       Cass Everitt
27
//       stoiko (Haemimont Games)
28
//       Brian Hook
29
//       Walter van Niftrik
30
//
31
// VERSION HISTORY
32
//
33
//   0.6c (2012-07-24) improve documentation
34
//   0.6b (2012-07-20) fix a few more warnings
35
//   0.6  (2012-07-17) fix warnings; added stbtt_ScaleForMappingEmToPixels,
36
//                        stbtt_GetFontBoundingBox, stbtt_IsGlyphEmpty
37
//   0.5 (2011-12-09) bugfixes:
38
//                        subpixel glyph renderer computed wrong bounding box
39
//                        first vertex of shape can be off-curve (FreeSans)
40
//   0.4b(2011-12-03) fixed an error in the font baking example
41
//   0.4 (2011-12-01) kerning, subpixel rendering (tor)
42
//                    bugfixes for:
43
//                        codepoint-to-glyph conversion using table fmt=12
44
//                        codepoint-to-glyph conversion using table fmt=4
45
//                        stbtt_GetBakedQuad with non-square texture (Zer)
46
//                    updated Hello World! sample to use kerning and subpixel
47
//                    fixed some warnings
48
//   0.3 (2009-06-24) cmap fmt=12, compound shapes (MM)
49
//                    userdata, malloc-from-userdata, non-zero fill (STB)
50
//   0.2 (2009-03-11) Fix unsigned/signed char warnings
51
//   0.1 (2009-03-09) First public release
52
//
53
// LICENSE
54
//
55
//   This software is in the public domain. Where that dedication is not
56
//   recognized, you are granted a perpetual, irrevokable license to copy
57
//   and modify this file as you see fit.
58
//
59
// USAGE
60
//
61
//   Include this file in whatever places neeed to refer to it. In ONE C/C++
62
//   file, write:
63
//      #define STB_TRUETYPE_IMPLEMENTATION
64
//   before the #include of this file. This expands out the actual
65
//   implementation into that C/C++ file.
66
//
67
//   Look at the header-file sections below for the API, but here's a quick skim:
68
//
69
//   Simple 3D API (don't ship this, but it's fine for tools and quick start,
70
//                  and you can cut and paste from it to move to more advanced)
71
//           stbtt_BakeFontBitmap()               -- bake a font to a bitmap for use as texture
72
//           stbtt_GetBakedQuad()                 -- compute quad to draw for a given char
73
//
74
//   "Load" a font file from a memory buffer (you have to keep the buffer loaded)
75
//           stbtt_InitFont()
76
//           stbtt_GetFontOffsetForIndex()        -- use for TTC font collections
77
//
78
//   Render a unicode codepoint to a bitmap
79
//           stbtt_GetCodepointBitmap()           -- allocates and returns a bitmap
80
//           stbtt_MakeCodepointBitmap()          -- renders into bitmap you provide
81
//           stbtt_GetCodepointBitmapBox()        -- how big the bitmap must be
82
//
83
//   Character advance/positioning
84
//           stbtt_GetCodepointHMetrics()
85
//           stbtt_GetFontVMetrics()
86
//           stbtt_GetCodepointKernAdvance()
87
//
88
// ADDITIONAL DOCUMENTATION
89
//
90
//   Immediately after this block comment are a series of sample programs.
91
//
92
//   After the sample programs is the "header file" section. This section
93
//   includes documentation for each API function.
94
//
95
//   Some important concepts to understand to use this library:
96
//
97
//      Codepoint
98
//         Characters are defined by unicode codepoints, e.g. 65 is
99
//         uppercase A, 231 is lowercase c with a cedilla, 0x7e30 is
100
//         the hiragana for "ma".
101
//
102
//      Glyph
103
//         A visual character shape (every codepoint is rendered as
104
//         some glyph)
105
//
106
//      Glyph index
107
//         A font-specific integer ID representing a glyph
108
//
109
//      Baseline
110
//         Glyph shapes are defined relative to a baseline, which is the
111
//         bottom of uppercase characters. Characters extend both above
112
//         and below the baseline.
113
//
114
//      Current Point
115
//         As you draw text to the screen, you keep track of a "current point"
116
//         which is the origin of each character. The current point's vertical
117
//         position is the baseline. Even "baked fonts" use this model.
118
//
119
//      Vertical Font Metrics
120
//         The vertical qualities of the font, used to vertically position
121
//         and space the characters. See docs for stbtt_GetFontVMetrics.
122
//
123
//      Font Size in Pixels or Points
124
//         The preferred interface for specifying font sizes in stb_truetype
125
//         is to specify how tall the font's vertical extent should be in pixels.
126
//         If that sounds good enough, skip the next paragraph.
127
//
128
//         Most font APIs instead use "points", which are a common typographic
129
//         measurement for describing font size, defined as 72 points per inch.
130
//         stb_truetype provides a point API for compatibility. However, true
131
//         "per inch" conventions don't make much sense on computer displays
132
//         since they different monitors have different number of pixels per
133
//         inch. For example, Windows traditionally uses a convention that
134
//         there are 96 pixels per inch, thus making 'inch' measurements have
135
//         nothing to do with inches, and thus effectively defining a point to
136
//         be 1.333 pixels. Additionally, the TrueType font data provides
137
//         an explicit scale factor to scale a given font's glyphs to points,
138
//         but the author has observed that this scale factor is often wrong
139
//         for non-commercial fonts, thus making fonts scaled in points
140
//         according to the TrueType spec incoherently sized in practice.
141
//
142
// ADVANCED USAGE
143
//
144
//   Quality:
145
//
146
//    - Use the functions with Subpixel at the end to allow your characters
147
//      to have subpixel positioning. Since the font is anti-aliased, not
148
//      hinted, this is very import for quality. (This is not possible with
149
//      baked fonts.)
150
//
151
//    - Kerning is now supported, and if you're supporting subpixel rendering
152
//      then kerning is worth using to give your text a polished look.
153
//
154
//   Performance:
155
//
156
//    - Convert Unicode codepoints to glyph indexes and operate on the glyphs;
157
//      if you don't do this, stb_truetype is forced to do the conversion on
158
//      every call.
159
//
160
//    - There are a lot of memory allocations. We should modify it to take
161
//      a temp buffer and allocate from the temp buffer (without freeing),
162
//      should help performance a lot.
163
//
164
// NOTES
165
//
166
//   The system uses the raw data found in the .ttf file without changing it
167
//   and without building auxiliary data structures. This is a bit inefficient
168
//   on little-endian systems (the data is big-endian), but assuming you're
169
//   caching the bitmaps or glyph shapes this shouldn't be a big deal.
170
//
171
//   It appears to be very hard to programmatically determine what font a
172
//   given file is in a general way. I provide an API for this, but I don't
173
//   recommend it.
174
//
175
//
176
// SOURCE STATISTICS (based on v0.6c, 2050 LOC)
177
//
178
//   Documentation & header file        520 LOC  \___ 660 LOC documentation
179
//   Sample code                        140 LOC  /
180
//   Truetype parsing                   620 LOC  ---- 620 LOC TrueType
181
//   Software rasterization             240 LOC  \                           .
182
//   Curve tesselation                  120 LOC   \__ 550 LOC Bitmap creation
183
//   Bitmap management                  100 LOC   /
184
//   Baked bitmap interface              70 LOC  /
185
//   Font name matching & access        150 LOC  ---- 150
186
//   C runtime library abstraction       60 LOC  ----  60
187
 
188
 
189
//////////////////////////////////////////////////////////////////////////////
190
//////////////////////////////////////////////////////////////////////////////
191
////
192
////  SAMPLE PROGRAMS
193
////
194
//
195
//  Incomplete text-in-3d-api example, which draws quads properly aligned to be lossless
196
//
197
#if 0
198
#define STB_TRUETYPE_IMPLEMENTATION  // force following include to generate implementation
199
#include "stb_truetype.h"
200
 
201
char ttf_buffer[1<<20];
202
unsigned char temp_bitmap[512*512];
203
 
204
stbtt_bakedchar cdata[96]; // ASCII 32..126 is 95 glyphs
205
GLstbtt_uint ftex;
206
 
207
void my_stbtt_initfont(void)
208
{
209
   fread(ttf_buffer, 1, 1<<20, fopen("c:/windows/fonts/times.ttf", "rb"));
210
   stbtt_BakeFontBitmap(data,0, 32.0, temp_bitmap,512,512, 32,96, cdata); // no guarantee this fits!
211
   // can free ttf_buffer at this point
212
   glGenTextures(1, &ftex);
213
   glBindTexture(GL_TEXTURE_2D, ftex);
214
   glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, 512,512, 0, GL_ALPHA, GL_UNSIGNED_BYTE, temp_bitmap);
215
   // can free temp_bitmap at this point
216
   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
217
}
218
 
219
void my_stbtt_print(float x, float y, char *text)
220
{
221
   // assume orthographic projection with units = screen pixels, origin at top left
222
   glBindTexture(GL_TEXTURE_2D, ftex);
223
   glBegin(GL_QUADS);
224
   while (*text) {
225
      if (*text >= 32 && *text < 128) {
226
         stbtt_aligned_quad q;
227
         stbtt_GetBakedQuad(cdata, 512,512, *text-32, &x,&y,&q,1);//1=opengl,0=old d3d
228
         glTexCoord2f(q.s0,q.t1); glVertex2f(q.x0,q.y0);
229
         glTexCoord2f(q.s1,q.t1); glVertex2f(q.x1,q.y0);
230
         glTexCoord2f(q.s1,q.t0); glVertex2f(q.x1,q.y1);
231
         glTexCoord2f(q.s0,q.t0); glVertex2f(q.x0,q.y1);
232
      }
233
      ++text;
234
   }
235
   glEnd();
236
}
237
#endif
238
//
239
//
240
//////////////////////////////////////////////////////////////////////////////
241
//
242
// Complete program (this compiles): get a single bitmap, print as ASCII art
243
//
244
#if 0
245
#include 
246
#define STB_TRUETYPE_IMPLEMENTATION  // force following include to generate implementation
247
#include "stb_truetype.h"
248
 
249
char ttf_buffer[1<<25];
250
 
251
int main(int argc, char **argv)
252
{
253
   stbtt_fontinfo font;
254
   unsigned char *bitmap;
255
   int w,h,i,j,c = (argc > 1 ? atoi(argv[1]) : 'a'), s = (argc > 2 ? atoi(argv[2]) : 20);
256
 
257
   fread(ttf_buffer, 1, 1<<25, fopen(argc > 3 ? argv[3] : "c:/windows/fonts/arialbd.ttf", "rb"));
258
 
259
   stbtt_InitFont(&font, ttf_buffer, stbtt_GetFontOffsetForIndex(ttf_buffer,0));
260
   bitmap = stbtt_GetCodepointBitmap(&font, 0,stbtt_ScaleForPixelHeight(&font, s), c, &w, &h, 0,0);
261
 
262
   for (j=0; j < h; ++j) {
263
      for (i=0; i < w; ++i)
264
         putchar(" .:ioVM@"[bitmap[j*w+i]>>5]);
265
      putchar('\n');
266
   }
267
   return 0;
268
}
269
#endif
270
//
271
// Output:
272
//
273
//     .ii.
274
//    @@@@@@.
275
//   V@Mio@@o
276
//   :i.  V@V
277
//     :oM@@M
278
//   :@@@MM@M
279
//   @@o  o@M
280
//  :@@.  M@M
281
//   @@@o@@@@
282
//   :M@@V:@@.
283
//
284
//////////////////////////////////////////////////////////////////////////////
285
//
286
// Complete program: print "Hello World!" banner, with bugs
287
//
288
#if 0
289
char buffer[24<<20];
290
unsigned char screen[20][79];
291
 
292
int main(int arg, char **argv)
293
{
294
   stbtt_fontinfo font;
295
   int i,j,ascent,baseline,ch=0;
296
   float scale, xpos=0;
297
   char *text = "Heljo World!";
298
 
299
   fread(buffer, 1, 1000000, fopen("c:/windows/fonts/arialbd.ttf", "rb"));
300
   stbtt_InitFont(&font, buffer, 0);
301
 
302
   scale = stbtt_ScaleForPixelHeight(&font, 15);
303
   stbtt_GetFontVMetrics(&font, &ascent,0,0);
304
   baseline = (int) (ascent*scale);
305
 
306
   while (text[ch]) {
307
      int advance,lsb,x0,y0,x1,y1;
308
      float x_shift = xpos - (float) floor(xpos);
309
      stbtt_GetCodepointHMetrics(&font, text[ch], &advance, &lsb);
310
      stbtt_GetCodepointBitmapBoxSubpixel(&font, text[ch], scale,scale,x_shift,0, &x0,&y0,&x1,&y1);
311
      stbtt_MakeCodepointBitmapSubpixel(&font, &screen[baseline + y0][(int) xpos + x0], x1-x0,y1-y0, 79, scale,scale,x_shift,0, text[ch]);
312
      // note that this stomps the old data, so where character boxes overlap (e.g. 'lj') it's wrong
313
      // because this API is really for baking character bitmaps into textures. if you want to render
314
      // a sequence of characters, you really need to render each bitmap to a temp buffer, then
315
      // "alpha blend" that into the working buffer
316
      xpos += (advance * scale);
317
      if (text[ch+1])
318
         xpos += scale*stbtt_GetCodepointKernAdvance(&font, text[ch],text[ch+1]);
319
      ++ch;
320
   }
321
 
322
   for (j=0; j < 20; ++j) {
323
      for (i=0; i < 78; ++i)
324
         putchar(" .:ioVM@"[screen[j][i]>>5]);
325
      putchar('\n');
326
   }
327
 
328
   return 0;
329
}
330
#endif
331
 
332
 
333
//////////////////////////////////////////////////////////////////////////////
334
//////////////////////////////////////////////////////////////////////////////
335
////
336
////   INTEGRATION WITH YOUR CODEBASE
337
////
338
////   The following sections allow you to supply alternate definitions
339
////   of C library functions used by stb_truetype.
340
 
341
#ifdef STB_TRUETYPE_IMPLEMENTATION
342
 
343
#define NULL 0
344
typedef unsigned int size_t;
345
   // #define your own (u)stbtt_int8/16/32 before including to override this
346
   #ifndef stbtt_uint8
347
   typedef unsigned char   stbtt_uint8;
348
   typedef signed   char   stbtt_int8;
349
   typedef unsigned short  stbtt_uint16;
350
   typedef signed   short  stbtt_int16;
351
   typedef unsigned int    stbtt_uint32;
352
   typedef signed   int    stbtt_int32;
353
   #endif
354
 
355
   typedef char stbtt__check_size32[sizeof(stbtt_int32)==4 ? 1 : -1];
356
   typedef char stbtt__check_size16[sizeof(stbtt_int16)==2 ? 1 : -1];
357
 
358
 
359
 
360
#define		THRESH		4		/* threshold for insertion */
361
#define		MTHRESH		6		/* threshold for median */
362
 
363
static  int		(*qcmp)(const void *, const void *);		/* the comparison routine */
364
static  int		qsz;			/* size of each record */
365
static  int		thresh;			/* THRESHold in chars */
366
static  int		mthresh;		/* MTHRESHold in chars */
367
 
368
/*
369
 * qst:
370
 * Do a quicksort
371
 * First, find the median element, and put that one in the first place as the
372
 * discriminator.  (This "median" is just the median of the first, last and
373
 * middle elements).  (Using this median instead of the first element is a big
374
 * win).  Then, the usual partitioning/swapping, followed by moving the
375
 * discriminator into the right place.  Then, figure out the sizes of the two
376
 * partions, do the smaller one recursively and the larger one via a repeat of
377
 * this code.  Stopping when there are less than THRESH elements in a partition
378
 * and cleaning up with an insertion sort (in our caller) is a huge win.
379
 * All data swaps are done in-line, which is space-losing but time-saving.
380
 * (And there are only three places where this is done).
381
 */
382
 
383
static void
384
qst(char *base, char *max)
385
{
386
  char c, *i, *j, *jj;
387
  int ii;
388
  char *mid, *tmp;
389
  int lo, hi;
390
 
391
  /*
392
   * At the top here, lo is the number of characters of elements in the
393
   * current partition.  (Which should be max - base).
394
   * Find the median of the first, last, and middle element and make
395
   * that the middle element.  Set j to largest of first and middle.
396
   * If max is larger than that guy, then it's that guy, else compare
397
   * max with loser of first and take larger.  Things are set up to
398
   * prefer the middle, then the first in case of ties.
399
   */
400
  lo = max - base;		/* number of elements as chars */
401
  do	{
402
    mid = i = base + qsz * ((lo / qsz) >> 1);
403
    if (lo >= mthresh)
404
    {
405
      j = (qcmp((jj = base), i) > 0 ? jj : i);
406
      if (qcmp(j, (tmp = max - qsz)) > 0)
407
      {
408
	/* switch to first loser */
409
	j = (j == jj ? i : jj);
410
	if (qcmp(j, tmp) < 0)
411
	  j = tmp;
412
      }
413
      if (j != i)
414
      {
415
	ii = qsz;
416
	do	{
417
	  c = *i;
418
	  *i++ = *j;
419
	  *j++ = c;
420
	} while (--ii);
421
      }
422
    }
423
    /*
424
     * Semi-standard quicksort partitioning/swapping
425
     */
426
    for (i = base, j = max - qsz; ; )
427
    {
428
      while (i < mid && qcmp(i, mid) <= 0)
429
	i += qsz;
430
      while (j > mid)
431
      {
432
	if (qcmp(mid, j) <= 0)
433
	{
434
	  j -= qsz;
435
	  continue;
436
	}
437
	tmp = i + qsz;		/* value of i after swap */
438
	if (i == mid)
439
	{
440
	  /* j <-> mid, new mid is j */
441
	  mid = jj = j;
442
	}
443
	else
444
	{
445
	  /* i <-> j */
446
	  jj = j;
447
	  j -= qsz;
448
	}
449
	goto swap;
450
      }
451
      if (i == mid)
452
      {
453
	break;
454
      }
455
      else
456
      {
457
	/* i <-> mid, new mid is i */
458
	jj = mid;
459
	tmp = mid = i;		/* value of i after swap */
460
	j -= qsz;
461
      }
462
    swap:
463
      ii = qsz;
464
      do	{
465
	c = *i;
466
	*i++ = *jj;
467
	*jj++ = c;
468
      } while (--ii);
469
      i = tmp;
470
    }
471
    /*
472
     * Look at sizes of the two partitions, do the smaller
473
     * one first by recursion, then do the larger one by
474
     * making sure lo is its size, base and max are update
475
     * correctly, and branching back.  But only repeat
476
     * (recursively or by branching) if the partition is
477
     * of at least size THRESH.
478
     */
479
    i = (j = mid) + qsz;
480
    if ((lo = j - base) <= (hi = max - i))
481
    {
482
      if (lo >= thresh)
483
	qst(base, j);
484
      base = i;
485
      lo = hi;
486
    }
487
    else
488
    {
489
      if (hi >= thresh)
490
	qst(i, max);
491
      max = j;
492
    }
493
  } while (lo >= thresh);
494
}
495
 
496
/*
497
 * qsort:
498
 * First, set up some global parameters for qst to share.  Then, quicksort
499
 * with qst(), and then a cleanup insertion sort ourselves.  Sound simple?
500
 * It's not...
501
 */
502
 
503
void
504
qsort_g(void *base0, size_t n, size_t size, int (*compar)(const void *, const void *))
505
{
506
  char *base = (char *)base0;
507
  char c, *i, *j, *lo, *hi;
508
  char *min, *max;
509
 
510
  if (n <= 1)
511
    return;
512
  qsz = size;
513
  qcmp = compar;
514
  thresh = qsz * THRESH;
515
  mthresh = qsz * MTHRESH;
516
  max = base + n * qsz;
517
  if (n >= THRESH)
518
  {
519
    qst(base, max);
520
    hi = base + thresh;
521
  }
522
  else
523
  {
524
    hi = max;
525
  }
526
  /*
527
   * First put smallest element, which must be in the first THRESH, in
528
   * the first position as a sentinel.  This is done just by searching
529
   * the first THRESH elements (or the first n if n < THRESH), finding
530
   * the min, and swapping it into the first position.
531
   */
532
  for (j = lo = base; (lo += qsz) < hi; )
533
    if (qcmp(j, lo) > 0)
534
      j = lo;
535
  if (j != base)
536
  {
537
    /* swap j into place */
538
    for (i = base, hi = base + qsz; i < hi; )
539
    {
540
      c = *j;
541
      *j++ = *i;
542
      *i++ = c;
543
    }
544
  }
545
  /*
546
   * With our sentinel in place, we now run the following hyper-fast
547
   * insertion sort.  For each remaining element, min, from [1] to [n-1],
548
   * set hi to the index of the element AFTER which this one goes.
549
   * Then, do the standard insertion sort shift on a character at a time
550
   * basis for each element in the frob.
551
   */
552
  for (min = base; (hi = min += qsz) < max; )
553
  {
554
    while (qcmp(hi -= qsz, min) > 0)
555
      /* void */;
556
    if ((hi += qsz) != min) {
557
      for (lo = min + qsz; --lo >= min; )
558
      {
559
	c = *lo;
560
	for (i = j = lo; (j -= qsz) >= hi; i = j)
561
	  *i = *j;
562
	*i = c;
563
      }
564
    }
565
  }
566
}
567
 
568
 
569
   // #define your own STBTT_sort() to override this to avoid qsort
570
   #ifndef STBTT_sort
571
   //#include 
572
   #define STBTT_sort(data,num_items,item_size,compare_func)   qsort_g(data,num_items,item_size,compare_func)
573
   #endif
574
 
575
asm ("_floor: \n\t"
576
	"pushl	%ebp\n\t"
577
	"movl	%esp,%ebp\n\t"
578
	"subl	$8,%esp\n\t"
579
	"fstcw	-4(%ebp)\n\t"
580
	"fwait\n\t"
581
	"movw	-4(%ebp),%ax\n\t"
582
	"andw	$0xf3ff,%ax\n\t"
583
	"orw	$0x0400,%ax\n\t"
584
	"movw	%ax,-2(%ebp)\n\t"
585
	"fldcw	-2(%ebp)\n\t"
586
	"fldl	8(%ebp)\n\t"
587
	"frndint\n\t"
588
	"fldcw	-4(%ebp)\n\t"
589
	"movl	%ebp,%esp\n\t"
590
	"popl	%ebp\n\t"
591
	"ret");
592
 
593
 
594
int i_floor (float x) {
595
	int z;
596
	z=x;
597
	if (z+1>x) {return z;} else {return (z+1);}
598
 
599
}
600
 
601
int i_ceil (float x) {
602
	int z;
603
	z=x;
604
	if (z>x) {return z;} else {return (z+1);}
605
 
606
}
607
 
608
 
609
double
610
sqrt (double x)
611
{
612
  if (x < 0.0F )
613
    {
614
      return -1;
615
    }
616
  else
617
    {
618
      double res;
619
      asm ("fsqrt" : "=t" (res) : "0" (x));
620
      return res;
621
    }
622
}
623
 
624
   // #define your own STBTT_ifloor/STBTT_iceil() to avoid math.h
625
   #ifndef STBTT_ifloor
626
  // #include 
627
   #define STBTT_ifloor(x)   ((int) i_floor(x))
628
   #define STBTT_iceil(x)    ((int) i_ceil(x))
629
   #endif
630
 
631
static inline void *zmalloc(size_t size) {
632
	void *val; __asm__ __volatile__( "int $0x40" :"=a"(val) :"a"(68),"b"(12),"c"(size));
633
	 return val; }
634
 
635
 
636
void zfree(void *p)
637
{
638
asm ("int $0x40"::"a"(68), "b"(13), "c"(p) );
639
}
640
 
641
   // #define your own functions "STBTT_malloc" / "STBTT_free" to avoid malloc.h
642
   #ifndef STBTT_malloc
643
  //#include 
644
   #define STBTT_malloc(x,u)  zmalloc(x)
645
   #define STBTT_free(x,u)    zfree(x)
646
   #endif
647
 
648
#define assert_g(ignore)((void) 0)
649
 
650
   #ifndef STBTT_assert
651
   //#include 
652
   #define STBTT_assert(x)    assert_g(x)
653
   #endif
654
 
655
 
656
int strlen_g(const char* string)
657
{
658
	int i;
659
	i=0;
660
	while (*string++) i++;
661
	return i;
662
}
663
 
664
 
665
   #ifndef STBTT_strlen
666
   //#include 
667
   #define STBTT_strlen(x)    strlen_g(x)
668
   #endif
669
 
670
void*  zmemset(void *mem, int c, unsigned size)
671
{
672
unsigned i;
673
 
674
for ( i = 0; i < size; i++ )
675
	 *((char *)mem+i) = (char) c;
676
 
677
return 0;
678
}
679
 
680
 
681
void* zmemcpy(void *dst, const void *src, unsigned size)
682
{
683
 
684
unsigned i;
685
 
686
for ( i = 0; i < size; i++)
687
	*(char *)(dst+i) = *(char *)(src+i);
688
 
689
return 0;
690
}
691
 
692
   #ifndef STBTT_memcpy
693
  // #include 
694
   #define STBTT_memcpy       zmemcpy
695
   #define STBTT_memset       zmemset
696
   #endif
697
#endif
698
 
699
///////////////////////////////////////////////////////////////////////////////
700
///////////////////////////////////////////////////////////////////////////////
701
////
702
////   INTERFACE
703
////
704
////
705
 
706
#ifndef __STB_INCLUDE_STB_TRUETYPE_H__
707
#define __STB_INCLUDE_STB_TRUETYPE_H__
708
 
709
#ifdef __cplusplus
710
extern "C" {
711
#endif
712
 
713
//////////////////////////////////////////////////////////////////////////////
714
//
715
// TEXTURE BAKING API
716
//
717
// If you use this API, you only have to call two functions ever.
718
//
719
 
720
typedef struct
721
{
722
   unsigned short x0,y0,x1,y1; // coordinates of bbox in bitmap
723
   float xoff,yoff,xadvance;
724
} stbtt_bakedchar;
725
 
726
extern int stbtt_BakeFontBitmap(const unsigned char *data, int offset,  // font location (use offset=0 for plain .ttf)
727
                                float pixel_height,                     // height of font in pixels
728
                                unsigned char *pixels, int pw, int ph,  // bitmap to be filled in
729
                                int first_char, int num_chars,          // characters to bake
730
                                stbtt_bakedchar *chardata);             // you allocate this, it's num_chars long
731
// if return is positive, the first unused row of the bitmap
732
// if return is negative, returns the negative of the number of characters that fit
733
// if return is 0, no characters fit and no rows were used
734
// This uses a very crappy packing.
735
 
736
typedef struct
737
{
738
   float x0,y0,s0,t0; // top-left
739
   float x1,y1,s1,t1; // bottom-right
740
} stbtt_aligned_quad;
741
 
742
extern void stbtt_GetBakedQuad(stbtt_bakedchar *chardata, int pw, int ph,  // same data as above
743
                               int char_index,             // character to display
744
                               float *xpos, float *ypos,   // pointers to current position in screen pixel space
745
                               stbtt_aligned_quad *q,      // output: quad to draw
746
                               int opengl_fillrule);       // true if opengl fill rule; false if DX9 or earlier
747
// Call GetBakedQuad with char_index = 'character - first_char', and it
748
// creates the quad you need to draw and advances the current position.
749
//
750
// The coordinate system used assumes y increases downwards.
751
//
752
// Characters will extend both above and below the current position;
753
// see discussion of "BASELINE" above.
754
//
755
// It's inefficient; you might want to c&p it and optimize it.
756
 
757
 
758
//////////////////////////////////////////////////////////////////////////////
759
//
760
// FONT LOADING
761
//
762
//
763
 
764
extern int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index);
765
// Each .ttf/.ttc file may have more than one font. Each font has a sequential
766
// index number starting from 0. Call this function to get the font offset for
767
// a given index; it returns -1 if the index is out of range. A regular .ttf
768
// file will only define one font and it always be at offset 0, so it will
769
// return '0' for index 0, and -1 for all other indices. You can just skip
770
// this step if you know it's that kind of font.
771
 
772
 
773
// The following structure is defined publically so you can declare one on
774
// the stack or as a global or etc, but you should treat it as opaque.
775
typedef struct stbtt_fontinfo
776
{
777
   void           * userdata;
778
   unsigned char  * data;              // pointer to .ttf file
779
   int              fontstart;         // offset of start of font
780
 
781
   int numGlyphs;                     // number of glyphs, needed for range checking
782
 
783
   int loca,head,glyf,hhea,hmtx,kern; // table locations as offset from start of .ttf
784
   int index_map;                     // a cmap mapping for our chosen character encoding
785
   int indexToLocFormat;              // format needed to map from glyph index to glyph
786
} stbtt_fontinfo;
787
 
788
extern int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data, int offset);
789
// Given an offset into the file that defines a font, this function builds
790
// the necessary cached info for the rest of the system. You must allocate
791
// the stbtt_fontinfo yourself, and stbtt_InitFont will fill it out. You don't
792
// need to do anything special to free it, because the contents are pure
793
// value data with no additional data structures. Returns 0 on failure.
794
 
795
 
796
//////////////////////////////////////////////////////////////////////////////
797
//
798
// CHARACTER TO GLYPH-INDEX CONVERSIOn
799
 
800
int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codepoint);
801
// If you're going to perform multiple operations on the same character
802
// and you want a speed-up, call this function with the character you're
803
// going to process, then use glyph-based functions instead of the
804
// codepoint-based functions.
805
 
806
 
807
//////////////////////////////////////////////////////////////////////////////
808
//
809
// CHARACTER PROPERTIES
810
//
811
 
812
extern float stbtt_ScaleForPixelHeight(const stbtt_fontinfo *info, float pixels);
813
// computes a scale factor to produce a font whose "height" is 'pixels' tall.
814
// Height is measured as the distance from the highest ascender to the lowest
815
// descender; in other words, it's equivalent to calling stbtt_GetFontVMetrics
816
// and computing:
817
//       scale = pixels / (ascent - descent)
818
// so if you prefer to measure height by the ascent only, use a similar calculation.
819
 
820
extern float stbtt_ScaleForMappingEmToPixels(const stbtt_fontinfo *info, float pixels);
821
// computes a scale factor to produce a font whose EM size is mapped to
822
// 'pixels' tall. This is probably what traditional APIs compute, but
823
// I'm not positive.
824
 
825
extern void stbtt_GetFontVMetrics(const stbtt_fontinfo *info, int *ascent, int *descent, int *lineGap);
826
// ascent is the coordinate above the baseline the font extends; descent
827
// is the coordinate below the baseline the font extends (i.e. it is typically negative)
828
// lineGap is the spacing between one row's descent and the next row's ascent...
829
// so you should advance the vertical position by "*ascent - *descent + *lineGap"
830
//   these are expressed in unscaled coordinates, so you must multiply by
831
//   the scale factor for a given size
832
 
833
extern void stbtt_GetFontBoundingBox(const stbtt_fontinfo *info, int *x0, int *y0, int *x1, int *y1);
834
// the bounding box around all possible characters
835
 
836
extern void stbtt_GetCodepointHMetrics(const stbtt_fontinfo *info, int codepoint, int *advanceWidth, int *leftSideBearing);
837
// leftSideBearing is the offset from the current horizontal position to the left edge of the character
838
// advanceWidth is the offset from the current horizontal position to the next horizontal position
839
//   these are expressed in unscaled coordinates
840
 
841
extern int  stbtt_GetCodepointKernAdvance(const stbtt_fontinfo *info, int ch1, int ch2);
842
// an additional amount to add to the 'advance' value between ch1 and ch2
843
// @TODO; for now always returns 0!
844
 
845
extern int stbtt_GetCodepointBox(const stbtt_fontinfo *info, int codepoint, int *x0, int *y0, int *x1, int *y1);
846
// Gets the bounding box of the visible part of the glyph, in unscaled coordinates
847
 
848
extern void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_index, int *advanceWidth, int *leftSideBearing);
849
extern int  stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2);
850
extern int  stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1);
851
// as above, but takes one or more glyph indices for greater efficiency
852
 
853
 
854
//////////////////////////////////////////////////////////////////////////////
855
//
856
// GLYPH SHAPES (you probably don't need these, but they have to go before
857
// the bitmaps for C declaration-order reasons)
858
//
859
 
860
#ifndef STBTT_vmove // you can predefine these to use different values (but why?)
861
   enum {
862
      STBTT_vmove=1,
863
      STBTT_vline,
864
      STBTT_vcurve
865
   };
866
#endif
867
 
868
#ifndef stbtt_vertex // you can predefine this to use different values
869
                   // (we share this with other code at RAD)
870
   #define stbtt_vertex_type short // can't use stbtt_int16 because that's not visible in the header file
871
   typedef struct
872
   {
873
      stbtt_vertex_type x,y,cx,cy;
874
      unsigned char type,padding;
875
   } stbtt_vertex;
876
#endif
877
 
878
extern int stbtt_IsGlyphEmpty(const stbtt_fontinfo *info, int glyph_index);
879
// returns non-zero if nothing is drawn for this glyph
880
 
881
extern int stbtt_GetCodepointShape(const stbtt_fontinfo *info, int unicode_codepoint, stbtt_vertex **vertices);
882
extern int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **vertices);
883
// returns # of vertices and fills *vertices with the pointer to them
884
//   these are expressed in "unscaled" coordinates
885
 
886
extern void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *vertices);
887
// frees the data allocated above
888
 
889
//////////////////////////////////////////////////////////////////////////////
890
//
891
// BITMAP RENDERING
892
//
893
 
894
extern void stbtt_FreeBitmap(unsigned char *bitmap, void *userdata);
895
// frees the bitmap allocated below
896
 
897
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);
898
// allocates a large-enough single-channel 8bpp bitmap and renders the
899
// specified character/glyph at the specified scale into it, with
900
// antialiasing. 0 is no coverage (transparent), 255 is fully covered (opaque).
901
// *width & *height are filled out with the width & height of the bitmap,
902
// which is stored left-to-right, top-to-bottom.
903
//
904
// xoff/yoff are the offset it pixel space from the glyph origin to the top-left of the bitmap
905
 
906
extern unsigned char *stbtt_GetCodepointBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint, int *width, int *height, int *xoff, int *yoff);
907
// the same as stbtt_GetCodepoitnBitmap, but you can specify a subpixel
908
// shift for the character
909
 
910
extern void stbtt_MakeCodepointBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int codepoint);
911
// the same as stbtt_GetCodepointBitmap, but you pass in storage for the bitmap
912
// in the form of 'output', with row spacing of 'out_stride' bytes. the bitmap
913
// is clipped to out_w/out_h bytes. Call stbtt_GetCodepointBitmapBox to get the
914
// width and height and positioning info for it first.
915
 
916
extern void stbtt_MakeCodepointBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint);
917
// same as stbtt_MakeCodepointBitmap, but you can specify a subpixel
918
// shift for the character
919
 
920
extern void stbtt_GetCodepointBitmapBox(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1);
921
// get the bbox of the bitmap centered around the glyph origin; so the
922
// bitmap width is ix1-ix0, height is iy1-iy0, and location to place
923
// the bitmap top left is (leftSideBearing*scale,iy0).
924
// (Note that the bitmap uses y-increases-down, but the shape uses
925
// y-increases-up, so CodepointBitmapBox and CodepointBox are inverted.)
926
 
927
extern void stbtt_GetCodepointBitmapBoxSubpixel(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1);
928
// same as stbtt_GetCodepointBitmapBox, but you can specify a subpixel
929
// shift for the character
930
 
931
// the following functions are equivalent to the above functions, but operate
932
// on glyph indices instead of Unicode codepoints (for efficiency)
933
extern unsigned char *stbtt_GetGlyphBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int glyph, int *width, int *height, int *xoff, int *yoff);
934
extern unsigned char *stbtt_GetGlyphBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int glyph, int *width, int *height, int *xoff, int *yoff);
935
extern void stbtt_MakeGlyphBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int glyph);
936
extern void stbtt_MakeGlyphBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int glyph);
937
extern void stbtt_GetGlyphBitmapBox(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1);
938
extern void stbtt_GetGlyphBitmapBoxSubpixel(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y,float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1);
939
 
940
 
941
// @TODO: don't expose this structure
942
typedef struct
943
{
944
   int w,h,stride;
945
   unsigned char *pixels;
946
} stbtt__bitmap;
947
 
948
extern void stbtt_Rasterize(stbtt__bitmap *result, float flatness_in_pixels, stbtt_vertex *vertices, int num_verts, float scale_x, float scale_y, float shift_x, float shift_y, int x_off, int y_off, int invert, void *userdata);
949
 
950
//////////////////////////////////////////////////////////////////////////////
951
//
952
// Finding the right font...
953
//
954
// You should really just solve this offline, keep your own tables
955
// of what font is what, and don't try to get it out of the .ttf file.
956
// That's because getting it out of the .ttf file is really hard, because
957
// the names in the file can appear in many possible encodings, in many
958
// possible languages, and e.g. if you need a case-insensitive comparison,
959
// the details of that depend on the encoding & language in a complex way
960
// (actually underspecified in truetype, but also gigantic).
961
//
962
// But you can use the provided functions in two possible ways:
963
//     stbtt_FindMatchingFont() will use *case-sensitive* comparisons on
964
//             unicode-encoded names to try to find the font you want;
965
//             you can run this before calling stbtt_InitFont()
966
//
967
//     stbtt_GetFontNameString() lets you get any of the various strings
968
//             from the file yourself and do your own comparisons on them.
969
//             You have to have called stbtt_InitFont() first.
970
 
971
 
972
extern int stbtt_FindMatchingFont(const unsigned char *fontdata, const char *name, int flags);
973
// returns the offset (not index) of the font that matches, or -1 if none
974
//   if you use STBTT_MACSTYLE_DONTCARE, use a font name like "Arial Bold".
975
//   if you use any other flag, use a font name like "Arial"; this checks
976
//     the 'macStyle' header field; i don't know if fonts set this consistently
977
#define STBTT_MACSTYLE_DONTCARE     0
978
#define STBTT_MACSTYLE_BOLD         1
979
#define STBTT_MACSTYLE_ITALIC       2
980
#define STBTT_MACSTYLE_UNDERSCORE   4
981
#define STBTT_MACSTYLE_NONE         8   // <= not same as 0, this makes us check the bitfield is 0
982
 
983
extern int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const char *s2, int len2);
984
// returns 1/0 whether the first string interpreted as utf8 is identical to
985
// the second string interpreted as big-endian utf16... useful for strings from next func
986
 
987
extern const char *stbtt_GetFontNameString(const stbtt_fontinfo *font, int *length, int platformID, int encodingID, int languageID, int nameID);
988
// returns the string (which may be big-endian double byte, e.g. for unicode)
989
// and puts the length in bytes in *length.
990
//
991
// some of the values for the IDs are below; for more see the truetype spec:
992
//     http://developer.apple.com/textfonts/TTRefMan/RM06/Chap6name.html
993
//     http://www.microsoft.com/typography/otspec/name.htm
994
 
995
enum { // platformID
996
   STBTT_PLATFORM_ID_UNICODE   =0,
997
   STBTT_PLATFORM_ID_MAC       =1,
998
   STBTT_PLATFORM_ID_ISO       =2,
999
   STBTT_PLATFORM_ID_MICROSOFT =3
1000
};
1001
 
1002
enum { // encodingID for STBTT_PLATFORM_ID_UNICODE
1003
   STBTT_UNICODE_EID_UNICODE_1_0    =0,
1004
   STBTT_UNICODE_EID_UNICODE_1_1    =1,
1005
   STBTT_UNICODE_EID_ISO_10646      =2,
1006
   STBTT_UNICODE_EID_UNICODE_2_0_BMP=3,
1007
   STBTT_UNICODE_EID_UNICODE_2_0_FULL=4
1008
};
1009
 
1010
enum { // encodingID for STBTT_PLATFORM_ID_MICROSOFT
1011
   STBTT_MS_EID_SYMBOL        =0,
1012
   STBTT_MS_EID_UNICODE_BMP   =1,
1013
   STBTT_MS_EID_SHIFTJIS      =2,
1014
   STBTT_MS_EID_UNICODE_FULL  =10
1015
};
1016
 
1017
enum { // encodingID for STBTT_PLATFORM_ID_MAC; same as Script Manager codes
1018
   STBTT_MAC_EID_ROMAN        =0,   STBTT_MAC_EID_ARABIC       =4,
1019
   STBTT_MAC_EID_JAPANESE     =1,   STBTT_MAC_EID_HEBREW       =5,
1020
   STBTT_MAC_EID_CHINESE_TRAD =2,   STBTT_MAC_EID_GREEK        =6,
1021
   STBTT_MAC_EID_KOREAN       =3,   STBTT_MAC_EID_RUSSIAN      =7
1022
};
1023
 
1024
enum { // languageID for STBTT_PLATFORM_ID_MICROSOFT; same as LCID...
1025
       // problematic because there are e.g. 16 english LCIDs and 16 arabic LCIDs
1026
   STBTT_MS_LANG_ENGLISH     =0x0409,   STBTT_MS_LANG_ITALIAN     =0x0410,
1027
   STBTT_MS_LANG_CHINESE     =0x0804,   STBTT_MS_LANG_JAPANESE    =0x0411,
1028
   STBTT_MS_LANG_DUTCH       =0x0413,   STBTT_MS_LANG_KOREAN      =0x0412,
1029
   STBTT_MS_LANG_FRENCH      =0x040c,   STBTT_MS_LANG_RUSSIAN     =0x0419,
1030
   STBTT_MS_LANG_GERMAN      =0x0407,   STBTT_MS_LANG_SPANISH     =0x0409,
1031
   STBTT_MS_LANG_HEBREW      =0x040d,   STBTT_MS_LANG_SWEDISH     =0x041D
1032
};
1033
 
1034
enum { // languageID for STBTT_PLATFORM_ID_MAC
1035
   STBTT_MAC_LANG_ENGLISH      =0 ,   STBTT_MAC_LANG_JAPANESE     =11,
1036
   STBTT_MAC_LANG_ARABIC       =12,   STBTT_MAC_LANG_KOREAN       =23,
1037
   STBTT_MAC_LANG_DUTCH        =4 ,   STBTT_MAC_LANG_RUSSIAN      =32,
1038
   STBTT_MAC_LANG_FRENCH       =1 ,   STBTT_MAC_LANG_SPANISH      =6 ,
1039
   STBTT_MAC_LANG_GERMAN       =2 ,   STBTT_MAC_LANG_SWEDISH      =5 ,
1040
   STBTT_MAC_LANG_HEBREW       =10,   STBTT_MAC_LANG_CHINESE_SIMPLIFIED =33,
1041
   STBTT_MAC_LANG_ITALIAN      =3 ,   STBTT_MAC_LANG_CHINESE_TRAD =19
1042
};
1043
 
1044
#ifdef __cplusplus
1045
}
1046
#endif
1047
 
1048
#endif // __STB_INCLUDE_STB_TRUETYPE_H__
1049
 
1050
///////////////////////////////////////////////////////////////////////////////
1051
///////////////////////////////////////////////////////////////////////////////
1052
////
1053
////   IMPLEMENTATION
1054
////
1055
////
1056
 
1057
#ifdef STB_TRUETYPE_IMPLEMENTATION
1058
 
1059
//////////////////////////////////////////////////////////////////////////
1060
//
1061
// accessors to parse data from file
1062
//
1063
 
1064
// on platforms that don't allow misaligned reads, if we want to allow
1065
// truetype fonts that aren't padded to alignment, define ALLOW_UNALIGNED_TRUETYPE
1066
 
1067
#define ttBYTE(p)     (* (stbtt_uint8 *) (p))
1068
#define ttCHAR(p)     (* (stbtt_int8 *) (p))
1069
#define ttFixed(p)    ttLONG(p)
1070
 
1071
 
1072
 
1073
//#if defined(STB_TRUETYPE_BIGENDIAN) && !defined(ALLOW_UNALIGNED_TRUETYPE)
1074
/*
1075
   #define ttUSHORT(p)   (* (stbtt_uint16 *) (p))
1076
   #define ttSHORT(p)    (* (stbtt_int16 *) (p))
1077
   #define ttULONG(p)    (* (stbtt_uint32 *) (p))
1078
   #define ttLONG(p)     (* (stbtt_int32 *) (p))
1079
*/
1080
//#else
1081
 
1082
   stbtt_uint16 ttUSHORT(const stbtt_uint8 *p) { return p[0]*256 + p[1]; }
1083
   stbtt_int16 ttSHORT(const stbtt_uint8 *p)   { return p[0]*256 + p[1]; }
1084
   stbtt_uint32 ttULONG(const stbtt_uint8 *p)  { return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; }
1085
   stbtt_int32 ttLONG(const stbtt_uint8 *p)    { return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; }
1086
 
1087
//#endif
1088
 
1089
#define stbtt_tag4(p,c0,c1,c2,c3) ((p)[0] == (c0) && (p)[1] == (c1) && (p)[2] == (c2) && (p)[3] == (c3))
1090
#define stbtt_tag(p,str)           stbtt_tag4(p,str[0],str[1],str[2],str[3])
1091
 
1092
static int stbtt__isfont(const stbtt_uint8 *font)
1093
{
1094
   // check the version number
1095
   if (stbtt_tag4(font, '1',0,0,0))  return 1; // TrueType 1
1096
   if (stbtt_tag(font, "typ1"))   return 1; // TrueType with type 1 font -- we don't support this!
1097
   if (stbtt_tag(font, "OTTO"))   return 1; // OpenType with CFF
1098
   if (stbtt_tag4(font, 0,1,0,0)) return 1; // OpenType 1.0
1099
   return 0;
1100
}
1101
 
1102
// @OPTIMIZE: binary search
1103
static stbtt_uint32 stbtt__find_table(stbtt_uint8 *data, stbtt_uint32 fontstart, const char *tag)
1104
{
1105
   stbtt_int32 num_tables = ttUSHORT(data+fontstart+4);
1106
   stbtt_uint32 tabledir = fontstart + 12;
1107
   stbtt_int32 i;
1108
   for (i=0; i < num_tables; ++i) {
1109
      stbtt_uint32 loc = tabledir + 16*i;
1110
      if (stbtt_tag(data+loc+0, tag))
1111
         return ttULONG(data+loc+8);
1112
   }
1113
   return 0;
1114
}
1115
 
1116
int stbtt_GetFontOffsetForIndex(const unsigned char *font_collection, int index)
1117
{
1118
   // if it's just a font, there's only one valid index
1119
   if (stbtt__isfont(font_collection))
1120
      return index == 0 ? 0 : -1;
1121
 
1122
   // check if it's a TTC
1123
   if (stbtt_tag(font_collection, "ttcf")) {
1124
      // version 1?
1125
      if (ttULONG(font_collection+4) == 0x00010000 || ttULONG(font_collection+4) == 0x00020000) {
1126
         stbtt_int32 n = ttLONG(font_collection+8);
1127
         if (index >= n)
1128
            return -1;
1129
         return ttULONG(font_collection+12+index*14);
1130
      }
1131
   }
1132
   return -1;
1133
}
1134
 
1135
int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data2, int fontstart)
1136
{
1137
   stbtt_uint8 *data = (stbtt_uint8 *) data2;
1138
   stbtt_uint32 cmap, t;
1139
   stbtt_int32 i,numTables;
1140
 
1141
   info->data = data;
1142
   info->fontstart = fontstart;
1143
 
1144
   cmap = stbtt__find_table(data, fontstart, "cmap");       // required
1145
   info->loca = stbtt__find_table(data, fontstart, "loca"); // required
1146
   info->head = stbtt__find_table(data, fontstart, "head"); // required
1147
   info->glyf = stbtt__find_table(data, fontstart, "glyf"); // required
1148
   info->hhea = stbtt__find_table(data, fontstart, "hhea"); // required
1149
   info->hmtx = stbtt__find_table(data, fontstart, "hmtx"); // required
1150
   info->kern = stbtt__find_table(data, fontstart, "kern"); // not required
1151
   if (!cmap || !info->loca || !info->head || !info->glyf || !info->hhea || !info->hmtx)
1152
      return 0;
1153
 
1154
   t = stbtt__find_table(data, fontstart, "maxp");
1155
   if (t)
1156
      info->numGlyphs = ttUSHORT(data+t+4);
1157
   else
1158
      info->numGlyphs = 0xffff;
1159
 
1160
   // find a cmap encoding table we understand *now* to avoid searching
1161
   // later. (todo: could make this installable)
1162
   // the same regardless of glyph.
1163
   numTables = ttUSHORT(data + cmap + 2);
1164
   info->index_map = 0;
1165
   for (i=0; i < numTables; ++i) {
1166
      stbtt_uint32 encoding_record = cmap + 4 + 8 * i;
1167
      // find an encoding we understand:
1168
      switch(ttUSHORT(data+encoding_record)) {
1169
         case STBTT_PLATFORM_ID_MICROSOFT:
1170
            switch (ttUSHORT(data+encoding_record+2)) {
1171
               case STBTT_MS_EID_UNICODE_BMP:
1172
               case STBTT_MS_EID_UNICODE_FULL:
1173
                  // MS/Unicode
1174
                  info->index_map = cmap + ttULONG(data+encoding_record+4);
1175
                  break;
1176
            }
1177
            break;
1178
      }
1179
   }
1180
   if (info->index_map == 0)
1181
      return 0;
1182
 
1183
   info->indexToLocFormat = ttUSHORT(data+info->head + 50);
1184
   return 1;
1185
}
1186
 
1187
int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codepoint)
1188
{
1189
   stbtt_uint8 *data = info->data;
1190
   stbtt_uint32 index_map = info->index_map;
1191
 
1192
   stbtt_uint16 format = ttUSHORT(data + index_map + 0);
1193
   if (format == 0) { // apple byte encoding
1194
      stbtt_int32 bytes = ttUSHORT(data + index_map + 2);
1195
      if (unicode_codepoint < bytes-6)
1196
         return ttBYTE(data + index_map + 6 + unicode_codepoint);
1197
      return 0;
1198
   } else if (format == 6) {
1199
      stbtt_uint32 first = ttUSHORT(data + index_map + 6);
1200
      stbtt_uint32 count = ttUSHORT(data + index_map + 8);
1201
      if ((stbtt_uint32) unicode_codepoint >= first && (stbtt_uint32) unicode_codepoint < first+count)
1202
         return ttUSHORT(data + index_map + 10 + (unicode_codepoint - first)*2);
1203
      return 0;
1204
   } else if (format == 2) {
1205
      STBTT_assert(0); // @TODO: high-byte mapping for japanese/chinese/korean
1206
      return 0;
1207
   } else if (format == 4) { // standard mapping for windows fonts: binary search collection of ranges
1208
      stbtt_uint16 segcount = ttUSHORT(data+index_map+6) >> 1;
1209
      stbtt_uint16 searchRange = ttUSHORT(data+index_map+8) >> 1;
1210
      stbtt_uint16 entrySelector = ttUSHORT(data+index_map+10);
1211
      stbtt_uint16 rangeShift = ttUSHORT(data+index_map+12) >> 1;
1212
      stbtt_uint16 item, offset, start, end;
1213
 
1214
      // do a binary search of the segments
1215
      stbtt_uint32 endCount = index_map + 14;
1216
      stbtt_uint32 search = endCount;
1217
 
1218
      if (unicode_codepoint > 0xffff)
1219
         return 0;
1220
 
1221
      // they lie from endCount .. endCount + segCount
1222
      // but searchRange is the nearest power of two, so...
1223
      if (unicode_codepoint >= ttUSHORT(data + search + rangeShift*2))
1224
         search += rangeShift*2;
1225
 
1226
      // now decrement to bias correctly to find smallest
1227
      search -= 2;
1228
      while (entrySelector) {
1229
         stbtt_uint16 start, end;
1230
         searchRange >>= 1;
1231
         start = ttUSHORT(data + search + 2 + segcount*2 + 2);
1232
         end = ttUSHORT(data + search + 2);
1233
         start = ttUSHORT(data + search + searchRange*2 + segcount*2 + 2);
1234
         end = ttUSHORT(data + search + searchRange*2);
1235
         if (unicode_codepoint > end)
1236
            search += searchRange*2;
1237
         --entrySelector;
1238
      }
1239
      search += 2;
1240
 
1241
      item = (stbtt_uint16) ((search - endCount) >> 1);
1242
 
1243
      STBTT_assert(unicode_codepoint <= ttUSHORT(data + endCount + 2*item));
1244
      start = ttUSHORT(data + index_map + 14 + segcount*2 + 2 + 2*item);
1245
      end = ttUSHORT(data + index_map + 14 + 2 + 2*item);
1246
      if (unicode_codepoint < start)
1247
         return 0;
1248
 
1249
      offset = ttUSHORT(data + index_map + 14 + segcount*6 + 2 + 2*item);
1250
      if (offset == 0)
1251
         return (stbtt_uint16) (unicode_codepoint + ttSHORT(data + index_map + 14 + segcount*4 + 2 + 2*item));
1252
 
1253
      return ttUSHORT(data + offset + (unicode_codepoint-start)*2 + index_map + 14 + segcount*6 + 2 + 2*item);
1254
   } else if (format == 12 || format == 13) {
1255
      stbtt_uint32 ngroups = ttULONG(data+index_map+12);
1256
      stbtt_int32 low,high;
1257
      //stbtt_uint16 g = 0;
1258
      low = 0; high = (stbtt_int32)ngroups;
1259
      // Binary search the right group.
1260
      while (low < high) {
1261
         stbtt_int32 mid = low + ((high-low) >> 1); // rounds down, so low <= mid < high
1262
         stbtt_uint32 start_char = ttULONG(data+index_map+16+mid*12);
1263
         stbtt_uint32 end_char = ttULONG(data+index_map+16+mid*12+4);
1264
         if ((stbtt_uint32) unicode_codepoint < start_char)
1265
            high = mid;
1266
         else if ((stbtt_uint32) unicode_codepoint > end_char)
1267
            low = mid+1;
1268
         else {
1269
            stbtt_uint32 start_glyph = ttULONG(data+index_map+16+mid*12+8);
1270
            if (format == 12)
1271
               return start_glyph + unicode_codepoint-start_char;
1272
            else // format == 13
1273
               return start_glyph;
1274
         }
1275
      }
1276
      return 0; // not found
1277
   }
1278
   // @TODO
1279
   STBTT_assert(0);
1280
   return 0;
1281
}
1282
 
1283
int stbtt_GetCodepointShape(const stbtt_fontinfo *info, int unicode_codepoint, stbtt_vertex **vertices)
1284
{
1285
   return stbtt_GetGlyphShape(info, stbtt_FindGlyphIndex(info, unicode_codepoint), vertices);
1286
}
1287
 
1288
static void stbtt_setvertex(stbtt_vertex *v, stbtt_uint8 type, stbtt_int32 x, stbtt_int32 y, stbtt_int32 cx, stbtt_int32 cy)
1289
{
1290
   v->type = type;
1291
   v->x = (stbtt_int16) x;
1292
   v->y = (stbtt_int16) y;
1293
   v->cx = (stbtt_int16) cx;
1294
   v->cy = (stbtt_int16) cy;
1295
}
1296
 
1297
static int stbtt__GetGlyfOffset(const stbtt_fontinfo *info, int glyph_index)
1298
{
1299
   int g1,g2;
1300
 
1301
   if (glyph_index >= info->numGlyphs) return -1; // glyph index out of range
1302
   if (info->indexToLocFormat >= 2)    return -1; // unknown index->glyph map format
1303
 
1304
   if (info->indexToLocFormat == 0) {
1305
      g1 = info->glyf + ttUSHORT(info->data + info->loca + glyph_index * 2) * 2;
1306
      g2 = info->glyf + ttUSHORT(info->data + info->loca + glyph_index * 2 + 2) * 2;
1307
   } else {
1308
      g1 = info->glyf + ttULONG (info->data + info->loca + glyph_index * 4);
1309
      g2 = info->glyf + ttULONG (info->data + info->loca + glyph_index * 4 + 4);
1310
   }
1311
 
1312
   return g1==g2 ? -1 : g1; // if length is 0, return -1
1313
}
1314
 
1315
int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1)
1316
{
1317
   int g = stbtt__GetGlyfOffset(info, glyph_index);
1318
   if (g < 0) return 0;
1319
 
1320
   if (x0) *x0 = ttSHORT(info->data + g + 2);
1321
   if (y0) *y0 = ttSHORT(info->data + g + 4);
1322
   if (x1) *x1 = ttSHORT(info->data + g + 6);
1323
   if (y1) *y1 = ttSHORT(info->data + g + 8);
1324
   return 1;
1325
}
1326
 
1327
int stbtt_GetCodepointBox(const stbtt_fontinfo *info, int codepoint, int *x0, int *y0, int *x1, int *y1)
1328
{
1329
   return stbtt_GetGlyphBox(info, stbtt_FindGlyphIndex(info,codepoint), x0,y0,x1,y1);
1330
}
1331
 
1332
int stbtt_IsGlyphEmpty(const stbtt_fontinfo *info, int glyph_index)
1333
{
1334
   stbtt_int16 numberOfContours;
1335
   int g = stbtt__GetGlyfOffset(info, glyph_index);
1336
   if (g < 0) return 1;
1337
   numberOfContours = ttSHORT(info->data + g);
1338
   return numberOfContours == 0;
1339
}
1340
 
1341
static int stbtt__close_shape(stbtt_vertex *vertices, int num_vertices, int was_off, int start_off,
1342
    stbtt_int32 sx, stbtt_int32 sy, stbtt_int32 scx, stbtt_int32 scy, stbtt_int32 cx, stbtt_int32 cy)
1343
{
1344
   if (start_off) {
1345
      if (was_off)
1346
         stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, (cx+scx)>>1, (cy+scy)>>1, cx,cy);
1347
      stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, sx,sy,scx,scy);
1348
   } else {
1349
      if (was_off)
1350
         stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve,sx,sy,cx,cy);
1351
      else
1352
         stbtt_setvertex(&vertices[num_vertices++], STBTT_vline,sx,sy,0,0);
1353
   }
1354
   return num_vertices;
1355
}
1356
 
1357
int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices)
1358
{
1359
   stbtt_int16 numberOfContours;
1360
   stbtt_uint8 *endPtsOfContours;
1361
   stbtt_uint8 *data = info->data;
1362
   stbtt_vertex *vertices=0;
1363
   int num_vertices=0;
1364
   int g = stbtt__GetGlyfOffset(info, glyph_index);
1365
 
1366
   *pvertices = NULL;
1367
 
1368
   if (g < 0) return 0;
1369
 
1370
   numberOfContours = ttSHORT(data + g);
1371
 
1372
   if (numberOfContours > 0) {
1373
      stbtt_uint8 flags=0,flagcount;
1374
      stbtt_int32 ins, i,j=0,m,n, next_move, was_off=0, off, start_off=0;
1375
      stbtt_int32 x,y,cx,cy,sx,sy, scx,scy;
1376
      stbtt_uint8 *points;
1377
      endPtsOfContours = (data + g + 10);
1378
      ins = ttUSHORT(data + g + 10 + numberOfContours * 2);
1379
      points = data + g + 10 + numberOfContours * 2 + 2 + ins;
1380
 
1381
      n = 1+ttUSHORT(endPtsOfContours + numberOfContours*2-2);
1382
 
1383
      m = n + 2*numberOfContours;  // a loose bound on how many vertices we might need
1384
      vertices = (stbtt_vertex *) STBTT_malloc(m * sizeof(vertices[0]), info->userdata);
1385
      if (vertices == 0)
1386
         return 0;
1387
 
1388
      next_move = 0;
1389
      flagcount=0;
1390
 
1391
      // in first pass, we load uninterpreted data into the allocated array
1392
      // above, shifted to the end of the array so we won't overwrite it when
1393
      // we create our final data starting from the front
1394
 
1395
      off = m - n; // starting offset for uninterpreted data, regardless of how m ends up being calculated
1396
 
1397
      // first load flags
1398
 
1399
      for (i=0; i < n; ++i) {
1400
         if (flagcount == 0) {
1401
            flags = *points++;
1402
            if (flags & 8)
1403
               flagcount = *points++;
1404
         } else
1405
            --flagcount;
1406
         vertices[off+i].type = flags;
1407
      }
1408
 
1409
      // now load x coordinates
1410
      x=0;
1411
      for (i=0; i < n; ++i) {
1412
         flags = vertices[off+i].type;
1413
         if (flags & 2) {
1414
            stbtt_int16 dx = *points++;
1415
            x += (flags & 16) ? dx : -dx; // ???
1416
         } else {
1417
            if (!(flags & 16)) {
1418
               x = x + (stbtt_int16) (points[0]*256 + points[1]);
1419
               points += 2;
1420
            }
1421
         }
1422
         vertices[off+i].x = (stbtt_int16) x;
1423
      }
1424
 
1425
      // now load y coordinates
1426
      y=0;
1427
      for (i=0; i < n; ++i) {
1428
         flags = vertices[off+i].type;
1429
         if (flags & 4) {
1430
            stbtt_int16 dy = *points++;
1431
            y += (flags & 32) ? dy : -dy; // ???
1432
         } else {
1433
            if (!(flags & 32)) {
1434
               y = y + (stbtt_int16) (points[0]*256 + points[1]);
1435
               points += 2;
1436
            }
1437
         }
1438
         vertices[off+i].y = (stbtt_int16) y;
1439
      }
1440
 
1441
      // now convert them to our format
1442
      num_vertices=0;
1443
      sx = sy = cx = cy = scx = scy = 0;
1444
      for (i=0; i < n; ++i) {
1445
         flags = vertices[off+i].type;
1446
         x     = (stbtt_int16) vertices[off+i].x;
1447
         y     = (stbtt_int16) vertices[off+i].y;
1448
 
1449
         if (next_move == i) {
1450
            if (i != 0)
1451
               num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy);
1452
 
1453
            // now start the new one
1454
            start_off = !(flags & 1);
1455
            if (start_off) {
1456
               // if we start off with an off-curve point, then when we need to find a point on the curve
1457
               // where we can start, and we need to save some state for when we wraparound.
1458
               scx = x;
1459
               scy = y;
1460
               if (!(vertices[off+i+1].type & 1)) {
1461
                  // next point is also a curve point, so interpolate an on-point curve
1462
                  sx = (x + (stbtt_int32) vertices[off+i+1].x) >> 1;
1463
                  sy = (y + (stbtt_int32) vertices[off+i+1].y) >> 1;
1464
               } else {
1465
                  // otherwise just use the next point as our start point
1466
                  sx = (stbtt_int32) vertices[off+i+1].x;
1467
                  sy = (stbtt_int32) vertices[off+i+1].y;
1468
                  ++i; // we're using point i+1 as the starting point, so skip it
1469
               }
1470
            } else {
1471
               sx = x;
1472
               sy = y;
1473
            }
1474
            stbtt_setvertex(&vertices[num_vertices++], STBTT_vmove,sx,sy,0,0);
1475
            was_off = 0;
1476
            next_move = 1 + ttUSHORT(endPtsOfContours+j*2);
1477
            ++j;
1478
         } else {
1479
            if (!(flags & 1)) { // if it's a curve
1480
               if (was_off) // two off-curve control points in a row means interpolate an on-curve midpoint
1481
                  stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, (cx+x)>>1, (cy+y)>>1, cx, cy);
1482
               cx = x;
1483
               cy = y;
1484
               was_off = 1;
1485
            } else {
1486
               if (was_off)
1487
                  stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, x,y, cx, cy);
1488
               else
1489
                  stbtt_setvertex(&vertices[num_vertices++], STBTT_vline, x,y,0,0);
1490
               was_off = 0;
1491
            }
1492
         }
1493
      }
1494
      num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy);
1495
   } else if (numberOfContours == -1) {
1496
      // Compound shapes.
1497
      int more = 1;
1498
      stbtt_uint8 *comp = data + g + 10;
1499
      num_vertices = 0;
1500
      vertices = 0;
1501
      while (more) {
1502
         stbtt_uint16 flags, gidx;
1503
         int comp_num_verts = 0, i;
1504
         stbtt_vertex *comp_verts = 0, *tmp = 0;
1505
         float mtx[6] = {1,0,0,1,0,0}, m, n;
1506
 
1507
         flags = ttSHORT(comp); comp+=2;
1508
         gidx = ttSHORT(comp); comp+=2;
1509
 
1510
         if (flags & 2) { // XY values
1511
            if (flags & 1) { // shorts
1512
               mtx[4] = ttSHORT(comp); comp+=2;
1513
               mtx[5] = ttSHORT(comp); comp+=2;
1514
            } else {
1515
               mtx[4] = ttCHAR(comp); comp+=1;
1516
               mtx[5] = ttCHAR(comp); comp+=1;
1517
            }
1518
         }
1519
         else {
1520
            // @TODO handle matching point
1521
            STBTT_assert(0);
1522
         }
1523
         if (flags & (1<<3)) { // WE_HAVE_A_SCALE
1524
            mtx[0] = mtx[3] = ttSHORT(comp)/16384.0f; comp+=2;
1525
            mtx[1] = mtx[2] = 0;
1526
         } else if (flags & (1<<6)) { // WE_HAVE_AN_X_AND_YSCALE
1527
            mtx[0] = ttSHORT(comp)/16384.0f; comp+=2;
1528
            mtx[1] = mtx[2] = 0;
1529
            mtx[3] = ttSHORT(comp)/16384.0f; comp+=2;
1530
         } else if (flags & (1<<7)) { // WE_HAVE_A_TWO_BY_TWO
1531
            mtx[0] = ttSHORT(comp)/16384.0f; comp+=2;
1532
            mtx[1] = ttSHORT(comp)/16384.0f; comp+=2;
1533
            mtx[2] = ttSHORT(comp)/16384.0f; comp+=2;
1534
            mtx[3] = ttSHORT(comp)/16384.0f; comp+=2;
1535
         }
1536
 
1537
         // Find transformation scales.
1538
         m = (float) sqrt(mtx[0]*mtx[0] + mtx[1]*mtx[1]);
1539
         n = (float) sqrt(mtx[2]*mtx[2] + mtx[3]*mtx[3]);
1540
 
1541
         // Get indexed glyph.
1542
         comp_num_verts = stbtt_GetGlyphShape(info, gidx, &comp_verts);
1543
         if (comp_num_verts > 0) {
1544
            // Transform vertices.
1545
            for (i = 0; i < comp_num_verts; ++i) {
1546
               stbtt_vertex* v = &comp_verts[i];
1547
               stbtt_vertex_type x,y;
1548
               x=v->x; y=v->y;
1549
               v->x = (stbtt_vertex_type)(m * (mtx[0]*x + mtx[2]*y + mtx[4]));
1550
               v->y = (stbtt_vertex_type)(n * (mtx[1]*x + mtx[3]*y + mtx[5]));
1551
               x=v->cx; y=v->cy;
1552
               v->cx = (stbtt_vertex_type)(m * (mtx[0]*x + mtx[2]*y + mtx[4]));
1553
               v->cy = (stbtt_vertex_type)(n * (mtx[1]*x + mtx[3]*y + mtx[5]));
1554
            }
1555
            // Append vertices.
1556
            tmp = (stbtt_vertex*)STBTT_malloc((num_vertices+comp_num_verts)*sizeof(stbtt_vertex), info->userdata);
1557
            if (!tmp) {
1558
               if (vertices) STBTT_free(vertices, info->userdata);
1559
               if (comp_verts) STBTT_free(comp_verts, info->userdata);
1560
               return 0;
1561
            }
1562
            //if (num_vertices > 0) STBTT_memset(tmp, vertices, num_vertices*sizeof(stbtt_vertex));
1563
            if (num_vertices > 0) STBTT_memcpy(tmp, vertices, num_vertices*sizeof(stbtt_vertex));//lev
1564
            STBTT_memcpy(tmp+num_vertices, comp_verts, comp_num_verts*sizeof(stbtt_vertex));
1565
            if (vertices) STBTT_free(vertices, info->userdata);
1566
            vertices = tmp;
1567
            STBTT_free(comp_verts, info->userdata);
1568
            num_vertices += comp_num_verts;
1569
         }
1570
         // More components ?
1571
         more = flags & (1<<5);
1572
      }
1573
   } else if (numberOfContours < 0) {
1574
      // @TODO other compound variations?
1575
      STBTT_assert(0);
1576
   } else {
1577
      // numberOfCounters == 0, do nothing
1578
   }
1579
 
1580
   *pvertices = vertices;
1581
   return num_vertices;
1582
}
1583
 
1584
void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_index, int *advanceWidth, int *leftSideBearing)
1585
{
1586
   stbtt_uint16 numOfLongHorMetrics = ttUSHORT(info->data+info->hhea + 34);
1587
   if (glyph_index < numOfLongHorMetrics) {
1588
      if (advanceWidth)     *advanceWidth    = ttSHORT(info->data + info->hmtx + 4*glyph_index);
1589
      if (leftSideBearing)  *leftSideBearing = ttSHORT(info->data + info->hmtx + 4*glyph_index + 2);
1590
   } else {
1591
      if (advanceWidth)     *advanceWidth    = ttSHORT(info->data + info->hmtx + 4*(numOfLongHorMetrics-1));
1592
      if (leftSideBearing)  *leftSideBearing = ttSHORT(info->data + info->hmtx + 4*numOfLongHorMetrics + 2*(glyph_index - numOfLongHorMetrics));
1593
   }
1594
}
1595
 
1596
int  stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2)
1597
{
1598
   stbtt_uint8 *data = info->data + info->kern;
1599
   stbtt_uint32 needle, straw;
1600
   int l, r, m;
1601
 
1602
   // we only look at the first table. it must be 'horizontal' and format 0.
1603
   if (!info->kern)
1604
      return 0;
1605
   if (ttUSHORT(data+2) < 1) // number of tables, need at least 1
1606
      return 0;
1607
   if (ttUSHORT(data+8) != 1) // horizontal flag must be set in format
1608
      return 0;
1609
 
1610
   l = 0;
1611
   r = ttUSHORT(data+10) - 1;
1612
   needle = glyph1 << 16 | glyph2;
1613
   while (l <= r) {
1614
      m = (l + r) >> 1;
1615
      straw = ttULONG(data+18+(m*6)); // note: unaligned read
1616
      if (needle < straw)
1617
         r = m - 1;
1618
      else if (needle > straw)
1619
         l = m + 1;
1620
      else
1621
         return ttSHORT(data+22+(m*6));
1622
   }
1623
   return 0;
1624
}
1625
 
1626
int  stbtt_GetCodepointKernAdvance(const stbtt_fontinfo *info, int ch1, int ch2)
1627
{
1628
   if (!info->kern) // if no kerning table, don't waste time looking up both codepoint->glyphs
1629
      return 0;
1630
   return stbtt_GetGlyphKernAdvance(info, stbtt_FindGlyphIndex(info,ch1), stbtt_FindGlyphIndex(info,ch2));
1631
}
1632
 
1633
void stbtt_GetCodepointHMetrics(const stbtt_fontinfo *info, int codepoint, int *advanceWidth, int *leftSideBearing)
1634
{
1635
   stbtt_GetGlyphHMetrics(info, stbtt_FindGlyphIndex(info,codepoint), advanceWidth, leftSideBearing);
1636
}
1637
 
1638
void stbtt_GetFontVMetrics(const stbtt_fontinfo *info, int *ascent, int *descent, int *lineGap)
1639
{
1640
   if (ascent ) *ascent  = ttSHORT(info->data+info->hhea + 4);
1641
   if (descent) *descent = ttSHORT(info->data+info->hhea + 6);
1642
   if (lineGap) *lineGap = ttSHORT(info->data+info->hhea + 8);
1643
}
1644
 
1645
void stbtt_GetFontBoundingBox(const stbtt_fontinfo *info, int *x0, int *y0, int *x1, int *y1)
1646
{
1647
   *x0 = ttSHORT(info->data + info->head + 36);
1648
   *y0 = ttSHORT(info->data + info->head + 38);
1649
   *x1 = ttSHORT(info->data + info->head + 40);
1650
   *y1 = ttSHORT(info->data + info->head + 42);
1651
}
1652
 
1653
float stbtt_ScaleForPixelHeight(const stbtt_fontinfo *info, float height)
1654
{
1655
   int fheight = ttSHORT(info->data + info->hhea + 4) - ttSHORT(info->data + info->hhea + 6);
1656
   return (float) height / fheight;
1657
}
1658
 
1659
float stbtt_ScaleForMappingEmToPixels(const stbtt_fontinfo *info, float pixels)
1660
{
1661
   int unitsPerEm = ttUSHORT(info->data + info->head + 18);
1662
   return pixels / unitsPerEm;
1663
}
1664
 
1665
void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *v)
1666
{
1667
   STBTT_free(v, info->userdata);
1668
}
1669
 
1670
//////////////////////////////////////////////////////////////////////////////
1671
//
1672
// antialiasing software rasterizer
1673
//
1674
 
1675
void stbtt_GetGlyphBitmapBoxSubpixel(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y,float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1)
1676
{
1677
   int x0,y0,x1,y1;
1678
   if (!stbtt_GetGlyphBox(font, glyph, &x0,&y0,&x1,&y1))
1679
      x0=y0=x1=y1=0; // e.g. space character
1680
   // now move to integral bboxes (treating pixels as little squares, what pixels get touched)?
1681
   if (ix0) *ix0 =  STBTT_ifloor(x0 * scale_x + shift_x);
1682
   if (iy0) *iy0 = -STBTT_iceil (y1 * scale_y + shift_y);
1683
   if (ix1) *ix1 =  STBTT_iceil (x1 * scale_x + shift_x);
1684
   if (iy1) *iy1 = -STBTT_ifloor(y0 * scale_y + shift_y);
1685
}
1686
void stbtt_GetGlyphBitmapBox(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1)
1687
{
1688
   stbtt_GetGlyphBitmapBoxSubpixel(font, glyph, scale_x, scale_y,0.0f,0.0f, ix0, iy0, ix1, iy1);
1689
}
1690
 
1691
void stbtt_GetCodepointBitmapBoxSubpixel(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1)
1692
{
1693
   stbtt_GetGlyphBitmapBoxSubpixel(font, stbtt_FindGlyphIndex(font,codepoint), scale_x, scale_y,shift_x,shift_y, ix0,iy0,ix1,iy1);
1694
}
1695
 
1696
void stbtt_GetCodepointBitmapBox(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1)
1697
{
1698
   stbtt_GetCodepointBitmapBoxSubpixel(font, codepoint, scale_x, scale_y,0.0f,0.0f, ix0,iy0,ix1,iy1);
1699
}
1700
 
1701
typedef struct stbtt__edge {
1702
   float x0,y0, x1,y1;
1703
   int invert;
1704
} stbtt__edge;
1705
 
1706
typedef struct stbtt__active_edge
1707
{
1708
   int x,dx;
1709
   float ey;
1710
   struct stbtt__active_edge *next;
1711
   int valid;
1712
} stbtt__active_edge;
1713
 
1714
#define FIXSHIFT   10
1715
#define FIX        (1 << FIXSHIFT)
1716
#define FIXMASK    (FIX-1)
1717
 
1718
static stbtt__active_edge *new_active(stbtt__edge *e, int off_x, float start_point, void *userdata)
1719
{
1720
   stbtt__active_edge *z = (stbtt__active_edge *) STBTT_malloc(sizeof(*z), userdata); // @TODO: make a pool of these!!!
1721
   float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0);
1722
   STBTT_assert(e->y0 <= start_point);
1723
   if (!z) return z;
1724
   // round dx down to avoid going too far
1725
   if (dxdy < 0)
1726
      z->dx = -STBTT_ifloor(FIX * -dxdy);
1727
   else
1728
      z->dx = STBTT_ifloor(FIX * dxdy);
1729
   z->x = STBTT_ifloor(FIX * (e->x0 + dxdy * (start_point - e->y0)));
1730
   z->x -= off_x * FIX;
1731
   z->ey = e->y1;
1732
   z->next = 0;
1733
   z->valid = e->invert ? 1 : -1;
1734
   return z;
1735
}
1736
 
1737
// note: this routine clips fills that extend off the edges... ideally this
1738
// wouldn't happen, but it could happen if the truetype glyph bounding boxes
1739
// are wrong, or if the user supplies a too-small bitmap
1740
static void stbtt__fill_active_edges(unsigned char *scanline, int len, stbtt__active_edge *e, int max_weight)
1741
{
1742
   // non-zero winding fill
1743
   int x0=0, w=0;
1744
 
1745
   while (e) {
1746
      if (w == 0) {
1747
         // if we're currently at zero, we need to record the edge start point
1748
         x0 = e->x; w += e->valid;
1749
      } else {
1750
         int x1 = e->x; w += e->valid;
1751
         // if we went to zero, we need to draw
1752
         if (w == 0) {
1753
            int i = x0 >> FIXSHIFT;
1754
            int j = x1 >> FIXSHIFT;
1755
 
1756
            if (i < len && j >= 0) {
1757
               if (i == j) {
1758
                  // x0,x1 are the same pixel, so compute combined coverage
1759
                  scanline[i] = scanline[i] + (stbtt_uint8) ((x1 - x0) * max_weight >> FIXSHIFT);
1760
               } else {
1761
                  if (i >= 0) // add antialiasing for x0
1762
                     scanline[i] = scanline[i] + (stbtt_uint8) (((FIX - (x0 & FIXMASK)) * max_weight) >> FIXSHIFT);
1763
                  else
1764
                     i = -1; // clip
1765
 
1766
                  if (j < len) // add antialiasing for x1
1767
                     scanline[j] = scanline[j] + (stbtt_uint8) (((x1 & FIXMASK) * max_weight) >> FIXSHIFT);
1768
                  else
1769
                     j = len; // clip
1770
 
1771
                  for (++i; i < j; ++i) // fill pixels between x0 and x1
1772
                     scanline[i] = scanline[i] + (stbtt_uint8) max_weight;
1773
               }
1774
            }
1775
         }
1776
      }
1777
 
1778
      e = e->next;
1779
   }
1780
}
1781
 
1782
static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, int n, int vsubsample, int off_x, int off_y, void *userdata)
1783
{
1784
   stbtt__active_edge *active = NULL;
1785
   int y,j=0;
1786
   int max_weight = (255 / vsubsample);  // weight per vertical scanline
1787
   int s; // vertical subsample index
1788
   unsigned char scanline_data[512], *scanline;
1789
 
1790
   if (result->w > 512)
1791
      scanline = (unsigned char *) STBTT_malloc(result->w, userdata);
1792
   else
1793
      scanline = scanline_data;
1794
 
1795
   y = off_y * vsubsample;
1796
   e[n].y0 = (off_y + result->h) * (float) vsubsample + 1;
1797
 
1798
   while (j < result->h) {
1799
      STBTT_memset(scanline, 0, result->w);
1800
      for (s=0; s < vsubsample; ++s) {
1801
         // find center of pixel for this scanline
1802
         float scan_y = y + 0.5f;
1803
         stbtt__active_edge **step = &active;
1804
 
1805
         // update all active edges;
1806
         // remove all active edges that terminate before the center of this scanline
1807
         while (*step) {
1808
            stbtt__active_edge * z = *step;
1809
            if (z->ey <= scan_y) {
1810
               *step = z->next; // delete from list
1811
               STBTT_assert(z->valid);
1812
               z->valid = 0;
1813
               STBTT_free(z, userdata);
1814
            } else {
1815
               z->x += z->dx; // advance to position for current scanline
1816
               step = &((*step)->next); // advance through list
1817
            }
1818
         }
1819
 
1820
         // resort the list if needed
1821
         for(;;) {
1822
            int changed=0;
1823
            step = &active;
1824
            while (*step && (*step)->next) {
1825
               if ((*step)->x > (*step)->next->x) {
1826
                  stbtt__active_edge *t = *step;
1827
                  stbtt__active_edge *q = t->next;
1828
 
1829
                  t->next = q->next;
1830
                  q->next = t;
1831
                  *step = q;
1832
                  changed = 1;
1833
               }
1834
               step = &(*step)->next;
1835
            }
1836
            if (!changed) break;
1837
         }
1838
 
1839
         // insert all edges that start before the center of this scanline -- omit ones that also end on this scanline
1840
         while (e->y0 <= scan_y) {
1841
            if (e->y1 > scan_y) {
1842
               stbtt__active_edge *z = new_active(e, off_x, scan_y, userdata);
1843
               // find insertion point
1844
               if (active == NULL)
1845
                  active = z;
1846
               else if (z->x < active->x) {
1847
                  // insert at front
1848
                  z->next = active;
1849
                  active = z;
1850
               } else {
1851
                  // find thing to insert AFTER
1852
                  stbtt__active_edge *p = active;
1853
                  while (p->next && p->next->x < z->x)
1854
                     p = p->next;
1855
                  // at this point, p->next->x is NOT < z->x
1856
                  z->next = p->next;
1857
                  p->next = z;
1858
               }
1859
            }
1860
            ++e;
1861
         }
1862
 
1863
         // now process all active edges in XOR fashion
1864
         if (active)
1865
            stbtt__fill_active_edges(scanline, result->w, active, max_weight);
1866
 
1867
         ++y;
1868
      }
1869
      STBTT_memcpy(result->pixels + j * result->stride, scanline, result->w);
1870
      ++j;
1871
   }
1872
 
1873
   while (active) {
1874
      stbtt__active_edge *z = active;
1875
      active = active->next;
1876
      STBTT_free(z, userdata);
1877
   }
1878
 
1879
   if (scanline != scanline_data)
1880
      STBTT_free(scanline, userdata);
1881
}
1882
 
1883
static int stbtt__edge_compare(const void *p, const void *q)
1884
{
1885
   stbtt__edge *a = (stbtt__edge *) p;
1886
   stbtt__edge *b = (stbtt__edge *) q;
1887
 
1888
   if (a->y0 < b->y0) return -1;
1889
   if (a->y0 > b->y0) return  1;
1890
   return 0;
1891
}
1892
 
1893
typedef struct
1894
{
1895
   float x,y;
1896
} stbtt__point;
1897
 
1898
static void stbtt__rasterize(stbtt__bitmap *result, stbtt__point *pts, int *wcount, int windings, float scale_x, float scale_y, float shift_x, float shift_y, int off_x, int off_y, int invert, void *userdata)
1899
{
1900
   float y_scale_inv = invert ? -scale_y : scale_y;
1901
   stbtt__edge *e;
1902
   int n,i,j,k,m;
1903
   int vsubsample = result->h < 8 ? 15 : 5;
1904
   // vsubsample should divide 255 evenly; otherwise we won't reach full opacity
1905
 
1906
   // now we have to blow out the windings into explicit edge lists
1907
   n = 0;
1908
   for (i=0; i < windings; ++i)
1909
      n += wcount[i];
1910
 
1911
   e = (stbtt__edge *) STBTT_malloc(sizeof(*e) * (n+1), userdata); // add an extra one as a sentinel
1912
   if (e == 0) return;
1913
   n = 0;
1914
 
1915
   m=0;
1916
   for (i=0; i < windings; ++i) {
1917
      stbtt__point *p = pts + m;
1918
      m += wcount[i];
1919
      j = wcount[i]-1;
1920
      for (k=0; k < wcount[i]; j=k++) {
1921
         int a=k,b=j;
1922
         // skip the edge if horizontal
1923
         if (p[j].y == p[k].y)
1924
            continue;
1925
         // add edge from j to k to the list
1926
         e[n].invert = 0;
1927
         if (invert ? p[j].y > p[k].y : p[j].y < p[k].y) {
1928
            e[n].invert = 1;
1929
            a=j,b=k;
1930
         }
1931
         e[n].x0 = p[a].x * scale_x + shift_x;
1932
         e[n].y0 = p[a].y * y_scale_inv * vsubsample + shift_y;
1933
         e[n].x1 = p[b].x * scale_x + shift_x;
1934
         e[n].y1 = p[b].y * y_scale_inv * vsubsample + shift_y;
1935
         ++n;
1936
      }
1937
   }
1938
 
1939
   // now sort the edges by their highest point (should snap to integer, and then by x)
1940
   STBTT_sort(e, n, sizeof(e[0]), stbtt__edge_compare);
1941
 
1942
   // now, traverse the scanlines and find the intersections on each scanline, use xor winding rule
1943
   stbtt__rasterize_sorted_edges(result, e, n, vsubsample, off_x, off_y, userdata);
1944
 
1945
   STBTT_free(e, userdata);
1946
}
1947
 
1948
static void stbtt__add_point(stbtt__point *points, int n, float x, float y)
1949
{
1950
   if (!points) return; // during first pass, it's unallocated
1951
   points[n].x = x;
1952
   points[n].y = y;
1953
}
1954
 
1955
// tesselate until threshhold p is happy... @TODO warped to compensate for non-linear stretching
1956
static int stbtt__tesselate_curve(stbtt__point *points, int *num_points, float x0, float y0, float x1, float y1, float x2, float y2, float objspace_flatness_squared, int n)
1957
{
1958
   // midpoint
1959
   float mx = (x0 + 2*x1 + x2)/4;
1960
   float my = (y0 + 2*y1 + y2)/4;
1961
   // versus directly drawn line
1962
   float dx = (x0+x2)/2 - mx;
1963
   float dy = (y0+y2)/2 - my;
1964
   if (n > 16) // 65536 segments on one curve better be enough!
1965
      return 1;
1966
   if (dx*dx+dy*dy > objspace_flatness_squared) { // half-pixel error allowed... need to be smaller if AA
1967
      stbtt__tesselate_curve(points, num_points, x0,y0, (x0+x1)/2.0f,(y0+y1)/2.0f, mx,my, objspace_flatness_squared,n+1);
1968
      stbtt__tesselate_curve(points, num_points, mx,my, (x1+x2)/2.0f,(y1+y2)/2.0f, x2,y2, objspace_flatness_squared,n+1);
1969
   } else {
1970
      stbtt__add_point(points, *num_points,x2,y2);
1971
      *num_points = *num_points+1;
1972
   }
1973
   return 1;
1974
}
1975
 
1976
// returns number of contours
1977
stbtt__point *stbtt_FlattenCurves(stbtt_vertex *vertices, int num_verts, float objspace_flatness, int **contour_lengths, int *num_contours, void *userdata)
1978
{
1979
   stbtt__point *points=0;
1980
   int num_points=0;
1981
 
1982
   float objspace_flatness_squared = objspace_flatness * objspace_flatness;
1983
   int i,n=0,start=0, pass;
1984
 
1985
   // count how many "moves" there are to get the contour count
1986
   for (i=0; i < num_verts; ++i)
1987
      if (vertices[i].type == STBTT_vmove)
1988
         ++n;
1989
 
1990
   *num_contours = n;
1991
   if (n == 0) return 0;
1992
 
1993
   *contour_lengths = (int *) STBTT_malloc(sizeof(**contour_lengths) * n, userdata);
1994
 
1995
   if (*contour_lengths == 0) {
1996
      *num_contours = 0;
1997
      return 0;
1998
   }
1999
 
2000
   // make two passes through the points so we don't need to realloc
2001
   for (pass=0; pass < 2; ++pass) {
2002
      float x=0,y=0;
2003
      if (pass == 1) {
2004
         points = (stbtt__point *) STBTT_malloc(num_points * sizeof(points[0]), userdata);
2005
         if (points == NULL) goto error;
2006
      }
2007
      num_points = 0;
2008
      n= -1;
2009
      for (i=0; i < num_verts; ++i) {
2010
         switch (vertices[i].type) {
2011
            case STBTT_vmove:
2012
               // start the next contour
2013
               if (n >= 0)
2014
                  (*contour_lengths)[n] = num_points - start;
2015
               ++n;
2016
               start = num_points;
2017
 
2018
               x = vertices[i].x, y = vertices[i].y;
2019
               stbtt__add_point(points, num_points++, x,y);
2020
               break;
2021
            case STBTT_vline:
2022
               x = vertices[i].x, y = vertices[i].y;
2023
               stbtt__add_point(points, num_points++, x, y);
2024
               break;
2025
            case STBTT_vcurve:
2026
               stbtt__tesselate_curve(points, &num_points, x,y,
2027
                                        vertices[i].cx, vertices[i].cy,
2028
                                        vertices[i].x,  vertices[i].y,
2029
                                        objspace_flatness_squared, 0);
2030
               x = vertices[i].x, y = vertices[i].y;
2031
               break;
2032
         }
2033
      }
2034
      (*contour_lengths)[n] = num_points - start;
2035
   }
2036
 
2037
   return points;
2038
error:
2039
   STBTT_free(points, userdata);
2040
   STBTT_free(*contour_lengths, userdata);
2041
   *contour_lengths = 0;
2042
   *num_contours = 0;
2043
   return NULL;
2044
}
2045
 
2046
void stbtt_Rasterize(stbtt__bitmap *result, float flatness_in_pixels, stbtt_vertex *vertices, int num_verts, float scale_x, float scale_y, float shift_x, float shift_y, int x_off, int y_off, int invert, void *userdata)
2047
{
2048
   float scale = scale_x > scale_y ? scale_y : scale_x;
2049
   int winding_count, *winding_lengths;
2050
   stbtt__point *windings = stbtt_FlattenCurves(vertices, num_verts, flatness_in_pixels / scale, &winding_lengths, &winding_count, userdata);
2051
   if (windings) {
2052
      stbtt__rasterize(result, windings, winding_lengths, winding_count, scale_x, scale_y, shift_x, shift_y, x_off, y_off, invert, userdata);
2053
      STBTT_free(winding_lengths, userdata);
2054
      STBTT_free(windings, userdata);
2055
   }
2056
}
2057
 
2058
void stbtt_FreeBitmap(unsigned char *bitmap, void *userdata)
2059
{
2060
   STBTT_free(bitmap, userdata);
2061
}
2062
 
2063
unsigned char *stbtt_GetGlyphBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int glyph, int *width, int *height, int *xoff, int *yoff)
2064
{
2065
   int ix0,iy0,ix1,iy1;
2066
   stbtt__bitmap gbm;
2067
   stbtt_vertex *vertices;
2068
   int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices);
2069
 
2070
   if (scale_x == 0) scale_x = scale_y;
2071
   if (scale_y == 0) {
2072
      if (scale_x == 0) return NULL;
2073
      scale_y = scale_x;
2074
   }
2075
 
2076
   stbtt_GetGlyphBitmapBox(info, glyph, scale_x, scale_y, &ix0,&iy0,&ix1,&iy1);
2077
 
2078
   // now we get the size
2079
   gbm.w = (ix1 - ix0);
2080
   gbm.h = (iy1 - iy0);
2081
   gbm.pixels = NULL; // in case we error
2082
 
2083
   if (width ) *width  = gbm.w;
2084
   if (height) *height = gbm.h;
2085
   if (xoff  ) *xoff   = ix0;
2086
   if (yoff  ) *yoff   = iy0;
2087
 
2088
   if (gbm.w && gbm.h) {
2089
      gbm.pixels = (unsigned char *) STBTT_malloc(gbm.w * gbm.h, info->userdata);
2090
      if (gbm.pixels) {
2091
         gbm.stride = gbm.w;
2092
 
2093
         stbtt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, shift_x, shift_y, ix0, iy0, 1, info->userdata);
2094
      }
2095
   }
2096
   STBTT_free(vertices, info->userdata);
2097
   return gbm.pixels;
2098
}
2099
 
2100
unsigned char *stbtt_GetGlyphBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int glyph, int *width, int *height, int *xoff, int *yoff)
2101
{
2102
   return stbtt_GetGlyphBitmapSubpixel(info, scale_x, scale_y, 0.0f, 0.0f, glyph, width, height, xoff, yoff);
2103
}
2104
 
2105
void stbtt_MakeGlyphBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int glyph)
2106
{
2107
   int ix0,iy0;
2108
   stbtt_vertex *vertices;
2109
   int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices);
2110
   stbtt__bitmap gbm;
2111
 
2112
   stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x, shift_y, &ix0,&iy0,0,0);
2113
   gbm.pixels = output;
2114
   gbm.w = out_w;
2115
   gbm.h = out_h;
2116
   gbm.stride = out_stride;
2117
 
2118
   if (gbm.w && gbm.h)
2119
      stbtt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, shift_x, shift_y, ix0,iy0, 1, info->userdata);
2120
 
2121
   STBTT_free(vertices, info->userdata);
2122
}
2123
 
2124
void stbtt_MakeGlyphBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int glyph)
2125
{
2126
   stbtt_MakeGlyphBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, 0.0f,0.0f, glyph);
2127
}
2128
 
2129
unsigned char *stbtt_GetCodepointBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint, int *width, int *height, int *xoff, int *yoff)
2130
{
2131
   return stbtt_GetGlyphBitmapSubpixel(info, scale_x, scale_y,shift_x,shift_y, stbtt_FindGlyphIndex(info,codepoint), width,height,xoff,yoff);
2132
}
2133
 
2134
void stbtt_MakeCodepointBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint)
2135
{
2136
   stbtt_MakeGlyphBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, shift_x, shift_y, stbtt_FindGlyphIndex(info,codepoint));
2137
}
2138
 
2139
unsigned char *stbtt_GetCodepointBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int codepoint, int *width, int *height, int *xoff, int *yoff)
2140
{
2141
   return stbtt_GetCodepointBitmapSubpixel(info, scale_x, scale_y, 0.0f,0.0f, codepoint, width,height,xoff,yoff);
2142
}
2143
 
2144
void stbtt_MakeCodepointBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int codepoint)
2145
{
2146
   stbtt_MakeCodepointBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, 0.0f,0.0f, codepoint);
2147
}
2148
 
2149
//////////////////////////////////////////////////////////////////////////////
2150
//
2151
// bitmap baking
2152
//
2153
// This is SUPER-CRAPPY packing to keep source code small
2154
 
2155
extern int stbtt_BakeFontBitmap(const unsigned char *data, int offset,  // font location (use offset=0 for plain .ttf)
2156
                                float pixel_height,                     // height of font in pixels
2157
                                unsigned char *pixels, int pw, int ph,  // bitmap to be filled in
2158
                                int first_char, int num_chars,          // characters to bake
2159
                                stbtt_bakedchar *chardata)
2160
{
2161
   float scale;
2162
   int x,y,bottom_y, i;
2163
   stbtt_fontinfo f;
2164
   stbtt_InitFont(&f, data, offset);
2165
   STBTT_memset(pixels, 0, pw*ph); // background of 0 around pixels
2166
   x=y=1;
2167
   bottom_y = 1;
2168
 
2169
   scale = stbtt_ScaleForPixelHeight(&f, pixel_height);
2170
 
2171
   for (i=0; i < num_chars; ++i) {
2172
      int advance, lsb, x0,y0,x1,y1,gw,gh;
2173
      int g = stbtt_FindGlyphIndex(&f, first_char + i);
2174
      stbtt_GetGlyphHMetrics(&f, g, &advance, &lsb);
2175
      stbtt_GetGlyphBitmapBox(&f, g, scale,scale, &x0,&y0,&x1,&y1);
2176
      gw = x1-x0;
2177
      gh = y1-y0;
2178
      if (x + gw + 1 >= pw)
2179
         y = bottom_y, x = 1; // advance to next row
2180
      if (y + gh + 1 >= ph) // check if it fits vertically AFTER potentially moving to next row
2181
         return -i;
2182
      STBTT_assert(x+gw < pw);
2183
      STBTT_assert(y+gh < ph);
2184
      stbtt_MakeGlyphBitmap(&f, pixels+x+y*pw, gw,gh,pw, scale,scale, g);
2185
      chardata[i].x0 = (stbtt_int16) x;
2186
      chardata[i].y0 = (stbtt_int16) y;
2187
      chardata[i].x1 = (stbtt_int16) (x + gw);
2188
      chardata[i].y1 = (stbtt_int16) (y + gh);
2189
      chardata[i].xadvance = scale * advance;
2190
      chardata[i].xoff     = (float) x0;
2191
      chardata[i].yoff     = (float) y0;
2192
      x = x + gw + 2;
2193
      if (y+gh+2 > bottom_y)
2194
         bottom_y = y+gh+2;
2195
   }
2196
   return bottom_y;
2197
}
2198
 
2199
void stbtt_GetBakedQuad(stbtt_bakedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int opengl_fillrule)
2200
{
2201
   float d3d_bias = opengl_fillrule ? 0 : -0.5f;
2202
   float ipw = 1.0f / pw, iph = 1.0f / ph;
2203
   stbtt_bakedchar *b = chardata + char_index;
2204
   int round_x = STBTT_ifloor((*xpos + b->xoff) + 0.5);
2205
   int round_y = STBTT_ifloor((*ypos + b->yoff) + 0.5);
2206
 
2207
   q->x0 = round_x + d3d_bias;
2208
   q->y0 = round_y + d3d_bias;
2209
   q->x1 = round_x + b->x1 - b->x0 + d3d_bias;
2210
   q->y1 = round_y + b->y1 - b->y0 + d3d_bias;
2211
 
2212
   q->s0 = b->x0 * ipw;
2213
   q->t0 = b->y0 * iph;
2214
   q->s1 = b->x1 * ipw;
2215
   q->t1 = b->y1 * iph;
2216
 
2217
   *xpos += b->xadvance;
2218
}
2219
 
2220
//////////////////////////////////////////////////////////////////////////////
2221
//
2222
// font name matching -- recommended not to use this
2223
//
2224
 
2225
// check if a utf8 string contains a prefix which is the utf16 string; if so return length of matching utf8 string
2226
static stbtt_int32 stbtt__CompareUTF8toUTF16_bigendian_prefix(const stbtt_uint8 *s1, stbtt_int32 len1, const stbtt_uint8 *s2, stbtt_int32 len2)
2227
{
2228
   stbtt_int32 i=0;
2229
 
2230
   // convert utf16 to utf8 and compare the results while converting
2231
   while (len2) {
2232
      stbtt_uint16 ch = s2[0]*256 + s2[1];
2233
      if (ch < 0x80) {
2234
         if (i >= len1) return -1;
2235
         if (s1[i++] != ch) return -1;
2236
      } else if (ch < 0x800) {
2237
         if (i+1 >= len1) return -1;
2238
         if (s1[i++] != 0xc0 + (ch >> 6)) return -1;
2239
         if (s1[i++] != 0x80 + (ch & 0x3f)) return -1;
2240
      } else if (ch >= 0xd800 && ch < 0xdc00) {
2241
         stbtt_uint32 c;
2242
         stbtt_uint16 ch2 = s2[2]*256 + s2[3];
2243
         if (i+3 >= len1) return -1;
2244
         c = ((ch - 0xd800) << 10) + (ch2 - 0xdc00) + 0x10000;
2245
         if (s1[i++] != 0xf0 + (c >> 18)) return -1;
2246
         if (s1[i++] != 0x80 + ((c >> 12) & 0x3f)) return -1;
2247
         if (s1[i++] != 0x80 + ((c >>  6) & 0x3f)) return -1;
2248
         if (s1[i++] != 0x80 + ((c      ) & 0x3f)) return -1;
2249
         s2 += 2; // plus another 2 below
2250
         len2 -= 2;
2251
      } else if (ch >= 0xdc00 && ch < 0xe000) {
2252
         return -1;
2253
      } else {
2254
         if (i+2 >= len1) return -1;
2255
         if (s1[i++] != 0xe0 + (ch >> 12)) return -1;
2256
         if (s1[i++] != 0x80 + ((ch >> 6) & 0x3f)) return -1;
2257
         if (s1[i++] != 0x80 + ((ch     ) & 0x3f)) return -1;
2258
      }
2259
      s2 += 2;
2260
      len2 -= 2;
2261
   }
2262
   return i;
2263
}
2264
 
2265
int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const char *s2, int len2)
2266
{
2267
   return len1 == stbtt__CompareUTF8toUTF16_bigendian_prefix((const stbtt_uint8*) s1, len1, (const stbtt_uint8*) s2, len2);
2268
}
2269
 
2270
// returns results in whatever encoding you request... but note that 2-byte encodings
2271
// will be BIG-ENDIAN... use stbtt_CompareUTF8toUTF16_bigendian() to compare
2272
const char *stbtt_GetFontNameString(const stbtt_fontinfo *font, int *length, int platformID, int encodingID, int languageID, int nameID)
2273
{
2274
   stbtt_int32 i,count,stringOffset;
2275
   stbtt_uint8 *fc = font->data;
2276
   stbtt_uint32 offset = font->fontstart;
2277
   stbtt_uint32 nm = stbtt__find_table(fc, offset, "name");
2278
   if (!nm) return NULL;
2279
 
2280
   count = ttUSHORT(fc+nm+2);
2281
   stringOffset = nm + ttUSHORT(fc+nm+4);
2282
   for (i=0; i < count; ++i) {
2283
      stbtt_uint32 loc = nm + 6 + 12 * i;
2284
      if (platformID == ttUSHORT(fc+loc+0) && encodingID == ttUSHORT(fc+loc+2)
2285
          && languageID == ttUSHORT(fc+loc+4) && nameID == ttUSHORT(fc+loc+6)) {
2286
         *length = ttUSHORT(fc+loc+8);
2287
         return (const char *) (fc+stringOffset+ttUSHORT(fc+loc+10));
2288
      }
2289
   }
2290
   return NULL;
2291
}
2292
 
2293
static int stbtt__matchpair(stbtt_uint8 *fc, stbtt_uint32 nm, stbtt_uint8 *name, stbtt_int32 nlen, stbtt_int32 target_id, stbtt_int32 next_id)
2294
{
2295
   stbtt_int32 i;
2296
   stbtt_int32 count = ttUSHORT(fc+nm+2);
2297
   stbtt_int32 stringOffset = nm + ttUSHORT(fc+nm+4);
2298
 
2299
   for (i=0; i < count; ++i) {
2300
      stbtt_uint32 loc = nm + 6 + 12 * i;
2301
      stbtt_int32 id = ttUSHORT(fc+loc+6);
2302
      if (id == target_id) {
2303
         // find the encoding
2304
         stbtt_int32 platform = ttUSHORT(fc+loc+0), encoding = ttUSHORT(fc+loc+2), language = ttUSHORT(fc+loc+4);
2305
 
2306
         // is this a Unicode encoding?
2307
         if (platform == 0 || (platform == 3 && encoding == 1) || (platform == 3 && encoding == 10)) {
2308
            stbtt_int32 slen = ttUSHORT(fc+loc+8), off = ttUSHORT(fc+loc+10);
2309
 
2310
            // check if there's a prefix match
2311
            stbtt_int32 matchlen = stbtt__CompareUTF8toUTF16_bigendian_prefix(name, nlen, fc+stringOffset+off,slen);
2312
            if (matchlen >= 0) {
2313
               // check for target_id+1 immediately following, with same encoding & language
2314
               if (i+1 < count && ttUSHORT(fc+loc+12+6) == next_id && ttUSHORT(fc+loc+12) == platform && ttUSHORT(fc+loc+12+2) == encoding && ttUSHORT(fc+loc+12+4) == language) {
2315
                  stbtt_int32 slen = ttUSHORT(fc+loc+12+8), off = ttUSHORT(fc+loc+12+10);
2316
                  if (slen == 0) {
2317
                     if (matchlen == nlen)
2318
                        return 1;
2319
                  } else if (matchlen < nlen && name[matchlen] == ' ') {
2320
                     ++matchlen;
2321
                     if (stbtt_CompareUTF8toUTF16_bigendian((char*) (name+matchlen), nlen-matchlen, (char*)(fc+stringOffset+off),slen))
2322
                        return 1;
2323
                  }
2324
               } else {
2325
                  // if nothing immediately following
2326
                  if (matchlen == nlen)
2327
                     return 1;
2328
               }
2329
            }
2330
         }
2331
 
2332
         // @TODO handle other encodings
2333
      }
2334
   }
2335
   return 0;
2336
}
2337
 
2338
static int stbtt__matches(stbtt_uint8 *fc, stbtt_uint32 offset, stbtt_uint8 *name, stbtt_int32 flags)
2339
{
2340
   stbtt_int32 nlen = (stbtt_int32) STBTT_strlen((char *) name);
2341
   stbtt_uint32 nm,hd;
2342
   if (!stbtt__isfont(fc+offset)) return 0;
2343
 
2344
   // check italics/bold/underline flags in macStyle...
2345
   if (flags) {
2346
      hd = stbtt__find_table(fc, offset, "head");
2347
      if ((ttUSHORT(fc+hd+44) & 7) != (flags & 7)) return 0;
2348
   }
2349
 
2350
   nm = stbtt__find_table(fc, offset, "name");
2351
   if (!nm) return 0;
2352
 
2353
   if (flags) {
2354
      // if we checked the macStyle flags, then just check the family and ignore the subfamily
2355
      if (stbtt__matchpair(fc, nm, name, nlen, 16, -1))  return 1;
2356
      if (stbtt__matchpair(fc, nm, name, nlen,  1, -1))  return 1;
2357
      if (stbtt__matchpair(fc, nm, name, nlen,  3, -1))  return 1;
2358
   } else {
2359
      if (stbtt__matchpair(fc, nm, name, nlen, 16, 17))  return 1;
2360
      if (stbtt__matchpair(fc, nm, name, nlen,  1,  2))  return 1;
2361
      if (stbtt__matchpair(fc, nm, name, nlen,  3, -1))  return 1;
2362
   }
2363
 
2364
   return 0;
2365
}
2366
 
2367
int stbtt_FindMatchingFont(const unsigned char *font_collection, const char *name_utf8, stbtt_int32 flags)
2368
{
2369
   stbtt_int32 i;
2370
   for (i=0;;++i) {
2371
      stbtt_int32 off = stbtt_GetFontOffsetForIndex(font_collection, i);
2372
      if (off < 0) return off;
2373
      if (stbtt__matches((stbtt_uint8 *) font_collection, off, (stbtt_uint8*) name_utf8, flags))
2374
         return off;
2375
   }
2376
}
2377
 
2378
#endif // STB_TRUETYPE_IMPLEMENTATION