gosu 0.14.4 → 0.15.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +1 -0
  3. data/COPYING +1 -1
  4. data/Gosu/Buttons.hpp +1 -0
  5. data/Gosu/Channel.h +25 -0
  6. data/Gosu/Color.h +38 -0
  7. data/Gosu/Font.h +36 -0
  8. data/Gosu/Gosu.h +79 -0
  9. data/Gosu/Image.h +54 -0
  10. data/Gosu/Sample.h +19 -0
  11. data/Gosu/Song.h +24 -0
  12. data/Gosu/TextInput.h +30 -0
  13. data/Gosu/Version.hpp +2 -2
  14. data/Gosu/Window.h +61 -0
  15. data/Gosu/Window.hpp +3 -2
  16. data/README.md +1 -1
  17. data/ext/gosu/extconf.rb +3 -0
  18. data/lib/gosu/compat.rb +12 -7
  19. data/lib/gosu/patches.rb +8 -2
  20. data/lib/gosu/swig_patches.rb +20 -9
  21. data/rdoc/gosu.rb +28 -7
  22. data/src/ChannelWrapper.cpp +50 -0
  23. data/src/ColorWrapper.cpp +126 -0
  24. data/src/Constants.cpp +287 -0
  25. data/src/Font.cpp +1 -0
  26. data/src/FontWrapper.cpp +74 -0
  27. data/src/GosuWrapper.cpp +232 -0
  28. data/src/Graphics.cpp +4 -1
  29. data/src/GraphicsImpl.hpp +0 -1
  30. data/src/ImageWrapper.cpp +168 -0
  31. data/src/LargeImageData.cpp +1 -0
  32. data/src/MarkupParser.cpp +11 -3
  33. data/src/RubyGosu.cxx +186 -121
  34. data/src/RubyGosu.h +2 -2
  35. data/src/SampleWrapper.cpp +30 -0
  36. data/src/SongWrapper.cpp +52 -0
  37. data/src/TexChunk.cpp +29 -19
  38. data/src/Text.cpp +2 -0
  39. data/src/TextBuilder.cpp +3 -3
  40. data/src/TextInputWrapper.cpp +101 -0
  41. data/src/TrueTypeFont.cpp +1 -0
  42. data/src/Window.cpp +62 -28
  43. data/src/WindowUIKit.cpp +8 -4
  44. data/src/WindowWrapper.cpp +289 -0
  45. data/src/stb_image.h +153 -56
  46. data/src/stb_image_write.h +111 -60
  47. data/src/stb_truetype.h +74 -39
  48. data/src/stb_vorbis.c +55 -15
  49. data/src/utf8proc.c +47 -29
  50. data/src/utf8proc.h +46 -24
  51. data/src/utf8proc_data.h +10043 -9609
  52. metadata +23 -4
