sourparse.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457
  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <string.h>
  4. #include "../headers/sourparse.h"
  5. void skip_8(SP_font *font){
  6. font->current_byte++;
  7. }
  8. void skip_16(SP_font *font){
  9. font->current_byte += 2;
  10. }
  11. void skip_32(SP_font *font){
  12. font->current_byte += 4;
  13. }
  14. uint8_t get_u8(SP_font *font){
  15. return font->buffer[font->current_byte++];
  16. }
  17. // file is in big endian
  18. // swap bytes
  19. // 0x1234 -> 0x3412
  20. uint16_t get_u16(SP_font *font){
  21. return (uint16_t)(font->buffer[font->current_byte++] << 8 | font->buffer[font->current_byte++]);
  22. }
  23. uint32_t get_u32(SP_font *font){
  24. return (uint32_t)(font->buffer[font->current_byte++] << 24 | font->buffer[font->current_byte++] << 16 | font->buffer[font->current_byte++] << 8 | font->buffer[font->current_byte++]);
  25. }
  26. int8_t get_i8(SP_font *font){
  27. return font->buffer[font->current_byte++];
  28. }
  29. int16_t get_i16(SP_font *font){
  30. return (int16_t)(font->buffer[font->current_byte++] << 8 | font->buffer[font->current_byte++]);
  31. }
  32. int32_t get_i32(SP_font *font){
  33. return (int32_t)(font->buffer[font->current_byte++] << 24 | font->buffer[font->current_byte++] << 16 | font->buffer[font->current_byte++] << 8 | font->buffer[font->current_byte++]);
  34. }
  35. void get_tag(SP_font *font, char *tag){
  36. tag[0] = get_u8(font);
  37. tag[1] = get_u8(font);
  38. tag[2] = get_u8(font);
  39. tag[3] = get_u8(font);
  40. tag[4] = '\0';
  41. }
  42. float get_F2DOT14(SP_font *font) {
  43. int16_t signedVal = (int16_t)(font->buffer[font->current_byte++] << 8 | font->buffer[font->current_byte++]);
  44. return signedVal / 16384.0f;
  45. }
  46. int* read_glyph_coords(SP_font *font, uint8_t *flags, int number_of_points, int is_this_function_reading_the_x_coordinates_hmmmm_well_if_this_vaSPable_is_one_then_it_means_we_are_okay_yayyyyyy){
  47. int byte_size_bit = is_this_function_reading_the_x_coordinates_hmmmm_well_if_this_vaSPable_is_one_then_it_means_we_are_okay_yayyyyyy ? 1 : 2;
  48. int sign_slash_repeat_bit = is_this_function_reading_the_x_coordinates_hmmmm_well_if_this_vaSPable_is_one_then_it_means_we_are_okay_yayyyyyy ? 4 : 5;
  49. int *coords = malloc(sizeof(int) * number_of_points);
  50. for (int i = 0; i < number_of_points; ++i){
  51. uint8_t flag = flags[i];
  52. int on_curve = flag & 1;
  53. int delta = 0;
  54. // delta is 8 bits
  55. if (flag >> byte_size_bit & 1){
  56. // delta is the current coord.
  57. // it's called delta because the coords are differences in position, not positions
  58. // also this part ------------------------------------------ sets the sign of the delta
  59. delta = (int)get_u8(font) * (flag >> sign_slash_repeat_bit & 1 ? 1 : -1);
  60. } // delta is 16 bits
  61. else {
  62. if (!(flag >> sign_slash_repeat_bit & 1)){
  63. delta = (int)get_i16(font);
  64. }
  65. }
  66. if (i == 0){
  67. coords[i] = delta;
  68. }else {
  69. coords[i] = coords[i - 1] + delta;
  70. }
  71. }
  72. return coords;
  73. }
  74. // composite flags
  75. #define ARG_1_AND_2_ARE_WORDS 0x0001
  76. #define ARGS_ARE_XY_VALUES 0x0002
  77. #define WE_HAVE_A_SCALE 0x0008
  78. #define MORE_COMPONENTS 0x0020
  79. #define WE_HAVE_AN_X_AND_Y_SCALE 0x0040
  80. #define WE_HAVE_A_TWO_BY_TWO 0x0080
  81. #define WE_HAVE_INSTRUCTIONS 0x0100
  82. // simple flags
  83. #define REPEAT_FLAG 0x08
  84. void read_glyph(SP_font *font, int current_glyph){
  85. int glyph_start = font->glyph_offsets[current_glyph];
  86. int glyph_end = font->glyph_offsets[current_glyph + 1];
  87. font->current_byte = glyph_start;
  88. SP_glyph *glyph = &font->glyphs[current_glyph];
  89. glyph->number_of_contours = (int)get_i16(font);
  90. // do i need these? i dont think so
  91. glyph->x_min = get_i16(font);
  92. glyph->y_min = get_i16(font);
  93. glyph->x_max = get_i16(font);
  94. glyph->y_max = get_i16(font);
  95. // glyph is composite :(
  96. if (glyph->number_of_contours < 0){
  97. glyph->is_composite = 1;
  98. uint16_t flags;
  99. glyph->number_of_components = 0;
  100. int current_allocated_components = 5;
  101. // assume the glyph has 5 children components
  102. glyph->components = malloc(sizeof(SP_component) * current_allocated_components);
  103. int reading_glyphs = 1;
  104. while (reading_glyphs) {
  105. glyph->number_of_components++;
  106. // we use number of components as the current component because we're iteratiing it anyways.
  107. // A better name would be more fitting, but it wouldn't make sense to use another var
  108. if (glyph->number_of_components >= current_allocated_components){
  109. current_allocated_components += 5;
  110. glyph->components = realloc(glyph->components, current_allocated_components);
  111. }
  112. SP_component *c_glyph = &glyph->components[glyph->number_of_components];
  113. flags = get_u16(font);
  114. uint16_t glyph_index = get_u16(font);
  115. c_glyph->scale_x = c_glyph->scale_y = c_glyph->scale01 = c_glyph->scale10 = 1;
  116. if (flags & ARG_1_AND_2_ARE_WORDS) { // args are words
  117. if (flags & ARGS_ARE_XY_VALUES) { // args are signed offsets
  118. c_glyph->arg1 = get_i16(font);
  119. c_glyph->arg2 = get_i16(font);
  120. } else { // ------------------------ args are point indecies
  121. c_glyph->arg1 = get_u16(font);
  122. c_glyph->arg2 = get_u16(font);
  123. }
  124. } else { // args are bytes
  125. if (flags & ARGS_ARE_XY_VALUES) {
  126. c_glyph->arg1 = get_i8(font);
  127. c_glyph->arg2 = get_i8(font);
  128. } else {
  129. c_glyph->arg1 = get_u8(font);
  130. c_glyph->arg2 = get_u8(font);
  131. }
  132. }
  133. if (flags & WE_HAVE_A_SCALE) { // we have a scale
  134. c_glyph->scale_x = c_glyph->scale_y = (int)get_F2DOT14(font);
  135. } else if (flags & WE_HAVE_AN_X_AND_Y_SCALE) { // seperate x and y scales
  136. c_glyph->scale_x = (int)get_F2DOT14(font);
  137. c_glyph->scale_y = (int)get_F2DOT14(font);
  138. } else if (flags & WE_HAVE_A_TWO_BY_TWO) { // 2x2 transform
  139. c_glyph->scale_x = (int)get_F2DOT14(font);
  140. c_glyph->scale01 = (int)get_F2DOT14(font);
  141. c_glyph->scale10 = (int)get_F2DOT14(font);
  142. c_glyph->scale_y = (int)get_F2DOT14(font);
  143. }
  144. if (!(flags & MORE_COMPONENTS)) { // this is the last c_glyph, stop reading (please&thankyou)
  145. reading_glyphs = 0;
  146. }
  147. }
  148. if (flags & WE_HAVE_INSTRUCTIONS){ // we have instructions
  149. uint16_t number_of_instructions = get_u16(font);
  150. for (int i = 0; i < number_of_instructions; ++i) skip_8(font); // we dont care about instructions
  151. }
  152. font->current_byte = glyph_end;
  153. return;
  154. }
  155. glyph->is_composite = 0;
  156. glyph->contour_end_indicies = malloc(sizeof(int) * glyph->number_of_contours);
  157. for (int i = 0; i < (int)glyph->number_of_contours; ++i){
  158. glyph->contour_end_indicies[i] = (int)get_u16(font);
  159. }
  160. // skip instructions
  161. uint16_t instruction_length = get_u16(font);
  162. if (instruction_length > 0){
  163. for (int i = 0; i < instruction_length; ++i){
  164. skip_8(font);
  165. }
  166. }
  167. if (glyph->number_of_contours == 0) return; // we still want to skip the instructions so that we dont get offset
  168. // add one because these are 0-indexed indicies.
  169. // the last one is the highest index
  170. glyph->number_of_points = glyph->contour_end_indicies[glyph->number_of_contours - 1] + 1;
  171. glyph->flags = malloc(sizeof(uint8_t) * (glyph->number_of_points));
  172. for (int i = 0; i < glyph->number_of_points; ++i){ // flags
  173. glyph->flags[i] = get_u8(font); // flag
  174. if (glyph->flags[i] & REPEAT_FLAG){ // is the flag a repeat flag?
  175. uint8_t flag = glyph->flags[i];
  176. int times_to_repeat = (int)get_u8(font);
  177. for (int j = 0; j < times_to_repeat; ++j){ // yes, get the next byte (number of repeats) and repeat this flag however many times
  178. glyph->flags[++i] = flag;
  179. }
  180. }
  181. }
  182. glyph->x_coords = read_glyph_coords(font, glyph->flags, glyph->number_of_points, 1);
  183. glyph->y_coords = read_glyph_coords(font, glyph->flags, glyph->number_of_points, 0);
  184. font->current_byte = glyph_end;
  185. }
  186. SP_font* SP_load_font(char *filename){
  187. SP_font *font = calloc(1, sizeof(SP_font));
  188. FILE *fp = fopen(filename, "rb");
  189. fseek(fp, 0, SEEK_END);
  190. long size = ftell(fp);
  191. rewind(fp);
  192. font->buffer = malloc(size);
  193. fread(font->buffer, 1, size, fp);
  194. fclose(fp);
  195. skip_32(font);
  196. uint16_t number_of_tables = get_u16(font);
  197. skip_32(font);
  198. skip_16(font);
  199. int glyph_offset = 0;
  200. int maxp_offset = 0;
  201. int cmap_offset = 0;
  202. int loca_offset = 0;
  203. int head_offset = 0;
  204. for (int i = 0; i < (int)number_of_tables; ++i){
  205. char tag[5]; get_tag(font, tag);
  206. uint32_t checksum = get_u32(font);
  207. uint32_t offset = get_u32(font);
  208. uint32_t length = get_u32(font);
  209. if (strcmp(tag, "glyf") == 0){
  210. glyph_offset = (int)offset;
  211. }
  212. else if (strcmp(tag, "maxp") == 0){
  213. maxp_offset = (int)offset;
  214. }
  215. else if (strcmp(tag, "cmap") == 0){
  216. cmap_offset = (int)offset;
  217. }
  218. else if (strcmp(tag, "loca") == 0){
  219. loca_offset = (int)offset;
  220. }
  221. else if (strcmp(tag, "head") == 0){
  222. head_offset = (int)offset;
  223. }
  224. }
  225. // head table
  226. font->current_byte = head_offset;
  227. // skip nonsense
  228. skip_32(font); // version
  229. skip_32(font); // font revision
  230. skip_32(font); // checksum adjustment
  231. skip_32(font); // magic number
  232. skip_16(font); // flags
  233. font->units_per_em = get_u16(font);
  234. // skip gibberjabber
  235. skip_32(font); // 64 bit longdatetime
  236. skip_32(font);
  237. skip_32(font); // 64 bit longdatetime
  238. skip_32(font);
  239. skip_32(font); // mins
  240. skip_32(font); // maxs
  241. skip_16(font);
  242. skip_16(font);
  243. skip_16(font);
  244. font->index_to_loca_format = get_i16(font);
  245. // get number of glyphs
  246. font->current_byte = maxp_offset;
  247. skip_32(font);
  248. font->number_of_glyphs = (int)get_u16(font);
  249. // glyph locations
  250. font->current_byte = loca_offset;
  251. font->glyph_offsets = malloc(sizeof(int) * (font->number_of_glyphs + 1));
  252. for (int i = 0; i <= font->number_of_glyphs; ++i){
  253. if (font->index_to_loca_format){ // long offsets (32 bit)
  254. font->glyph_offsets[i] = (int)get_u32(font) + glyph_offset;
  255. }else { // short offsets (16 bit)
  256. font->glyph_offsets[i] = (int)get_u16(font) * 2 + glyph_offset;
  257. }
  258. }
  259. // character map
  260. font->current_byte = cmap_offset;
  261. uint16_t version = get_u16(font);
  262. uint16_t number_of_cmap_tables = get_u16(font);
  263. int last_byte_offset;
  264. for (int i = 0; i < number_of_cmap_tables; ++i){
  265. uint16_t platform_id = get_u16(font);
  266. uint16_t encoding_id = get_u16(font);
  267. uint32_t subtable_offset = get_u32(font);
  268. last_byte_offset = font->current_byte;
  269. font->current_byte = cmap_offset + subtable_offset;
  270. if (platform_id == 3 && encoding_id == 1){
  271. // i'll add this when i have to use a font that needs it
  272. } else if (platform_id == 0 && encoding_id == 3){
  273. // assuming only format 4 for now because im lazy >w<
  274. uint16_t format = get_u16(font);
  275. uint16_t length = get_u16(font);
  276. uint16_t language = get_u16(font);
  277. uint16_t seg_count_x2 = get_u16(font); uint16_t seg_count = seg_count_x2 / 2;
  278. skip_16(font);
  279. skip_16(font);
  280. skip_16(font);
  281. uint16_t *end_codes = malloc(sizeof(uint16_t) * seg_count);
  282. for (int i = 0; i < seg_count; ++i) end_codes[i] = get_u16(font);
  283. skip_16(font);
  284. uint16_t *start_codes = malloc(sizeof(uint16_t) * seg_count);
  285. for (int i = 0; i < seg_count; ++i) start_codes[i] = get_u16(font);
  286. int16_t *id_deltas = malloc(sizeof(uint16_t) * seg_count);
  287. for (int i = 0; i < seg_count; ++i) id_deltas[i] = get_u16(font);
  288. int id_range_offsets_size = length - (font->current_byte - (cmap_offset + subtable_offset));
  289. uint16_t *id_range_offsets = malloc(sizeof(uint16_t) * id_range_offsets_size);
  290. for (int i = 0; i < id_range_offsets_size; ++i) id_range_offsets[i] = get_u16(font);
  291. int highest_code = end_codes[seg_count - 1];
  292. font->unicode_to_glyph_indicies = malloc(sizeof(uint16_t) * highest_code);
  293. // loop over segments.
  294. // a segment is a range of unicode characters that are all mapped with the same formula.
  295. // i dont understand this at all
  296. for (int i = 0; i < (int)seg_count; ++i) {
  297. int start_code = start_codes[i];
  298. int end_code = end_codes[i];
  299. uint16_t glyph_index = 0;
  300. for (int j = start_code; j < end_code; j++){
  301. // if range offset is zero, the id comes from glyph id array
  302. if (id_range_offsets[i] == 0){
  303. glyph_index = (j + id_deltas[i]) % 65536;
  304. } else {
  305. glyph_index = *(id_range_offsets[i]/2 + (j - start_codes[i]) + &id_range_offsets[i]);
  306. glyph_index = (glyph_index + id_deltas[i]) % 65536;
  307. }
  308. font->unicode_to_glyph_indicies[j] = glyph_index;
  309. }
  310. }
  311. free(end_codes);
  312. free(start_codes);
  313. free(id_deltas);
  314. free(id_range_offsets);
  315. break; // stop because we only need one
  316. } else { // excuse
  317. // printf("cant read this becuase dont want to");
  318. }
  319. font->current_byte = last_byte_offset;
  320. }
  321. // read glyphs
  322. font->current_byte = glyph_offset;
  323. font->glyphs = malloc(sizeof(SP_glyph) * font->number_of_glyphs);
  324. for (int i = 0; i < font->number_of_glyphs; ++i){
  325. read_glyph(font, i);
  326. }
  327. return font;
  328. }
  329. void SP_free_font(SP_font *font){
  330. free(font->buffer);
  331. free(font->glyph_offsets);
  332. for (int i = 0; i < font->number_of_glyphs; ++i){
  333. if (!font->glyphs[i].is_composite){
  334. free(font->glyphs[i].contour_end_indicies);
  335. free(font->glyphs[i].flags);
  336. free(font->glyphs[i].x_coords);
  337. free(font->glyphs[i].y_coords);
  338. } else {
  339. free(font->glyphs[i].components);
  340. }
  341. }
  342. free(font->glyphs);
  343. free(font->unicode_to_glyph_indicies);
  344. free(font);
  345. }