@@ -1,4 +1,4 @@
1
- /* stb_image_write - v1.09 - public domain - http://nothings.org/stb/stb_image_write.h
1
+ /* stb_image_write - v1.13 - public domain - http://nothings.org/stb
2
2
  writes out PNG/BMP/TGA/JPEG/HDR images to C stdio - Sean Barrett 2010-2015
3
3
  no warranty implied; use at your own risk
4
4
 
@@ -10,15 +10,9 @@
10
10
 
11
11
  Will probably not work correctly with strict-aliasing optimizations.
12
12
 
13
- If using a modern Microsoft Compiler, non-safe versions of CRT calls may cause
14
- compilation warnings or even errors. To avoid this, also before #including,
15
-
16
- #define STBI_MSC_SECURE_CRT
17
-
18
13
  ABOUT:
19
14
 
20
- This header file is a library for writing images to C stdio. It could be
21
- adapted to write to memory or a general streaming interface; let me know.
15
+ This header file is a library for writing images to C stdio or a callback.
22
16
 
23
17
  The PNG output is not optimal; it is 20-50% larger than the file
24
18
  written by a decent optimizing implementation; though providing a custom
@@ -38,6 +32,14 @@ BUILDING:
38
32
  The returned data will be freed with STBIW_FREE() (free() by default),
39
33
  so it must be heap allocated with STBIW_MALLOC() (malloc() by default),
40
34
 
35
+ UNICODE:
36
+
37
+ If compiling for Windows and you wish to use Unicode filenames, compile
38
+ with
39
+ #define STBIW_WINDOWS_UTF8
40
+ and pass utf8-encoded filenames. Call stbiw_convert_wchar_to_utf8 to convert
41
+ Windows wchar_t filenames to utf8.
42
+
41
43
  USAGE:
42
44
 
43
45
  There are five functions, one for each image file format:
@@ -148,6 +150,8 @@ LICENSE
148
150
  #ifndef INCLUDE_STB_IMAGE_WRITE_H
149
151
  #define INCLUDE_STB_IMAGE_WRITE_H
150
152
 
153
+ #include <stdlib.h>
154
+
151
155
  // if STB_IMAGE_WRITE_STATIC causes problems, try defining STBIWDEF to 'inline' or 'static inline'
152
156
  #ifndef STBIWDEF
153
157
  #ifdef STB_IMAGE_WRITE_STATIC
@@ -173,6 +177,10 @@ STBIWDEF int stbi_write_bmp(char const *filename, int w, int h, int comp, const
173
177
  STBIWDEF int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data);
174
178
  STBIWDEF int stbi_write_hdr(char const *filename, int w, int h, int comp, const float *data);
175
179
  STBIWDEF int stbi_write_jpg(char const *filename, int x, int y, int comp, const void *data, int quality);
180
+
181
+ #ifdef STBI_WINDOWS_UTF8
182
+ STBIWDEF int stbiw_convert_wchar_to_utf8(char *buffer, size_t bufferlen, const wchar_t* input);
183
+ #endif
176
184
  #endif
177
185
 
178
186
  typedef void stbi_write_func(void *context, void *data, int size);
@@ -275,15 +283,52 @@ static void stbi__stdio_write(void *context, void *data, int size)
275
283
  fwrite(data,1,size,(FILE*) context);
276
284
  }
277
285
 
278
- static int stbi__start_write_file(stbi__write_context *s, const char *filename)
286
+ #if defined(_MSC_VER) && defined(STBI_WINDOWS_UTF8)
287
+ #ifdef __cplusplus
288
+ #define STBIW_EXTERN extern "C"
289
+ #else
290
+ #define STBIW_EXTERN extern
291
+ #endif
292
+ STBIW_EXTERN __declspec(dllimport) int __stdcall MultiByteToWideChar(unsigned int cp, unsigned long flags, const char *str, int cbmb, wchar_t *widestr, int cchwide);
293
+ STBIW_EXTERN __declspec(dllimport) int __stdcall WideCharToMultiByte(unsigned int cp, unsigned long flags, const wchar_t *widestr, int cchwide, char *str, int cbmb, const char *defchar, int *used_default);
294
+
295
+ STBIWDEF int stbiw_convert_wchar_to_utf8(char *buffer, size_t bufferlen, const wchar_t* input)
296
+ {
297
+ return WideCharToMultiByte(65001 /* UTF8 */, 0, input, -1, buffer, (int) bufferlen, NULL, NULL);
298
+ }
299
+ #endif
300
+
301
+ static FILE *stbiw__fopen(char const *filename, char const *mode)
279
302
  {
280
303
  FILE *f;
281
- #ifdef STBI_MSC_SECURE_CRT
282
- if (fopen_s(&f, filename, "wb"))
283
- f = NULL;
304
+ #if defined(_MSC_VER) && defined(STBI_WINDOWS_UTF8)
305
+ wchar_t wMode[64];
306
+ wchar_t wFilename[1024];
307
+ if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, filename, -1, wFilename, sizeof(wFilename)))
308
+ return 0;
309
+
310
+ if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, mode, -1, wMode, sizeof(wMode)))
311
+ return 0;
312
+
313
+ #if _MSC_VER >= 1400
314
+ if (0 != _wfopen_s(&f, wFilename, wMode))
315
+ f = 0;
316
+ #else
317
+ f = _wfopen(wFilename, wMode);
318
+ #endif
319
+
320
+ #elif defined(_MSC_VER) && _MSC_VER >= 1400
321
+ if (0 != fopen_s(&f, filename, mode))
322
+ f=0;
284
323
  #else
285
- f = fopen(filename, "wb");
324
+ f = fopen(filename, mode);
286
325
  #endif
326
+ return f;
327
+ }
328
+
329
+ static int stbi__start_write_file(stbi__write_context *s, const char *filename)
330
+ {
331
+ FILE *f = stbiw__fopen(filename, "wb");
287
332
  stbi__start_write_callbacks(s, stbi__stdio_write, (void *) f);
288
333
  return f != NULL;
289
334
  }
@@ -343,7 +388,7 @@ static void stbiw__putc(stbi__write_context *s, unsigned char c)
343
388
  static void stbiw__write3(stbi__write_context *s, unsigned char a, unsigned char b, unsigned char c)
344
389
  {
345
390
  unsigned char arr[3];
346
- arr[0] = a, arr[1] = b, arr[2] = c;
391
+ arr[0] = a; arr[1] = b; arr[2] = c;
347
392
  s->func(s->context, arr, 3);
348
393
  }
349
394
 
@@ -391,10 +436,11 @@ static void stbiw__write_pixels(stbi__write_context *s, int rgb_dir, int vdir, i
391
436
  if (stbi__flip_vertically_on_write)
392
437
  vdir *= -1;
393
438
 
394
- if (vdir < 0)
395
- j_end = -1, j = y-1;
396
- else
397
- j_end = y, j = 0;
439
+ if (vdir < 0) {
440
+ j_end = -1; j = y-1;
441
+ } else {
442
+ j_end = y; j = 0;
443
+ }
398
444
 
399
445
  for (; j != j_end; j += vdir) {
400
446
  for (i=0; i < x; ++i) {
@@ -552,7 +598,7 @@ STBIWDEF int stbi_write_tga(char const *filename, int x, int y, int comp, const
552
598
 
553
599
  #define stbiw__max(a, b) ((a) > (b) ? (a) : (b))
554
600
 
555
- void stbiw__linear_to_rgbe(unsigned char *rgbe, float *linear)
601
+ static void stbiw__linear_to_rgbe(unsigned char *rgbe, float *linear)
556
602
  {
557
603
  int exponent;
558
604
  float maxcomp = stbiw__max(linear[0], stbiw__max(linear[1], linear[2]));
@@ -569,7 +615,7 @@ void stbiw__linear_to_rgbe(unsigned char *rgbe, float *linear)
569
615
  }
570
616
  }
571
617
 
572
- void stbiw__write_run_data(stbi__write_context *s, int length, unsigned char databyte)
618
+ static void stbiw__write_run_data(stbi__write_context *s, int length, unsigned char databyte)
573
619
  {
574
620
  unsigned char lengthbyte = STBIW_UCHAR(length+128);
575
621
  STBIW_ASSERT(length+128 <= 255);
@@ -577,7 +623,7 @@ void stbiw__write_run_data(stbi__write_context *s, int length, unsigned char dat
577
623
  s->func(s->context, &databyte, 1);
578
624
  }
579
625
 
580
- void stbiw__write_dump_data(stbi__write_context *s, int length, unsigned char *data)
626
+ static void stbiw__write_dump_data(stbi__write_context *s, int length, unsigned char *data)
581
627
  {
582
628
  unsigned char lengthbyte = STBIW_UCHAR(length);
583
629
  STBIW_ASSERT(length <= 128); // inconsistent with spec but consistent with official code
@@ -585,7 +631,7 @@ void stbiw__write_dump_data(stbi__write_context *s, int length, unsigned char *d
585
631
  s->func(s->context, data, length);
586
632
  }
587
633
 
588
- void stbiw__write_hdr_scanline(stbi__write_context *s, int width, int ncomp, unsigned char *scratch, float *scanline)
634
+ static void stbiw__write_hdr_scanline(stbi__write_context *s, int width, int ncomp, unsigned char *scratch, float *scanline)
589
635
  {
590
636
  unsigned char scanlineheader[4] = { 2, 2, 0, 0 };
591
637
  unsigned char rgbe[4];
@@ -686,15 +732,15 @@ static int stbi_write_hdr_core(stbi__write_context *s, int x, int y, int comp, f
686
732
  char header[] = "#?RADIANCE\n# Written by stb_image_write.h\nFORMAT=32-bit_rle_rgbe\n";
687
733
  s->func(s->context, header, sizeof(header)-1);
688
734
 
689
- #ifdef STBI_MSC_SECURE_CRT
690
- len = sprintf_s(buffer, "EXPOSURE= 1.0000000000000\n\n-Y %d +X %d\n", y, x);
735
+ #ifdef __STDC_WANT_SECURE_LIB__
736
+ len = sprintf_s(buffer, sizeof(buffer), "EXPOSURE= 1.0000000000000\n\n-Y %d +X %d\n", y, x);
691
737
  #else
692
738
  len = sprintf(buffer, "EXPOSURE= 1.0000000000000\n\n-Y %d +X %d\n", y, x);
693
739
  #endif
694
740
  s->func(s->context, buffer, len);
695
741
 
696
742
  for(i=0; i < y; i++)
697
- stbiw__write_hdr_scanline(s, x, comp, scratch, data + comp*x*(stbi__flip_vertically_on_write ? y-1-i : i)*x);
743
+ stbiw__write_hdr_scanline(s, x, comp, scratch, data + comp*x*(stbi__flip_vertically_on_write ? y-1-i : i));
698
744
  STBIW_FREE(scratch);
699
745
  return 1;
700
746
  }
@@ -809,7 +855,7 @@ static unsigned int stbiw__zhash(unsigned char *data)
809
855
 
810
856
  #endif // STBIW_ZLIB_COMPRESS
811
857
 
812
- unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_len, int quality)
858
+ STBIWDEF unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_len, int quality)
813
859
  {
814
860
  #ifdef STBIW_ZLIB_COMPRESS
815
861
  // user provided a zlib compress implementation, use that
@@ -822,7 +868,7 @@ unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_l
822
868
  unsigned int bitbuf=0;
823
869
  int i,j, bitcount=0;
824
870
  unsigned char *out = NULL;
825
- unsigned char ***hash_table = (unsigned char***) STBIW_MALLOC(stbiw__ZHASH * sizeof(char**));
871
+ unsigned char ***hash_table = (unsigned char***) STBIW_MALLOC(stbiw__ZHASH * sizeof(unsigned char**));
826
872
  if (hash_table == NULL)
827
873
  return NULL;
828
874
  if (quality < 5) quality = 5;
@@ -845,7 +891,7 @@ unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_l
845
891
  for (j=0; j < n; ++j) {
846
892
  if (hlist[j]-data > i-32768) { // if entry lies within window
847
893
  int d = stbiw__zlib_countm(hlist[j], data+i, data_len-i);
848
- if (d >= best) best=d,bestloc=hlist[j];
894
+ if (d >= best) { best=d; bestloc=hlist[j]; }
849
895
  }
850
896
  }
851
897
  // when hash table entry is too long, delete half the entries
@@ -904,8 +950,8 @@ unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_l
904
950
  int blocklen = (int) (data_len % 5552);
905
951
  j=0;
906
952
  while (j < data_len) {
907
- for (i=0; i < blocklen; ++i) s1 += data[j+i], s2 += s1;
908
- s1 %= 65521, s2 %= 65521;
953
+ for (i=0; i < blocklen; ++i) { s1 += data[j+i]; s2 += s1; }
954
+ s1 %= 65521; s2 %= 65521;
909
955
  j += blocklen;
910
956
  blocklen = 5552;
911
957
  }
@@ -923,6 +969,9 @@ unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_l
923
969
 
924
970
  static unsigned int stbiw__crc32(unsigned char *buffer, int len)
925
971
  {
972
+ #ifdef STBIW_CRC32
973
+ return STBIW_CRC32(buffer, len);
974
+ #else
926
975
  static unsigned int crc_table[256] =
927
976
  {
928
977
  0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
@@ -964,6 +1013,7 @@ static unsigned int stbiw__crc32(unsigned char *buffer, int len)
964
1013
  for (i=0; i < len; ++i)
965
1014
  crc = (crc >> 8) ^ crc_table[buffer[i] ^ (crc & 0xff)];
966
1015
  return ~crc;
1016
+ #endif
967
1017
  }
968
1018
 
969
1019
  #define stbiw__wpng4(o,a,b,c,d) ((o)[0]=STBIW_UCHAR(a),(o)[1]=STBIW_UCHAR(b),(o)[2]=STBIW_UCHAR(c),(o)[3]=STBIW_UCHAR(d),(o)+=4)
@@ -994,9 +1044,15 @@ static void stbiw__encode_png_line(unsigned char *pixels, int stride_bytes, int
994
1044
  int type = mymap[filter_type];
995
1045
  unsigned char *z = pixels + stride_bytes * (stbi__flip_vertically_on_write ? height-1-y : y);
996
1046
  int signed_stride = stbi__flip_vertically_on_write ? -stride_bytes : stride_bytes;
1047
+
1048
+ if (type==0) {
1049
+ memcpy(line_buffer, z, width*n);
1050
+ return;
1051
+ }
1052
+
1053
+ // first loop isn't optimized since it's just one pixel
997
1054
  for (i = 0; i < n; ++i) {
998
1055
  switch (type) {
999
- case 0: line_buffer[i] = z[i]; break;
1000
1056
  case 1: line_buffer[i] = z[i]; break;
1001
1057
  case 2: line_buffer[i] = z[i] - z[i-signed_stride]; break;
1002
1058
  case 3: line_buffer[i] = z[i] - (z[i-signed_stride]>>1); break;
@@ -1005,20 +1061,17 @@ static void stbiw__encode_png_line(unsigned char *pixels, int stride_bytes, int
1005
1061
  case 6: line_buffer[i] = z[i]; break;
1006
1062
  }
1007
1063
  }
1008
- for (i=n; i < width*n; ++i) {
1009
- switch (type) {
1010
- case 0: line_buffer[i] = z[i]; break;
1011
- case 1: line_buffer[i] = z[i] - z[i-n]; break;
1012
- case 2: line_buffer[i] = z[i] - z[i-signed_stride]; break;
1013
- case 3: line_buffer[i] = z[i] - ((z[i-n] + z[i-signed_stride])>>1); break;
1014
- case 4: line_buffer[i] = z[i] - stbiw__paeth(z[i-n], z[i-signed_stride], z[i-signed_stride-n]); break;
1015
- case 5: line_buffer[i] = z[i] - (z[i-n]>>1); break;
1016
- case 6: line_buffer[i] = z[i] - stbiw__paeth(z[i-n], 0,0); break;
1017
- }
1064
+ switch (type) {
1065
+ case 1: for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - z[i-n]; break;
1066
+ case 2: for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - z[i-signed_stride]; break;
1067
+ case 3: for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - ((z[i-n] + z[i-signed_stride])>>1); break;
1068
+ case 4: for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - stbiw__paeth(z[i-n], z[i-signed_stride], z[i-signed_stride-n]); break;
1069
+ case 5: for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - (z[i-n]>>1); break;
1070
+ case 6: for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - stbiw__paeth(z[i-n], 0,0); break;
1018
1071
  }
1019
1072
  }
1020
1073
 
1021
- unsigned char *stbi_write_png_to_mem(unsigned char *pixels, int stride_bytes, int x, int y, int n, int *out_len)
1074
+ STBIWDEF unsigned char *stbi_write_png_to_mem(const unsigned char *pixels, int stride_bytes, int x, int y, int n, int *out_len)
1022
1075
  {
1023
1076
  int force_filter = stbi_write_force_png_filter;
1024
1077
  int ctype[5] = { -1, 0, 4, 2, 6 };
@@ -1040,11 +1093,11 @@ unsigned char *stbi_write_png_to_mem(unsigned char *pixels, int stride_bytes, in
1040
1093
  int filter_type;
1041
1094
  if (force_filter > -1) {
1042
1095
  filter_type = force_filter;
1043
- stbiw__encode_png_line(pixels, stride_bytes, x, y, j, n, force_filter, line_buffer);
1096
+ stbiw__encode_png_line((unsigned char*)(pixels), stride_bytes, x, y, j, n, force_filter, line_buffer);
1044
1097
  } else { // Estimate the best filter by running through all of them:
1045
1098
  int best_filter = 0, best_filter_val = 0x7fffffff, est, i;
1046
1099
  for (filter_type = 0; filter_type < 5; filter_type++) {
1047
- stbiw__encode_png_line(pixels, stride_bytes, x, y, j, n, filter_type, line_buffer);
1100
+ stbiw__encode_png_line((unsigned char*)(pixels), stride_bytes, x, y, j, n, filter_type, line_buffer);
1048
1101
 
1049
1102
  // Estimate the entropy of the line using this filter; the less, the better.
1050
1103
  est = 0;
@@ -1057,7 +1110,7 @@ unsigned char *stbi_write_png_to_mem(unsigned char *pixels, int stride_bytes, in
1057
1110
  }
1058
1111
  }
1059
1112
  if (filter_type != best_filter) { // If the last iteration already got us the best filter, don't redo it
1060
- stbiw__encode_png_line(pixels, stride_bytes, x, y, j, n, best_filter, line_buffer);
1113
+ stbiw__encode_png_line((unsigned char*)(pixels), stride_bytes, x, y, j, n, best_filter, line_buffer);
1061
1114
  filter_type = best_filter;
1062
1115
  }
1063
1116
  }
@@ -1109,14 +1162,10 @@ STBIWDEF int stbi_write_png(char const *filename, int x, int y, int comp, const
1109
1162
  {
1110
1163
  FILE *f;
1111
1164
  int len;
1112
- unsigned char *png = stbi_write_png_to_mem((unsigned char *) data, stride_bytes, x, y, comp, &len);
1165
+ unsigned char *png = stbi_write_png_to_mem((const unsigned char *) data, stride_bytes, x, y, comp, &len);
1113
1166
  if (png == NULL) return 0;
1114
- #ifdef STBI_MSC_SECURE_CRT
1115
- if (fopen_s(&f, filename, "wb"))
1116
- f = NULL;
1117
- #else
1118
- f = fopen(filename, "wb");
1119
- #endif
1167
+
1168
+ f = stbiw__fopen(filename, "wb");
1120
1169
  if (!f) { STBIW_FREE(png); return 0; }
1121
1170
  fwrite(png, 1, len, f);
1122
1171
  fclose(f);
@@ -1128,7 +1177,7 @@ STBIWDEF int stbi_write_png(char const *filename, int x, int y, int comp, const
1128
1177
  STBIWDEF int stbi_write_png_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int stride_bytes)
1129
1178
  {
1130
1179
  int len;
1131
- unsigned char *png = stbi_write_png_to_mem((unsigned char *) data, stride_bytes, x, y, comp, &len);
1180
+ unsigned char *png = stbi_write_png_to_mem((const unsigned char *) data, stride_bytes, x, y, comp, &len);
1132
1181
  if (png == NULL) return 0;
1133
1182
  func(context, png, len);
1134
1183
  STBIW_FREE(png);
@@ -1423,15 +1472,13 @@ static int stbi_write_jpg_core(stbi__write_context *s, int width, int height, in
1423
1472
  for(x = 0; x < width; x += 8) {
1424
1473
  float YDU[64], UDU[64], VDU[64];
1425
1474
  for(row = y, pos = 0; row < y+8; ++row) {
1475
+ // row >= height => use last input row
1476
+ int clamped_row = (row < height) ? row : height - 1;
1477
+ int base_p = (stbi__flip_vertically_on_write ? (height-1-clamped_row) : clamped_row)*width*comp;
1426
1478
  for(col = x; col < x+8; ++col, ++pos) {
1427
- int p = (stbi__flip_vertically_on_write ? height-1-row : row)*width*comp + col*comp;
1428
1479
  float r, g, b;
1429
- if(row >= height) {
1430
- p -= width*comp*(row+1 - height);
1431
- }
1432
- if(col >= width) {
1433
- p -= comp*(col+1 - width);
1434
- }
1480
+ // if col >= width => use pixel from last input column
1481
+ int p = base_p + ((col < width) ? col : (width-1))*comp;
1435
1482
 
1436
1483
  r = imageData[p+0];
1437
1484
  g = imageData[p+ofsG];
@@ -1483,6 +1530,10 @@ STBIWDEF int stbi_write_jpg(char const *filename, int x, int y, int comp, const
1483
1530
  #endif // STB_IMAGE_WRITE_IMPLEMENTATION
1484
1531
 
1485
1532
  /* Revision history
1533
+ 1.11 (2019-08-11)
1534
+
1535
+ 1.10 (2019-02-07)
1536
+ support utf8 filenames in Windows; fix warnings and platform ifdefs
1486
1537
  1.09 (2018-02-11)
1487
1538
  fix typo in zlib quality API, improve STB_I_W_STATIC in C++
1488
1539
  1.08 (2018-01-29)
@@ -1,5 +1,5 @@
1
- // stb_truetype.h - v1.19 - public domain
2
- // authored from 2009-2016 by Sean Barrett / RAD Game Tools
1
+ // stb_truetype.h - v1.22 - public domain
2
+ // authored from 2009-2019 by Sean Barrett / RAD Game Tools
3
3
  //
4
4
  // This library processes TrueType files:
5
5
  // parse files
@@ -46,9 +46,13 @@
46
46
  // Rob Loach Cort Stratton
47
47
  // Kenney Phillis Jr. github:oyvindjam
48
48
  // Brian Costabile github:vassvik
49
+ // Ken Voskuil (kaesve) Ryan Griege
49
50
  //
50
51
  // VERSION HISTORY
51
52
  //
53
+ // 1.22 (2019-08-11) minimize missing-glyph duplication; fix kerning if both 'GPOS' and 'kern' are defined
54
+ // 1.21 (2019-02-25) fix warning
55
+ // 1.20 (2019-02-07) PackFontRange skips missing codepoints; GetScaleFontVMetrics()
52
56
  // 1.19 (2018-02-11) GPOS kerning, STBTT_fmod
53
57
  // 1.18 (2018-01-29) add missing function
54
58
  // 1.17 (2017-07-23) make more arguments const; doc fix
@@ -75,7 +79,7 @@
75
79
  //
76
80
  // USAGE
77
81
  //
78
- // Include this file in whatever places neeed to refer to it. In ONE C/C++
82
+ // Include this file in whatever places need to refer to it. In ONE C/C++
79
83
  // file, write:
80
84
  // #define STB_TRUETYPE_IMPLEMENTATION
81
85
  // before the #include of this file. This expands out the actual
@@ -242,19 +246,6 @@
242
246
  // recommend it.
243
247
  //
244
248
  //
245
- // SOURCE STATISTICS (based on v0.6c, 2050 LOC)
246
- //
247
- // Documentation & header file 520 LOC \___ 660 LOC documentation
248
- // Sample code 140 LOC /
249
- // Truetype parsing 620 LOC ---- 620 LOC TrueType
250
- // Software rasterization 240 LOC \ .
251
- // Curve tesselation 120 LOC \__ 550 LOC Bitmap creation
252
- // Bitmap management 100 LOC /
253
- // Baked bitmap interface 70 LOC /
254
- // Font name matching & access 150 LOC ---- 150
255
- // C runtime library abstraction 60 LOC ---- 60
256
- //
257
- //
258
249
  // PERFORMANCE MEASUREMENTS FOR 1.06:
259
250
  //
260
251
  // 32-bit 64-bit
@@ -556,6 +547,8 @@ STBTT_DEF void stbtt_GetBakedQuad(const stbtt_bakedchar *chardata, int pw, int p
556
547
  //
557
548
  // It's inefficient; you might want to c&p it and optimize it.
558
549
 
550
+ STBTT_DEF void stbtt_GetScaledFontVMetrics(const unsigned char *fontdata, int index, float size, float *ascent, float *descent, float *lineGap);
551
+ // Query the font vertical metrics without having to create a font first.
559
552
 
560
553
 
561
554
  //////////////////////////////////////////////////////////////////////////////
@@ -641,6 +634,12 @@ STBTT_DEF void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h
641
634
  // To use with PackFontRangesGather etc., you must set it before calls
642
635
  // call to PackFontRangesGatherRects.
643
636
 
637
+ STBTT_DEF void stbtt_PackSetSkipMissingCodepoints(stbtt_pack_context *spc, int skip);
638
+ // If skip != 0, this tells stb_truetype to skip any codepoints for which
639
+ // there is no corresponding glyph. If skip=0, which is the default, then
640
+ // codepoints without a glyph recived the font's "missing character" glyph,
641
+ // typically an empty box by convention.
642
+
644
643
  STBTT_DEF void stbtt_GetPackedQuad(const stbtt_packedchar *chardata, int pw, int ph, // same data as above
645
644
  int char_index, // character to display
646
645
  float *xpos, float *ypos, // pointers to current position in screen pixel space
@@ -669,6 +668,7 @@ struct stbtt_pack_context {
669
668
  int height;
670
669
  int stride_in_bytes;
671
670
  int padding;
671
+ int skip_missing;
672
672
  unsigned int h_oversample, v_oversample;
673
673
  unsigned char *pixels;
674
674
  void *nodes;
@@ -694,7 +694,7 @@ STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index);
694
694
  // file will only define one font and it always be at offset 0, so it will
695
695
  // return '0' for index 0, and -1 for all other indices.
696
696
 
697
- // The following structure is defined publically so you can declare one on
697
+ // The following structure is defined publicly so you can declare one on
698
698
  // the stack or as a global or etc, but you should treat it as opaque.
699
699
  struct stbtt_fontinfo
700
700
  {
@@ -733,6 +733,7 @@ STBTT_DEF int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codep
733
733
  // and you want a speed-up, call this function with the character you're
734
734
  // going to process, then use glyph-based functions instead of the
735
735
  // codepoint-based functions.
736
+ // Returns 0 if the character codepoint is not defined in the font.
736
737
 
737
738
 
738
739
  //////////////////////////////////////////////////////////////////////////////
@@ -820,7 +821,7 @@ STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, s
820
821
  // returns # of vertices and fills *vertices with the pointer to them
821
822
  // these are expressed in "unscaled" coordinates
822
823
  //
823
- // The shape is a series of countours. Each one starts with
824
+ // The shape is a series of contours. Each one starts with
824
825
  // a STBTT_moveto, then consists of a series of mixed
825
826
  // STBTT_lineto and STBTT_curveto segments. A lineto
826
827
  // draws a line from previous endpoint to its x,y; a curveto
@@ -916,7 +917,7 @@ STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float sc
916
917
  STBTT_DEF unsigned char * stbtt_GetCodepointSDF(const stbtt_fontinfo *info, float scale, int codepoint, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff);
917
918
  // These functions compute a discretized SDF field for a single character, suitable for storing
918
919
  // in a single-channel texture, sampling with bilinear filtering, and testing against
919
- // larger than some threshhold to produce scalable fonts.
920
+ // larger than some threshold to produce scalable fonts.
920
921
  // info -- the font
921
922
  // scale -- controls the size of the resulting SDF bitmap, same as it would be creating a regular bitmap
922
923
  // glyph/codepoint -- the character to generate the SDF for
@@ -2463,6 +2464,7 @@ static stbtt_int32 stbtt__GetGlyphGPOSInfoAdvance(const stbtt_fontinfo *info, i
2463
2464
  if (valueFormat2 != 0) return 0;
2464
2465
 
2465
2466
  STBTT_assert(coverageIndex < pairSetCount);
2467
+ STBTT__NOTUSED(pairSetCount);
2466
2468
 
2467
2469
  needle=glyph2;
2468
2470
  r=pairValueCount-1;
@@ -2540,8 +2542,7 @@ STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int g1, int
2540
2542
 
2541
2543
  if (info->gpos)
2542
2544
  xAdvance += stbtt__GetGlyphGPOSInfoAdvance(info, g1, g2);
2543
-
2544
- if (info->kern)
2545
+ else if (info->kern)
2545
2546
  xAdvance += stbtt__GetGlyphKernInfoAdvance(info, g1, g2);
2546
2547
 
2547
2548
  return xAdvance;
@@ -3160,7 +3161,13 @@ static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e,
3160
3161
  if (e->y0 != e->y1) {
3161
3162
  stbtt__active_edge *z = stbtt__new_active(&hh, e, off_x, scan_y_top, userdata);
3162
3163
  if (z != NULL) {
3163
- STBTT_assert(z->ey >= scan_y_top);
3164
+ if (j == 0 && off_y != 0) {
3165
+ if (z->ey < scan_y_top) {
3166
+ // this can happen due to subpixel positioning and some kind of fp rounding error i think
3167
+ z->ey = scan_y_top;
3168
+ }
3169
+ }
3170
+ STBTT_assert(z->ey >= scan_y_top); // if we get really unlucky a tiny bit of an edge can be out of bounds
3164
3171
  // insert at front
3165
3172
  z->next = active;
3166
3173
  active = z;
@@ -3229,7 +3236,7 @@ static void stbtt__sort_edges_ins_sort(stbtt__edge *p, int n)
3229
3236
 
3230
3237
  static void stbtt__sort_edges_quicksort(stbtt__edge *p, int n)
3231
3238
  {
3232
- /* threshhold for transitioning to insertion sort */
3239
+ /* threshold for transitioning to insertion sort */
3233
3240
  while (n > 12) {
3234
3241
  stbtt__edge t;
3235
3242
  int c01,c12,c,m,i,j;
@@ -3364,7 +3371,7 @@ static void stbtt__add_point(stbtt__point *points, int n, float x, float y)
3364
3371
  points[n].y = y;
3365
3372
  }
3366
3373
 
3367
- // tesselate until threshhold p is happy... @TODO warped to compensate for non-linear stretching
3374
+ // tessellate until threshold p is happy... @TODO warped to compensate for non-linear stretching
3368
3375
  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)
3369
3376
  {
3370
3377
  // midpoint
@@ -3789,6 +3796,7 @@ STBTT_DEF int stbtt_PackBegin(stbtt_pack_context *spc, unsigned char *pixels, in
3789
3796
  spc->stride_in_bytes = stride_in_bytes != 0 ? stride_in_bytes : pw;
3790
3797
  spc->h_oversample = 1;
3791
3798
  spc->v_oversample = 1;
3799
+ spc->skip_missing = 0;
3792
3800
 
3793
3801
  stbrp_init_target(context, pw-padding, ph-padding, nodes, num_nodes);
3794
3802
 
@@ -3814,6 +3822,11 @@ STBTT_DEF void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h
3814
3822
  spc->v_oversample = v_oversample;
3815
3823
  }
3816
3824
 
3825
+ STBTT_DEF void stbtt_PackSetSkipMissingCodepoints(stbtt_pack_context *spc, int skip)
3826
+ {
3827
+ spc->skip_missing = skip;
3828
+ }
3829
+
3817
3830
  #define STBTT__OVER_MASK (STBTT_MAX_OVERSAMPLE-1)
3818
3831
 
3819
3832
  static void stbtt__h_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes, unsigned int kernel_width)
@@ -3956,6 +3969,7 @@ static float stbtt__oversample_shift(int oversample)
3956
3969
  STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects)
3957
3970
  {
3958
3971
  int i,j,k;
3972
+ int missing_glyph_added = 0;
3959
3973
 
3960
3974
  k=0;
3961
3975
  for (i=0; i < num_ranges; ++i) {
@@ -3967,13 +3981,19 @@ STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stb
3967
3981
  int x0,y0,x1,y1;
3968
3982
  int codepoint = ranges[i].array_of_unicode_codepoints == NULL ? ranges[i].first_unicode_codepoint_in_range + j : ranges[i].array_of_unicode_codepoints[j];
3969
3983
  int glyph = stbtt_FindGlyphIndex(info, codepoint);
3970
- stbtt_GetGlyphBitmapBoxSubpixel(info,glyph,
3971
- scale * spc->h_oversample,
3972
- scale * spc->v_oversample,
3973
- 0,0,
3974
- &x0,&y0,&x1,&y1);
3975
- rects[k].w = (stbrp_coord) (x1-x0 + spc->padding + spc->h_oversample-1);
3976
- rects[k].h = (stbrp_coord) (y1-y0 + spc->padding + spc->v_oversample-1);
3984
+ if (glyph == 0 && (spc->skip_missing || missing_glyph_added)) {
3985
+ rects[k].w = rects[k].h = 0;
3986
+ } else {
3987
+ stbtt_GetGlyphBitmapBoxSubpixel(info,glyph,
3988
+ scale * spc->h_oversample,
3989
+ scale * spc->v_oversample,
3990
+ 0,0,
3991
+ &x0,&y0,&x1,&y1);
3992
+ rects[k].w = (stbrp_coord) (x1-x0 + spc->padding + spc->h_oversample-1);
3993
+ rects[k].h = (stbrp_coord) (y1-y0 + spc->padding + spc->v_oversample-1);
3994
+ if (glyph == 0)
3995
+ missing_glyph_added = 1;
3996
+ }
3977
3997
  ++k;
3978
3998
  }
3979
3999
  }
@@ -4007,7 +4027,7 @@ STBTT_DEF void stbtt_MakeGlyphBitmapSubpixelPrefilter(const stbtt_fontinfo *info
4007
4027
  // rects array must be big enough to accommodate all characters in the given ranges
4008
4028
  STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects)
4009
4029
  {
4010
- int i,j,k, return_value = 1;
4030
+ int i,j,k, missing_glyph = -1, return_value = 1;
4011
4031
 
4012
4032
  // save current values
4013
4033
  int old_h_over = spc->h_oversample;
@@ -4026,7 +4046,7 @@ STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const
4026
4046
  sub_y = stbtt__oversample_shift(spc->v_oversample);
4027
4047
  for (j=0; j < ranges[i].num_chars; ++j) {
4028
4048
  stbrp_rect *r = &rects[k];
4029
- if (r->was_packed) {
4049
+ if (r->was_packed && r->w != 0 && r->h != 0) {
4030
4050
  stbtt_packedchar *bc = &ranges[i].chardata_for_range[j];
4031
4051
  int advance, lsb, x0,y0,x1,y1;
4032
4052
  int codepoint = ranges[i].array_of_unicode_codepoints == NULL ? ranges[i].first_unicode_codepoint_in_range + j : ranges[i].array_of_unicode_codepoints[j];
@@ -4072,6 +4092,13 @@ STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const
4072
4092
  bc->yoff = (float) y0 * recip_v + sub_y;
4073
4093
  bc->xoff2 = (x0 + r->w) * recip_h + sub_x;
4074
4094
  bc->yoff2 = (y0 + r->h) * recip_v + sub_y;
4095
+
4096
+ if (glyph == 0)
4097
+ missing_glyph = j;
4098
+ } else if (spc->skip_missing) {
4099
+ return_value = 0;
4100
+ } else if (r->was_packed && r->w == 0 && r->h == 0 && missing_glyph >= 0) {
4101
+ ranges[i].chardata_for_range[j] = ranges[i].chardata_for_range[missing_glyph];
4075
4102
  } else {
4076
4103
  return_value = 0; // if any fail, report failure
4077
4104
  }
@@ -4140,6 +4167,19 @@ STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, const unsigned char *
4140
4167
  return stbtt_PackFontRanges(spc, fontdata, font_index, &range, 1);
4141
4168
  }
4142
4169
 
4170
+ STBTT_DEF void stbtt_GetScaledFontVMetrics(const unsigned char *fontdata, int index, float size, float *ascent, float *descent, float *lineGap)
4171
+ {
4172
+ int i_ascent, i_descent, i_lineGap;
4173
+ float scale;
4174
+ stbtt_fontinfo info;
4175
+ stbtt_InitFont(&info, fontdata, stbtt_GetFontOffsetForIndex(fontdata, index));
4176
+ scale = size > 0 ? stbtt_ScaleForPixelHeight(&info, size) : stbtt_ScaleForMappingEmToPixels(&info, -size);
4177
+ stbtt_GetFontVMetrics(&info, &i_ascent, &i_descent, &i_lineGap);
4178
+ *ascent = (float) i_ascent * scale;
4179
+ *descent = (float) i_descent * scale;
4180
+ *lineGap = (float) i_lineGap * scale;
4181
+ }
4182
+
4143
4183
  STBTT_DEF void stbtt_GetPackedQuad(const stbtt_packedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int align_to_integer)
4144
4184
  {
4145
4185
  float ipw = 1.0f / pw, iph = 1.0f / ph;
@@ -4360,12 +4400,7 @@ STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float sc
4360
4400
  int w,h;
4361
4401
  unsigned char *data;
4362
4402
 
4363
- // if one scale is 0, use same scale for both
4364
- if (scale_x == 0) scale_x = scale_y;
4365
- if (scale_y == 0) {
4366
- if (scale_x == 0) return NULL; // if both scales are 0, return NULL
4367
- scale_y = scale_x;
4368
- }
4403
+ if (scale == 0) return NULL;
4369
4404
 
4370
4405
  stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale, scale, 0.0f,0.0f, &ix0,&iy0,&ix1,&iy1);
4371
4406