• R/O
  • SSH
  • HTTPS

gd10: Commit


Commit MetaInfo

Revisão213 (tree)
Hora2019-09-21 05:04:20
Autorhgtterry

Mensagem de Log

(mensagem de log vazia)

Mudança Sumário

Diff

--- Equity10/Common/imGui/include/imstb_rectpack.h (revision 212)
+++ Equity10/Common/imGui/include/imstb_rectpack.h (nonexistent)
@@ -1,630 +0,0 @@
1-// [DEAR IMGUI]
2-// This is a slightly modified version of stb_rect_pack.h 0.99.
3-// Those changes would need to be pushed into nothings/stb:
4-// - Added STBRP__CDECL
5-// Grep for [DEAR IMGUI] to find the changes.
6-
7-// stb_rect_pack.h - v0.99 - public domain - rectangle packing
8-// Sean Barrett 2014
9-//
10-// Useful for e.g. packing rectangular textures into an atlas.
11-// Does not do rotation.
12-//
13-// Not necessarily the awesomest packing method, but better than
14-// the totally naive one in stb_truetype (which is primarily what
15-// this is meant to replace).
16-//
17-// Has only had a few tests run, may have issues.
18-//
19-// More docs to come.
20-//
21-// No memory allocations; uses qsort() and assert() from stdlib.
22-// Can override those by defining STBRP_SORT and STBRP_ASSERT.
23-//
24-// This library currently uses the Skyline Bottom-Left algorithm.
25-//
26-// Please note: better rectangle packers are welcome! Please
27-// implement them to the same API, but with a different init
28-// function.
29-//
30-// Credits
31-//
32-// Library
33-// Sean Barrett
34-// Minor features
35-// Martins Mozeiko
36-// github:IntellectualKitty
37-//
38-// Bugfixes / warning fixes
39-// Jeremy Jaussaud
40-//
41-// Version history:
42-//
43-// 0.99 (2019-02-07) warning fixes
44-// 0.11 (2017-03-03) return packing success/fail result
45-// 0.10 (2016-10-25) remove cast-away-const to avoid warnings
46-// 0.09 (2016-08-27) fix compiler warnings
47-// 0.08 (2015-09-13) really fix bug with empty rects (w=0 or h=0)
48-// 0.07 (2015-09-13) fix bug with empty rects (w=0 or h=0)
49-// 0.06 (2015-04-15) added STBRP_SORT to allow replacing qsort
50-// 0.05: added STBRP_ASSERT to allow replacing assert
51-// 0.04: fixed minor bug in STBRP_LARGE_RECTS support
52-// 0.01: initial release
53-//
54-// LICENSE
55-//
56-// See end of file for license information.
57-
58-//////////////////////////////////////////////////////////////////////////////
59-//
60-// INCLUDE SECTION
61-//
62-
63-#ifndef STB_INCLUDE_STB_RECT_PACK_H
64-#define STB_INCLUDE_STB_RECT_PACK_H
65-
66-#define STB_RECT_PACK_VERSION 1
67-
68-#ifdef STBRP_STATIC
69-#define STBRP_DEF static
70-#else
71-#define STBRP_DEF extern
72-#endif
73-
74-#ifdef __cplusplus
75-extern "C" {
76-#endif
77-
78-typedef struct stbrp_context stbrp_context;
79-typedef struct stbrp_node stbrp_node;
80-typedef struct stbrp_rect stbrp_rect;
81-
82-#ifdef STBRP_LARGE_RECTS
83-typedef int stbrp_coord;
84-#else
85-typedef unsigned short stbrp_coord;
86-#endif
87-
88-STBRP_DEF int stbrp_pack_rects (stbrp_context *context, stbrp_rect *rects, int num_rects);
89-// Assign packed locations to rectangles. The rectangles are of type
90-// 'stbrp_rect' defined below, stored in the array 'rects', and there
91-// are 'num_rects' many of them.
92-//
93-// Rectangles which are successfully packed have the 'was_packed' flag
94-// set to a non-zero value and 'x' and 'y' store the minimum location
95-// on each axis (i.e. bottom-left in cartesian coordinates, top-left
96-// if you imagine y increasing downwards). Rectangles which do not fit
97-// have the 'was_packed' flag set to 0.
98-//
99-// You should not try to access the 'rects' array from another thread
100-// while this function is running, as the function temporarily reorders
101-// the array while it executes.
102-//
103-// To pack into another rectangle, you need to call stbrp_init_target
104-// again. To continue packing into the same rectangle, you can call
105-// this function again. Calling this multiple times with multiple rect
106-// arrays will probably produce worse packing results than calling it
107-// a single time with the full rectangle array, but the option is
108-// available.
109-//
110-// The function returns 1 if all of the rectangles were successfully
111-// packed and 0 otherwise.
112-
113-struct stbrp_rect
114-{
115- // reserved for your use:
116- int id;
117-
118- // input:
119- stbrp_coord w, h;
120-
121- // output:
122- stbrp_coord x, y;
123- int was_packed; // non-zero if valid packing
124-
125-}; // 16 bytes, nominally
126-
127-
128-STBRP_DEF void stbrp_init_target (stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes);
129-// Initialize a rectangle packer to:
130-// pack a rectangle that is 'width' by 'height' in dimensions
131-// using temporary storage provided by the array 'nodes', which is 'num_nodes' long
132-//
133-// You must call this function every time you start packing into a new target.
134-//
135-// There is no "shutdown" function. The 'nodes' memory must stay valid for
136-// the following stbrp_pack_rects() call (or calls), but can be freed after
137-// the call (or calls) finish.
138-//
139-// Note: to guarantee best results, either:
140-// 1. make sure 'num_nodes' >= 'width'
141-// or 2. call stbrp_allow_out_of_mem() defined below with 'allow_out_of_mem = 1'
142-//
143-// If you don't do either of the above things, widths will be quantized to multiples
144-// of small integers to guarantee the algorithm doesn't run out of temporary storage.
145-//
146-// If you do #2, then the non-quantized algorithm will be used, but the algorithm
147-// may run out of temporary storage and be unable to pack some rectangles.
148-
149-STBRP_DEF void stbrp_setup_allow_out_of_mem (stbrp_context *context, int allow_out_of_mem);
150-// Optionally call this function after init but before doing any packing to
151-// change the handling of the out-of-temp-memory scenario, described above.
152-// If you call init again, this will be reset to the default (false).
153-
154-
155-STBRP_DEF void stbrp_setup_heuristic (stbrp_context *context, int heuristic);
156-// Optionally select which packing heuristic the library should use. Different
157-// heuristics will produce better/worse results for different data sets.
158-// If you call init again, this will be reset to the default.
159-
160-enum
161-{
162- STBRP_HEURISTIC_Skyline_default=0,
163- STBRP_HEURISTIC_Skyline_BL_sortHeight = STBRP_HEURISTIC_Skyline_default,
164- STBRP_HEURISTIC_Skyline_BF_sortHeight
165-};
166-
167-
168-//////////////////////////////////////////////////////////////////////////////
169-//
170-// the details of the following structures don't matter to you, but they must
171-// be visible so you can handle the memory allocations for them
172-
173-struct stbrp_node
174-{
175- stbrp_coord x,y;
176- stbrp_node *next;
177-};
178-
179-struct stbrp_context
180-{
181- int width;
182- int height;
183- int align;
184- int init_mode;
185- int heuristic;
186- int num_nodes;
187- stbrp_node *active_head;
188- stbrp_node *free_head;
189- stbrp_node extra[2]; // we allocate two extra nodes so optimal user-node-count is 'width' not 'width+2'
190-};
191-
192-#ifdef __cplusplus
193-}
194-#endif
195-
196-#endif
197-
198-//////////////////////////////////////////////////////////////////////////////
199-//
200-// IMPLEMENTATION SECTION
201-//
202-
203-#ifdef STB_RECT_PACK_IMPLEMENTATION
204-#ifndef STBRP_SORT
205-#include <stdlib.h>
206-#define STBRP_SORT qsort
207-#endif
208-
209-#ifndef STBRP_ASSERT
210-#include <assert.h>
211-#define STBRP_ASSERT assert
212-#endif
213-
214-// [DEAR IMGUI] Added STBRP__CDECL
215-#ifdef _MSC_VER
216-#define STBRP__NOTUSED(v) (void)(v)
217-#define STBRP__CDECL __cdecl
218-#else
219-#define STBRP__NOTUSED(v) (void)sizeof(v)
220-#define STBRP__CDECL
221-#endif
222-
223-enum
224-{
225- STBRP__INIT_skyline = 1
226-};
227-
228-STBRP_DEF void stbrp_setup_heuristic(stbrp_context *context, int heuristic)
229-{
230- switch (context->init_mode) {
231- case STBRP__INIT_skyline:
232- STBRP_ASSERT(heuristic == STBRP_HEURISTIC_Skyline_BL_sortHeight || heuristic == STBRP_HEURISTIC_Skyline_BF_sortHeight);
233- context->heuristic = heuristic;
234- break;
235- default:
236- STBRP_ASSERT(0);
237- }
238-}
239-
240-STBRP_DEF void stbrp_setup_allow_out_of_mem(stbrp_context *context, int allow_out_of_mem)
241-{
242- if (allow_out_of_mem)
243- // if it's ok to run out of memory, then don't bother aligning them;
244- // this gives better packing, but may fail due to OOM (even though
245- // the rectangles easily fit). @TODO a smarter approach would be to only
246- // quantize once we've hit OOM, then we could get rid of this parameter.
247- context->align = 1;
248- else {
249- // if it's not ok to run out of memory, then quantize the widths
250- // so that num_nodes is always enough nodes.
251- //
252- // I.e. num_nodes * align >= width
253- // align >= width / num_nodes
254- // align = ceil(width/num_nodes)
255-
256- context->align = (context->width + context->num_nodes-1) / context->num_nodes;
257- }
258-}
259-
260-STBRP_DEF void stbrp_init_target(stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes)
261-{
262- int i;
263-#ifndef STBRP_LARGE_RECTS
264- STBRP_ASSERT(width <= 0xffff && height <= 0xffff);
265-#endif
266-
267- for (i=0; i < num_nodes-1; ++i)
268- nodes[i].next = &nodes[i+1];
269- nodes[i].next = NULL;
270- context->init_mode = STBRP__INIT_skyline;
271- context->heuristic = STBRP_HEURISTIC_Skyline_default;
272- context->free_head = &nodes[0];
273- context->active_head = &context->extra[0];
274- context->width = width;
275- context->height = height;
276- context->num_nodes = num_nodes;
277- stbrp_setup_allow_out_of_mem(context, 0);
278-
279- // node 0 is the full width, node 1 is the sentinel (lets us not store width explicitly)
280- context->extra[0].x = 0;
281- context->extra[0].y = 0;
282- context->extra[0].next = &context->extra[1];
283- context->extra[1].x = (stbrp_coord) width;
284-#ifdef STBRP_LARGE_RECTS
285- context->extra[1].y = (1<<30);
286-#else
287- context->extra[1].y = 65535;
288-#endif
289- context->extra[1].next = NULL;
290-}
291-
292-// find minimum y position if it starts at x1
293-static int stbrp__skyline_find_min_y(stbrp_context *c, stbrp_node *first, int x0, int width, int *pwaste)
294-{
295- stbrp_node *node = first;
296- int x1 = x0 + width;
297- int min_y, visited_width, waste_area;
298-
299- STBRP__NOTUSED(c);
300-
301- STBRP_ASSERT(first->x <= x0);
302-
303- #if 0
304- // skip in case we're past the node
305- while (node->next->x <= x0)
306- ++node;
307- #else
308- STBRP_ASSERT(node->next->x > x0); // we ended up handling this in the caller for efficiency
309- #endif
310-
311- STBRP_ASSERT(node->x <= x0);
312-
313- min_y = 0;
314- waste_area = 0;
315- visited_width = 0;
316- while (node->x < x1) {
317- if (node->y > min_y) {
318- // raise min_y higher.
319- // we've accounted for all waste up to min_y,
320- // but we'll now add more waste for everything we've visted
321- waste_area += visited_width * (node->y - min_y);
322- min_y = node->y;
323- // the first time through, visited_width might be reduced
324- if (node->x < x0)
325- visited_width += node->next->x - x0;
326- else
327- visited_width += node->next->x - node->x;
328- } else {
329- // add waste area
330- int under_width = node->next->x - node->x;
331- if (under_width + visited_width > width)
332- under_width = width - visited_width;
333- waste_area += under_width * (min_y - node->y);
334- visited_width += under_width;
335- }
336- node = node->next;
337- }
338-
339- *pwaste = waste_area;
340- return min_y;
341-}
342-
343-typedef struct
344-{
345- int x,y;
346- stbrp_node **prev_link;
347-} stbrp__findresult;
348-
349-static stbrp__findresult stbrp__skyline_find_best_pos(stbrp_context *c, int width, int height)
350-{
351- int best_waste = (1<<30), best_x, best_y = (1 << 30);
352- stbrp__findresult fr;
353- stbrp_node **prev, *node, *tail, **best = NULL;
354-
355- // align to multiple of c->align
356- width = (width + c->align - 1);
357- width -= width % c->align;
358- STBRP_ASSERT(width % c->align == 0);
359-
360- node = c->active_head;
361- prev = &c->active_head;
362- while (node->x + width <= c->width) {
363- int y,waste;
364- y = stbrp__skyline_find_min_y(c, node, node->x, width, &waste);
365- if (c->heuristic == STBRP_HEURISTIC_Skyline_BL_sortHeight) { // actually just want to test BL
366- // bottom left
367- if (y < best_y) {
368- best_y = y;
369- best = prev;
370- }
371- } else {
372- // best-fit
373- if (y + height <= c->height) {
374- // can only use it if it first vertically
375- if (y < best_y || (y == best_y && waste < best_waste)) {
376- best_y = y;
377- best_waste = waste;
378- best = prev;
379- }
380- }
381- }
382- prev = &node->next;
383- node = node->next;
384- }
385-
386- best_x = (best == NULL) ? 0 : (*best)->x;
387-
388- // if doing best-fit (BF), we also have to try aligning right edge to each node position
389- //
390- // e.g, if fitting
391- //
392- // ____________________
393- // |____________________|
394- //
395- // into
396- //
397- // | |
398- // | ____________|
399- // |____________|
400- //
401- // then right-aligned reduces waste, but bottom-left BL is always chooses left-aligned
402- //
403- // This makes BF take about 2x the time
404-
405- if (c->heuristic == STBRP_HEURISTIC_Skyline_BF_sortHeight) {
406- tail = c->active_head;
407- node = c->active_head;
408- prev = &c->active_head;
409- // find first node that's admissible
410- while (tail->x < width)
411- tail = tail->next;
412- while (tail) {
413- int xpos = tail->x - width;
414- int y,waste;
415- STBRP_ASSERT(xpos >= 0);
416- // find the left position that matches this
417- while (node->next->x <= xpos) {
418- prev = &node->next;
419- node = node->next;
420- }
421- STBRP_ASSERT(node->next->x > xpos && node->x <= xpos);
422- y = stbrp__skyline_find_min_y(c, node, xpos, width, &waste);
423- if (y + height < c->height) {
424- if (y <= best_y) {
425- if (y < best_y || waste < best_waste || (waste==best_waste && xpos < best_x)) {
426- best_x = xpos;
427- STBRP_ASSERT(y <= best_y);
428- best_y = y;
429- best_waste = waste;
430- best = prev;
431- }
432- }
433- }
434- tail = tail->next;
435- }
436- }
437-
438- fr.prev_link = best;
439- fr.x = best_x;
440- fr.y = best_y;
441- return fr;
442-}
443-
444-static stbrp__findresult stbrp__skyline_pack_rectangle(stbrp_context *context, int width, int height)
445-{
446- // find best position according to heuristic
447- stbrp__findresult res = stbrp__skyline_find_best_pos(context, width, height);
448- stbrp_node *node, *cur;
449-
450- // bail if:
451- // 1. it failed
452- // 2. the best node doesn't fit (we don't always check this)
453- // 3. we're out of memory
454- if (res.prev_link == NULL || res.y + height > context->height || context->free_head == NULL) {
455- res.prev_link = NULL;
456- return res;
457- }
458-
459- // on success, create new node
460- node = context->free_head;
461- node->x = (stbrp_coord) res.x;
462- node->y = (stbrp_coord) (res.y + height);
463-
464- context->free_head = node->next;
465-
466- // insert the new node into the right starting point, and
467- // let 'cur' point to the remaining nodes needing to be
468- // stiched back in
469-
470- cur = *res.prev_link;
471- if (cur->x < res.x) {
472- // preserve the existing one, so start testing with the next one
473- stbrp_node *next = cur->next;
474- cur->next = node;
475- cur = next;
476- } else {
477- *res.prev_link = node;
478- }
479-
480- // from here, traverse cur and free the nodes, until we get to one
481- // that shouldn't be freed
482- while (cur->next && cur->next->x <= res.x + width) {
483- stbrp_node *next = cur->next;
484- // move the current node to the free list
485- cur->next = context->free_head;
486- context->free_head = cur;
487- cur = next;
488- }
489-
490- // stitch the list back in
491- node->next = cur;
492-
493- if (cur->x < res.x + width)
494- cur->x = (stbrp_coord) (res.x + width);
495-
496-#ifdef _DEBUG
497- cur = context->active_head;
498- while (cur->x < context->width) {
499- STBRP_ASSERT(cur->x < cur->next->x);
500- cur = cur->next;
501- }
502- STBRP_ASSERT(cur->next == NULL);
503-
504- {
505- int count=0;
506- cur = context->active_head;
507- while (cur) {
508- cur = cur->next;
509- ++count;
510- }
511- cur = context->free_head;
512- while (cur) {
513- cur = cur->next;
514- ++count;
515- }
516- STBRP_ASSERT(count == context->num_nodes+2);
517- }
518-#endif
519-
520- return res;
521-}
522-
523-// [DEAR IMGUI] Added STBRP__CDECL
524-static int STBRP__CDECL rect_height_compare(const void *a, const void *b)
525-{
526- const stbrp_rect *p = (const stbrp_rect *) a;
527- const stbrp_rect *q = (const stbrp_rect *) b;
528- if (p->h > q->h)
529- return -1;
530- if (p->h < q->h)
531- return 1;
532- return (p->w > q->w) ? -1 : (p->w < q->w);
533-}
534-
535-// [DEAR IMGUI] Added STBRP__CDECL
536-static int STBRP__CDECL rect_original_order(const void *a, const void *b)
537-{
538- const stbrp_rect *p = (const stbrp_rect *) a;
539- const stbrp_rect *q = (const stbrp_rect *) b;
540- return (p->was_packed < q->was_packed) ? -1 : (p->was_packed > q->was_packed);
541-}
542-
543-#ifdef STBRP_LARGE_RECTS
544-#define STBRP__MAXVAL 0xffffffff
545-#else
546-#define STBRP__MAXVAL 0xffff
547-#endif
548-
549-STBRP_DEF int stbrp_pack_rects(stbrp_context *context, stbrp_rect *rects, int num_rects)
550-{
551- int i, all_rects_packed = 1;
552-
553- // we use the 'was_packed' field internally to allow sorting/unsorting
554- for (i=0; i < num_rects; ++i) {
555- rects[i].was_packed = i;
556- }
557-
558- // sort according to heuristic
559- STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_height_compare);
560-
561- for (i=0; i < num_rects; ++i) {
562- if (rects[i].w == 0 || rects[i].h == 0) {
563- rects[i].x = rects[i].y = 0; // empty rect needs no space
564- } else {
565- stbrp__findresult fr = stbrp__skyline_pack_rectangle(context, rects[i].w, rects[i].h);
566- if (fr.prev_link) {
567- rects[i].x = (stbrp_coord) fr.x;
568- rects[i].y = (stbrp_coord) fr.y;
569- } else {
570- rects[i].x = rects[i].y = STBRP__MAXVAL;
571- }
572- }
573- }
574-
575- // unsort
576- STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_original_order);
577-
578- // set was_packed flags and all_rects_packed status
579- for (i=0; i < num_rects; ++i) {
580- rects[i].was_packed = !(rects[i].x == STBRP__MAXVAL && rects[i].y == STBRP__MAXVAL);
581- if (!rects[i].was_packed)
582- all_rects_packed = 0;
583- }
584-
585- // return the all_rects_packed status
586- return all_rects_packed;
587-}
588-#endif
589-
590-/*
591-------------------------------------------------------------------------------
592-This software is available under 2 licenses -- choose whichever you prefer.
593-------------------------------------------------------------------------------
594-ALTERNATIVE A - MIT License
595-Copyright (c) 2017 Sean Barrett
596-Permission is hereby granted, free of charge, to any person obtaining a copy of
597-this software and associated documentation files (the "Software"), to deal in
598-the Software without restriction, including without limitation the rights to
599-use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
600-of the Software, and to permit persons to whom the Software is furnished to do
601-so, subject to the following conditions:
602-The above copyright notice and this permission notice shall be included in all
603-copies or substantial portions of the Software.
604-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
605-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
606-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
607-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
608-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
609-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
610-SOFTWARE.
611-------------------------------------------------------------------------------
612-ALTERNATIVE B - Public Domain (www.unlicense.org)
613-This is free and unencumbered software released into the public domain.
614-Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
615-software, either in source code form or as a compiled binary, for any purpose,
616-commercial or non-commercial, and by any means.
617-In jurisdictions that recognize copyright laws, the author or authors of this
618-software dedicate any and all copyright interest in the software to the public
619-domain. We make this dedication for the benefit of the public at large and to
620-the detriment of our heirs and successors. We intend this dedication to be an
621-overt act of relinquishment in perpetuity of all present and future rights to
622-this software under copyright law.
623-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
624-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
625-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
626-AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
627-ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
628-WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
629-------------------------------------------------------------------------------
630-*/
--- Equity10/Common/imGui/include/imstb_truetype.h (revision 212)
+++ Equity10/Common/imGui/include/imstb_truetype.h (nonexistent)
@@ -1,4903 +0,0 @@
1-// [DEAR IMGUI]
2-// This is a slightly modified version of stb_truetype.h 1.20.
3-// Mostly fixing for compiler and static analyzer warnings.
4-// Grep for [DEAR IMGUI] to find the changes.
5-
6-// stb_truetype.h - v1.20 - public domain
7-// authored from 2009-2016 by Sean Barrett / RAD Game Tools
8-//
9-// This library processes TrueType files:
10-// parse files
11-// extract glyph metrics
12-// extract glyph shapes
13-// render glyphs to one-channel bitmaps with antialiasing (box filter)
14-// render glyphs to one-channel SDF bitmaps (signed-distance field/function)
15-//
16-// Todo:
17-// non-MS cmaps
18-// crashproof on bad data
19-// hinting? (no longer patented)
20-// cleartype-style AA?
21-// optimize: use simple memory allocator for intermediates
22-// optimize: build edge-list directly from curves
23-// optimize: rasterize directly from curves?
24-//
25-// ADDITIONAL CONTRIBUTORS
26-//
27-// Mikko Mononen: compound shape support, more cmap formats
28-// Tor Andersson: kerning, subpixel rendering
29-// Dougall Johnson: OpenType / Type 2 font handling
30-// Daniel Ribeiro Maciel: basic GPOS-based kerning
31-//
32-// Misc other:
33-// Ryan Gordon
34-// Simon Glass
35-// github:IntellectualKitty
36-// Imanol Celaya
37-// Daniel Ribeiro Maciel
38-//
39-// Bug/warning reports/fixes:
40-// "Zer" on mollyrocket Fabian "ryg" Giesen
41-// Cass Everitt Martins Mozeiko
42-// stoiko (Haemimont Games) Cap Petschulat
43-// Brian Hook Omar Cornut
44-// Walter van Niftrik github:aloucks
45-// David Gow Peter LaValle
46-// David Given Sergey Popov
47-// Ivan-Assen Ivanov Giumo X. Clanjor
48-// Anthony Pesch Higor Euripedes
49-// Johan Duparc Thomas Fields
50-// Hou Qiming Derek Vinyard
51-// Rob Loach Cort Stratton
52-// Kenney Phillis Jr. github:oyvindjam
53-// Brian Costabile github:vassvik
54-//
55-// VERSION HISTORY
56-//
57-// 1.20 (2019-02-07) PackFontRange skips missing codepoints; GetScaleFontVMetrics()
58-// 1.19 (2018-02-11) GPOS kerning, STBTT_fmod
59-// 1.18 (2018-01-29) add missing function
60-// 1.17 (2017-07-23) make more arguments const; doc fix
61-// 1.16 (2017-07-12) SDF support
62-// 1.15 (2017-03-03) make more arguments const
63-// 1.14 (2017-01-16) num-fonts-in-TTC function
64-// 1.13 (2017-01-02) support OpenType fonts, certain Apple fonts
65-// 1.12 (2016-10-25) suppress warnings about casting away const with -Wcast-qual
66-// 1.11 (2016-04-02) fix unused-variable warning
67-// 1.10 (2016-04-02) user-defined fabs(); rare memory leak; remove duplicate typedef
68-// 1.09 (2016-01-16) warning fix; avoid crash on outofmem; use allocation userdata properly
69-// 1.08 (2015-09-13) document stbtt_Rasterize(); fixes for vertical & horizontal edges
70-// 1.07 (2015-08-01) allow PackFontRanges to accept arrays of sparse codepoints;
71-// variant PackFontRanges to pack and render in separate phases;
72-// fix stbtt_GetFontOFfsetForIndex (never worked for non-0 input?);
73-// fixed an assert() bug in the new rasterizer
74-// replace assert() with STBTT_assert() in new rasterizer
75-//
76-// Full history can be found at the end of this file.
77-//
78-// LICENSE
79-//
80-// See end of file for license information.
81-//
82-// USAGE
83-//
84-// Include this file in whatever places need to refer to it. In ONE C/C++
85-// file, write:
86-// #define STB_TRUETYPE_IMPLEMENTATION
87-// before the #include of this file. This expands out the actual
88-// implementation into that C/C++ file.
89-//
90-// To make the implementation private to the file that generates the implementation,
91-// #define STBTT_STATIC
92-//
93-// Simple 3D API (don't ship this, but it's fine for tools and quick start)
94-// stbtt_BakeFontBitmap() -- bake a font to a bitmap for use as texture
95-// stbtt_GetBakedQuad() -- compute quad to draw for a given char
96-//
97-// Improved 3D API (more shippable):
98-// #include "stb_rect_pack.h" -- optional, but you really want it
99-// stbtt_PackBegin()
100-// stbtt_PackSetOversampling() -- for improved quality on small fonts
101-// stbtt_PackFontRanges() -- pack and renders
102-// stbtt_PackEnd()
103-// stbtt_GetPackedQuad()
104-//
105-// "Load" a font file from a memory buffer (you have to keep the buffer loaded)
106-// stbtt_InitFont()
107-// stbtt_GetFontOffsetForIndex() -- indexing for TTC font collections
108-// stbtt_GetNumberOfFonts() -- number of fonts for TTC font collections
109-//
110-// Render a unicode codepoint to a bitmap
111-// stbtt_GetCodepointBitmap() -- allocates and returns a bitmap
112-// stbtt_MakeCodepointBitmap() -- renders into bitmap you provide
113-// stbtt_GetCodepointBitmapBox() -- how big the bitmap must be
114-//
115-// Character advance/positioning
116-// stbtt_GetCodepointHMetrics()
117-// stbtt_GetFontVMetrics()
118-// stbtt_GetFontVMetricsOS2()
119-// stbtt_GetCodepointKernAdvance()
120-//
121-// Starting with version 1.06, the rasterizer was replaced with a new,
122-// faster and generally-more-precise rasterizer. The new rasterizer more
123-// accurately measures pixel coverage for anti-aliasing, except in the case
124-// where multiple shapes overlap, in which case it overestimates the AA pixel
125-// coverage. Thus, anti-aliasing of intersecting shapes may look wrong. If
126-// this turns out to be a problem, you can re-enable the old rasterizer with
127-// #define STBTT_RASTERIZER_VERSION 1
128-// which will incur about a 15% speed hit.
129-//
130-// ADDITIONAL DOCUMENTATION
131-//
132-// Immediately after this block comment are a series of sample programs.
133-//
134-// After the sample programs is the "header file" section. This section
135-// includes documentation for each API function.
136-//
137-// Some important concepts to understand to use this library:
138-//
139-// Codepoint
140-// Characters are defined by unicode codepoints, e.g. 65 is
141-// uppercase A, 231 is lowercase c with a cedilla, 0x7e30 is
142-// the hiragana for "ma".
143-//
144-// Glyph
145-// A visual character shape (every codepoint is rendered as
146-// some glyph)
147-//
148-// Glyph index
149-// A font-specific integer ID representing a glyph
150-//
151-// Baseline
152-// Glyph shapes are defined relative to a baseline, which is the
153-// bottom of uppercase characters. Characters extend both above
154-// and below the baseline.
155-//
156-// Current Point
157-// As you draw text to the screen, you keep track of a "current point"
158-// which is the origin of each character. The current point's vertical
159-// position is the baseline. Even "baked fonts" use this model.
160-//
161-// Vertical Font Metrics
162-// The vertical qualities of the font, used to vertically position
163-// and space the characters. See docs for stbtt_GetFontVMetrics.
164-//
165-// Font Size in Pixels or Points
166-// The preferred interface for specifying font sizes in stb_truetype
167-// is to specify how tall the font's vertical extent should be in pixels.
168-// If that sounds good enough, skip the next paragraph.
169-//
170-// Most font APIs instead use "points", which are a common typographic
171-// measurement for describing font size, defined as 72 points per inch.
172-// stb_truetype provides a point API for compatibility. However, true
173-// "per inch" conventions don't make much sense on computer displays
174-// since different monitors have different number of pixels per
175-// inch. For example, Windows traditionally uses a convention that
176-// there are 96 pixels per inch, thus making 'inch' measurements have
177-// nothing to do with inches, and thus effectively defining a point to
178-// be 1.333 pixels. Additionally, the TrueType font data provides
179-// an explicit scale factor to scale a given font's glyphs to points,
180-// but the author has observed that this scale factor is often wrong
181-// for non-commercial fonts, thus making fonts scaled in points
182-// according to the TrueType spec incoherently sized in practice.
183-//
184-// DETAILED USAGE:
185-//
186-// Scale:
187-// Select how high you want the font to be, in points or pixels.
188-// Call ScaleForPixelHeight or ScaleForMappingEmToPixels to compute
189-// a scale factor SF that will be used by all other functions.
190-//
191-// Baseline:
192-// You need to select a y-coordinate that is the baseline of where
193-// your text will appear. Call GetFontBoundingBox to get the baseline-relative
194-// bounding box for all characters. SF*-y0 will be the distance in pixels
195-// that the worst-case character could extend above the baseline, so if
196-// you want the top edge of characters to appear at the top of the
197-// screen where y=0, then you would set the baseline to SF*-y0.
198-//
199-// Current point:
200-// Set the current point where the first character will appear. The
201-// first character could extend left of the current point; this is font
202-// dependent. You can either choose a current point that is the leftmost
203-// point and hope, or add some padding, or check the bounding box or
204-// left-side-bearing of the first character to be displayed and set
205-// the current point based on that.
206-//
207-// Displaying a character:
208-// Compute the bounding box of the character. It will contain signed values
209-// relative to <current_point, baseline>. I.e. if it returns x0,y0,x1,y1,
210-// then the character should be displayed in the rectangle from
211-// <current_point+SF*x0, baseline+SF*y0> to <current_point+SF*x1,baseline+SF*y1).
212-//
213-// Advancing for the next character:
214-// Call GlyphHMetrics, and compute 'current_point += SF * advance'.
215-//
216-//
217-// ADVANCED USAGE
218-//
219-// Quality:
220-//
221-// - Use the functions with Subpixel at the end to allow your characters
222-// to have subpixel positioning. Since the font is anti-aliased, not
223-// hinted, this is very import for quality. (This is not possible with
224-// baked fonts.)
225-//
226-// - Kerning is now supported, and if you're supporting subpixel rendering
227-// then kerning is worth using to give your text a polished look.
228-//
229-// Performance:
230-//
231-// - Convert Unicode codepoints to glyph indexes and operate on the glyphs;
232-// if you don't do this, stb_truetype is forced to do the conversion on
233-// every call.
234-//
235-// - There are a lot of memory allocations. We should modify it to take
236-// a temp buffer and allocate from the temp buffer (without freeing),
237-// should help performance a lot.
238-//
239-// NOTES
240-//
241-// The system uses the raw data found in the .ttf file without changing it
242-// and without building auxiliary data structures. This is a bit inefficient
243-// on little-endian systems (the data is big-endian), but assuming you're
244-// caching the bitmaps or glyph shapes this shouldn't be a big deal.
245-//
246-// It appears to be very hard to programmatically determine what font a
247-// given file is in a general way. I provide an API for this, but I don't
248-// recommend it.
249-//
250-//
251-// SOURCE STATISTICS (based on v0.6c, 2050 LOC)
252-//
253-// Documentation & header file 520 LOC \___ 660 LOC documentation
254-// Sample code 140 LOC /
255-// Truetype parsing 620 LOC ---- 620 LOC TrueType
256-// Software rasterization 240 LOC \.
257-// Curve tessellation 120 LOC \__ 550 LOC Bitmap creation
258-// Bitmap management 100 LOC /
259-// Baked bitmap interface 70 LOC /
260-// Font name matching & access 150 LOC ---- 150
261-// C runtime library abstraction 60 LOC ---- 60
262-//
263-//
264-// PERFORMANCE MEASUREMENTS FOR 1.06:
265-//
266-// 32-bit 64-bit
267-// Previous release: 8.83 s 7.68 s
268-// Pool allocations: 7.72 s 6.34 s
269-// Inline sort : 6.54 s 5.65 s
270-// New rasterizer : 5.63 s 5.00 s
271-
272-//////////////////////////////////////////////////////////////////////////////
273-//////////////////////////////////////////////////////////////////////////////
274-////
275-//// SAMPLE PROGRAMS
276-////
277-//
278-// Incomplete text-in-3d-api example, which draws quads properly aligned to be lossless
279-//
280-#if 0
281-#define STB_TRUETYPE_IMPLEMENTATION // force following include to generate implementation
282-#include "stb_truetype.h"
283-
284-unsigned char ttf_buffer[1<<20];
285-unsigned char temp_bitmap[512*512];
286-
287-stbtt_bakedchar cdata[96]; // ASCII 32..126 is 95 glyphs
288-GLuint ftex;
289-
290-void my_stbtt_initfont(void)
291-{
292- fread(ttf_buffer, 1, 1<<20, fopen("c:/windows/fonts/times.ttf", "rb"));
293- stbtt_BakeFontBitmap(ttf_buffer,0, 32.0, temp_bitmap,512,512, 32,96, cdata); // no guarantee this fits!
294- // can free ttf_buffer at this point
295- glGenTextures(1, &ftex);
296- glBindTexture(GL_TEXTURE_2D, ftex);
297- glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, 512,512, 0, GL_ALPHA, GL_UNSIGNED_BYTE, temp_bitmap);
298- // can free temp_bitmap at this point
299- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
300-}
301-
302-void my_stbtt_print(float x, float y, char *text)
303-{
304- // assume orthographic projection with units = screen pixels, origin at top left
305- glEnable(GL_TEXTURE_2D);
306- glBindTexture(GL_TEXTURE_2D, ftex);
307- glBegin(GL_QUADS);
308- while (*text) {
309- if (*text >= 32 && *text < 128) {
310- stbtt_aligned_quad q;
311- stbtt_GetBakedQuad(cdata, 512,512, *text-32, &x,&y,&q,1);//1=opengl & d3d10+,0=d3d9
312- glTexCoord2f(q.s0,q.t1); glVertex2f(q.x0,q.y0);
313- glTexCoord2f(q.s1,q.t1); glVertex2f(q.x1,q.y0);
314- glTexCoord2f(q.s1,q.t0); glVertex2f(q.x1,q.y1);
315- glTexCoord2f(q.s0,q.t0); glVertex2f(q.x0,q.y1);
316- }
317- ++text;
318- }
319- glEnd();
320-}
321-#endif
322-//
323-//
324-//////////////////////////////////////////////////////////////////////////////
325-//
326-// Complete program (this compiles): get a single bitmap, print as ASCII art
327-//
328-#if 0
329-#include <stdio.h>
330-#define STB_TRUETYPE_IMPLEMENTATION // force following include to generate implementation
331-#include "stb_truetype.h"
332-
333-char ttf_buffer[1<<25];
334-
335-int main(int argc, char **argv)
336-{
337- stbtt_fontinfo font;
338- unsigned char *bitmap;
339- int w,h,i,j,c = (argc > 1 ? atoi(argv[1]) : 'a'), s = (argc > 2 ? atoi(argv[2]) : 20);
340-
341- fread(ttf_buffer, 1, 1<<25, fopen(argc > 3 ? argv[3] : "c:/windows/fonts/arialbd.ttf", "rb"));
342-
343- stbtt_InitFont(&font, ttf_buffer, stbtt_GetFontOffsetForIndex(ttf_buffer,0));
344- bitmap = stbtt_GetCodepointBitmap(&font, 0,stbtt_ScaleForPixelHeight(&font, s), c, &w, &h, 0,0);
345-
346- for (j=0; j < h; ++j) {
347- for (i=0; i < w; ++i)
348- putchar(" .:ioVM@"[bitmap[j*w+i]>>5]);
349- putchar('\n');
350- }
351- return 0;
352-}
353-#endif
354-//
355-// Output:
356-//
357-// .ii.
358-// @@@@@@.
359-// V@Mio@@o
360-// :i. V@V
361-// :oM@@M
362-// :@@@MM@M
363-// @@o o@M
364-// :@@. M@M
365-// @@@o@@@@
366-// :M@@V:@@.
367-//
368-//////////////////////////////////////////////////////////////////////////////
369-//
370-// Complete program: print "Hello World!" banner, with bugs
371-//
372-#if 0
373-char buffer[24<<20];
374-unsigned char screen[20][79];
375-
376-int main(int arg, char **argv)
377-{
378- stbtt_fontinfo font;
379- int i,j,ascent,baseline,ch=0;
380- float scale, xpos=2; // leave a little padding in case the character extends left
381- char *text = "Heljo World!"; // intentionally misspelled to show 'lj' brokenness
382-
383- fread(buffer, 1, 1000000, fopen("c:/windows/fonts/arialbd.ttf", "rb"));
384- stbtt_InitFont(&font, buffer, 0);
385-
386- scale = stbtt_ScaleForPixelHeight(&font, 15);
387- stbtt_GetFontVMetrics(&font, &ascent,0,0);
388- baseline = (int) (ascent*scale);
389-
390- while (text[ch]) {
391- int advance,lsb,x0,y0,x1,y1;
392- float x_shift = xpos - (float) floor(xpos);
393- stbtt_GetCodepointHMetrics(&font, text[ch], &advance, &lsb);
394- stbtt_GetCodepointBitmapBoxSubpixel(&font, text[ch], scale,scale,x_shift,0, &x0,&y0,&x1,&y1);
395- stbtt_MakeCodepointBitmapSubpixel(&font, &screen[baseline + y0][(int) xpos + x0], x1-x0,y1-y0, 79, scale,scale,x_shift,0, text[ch]);
396- // note that this stomps the old data, so where character boxes overlap (e.g. 'lj') it's wrong
397- // because this API is really for baking character bitmaps into textures. if you want to render
398- // a sequence of characters, you really need to render each bitmap to a temp buffer, then
399- // "alpha blend" that into the working buffer
400- xpos += (advance * scale);
401- if (text[ch+1])
402- xpos += scale*stbtt_GetCodepointKernAdvance(&font, text[ch],text[ch+1]);
403- ++ch;
404- }
405-
406- for (j=0; j < 20; ++j) {
407- for (i=0; i < 78; ++i)
408- putchar(" .:ioVM@"[screen[j][i]>>5]);
409- putchar('\n');
410- }
411-
412- return 0;
413-}
414-#endif
415-
416-
417-//////////////////////////////////////////////////////////////////////////////
418-//////////////////////////////////////////////////////////////////////////////
419-////
420-//// INTEGRATION WITH YOUR CODEBASE
421-////
422-//// The following sections allow you to supply alternate definitions
423-//// of C library functions used by stb_truetype, e.g. if you don't
424-//// link with the C runtime library.
425-
426-#ifdef STB_TRUETYPE_IMPLEMENTATION
427- // #define your own (u)stbtt_int8/16/32 before including to override this
428- #ifndef stbtt_uint8
429- typedef unsigned char stbtt_uint8;
430- typedef signed char stbtt_int8;
431- typedef unsigned short stbtt_uint16;
432- typedef signed short stbtt_int16;
433- typedef unsigned int stbtt_uint32;
434- typedef signed int stbtt_int32;
435- #endif
436-
437- typedef char stbtt__check_size32[sizeof(stbtt_int32)==4 ? 1 : -1];
438- typedef char stbtt__check_size16[sizeof(stbtt_int16)==2 ? 1 : -1];
439-
440- // e.g. #define your own STBTT_ifloor/STBTT_iceil() to avoid math.h
441- #ifndef STBTT_ifloor
442- #include <math.h>
443- #define STBTT_ifloor(x) ((int) floor(x))
444- #define STBTT_iceil(x) ((int) ceil(x))
445- #endif
446-
447- #ifndef STBTT_sqrt
448- #include <math.h>
449- #define STBTT_sqrt(x) sqrt(x)
450- #define STBTT_pow(x,y) pow(x,y)
451- #endif
452-
453- #ifndef STBTT_fmod
454- #include <math.h>
455- #define STBTT_fmod(x,y) fmod(x,y)
456- #endif
457-
458- #ifndef STBTT_cos
459- #include <math.h>
460- #define STBTT_cos(x) cos(x)
461- #define STBTT_acos(x) acos(x)
462- #endif
463-
464- #ifndef STBTT_fabs
465- #include <math.h>
466- #define STBTT_fabs(x) fabs(x)
467- #endif
468-
469- // #define your own functions "STBTT_malloc" / "STBTT_free" to avoid malloc.h
470- #ifndef STBTT_malloc
471- #include <stdlib.h>
472- #define STBTT_malloc(x,u) ((void)(u),malloc(x))
473- #define STBTT_free(x,u) ((void)(u),free(x))
474- #endif
475-
476- #ifndef STBTT_assert
477- #include <assert.h>
478- #define STBTT_assert(x) assert(x)
479- #endif
480-
481- #ifndef STBTT_strlen
482- #include <string.h>
483- #define STBTT_strlen(x) strlen(x)
484- #endif
485-
486- #ifndef STBTT_memcpy
487- #include <string.h>
488- #define STBTT_memcpy memcpy
489- #define STBTT_memset memset
490- #endif
491-#endif
492-
493-///////////////////////////////////////////////////////////////////////////////
494-///////////////////////////////////////////////////////////////////////////////
495-////
496-//// INTERFACE
497-////
498-////
499-
500-#ifndef __STB_INCLUDE_STB_TRUETYPE_H__
501-#define __STB_INCLUDE_STB_TRUETYPE_H__
502-
503-#ifdef STBTT_STATIC
504-#define STBTT_DEF static
505-#else
506-#define STBTT_DEF extern
507-#endif
508-
509-#ifdef __cplusplus
510-extern "C" {
511-#endif
512-
513-// private structure
514-typedef struct
515-{
516- unsigned char *data;
517- int cursor;
518- int size;
519-} stbtt__buf;
520-
521-//////////////////////////////////////////////////////////////////////////////
522-//
523-// TEXTURE BAKING API
524-//
525-// If you use this API, you only have to call two functions ever.
526-//
527-
528-typedef struct
529-{
530- unsigned short x0,y0,x1,y1; // coordinates of bbox in bitmap
531- float xoff,yoff,xadvance;
532-} stbtt_bakedchar;
533-
534-STBTT_DEF int stbtt_BakeFontBitmap(const unsigned char *data, int offset, // font location (use offset=0 for plain .ttf)
535- float pixel_height, // height of font in pixels
536- unsigned char *pixels, int pw, int ph, // bitmap to be filled in
537- int first_char, int num_chars, // characters to bake
538- stbtt_bakedchar *chardata); // you allocate this, it's num_chars long
539-// if return is positive, the first unused row of the bitmap
540-// if return is negative, returns the negative of the number of characters that fit
541-// if return is 0, no characters fit and no rows were used
542-// This uses a very crappy packing.
543-
544-typedef struct
545-{
546- float x0,y0,s0,t0; // top-left
547- float x1,y1,s1,t1; // bottom-right
548-} stbtt_aligned_quad;
549-
550-STBTT_DEF void stbtt_GetBakedQuad(const stbtt_bakedchar *chardata, int pw, int ph, // same data as above
551- int char_index, // character to display
552- float *xpos, float *ypos, // pointers to current position in screen pixel space
553- stbtt_aligned_quad *q, // output: quad to draw
554- int opengl_fillrule); // true if opengl fill rule; false if DX9 or earlier
555-// Call GetBakedQuad with char_index = 'character - first_char', and it
556-// creates the quad you need to draw and advances the current position.
557-//
558-// The coordinate system used assumes y increases downwards.
559-//
560-// Characters will extend both above and below the current position;
561-// see discussion of "BASELINE" above.
562-//
563-// It's inefficient; you might want to c&p it and optimize it.
564-
565-STBTT_DEF void stbtt_GetScaledFontVMetrics(const unsigned char *fontdata, int index, float size, float *ascent, float *descent, float *lineGap);
566-// Query the font vertical metrics without having to create a font first.
567-
568-
569-//////////////////////////////////////////////////////////////////////////////
570-//
571-// NEW TEXTURE BAKING API
572-//
573-// This provides options for packing multiple fonts into one atlas, not
574-// perfectly but better than nothing.
575-
576-typedef struct
577-{
578- unsigned short x0,y0,x1,y1; // coordinates of bbox in bitmap
579- float xoff,yoff,xadvance;
580- float xoff2,yoff2;
581-} stbtt_packedchar;
582-
583-typedef struct stbtt_pack_context stbtt_pack_context;
584-typedef struct stbtt_fontinfo stbtt_fontinfo;
585-#ifndef STB_RECT_PACK_VERSION
586-typedef struct stbrp_rect stbrp_rect;
587-#endif
588-
589-STBTT_DEF int stbtt_PackBegin(stbtt_pack_context *spc, unsigned char *pixels, int width, int height, int stride_in_bytes, int padding, void *alloc_context);
590-// Initializes a packing context stored in the passed-in stbtt_pack_context.
591-// Future calls using this context will pack characters into the bitmap passed
592-// in here: a 1-channel bitmap that is width * height. stride_in_bytes is
593-// the distance from one row to the next (or 0 to mean they are packed tightly
594-// together). "padding" is the amount of padding to leave between each
595-// character (normally you want '1' for bitmaps you'll use as textures with
596-// bilinear filtering).
597-//
598-// Returns 0 on failure, 1 on success.
599-
600-STBTT_DEF void stbtt_PackEnd (stbtt_pack_context *spc);
601-// Cleans up the packing context and frees all memory.
602-
603-#define STBTT_POINT_SIZE(x) (-(x))
604-
605-STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, float font_size,
606- int first_unicode_char_in_range, int num_chars_in_range, stbtt_packedchar *chardata_for_range);
607-// Creates character bitmaps from the font_index'th font found in fontdata (use
608-// font_index=0 if you don't know what that is). It creates num_chars_in_range
609-// bitmaps for characters with unicode values starting at first_unicode_char_in_range
610-// and increasing. Data for how to render them is stored in chardata_for_range;
611-// pass these to stbtt_GetPackedQuad to get back renderable quads.
612-//
613-// font_size is the full height of the character from ascender to descender,
614-// as computed by stbtt_ScaleForPixelHeight. To use a point size as computed
615-// by stbtt_ScaleForMappingEmToPixels, wrap the point size in STBTT_POINT_SIZE()
616-// and pass that result as 'font_size':
617-// ..., 20 , ... // font max minus min y is 20 pixels tall
618-// ..., STBTT_POINT_SIZE(20), ... // 'M' is 20 pixels tall
619-
620-typedef struct
621-{
622- float font_size;
623- int first_unicode_codepoint_in_range; // if non-zero, then the chars are continuous, and this is the first codepoint
624- int *array_of_unicode_codepoints; // if non-zero, then this is an array of unicode codepoints
625- int num_chars;
626- stbtt_packedchar *chardata_for_range; // output
627- unsigned char h_oversample, v_oversample; // don't set these, they're used internally
628-} stbtt_pack_range;
629-
630-STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges);
631-// Creates character bitmaps from multiple ranges of characters stored in
632-// ranges. This will usually create a better-packed bitmap than multiple
633-// calls to stbtt_PackFontRange. Note that you can call this multiple
634-// times within a single PackBegin/PackEnd.
635-
636-STBTT_DEF void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h_oversample, unsigned int v_oversample);
637-// Oversampling a font increases the quality by allowing higher-quality subpixel
638-// positioning, and is especially valuable at smaller text sizes.
639-//
640-// This function sets the amount of oversampling for all following calls to
641-// stbtt_PackFontRange(s) or stbtt_PackFontRangesGatherRects for a given
642-// pack context. The default (no oversampling) is achieved by h_oversample=1
643-// and v_oversample=1. The total number of pixels required is
644-// h_oversample*v_oversample larger than the default; for example, 2x2
645-// oversampling requires 4x the storage of 1x1. For best results, render
646-// oversampled textures with bilinear filtering. Look at the readme in
647-// stb/tests/oversample for information about oversampled fonts
648-//
649-// To use with PackFontRangesGather etc., you must set it before calls
650-// call to PackFontRangesGatherRects.
651-
652-STBTT_DEF void stbtt_PackSetSkipMissingCodepoints(stbtt_pack_context *spc, int skip);
653-// If skip != 0, this tells stb_truetype to skip any codepoints for which
654-// there is no corresponding glyph. If skip=0, which is the default, then
655-// codepoints without a glyph recived the font's "missing character" glyph,
656-// typically an empty box by convention.
657-
658-STBTT_DEF void stbtt_GetPackedQuad(const stbtt_packedchar *chardata, int pw, int ph, // same data as above
659- int char_index, // character to display
660- float *xpos, float *ypos, // pointers to current position in screen pixel space
661- stbtt_aligned_quad *q, // output: quad to draw
662- int align_to_integer);
663-
664-STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects);
665-STBTT_DEF void stbtt_PackFontRangesPackRects(stbtt_pack_context *spc, stbrp_rect *rects, int num_rects);
666-STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects);
667-// Calling these functions in sequence is roughly equivalent to calling
668-// stbtt_PackFontRanges(). If you more control over the packing of multiple
669-// fonts, or if you want to pack custom data into a font texture, take a look
670-// at the source to of stbtt_PackFontRanges() and create a custom version
671-// using these functions, e.g. call GatherRects multiple times,
672-// building up a single array of rects, then call PackRects once,
673-// then call RenderIntoRects repeatedly. This may result in a
674-// better packing than calling PackFontRanges multiple times
675-// (or it may not).
676-
677-// this is an opaque structure that you shouldn't mess with which holds
678-// all the context needed from PackBegin to PackEnd.
679-struct stbtt_pack_context {
680- void *user_allocator_context;
681- void *pack_info;
682- int width;
683- int height;
684- int stride_in_bytes;
685- int padding;
686- int skip_missing;
687- unsigned int h_oversample, v_oversample;
688- unsigned char *pixels;
689- void *nodes;
690-};
691-
692-//////////////////////////////////////////////////////////////////////////////
693-//
694-// FONT LOADING
695-//
696-//
697-
698-STBTT_DEF int stbtt_GetNumberOfFonts(const unsigned char *data);
699-// This function will determine the number of fonts in a font file. TrueType
700-// collection (.ttc) files may contain multiple fonts, while TrueType font
701-// (.ttf) files only contain one font. The number of fonts can be used for
702-// indexing with the previous function where the index is between zero and one
703-// less than the total fonts. If an error occurs, -1 is returned.
704-
705-STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index);
706-// Each .ttf/.ttc file may have more than one font. Each font has a sequential
707-// index number starting from 0. Call this function to get the font offset for
708-// a given index; it returns -1 if the index is out of range. A regular .ttf
709-// file will only define one font and it always be at offset 0, so it will
710-// return '0' for index 0, and -1 for all other indices.
711-
712-// The following structure is defined publicly so you can declare one on
713-// the stack or as a global or etc, but you should treat it as opaque.
714-struct stbtt_fontinfo
715-{
716- void * userdata;
717- unsigned char * data; // pointer to .ttf file
718- int fontstart; // offset of start of font
719-
720- int numGlyphs; // number of glyphs, needed for range checking
721-
722- int loca,head,glyf,hhea,hmtx,kern,gpos; // table locations as offset from start of .ttf
723- int index_map; // a cmap mapping for our chosen character encoding
724- int indexToLocFormat; // format needed to map from glyph index to glyph
725-
726- stbtt__buf cff; // cff font data
727- stbtt__buf charstrings; // the charstring index
728- stbtt__buf gsubrs; // global charstring subroutines index
729- stbtt__buf subrs; // private charstring subroutines index
730- stbtt__buf fontdicts; // array of font dicts
731- stbtt__buf fdselect; // map from glyph to fontdict
732-};
733-
734-STBTT_DEF int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data, int offset);
735-// Given an offset into the file that defines a font, this function builds
736-// the necessary cached info for the rest of the system. You must allocate
737-// the stbtt_fontinfo yourself, and stbtt_InitFont will fill it out. You don't
738-// need to do anything special to free it, because the contents are pure
739-// value data with no additional data structures. Returns 0 on failure.
740-
741-
742-//////////////////////////////////////////////////////////////////////////////
743-//
744-// CHARACTER TO GLYPH-INDEX CONVERSIOn
745-
746-STBTT_DEF int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codepoint);
747-// If you're going to perform multiple operations on the same character
748-// and you want a speed-up, call this function with the character you're
749-// going to process, then use glyph-based functions instead of the
750-// codepoint-based functions.
751-// Returns 0 if the character codepoint is not defined in the font.
752-
753-
754-//////////////////////////////////////////////////////////////////////////////
755-//
756-// CHARACTER PROPERTIES
757-//
758-
759-STBTT_DEF float stbtt_ScaleForPixelHeight(const stbtt_fontinfo *info, float pixels);
760-// computes a scale factor to produce a font whose "height" is 'pixels' tall.
761-// Height is measured as the distance from the highest ascender to the lowest
762-// descender; in other words, it's equivalent to calling stbtt_GetFontVMetrics
763-// and computing:
764-// scale = pixels / (ascent - descent)
765-// so if you prefer to measure height by the ascent only, use a similar calculation.
766-
767-STBTT_DEF float stbtt_ScaleForMappingEmToPixels(const stbtt_fontinfo *info, float pixels);
768-// computes a scale factor to produce a font whose EM size is mapped to
769-// 'pixels' tall. This is probably what traditional APIs compute, but
770-// I'm not positive.
771-
772-STBTT_DEF void stbtt_GetFontVMetrics(const stbtt_fontinfo *info, int *ascent, int *descent, int *lineGap);
773-// ascent is the coordinate above the baseline the font extends; descent
774-// is the coordinate below the baseline the font extends (i.e. it is typically negative)
775-// lineGap is the spacing between one row's descent and the next row's ascent...
776-// so you should advance the vertical position by "*ascent - *descent + *lineGap"
777-// these are expressed in unscaled coordinates, so you must multiply by
778-// the scale factor for a given size
779-
780-STBTT_DEF int stbtt_GetFontVMetricsOS2(const stbtt_fontinfo *info, int *typoAscent, int *typoDescent, int *typoLineGap);
781-// analogous to GetFontVMetrics, but returns the "typographic" values from the OS/2
782-// table (specific to MS/Windows TTF files).
783-//
784-// Returns 1 on success (table present), 0 on failure.
785-
786-STBTT_DEF void stbtt_GetFontBoundingBox(const stbtt_fontinfo *info, int *x0, int *y0, int *x1, int *y1);
787-// the bounding box around all possible characters
788-
789-STBTT_DEF void stbtt_GetCodepointHMetrics(const stbtt_fontinfo *info, int codepoint, int *advanceWidth, int *leftSideBearing);
790-// leftSideBearing is the offset from the current horizontal position to the left edge of the character
791-// advanceWidth is the offset from the current horizontal position to the next horizontal position
792-// these are expressed in unscaled coordinates
793-
794-STBTT_DEF int stbtt_GetCodepointKernAdvance(const stbtt_fontinfo *info, int ch1, int ch2);
795-// an additional amount to add to the 'advance' value between ch1 and ch2
796-
797-STBTT_DEF int stbtt_GetCodepointBox(const stbtt_fontinfo *info, int codepoint, int *x0, int *y0, int *x1, int *y1);
798-// Gets the bounding box of the visible part of the glyph, in unscaled coordinates
799-
800-STBTT_DEF void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_index, int *advanceWidth, int *leftSideBearing);
801-STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2);
802-STBTT_DEF int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1);
803-// as above, but takes one or more glyph indices for greater efficiency
804-
805-
806-//////////////////////////////////////////////////////////////////////////////
807-//
808-// GLYPH SHAPES (you probably don't need these, but they have to go before
809-// the bitmaps for C declaration-order reasons)
810-//
811-
812-#ifndef STBTT_vmove // you can predefine these to use different values (but why?)
813- enum {
814- STBTT_vmove=1,
815- STBTT_vline,
816- STBTT_vcurve,
817- STBTT_vcubic
818- };
819-#endif
820-
821-#ifndef stbtt_vertex // you can predefine this to use different values
822- // (we share this with other code at RAD)
823- #define stbtt_vertex_type short // can't use stbtt_int16 because that's not visible in the header file
824- typedef struct
825- {
826- stbtt_vertex_type x,y,cx,cy,cx1,cy1;
827- unsigned char type,padding;
828- } stbtt_vertex;
829-#endif
830-
831-STBTT_DEF int stbtt_IsGlyphEmpty(const stbtt_fontinfo *info, int glyph_index);
832-// returns non-zero if nothing is drawn for this glyph
833-
834-STBTT_DEF int stbtt_GetCodepointShape(const stbtt_fontinfo *info, int unicode_codepoint, stbtt_vertex **vertices);
835-STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **vertices);
836-// returns # of vertices and fills *vertices with the pointer to them
837-// these are expressed in "unscaled" coordinates
838-//
839-// The shape is a series of contours. Each one starts with
840-// a STBTT_moveto, then consists of a series of mixed
841-// STBTT_lineto and STBTT_curveto segments. A lineto
842-// draws a line from previous endpoint to its x,y; a curveto
843-// draws a quadratic bezier from previous endpoint to
844-// its x,y, using cx,cy as the bezier control point.
845-
846-STBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *vertices);
847-// frees the data allocated above
848-
849-//////////////////////////////////////////////////////////////////////////////
850-//
851-// BITMAP RENDERING
852-//
853-
854-STBTT_DEF void stbtt_FreeBitmap(unsigned char *bitmap, void *userdata);
855-// frees the bitmap allocated below
856-
857-STBTT_DEF unsigned char *stbtt_GetCodepointBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int codepoint, int *width, int *height, int *xoff, int *yoff);
858-// allocates a large-enough single-channel 8bpp bitmap and renders the
859-// specified character/glyph at the specified scale into it, with
860-// antialiasing. 0 is no coverage (transparent), 255 is fully covered (opaque).
861-// *width & *height are filled out with the width & height of the bitmap,
862-// which is stored left-to-right, top-to-bottom.
863-//
864-// xoff/yoff are the offset it pixel space from the glyph origin to the top-left of the bitmap
865-
866-STBTT_DEF 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);
867-// the same as stbtt_GetCodepoitnBitmap, but you can specify a subpixel
868-// shift for the character
869-
870-STBTT_DEF 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);
871-// the same as stbtt_GetCodepointBitmap, but you pass in storage for the bitmap
872-// in the form of 'output', with row spacing of 'out_stride' bytes. the bitmap
873-// is clipped to out_w/out_h bytes. Call stbtt_GetCodepointBitmapBox to get the
874-// width and height and positioning info for it first.
875-
876-STBTT_DEF 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);
877-// same as stbtt_MakeCodepointBitmap, but you can specify a subpixel
878-// shift for the character
879-
880-STBTT_DEF void stbtt_MakeCodepointBitmapSubpixelPrefilter(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 oversample_x, int oversample_y, float *sub_x, float *sub_y, int codepoint);
881-// same as stbtt_MakeCodepointBitmapSubpixel, but prefiltering
882-// is performed (see stbtt_PackSetOversampling)
883-
884-STBTT_DEF void stbtt_GetCodepointBitmapBox(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1);
885-// get the bbox of the bitmap centered around the glyph origin; so the
886-// bitmap width is ix1-ix0, height is iy1-iy0, and location to place
887-// the bitmap top left is (leftSideBearing*scale,iy0).
888-// (Note that the bitmap uses y-increases-down, but the shape uses
889-// y-increases-up, so CodepointBitmapBox and CodepointBox are inverted.)
890-
891-STBTT_DEF 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);
892-// same as stbtt_GetCodepointBitmapBox, but you can specify a subpixel
893-// shift for the character
894-
895-// the following functions are equivalent to the above functions, but operate
896-// on glyph indices instead of Unicode codepoints (for efficiency)
897-STBTT_DEF unsigned char *stbtt_GetGlyphBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int glyph, int *width, int *height, int *xoff, int *yoff);
898-STBTT_DEF 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);
899-STBTT_DEF 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);
900-STBTT_DEF 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);
901-STBTT_DEF void stbtt_MakeGlyphBitmapSubpixelPrefilter(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 oversample_x, int oversample_y, float *sub_x, float *sub_y, int glyph);
902-STBTT_DEF void stbtt_GetGlyphBitmapBox(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1);
903-STBTT_DEF 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);
904-
905-
906-// @TODO: don't expose this structure
907-typedef struct
908-{
909- int w,h,stride;
910- unsigned char *pixels;
911-} stbtt__bitmap;
912-
913-// rasterize a shape with quadratic beziers into a bitmap
914-STBTT_DEF void stbtt_Rasterize(stbtt__bitmap *result, // 1-channel bitmap to draw into
915- float flatness_in_pixels, // allowable error of curve in pixels
916- stbtt_vertex *vertices, // array of vertices defining shape
917- int num_verts, // number of vertices in above array
918- float scale_x, float scale_y, // scale applied to input vertices
919- float shift_x, float shift_y, // translation applied to input vertices
920- int x_off, int y_off, // another translation applied to input
921- int invert, // if non-zero, vertically flip shape
922- void *userdata); // context for to STBTT_MALLOC
923-
924-//////////////////////////////////////////////////////////////////////////////
925-//
926-// Signed Distance Function (or Field) rendering
927-
928-STBTT_DEF void stbtt_FreeSDF(unsigned char *bitmap, void *userdata);
929-// frees the SDF bitmap allocated below
930-
931-STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float scale, int glyph, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff);
932-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);
933-// These functions compute a discretized SDF field for a single character, suitable for storing
934-// in a single-channel texture, sampling with bilinear filtering, and testing against
935-// larger than some threshold to produce scalable fonts.
936-// info -- the font
937-// scale -- controls the size of the resulting SDF bitmap, same as it would be creating a regular bitmap
938-// glyph/codepoint -- the character to generate the SDF for
939-// padding -- extra "pixels" around the character which are filled with the distance to the character (not 0),
940-// which allows effects like bit outlines
941-// onedge_value -- value 0-255 to test the SDF against to reconstruct the character (i.e. the isocontour of the character)
942-// pixel_dist_scale -- what value the SDF should increase by when moving one SDF "pixel" away from the edge (on the 0..255 scale)
943-// if positive, > onedge_value is inside; if negative, < onedge_value is inside
944-// width,height -- output height & width of the SDF bitmap (including padding)
945-// xoff,yoff -- output origin of the character
946-// return value -- a 2D array of bytes 0..255, width*height in size
947-//
948-// pixel_dist_scale & onedge_value are a scale & bias that allows you to make
949-// optimal use of the limited 0..255 for your application, trading off precision
950-// and special effects. SDF values outside the range 0..255 are clamped to 0..255.
951-//
952-// Example:
953-// scale = stbtt_ScaleForPixelHeight(22)
954-// padding = 5
955-// onedge_value = 180
956-// pixel_dist_scale = 180/5.0 = 36.0
957-//
958-// This will create an SDF bitmap in which the character is about 22 pixels
959-// high but the whole bitmap is about 22+5+5=32 pixels high. To produce a filled
960-// shape, sample the SDF at each pixel and fill the pixel if the SDF value
961-// is greater than or equal to 180/255. (You'll actually want to antialias,
962-// which is beyond the scope of this example.) Additionally, you can compute
963-// offset outlines (e.g. to stroke the character border inside & outside,
964-// or only outside). For example, to fill outside the character up to 3 SDF
965-// pixels, you would compare against (180-36.0*3)/255 = 72/255. The above
966-// choice of variables maps a range from 5 pixels outside the shape to
967-// 2 pixels inside the shape to 0..255; this is intended primarily for apply
968-// outside effects only (the interior range is needed to allow proper
969-// antialiasing of the font at *smaller* sizes)
970-//
971-// The function computes the SDF analytically at each SDF pixel, not by e.g.
972-// building a higher-res bitmap and approximating it. In theory the quality
973-// should be as high as possible for an SDF of this size & representation, but
974-// unclear if this is true in practice (perhaps building a higher-res bitmap
975-// and computing from that can allow drop-out prevention).
976-//
977-// The algorithm has not been optimized at all, so expect it to be slow
978-// if computing lots of characters or very large sizes.
979-
980-
981-
982-//////////////////////////////////////////////////////////////////////////////
983-//
984-// Finding the right font...
985-//
986-// You should really just solve this offline, keep your own tables
987-// of what font is what, and don't try to get it out of the .ttf file.
988-// That's because getting it out of the .ttf file is really hard, because
989-// the names in the file can appear in many possible encodings, in many
990-// possible languages, and e.g. if you need a case-insensitive comparison,
991-// the details of that depend on the encoding & language in a complex way
992-// (actually underspecified in truetype, but also gigantic).
993-//
994-// But you can use the provided functions in two possible ways:
995-// stbtt_FindMatchingFont() will use *case-sensitive* comparisons on
996-// unicode-encoded names to try to find the font you want;
997-// you can run this before calling stbtt_InitFont()
998-//
999-// stbtt_GetFontNameString() lets you get any of the various strings
1000-// from the file yourself and do your own comparisons on them.
1001-// You have to have called stbtt_InitFont() first.
1002-
1003-
1004-STBTT_DEF int stbtt_FindMatchingFont(const unsigned char *fontdata, const char *name, int flags);
1005-// returns the offset (not index) of the font that matches, or -1 if none
1006-// if you use STBTT_MACSTYLE_DONTCARE, use a font name like "Arial Bold".
1007-// if you use any other flag, use a font name like "Arial"; this checks
1008-// the 'macStyle' header field; i don't know if fonts set this consistently
1009-#define STBTT_MACSTYLE_DONTCARE 0
1010-#define STBTT_MACSTYLE_BOLD 1
1011-#define STBTT_MACSTYLE_ITALIC 2
1012-#define STBTT_MACSTYLE_UNDERSCORE 4
1013-#define STBTT_MACSTYLE_NONE 8 // <= not same as 0, this makes us check the bitfield is 0
1014-
1015-STBTT_DEF int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const char *s2, int len2);
1016-// returns 1/0 whether the first string interpreted as utf8 is identical to
1017-// the second string interpreted as big-endian utf16... useful for strings from next func
1018-
1019-STBTT_DEF const char *stbtt_GetFontNameString(const stbtt_fontinfo *font, int *length, int platformID, int encodingID, int languageID, int nameID);
1020-// returns the string (which may be big-endian double byte, e.g. for unicode)
1021-// and puts the length in bytes in *length.
1022-//
1023-// some of the values for the IDs are below; for more see the truetype spec:
1024-// http://developer.apple.com/textfonts/TTRefMan/RM06/Chap6name.html
1025-// http://www.microsoft.com/typography/otspec/name.htm
1026-
1027-enum { // platformID
1028- STBTT_PLATFORM_ID_UNICODE =0,
1029- STBTT_PLATFORM_ID_MAC =1,
1030- STBTT_PLATFORM_ID_ISO =2,
1031- STBTT_PLATFORM_ID_MICROSOFT =3
1032-};
1033-
1034-enum { // encodingID for STBTT_PLATFORM_ID_UNICODE
1035- STBTT_UNICODE_EID_UNICODE_1_0 =0,
1036- STBTT_UNICODE_EID_UNICODE_1_1 =1,
1037- STBTT_UNICODE_EID_ISO_10646 =2,
1038- STBTT_UNICODE_EID_UNICODE_2_0_BMP=3,
1039- STBTT_UNICODE_EID_UNICODE_2_0_FULL=4
1040-};
1041-
1042-enum { // encodingID for STBTT_PLATFORM_ID_MICROSOFT
1043- STBTT_MS_EID_SYMBOL =0,
1044- STBTT_MS_EID_UNICODE_BMP =1,
1045- STBTT_MS_EID_SHIFTJIS =2,
1046- STBTT_MS_EID_UNICODE_FULL =10
1047-};
1048-
1049-enum { // encodingID for STBTT_PLATFORM_ID_MAC; same as Script Manager codes
1050- STBTT_MAC_EID_ROMAN =0, STBTT_MAC_EID_ARABIC =4,
1051- STBTT_MAC_EID_JAPANESE =1, STBTT_MAC_EID_HEBREW =5,
1052- STBTT_MAC_EID_CHINESE_TRAD =2, STBTT_MAC_EID_GREEK =6,
1053- STBTT_MAC_EID_KOREAN =3, STBTT_MAC_EID_RUSSIAN =7
1054-};
1055-
1056-enum { // languageID for STBTT_PLATFORM_ID_MICROSOFT; same as LCID...
1057- // problematic because there are e.g. 16 english LCIDs and 16 arabic LCIDs
1058- STBTT_MS_LANG_ENGLISH =0x0409, STBTT_MS_LANG_ITALIAN =0x0410,
1059- STBTT_MS_LANG_CHINESE =0x0804, STBTT_MS_LANG_JAPANESE =0x0411,
1060- STBTT_MS_LANG_DUTCH =0x0413, STBTT_MS_LANG_KOREAN =0x0412,
1061- STBTT_MS_LANG_FRENCH =0x040c, STBTT_MS_LANG_RUSSIAN =0x0419,
1062- STBTT_MS_LANG_GERMAN =0x0407, STBTT_MS_LANG_SPANISH =0x0409,
1063- STBTT_MS_LANG_HEBREW =0x040d, STBTT_MS_LANG_SWEDISH =0x041D
1064-};
1065-
1066-enum { // languageID for STBTT_PLATFORM_ID_MAC
1067- STBTT_MAC_LANG_ENGLISH =0 , STBTT_MAC_LANG_JAPANESE =11,
1068- STBTT_MAC_LANG_ARABIC =12, STBTT_MAC_LANG_KOREAN =23,
1069- STBTT_MAC_LANG_DUTCH =4 , STBTT_MAC_LANG_RUSSIAN =32,
1070- STBTT_MAC_LANG_FRENCH =1 , STBTT_MAC_LANG_SPANISH =6 ,
1071- STBTT_MAC_LANG_GERMAN =2 , STBTT_MAC_LANG_SWEDISH =5 ,
1072- STBTT_MAC_LANG_HEBREW =10, STBTT_MAC_LANG_CHINESE_SIMPLIFIED =33,
1073- STBTT_MAC_LANG_ITALIAN =3 , STBTT_MAC_LANG_CHINESE_TRAD =19
1074-};
1075-
1076-#ifdef __cplusplus
1077-}
1078-#endif
1079-
1080-#endif // __STB_INCLUDE_STB_TRUETYPE_H__
1081-
1082-///////////////////////////////////////////////////////////////////////////////
1083-///////////////////////////////////////////////////////////////////////////////
1084-////
1085-//// IMPLEMENTATION
1086-////
1087-////
1088-
1089-#ifdef STB_TRUETYPE_IMPLEMENTATION
1090-
1091-#ifndef STBTT_MAX_OVERSAMPLE
1092-#define STBTT_MAX_OVERSAMPLE 8
1093-#endif
1094-
1095-#if STBTT_MAX_OVERSAMPLE > 255
1096-#error "STBTT_MAX_OVERSAMPLE cannot be > 255"
1097-#endif
1098-
1099-typedef int stbtt__test_oversample_pow2[(STBTT_MAX_OVERSAMPLE & (STBTT_MAX_OVERSAMPLE-1)) == 0 ? 1 : -1];
1100-
1101-#ifndef STBTT_RASTERIZER_VERSION
1102-#define STBTT_RASTERIZER_VERSION 2
1103-#endif
1104-
1105-#ifdef _MSC_VER
1106-#define STBTT__NOTUSED(v) (void)(v)
1107-#else
1108-#define STBTT__NOTUSED(v) (void)sizeof(v)
1109-#endif
1110-
1111-//////////////////////////////////////////////////////////////////////////
1112-//
1113-// stbtt__buf helpers to parse data from file
1114-//
1115-
1116-static stbtt_uint8 stbtt__buf_get8(stbtt__buf *b)
1117-{
1118- if (b->cursor >= b->size)
1119- return 0;
1120- return b->data[b->cursor++];
1121-}
1122-
1123-static stbtt_uint8 stbtt__buf_peek8(stbtt__buf *b)
1124-{
1125- if (b->cursor >= b->size)
1126- return 0;
1127- return b->data[b->cursor];
1128-}
1129-
1130-static void stbtt__buf_seek(stbtt__buf *b, int o)
1131-{
1132- STBTT_assert(!(o > b->size || o < 0));
1133- b->cursor = (o > b->size || o < 0) ? b->size : o;
1134-}
1135-
1136-static void stbtt__buf_skip(stbtt__buf *b, int o)
1137-{
1138- stbtt__buf_seek(b, b->cursor + o);
1139-}
1140-
1141-static stbtt_uint32 stbtt__buf_get(stbtt__buf *b, int n)
1142-{
1143- stbtt_uint32 v = 0;
1144- int i;
1145- STBTT_assert(n >= 1 && n <= 4);
1146- for (i = 0; i < n; i++)
1147- v = (v << 8) | stbtt__buf_get8(b);
1148- return v;
1149-}
1150-
1151-static stbtt__buf stbtt__new_buf(const void *p, size_t size)
1152-{
1153- stbtt__buf r;
1154- STBTT_assert(size < 0x40000000);
1155- r.data = (stbtt_uint8*) p;
1156- r.size = (int) size;
1157- r.cursor = 0;
1158- return r;
1159-}
1160-
1161-#define stbtt__buf_get16(b) stbtt__buf_get((b), 2)
1162-#define stbtt__buf_get32(b) stbtt__buf_get((b), 4)
1163-
1164-static stbtt__buf stbtt__buf_range(const stbtt__buf *b, int o, int s)
1165-{
1166- stbtt__buf r = stbtt__new_buf(NULL, 0);
1167- if (o < 0 || s < 0 || o > b->size || s > b->size - o) return r;
1168- r.data = b->data + o;
1169- r.size = s;
1170- return r;
1171-}
1172-
1173-static stbtt__buf stbtt__cff_get_index(stbtt__buf *b)
1174-{
1175- int count, start, offsize;
1176- start = b->cursor;
1177- count = stbtt__buf_get16(b);
1178- if (count) {
1179- offsize = stbtt__buf_get8(b);
1180- STBTT_assert(offsize >= 1 && offsize <= 4);
1181- stbtt__buf_skip(b, offsize * count);
1182- stbtt__buf_skip(b, stbtt__buf_get(b, offsize) - 1);
1183- }
1184- return stbtt__buf_range(b, start, b->cursor - start);
1185-}
1186-
1187-static stbtt_uint32 stbtt__cff_int(stbtt__buf *b)
1188-{
1189- int b0 = stbtt__buf_get8(b);
1190- if (b0 >= 32 && b0 <= 246) return b0 - 139;
1191- else if (b0 >= 247 && b0 <= 250) return (b0 - 247)*256 + stbtt__buf_get8(b) + 108;
1192- else if (b0 >= 251 && b0 <= 254) return -(b0 - 251)*256 - stbtt__buf_get8(b) - 108;
1193- else if (b0 == 28) return stbtt__buf_get16(b);
1194- else if (b0 == 29) return stbtt__buf_get32(b);
1195- STBTT_assert(0);
1196- return 0;
1197-}
1198-
1199-static void stbtt__cff_skip_operand(stbtt__buf *b) {
1200- int v, b0 = stbtt__buf_peek8(b);
1201- STBTT_assert(b0 >= 28);
1202- if (b0 == 30) {
1203- stbtt__buf_skip(b, 1);
1204- while (b->cursor < b->size) {
1205- v = stbtt__buf_get8(b);
1206- if ((v & 0xF) == 0xF || (v >> 4) == 0xF)
1207- break;
1208- }
1209- } else {
1210- stbtt__cff_int(b);
1211- }
1212-}
1213-
1214-static stbtt__buf stbtt__dict_get(stbtt__buf *b, int key)
1215-{
1216- stbtt__buf_seek(b, 0);
1217- while (b->cursor < b->size) {
1218- int start = b->cursor, end, op;
1219- while (stbtt__buf_peek8(b) >= 28)
1220- stbtt__cff_skip_operand(b);
1221- end = b->cursor;
1222- op = stbtt__buf_get8(b);
1223- if (op == 12) op = stbtt__buf_get8(b) | 0x100;
1224- if (op == key) return stbtt__buf_range(b, start, end-start);
1225- }
1226- return stbtt__buf_range(b, 0, 0);
1227-}
1228-
1229-static void stbtt__dict_get_ints(stbtt__buf *b, int key, int outcount, stbtt_uint32 *out)
1230-{
1231- int i;
1232- stbtt__buf operands = stbtt__dict_get(b, key);
1233- for (i = 0; i < outcount && operands.cursor < operands.size; i++)
1234- out[i] = stbtt__cff_int(&operands);
1235-}
1236-
1237-static int stbtt__cff_index_count(stbtt__buf *b)
1238-{
1239- stbtt__buf_seek(b, 0);
1240- return stbtt__buf_get16(b);
1241-}
1242-
1243-static stbtt__buf stbtt__cff_index_get(stbtt__buf b, int i)
1244-{
1245- int count, offsize, start, end;
1246- stbtt__buf_seek(&b, 0);
1247- count = stbtt__buf_get16(&b);
1248- offsize = stbtt__buf_get8(&b);
1249- STBTT_assert(i >= 0 && i < count);
1250- STBTT_assert(offsize >= 1 && offsize <= 4);
1251- stbtt__buf_skip(&b, i*offsize);
1252- start = stbtt__buf_get(&b, offsize);
1253- end = stbtt__buf_get(&b, offsize);
1254- return stbtt__buf_range(&b, 2+(count+1)*offsize+start, end - start);
1255-}
1256-
1257-//////////////////////////////////////////////////////////////////////////
1258-//
1259-// accessors to parse data from file
1260-//
1261-
1262-// on platforms that don't allow misaligned reads, if we want to allow
1263-// truetype fonts that aren't padded to alignment, define ALLOW_UNALIGNED_TRUETYPE
1264-
1265-#define ttBYTE(p) (* (stbtt_uint8 *) (p))
1266-#define ttCHAR(p) (* (stbtt_int8 *) (p))
1267-#define ttFixed(p) ttLONG(p)
1268-
1269-static stbtt_uint16 ttUSHORT(stbtt_uint8 *p) { return p[0]*256 + p[1]; }
1270-static stbtt_int16 ttSHORT(stbtt_uint8 *p) { return p[0]*256 + p[1]; }
1271-static stbtt_uint32 ttULONG(stbtt_uint8 *p) { return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; }
1272-static stbtt_int32 ttLONG(stbtt_uint8 *p) { return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; }
1273-
1274-#define stbtt_tag4(p,c0,c1,c2,c3) ((p)[0] == (c0) && (p)[1] == (c1) && (p)[2] == (c2) && (p)[3] == (c3))
1275-#define stbtt_tag(p,str) stbtt_tag4(p,str[0],str[1],str[2],str[3])
1276-
1277-static int stbtt__isfont(stbtt_uint8 *font)
1278-{
1279- // check the version number
1280- if (stbtt_tag4(font, '1',0,0,0)) return 1; // TrueType 1
1281- if (stbtt_tag(font, "typ1")) return 1; // TrueType with type 1 font -- we don't support this!
1282- if (stbtt_tag(font, "OTTO")) return 1; // OpenType with CFF
1283- if (stbtt_tag4(font, 0,1,0,0)) return 1; // OpenType 1.0
1284- if (stbtt_tag(font, "true")) return 1; // Apple specification for TrueType fonts
1285- return 0;
1286-}
1287-
1288-// @OPTIMIZE: binary search
1289-static stbtt_uint32 stbtt__find_table(stbtt_uint8 *data, stbtt_uint32 fontstart, const char *tag)
1290-{
1291- stbtt_int32 num_tables = ttUSHORT(data+fontstart+4);
1292- stbtt_uint32 tabledir = fontstart + 12;
1293- stbtt_int32 i;
1294- for (i=0; i < num_tables; ++i) {
1295- stbtt_uint32 loc = tabledir + 16*i;
1296- if (stbtt_tag(data+loc+0, tag))
1297- return ttULONG(data+loc+8);
1298- }
1299- return 0;
1300-}
1301-
1302-static int stbtt_GetFontOffsetForIndex_internal(unsigned char *font_collection, int index)
1303-{
1304- // if it's just a font, there's only one valid index
1305- if (stbtt__isfont(font_collection))
1306- return index == 0 ? 0 : -1;
1307-
1308- // check if it's a TTC
1309- if (stbtt_tag(font_collection, "ttcf")) {
1310- // version 1?
1311- if (ttULONG(font_collection+4) == 0x00010000 || ttULONG(font_collection+4) == 0x00020000) {
1312- stbtt_int32 n = ttLONG(font_collection+8);
1313- if (index >= n)
1314- return -1;
1315- return ttULONG(font_collection+12+index*4);
1316- }
1317- }
1318- return -1;
1319-}
1320-
1321-static int stbtt_GetNumberOfFonts_internal(unsigned char *font_collection)
1322-{
1323- // if it's just a font, there's only one valid font
1324- if (stbtt__isfont(font_collection))
1325- return 1;
1326-
1327- // check if it's a TTC
1328- if (stbtt_tag(font_collection, "ttcf")) {
1329- // version 1?
1330- if (ttULONG(font_collection+4) == 0x00010000 || ttULONG(font_collection+4) == 0x00020000) {
1331- return ttLONG(font_collection+8);
1332- }
1333- }
1334- return 0;
1335-}
1336-
1337-static stbtt__buf stbtt__get_subrs(stbtt__buf cff, stbtt__buf fontdict)
1338-{
1339- stbtt_uint32 subrsoff = 0, private_loc[2] = { 0, 0 };
1340- stbtt__buf pdict;
1341- stbtt__dict_get_ints(&fontdict, 18, 2, private_loc);
1342- if (!private_loc[1] || !private_loc[0]) return stbtt__new_buf(NULL, 0);
1343- pdict = stbtt__buf_range(&cff, private_loc[1], private_loc[0]);
1344- stbtt__dict_get_ints(&pdict, 19, 1, &subrsoff);
1345- if (!subrsoff) return stbtt__new_buf(NULL, 0);
1346- stbtt__buf_seek(&cff, private_loc[1]+subrsoff);
1347- return stbtt__cff_get_index(&cff);
1348-}
1349-
1350-static int stbtt_InitFont_internal(stbtt_fontinfo *info, unsigned char *data, int fontstart)
1351-{
1352- stbtt_uint32 cmap, t;
1353- stbtt_int32 i,numTables;
1354-
1355- info->data = data;
1356- info->fontstart = fontstart;
1357- info->cff = stbtt__new_buf(NULL, 0);
1358-
1359- cmap = stbtt__find_table(data, fontstart, "cmap"); // required
1360- info->loca = stbtt__find_table(data, fontstart, "loca"); // required
1361- info->head = stbtt__find_table(data, fontstart, "head"); // required
1362- info->glyf = stbtt__find_table(data, fontstart, "glyf"); // required
1363- info->hhea = stbtt__find_table(data, fontstart, "hhea"); // required
1364- info->hmtx = stbtt__find_table(data, fontstart, "hmtx"); // required
1365- info->kern = stbtt__find_table(data, fontstart, "kern"); // not required
1366- info->gpos = stbtt__find_table(data, fontstart, "GPOS"); // not required
1367-
1368- if (!cmap || !info->head || !info->hhea || !info->hmtx)
1369- return 0;
1370- if (info->glyf) {
1371- // required for truetype
1372- if (!info->loca) return 0;
1373- } else {
1374- // initialization for CFF / Type2 fonts (OTF)
1375- stbtt__buf b, topdict, topdictidx;
1376- stbtt_uint32 cstype = 2, charstrings = 0, fdarrayoff = 0, fdselectoff = 0;
1377- stbtt_uint32 cff;
1378-
1379- cff = stbtt__find_table(data, fontstart, "CFF ");
1380- if (!cff) return 0;
1381-
1382- info->fontdicts = stbtt__new_buf(NULL, 0);
1383- info->fdselect = stbtt__new_buf(NULL, 0);
1384-
1385- // @TODO this should use size from table (not 512MB)
1386- info->cff = stbtt__new_buf(data+cff, 512*1024*1024);
1387- b = info->cff;
1388-
1389- // read the header
1390- stbtt__buf_skip(&b, 2);
1391- stbtt__buf_seek(&b, stbtt__buf_get8(&b)); // hdrsize
1392-
1393- // @TODO the name INDEX could list multiple fonts,
1394- // but we just use the first one.
1395- stbtt__cff_get_index(&b); // name INDEX
1396- topdictidx = stbtt__cff_get_index(&b);
1397- topdict = stbtt__cff_index_get(topdictidx, 0);
1398- stbtt__cff_get_index(&b); // string INDEX
1399- info->gsubrs = stbtt__cff_get_index(&b);
1400-
1401- stbtt__dict_get_ints(&topdict, 17, 1, &charstrings);
1402- stbtt__dict_get_ints(&topdict, 0x100 | 6, 1, &cstype);
1403- stbtt__dict_get_ints(&topdict, 0x100 | 36, 1, &fdarrayoff);
1404- stbtt__dict_get_ints(&topdict, 0x100 | 37, 1, &fdselectoff);
1405- info->subrs = stbtt__get_subrs(b, topdict);
1406-
1407- // we only support Type 2 charstrings
1408- if (cstype != 2) return 0;
1409- if (charstrings == 0) return 0;
1410-
1411- if (fdarrayoff) {
1412- // looks like a CID font
1413- if (!fdselectoff) return 0;
1414- stbtt__buf_seek(&b, fdarrayoff);
1415- info->fontdicts = stbtt__cff_get_index(&b);
1416- info->fdselect = stbtt__buf_range(&b, fdselectoff, b.size-fdselectoff);
1417- }
1418-
1419- stbtt__buf_seek(&b, charstrings);
1420- info->charstrings = stbtt__cff_get_index(&b);
1421- }
1422-
1423- t = stbtt__find_table(data, fontstart, "maxp");
1424- if (t)
1425- info->numGlyphs = ttUSHORT(data+t+4);
1426- else
1427- info->numGlyphs = 0xffff;
1428-
1429- // find a cmap encoding table we understand *now* to avoid searching
1430- // later. (todo: could make this installable)
1431- // the same regardless of glyph.
1432- numTables = ttUSHORT(data + cmap + 2);
1433- info->index_map = 0;
1434- for (i=0; i < numTables; ++i) {
1435- stbtt_uint32 encoding_record = cmap + 4 + 8 * i;
1436- // find an encoding we understand:
1437- switch(ttUSHORT(data+encoding_record)) {
1438- case STBTT_PLATFORM_ID_MICROSOFT:
1439- switch (ttUSHORT(data+encoding_record+2)) {
1440- case STBTT_MS_EID_UNICODE_BMP:
1441- case STBTT_MS_EID_UNICODE_FULL:
1442- // MS/Unicode
1443- info->index_map = cmap + ttULONG(data+encoding_record+4);
1444- break;
1445- }
1446- break;
1447- case STBTT_PLATFORM_ID_UNICODE:
1448- // Mac/iOS has these
1449- // all the encodingIDs are unicode, so we don't bother to check it
1450- info->index_map = cmap + ttULONG(data+encoding_record+4);
1451- break;
1452- }
1453- }
1454- if (info->index_map == 0)
1455- return 0;
1456-
1457- info->indexToLocFormat = ttUSHORT(data+info->head + 50);
1458- return 1;
1459-}
1460-
1461-STBTT_DEF int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codepoint)
1462-{
1463- stbtt_uint8 *data = info->data;
1464- stbtt_uint32 index_map = info->index_map;
1465-
1466- stbtt_uint16 format = ttUSHORT(data + index_map + 0);
1467- if (format == 0) { // apple byte encoding
1468- stbtt_int32 bytes = ttUSHORT(data + index_map + 2);
1469- if (unicode_codepoint < bytes-6)
1470- return ttBYTE(data + index_map + 6 + unicode_codepoint);
1471- return 0;
1472- } else if (format == 6) {
1473- stbtt_uint32 first = ttUSHORT(data + index_map + 6);
1474- stbtt_uint32 count = ttUSHORT(data + index_map + 8);
1475- if ((stbtt_uint32) unicode_codepoint >= first && (stbtt_uint32) unicode_codepoint < first+count)
1476- return ttUSHORT(data + index_map + 10 + (unicode_codepoint - first)*2);
1477- return 0;
1478- } else if (format == 2) {
1479- STBTT_assert(0); // @TODO: high-byte mapping for japanese/chinese/korean
1480- return 0;
1481- } else if (format == 4) { // standard mapping for windows fonts: binary search collection of ranges
1482- stbtt_uint16 segcount = ttUSHORT(data+index_map+6) >> 1;
1483- stbtt_uint16 searchRange = ttUSHORT(data+index_map+8) >> 1;
1484- stbtt_uint16 entrySelector = ttUSHORT(data+index_map+10);
1485- stbtt_uint16 rangeShift = ttUSHORT(data+index_map+12) >> 1;
1486-
1487- // do a binary search of the segments
1488- stbtt_uint32 endCount = index_map + 14;
1489- stbtt_uint32 search = endCount;
1490-
1491- if (unicode_codepoint > 0xffff)
1492- return 0;
1493-
1494- // they lie from endCount .. endCount + segCount
1495- // but searchRange is the nearest power of two, so...
1496- if (unicode_codepoint >= ttUSHORT(data + search + rangeShift*2))
1497- search += rangeShift*2;
1498-
1499- // now decrement to bias correctly to find smallest
1500- search -= 2;
1501- while (entrySelector) {
1502- stbtt_uint16 end;
1503- searchRange >>= 1;
1504- end = ttUSHORT(data + search + searchRange*2);
1505- if (unicode_codepoint > end)
1506- search += searchRange*2;
1507- --entrySelector;
1508- }
1509- search += 2;
1510-
1511- {
1512- stbtt_uint16 offset, start;
1513- stbtt_uint16 item = (stbtt_uint16) ((search - endCount) >> 1);
1514-
1515- STBTT_assert(unicode_codepoint <= ttUSHORT(data + endCount + 2*item));
1516- start = ttUSHORT(data + index_map + 14 + segcount*2 + 2 + 2*item);
1517- if (unicode_codepoint < start)
1518- return 0;
1519-
1520- offset = ttUSHORT(data + index_map + 14 + segcount*6 + 2 + 2*item);
1521- if (offset == 0)
1522- return (stbtt_uint16) (unicode_codepoint + ttSHORT(data + index_map + 14 + segcount*4 + 2 + 2*item));
1523-
1524- return ttUSHORT(data + offset + (unicode_codepoint-start)*2 + index_map + 14 + segcount*6 + 2 + 2*item);
1525- }
1526- } else if (format == 12 || format == 13) {
1527- stbtt_uint32 ngroups = ttULONG(data+index_map+12);
1528- stbtt_int32 low,high;
1529- low = 0; high = (stbtt_int32)ngroups;
1530- // Binary search the right group.
1531- while (low < high) {
1532- stbtt_int32 mid = low + ((high-low) >> 1); // rounds down, so low <= mid < high
1533- stbtt_uint32 start_char = ttULONG(data+index_map+16+mid*12);
1534- stbtt_uint32 end_char = ttULONG(data+index_map+16+mid*12+4);
1535- if ((stbtt_uint32) unicode_codepoint < start_char)
1536- high = mid;
1537- else if ((stbtt_uint32) unicode_codepoint > end_char)
1538- low = mid+1;
1539- else {
1540- stbtt_uint32 start_glyph = ttULONG(data+index_map+16+mid*12+8);
1541- if (format == 12)
1542- return start_glyph + unicode_codepoint-start_char;
1543- else // format == 13
1544- return start_glyph;
1545- }
1546- }
1547- return 0; // not found
1548- }
1549- // @TODO
1550- STBTT_assert(0);
1551- return 0;
1552-}
1553-
1554-STBTT_DEF int stbtt_GetCodepointShape(const stbtt_fontinfo *info, int unicode_codepoint, stbtt_vertex **vertices)
1555-{
1556- return stbtt_GetGlyphShape(info, stbtt_FindGlyphIndex(info, unicode_codepoint), vertices);
1557-}
1558-
1559-static void stbtt_setvertex(stbtt_vertex *v, stbtt_uint8 type, stbtt_int32 x, stbtt_int32 y, stbtt_int32 cx, stbtt_int32 cy)
1560-{
1561- v->type = type;
1562- v->x = (stbtt_int16) x;
1563- v->y = (stbtt_int16) y;
1564- v->cx = (stbtt_int16) cx;
1565- v->cy = (stbtt_int16) cy;
1566-}
1567-
1568-static int stbtt__GetGlyfOffset(const stbtt_fontinfo *info, int glyph_index)
1569-{
1570- int g1,g2;
1571-
1572- STBTT_assert(!info->cff.size);
1573-
1574- if (glyph_index >= info->numGlyphs) return -1; // glyph index out of range
1575- if (info->indexToLocFormat >= 2) return -1; // unknown index->glyph map format
1576-
1577- if (info->indexToLocFormat == 0) {
1578- g1 = info->glyf + ttUSHORT(info->data + info->loca + glyph_index * 2) * 2;
1579- g2 = info->glyf + ttUSHORT(info->data + info->loca + glyph_index * 2 + 2) * 2;
1580- } else {
1581- g1 = info->glyf + ttULONG (info->data + info->loca + glyph_index * 4);
1582- g2 = info->glyf + ttULONG (info->data + info->loca + glyph_index * 4 + 4);
1583- }
1584-
1585- return g1==g2 ? -1 : g1; // if length is 0, return -1
1586-}
1587-
1588-static int stbtt__GetGlyphInfoT2(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1);
1589-
1590-STBTT_DEF int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1)
1591-{
1592- if (info->cff.size) {
1593- stbtt__GetGlyphInfoT2(info, glyph_index, x0, y0, x1, y1);
1594- } else {
1595- int g = stbtt__GetGlyfOffset(info, glyph_index);
1596- if (g < 0) return 0;
1597-
1598- if (x0) *x0 = ttSHORT(info->data + g + 2);
1599- if (y0) *y0 = ttSHORT(info->data + g + 4);
1600- if (x1) *x1 = ttSHORT(info->data + g + 6);
1601- if (y1) *y1 = ttSHORT(info->data + g + 8);
1602- }
1603- return 1;
1604-}
1605-
1606-STBTT_DEF int stbtt_GetCodepointBox(const stbtt_fontinfo *info, int codepoint, int *x0, int *y0, int *x1, int *y1)
1607-{
1608- return stbtt_GetGlyphBox(info, stbtt_FindGlyphIndex(info,codepoint), x0,y0,x1,y1);
1609-}
1610-
1611-STBTT_DEF int stbtt_IsGlyphEmpty(const stbtt_fontinfo *info, int glyph_index)
1612-{
1613- stbtt_int16 numberOfContours;
1614- int g;
1615- if (info->cff.size)
1616- return stbtt__GetGlyphInfoT2(info, glyph_index, NULL, NULL, NULL, NULL) == 0;
1617- g = stbtt__GetGlyfOffset(info, glyph_index);
1618- if (g < 0) return 1;
1619- numberOfContours = ttSHORT(info->data + g);
1620- return numberOfContours == 0;
1621-}
1622-
1623-static int stbtt__close_shape(stbtt_vertex *vertices, int num_vertices, int was_off, int start_off,
1624- stbtt_int32 sx, stbtt_int32 sy, stbtt_int32 scx, stbtt_int32 scy, stbtt_int32 cx, stbtt_int32 cy)
1625-{
1626- if (start_off) {
1627- if (was_off)
1628- stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, (cx+scx)>>1, (cy+scy)>>1, cx,cy);
1629- stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, sx,sy,scx,scy);
1630- } else {
1631- if (was_off)
1632- stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve,sx,sy,cx,cy);
1633- else
1634- stbtt_setvertex(&vertices[num_vertices++], STBTT_vline,sx,sy,0,0);
1635- }
1636- return num_vertices;
1637-}
1638-
1639-static int stbtt__GetGlyphShapeTT(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices)
1640-{
1641- stbtt_int16 numberOfContours;
1642- stbtt_uint8 *endPtsOfContours;
1643- stbtt_uint8 *data = info->data;
1644- stbtt_vertex *vertices=0;
1645- int num_vertices=0;
1646- int g = stbtt__GetGlyfOffset(info, glyph_index);
1647-
1648- *pvertices = NULL;
1649-
1650- if (g < 0) return 0;
1651-
1652- numberOfContours = ttSHORT(data + g);
1653-
1654- if (numberOfContours > 0) {
1655- stbtt_uint8 flags=0,flagcount;
1656- stbtt_int32 ins, i,j=0,m,n, next_move, was_off=0, off, start_off=0;
1657- stbtt_int32 x,y,cx,cy,sx,sy, scx,scy;
1658- stbtt_uint8 *points;
1659- endPtsOfContours = (data + g + 10);
1660- ins = ttUSHORT(data + g + 10 + numberOfContours * 2);
1661- points = data + g + 10 + numberOfContours * 2 + 2 + ins;
1662-
1663- n = 1+ttUSHORT(endPtsOfContours + numberOfContours*2-2);
1664-
1665- m = n + 2*numberOfContours; // a loose bound on how many vertices we might need
1666- vertices = (stbtt_vertex *) STBTT_malloc(m * sizeof(vertices[0]), info->userdata);
1667- if (vertices == 0)
1668- return 0;
1669-
1670- next_move = 0;
1671- flagcount=0;
1672-
1673- // in first pass, we load uninterpreted data into the allocated array
1674- // above, shifted to the end of the array so we won't overwrite it when
1675- // we create our final data starting from the front
1676-
1677- off = m - n; // starting offset for uninterpreted data, regardless of how m ends up being calculated
1678-
1679- // first load flags
1680-
1681- for (i=0; i < n; ++i) {
1682- if (flagcount == 0) {
1683- flags = *points++;
1684- if (flags & 8)
1685- flagcount = *points++;
1686- } else
1687- --flagcount;
1688- vertices[off+i].type = flags;
1689- }
1690-
1691- // now load x coordinates
1692- x=0;
1693- for (i=0; i < n; ++i) {
1694- flags = vertices[off+i].type;
1695- if (flags & 2) {
1696- stbtt_int16 dx = *points++;
1697- x += (flags & 16) ? dx : -dx; // ???
1698- } else {
1699- if (!(flags & 16)) {
1700- x = x + (stbtt_int16) (points[0]*256 + points[1]);
1701- points += 2;
1702- }
1703- }
1704- vertices[off+i].x = (stbtt_int16) x;
1705- }
1706-
1707- // now load y coordinates
1708- y=0;
1709- for (i=0; i < n; ++i) {
1710- flags = vertices[off+i].type;
1711- if (flags & 4) {
1712- stbtt_int16 dy = *points++;
1713- y += (flags & 32) ? dy : -dy; // ???
1714- } else {
1715- if (!(flags & 32)) {
1716- y = y + (stbtt_int16) (points[0]*256 + points[1]);
1717- points += 2;
1718- }
1719- }
1720- vertices[off+i].y = (stbtt_int16) y;
1721- }
1722-
1723- // now convert them to our format
1724- num_vertices=0;
1725- sx = sy = cx = cy = scx = scy = 0;
1726- for (i=0; i < n; ++i) {
1727- flags = vertices[off+i].type;
1728- x = (stbtt_int16) vertices[off+i].x;
1729- y = (stbtt_int16) vertices[off+i].y;
1730-
1731- if (next_move == i) {
1732- if (i != 0)
1733- num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy);
1734-
1735- // now start the new one
1736- start_off = !(flags & 1);
1737- if (start_off) {
1738- // if we start off with an off-curve point, then when we need to find a point on the curve
1739- // where we can start, and we need to save some state for when we wraparound.
1740- scx = x;
1741- scy = y;
1742- if (!(vertices[off+i+1].type & 1)) {
1743- // next point is also a curve point, so interpolate an on-point curve
1744- sx = (x + (stbtt_int32) vertices[off+i+1].x) >> 1;
1745- sy = (y + (stbtt_int32) vertices[off+i+1].y) >> 1;
1746- } else {
1747- // otherwise just use the next point as our start point
1748- sx = (stbtt_int32) vertices[off+i+1].x;
1749- sy = (stbtt_int32) vertices[off+i+1].y;
1750- ++i; // we're using point i+1 as the starting point, so skip it
1751- }
1752- } else {
1753- sx = x;
1754- sy = y;
1755- }
1756- stbtt_setvertex(&vertices[num_vertices++], STBTT_vmove,sx,sy,0,0);
1757- was_off = 0;
1758- next_move = 1 + ttUSHORT(endPtsOfContours+j*2);
1759- ++j;
1760- } else {
1761- if (!(flags & 1)) { // if it's a curve
1762- if (was_off) // two off-curve control points in a row means interpolate an on-curve midpoint
1763- stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, (cx+x)>>1, (cy+y)>>1, cx, cy);
1764- cx = x;
1765- cy = y;
1766- was_off = 1;
1767- } else {
1768- if (was_off)
1769- stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, x,y, cx, cy);
1770- else
1771- stbtt_setvertex(&vertices[num_vertices++], STBTT_vline, x,y,0,0);
1772- was_off = 0;
1773- }
1774- }
1775- }
1776- num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy);
1777- } else if (numberOfContours == -1) {
1778- // Compound shapes.
1779- int more = 1;
1780- stbtt_uint8 *comp = data + g + 10;
1781- num_vertices = 0;
1782- vertices = 0;
1783- while (more) {
1784- stbtt_uint16 flags, gidx;
1785- int comp_num_verts = 0, i;
1786- stbtt_vertex *comp_verts = 0, *tmp = 0;
1787- float mtx[6] = {1,0,0,1,0,0}, m, n;
1788-
1789- flags = ttSHORT(comp); comp+=2;
1790- gidx = ttSHORT(comp); comp+=2;
1791-
1792- if (flags & 2) { // XY values
1793- if (flags & 1) { // shorts
1794- mtx[4] = ttSHORT(comp); comp+=2;
1795- mtx[5] = ttSHORT(comp); comp+=2;
1796- } else {
1797- mtx[4] = ttCHAR(comp); comp+=1;
1798- mtx[5] = ttCHAR(comp); comp+=1;
1799- }
1800- }
1801- else {
1802- // @TODO handle matching point
1803- STBTT_assert(0);
1804- }
1805- if (flags & (1<<3)) { // WE_HAVE_A_SCALE
1806- mtx[0] = mtx[3] = ttSHORT(comp)/16384.0f; comp+=2;
1807- mtx[1] = mtx[2] = 0;
1808- } else if (flags & (1<<6)) { // WE_HAVE_AN_X_AND_YSCALE
1809- mtx[0] = ttSHORT(comp)/16384.0f; comp+=2;
1810- mtx[1] = mtx[2] = 0;
1811- mtx[3] = ttSHORT(comp)/16384.0f; comp+=2;
1812- } else if (flags & (1<<7)) { // WE_HAVE_A_TWO_BY_TWO
1813- mtx[0] = ttSHORT(comp)/16384.0f; comp+=2;
1814- mtx[1] = ttSHORT(comp)/16384.0f; comp+=2;
1815- mtx[2] = ttSHORT(comp)/16384.0f; comp+=2;
1816- mtx[3] = ttSHORT(comp)/16384.0f; comp+=2;
1817- }
1818-
1819- // Find transformation scales.
1820- m = (float) STBTT_sqrt(mtx[0]*mtx[0] + mtx[1]*mtx[1]);
1821- n = (float) STBTT_sqrt(mtx[2]*mtx[2] + mtx[3]*mtx[3]);
1822-
1823- // Get indexed glyph.
1824- comp_num_verts = stbtt_GetGlyphShape(info, gidx, &comp_verts);
1825- if (comp_num_verts > 0) {
1826- // Transform vertices.
1827- for (i = 0; i < comp_num_verts; ++i) {
1828- stbtt_vertex* v = &comp_verts[i];
1829- stbtt_vertex_type x,y;
1830- x=v->x; y=v->y;
1831- v->x = (stbtt_vertex_type)(m * (mtx[0]*x + mtx[2]*y + mtx[4]));
1832- v->y = (stbtt_vertex_type)(n * (mtx[1]*x + mtx[3]*y + mtx[5]));
1833- x=v->cx; y=v->cy;
1834- v->cx = (stbtt_vertex_type)(m * (mtx[0]*x + mtx[2]*y + mtx[4]));
1835- v->cy = (stbtt_vertex_type)(n * (mtx[1]*x + mtx[3]*y + mtx[5]));
1836- }
1837- // Append vertices.
1838- tmp = (stbtt_vertex*)STBTT_malloc((num_vertices+comp_num_verts)*sizeof(stbtt_vertex), info->userdata);
1839- if (!tmp) {
1840- if (vertices) STBTT_free(vertices, info->userdata);
1841- if (comp_verts) STBTT_free(comp_verts, info->userdata);
1842- return 0;
1843- }
1844- if (num_vertices > 0) STBTT_memcpy(tmp, vertices, num_vertices*sizeof(stbtt_vertex)); //-V595
1845- STBTT_memcpy(tmp+num_vertices, comp_verts, comp_num_verts*sizeof(stbtt_vertex));
1846- if (vertices) STBTT_free(vertices, info->userdata);
1847- vertices = tmp;
1848- STBTT_free(comp_verts, info->userdata);
1849- num_vertices += comp_num_verts;
1850- }
1851- // More components ?
1852- more = flags & (1<<5);
1853- }
1854- } else if (numberOfContours < 0) {
1855- // @TODO other compound variations?
1856- STBTT_assert(0);
1857- } else {
1858- // numberOfCounters == 0, do nothing
1859- }
1860-
1861- *pvertices = vertices;
1862- return num_vertices;
1863-}
1864-
1865-typedef struct
1866-{
1867- int bounds;
1868- int started;
1869- float first_x, first_y;
1870- float x, y;
1871- stbtt_int32 min_x, max_x, min_y, max_y;
1872-
1873- stbtt_vertex *pvertices;
1874- int num_vertices;
1875-} stbtt__csctx;
1876-
1877-#define STBTT__CSCTX_INIT(bounds) {bounds,0, 0,0, 0,0, 0,0,0,0, NULL, 0}
1878-
1879-static void stbtt__track_vertex(stbtt__csctx *c, stbtt_int32 x, stbtt_int32 y)
1880-{
1881- if (x > c->max_x || !c->started) c->max_x = x;
1882- if (y > c->max_y || !c->started) c->max_y = y;
1883- if (x < c->min_x || !c->started) c->min_x = x;
1884- if (y < c->min_y || !c->started) c->min_y = y;
1885- c->started = 1;
1886-}
1887-
1888-static void stbtt__csctx_v(stbtt__csctx *c, stbtt_uint8 type, stbtt_int32 x, stbtt_int32 y, stbtt_int32 cx, stbtt_int32 cy, stbtt_int32 cx1, stbtt_int32 cy1)
1889-{
1890- if (c->bounds) {
1891- stbtt__track_vertex(c, x, y);
1892- if (type == STBTT_vcubic) {
1893- stbtt__track_vertex(c, cx, cy);
1894- stbtt__track_vertex(c, cx1, cy1);
1895- }
1896- } else {
1897- stbtt_setvertex(&c->pvertices[c->num_vertices], type, x, y, cx, cy);
1898- c->pvertices[c->num_vertices].cx1 = (stbtt_int16) cx1;
1899- c->pvertices[c->num_vertices].cy1 = (stbtt_int16) cy1;
1900- }
1901- c->num_vertices++;
1902-}
1903-
1904-static void stbtt__csctx_close_shape(stbtt__csctx *ctx)
1905-{
1906- if (ctx->first_x != ctx->x || ctx->first_y != ctx->y)
1907- stbtt__csctx_v(ctx, STBTT_vline, (int)ctx->first_x, (int)ctx->first_y, 0, 0, 0, 0);
1908-}
1909-
1910-static void stbtt__csctx_rmove_to(stbtt__csctx *ctx, float dx, float dy)
1911-{
1912- stbtt__csctx_close_shape(ctx);
1913- ctx->first_x = ctx->x = ctx->x + dx;
1914- ctx->first_y = ctx->y = ctx->y + dy;
1915- stbtt__csctx_v(ctx, STBTT_vmove, (int)ctx->x, (int)ctx->y, 0, 0, 0, 0);
1916-}
1917-
1918-static void stbtt__csctx_rline_to(stbtt__csctx *ctx, float dx, float dy)
1919-{
1920- ctx->x += dx;
1921- ctx->y += dy;
1922- stbtt__csctx_v(ctx, STBTT_vline, (int)ctx->x, (int)ctx->y, 0, 0, 0, 0);
1923-}
1924-
1925-static void stbtt__csctx_rccurve_to(stbtt__csctx *ctx, float dx1, float dy1, float dx2, float dy2, float dx3, float dy3)
1926-{
1927- float cx1 = ctx->x + dx1;
1928- float cy1 = ctx->y + dy1;
1929- float cx2 = cx1 + dx2;
1930- float cy2 = cy1 + dy2;
1931- ctx->x = cx2 + dx3;
1932- ctx->y = cy2 + dy3;
1933- stbtt__csctx_v(ctx, STBTT_vcubic, (int)ctx->x, (int)ctx->y, (int)cx1, (int)cy1, (int)cx2, (int)cy2);
1934-}
1935-
1936-static stbtt__buf stbtt__get_subr(stbtt__buf idx, int n)
1937-{
1938- int count = stbtt__cff_index_count(&idx);
1939- int bias = 107;
1940- if (count >= 33900)
1941- bias = 32768;
1942- else if (count >= 1240)
1943- bias = 1131;
1944- n += bias;
1945- if (n < 0 || n >= count)
1946- return stbtt__new_buf(NULL, 0);
1947- return stbtt__cff_index_get(idx, n);
1948-}
1949-
1950-static stbtt__buf stbtt__cid_get_glyph_subrs(const stbtt_fontinfo *info, int glyph_index)
1951-{
1952- stbtt__buf fdselect = info->fdselect;
1953- int nranges, start, end, v, fmt, fdselector = -1, i;
1954-
1955- stbtt__buf_seek(&fdselect, 0);
1956- fmt = stbtt__buf_get8(&fdselect);
1957- if (fmt == 0) {
1958- // untested
1959- stbtt__buf_skip(&fdselect, glyph_index);
1960- fdselector = stbtt__buf_get8(&fdselect);
1961- } else if (fmt == 3) {
1962- nranges = stbtt__buf_get16(&fdselect);
1963- start = stbtt__buf_get16(&fdselect);
1964- for (i = 0; i < nranges; i++) {
1965- v = stbtt__buf_get8(&fdselect);
1966- end = stbtt__buf_get16(&fdselect);
1967- if (glyph_index >= start && glyph_index < end) {
1968- fdselector = v;
1969- break;
1970- }
1971- start = end;
1972- }
1973- }
1974- if (fdselector == -1) stbtt__new_buf(NULL, 0);
1975- return stbtt__get_subrs(info->cff, stbtt__cff_index_get(info->fontdicts, fdselector));
1976-}
1977-
1978-static int stbtt__run_charstring(const stbtt_fontinfo *info, int glyph_index, stbtt__csctx *c)
1979-{
1980- int in_header = 1, maskbits = 0, subr_stack_height = 0, sp = 0, v, i, b0;
1981- int has_subrs = 0, clear_stack;
1982- float s[48];
1983- stbtt__buf subr_stack[10], subrs = info->subrs, b;
1984- float f;
1985-
1986-#define STBTT__CSERR(s) (0)
1987-
1988- // this currently ignores the initial width value, which isn't needed if we have hmtx
1989- b = stbtt__cff_index_get(info->charstrings, glyph_index);
1990- while (b.cursor < b.size) {
1991- i = 0;
1992- clear_stack = 1;
1993- b0 = stbtt__buf_get8(&b);
1994- switch (b0) {
1995- // @TODO implement hinting
1996- case 0x13: // hintmask
1997- case 0x14: // cntrmask
1998- if (in_header)
1999- maskbits += (sp / 2); // implicit "vstem"
2000- in_header = 0;
2001- stbtt__buf_skip(&b, (maskbits + 7) / 8);
2002- break;
2003-
2004- case 0x01: // hstem
2005- case 0x03: // vstem
2006- case 0x12: // hstemhm
2007- case 0x17: // vstemhm
2008- maskbits += (sp / 2);
2009- break;
2010-
2011- case 0x15: // rmoveto
2012- in_header = 0;
2013- if (sp < 2) return STBTT__CSERR("rmoveto stack");
2014- stbtt__csctx_rmove_to(c, s[sp-2], s[sp-1]);
2015- break;
2016- case 0x04: // vmoveto
2017- in_header = 0;
2018- if (sp < 1) return STBTT__CSERR("vmoveto stack");
2019- stbtt__csctx_rmove_to(c, 0, s[sp-1]);
2020- break;
2021- case 0x16: // hmoveto
2022- in_header = 0;
2023- if (sp < 1) return STBTT__CSERR("hmoveto stack");
2024- stbtt__csctx_rmove_to(c, s[sp-1], 0);
2025- break;
2026-
2027- case 0x05: // rlineto
2028- if (sp < 2) return STBTT__CSERR("rlineto stack");
2029- for (; i + 1 < sp; i += 2)
2030- stbtt__csctx_rline_to(c, s[i], s[i+1]);
2031- break;
2032-
2033- // hlineto/vlineto and vhcurveto/hvcurveto alternate horizontal and vertical
2034- // starting from a different place.
2035-
2036- case 0x07: // vlineto
2037- if (sp < 1) return STBTT__CSERR("vlineto stack");
2038- goto vlineto;
2039- case 0x06: // hlineto
2040- if (sp < 1) return STBTT__CSERR("hlineto stack");
2041- for (;;) {
2042- if (i >= sp) break;
2043- stbtt__csctx_rline_to(c, s[i], 0);
2044- i++;
2045- vlineto:
2046- if (i >= sp) break;
2047- stbtt__csctx_rline_to(c, 0, s[i]);
2048- i++;
2049- }
2050- break;
2051-
2052- case 0x1F: // hvcurveto
2053- if (sp < 4) return STBTT__CSERR("hvcurveto stack");
2054- goto hvcurveto;
2055- case 0x1E: // vhcurveto
2056- if (sp < 4) return STBTT__CSERR("vhcurveto stack");
2057- for (;;) {
2058- if (i + 3 >= sp) break;
2059- stbtt__csctx_rccurve_to(c, 0, s[i], s[i+1], s[i+2], s[i+3], (sp - i == 5) ? s[i + 4] : 0.0f);
2060- i += 4;
2061- hvcurveto:
2062- if (i + 3 >= sp) break;
2063- stbtt__csctx_rccurve_to(c, s[i], 0, s[i+1], s[i+2], (sp - i == 5) ? s[i+4] : 0.0f, s[i+3]);
2064- i += 4;
2065- }
2066- break;
2067-
2068- case 0x08: // rrcurveto
2069- if (sp < 6) return STBTT__CSERR("rcurveline stack");
2070- for (; i + 5 < sp; i += 6)
2071- stbtt__csctx_rccurve_to(c, s[i], s[i+1], s[i+2], s[i+3], s[i+4], s[i+5]);
2072- break;
2073-
2074- case 0x18: // rcurveline
2075- if (sp < 8) return STBTT__CSERR("rcurveline stack");
2076- for (; i + 5 < sp - 2; i += 6)
2077- stbtt__csctx_rccurve_to(c, s[i], s[i+1], s[i+2], s[i+3], s[i+4], s[i+5]);
2078- if (i + 1 >= sp) return STBTT__CSERR("rcurveline stack");
2079- stbtt__csctx_rline_to(c, s[i], s[i+1]);
2080- break;
2081-
2082- case 0x19: // rlinecurve
2083- if (sp < 8) return STBTT__CSERR("rlinecurve stack");
2084- for (; i + 1 < sp - 6; i += 2)
2085- stbtt__csctx_rline_to(c, s[i], s[i+1]);
2086- if (i + 5 >= sp) return STBTT__CSERR("rlinecurve stack");
2087- stbtt__csctx_rccurve_to(c, s[i], s[i+1], s[i+2], s[i+3], s[i+4], s[i+5]);
2088- break;
2089-
2090- case 0x1A: // vvcurveto
2091- case 0x1B: // hhcurveto
2092- if (sp < 4) return STBTT__CSERR("(vv|hh)curveto stack");
2093- f = 0.0;
2094- if (sp & 1) { f = s[i]; i++; }
2095- for (; i + 3 < sp; i += 4) {
2096- if (b0 == 0x1B)
2097- stbtt__csctx_rccurve_to(c, s[i], f, s[i+1], s[i+2], s[i+3], 0.0);
2098- else
2099- stbtt__csctx_rccurve_to(c, f, s[i], s[i+1], s[i+2], 0.0, s[i+3]);
2100- f = 0.0;
2101- }
2102- break;
2103-
2104- case 0x0A: // callsubr
2105- if (!has_subrs) {
2106- if (info->fdselect.size)
2107- subrs = stbtt__cid_get_glyph_subrs(info, glyph_index);
2108- has_subrs = 1;
2109- }
2110- // fallthrough
2111- case 0x1D: // callgsubr
2112- if (sp < 1) return STBTT__CSERR("call(g|)subr stack");
2113- v = (int) s[--sp];
2114- if (subr_stack_height >= 10) return STBTT__CSERR("recursion limit");
2115- subr_stack[subr_stack_height++] = b;
2116- b = stbtt__get_subr(b0 == 0x0A ? subrs : info->gsubrs, v);
2117- if (b.size == 0) return STBTT__CSERR("subr not found");
2118- b.cursor = 0;
2119- clear_stack = 0;
2120- break;
2121-
2122- case 0x0B: // return
2123- if (subr_stack_height <= 0) return STBTT__CSERR("return outside subr");
2124- b = subr_stack[--subr_stack_height];
2125- clear_stack = 0;
2126- break;
2127-
2128- case 0x0E: // endchar
2129- stbtt__csctx_close_shape(c);
2130- return 1;
2131-
2132- case 0x0C: { // two-byte escape
2133- float dx1, dx2, dx3, dx4, dx5, dx6, dy1, dy2, dy3, dy4, dy5, dy6;
2134- float dx, dy;
2135- int b1 = stbtt__buf_get8(&b);
2136- switch (b1) {
2137- // @TODO These "flex" implementations ignore the flex-depth and resolution,
2138- // and always draw beziers.
2139- case 0x22: // hflex
2140- if (sp < 7) return STBTT__CSERR("hflex stack");
2141- dx1 = s[0];
2142- dx2 = s[1];
2143- dy2 = s[2];
2144- dx3 = s[3];
2145- dx4 = s[4];
2146- dx5 = s[5];
2147- dx6 = s[6];
2148- stbtt__csctx_rccurve_to(c, dx1, 0, dx2, dy2, dx3, 0);
2149- stbtt__csctx_rccurve_to(c, dx4, 0, dx5, -dy2, dx6, 0);
2150- break;
2151-
2152- case 0x23: // flex
2153- if (sp < 13) return STBTT__CSERR("flex stack");
2154- dx1 = s[0];
2155- dy1 = s[1];
2156- dx2 = s[2];
2157- dy2 = s[3];
2158- dx3 = s[4];
2159- dy3 = s[5];
2160- dx4 = s[6];
2161- dy4 = s[7];
2162- dx5 = s[8];
2163- dy5 = s[9];
2164- dx6 = s[10];
2165- dy6 = s[11];
2166- //fd is s[12]
2167- stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, dy3);
2168- stbtt__csctx_rccurve_to(c, dx4, dy4, dx5, dy5, dx6, dy6);
2169- break;
2170-
2171- case 0x24: // hflex1
2172- if (sp < 9) return STBTT__CSERR("hflex1 stack");
2173- dx1 = s[0];
2174- dy1 = s[1];
2175- dx2 = s[2];
2176- dy2 = s[3];
2177- dx3 = s[4];
2178- dx4 = s[5];
2179- dx5 = s[6];
2180- dy5 = s[7];
2181- dx6 = s[8];
2182- stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, 0);
2183- stbtt__csctx_rccurve_to(c, dx4, 0, dx5, dy5, dx6, -(dy1+dy2+dy5));
2184- break;
2185-
2186- case 0x25: // flex1
2187- if (sp < 11) return STBTT__CSERR("flex1 stack");
2188- dx1 = s[0];
2189- dy1 = s[1];
2190- dx2 = s[2];
2191- dy2 = s[3];
2192- dx3 = s[4];
2193- dy3 = s[5];
2194- dx4 = s[6];
2195- dy4 = s[7];
2196- dx5 = s[8];
2197- dy5 = s[9];
2198- dx6 = dy6 = s[10];
2199- dx = dx1+dx2+dx3+dx4+dx5;
2200- dy = dy1+dy2+dy3+dy4+dy5;
2201- if (STBTT_fabs(dx) > STBTT_fabs(dy))
2202- dy6 = -dy;
2203- else
2204- dx6 = -dx;
2205- stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, dy3);
2206- stbtt__csctx_rccurve_to(c, dx4, dy4, dx5, dy5, dx6, dy6);
2207- break;
2208-
2209- default:
2210- return STBTT__CSERR("unimplemented");
2211- }
2212- } break;
2213-
2214- default:
2215- if (b0 != 255 && b0 != 28 && (b0 < 32 || b0 > 254)) //-V560
2216- return STBTT__CSERR("reserved operator");
2217-
2218- // push immediate
2219- if (b0 == 255) {
2220- f = (float)(stbtt_int32)stbtt__buf_get32(&b) / 0x10000;
2221- } else {
2222- stbtt__buf_skip(&b, -1);
2223- f = (float)(stbtt_int16)stbtt__cff_int(&b);
2224- }
2225- if (sp >= 48) return STBTT__CSERR("push stack overflow");
2226- s[sp++] = f;
2227- clear_stack = 0;
2228- break;
2229- }
2230- if (clear_stack) sp = 0;
2231- }
2232- return STBTT__CSERR("no endchar");
2233-
2234-#undef STBTT__CSERR
2235-}
2236-
2237-static int stbtt__GetGlyphShapeT2(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices)
2238-{
2239- // runs the charstring twice, once to count and once to output (to avoid realloc)
2240- stbtt__csctx count_ctx = STBTT__CSCTX_INIT(1);
2241- stbtt__csctx output_ctx = STBTT__CSCTX_INIT(0);
2242- if (stbtt__run_charstring(info, glyph_index, &count_ctx)) {
2243- *pvertices = (stbtt_vertex*)STBTT_malloc(count_ctx.num_vertices*sizeof(stbtt_vertex), info->userdata);
2244- output_ctx.pvertices = *pvertices;
2245- if (stbtt__run_charstring(info, glyph_index, &output_ctx)) {
2246- STBTT_assert(output_ctx.num_vertices == count_ctx.num_vertices);
2247- return output_ctx.num_vertices;
2248- }
2249- }
2250- *pvertices = NULL;
2251- return 0;
2252-}
2253-
2254-static int stbtt__GetGlyphInfoT2(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1)
2255-{
2256- stbtt__csctx c = STBTT__CSCTX_INIT(1);
2257- int r = stbtt__run_charstring(info, glyph_index, &c);
2258- if (x0) *x0 = r ? c.min_x : 0;
2259- if (y0) *y0 = r ? c.min_y : 0;
2260- if (x1) *x1 = r ? c.max_x : 0;
2261- if (y1) *y1 = r ? c.max_y : 0;
2262- return r ? c.num_vertices : 0;
2263-}
2264-
2265-STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices)
2266-{
2267- if (!info->cff.size)
2268- return stbtt__GetGlyphShapeTT(info, glyph_index, pvertices);
2269- else
2270- return stbtt__GetGlyphShapeT2(info, glyph_index, pvertices);
2271-}
2272-
2273-STBTT_DEF void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_index, int *advanceWidth, int *leftSideBearing)
2274-{
2275- stbtt_uint16 numOfLongHorMetrics = ttUSHORT(info->data+info->hhea + 34);
2276- if (glyph_index < numOfLongHorMetrics) {
2277- if (advanceWidth) *advanceWidth = ttSHORT(info->data + info->hmtx + 4*glyph_index);
2278- if (leftSideBearing) *leftSideBearing = ttSHORT(info->data + info->hmtx + 4*glyph_index + 2);
2279- } else {
2280- if (advanceWidth) *advanceWidth = ttSHORT(info->data + info->hmtx + 4*(numOfLongHorMetrics-1));
2281- if (leftSideBearing) *leftSideBearing = ttSHORT(info->data + info->hmtx + 4*numOfLongHorMetrics + 2*(glyph_index - numOfLongHorMetrics));
2282- }
2283-}
2284-
2285-static int stbtt__GetGlyphKernInfoAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2)
2286-{
2287- stbtt_uint8 *data = info->data + info->kern;
2288- stbtt_uint32 needle, straw;
2289- int l, r, m;
2290-
2291- // we only look at the first table. it must be 'horizontal' and format 0.
2292- if (!info->kern)
2293- return 0;
2294- if (ttUSHORT(data+2) < 1) // number of tables, need at least 1
2295- return 0;
2296- if (ttUSHORT(data+8) != 1) // horizontal flag must be set in format
2297- return 0;
2298-
2299- l = 0;
2300- r = ttUSHORT(data+10) - 1;
2301- needle = glyph1 << 16 | glyph2;
2302- while (l <= r) {
2303- m = (l + r) >> 1;
2304- straw = ttULONG(data+18+(m*6)); // note: unaligned read
2305- if (needle < straw)
2306- r = m - 1;
2307- else if (needle > straw)
2308- l = m + 1;
2309- else
2310- return ttSHORT(data+22+(m*6));
2311- }
2312- return 0;
2313-}
2314-
2315-static stbtt_int32 stbtt__GetCoverageIndex(stbtt_uint8 *coverageTable, int glyph)
2316-{
2317- stbtt_uint16 coverageFormat = ttUSHORT(coverageTable);
2318- switch(coverageFormat) {
2319- case 1: {
2320- stbtt_uint16 glyphCount = ttUSHORT(coverageTable + 2);
2321-
2322- // Binary search.
2323- stbtt_int32 l=0, r=glyphCount-1, m;
2324- int straw, needle=glyph;
2325- while (l <= r) {
2326- stbtt_uint8 *glyphArray = coverageTable + 4;
2327- stbtt_uint16 glyphID;
2328- m = (l + r) >> 1;
2329- glyphID = ttUSHORT(glyphArray + 2 * m);
2330- straw = glyphID;
2331- if (needle < straw)
2332- r = m - 1;
2333- else if (needle > straw)
2334- l = m + 1;
2335- else {
2336- return m;
2337- }
2338- }
2339- } break;
2340-
2341- case 2: {
2342- stbtt_uint16 rangeCount = ttUSHORT(coverageTable + 2);
2343- stbtt_uint8 *rangeArray = coverageTable + 4;
2344-
2345- // Binary search.
2346- stbtt_int32 l=0, r=rangeCount-1, m;
2347- int strawStart, strawEnd, needle=glyph;
2348- while (l <= r) {
2349- stbtt_uint8 *rangeRecord;
2350- m = (l + r) >> 1;
2351- rangeRecord = rangeArray + 6 * m;
2352- strawStart = ttUSHORT(rangeRecord);
2353- strawEnd = ttUSHORT(rangeRecord + 2);
2354- if (needle < strawStart)
2355- r = m - 1;
2356- else if (needle > strawEnd)
2357- l = m + 1;
2358- else {
2359- stbtt_uint16 startCoverageIndex = ttUSHORT(rangeRecord + 4);
2360- return startCoverageIndex + glyph - strawStart;
2361- }
2362- }
2363- } break;
2364-
2365- default: {
2366- // There are no other cases.
2367- STBTT_assert(0);
2368- } break;
2369- }
2370-
2371- return -1;
2372-}
2373-
2374-static stbtt_int32 stbtt__GetGlyphClass(stbtt_uint8 *classDefTable, int glyph)
2375-{
2376- stbtt_uint16 classDefFormat = ttUSHORT(classDefTable);
2377- switch(classDefFormat)
2378- {
2379- case 1: {
2380- stbtt_uint16 startGlyphID = ttUSHORT(classDefTable + 2);
2381- stbtt_uint16 glyphCount = ttUSHORT(classDefTable + 4);
2382- stbtt_uint8 *classDef1ValueArray = classDefTable + 6;
2383-
2384- if (glyph >= startGlyphID && glyph < startGlyphID + glyphCount)
2385- return (stbtt_int32)ttUSHORT(classDef1ValueArray + 2 * (glyph - startGlyphID));
2386-
2387- // [DEAR IMGUI] Commented to fix static analyzer warning
2388- //classDefTable = classDef1ValueArray + 2 * glyphCount;
2389- } break;
2390-
2391- case 2: {
2392- stbtt_uint16 classRangeCount = ttUSHORT(classDefTable + 2);
2393- stbtt_uint8 *classRangeRecords = classDefTable + 4;
2394-
2395- // Binary search.
2396- stbtt_int32 l=0, r=classRangeCount-1, m;
2397- int strawStart, strawEnd, needle=glyph;
2398- while (l <= r) {
2399- stbtt_uint8 *classRangeRecord;
2400- m = (l + r) >> 1;
2401- classRangeRecord = classRangeRecords + 6 * m;
2402- strawStart = ttUSHORT(classRangeRecord);
2403- strawEnd = ttUSHORT(classRangeRecord + 2);
2404- if (needle < strawStart)
2405- r = m - 1;
2406- else if (needle > strawEnd)
2407- l = m + 1;
2408- else
2409- return (stbtt_int32)ttUSHORT(classRangeRecord + 4);
2410- }
2411-
2412- // [DEAR IMGUI] Commented to fix static analyzer warning
2413- //classDefTable = classRangeRecords + 6 * classRangeCount;
2414- } break;
2415-
2416- default: {
2417- // There are no other cases.
2418- STBTT_assert(0);
2419- } break;
2420- }
2421-
2422- return -1;
2423-}
2424-
2425-// Define to STBTT_assert(x) if you want to break on unimplemented formats.
2426-#define STBTT_GPOS_TODO_assert(x)
2427-
2428-static stbtt_int32 stbtt__GetGlyphGPOSInfoAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2)
2429-{
2430- stbtt_uint16 lookupListOffset;
2431- stbtt_uint8 *lookupList;
2432- stbtt_uint16 lookupCount;
2433- stbtt_uint8 *data;
2434- stbtt_int32 i;
2435-
2436- if (!info->gpos) return 0;
2437-
2438- data = info->data + info->gpos;
2439-
2440- if (ttUSHORT(data+0) != 1) return 0; // Major version 1
2441- if (ttUSHORT(data+2) != 0) return 0; // Minor version 0
2442-
2443- lookupListOffset = ttUSHORT(data+8);
2444- lookupList = data + lookupListOffset;
2445- lookupCount = ttUSHORT(lookupList);
2446-
2447- for (i=0; i<lookupCount; ++i) {
2448- stbtt_uint16 lookupOffset = ttUSHORT(lookupList + 2 + 2 * i);
2449- stbtt_uint8 *lookupTable = lookupList + lookupOffset;
2450-
2451- stbtt_uint16 lookupType = ttUSHORT(lookupTable);
2452- stbtt_uint16 subTableCount = ttUSHORT(lookupTable + 4);
2453- stbtt_uint8 *subTableOffsets = lookupTable + 6;
2454- switch(lookupType) {
2455- case 2: { // Pair Adjustment Positioning Subtable
2456- stbtt_int32 sti;
2457- for (sti=0; sti<subTableCount; sti++) {
2458- stbtt_uint16 subtableOffset = ttUSHORT(subTableOffsets + 2 * sti);
2459- stbtt_uint8 *table = lookupTable + subtableOffset;
2460- stbtt_uint16 posFormat = ttUSHORT(table);
2461- stbtt_uint16 coverageOffset = ttUSHORT(table + 2);
2462- stbtt_int32 coverageIndex = stbtt__GetCoverageIndex(table + coverageOffset, glyph1);
2463- if (coverageIndex == -1) continue;
2464-
2465- switch (posFormat) {
2466- case 1: {
2467- stbtt_int32 l, r, m;
2468- int straw, needle;
2469- stbtt_uint16 valueFormat1 = ttUSHORT(table + 4);
2470- stbtt_uint16 valueFormat2 = ttUSHORT(table + 6);
2471- stbtt_int32 valueRecordPairSizeInBytes = 2;
2472- stbtt_uint16 pairSetCount = ttUSHORT(table + 8);
2473- stbtt_uint16 pairPosOffset = ttUSHORT(table + 10 + 2 * coverageIndex);
2474- stbtt_uint8 *pairValueTable = table + pairPosOffset;
2475- stbtt_uint16 pairValueCount = ttUSHORT(pairValueTable);
2476- stbtt_uint8 *pairValueArray = pairValueTable + 2;
2477- // TODO: Support more formats.
2478- STBTT_GPOS_TODO_assert(valueFormat1 == 4);
2479- if (valueFormat1 != 4) return 0;
2480- STBTT_GPOS_TODO_assert(valueFormat2 == 0);
2481- if (valueFormat2 != 0) return 0;
2482-
2483- STBTT_assert(coverageIndex < pairSetCount);
2484- STBTT__NOTUSED(pairSetCount);
2485-
2486- needle=glyph2;
2487- r=pairValueCount-1;
2488- l=0;
2489-
2490- // Binary search.
2491- while (l <= r) {
2492- stbtt_uint16 secondGlyph;
2493- stbtt_uint8 *pairValue;
2494- m = (l + r) >> 1;
2495- pairValue = pairValueArray + (2 + valueRecordPairSizeInBytes) * m;
2496- secondGlyph = ttUSHORT(pairValue);
2497- straw = secondGlyph;
2498- if (needle < straw)
2499- r = m - 1;
2500- else if (needle > straw)
2501- l = m + 1;
2502- else {
2503- stbtt_int16 xAdvance = ttSHORT(pairValue + 2);
2504- return xAdvance;
2505- }
2506- }
2507- } break;
2508-
2509- case 2: {
2510- stbtt_uint16 valueFormat1 = ttUSHORT(table + 4);
2511- stbtt_uint16 valueFormat2 = ttUSHORT(table + 6);
2512-
2513- stbtt_uint16 classDef1Offset = ttUSHORT(table + 8);
2514- stbtt_uint16 classDef2Offset = ttUSHORT(table + 10);
2515- int glyph1class = stbtt__GetGlyphClass(table + classDef1Offset, glyph1);
2516- int glyph2class = stbtt__GetGlyphClass(table + classDef2Offset, glyph2);
2517-
2518- stbtt_uint16 class1Count = ttUSHORT(table + 12);
2519- stbtt_uint16 class2Count = ttUSHORT(table + 14);
2520- STBTT_assert(glyph1class < class1Count);
2521- STBTT_assert(glyph2class < class2Count);
2522-
2523- // TODO: Support more formats.
2524- STBTT_GPOS_TODO_assert(valueFormat1 == 4);
2525- if (valueFormat1 != 4) return 0;
2526- STBTT_GPOS_TODO_assert(valueFormat2 == 0);
2527- if (valueFormat2 != 0) return 0;
2528-
2529- if (glyph1class >= 0 && glyph1class < class1Count && glyph2class >= 0 && glyph2class < class2Count) {
2530- stbtt_uint8 *class1Records = table + 16;
2531- stbtt_uint8 *class2Records = class1Records + 2 * (glyph1class * class2Count);
2532- stbtt_int16 xAdvance = ttSHORT(class2Records + 2 * glyph2class);
2533- return xAdvance;
2534- }
2535- } break;
2536-
2537- default: {
2538- // There are no other cases.
2539- STBTT_assert(0);
2540- break;
2541- };
2542- }
2543- }
2544- break;
2545- };
2546-
2547- default:
2548- // TODO: Implement other stuff.
2549- break;
2550- }
2551- }
2552-
2553- return 0;
2554-}
2555-
2556-STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int g1, int g2)
2557-{
2558- int xAdvance = 0;
2559-
2560- if (info->gpos)
2561- xAdvance += stbtt__GetGlyphGPOSInfoAdvance(info, g1, g2);
2562-
2563- if (info->kern)
2564- xAdvance += stbtt__GetGlyphKernInfoAdvance(info, g1, g2);
2565-
2566- return xAdvance;
2567-}
2568-
2569-STBTT_DEF int stbtt_GetCodepointKernAdvance(const stbtt_fontinfo *info, int ch1, int ch2)
2570-{
2571- if (!info->kern && !info->gpos) // if no kerning table, don't waste time looking up both codepoint->glyphs
2572- return 0;
2573- return stbtt_GetGlyphKernAdvance(info, stbtt_FindGlyphIndex(info,ch1), stbtt_FindGlyphIndex(info,ch2));
2574-}
2575-
2576-STBTT_DEF void stbtt_GetCodepointHMetrics(const stbtt_fontinfo *info, int codepoint, int *advanceWidth, int *leftSideBearing)
2577-{
2578- stbtt_GetGlyphHMetrics(info, stbtt_FindGlyphIndex(info,codepoint), advanceWidth, leftSideBearing);
2579-}
2580-
2581-STBTT_DEF void stbtt_GetFontVMetrics(const stbtt_fontinfo *info, int *ascent, int *descent, int *lineGap)
2582-{
2583- if (ascent ) *ascent = ttSHORT(info->data+info->hhea + 4);
2584- if (descent) *descent = ttSHORT(info->data+info->hhea + 6);
2585- if (lineGap) *lineGap = ttSHORT(info->data+info->hhea + 8);
2586-}
2587-
2588-STBTT_DEF int stbtt_GetFontVMetricsOS2(const stbtt_fontinfo *info, int *typoAscent, int *typoDescent, int *typoLineGap)
2589-{
2590- int tab = stbtt__find_table(info->data, info->fontstart, "OS/2");
2591- if (!tab)
2592- return 0;
2593- if (typoAscent ) *typoAscent = ttSHORT(info->data+tab + 68);
2594- if (typoDescent) *typoDescent = ttSHORT(info->data+tab + 70);
2595- if (typoLineGap) *typoLineGap = ttSHORT(info->data+tab + 72);
2596- return 1;
2597-}
2598-
2599-STBTT_DEF void stbtt_GetFontBoundingBox(const stbtt_fontinfo *info, int *x0, int *y0, int *x1, int *y1)
2600-{
2601- *x0 = ttSHORT(info->data + info->head + 36);
2602- *y0 = ttSHORT(info->data + info->head + 38);
2603- *x1 = ttSHORT(info->data + info->head + 40);
2604- *y1 = ttSHORT(info->data + info->head + 42);
2605-}
2606-
2607-STBTT_DEF float stbtt_ScaleForPixelHeight(const stbtt_fontinfo *info, float height)
2608-{
2609- int fheight = ttSHORT(info->data + info->hhea + 4) - ttSHORT(info->data + info->hhea + 6);
2610- return (float) height / fheight;
2611-}
2612-
2613-STBTT_DEF float stbtt_ScaleForMappingEmToPixels(const stbtt_fontinfo *info, float pixels)
2614-{
2615- int unitsPerEm = ttUSHORT(info->data + info->head + 18);
2616- return pixels / unitsPerEm;
2617-}
2618-
2619-STBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *v)
2620-{
2621- STBTT_free(v, info->userdata);
2622-}
2623-
2624-//////////////////////////////////////////////////////////////////////////////
2625-//
2626-// antialiasing software rasterizer
2627-//
2628-
2629-STBTT_DEF 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)
2630-{
2631- int x0=0,y0=0,x1,y1; // =0 suppresses compiler warning
2632- if (!stbtt_GetGlyphBox(font, glyph, &x0,&y0,&x1,&y1)) {
2633- // e.g. space character
2634- if (ix0) *ix0 = 0;
2635- if (iy0) *iy0 = 0;
2636- if (ix1) *ix1 = 0;
2637- if (iy1) *iy1 = 0;
2638- } else {
2639- // move to integral bboxes (treating pixels as little squares, what pixels get touched)?
2640- if (ix0) *ix0 = STBTT_ifloor( x0 * scale_x + shift_x);
2641- if (iy0) *iy0 = STBTT_ifloor(-y1 * scale_y + shift_y);
2642- if (ix1) *ix1 = STBTT_iceil ( x1 * scale_x + shift_x);
2643- if (iy1) *iy1 = STBTT_iceil (-y0 * scale_y + shift_y);
2644- }
2645-}
2646-
2647-STBTT_DEF void stbtt_GetGlyphBitmapBox(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1)
2648-{
2649- stbtt_GetGlyphBitmapBoxSubpixel(font, glyph, scale_x, scale_y,0.0f,0.0f, ix0, iy0, ix1, iy1);
2650-}
2651-
2652-STBTT_DEF 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)
2653-{
2654- stbtt_GetGlyphBitmapBoxSubpixel(font, stbtt_FindGlyphIndex(font,codepoint), scale_x, scale_y,shift_x,shift_y, ix0,iy0,ix1,iy1);
2655-}
2656-
2657-STBTT_DEF void stbtt_GetCodepointBitmapBox(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1)
2658-{
2659- stbtt_GetCodepointBitmapBoxSubpixel(font, codepoint, scale_x, scale_y,0.0f,0.0f, ix0,iy0,ix1,iy1);
2660-}
2661-
2662-//////////////////////////////////////////////////////////////////////////////
2663-//
2664-// Rasterizer
2665-
2666-typedef struct stbtt__hheap_chunk
2667-{
2668- struct stbtt__hheap_chunk *next;
2669-} stbtt__hheap_chunk;
2670-
2671-typedef struct stbtt__hheap
2672-{
2673- struct stbtt__hheap_chunk *head;
2674- void *first_free;
2675- int num_remaining_in_head_chunk;
2676-} stbtt__hheap;
2677-
2678-static void *stbtt__hheap_alloc(stbtt__hheap *hh, size_t size, void *userdata)
2679-{
2680- if (hh->first_free) {
2681- void *p = hh->first_free;
2682- hh->first_free = * (void **) p;
2683- return p;
2684- } else {
2685- if (hh->num_remaining_in_head_chunk == 0) {
2686- int count = (size < 32 ? 2000 : size < 128 ? 800 : 100);
2687- stbtt__hheap_chunk *c = (stbtt__hheap_chunk *) STBTT_malloc(sizeof(stbtt__hheap_chunk) + size * count, userdata);
2688- if (c == NULL)
2689- return NULL;
2690- c->next = hh->head;
2691- hh->head = c;
2692- hh->num_remaining_in_head_chunk = count;
2693- }
2694- --hh->num_remaining_in_head_chunk;
2695- return (char *) (hh->head) + sizeof(stbtt__hheap_chunk) + size * hh->num_remaining_in_head_chunk;
2696- }
2697-}
2698-
2699-static void stbtt__hheap_free(stbtt__hheap *hh, void *p)
2700-{
2701- *(void **) p = hh->first_free;
2702- hh->first_free = p;
2703-}
2704-
2705-static void stbtt__hheap_cleanup(stbtt__hheap *hh, void *userdata)
2706-{
2707- stbtt__hheap_chunk *c = hh->head;
2708- while (c) {
2709- stbtt__hheap_chunk *n = c->next;
2710- STBTT_free(c, userdata);
2711- c = n;
2712- }
2713-}
2714-
2715-typedef struct stbtt__edge {
2716- float x0,y0, x1,y1;
2717- int invert;
2718-} stbtt__edge;
2719-
2720-
2721-typedef struct stbtt__active_edge
2722-{
2723- struct stbtt__active_edge *next;
2724- #if STBTT_RASTERIZER_VERSION==1
2725- int x,dx;
2726- float ey;
2727- int direction;
2728- #elif STBTT_RASTERIZER_VERSION==2
2729- float fx,fdx,fdy;
2730- float direction;
2731- float sy;
2732- float ey;
2733- #else
2734- #error "Unrecognized value of STBTT_RASTERIZER_VERSION"
2735- #endif
2736-} stbtt__active_edge;
2737-
2738-#if STBTT_RASTERIZER_VERSION == 1
2739-#define STBTT_FIXSHIFT 10
2740-#define STBTT_FIX (1 << STBTT_FIXSHIFT)
2741-#define STBTT_FIXMASK (STBTT_FIX-1)
2742-
2743-static stbtt__active_edge *stbtt__new_active(stbtt__hheap *hh, stbtt__edge *e, int off_x, float start_point, void *userdata)
2744-{
2745- stbtt__active_edge *z = (stbtt__active_edge *) stbtt__hheap_alloc(hh, sizeof(*z), userdata);
2746- float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0);
2747- STBTT_assert(z != NULL);
2748- if (!z) return z;
2749-
2750- // round dx down to avoid overshooting
2751- if (dxdy < 0)
2752- z->dx = -STBTT_ifloor(STBTT_FIX * -dxdy);
2753- else
2754- z->dx = STBTT_ifloor(STBTT_FIX * dxdy);
2755-
2756- z->x = STBTT_ifloor(STBTT_FIX * e->x0 + z->dx * (start_point - e->y0)); // use z->dx so when we offset later it's by the same amount
2757- z->x -= off_x * STBTT_FIX;
2758-
2759- z->ey = e->y1;
2760- z->next = 0;
2761- z->direction = e->invert ? 1 : -1;
2762- return z;
2763-}
2764-#elif STBTT_RASTERIZER_VERSION == 2
2765-static stbtt__active_edge *stbtt__new_active(stbtt__hheap *hh, stbtt__edge *e, int off_x, float start_point, void *userdata)
2766-{
2767- stbtt__active_edge *z = (stbtt__active_edge *) stbtt__hheap_alloc(hh, sizeof(*z), userdata);
2768- float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0);
2769- STBTT_assert(z != NULL);
2770- //STBTT_assert(e->y0 <= start_point);
2771- if (!z) return z;
2772- z->fdx = dxdy;
2773- z->fdy = dxdy != 0.0f ? (1.0f/dxdy) : 0.0f;
2774- z->fx = e->x0 + dxdy * (start_point - e->y0);
2775- z->fx -= off_x;
2776- z->direction = e->invert ? 1.0f : -1.0f;
2777- z->sy = e->y0;
2778- z->ey = e->y1;
2779- z->next = 0;
2780- return z;
2781-}
2782-#else
2783-#error "Unrecognized value of STBTT_RASTERIZER_VERSION"
2784-#endif
2785-
2786-#if STBTT_RASTERIZER_VERSION == 1
2787-// note: this routine clips fills that extend off the edges... ideally this
2788-// wouldn't happen, but it could happen if the truetype glyph bounding boxes
2789-// are wrong, or if the user supplies a too-small bitmap
2790-static void stbtt__fill_active_edges(unsigned char *scanline, int len, stbtt__active_edge *e, int max_weight)
2791-{
2792- // non-zero winding fill
2793- int x0=0, w=0;
2794-
2795- while (e) {
2796- if (w == 0) {
2797- // if we're currently at zero, we need to record the edge start point
2798- x0 = e->x; w += e->direction;
2799- } else {
2800- int x1 = e->x; w += e->direction;
2801- // if we went to zero, we need to draw
2802- if (w == 0) {
2803- int i = x0 >> STBTT_FIXSHIFT;
2804- int j = x1 >> STBTT_FIXSHIFT;
2805-
2806- if (i < len && j >= 0) {
2807- if (i == j) {
2808- // x0,x1 are the same pixel, so compute combined coverage
2809- scanline[i] = scanline[i] + (stbtt_uint8) ((x1 - x0) * max_weight >> STBTT_FIXSHIFT);
2810- } else {
2811- if (i >= 0) // add antialiasing for x0
2812- scanline[i] = scanline[i] + (stbtt_uint8) (((STBTT_FIX - (x0 & STBTT_FIXMASK)) * max_weight) >> STBTT_FIXSHIFT);
2813- else
2814- i = -1; // clip
2815-
2816- if (j < len) // add antialiasing for x1
2817- scanline[j] = scanline[j] + (stbtt_uint8) (((x1 & STBTT_FIXMASK) * max_weight) >> STBTT_FIXSHIFT);
2818- else
2819- j = len; // clip
2820-
2821- for (++i; i < j; ++i) // fill pixels between x0 and x1
2822- scanline[i] = scanline[i] + (stbtt_uint8) max_weight;
2823- }
2824- }
2825- }
2826- }
2827-
2828- e = e->next;
2829- }
2830-}
2831-
2832-static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, int n, int vsubsample, int off_x, int off_y, void *userdata)
2833-{
2834- stbtt__hheap hh = { 0, 0, 0 };
2835- stbtt__active_edge *active = NULL;
2836- int y,j=0;
2837- int max_weight = (255 / vsubsample); // weight per vertical scanline
2838- int s; // vertical subsample index
2839- unsigned char scanline_data[512], *scanline;
2840-
2841- if (result->w > 512)
2842- scanline = (unsigned char *) STBTT_malloc(result->w, userdata);
2843- else
2844- scanline = scanline_data;
2845-
2846- y = off_y * vsubsample;
2847- e[n].y0 = (off_y + result->h) * (float) vsubsample + 1;
2848-
2849- while (j < result->h) {
2850- STBTT_memset(scanline, 0, result->w);
2851- for (s=0; s < vsubsample; ++s) {
2852- // find center of pixel for this scanline
2853- float scan_y = y + 0.5f;
2854- stbtt__active_edge **step = &active;
2855-
2856- // update all active edges;
2857- // remove all active edges that terminate before the center of this scanline
2858- while (*step) {
2859- stbtt__active_edge * z = *step;
2860- if (z->ey <= scan_y) {
2861- *step = z->next; // delete from list
2862- STBTT_assert(z->direction);
2863- z->direction = 0;
2864- stbtt__hheap_free(&hh, z);
2865- } else {
2866- z->x += z->dx; // advance to position for current scanline
2867- step = &((*step)->next); // advance through list
2868- }
2869- }
2870-
2871- // resort the list if needed
2872- for(;;) {
2873- int changed=0;
2874- step = &active;
2875- while (*step && (*step)->next) {
2876- if ((*step)->x > (*step)->next->x) {
2877- stbtt__active_edge *t = *step;
2878- stbtt__active_edge *q = t->next;
2879-
2880- t->next = q->next;
2881- q->next = t;
2882- *step = q;
2883- changed = 1;
2884- }
2885- step = &(*step)->next;
2886- }
2887- if (!changed) break;
2888- }
2889-
2890- // insert all edges that start before the center of this scanline -- omit ones that also end on this scanline
2891- while (e->y0 <= scan_y) {
2892- if (e->y1 > scan_y) {
2893- stbtt__active_edge *z = stbtt__new_active(&hh, e, off_x, scan_y, userdata);
2894- if (z != NULL) {
2895- // find insertion point
2896- if (active == NULL)
2897- active = z;
2898- else if (z->x < active->x) {
2899- // insert at front
2900- z->next = active;
2901- active = z;
2902- } else {
2903- // find thing to insert AFTER
2904- stbtt__active_edge *p = active;
2905- while (p->next && p->next->x < z->x)
2906- p = p->next;
2907- // at this point, p->next->x is NOT < z->x
2908- z->next = p->next;
2909- p->next = z;
2910- }
2911- }
2912- }
2913- ++e;
2914- }
2915-
2916- // now process all active edges in XOR fashion
2917- if (active)
2918- stbtt__fill_active_edges(scanline, result->w, active, max_weight);
2919-
2920- ++y;
2921- }
2922- STBTT_memcpy(result->pixels + j * result->stride, scanline, result->w);
2923- ++j;
2924- }
2925-
2926- stbtt__hheap_cleanup(&hh, userdata);
2927-
2928- if (scanline != scanline_data)
2929- STBTT_free(scanline, userdata);
2930-}
2931-
2932-#elif STBTT_RASTERIZER_VERSION == 2
2933-
2934-// the edge passed in here does not cross the vertical line at x or the vertical line at x+1
2935-// (i.e. it has already been clipped to those)
2936-static void stbtt__handle_clipped_edge(float *scanline, int x, stbtt__active_edge *e, float x0, float y0, float x1, float y1)
2937-{
2938- if (y0 == y1) return;
2939- STBTT_assert(y0 < y1);
2940- STBTT_assert(e->sy <= e->ey);
2941- if (y0 > e->ey) return;
2942- if (y1 < e->sy) return;
2943- if (y0 < e->sy) {
2944- x0 += (x1-x0) * (e->sy - y0) / (y1-y0);
2945- y0 = e->sy;
2946- }
2947- if (y1 > e->ey) {
2948- x1 += (x1-x0) * (e->ey - y1) / (y1-y0);
2949- y1 = e->ey;
2950- }
2951-
2952- if (x0 == x)
2953- STBTT_assert(x1 <= x+1);
2954- else if (x0 == x+1)
2955- STBTT_assert(x1 >= x);
2956- else if (x0 <= x)
2957- STBTT_assert(x1 <= x);
2958- else if (x0 >= x+1)
2959- STBTT_assert(x1 >= x+1);
2960- else
2961- STBTT_assert(x1 >= x && x1 <= x+1);
2962-
2963- if (x0 <= x && x1 <= x)
2964- scanline[x] += e->direction * (y1-y0);
2965- else if (x0 >= x+1 && x1 >= x+1)
2966- ;
2967- else {
2968- STBTT_assert(x0 >= x && x0 <= x+1 && x1 >= x && x1 <= x+1);
2969- scanline[x] += e->direction * (y1-y0) * (1-((x0-x)+(x1-x))/2); // coverage = 1 - average x position
2970- }
2971-}
2972-
2973-static void stbtt__fill_active_edges_new(float *scanline, float *scanline_fill, int len, stbtt__active_edge *e, float y_top)
2974-{
2975- float y_bottom = y_top+1;
2976-
2977- while (e) {
2978- // brute force every pixel
2979-
2980- // compute intersection points with top & bottom
2981- STBTT_assert(e->ey >= y_top);
2982-
2983- if (e->fdx == 0) {
2984- float x0 = e->fx;
2985- if (x0 < len) {
2986- if (x0 >= 0) {
2987- stbtt__handle_clipped_edge(scanline,(int) x0,e, x0,y_top, x0,y_bottom);
2988- stbtt__handle_clipped_edge(scanline_fill-1,(int) x0+1,e, x0,y_top, x0,y_bottom);
2989- } else {
2990- stbtt__handle_clipped_edge(scanline_fill-1,0,e, x0,y_top, x0,y_bottom);
2991- }
2992- }
2993- } else {
2994- float x0 = e->fx;
2995- float dx = e->fdx;
2996- float xb = x0 + dx;
2997- float x_top, x_bottom;
2998- float sy0,sy1;
2999- float dy = e->fdy;
3000- STBTT_assert(e->sy <= y_bottom && e->ey >= y_top);
3001-
3002- // compute endpoints of line segment clipped to this scanline (if the
3003- // line segment starts on this scanline. x0 is the intersection of the
3004- // line with y_top, but that may be off the line segment.
3005- if (e->sy > y_top) {
3006- x_top = x0 + dx * (e->sy - y_top);
3007- sy0 = e->sy;
3008- } else {
3009- x_top = x0;
3010- sy0 = y_top;
3011- }
3012- if (e->ey < y_bottom) {
3013- x_bottom = x0 + dx * (e->ey - y_top);
3014- sy1 = e->ey;
3015- } else {
3016- x_bottom = xb;
3017- sy1 = y_bottom;
3018- }
3019-
3020- if (x_top >= 0 && x_bottom >= 0 && x_top < len && x_bottom < len) {
3021- // from here on, we don't have to range check x values
3022-
3023- if ((int) x_top == (int) x_bottom) {
3024- float height;
3025- // simple case, only spans one pixel
3026- int x = (int) x_top;
3027- height = sy1 - sy0;
3028- STBTT_assert(x >= 0 && x < len);
3029- scanline[x] += e->direction * (1-((x_top - x) + (x_bottom-x))/2) * height;
3030- scanline_fill[x] += e->direction * height; // everything right of this pixel is filled
3031- } else {
3032- int x,x1,x2;
3033- float y_crossing, step, sign, area;
3034- // covers 2+ pixels
3035- if (x_top > x_bottom) {
3036- // flip scanline vertically; signed area is the same
3037- float t;
3038- sy0 = y_bottom - (sy0 - y_top);
3039- sy1 = y_bottom - (sy1 - y_top);
3040- t = sy0, sy0 = sy1, sy1 = t;
3041- t = x_bottom, x_bottom = x_top, x_top = t;
3042- dx = -dx;
3043- dy = -dy;
3044- t = x0, x0 = xb, xb = t;
3045- // [DEAR IMGUI] Fix static analyzer warning
3046- (void)dx; // [ImGui: fix static analyzer warning]
3047- }
3048-
3049- x1 = (int) x_top;
3050- x2 = (int) x_bottom;
3051- // compute intersection with y axis at x1+1
3052- y_crossing = (x1+1 - x0) * dy + y_top;
3053-
3054- sign = e->direction;
3055- // area of the rectangle covered from y0..y_crossing
3056- area = sign * (y_crossing-sy0);
3057- // area of the triangle (x_top,y0), (x+1,y0), (x+1,y_crossing)
3058- scanline[x1] += area * (1-((x_top - x1)+(x1+1-x1))/2);
3059-
3060- step = sign * dy;
3061- for (x = x1+1; x < x2; ++x) {
3062- scanline[x] += area + step/2;
3063- area += step;
3064- }
3065- y_crossing += dy * (x2 - (x1+1));
3066-
3067- STBTT_assert(STBTT_fabs(area) <= 1.01f);
3068-
3069- scanline[x2] += area + sign * (1-((x2-x2)+(x_bottom-x2))/2) * (sy1-y_crossing);
3070-
3071- scanline_fill[x2] += sign * (sy1-sy0);
3072- }
3073- } else {
3074- // if edge goes outside of box we're drawing, we require
3075- // clipping logic. since this does not match the intended use
3076- // of this library, we use a different, very slow brute
3077- // force implementation
3078- int x;
3079- for (x=0; x < len; ++x) {
3080- // cases:
3081- //
3082- // there can be up to two intersections with the pixel. any intersection
3083- // with left or right edges can be handled by splitting into two (or three)
3084- // regions. intersections with top & bottom do not necessitate case-wise logic.
3085- //
3086- // the old way of doing this found the intersections with the left & right edges,
3087- // then used some simple logic to produce up to three segments in sorted order
3088- // from top-to-bottom. however, this had a problem: if an x edge was epsilon
3089- // across the x border, then the corresponding y position might not be distinct
3090- // from the other y segment, and it might ignored as an empty segment. to avoid
3091- // that, we need to explicitly produce segments based on x positions.
3092-
3093- // rename variables to clearly-defined pairs
3094- float y0 = y_top;
3095- float x1 = (float) (x);
3096- float x2 = (float) (x+1);
3097- float x3 = xb;
3098- float y3 = y_bottom;
3099-
3100- // x = e->x + e->dx * (y-y_top)
3101- // (y-y_top) = (x - e->x) / e->dx
3102- // y = (x - e->x) / e->dx + y_top
3103- float y1 = (x - x0) / dx + y_top;
3104- float y2 = (x+1 - x0) / dx + y_top;
3105-
3106- if (x0 < x1 && x3 > x2) { // three segments descending down-right
3107- stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1);
3108- stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x2,y2);
3109- stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3);
3110- } else if (x3 < x1 && x0 > x2) { // three segments descending down-left
3111- stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x2,y2);
3112- stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x1,y1);
3113- stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x3,y3);
3114- } else if (x0 < x1 && x3 > x1) { // two segments across x, down-right
3115- stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1);
3116- stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x3,y3);
3117- } else if (x3 < x1 && x0 > x1) { // two segments across x, down-left
3118- stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1);
3119- stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x3,y3);
3120- } else if (x0 < x2 && x3 > x2) { // two segments across x+1, down-right
3121- stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x2,y2);
3122- stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3);
3123- } else if (x3 < x2 && x0 > x2) { // two segments across x+1, down-left
3124- stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x2,y2);
3125- stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3);
3126- } else { // one segment
3127- stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x3,y3);
3128- }
3129- }
3130- }
3131- }
3132- e = e->next;
3133- }
3134-}
3135-
3136-// directly AA rasterize edges w/o supersampling
3137-static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, int n, int vsubsample, int off_x, int off_y, void *userdata)
3138-{
3139- stbtt__hheap hh = { 0, 0, 0 };
3140- stbtt__active_edge *active = NULL;
3141- int y,j=0, i;
3142- float scanline_data[129], *scanline, *scanline2;
3143-
3144- STBTT__NOTUSED(vsubsample);
3145-
3146- if (result->w > 64)
3147- scanline = (float *) STBTT_malloc((result->w*2+1) * sizeof(float), userdata);
3148- else
3149- scanline = scanline_data;
3150-
3151- scanline2 = scanline + result->w;
3152-
3153- y = off_y;
3154- e[n].y0 = (float) (off_y + result->h) + 1;
3155-
3156- while (j < result->h) {
3157- // find center of pixel for this scanline
3158- float scan_y_top = y + 0.0f;
3159- float scan_y_bottom = y + 1.0f;
3160- stbtt__active_edge **step = &active;
3161-
3162- STBTT_memset(scanline , 0, result->w*sizeof(scanline[0]));
3163- STBTT_memset(scanline2, 0, (result->w+1)*sizeof(scanline[0]));
3164-
3165- // update all active edges;
3166- // remove all active edges that terminate before the top of this scanline
3167- while (*step) {
3168- stbtt__active_edge * z = *step;
3169- if (z->ey <= scan_y_top) {
3170- *step = z->next; // delete from list
3171- STBTT_assert(z->direction);
3172- z->direction = 0;
3173- stbtt__hheap_free(&hh, z);
3174- } else {
3175- step = &((*step)->next); // advance through list
3176- }
3177- }
3178-
3179- // insert all edges that start before the bottom of this scanline
3180- while (e->y0 <= scan_y_bottom) {
3181- if (e->y0 != e->y1) {
3182- stbtt__active_edge *z = stbtt__new_active(&hh, e, off_x, scan_y_top, userdata);
3183- if (z != NULL) {
3184- if (j == 0 && off_y != 0) {
3185- if (z->ey < scan_y_top) {
3186- // this can happen due to subpixel positioning and some kind of fp rounding error i think
3187- z->ey = scan_y_top;
3188- }
3189- }
3190- STBTT_assert(z->ey >= scan_y_top); // if we get really unlucky a tiny bit of an edge can be out of bounds
3191- // insert at front
3192- z->next = active;
3193- active = z;
3194- }
3195- }
3196- ++e;
3197- }
3198-
3199- // now process all active edges
3200- if (active)
3201- stbtt__fill_active_edges_new(scanline, scanline2+1, result->w, active, scan_y_top);
3202-
3203- {
3204- float sum = 0;
3205- for (i=0; i < result->w; ++i) {
3206- float k;
3207- int m;
3208- sum += scanline2[i];
3209- k = scanline[i] + sum;
3210- k = (float) STBTT_fabs(k)*255 + 0.5f;
3211- m = (int) k;
3212- if (m > 255) m = 255;
3213- result->pixels[j*result->stride + i] = (unsigned char) m;
3214- }
3215- }
3216- // advance all the edges
3217- step = &active;
3218- while (*step) {
3219- stbtt__active_edge *z = *step;
3220- z->fx += z->fdx; // advance to position for current scanline
3221- step = &((*step)->next); // advance through list
3222- }
3223-
3224- ++y;
3225- ++j;
3226- }
3227-
3228- stbtt__hheap_cleanup(&hh, userdata);
3229-
3230- if (scanline != scanline_data)
3231- STBTT_free(scanline, userdata);
3232-}
3233-#else
3234-#error "Unrecognized value of STBTT_RASTERIZER_VERSION"
3235-#endif
3236-
3237-#define STBTT__COMPARE(a,b) ((a)->y0 < (b)->y0)
3238-
3239-static void stbtt__sort_edges_ins_sort(stbtt__edge *p, int n)
3240-{
3241- int i,j;
3242- for (i=1; i < n; ++i) {
3243- stbtt__edge t = p[i], *a = &t;
3244- j = i;
3245- while (j > 0) {
3246- stbtt__edge *b = &p[j-1];
3247- int c = STBTT__COMPARE(a,b);
3248- if (!c) break;
3249- p[j] = p[j-1];
3250- --j;
3251- }
3252- if (i != j)
3253- p[j] = t;
3254- }
3255-}
3256-
3257-static void stbtt__sort_edges_quicksort(stbtt__edge *p, int n)
3258-{
3259- /* threshold for transitioning to insertion sort */
3260- while (n > 12) {
3261- stbtt__edge t;
3262- int c01,c12,c,m,i,j;
3263-
3264- /* compute median of three */
3265- m = n >> 1;
3266- c01 = STBTT__COMPARE(&p[0],&p[m]);
3267- c12 = STBTT__COMPARE(&p[m],&p[n-1]);
3268- /* if 0 >= mid >= end, or 0 < mid < end, then use mid */
3269- if (c01 != c12) {
3270- /* otherwise, we'll need to swap something else to middle */
3271- int z;
3272- c = STBTT__COMPARE(&p[0],&p[n-1]);
3273- /* 0>mid && mid<n: 0>n => n; 0<n => 0 */
3274- /* 0<mid && mid>n: 0>n => 0; 0<n => n */
3275- z = (c == c12) ? 0 : n-1;
3276- t = p[z];
3277- p[z] = p[m];
3278- p[m] = t;
3279- }
3280- /* now p[m] is the median-of-three */
3281- /* swap it to the beginning so it won't move around */
3282- t = p[0];
3283- p[0] = p[m];
3284- p[m] = t;
3285-
3286- /* partition loop */
3287- i=1;
3288- j=n-1;
3289- for(;;) {
3290- /* handling of equality is crucial here */
3291- /* for sentinels & efficiency with duplicates */
3292- for (;;++i) {
3293- if (!STBTT__COMPARE(&p[i], &p[0])) break;
3294- }
3295- for (;;--j) {
3296- if (!STBTT__COMPARE(&p[0], &p[j])) break;
3297- }
3298- /* make sure we haven't crossed */
3299- if (i >= j) break;
3300- t = p[i];
3301- p[i] = p[j];
3302- p[j] = t;
3303-
3304- ++i;
3305- --j;
3306- }
3307- /* recurse on smaller side, iterate on larger */
3308- if (j < (n-i)) {
3309- stbtt__sort_edges_quicksort(p,j);
3310- p = p+i;
3311- n = n-i;
3312- } else {
3313- stbtt__sort_edges_quicksort(p+i, n-i);
3314- n = j;
3315- }
3316- }
3317-}
3318-
3319-static void stbtt__sort_edges(stbtt__edge *p, int n)
3320-{
3321- stbtt__sort_edges_quicksort(p, n);
3322- stbtt__sort_edges_ins_sort(p, n);
3323-}
3324-
3325-typedef struct
3326-{
3327- float x,y;
3328-} stbtt__point;
3329-
3330-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)
3331-{
3332- float y_scale_inv = invert ? -scale_y : scale_y;
3333- stbtt__edge *e;
3334- int n,i,j,k,m;
3335-#if STBTT_RASTERIZER_VERSION == 1
3336- int vsubsample = result->h < 8 ? 15 : 5;
3337-#elif STBTT_RASTERIZER_VERSION == 2
3338- int vsubsample = 1;
3339-#else
3340- #error "Unrecognized value of STBTT_RASTERIZER_VERSION"
3341-#endif
3342- // vsubsample should divide 255 evenly; otherwise we won't reach full opacity
3343-
3344- // now we have to blow out the windings into explicit edge lists
3345- n = 0;
3346- for (i=0; i < windings; ++i)
3347- n += wcount[i];
3348-
3349- e = (stbtt__edge *) STBTT_malloc(sizeof(*e) * (n+1), userdata); // add an extra one as a sentinel
3350- if (e == 0) return;
3351- n = 0;
3352-
3353- m=0;
3354- for (i=0; i < windings; ++i) {
3355- stbtt__point *p = pts + m;
3356- m += wcount[i];
3357- j = wcount[i]-1;
3358- for (k=0; k < wcount[i]; j=k++) {
3359- int a=k,b=j;
3360- // skip the edge if horizontal
3361- if (p[j].y == p[k].y)
3362- continue;
3363- // add edge from j to k to the list
3364- e[n].invert = 0;
3365- if (invert ? p[j].y > p[k].y : p[j].y < p[k].y) {
3366- e[n].invert = 1;
3367- a=j,b=k;
3368- }
3369- e[n].x0 = p[a].x * scale_x + shift_x;
3370- e[n].y0 = (p[a].y * y_scale_inv + shift_y) * vsubsample;
3371- e[n].x1 = p[b].x * scale_x + shift_x;
3372- e[n].y1 = (p[b].y * y_scale_inv + shift_y) * vsubsample;
3373- ++n;
3374- }
3375- }
3376-
3377- // now sort the edges by their highest point (should snap to integer, and then by x)
3378- //STBTT_sort(e, n, sizeof(e[0]), stbtt__edge_compare);
3379- stbtt__sort_edges(e, n);
3380-
3381- // now, traverse the scanlines and find the intersections on each scanline, use xor winding rule
3382- stbtt__rasterize_sorted_edges(result, e, n, vsubsample, off_x, off_y, userdata);
3383-
3384- STBTT_free(e, userdata);
3385-}
3386-
3387-static void stbtt__add_point(stbtt__point *points, int n, float x, float y)
3388-{
3389- if (!points) return; // during first pass, it's unallocated
3390- points[n].x = x;
3391- points[n].y = y;
3392-}
3393-
3394-// tessellate until threshold p is happy... @TODO warped to compensate for non-linear stretching
3395-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)
3396-{
3397- // midpoint
3398- float mx = (x0 + 2*x1 + x2)/4;
3399- float my = (y0 + 2*y1 + y2)/4;
3400- // versus directly drawn line
3401- float dx = (x0+x2)/2 - mx;
3402- float dy = (y0+y2)/2 - my;
3403- if (n > 16) // 65536 segments on one curve better be enough!
3404- return 1;
3405- if (dx*dx+dy*dy > objspace_flatness_squared) { // half-pixel error allowed... need to be smaller if AA
3406- stbtt__tesselate_curve(points, num_points, x0,y0, (x0+x1)/2.0f,(y0+y1)/2.0f, mx,my, objspace_flatness_squared,n+1);
3407- stbtt__tesselate_curve(points, num_points, mx,my, (x1+x2)/2.0f,(y1+y2)/2.0f, x2,y2, objspace_flatness_squared,n+1);
3408- } else {
3409- stbtt__add_point(points, *num_points,x2,y2);
3410- *num_points = *num_points+1;
3411- }
3412- return 1;
3413-}
3414-
3415-static void stbtt__tesselate_cubic(stbtt__point *points, int *num_points, float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3, float objspace_flatness_squared, int n)
3416-{
3417- // @TODO this "flatness" calculation is just made-up nonsense that seems to work well enough
3418- float dx0 = x1-x0;
3419- float dy0 = y1-y0;
3420- float dx1 = x2-x1;
3421- float dy1 = y2-y1;
3422- float dx2 = x3-x2;
3423- float dy2 = y3-y2;
3424- float dx = x3-x0;
3425- float dy = y3-y0;
3426- float longlen = (float) (STBTT_sqrt(dx0*dx0+dy0*dy0)+STBTT_sqrt(dx1*dx1+dy1*dy1)+STBTT_sqrt(dx2*dx2+dy2*dy2));
3427- float shortlen = (float) STBTT_sqrt(dx*dx+dy*dy);
3428- float flatness_squared = longlen*longlen-shortlen*shortlen;
3429-
3430- if (n > 16) // 65536 segments on one curve better be enough!
3431- return;
3432-
3433- if (flatness_squared > objspace_flatness_squared) {
3434- float x01 = (x0+x1)/2;
3435- float y01 = (y0+y1)/2;
3436- float x12 = (x1+x2)/2;
3437- float y12 = (y1+y2)/2;
3438- float x23 = (x2+x3)/2;
3439- float y23 = (y2+y3)/2;
3440-
3441- float xa = (x01+x12)/2;
3442- float ya = (y01+y12)/2;
3443- float xb = (x12+x23)/2;
3444- float yb = (y12+y23)/2;
3445-
3446- float mx = (xa+xb)/2;
3447- float my = (ya+yb)/2;
3448-
3449- stbtt__tesselate_cubic(points, num_points, x0,y0, x01,y01, xa,ya, mx,my, objspace_flatness_squared,n+1);
3450- stbtt__tesselate_cubic(points, num_points, mx,my, xb,yb, x23,y23, x3,y3, objspace_flatness_squared,n+1);
3451- } else {
3452- stbtt__add_point(points, *num_points,x3,y3);
3453- *num_points = *num_points+1;
3454- }
3455-}
3456-
3457-// returns number of contours
3458-static stbtt__point *stbtt_FlattenCurves(stbtt_vertex *vertices, int num_verts, float objspace_flatness, int **contour_lengths, int *num_contours, void *userdata)
3459-{
3460- stbtt__point *points=0;
3461- int num_points=0;
3462-
3463- float objspace_flatness_squared = objspace_flatness * objspace_flatness;
3464- int i,n=0,start=0, pass;
3465-
3466- // count how many "moves" there are to get the contour count
3467- for (i=0; i < num_verts; ++i)
3468- if (vertices[i].type == STBTT_vmove)
3469- ++n;
3470-
3471- *num_contours = n;
3472- if (n == 0) return 0;
3473-
3474- *contour_lengths = (int *) STBTT_malloc(sizeof(**contour_lengths) * n, userdata);
3475-
3476- if (*contour_lengths == 0) {
3477- *num_contours = 0;
3478- return 0;
3479- }
3480-
3481- // make two passes through the points so we don't need to realloc
3482- for (pass=0; pass < 2; ++pass) {
3483- float x=0,y=0;
3484- if (pass == 1) {
3485- points = (stbtt__point *) STBTT_malloc(num_points * sizeof(points[0]), userdata);
3486- if (points == NULL) goto error;
3487- }
3488- num_points = 0;
3489- n= -1;
3490- for (i=0; i < num_verts; ++i) {
3491- switch (vertices[i].type) {
3492- case STBTT_vmove:
3493- // start the next contour
3494- if (n >= 0)
3495- (*contour_lengths)[n] = num_points - start;
3496- ++n;
3497- start = num_points;
3498-
3499- x = vertices[i].x, y = vertices[i].y;
3500- stbtt__add_point(points, num_points++, x,y);
3501- break;
3502- case STBTT_vline:
3503- x = vertices[i].x, y = vertices[i].y;
3504- stbtt__add_point(points, num_points++, x, y);
3505- break;
3506- case STBTT_vcurve:
3507- stbtt__tesselate_curve(points, &num_points, x,y,
3508- vertices[i].cx, vertices[i].cy,
3509- vertices[i].x, vertices[i].y,
3510- objspace_flatness_squared, 0);
3511- x = vertices[i].x, y = vertices[i].y;
3512- break;
3513- case STBTT_vcubic:
3514- stbtt__tesselate_cubic(points, &num_points, x,y,
3515- vertices[i].cx, vertices[i].cy,
3516- vertices[i].cx1, vertices[i].cy1,
3517- vertices[i].x, vertices[i].y,
3518- objspace_flatness_squared, 0);
3519- x = vertices[i].x, y = vertices[i].y;
3520- break;
3521- }
3522- }
3523- (*contour_lengths)[n] = num_points - start;
3524- }
3525-
3526- return points;
3527-error:
3528- STBTT_free(points, userdata);
3529- STBTT_free(*contour_lengths, userdata);
3530- *contour_lengths = 0;
3531- *num_contours = 0;
3532- return NULL;
3533-}
3534-
3535-STBTT_DEF 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)
3536-{
3537- float scale = scale_x > scale_y ? scale_y : scale_x;
3538- int winding_count = 0;
3539- int *winding_lengths = NULL;
3540- stbtt__point *windings = stbtt_FlattenCurves(vertices, num_verts, flatness_in_pixels / scale, &winding_lengths, &winding_count, userdata);
3541- if (windings) {
3542- stbtt__rasterize(result, windings, winding_lengths, winding_count, scale_x, scale_y, shift_x, shift_y, x_off, y_off, invert, userdata);
3543- STBTT_free(winding_lengths, userdata);
3544- STBTT_free(windings, userdata);
3545- }
3546-}
3547-
3548-STBTT_DEF void stbtt_FreeBitmap(unsigned char *bitmap, void *userdata)
3549-{
3550- STBTT_free(bitmap, userdata);
3551-}
3552-
3553-STBTT_DEF 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)
3554-{
3555- int ix0,iy0,ix1,iy1;
3556- stbtt__bitmap gbm;
3557- stbtt_vertex *vertices;
3558- int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices);
3559-
3560- if (scale_x == 0) scale_x = scale_y;
3561- if (scale_y == 0) {
3562- if (scale_x == 0) {
3563- STBTT_free(vertices, info->userdata);
3564- return NULL;
3565- }
3566- scale_y = scale_x;
3567- }
3568-
3569- stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x, shift_y, &ix0,&iy0,&ix1,&iy1);
3570-
3571- // now we get the size
3572- gbm.w = (ix1 - ix0);
3573- gbm.h = (iy1 - iy0);
3574- gbm.pixels = NULL; // in case we error
3575-
3576- if (width ) *width = gbm.w;
3577- if (height) *height = gbm.h;
3578- if (xoff ) *xoff = ix0;
3579- if (yoff ) *yoff = iy0;
3580-
3581- if (gbm.w && gbm.h) {
3582- gbm.pixels = (unsigned char *) STBTT_malloc(gbm.w * gbm.h, info->userdata);
3583- if (gbm.pixels) {
3584- gbm.stride = gbm.w;
3585-
3586- stbtt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, shift_x, shift_y, ix0, iy0, 1, info->userdata);
3587- }
3588- }
3589- STBTT_free(vertices, info->userdata);
3590- return gbm.pixels;
3591-}
3592-
3593-STBTT_DEF unsigned char *stbtt_GetGlyphBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int glyph, int *width, int *height, int *xoff, int *yoff)
3594-{
3595- return stbtt_GetGlyphBitmapSubpixel(info, scale_x, scale_y, 0.0f, 0.0f, glyph, width, height, xoff, yoff);
3596-}
3597-
3598-STBTT_DEF 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)
3599-{
3600- int ix0,iy0;
3601- stbtt_vertex *vertices;
3602- int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices);
3603- stbtt__bitmap gbm;
3604-
3605- stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x, shift_y, &ix0,&iy0,0,0);
3606- gbm.pixels = output;
3607- gbm.w = out_w;
3608- gbm.h = out_h;
3609- gbm.stride = out_stride;
3610-
3611- if (gbm.w && gbm.h)
3612- stbtt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, shift_x, shift_y, ix0,iy0, 1, info->userdata);
3613-
3614- STBTT_free(vertices, info->userdata);
3615-}
3616-
3617-STBTT_DEF 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)
3618-{
3619- stbtt_MakeGlyphBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, 0.0f,0.0f, glyph);
3620-}
3621-
3622-STBTT_DEF 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)
3623-{
3624- return stbtt_GetGlyphBitmapSubpixel(info, scale_x, scale_y,shift_x,shift_y, stbtt_FindGlyphIndex(info,codepoint), width,height,xoff,yoff);
3625-}
3626-
3627-STBTT_DEF void stbtt_MakeCodepointBitmapSubpixelPrefilter(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 oversample_x, int oversample_y, float *sub_x, float *sub_y, int codepoint)
3628-{
3629- stbtt_MakeGlyphBitmapSubpixelPrefilter(info, output, out_w, out_h, out_stride, scale_x, scale_y, shift_x, shift_y, oversample_x, oversample_y, sub_x, sub_y, stbtt_FindGlyphIndex(info,codepoint));
3630-}
3631-
3632-STBTT_DEF 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)
3633-{
3634- stbtt_MakeGlyphBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, shift_x, shift_y, stbtt_FindGlyphIndex(info,codepoint));
3635-}
3636-
3637-STBTT_DEF unsigned char *stbtt_GetCodepointBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int codepoint, int *width, int *height, int *xoff, int *yoff)
3638-{
3639- return stbtt_GetCodepointBitmapSubpixel(info, scale_x, scale_y, 0.0f,0.0f, codepoint, width,height,xoff,yoff);
3640-}
3641-
3642-STBTT_DEF 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)
3643-{
3644- stbtt_MakeCodepointBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, 0.0f,0.0f, codepoint);
3645-}
3646-
3647-//////////////////////////////////////////////////////////////////////////////
3648-//
3649-// bitmap baking
3650-//
3651-// This is SUPER-CRAPPY packing to keep source code small
3652-
3653-static int stbtt_BakeFontBitmap_internal(unsigned char *data, int offset, // font location (use offset=0 for plain .ttf)
3654- float pixel_height, // height of font in pixels
3655- unsigned char *pixels, int pw, int ph, // bitmap to be filled in
3656- int first_char, int num_chars, // characters to bake
3657- stbtt_bakedchar *chardata)
3658-{
3659- float scale;
3660- int x,y,bottom_y, i;
3661- stbtt_fontinfo f;
3662- f.userdata = NULL;
3663- if (!stbtt_InitFont(&f, data, offset))
3664- return -1;
3665- STBTT_memset(pixels, 0, pw*ph); // background of 0 around pixels
3666- x=y=1;
3667- bottom_y = 1;
3668-
3669- scale = stbtt_ScaleForPixelHeight(&f, pixel_height);
3670-
3671- for (i=0; i < num_chars; ++i) {
3672- int advance, lsb, x0,y0,x1,y1,gw,gh;
3673- int g = stbtt_FindGlyphIndex(&f, first_char + i);
3674- stbtt_GetGlyphHMetrics(&f, g, &advance, &lsb);
3675- stbtt_GetGlyphBitmapBox(&f, g, scale,scale, &x0,&y0,&x1,&y1);
3676- gw = x1-x0;
3677- gh = y1-y0;
3678- if (x + gw + 1 >= pw)
3679- y = bottom_y, x = 1; // advance to next row
3680- if (y + gh + 1 >= ph) // check if it fits vertically AFTER potentially moving to next row
3681- return -i;
3682- STBTT_assert(x+gw < pw);
3683- STBTT_assert(y+gh < ph);
3684- stbtt_MakeGlyphBitmap(&f, pixels+x+y*pw, gw,gh,pw, scale,scale, g);
3685- chardata[i].x0 = (stbtt_int16) x;
3686- chardata[i].y0 = (stbtt_int16) y;
3687- chardata[i].x1 = (stbtt_int16) (x + gw);
3688- chardata[i].y1 = (stbtt_int16) (y + gh);
3689- chardata[i].xadvance = scale * advance;
3690- chardata[i].xoff = (float) x0;
3691- chardata[i].yoff = (float) y0;
3692- x = x + gw + 1;
3693- if (y+gh+1 > bottom_y)
3694- bottom_y = y+gh+1;
3695- }
3696- return bottom_y;
3697-}
3698-
3699-STBTT_DEF void stbtt_GetBakedQuad(const stbtt_bakedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int opengl_fillrule)
3700-{
3701- float d3d_bias = opengl_fillrule ? 0 : -0.5f;
3702- float ipw = 1.0f / pw, iph = 1.0f / ph;
3703- const stbtt_bakedchar *b = chardata + char_index;
3704- int round_x = STBTT_ifloor((*xpos + b->xoff) + 0.5f);
3705- int round_y = STBTT_ifloor((*ypos + b->yoff) + 0.5f);
3706-
3707- q->x0 = round_x + d3d_bias;
3708- q->y0 = round_y + d3d_bias;
3709- q->x1 = round_x + b->x1 - b->x0 + d3d_bias;
3710- q->y1 = round_y + b->y1 - b->y0 + d3d_bias;
3711-
3712- q->s0 = b->x0 * ipw;
3713- q->t0 = b->y0 * iph;
3714- q->s1 = b->x1 * ipw;
3715- q->t1 = b->y1 * iph;
3716-
3717- *xpos += b->xadvance;
3718-}
3719-
3720-//////////////////////////////////////////////////////////////////////////////
3721-//
3722-// rectangle packing replacement routines if you don't have stb_rect_pack.h
3723-//
3724-
3725-#ifndef STB_RECT_PACK_VERSION
3726-
3727-typedef int stbrp_coord;
3728-
3729-////////////////////////////////////////////////////////////////////////////////////
3730-// //
3731-// //
3732-// COMPILER WARNING ?!?!? //
3733-// //
3734-// //
3735-// if you get a compile warning due to these symbols being defined more than //
3736-// once, move #include "stb_rect_pack.h" before #include "stb_truetype.h" //
3737-// //
3738-////////////////////////////////////////////////////////////////////////////////////
3739-
3740-typedef struct
3741-{
3742- int width,height;
3743- int x,y,bottom_y;
3744-} stbrp_context;
3745-
3746-typedef struct
3747-{
3748- unsigned char x;
3749-} stbrp_node;
3750-
3751-struct stbrp_rect
3752-{
3753- stbrp_coord x,y;
3754- int id,w,h,was_packed;
3755-};
3756-
3757-static void stbrp_init_target(stbrp_context *con, int pw, int ph, stbrp_node *nodes, int num_nodes)
3758-{
3759- con->width = pw;
3760- con->height = ph;
3761- con->x = 0;
3762- con->y = 0;
3763- con->bottom_y = 0;
3764- STBTT__NOTUSED(nodes);
3765- STBTT__NOTUSED(num_nodes);
3766-}
3767-
3768-static void stbrp_pack_rects(stbrp_context *con, stbrp_rect *rects, int num_rects)
3769-{
3770- int i;
3771- for (i=0; i < num_rects; ++i) {
3772- if (con->x + rects[i].w > con->width) {
3773- con->x = 0;
3774- con->y = con->bottom_y;
3775- }
3776- if (con->y + rects[i].h > con->height)
3777- break;
3778- rects[i].x = con->x;
3779- rects[i].y = con->y;
3780- rects[i].was_packed = 1;
3781- con->x += rects[i].w;
3782- if (con->y + rects[i].h > con->bottom_y)
3783- con->bottom_y = con->y + rects[i].h;
3784- }
3785- for ( ; i < num_rects; ++i)
3786- rects[i].was_packed = 0;
3787-}
3788-#endif
3789-
3790-//////////////////////////////////////////////////////////////////////////////
3791-//
3792-// bitmap baking
3793-//
3794-// This is SUPER-AWESOME (tm Ryan Gordon) packing using stb_rect_pack.h. If
3795-// stb_rect_pack.h isn't available, it uses the BakeFontBitmap strategy.
3796-
3797-STBTT_DEF int stbtt_PackBegin(stbtt_pack_context *spc, unsigned char *pixels, int pw, int ph, int stride_in_bytes, int padding, void *alloc_context)
3798-{
3799- stbrp_context *context = (stbrp_context *) STBTT_malloc(sizeof(*context) ,alloc_context);
3800- int num_nodes = pw - padding;
3801- stbrp_node *nodes = (stbrp_node *) STBTT_malloc(sizeof(*nodes ) * num_nodes,alloc_context);
3802-
3803- if (context == NULL || nodes == NULL) {
3804- if (context != NULL) STBTT_free(context, alloc_context);
3805- if (nodes != NULL) STBTT_free(nodes , alloc_context);
3806- return 0;
3807- }
3808-
3809- spc->user_allocator_context = alloc_context;
3810- spc->width = pw;
3811- spc->height = ph;
3812- spc->pixels = pixels;
3813- spc->pack_info = context;
3814- spc->nodes = nodes;
3815- spc->padding = padding;
3816- spc->stride_in_bytes = stride_in_bytes != 0 ? stride_in_bytes : pw;
3817- spc->h_oversample = 1;
3818- spc->v_oversample = 1;
3819- spc->skip_missing = 0;
3820-
3821- stbrp_init_target(context, pw-padding, ph-padding, nodes, num_nodes);
3822-
3823- if (pixels)
3824- STBTT_memset(pixels, 0, pw*ph); // background of 0 around pixels
3825-
3826- return 1;
3827-}
3828-
3829-STBTT_DEF void stbtt_PackEnd (stbtt_pack_context *spc)
3830-{
3831- STBTT_free(spc->nodes , spc->user_allocator_context);
3832- STBTT_free(spc->pack_info, spc->user_allocator_context);
3833-}
3834-
3835-STBTT_DEF void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h_oversample, unsigned int v_oversample)
3836-{
3837- STBTT_assert(h_oversample <= STBTT_MAX_OVERSAMPLE);
3838- STBTT_assert(v_oversample <= STBTT_MAX_OVERSAMPLE);
3839- if (h_oversample <= STBTT_MAX_OVERSAMPLE)
3840- spc->h_oversample = h_oversample;
3841- if (v_oversample <= STBTT_MAX_OVERSAMPLE)
3842- spc->v_oversample = v_oversample;
3843-}
3844-
3845-STBTT_DEF void stbtt_PackSetSkipMissingCodepoints(stbtt_pack_context *spc, int skip)
3846-{
3847- spc->skip_missing = skip;
3848-}
3849-
3850-#define STBTT__OVER_MASK (STBTT_MAX_OVERSAMPLE-1)
3851-
3852-static void stbtt__h_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes, unsigned int kernel_width)
3853-{
3854- unsigned char buffer[STBTT_MAX_OVERSAMPLE];
3855- int safe_w = w - kernel_width;
3856- int j;
3857- STBTT_memset(buffer, 0, STBTT_MAX_OVERSAMPLE); // suppress bogus warning from VS2013 -analyze
3858- for (j=0; j < h; ++j) {
3859- int i;
3860- unsigned int total;
3861- STBTT_memset(buffer, 0, kernel_width);
3862-
3863- total = 0;
3864-
3865- // make kernel_width a constant in common cases so compiler can optimize out the divide
3866- switch (kernel_width) {
3867- case 2:
3868- for (i=0; i <= safe_w; ++i) {
3869- total += pixels[i] - buffer[i & STBTT__OVER_MASK];
3870- buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i];
3871- pixels[i] = (unsigned char) (total / 2);
3872- }
3873- break;
3874- case 3:
3875- for (i=0; i <= safe_w; ++i) {
3876- total += pixels[i] - buffer[i & STBTT__OVER_MASK];
3877- buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i];
3878- pixels[i] = (unsigned char) (total / 3);
3879- }
3880- break;
3881- case 4:
3882- for (i=0; i <= safe_w; ++i) {
3883- total += pixels[i] - buffer[i & STBTT__OVER_MASK];
3884- buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i];
3885- pixels[i] = (unsigned char) (total / 4);
3886- }
3887- break;
3888- case 5:
3889- for (i=0; i <= safe_w; ++i) {
3890- total += pixels[i] - buffer[i & STBTT__OVER_MASK];
3891- buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i];
3892- pixels[i] = (unsigned char) (total / 5);
3893- }
3894- break;
3895- default:
3896- for (i=0; i <= safe_w; ++i) {
3897- total += pixels[i] - buffer[i & STBTT__OVER_MASK];
3898- buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i];
3899- pixels[i] = (unsigned char) (total / kernel_width);
3900- }
3901- break;
3902- }
3903-
3904- for (; i < w; ++i) {
3905- STBTT_assert(pixels[i] == 0);
3906- total -= buffer[i & STBTT__OVER_MASK];
3907- pixels[i] = (unsigned char) (total / kernel_width);
3908- }
3909-
3910- pixels += stride_in_bytes;
3911- }
3912-}
3913-
3914-static void stbtt__v_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes, unsigned int kernel_width)
3915-{
3916- unsigned char buffer[STBTT_MAX_OVERSAMPLE];
3917- int safe_h = h - kernel_width;
3918- int j;
3919- STBTT_memset(buffer, 0, STBTT_MAX_OVERSAMPLE); // suppress bogus warning from VS2013 -analyze
3920- for (j=0; j < w; ++j) {
3921- int i;
3922- unsigned int total;
3923- STBTT_memset(buffer, 0, kernel_width);
3924-
3925- total = 0;
3926-
3927- // make kernel_width a constant in common cases so compiler can optimize out the divide
3928- switch (kernel_width) {
3929- case 2:
3930- for (i=0; i <= safe_h; ++i) {
3931- total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK];
3932- buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes];
3933- pixels[i*stride_in_bytes] = (unsigned char) (total / 2);
3934- }
3935- break;
3936- case 3:
3937- for (i=0; i <= safe_h; ++i) {
3938- total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK];
3939- buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes];
3940- pixels[i*stride_in_bytes] = (unsigned char) (total / 3);
3941- }
3942- break;
3943- case 4:
3944- for (i=0; i <= safe_h; ++i) {
3945- total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK];
3946- buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes];
3947- pixels[i*stride_in_bytes] = (unsigned char) (total / 4);
3948- }
3949- break;
3950- case 5:
3951- for (i=0; i <= safe_h; ++i) {
3952- total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK];
3953- buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes];
3954- pixels[i*stride_in_bytes] = (unsigned char) (total / 5);
3955- }
3956- break;
3957- default:
3958- for (i=0; i <= safe_h; ++i) {
3959- total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK];
3960- buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes];
3961- pixels[i*stride_in_bytes] = (unsigned char) (total / kernel_width);
3962- }
3963- break;
3964- }
3965-
3966- for (; i < h; ++i) {
3967- STBTT_assert(pixels[i*stride_in_bytes] == 0);
3968- total -= buffer[i & STBTT__OVER_MASK];
3969- pixels[i*stride_in_bytes] = (unsigned char) (total / kernel_width);
3970- }
3971-
3972- pixels += 1;
3973- }
3974-}
3975-
3976-static float stbtt__oversample_shift(int oversample)
3977-{
3978- if (!oversample)
3979- return 0.0f;
3980-
3981- // The prefilter is a box filter of width "oversample",
3982- // which shifts phase by (oversample - 1)/2 pixels in
3983- // oversampled space. We want to shift in the opposite
3984- // direction to counter this.
3985- return (float)-(oversample - 1) / (2.0f * (float)oversample);
3986-}
3987-
3988-// rects array must be big enough to accommodate all characters in the given ranges
3989-STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects)
3990-{
3991- int i,j,k;
3992-
3993- k=0;
3994- for (i=0; i < num_ranges; ++i) {
3995- float fh = ranges[i].font_size;
3996- float scale = fh > 0 ? stbtt_ScaleForPixelHeight(info, fh) : stbtt_ScaleForMappingEmToPixels(info, -fh);
3997- ranges[i].h_oversample = (unsigned char) spc->h_oversample;
3998- ranges[i].v_oversample = (unsigned char) spc->v_oversample;
3999- for (j=0; j < ranges[i].num_chars; ++j) {
4000- int x0,y0,x1,y1;
4001- int codepoint = ranges[i].array_of_unicode_codepoints == NULL ? ranges[i].first_unicode_codepoint_in_range + j : ranges[i].array_of_unicode_codepoints[j];
4002- int glyph = stbtt_FindGlyphIndex(info, codepoint);
4003- if (glyph == 0 && spc->skip_missing) {
4004- rects[k].w = rects[k].h = 0;
4005- } else {
4006- stbtt_GetGlyphBitmapBoxSubpixel(info,glyph,
4007- scale * spc->h_oversample,
4008- scale * spc->v_oversample,
4009- 0,0,
4010- &x0,&y0,&x1,&y1);
4011- rects[k].w = (stbrp_coord) (x1-x0 + spc->padding + spc->h_oversample-1);
4012- rects[k].h = (stbrp_coord) (y1-y0 + spc->padding + spc->v_oversample-1);
4013- }
4014- ++k;
4015- }
4016- }
4017-
4018- return k;
4019-}
4020-
4021-STBTT_DEF void stbtt_MakeGlyphBitmapSubpixelPrefilter(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 prefilter_x, int prefilter_y, float *sub_x, float *sub_y, int glyph)
4022-{
4023- stbtt_MakeGlyphBitmapSubpixel(info,
4024- output,
4025- out_w - (prefilter_x - 1),
4026- out_h - (prefilter_y - 1),
4027- out_stride,
4028- scale_x,
4029- scale_y,
4030- shift_x,
4031- shift_y,
4032- glyph);
4033-
4034- if (prefilter_x > 1)
4035- stbtt__h_prefilter(output, out_w, out_h, out_stride, prefilter_x);
4036-
4037- if (prefilter_y > 1)
4038- stbtt__v_prefilter(output, out_w, out_h, out_stride, prefilter_y);
4039-
4040- *sub_x = stbtt__oversample_shift(prefilter_x);
4041- *sub_y = stbtt__oversample_shift(prefilter_y);
4042-}
4043-
4044-// rects array must be big enough to accommodate all characters in the given ranges
4045-STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects)
4046-{
4047- int i,j,k, return_value = 1;
4048-
4049- // save current values
4050- int old_h_over = spc->h_oversample;
4051- int old_v_over = spc->v_oversample;
4052-
4053- k = 0;
4054- for (i=0; i < num_ranges; ++i) {
4055- float fh = ranges[i].font_size;
4056- float scale = fh > 0 ? stbtt_ScaleForPixelHeight(info, fh) : stbtt_ScaleForMappingEmToPixels(info, -fh);
4057- float recip_h,recip_v,sub_x,sub_y;
4058- spc->h_oversample = ranges[i].h_oversample;
4059- spc->v_oversample = ranges[i].v_oversample;
4060- recip_h = 1.0f / spc->h_oversample;
4061- recip_v = 1.0f / spc->v_oversample;
4062- sub_x = stbtt__oversample_shift(spc->h_oversample);
4063- sub_y = stbtt__oversample_shift(spc->v_oversample);
4064- for (j=0; j < ranges[i].num_chars; ++j) {
4065- stbrp_rect *r = &rects[k];
4066- if (r->was_packed && r->w != 0 && r->h != 0) {
4067- stbtt_packedchar *bc = &ranges[i].chardata_for_range[j];
4068- int advance, lsb, x0,y0,x1,y1;
4069- int codepoint = ranges[i].array_of_unicode_codepoints == NULL ? ranges[i].first_unicode_codepoint_in_range + j : ranges[i].array_of_unicode_codepoints[j];
4070- int glyph = stbtt_FindGlyphIndex(info, codepoint);
4071- stbrp_coord pad = (stbrp_coord) spc->padding;
4072-
4073- // pad on left and top
4074- r->x += pad;
4075- r->y += pad;
4076- r->w -= pad;
4077- r->h -= pad;
4078- stbtt_GetGlyphHMetrics(info, glyph, &advance, &lsb);
4079- stbtt_GetGlyphBitmapBox(info, glyph,
4080- scale * spc->h_oversample,
4081- scale * spc->v_oversample,
4082- &x0,&y0,&x1,&y1);
4083- stbtt_MakeGlyphBitmapSubpixel(info,
4084- spc->pixels + r->x + r->y*spc->stride_in_bytes,
4085- r->w - spc->h_oversample+1,
4086- r->h - spc->v_oversample+1,
4087- spc->stride_in_bytes,
4088- scale * spc->h_oversample,
4089- scale * spc->v_oversample,
4090- 0,0,
4091- glyph);
4092-
4093- if (spc->h_oversample > 1)
4094- stbtt__h_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes,
4095- r->w, r->h, spc->stride_in_bytes,
4096- spc->h_oversample);
4097-
4098- if (spc->v_oversample > 1)
4099- stbtt__v_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes,
4100- r->w, r->h, spc->stride_in_bytes,
4101- spc->v_oversample);
4102-
4103- bc->x0 = (stbtt_int16) r->x;
4104- bc->y0 = (stbtt_int16) r->y;
4105- bc->x1 = (stbtt_int16) (r->x + r->w);
4106- bc->y1 = (stbtt_int16) (r->y + r->h);
4107- bc->xadvance = scale * advance;
4108- bc->xoff = (float) x0 * recip_h + sub_x;
4109- bc->yoff = (float) y0 * recip_v + sub_y;
4110- bc->xoff2 = (x0 + r->w) * recip_h + sub_x;
4111- bc->yoff2 = (y0 + r->h) * recip_v + sub_y;
4112- } else {
4113- return_value = 0; // if any fail, report failure
4114- }
4115-
4116- ++k;
4117- }
4118- }
4119-
4120- // restore original values
4121- spc->h_oversample = old_h_over;
4122- spc->v_oversample = old_v_over;
4123-
4124- return return_value;
4125-}
4126-
4127-STBTT_DEF void stbtt_PackFontRangesPackRects(stbtt_pack_context *spc, stbrp_rect *rects, int num_rects)
4128-{
4129- stbrp_pack_rects((stbrp_context *) spc->pack_info, rects, num_rects);
4130-}
4131-
4132-STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges)
4133-{
4134- stbtt_fontinfo info;
4135- int i,j,n, return_value = 1;
4136- //stbrp_context *context = (stbrp_context *) spc->pack_info;
4137- stbrp_rect *rects;
4138-
4139- // flag all characters as NOT packed
4140- for (i=0; i < num_ranges; ++i)
4141- for (j=0; j < ranges[i].num_chars; ++j)
4142- ranges[i].chardata_for_range[j].x0 =
4143- ranges[i].chardata_for_range[j].y0 =
4144- ranges[i].chardata_for_range[j].x1 =
4145- ranges[i].chardata_for_range[j].y1 = 0;
4146-
4147- n = 0;
4148- for (i=0; i < num_ranges; ++i)
4149- n += ranges[i].num_chars;
4150-
4151- rects = (stbrp_rect *) STBTT_malloc(sizeof(*rects) * n, spc->user_allocator_context);
4152- if (rects == NULL)
4153- return 0;
4154-
4155- info.userdata = spc->user_allocator_context;
4156- stbtt_InitFont(&info, fontdata, stbtt_GetFontOffsetForIndex(fontdata,font_index));
4157-
4158- n = stbtt_PackFontRangesGatherRects(spc, &info, ranges, num_ranges, rects);
4159-
4160- stbtt_PackFontRangesPackRects(spc, rects, n);
4161-
4162- return_value = stbtt_PackFontRangesRenderIntoRects(spc, &info, ranges, num_ranges, rects);
4163-
4164- STBTT_free(rects, spc->user_allocator_context);
4165- return return_value;
4166-}
4167-
4168-STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, float font_size,
4169- int first_unicode_codepoint_in_range, int num_chars_in_range, stbtt_packedchar *chardata_for_range)
4170-{
4171- stbtt_pack_range range;
4172- range.first_unicode_codepoint_in_range = first_unicode_codepoint_in_range;
4173- range.array_of_unicode_codepoints = NULL;
4174- range.num_chars = num_chars_in_range;
4175- range.chardata_for_range = chardata_for_range;
4176- range.font_size = font_size;
4177- return stbtt_PackFontRanges(spc, fontdata, font_index, &range, 1);
4178-}
4179-
4180-STBTT_DEF void stbtt_GetScaledFontVMetrics(const unsigned char *fontdata, int index, float size, float *ascent, float *descent, float *lineGap)
4181-{
4182- int i_ascent, i_descent, i_lineGap;
4183- float scale;
4184- stbtt_fontinfo info;
4185- stbtt_InitFont(&info, fontdata, stbtt_GetFontOffsetForIndex(fontdata, index));
4186- scale = size > 0 ? stbtt_ScaleForPixelHeight(&info, size) : stbtt_ScaleForMappingEmToPixels(&info, -size);
4187- stbtt_GetFontVMetrics(&info, &i_ascent, &i_descent, &i_lineGap);
4188- *ascent = (float) i_ascent * scale;
4189- *descent = (float) i_descent * scale;
4190- *lineGap = (float) i_lineGap * scale;
4191-}
4192-
4193-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)
4194-{
4195- float ipw = 1.0f / pw, iph = 1.0f / ph;
4196- const stbtt_packedchar *b = chardata + char_index;
4197-
4198- if (align_to_integer) {
4199- float x = (float) STBTT_ifloor((*xpos + b->xoff) + 0.5f);
4200- float y = (float) STBTT_ifloor((*ypos + b->yoff) + 0.5f);
4201- q->x0 = x;
4202- q->y0 = y;
4203- q->x1 = x + b->xoff2 - b->xoff;
4204- q->y1 = y + b->yoff2 - b->yoff;
4205- } else {
4206- q->x0 = *xpos + b->xoff;
4207- q->y0 = *ypos + b->yoff;
4208- q->x1 = *xpos + b->xoff2;
4209- q->y1 = *ypos + b->yoff2;
4210- }
4211-
4212- q->s0 = b->x0 * ipw;
4213- q->t0 = b->y0 * iph;
4214- q->s1 = b->x1 * ipw;
4215- q->t1 = b->y1 * iph;
4216-
4217- *xpos += b->xadvance;
4218-}
4219-
4220-//////////////////////////////////////////////////////////////////////////////
4221-//
4222-// sdf computation
4223-//
4224-
4225-#define STBTT_min(a,b) ((a) < (b) ? (a) : (b))
4226-#define STBTT_max(a,b) ((a) < (b) ? (b) : (a))
4227-
4228-static int stbtt__ray_intersect_bezier(float orig[2], float ray[2], float q0[2], float q1[2], float q2[2], float hits[2][2])
4229-{
4230- float q0perp = q0[1]*ray[0] - q0[0]*ray[1];
4231- float q1perp = q1[1]*ray[0] - q1[0]*ray[1];
4232- float q2perp = q2[1]*ray[0] - q2[0]*ray[1];
4233- float roperp = orig[1]*ray[0] - orig[0]*ray[1];
4234-
4235- float a = q0perp - 2*q1perp + q2perp;
4236- float b = q1perp - q0perp;
4237- float c = q0perp - roperp;
4238-
4239- float s0 = 0., s1 = 0.;
4240- int num_s = 0;
4241-
4242- if (a != 0.0) {
4243- float discr = b*b - a*c;
4244- if (discr > 0.0) {
4245- float rcpna = -1 / a;
4246- float d = (float) STBTT_sqrt(discr);
4247- s0 = (b+d) * rcpna;
4248- s1 = (b-d) * rcpna;
4249- if (s0 >= 0.0 && s0 <= 1.0)
4250- num_s = 1;
4251- if (d > 0.0 && s1 >= 0.0 && s1 <= 1.0) {
4252- if (num_s == 0) s0 = s1;
4253- ++num_s;
4254- }
4255- }
4256- } else {
4257- // 2*b*s + c = 0
4258- // s = -c / (2*b)
4259- s0 = c / (-2 * b);
4260- if (s0 >= 0.0 && s0 <= 1.0)
4261- num_s = 1;
4262- }
4263-
4264- if (num_s == 0)
4265- return 0;
4266- else {
4267- float rcp_len2 = 1 / (ray[0]*ray[0] + ray[1]*ray[1]);
4268- float rayn_x = ray[0] * rcp_len2, rayn_y = ray[1] * rcp_len2;
4269-
4270- float q0d = q0[0]*rayn_x + q0[1]*rayn_y;
4271- float q1d = q1[0]*rayn_x + q1[1]*rayn_y;
4272- float q2d = q2[0]*rayn_x + q2[1]*rayn_y;
4273- float rod = orig[0]*rayn_x + orig[1]*rayn_y;
4274-
4275- float q10d = q1d - q0d;
4276- float q20d = q2d - q0d;
4277- float q0rd = q0d - rod;
4278-
4279- hits[0][0] = q0rd + s0*(2.0f - 2.0f*s0)*q10d + s0*s0*q20d;
4280- hits[0][1] = a*s0+b;
4281-
4282- if (num_s > 1) {
4283- hits[1][0] = q0rd + s1*(2.0f - 2.0f*s1)*q10d + s1*s1*q20d;
4284- hits[1][1] = a*s1+b;
4285- return 2;
4286- } else {
4287- return 1;
4288- }
4289- }
4290-}
4291-
4292-static int equal(float *a, float *b)
4293-{
4294- return (a[0] == b[0] && a[1] == b[1]);
4295-}
4296-
4297-static int stbtt__compute_crossings_x(float x, float y, int nverts, stbtt_vertex *verts)
4298-{
4299- int i;
4300- float orig[2], ray[2] = { 1, 0 };
4301- float y_frac;
4302- int winding = 0;
4303-
4304- orig[0] = x;
4305- //orig[1] = y; // [DEAR IMGUI] commmented double assignment
4306-
4307- // make sure y never passes through a vertex of the shape
4308- y_frac = (float) STBTT_fmod(y, 1.0f);
4309- if (y_frac < 0.01f)
4310- y += 0.01f;
4311- else if (y_frac > 0.99f)
4312- y -= 0.01f;
4313- orig[1] = y;
4314-
4315- // test a ray from (-infinity,y) to (x,y)
4316- for (i=0; i < nverts; ++i) {
4317- if (verts[i].type == STBTT_vline) {
4318- int x0 = (int) verts[i-1].x, y0 = (int) verts[i-1].y;
4319- int x1 = (int) verts[i ].x, y1 = (int) verts[i ].y;
4320- if (y > STBTT_min(y0,y1) && y < STBTT_max(y0,y1) && x > STBTT_min(x0,x1)) {
4321- float x_inter = (y - y0) / (y1 - y0) * (x1-x0) + x0;
4322- if (x_inter < x)
4323- winding += (y0 < y1) ? 1 : -1;
4324- }
4325- }
4326- if (verts[i].type == STBTT_vcurve) {
4327- int x0 = (int) verts[i-1].x , y0 = (int) verts[i-1].y ;
4328- int x1 = (int) verts[i ].cx, y1 = (int) verts[i ].cy;
4329- int x2 = (int) verts[i ].x , y2 = (int) verts[i ].y ;
4330- int ax = STBTT_min(x0,STBTT_min(x1,x2)), ay = STBTT_min(y0,STBTT_min(y1,y2));
4331- int by = STBTT_max(y0,STBTT_max(y1,y2));
4332- if (y > ay && y < by && x > ax) {
4333- float q0[2],q1[2],q2[2];
4334- float hits[2][2];
4335- q0[0] = (float)x0;
4336- q0[1] = (float)y0;
4337- q1[0] = (float)x1;
4338- q1[1] = (float)y1;
4339- q2[0] = (float)x2;
4340- q2[1] = (float)y2;
4341- if (equal(q0,q1) || equal(q1,q2)) {
4342- x0 = (int)verts[i-1].x;
4343- y0 = (int)verts[i-1].y;
4344- x1 = (int)verts[i ].x;
4345- y1 = (int)verts[i ].y;
4346- if (y > STBTT_min(y0,y1) && y < STBTT_max(y0,y1) && x > STBTT_min(x0,x1)) {
4347- float x_inter = (y - y0) / (y1 - y0) * (x1-x0) + x0;
4348- if (x_inter < x)
4349- winding += (y0 < y1) ? 1 : -1;
4350- }
4351- } else {
4352- int num_hits = stbtt__ray_intersect_bezier(orig, ray, q0, q1, q2, hits);
4353- if (num_hits >= 1)
4354- if (hits[0][0] < 0)
4355- winding += (hits[0][1] < 0 ? -1 : 1);
4356- if (num_hits >= 2)
4357- if (hits[1][0] < 0)
4358- winding += (hits[1][1] < 0 ? -1 : 1);
4359- }
4360- }
4361- }
4362- }
4363- return winding;
4364-}
4365-
4366-static float stbtt__cuberoot( float x )
4367-{
4368- if (x<0)
4369- return -(float) STBTT_pow(-x,1.0f/3.0f);
4370- else
4371- return (float) STBTT_pow( x,1.0f/3.0f);
4372-}
4373-
4374-// x^3 + c*x^2 + b*x + a = 0
4375-static int stbtt__solve_cubic(float a, float b, float c, float* r)
4376-{
4377- float s = -a / 3;
4378- float p = b - a*a / 3;
4379- float q = a * (2*a*a - 9*b) / 27 + c;
4380- float p3 = p*p*p;
4381- float d = q*q + 4*p3 / 27;
4382- if (d >= 0) {
4383- float z = (float) STBTT_sqrt(d);
4384- float u = (-q + z) / 2;
4385- float v = (-q - z) / 2;
4386- u = stbtt__cuberoot(u);
4387- v = stbtt__cuberoot(v);
4388- r[0] = s + u + v;
4389- return 1;
4390- } else {
4391- float u = (float) STBTT_sqrt(-p/3);
4392- float v = (float) STBTT_acos(-STBTT_sqrt(-27/p3) * q / 2) / 3; // p3 must be negative, since d is negative
4393- float m = (float) STBTT_cos(v);
4394- float n = (float) STBTT_cos(v-3.141592/2)*1.732050808f;
4395- r[0] = s + u * 2 * m;
4396- r[1] = s - u * (m + n);
4397- r[2] = s - u * (m - n);
4398-
4399- //STBTT_assert( STBTT_fabs(((r[0]+a)*r[0]+b)*r[0]+c) < 0.05f); // these asserts may not be safe at all scales, though they're in bezier t parameter units so maybe?
4400- //STBTT_assert( STBTT_fabs(((r[1]+a)*r[1]+b)*r[1]+c) < 0.05f);
4401- //STBTT_assert( STBTT_fabs(((r[2]+a)*r[2]+b)*r[2]+c) < 0.05f);
4402- return 3;
4403- }
4404-}
4405-
4406-STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float scale, int glyph, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff)
4407-{
4408- float scale_x = scale, scale_y = scale;
4409- int ix0,iy0,ix1,iy1;
4410- int w,h;
4411- unsigned char *data;
4412-
4413- // if one scale is 0, use same scale for both
4414- if (scale_x == 0) scale_x = scale_y;
4415- if (scale_y == 0) {
4416- if (scale_x == 0) return NULL; // if both scales are 0, return NULL
4417- scale_y = scale_x;
4418- }
4419-
4420- stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale, scale, 0.0f,0.0f, &ix0,&iy0,&ix1,&iy1);
4421-
4422- // if empty, return NULL
4423- if (ix0 == ix1 || iy0 == iy1)
4424- return NULL;
4425-
4426- ix0 -= padding;
4427- iy0 -= padding;
4428- ix1 += padding;
4429- iy1 += padding;
4430-
4431- w = (ix1 - ix0);
4432- h = (iy1 - iy0);
4433-
4434- if (width ) *width = w;
4435- if (height) *height = h;
4436- if (xoff ) *xoff = ix0;
4437- if (yoff ) *yoff = iy0;
4438-
4439- // invert for y-downwards bitmaps
4440- scale_y = -scale_y;
4441-
4442- {
4443- int x,y,i,j;
4444- float *precompute;
4445- stbtt_vertex *verts;
4446- int num_verts = stbtt_GetGlyphShape(info, glyph, &verts);
4447- data = (unsigned char *) STBTT_malloc(w * h, info->userdata);
4448- precompute = (float *) STBTT_malloc(num_verts * sizeof(float), info->userdata);
4449-
4450- for (i=0,j=num_verts-1; i < num_verts; j=i++) {
4451- if (verts[i].type == STBTT_vline) {
4452- float x0 = verts[i].x*scale_x, y0 = verts[i].y*scale_y;
4453- float x1 = verts[j].x*scale_x, y1 = verts[j].y*scale_y;
4454- float dist = (float) STBTT_sqrt((x1-x0)*(x1-x0) + (y1-y0)*(y1-y0));
4455- precompute[i] = (dist == 0) ? 0.0f : 1.0f / dist;
4456- } else if (verts[i].type == STBTT_vcurve) {
4457- float x2 = verts[j].x *scale_x, y2 = verts[j].y *scale_y;
4458- float x1 = verts[i].cx*scale_x, y1 = verts[i].cy*scale_y;
4459- float x0 = verts[i].x *scale_x, y0 = verts[i].y *scale_y;
4460- float bx = x0 - 2*x1 + x2, by = y0 - 2*y1 + y2;
4461- float len2 = bx*bx + by*by;
4462- if (len2 != 0.0f)
4463- precompute[i] = 1.0f / (bx*bx + by*by);
4464- else
4465- precompute[i] = 0.0f;
4466- } else
4467- precompute[i] = 0.0f;
4468- }
4469-
4470- for (y=iy0; y < iy1; ++y) {
4471- for (x=ix0; x < ix1; ++x) {
4472- float val;
4473- float min_dist = 999999.0f;
4474- float sx = (float) x + 0.5f;
4475- float sy = (float) y + 0.5f;
4476- float x_gspace = (sx / scale_x);
4477- float y_gspace = (sy / scale_y);
4478-
4479- int winding = stbtt__compute_crossings_x(x_gspace, y_gspace, num_verts, verts); // @OPTIMIZE: this could just be a rasterization, but needs to be line vs. non-tesselated curves so a new path
4480-
4481- for (i=0; i < num_verts; ++i) {
4482- float x0 = verts[i].x*scale_x, y0 = verts[i].y*scale_y;
4483-
4484- // check against every point here rather than inside line/curve primitives -- @TODO: wrong if multiple 'moves' in a row produce a garbage point, and given culling, probably more efficient to do within line/curve
4485- float dist2 = (x0-sx)*(x0-sx) + (y0-sy)*(y0-sy);
4486- if (dist2 < min_dist*min_dist)
4487- min_dist = (float) STBTT_sqrt(dist2);
4488-
4489- if (verts[i].type == STBTT_vline) {
4490- float x1 = verts[i-1].x*scale_x, y1 = verts[i-1].y*scale_y;
4491-
4492- // coarse culling against bbox
4493- //if (sx > STBTT_min(x0,x1)-min_dist && sx < STBTT_max(x0,x1)+min_dist &&
4494- // sy > STBTT_min(y0,y1)-min_dist && sy < STBTT_max(y0,y1)+min_dist)
4495- float dist = (float) STBTT_fabs((x1-x0)*(y0-sy) - (y1-y0)*(x0-sx)) * precompute[i];
4496- STBTT_assert(i != 0);
4497- if (dist < min_dist) {
4498- // check position along line
4499- // x' = x0 + t*(x1-x0), y' = y0 + t*(y1-y0)
4500- // minimize (x'-sx)*(x'-sx)+(y'-sy)*(y'-sy)
4501- float dx = x1-x0, dy = y1-y0;
4502- float px = x0-sx, py = y0-sy;
4503- // minimize (px+t*dx)^2 + (py+t*dy)^2 = px*px + 2*px*dx*t + t^2*dx*dx + py*py + 2*py*dy*t + t^2*dy*dy
4504- // derivative: 2*px*dx + 2*py*dy + (2*dx*dx+2*dy*dy)*t, set to 0 and solve
4505- float t = -(px*dx + py*dy) / (dx*dx + dy*dy);
4506- if (t >= 0.0f && t <= 1.0f)
4507- min_dist = dist;
4508- }
4509- } else if (verts[i].type == STBTT_vcurve) {
4510- float x2 = verts[i-1].x *scale_x, y2 = verts[i-1].y *scale_y;
4511- float x1 = verts[i ].cx*scale_x, y1 = verts[i ].cy*scale_y;
4512- float box_x0 = STBTT_min(STBTT_min(x0,x1),x2);
4513- float box_y0 = STBTT_min(STBTT_min(y0,y1),y2);
4514- float box_x1 = STBTT_max(STBTT_max(x0,x1),x2);
4515- float box_y1 = STBTT_max(STBTT_max(y0,y1),y2);
4516- // coarse culling against bbox to avoid computing cubic unnecessarily
4517- if (sx > box_x0-min_dist && sx < box_x1+min_dist && sy > box_y0-min_dist && sy < box_y1+min_dist) {
4518- int num=0;
4519- float ax = x1-x0, ay = y1-y0;
4520- float bx = x0 - 2*x1 + x2, by = y0 - 2*y1 + y2;
4521- float mx = x0 - sx, my = y0 - sy;
4522- float res[3],px,py,t,it;
4523- float a_inv = precompute[i];
4524- if (a_inv == 0.0) { // if a_inv is 0, it's 2nd degree so use quadratic formula
4525- float a = 3*(ax*bx + ay*by);
4526- float b = 2*(ax*ax + ay*ay) + (mx*bx+my*by);
4527- float c = mx*ax+my*ay;
4528- if (a == 0.0) { // if a is 0, it's linear
4529- if (b != 0.0) {
4530- res[num++] = -c/b;
4531- }
4532- } else {
4533- float discriminant = b*b - 4*a*c;
4534- if (discriminant < 0)
4535- num = 0;
4536- else {
4537- float root = (float) STBTT_sqrt(discriminant);
4538- res[0] = (-b - root)/(2*a);
4539- res[1] = (-b + root)/(2*a);
4540- num = 2; // don't bother distinguishing 1-solution case, as code below will still work
4541- }
4542- }
4543- } else {
4544- float b = 3*(ax*bx + ay*by) * a_inv; // could precompute this as it doesn't depend on sample point
4545- float c = (2*(ax*ax + ay*ay) + (mx*bx+my*by)) * a_inv;
4546- float d = (mx*ax+my*ay) * a_inv;
4547- num = stbtt__solve_cubic(b, c, d, res);
4548- }
4549- if (num >= 1 && res[0] >= 0.0f && res[0] <= 1.0f) {
4550- t = res[0], it = 1.0f - t;
4551- px = it*it*x0 + 2*t*it*x1 + t*t*x2;
4552- py = it*it*y0 + 2*t*it*y1 + t*t*y2;
4553- dist2 = (px-sx)*(px-sx) + (py-sy)*(py-sy);
4554- if (dist2 < min_dist * min_dist)
4555- min_dist = (float) STBTT_sqrt(dist2);
4556- }
4557- if (num >= 2 && res[1] >= 0.0f && res[1] <= 1.0f) {
4558- t = res[1], it = 1.0f - t;
4559- px = it*it*x0 + 2*t*it*x1 + t*t*x2;
4560- py = it*it*y0 + 2*t*it*y1 + t*t*y2;
4561- dist2 = (px-sx)*(px-sx) + (py-sy)*(py-sy);
4562- if (dist2 < min_dist * min_dist)
4563- min_dist = (float) STBTT_sqrt(dist2);
4564- }
4565- if (num >= 3 && res[2] >= 0.0f && res[2] <= 1.0f) {
4566- t = res[2], it = 1.0f - t;
4567- px = it*it*x0 + 2*t*it*x1 + t*t*x2;
4568- py = it*it*y0 + 2*t*it*y1 + t*t*y2;
4569- dist2 = (px-sx)*(px-sx) + (py-sy)*(py-sy);
4570- if (dist2 < min_dist * min_dist)
4571- min_dist = (float) STBTT_sqrt(dist2);
4572- }
4573- }
4574- }
4575- }
4576- if (winding == 0)
4577- min_dist = -min_dist; // if outside the shape, value is negative
4578- val = onedge_value + pixel_dist_scale * min_dist;
4579- if (val < 0)
4580- val = 0;
4581- else if (val > 255)
4582- val = 255;
4583- data[(y-iy0)*w+(x-ix0)] = (unsigned char) val;
4584- }
4585- }
4586- STBTT_free(precompute, info->userdata);
4587- STBTT_free(verts, info->userdata);
4588- }
4589- return data;
4590-}
4591-
4592-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)
4593-{
4594- return stbtt_GetGlyphSDF(info, scale, stbtt_FindGlyphIndex(info, codepoint), padding, onedge_value, pixel_dist_scale, width, height, xoff, yoff);
4595-}
4596-
4597-STBTT_DEF void stbtt_FreeSDF(unsigned char *bitmap, void *userdata)
4598-{
4599- STBTT_free(bitmap, userdata);
4600-}
4601-
4602-//////////////////////////////////////////////////////////////////////////////
4603-//
4604-// font name matching -- recommended not to use this
4605-//
4606-
4607-// check if a utf8 string contains a prefix which is the utf16 string; if so return length of matching utf8 string
4608-static stbtt_int32 stbtt__CompareUTF8toUTF16_bigendian_prefix(stbtt_uint8 *s1, stbtt_int32 len1, stbtt_uint8 *s2, stbtt_int32 len2)
4609-{
4610- stbtt_int32 i=0;
4611-
4612- // convert utf16 to utf8 and compare the results while converting
4613- while (len2) {
4614- stbtt_uint16 ch = s2[0]*256 + s2[1];
4615- if (ch < 0x80) {
4616- if (i >= len1) return -1;
4617- if (s1[i++] != ch) return -1;
4618- } else if (ch < 0x800) {
4619- if (i+1 >= len1) return -1;
4620- if (s1[i++] != 0xc0 + (ch >> 6)) return -1;
4621- if (s1[i++] != 0x80 + (ch & 0x3f)) return -1;
4622- } else if (ch >= 0xd800 && ch < 0xdc00) {
4623- stbtt_uint32 c;
4624- stbtt_uint16 ch2 = s2[2]*256 + s2[3];
4625- if (i+3 >= len1) return -1;
4626- c = ((ch - 0xd800) << 10) + (ch2 - 0xdc00) + 0x10000;
4627- if (s1[i++] != 0xf0 + (c >> 18)) return -1;
4628- if (s1[i++] != 0x80 + ((c >> 12) & 0x3f)) return -1;
4629- if (s1[i++] != 0x80 + ((c >> 6) & 0x3f)) return -1;
4630- if (s1[i++] != 0x80 + ((c ) & 0x3f)) return -1;
4631- s2 += 2; // plus another 2 below
4632- len2 -= 2;
4633- } else if (ch >= 0xdc00 && ch < 0xe000) {
4634- return -1;
4635- } else {
4636- if (i+2 >= len1) return -1;
4637- if (s1[i++] != 0xe0 + (ch >> 12)) return -1;
4638- if (s1[i++] != 0x80 + ((ch >> 6) & 0x3f)) return -1;
4639- if (s1[i++] != 0x80 + ((ch ) & 0x3f)) return -1;
4640- }
4641- s2 += 2;
4642- len2 -= 2;
4643- }
4644- return i;
4645-}
4646-
4647-static int stbtt_CompareUTF8toUTF16_bigendian_internal(char *s1, int len1, char *s2, int len2)
4648-{
4649- return len1 == stbtt__CompareUTF8toUTF16_bigendian_prefix((stbtt_uint8*) s1, len1, (stbtt_uint8*) s2, len2);
4650-}
4651-
4652-// returns results in whatever encoding you request... but note that 2-byte encodings
4653-// will be BIG-ENDIAN... use stbtt_CompareUTF8toUTF16_bigendian() to compare
4654-STBTT_DEF const char *stbtt_GetFontNameString(const stbtt_fontinfo *font, int *length, int platformID, int encodingID, int languageID, int nameID)
4655-{
4656- stbtt_int32 i,count,stringOffset;
4657- stbtt_uint8 *fc = font->data;
4658- stbtt_uint32 offset = font->fontstart;
4659- stbtt_uint32 nm = stbtt__find_table(fc, offset, "name");
4660- if (!nm) return NULL;
4661-
4662- count = ttUSHORT(fc+nm+2);
4663- stringOffset = nm + ttUSHORT(fc+nm+4);
4664- for (i=0; i < count; ++i) {
4665- stbtt_uint32 loc = nm + 6 + 12 * i;
4666- if (platformID == ttUSHORT(fc+loc+0) && encodingID == ttUSHORT(fc+loc+2)
4667- && languageID == ttUSHORT(fc+loc+4) && nameID == ttUSHORT(fc+loc+6)) {
4668- *length = ttUSHORT(fc+loc+8);
4669- return (const char *) (fc+stringOffset+ttUSHORT(fc+loc+10));
4670- }
4671- }
4672- return NULL;
4673-}
4674-
4675-static int stbtt__matchpair(stbtt_uint8 *fc, stbtt_uint32 nm, stbtt_uint8 *name, stbtt_int32 nlen, stbtt_int32 target_id, stbtt_int32 next_id)
4676-{
4677- stbtt_int32 i;
4678- stbtt_int32 count = ttUSHORT(fc+nm+2);
4679- stbtt_int32 stringOffset = nm + ttUSHORT(fc+nm+4);
4680-
4681- for (i=0; i < count; ++i) {
4682- stbtt_uint32 loc = nm + 6 + 12 * i;
4683- stbtt_int32 id = ttUSHORT(fc+loc+6);
4684- if (id == target_id) {
4685- // find the encoding
4686- stbtt_int32 platform = ttUSHORT(fc+loc+0), encoding = ttUSHORT(fc+loc+2), language = ttUSHORT(fc+loc+4);
4687-
4688- // is this a Unicode encoding?
4689- if (platform == 0 || (platform == 3 && encoding == 1) || (platform == 3 && encoding == 10)) {
4690- stbtt_int32 slen = ttUSHORT(fc+loc+8);
4691- stbtt_int32 off = ttUSHORT(fc+loc+10);
4692-
4693- // check if there's a prefix match
4694- stbtt_int32 matchlen = stbtt__CompareUTF8toUTF16_bigendian_prefix(name, nlen, fc+stringOffset+off,slen);
4695- if (matchlen >= 0) {
4696- // check for target_id+1 immediately following, with same encoding & language
4697- 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) {
4698- slen = ttUSHORT(fc+loc+12+8);
4699- off = ttUSHORT(fc+loc+12+10);
4700- if (slen == 0) {
4701- if (matchlen == nlen)
4702- return 1;
4703- } else if (matchlen < nlen && name[matchlen] == ' ') {
4704- ++matchlen;
4705- if (stbtt_CompareUTF8toUTF16_bigendian_internal((char*) (name+matchlen), nlen-matchlen, (char*)(fc+stringOffset+off),slen))
4706- return 1;
4707- }
4708- } else {
4709- // if nothing immediately following
4710- if (matchlen == nlen)
4711- return 1;
4712- }
4713- }
4714- }
4715-
4716- // @TODO handle other encodings
4717- }
4718- }
4719- return 0;
4720-}
4721-
4722-static int stbtt__matches(stbtt_uint8 *fc, stbtt_uint32 offset, stbtt_uint8 *name, stbtt_int32 flags)
4723-{
4724- stbtt_int32 nlen = (stbtt_int32) STBTT_strlen((char *) name);
4725- stbtt_uint32 nm,hd;
4726- if (!stbtt__isfont(fc+offset)) return 0;
4727-
4728- // check italics/bold/underline flags in macStyle...
4729- if (flags) {
4730- hd = stbtt__find_table(fc, offset, "head");
4731- if ((ttUSHORT(fc+hd+44) & 7) != (flags & 7)) return 0;
4732- }
4733-
4734- nm = stbtt__find_table(fc, offset, "name");
4735- if (!nm) return 0;
4736-
4737- if (flags) {
4738- // if we checked the macStyle flags, then just check the family and ignore the subfamily
4739- if (stbtt__matchpair(fc, nm, name, nlen, 16, -1)) return 1;
4740- if (stbtt__matchpair(fc, nm, name, nlen, 1, -1)) return 1;
4741- if (stbtt__matchpair(fc, nm, name, nlen, 3, -1)) return 1;
4742- } else {
4743- if (stbtt__matchpair(fc, nm, name, nlen, 16, 17)) return 1;
4744- if (stbtt__matchpair(fc, nm, name, nlen, 1, 2)) return 1;
4745- if (stbtt__matchpair(fc, nm, name, nlen, 3, -1)) return 1;
4746- }
4747-
4748- return 0;
4749-}
4750-
4751-static int stbtt_FindMatchingFont_internal(unsigned char *font_collection, char *name_utf8, stbtt_int32 flags)
4752-{
4753- stbtt_int32 i;
4754- for (i=0;;++i) {
4755- stbtt_int32 off = stbtt_GetFontOffsetForIndex(font_collection, i);
4756- if (off < 0) return off;
4757- if (stbtt__matches((stbtt_uint8 *) font_collection, off, (stbtt_uint8*) name_utf8, flags))
4758- return off;
4759- }
4760-}
4761-
4762-#if defined(__GNUC__) || defined(__clang__)
4763-#pragma GCC diagnostic push
4764-#pragma GCC diagnostic ignored "-Wcast-qual"
4765-#endif
4766-
4767-STBTT_DEF int stbtt_BakeFontBitmap(const unsigned char *data, int offset,
4768- float pixel_height, unsigned char *pixels, int pw, int ph,
4769- int first_char, int num_chars, stbtt_bakedchar *chardata)
4770-{
4771- return stbtt_BakeFontBitmap_internal((unsigned char *) data, offset, pixel_height, pixels, pw, ph, first_char, num_chars, chardata);
4772-}
4773-
4774-STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index)
4775-{
4776- return stbtt_GetFontOffsetForIndex_internal((unsigned char *) data, index);
4777-}
4778-
4779-STBTT_DEF int stbtt_GetNumberOfFonts(const unsigned char *data)
4780-{
4781- return stbtt_GetNumberOfFonts_internal((unsigned char *) data);
4782-}
4783-
4784-STBTT_DEF int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data, int offset)
4785-{
4786- return stbtt_InitFont_internal(info, (unsigned char *) data, offset);
4787-}
4788-
4789-STBTT_DEF int stbtt_FindMatchingFont(const unsigned char *fontdata, const char *name, int flags)
4790-{
4791- return stbtt_FindMatchingFont_internal((unsigned char *) fontdata, (char *) name, flags);
4792-}
4793-
4794-STBTT_DEF int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const char *s2, int len2)
4795-{
4796- return stbtt_CompareUTF8toUTF16_bigendian_internal((char *) s1, len1, (char *) s2, len2);
4797-}
4798-
4799-#if defined(__GNUC__) || defined(__clang__)
4800-#pragma GCC diagnostic pop
4801-#endif
4802-
4803-#endif // STB_TRUETYPE_IMPLEMENTATION
4804-
4805-
4806-// FULL VERSION HISTORY
4807-//
4808-// 1.19 (2018-02-11) OpenType GPOS kerning (horizontal only), STBTT_fmod
4809-// 1.18 (2018-01-29) add missing function
4810-// 1.17 (2017-07-23) make more arguments const; doc fix
4811-// 1.16 (2017-07-12) SDF support
4812-// 1.15 (2017-03-03) make more arguments const
4813-// 1.14 (2017-01-16) num-fonts-in-TTC function
4814-// 1.13 (2017-01-02) support OpenType fonts, certain Apple fonts
4815-// 1.12 (2016-10-25) suppress warnings about casting away const with -Wcast-qual
4816-// 1.11 (2016-04-02) fix unused-variable warning
4817-// 1.10 (2016-04-02) allow user-defined fabs() replacement
4818-// fix memory leak if fontsize=0.0
4819-// fix warning from duplicate typedef
4820-// 1.09 (2016-01-16) warning fix; avoid crash on outofmem; use alloc userdata for PackFontRanges
4821-// 1.08 (2015-09-13) document stbtt_Rasterize(); fixes for vertical & horizontal edges
4822-// 1.07 (2015-08-01) allow PackFontRanges to accept arrays of sparse codepoints;
4823-// allow PackFontRanges to pack and render in separate phases;
4824-// fix stbtt_GetFontOFfsetForIndex (never worked for non-0 input?);
4825-// fixed an assert() bug in the new rasterizer
4826-// replace assert() with STBTT_assert() in new rasterizer
4827-// 1.06 (2015-07-14) performance improvements (~35% faster on x86 and x64 on test machine)
4828-// also more precise AA rasterizer, except if shapes overlap
4829-// remove need for STBTT_sort
4830-// 1.05 (2015-04-15) fix misplaced definitions for STBTT_STATIC
4831-// 1.04 (2015-04-15) typo in example
4832-// 1.03 (2015-04-12) STBTT_STATIC, fix memory leak in new packing, various fixes
4833-// 1.02 (2014-12-10) fix various warnings & compile issues w/ stb_rect_pack, C++
4834-// 1.01 (2014-12-08) fix subpixel position when oversampling to exactly match
4835-// non-oversampled; STBTT_POINT_SIZE for packed case only
4836-// 1.00 (2014-12-06) add new PackBegin etc. API, w/ support for oversampling
4837-// 0.99 (2014-09-18) fix multiple bugs with subpixel rendering (ryg)
4838-// 0.9 (2014-08-07) support certain mac/iOS fonts without an MS platformID
4839-// 0.8b (2014-07-07) fix a warning
4840-// 0.8 (2014-05-25) fix a few more warnings
4841-// 0.7 (2013-09-25) bugfix: subpixel glyph bug fixed in 0.5 had come back
4842-// 0.6c (2012-07-24) improve documentation
4843-// 0.6b (2012-07-20) fix a few more warnings
4844-// 0.6 (2012-07-17) fix warnings; added stbtt_ScaleForMappingEmToPixels,
4845-// stbtt_GetFontBoundingBox, stbtt_IsGlyphEmpty
4846-// 0.5 (2011-12-09) bugfixes:
4847-// subpixel glyph renderer computed wrong bounding box
4848-// first vertex of shape can be off-curve (FreeSans)
4849-// 0.4b (2011-12-03) fixed an error in the font baking example
4850-// 0.4 (2011-12-01) kerning, subpixel rendering (tor)
4851-// bugfixes for:
4852-// codepoint-to-glyph conversion using table fmt=12
4853-// codepoint-to-glyph conversion using table fmt=4
4854-// stbtt_GetBakedQuad with non-square texture (Zer)
4855-// updated Hello World! sample to use kerning and subpixel
4856-// fixed some warnings
4857-// 0.3 (2009-06-24) cmap fmt=12, compound shapes (MM)
4858-// userdata, malloc-from-userdata, non-zero fill (stb)
4859-// 0.2 (2009-03-11) Fix unsigned/signed char warnings
4860-// 0.1 (2009-03-09) First public release
4861-//
4862-
4863-/*
4864-------------------------------------------------------------------------------
4865-This software is available under 2 licenses -- choose whichever you prefer.
4866-------------------------------------------------------------------------------
4867-ALTERNATIVE A - MIT License
4868-Copyright (c) 2017 Sean Barrett
4869-Permission is hereby granted, free of charge, to any person obtaining a copy of
4870-this software and associated documentation files (the "Software"), to deal in
4871-the Software without restriction, including without limitation the rights to
4872-use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
4873-of the Software, and to permit persons to whom the Software is furnished to do
4874-so, subject to the following conditions:
4875-The above copyright notice and this permission notice shall be included in all
4876-copies or substantial portions of the Software.
4877-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
4878-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
4879-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
4880-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
4881-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
4882-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
4883-SOFTWARE.
4884-------------------------------------------------------------------------------
4885-ALTERNATIVE B - Public Domain (www.unlicense.org)
4886-This is free and unencumbered software released into the public domain.
4887-Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
4888-software, either in source code form or as a compiled binary, for any purpose,
4889-commercial or non-commercial, and by any means.
4890-In jurisdictions that recognize copyright laws, the author or authors of this
4891-software dedicate any and all copyright interest in the software to the public
4892-domain. We make this dedication for the benefit of the public at large and to
4893-the detriment of our heirs and successors. We intend this dedication to be an
4894-overt act of relinquishment in perpetuity of all present and future rights to
4895-this software under copyright law.
4896-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
4897-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
4898-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
4899-AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
4900-ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
4901-WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
4902-------------------------------------------------------------------------------
4903-*/
--- Equity10/Common/imGui/include/imstb_textedit.h (revision 212)
+++ Equity10/Common/imGui/include/imstb_textedit.h (nonexistent)
@@ -1,1417 +0,0 @@
1-// [DEAR IMGUI]
2-// This is a slightly modified version of stb_textedit.h 1.13.
3-// Those changes would need to be pushed into nothings/stb:
4-// - Fix in stb_textedit_discard_redo (see https://github.com/nothings/stb/issues/321)
5-// Grep for [DEAR IMGUI] to find the changes.
6-
7-// stb_textedit.h - v1.13 - public domain - Sean Barrett
8-// Development of this library was sponsored by RAD Game Tools
9-//
10-// This C header file implements the guts of a multi-line text-editing
11-// widget; you implement display, word-wrapping, and low-level string
12-// insertion/deletion, and stb_textedit will map user inputs into
13-// insertions & deletions, plus updates to the cursor position,
14-// selection state, and undo state.
15-//
16-// It is intended for use in games and other systems that need to build
17-// their own custom widgets and which do not have heavy text-editing
18-// requirements (this library is not recommended for use for editing large
19-// texts, as its performance does not scale and it has limited undo).
20-//
21-// Non-trivial behaviors are modelled after Windows text controls.
22-//
23-//
24-// LICENSE
25-//
26-// See end of file for license information.
27-//
28-//
29-// DEPENDENCIES
30-//
31-// Uses the C runtime function 'memmove', which you can override
32-// by defining STB_TEXTEDIT_memmove before the implementation.
33-// Uses no other functions. Performs no runtime allocations.
34-//
35-//
36-// VERSION HISTORY
37-//
38-// 1.13 (2019-02-07) fix bug in undo size management
39-// 1.12 (2018-01-29) user can change STB_TEXTEDIT_KEYTYPE, fix redo to avoid crash
40-// 1.11 (2017-03-03) fix HOME on last line, dragging off single-line textfield
41-// 1.10 (2016-10-25) supress warnings about casting away const with -Wcast-qual
42-// 1.9 (2016-08-27) customizable move-by-word
43-// 1.8 (2016-04-02) better keyboard handling when mouse button is down
44-// 1.7 (2015-09-13) change y range handling in case baseline is non-0
45-// 1.6 (2015-04-15) allow STB_TEXTEDIT_memmove
46-// 1.5 (2014-09-10) add support for secondary keys for OS X
47-// 1.4 (2014-08-17) fix signed/unsigned warnings
48-// 1.3 (2014-06-19) fix mouse clicking to round to nearest char boundary
49-// 1.2 (2014-05-27) fix some RAD types that had crept into the new code
50-// 1.1 (2013-12-15) move-by-word (requires STB_TEXTEDIT_IS_SPACE )
51-// 1.0 (2012-07-26) improve documentation, initial public release
52-// 0.3 (2012-02-24) bugfixes, single-line mode; insert mode
53-// 0.2 (2011-11-28) fixes to undo/redo
54-// 0.1 (2010-07-08) initial version
55-//
56-// ADDITIONAL CONTRIBUTORS
57-//
58-// Ulf Winklemann: move-by-word in 1.1
59-// Fabian Giesen: secondary key inputs in 1.5
60-// Martins Mozeiko: STB_TEXTEDIT_memmove in 1.6
61-//
62-// Bugfixes:
63-// Scott Graham
64-// Daniel Keller
65-// Omar Cornut
66-// Dan Thompson
67-//
68-// USAGE
69-//
70-// This file behaves differently depending on what symbols you define
71-// before including it.
72-//
73-//
74-// Header-file mode:
75-//
76-// If you do not define STB_TEXTEDIT_IMPLEMENTATION before including this,
77-// it will operate in "header file" mode. In this mode, it declares a
78-// single public symbol, STB_TexteditState, which encapsulates the current
79-// state of a text widget (except for the string, which you will store
80-// separately).
81-//
82-// To compile in this mode, you must define STB_TEXTEDIT_CHARTYPE to a
83-// primitive type that defines a single character (e.g. char, wchar_t, etc).
84-//
85-// To save space or increase undo-ability, you can optionally define the
86-// following things that are used by the undo system:
87-//
88-// STB_TEXTEDIT_POSITIONTYPE small int type encoding a valid cursor position
89-// STB_TEXTEDIT_UNDOSTATECOUNT the number of undo states to allow
90-// STB_TEXTEDIT_UNDOCHARCOUNT the number of characters to store in the undo buffer
91-//
92-// If you don't define these, they are set to permissive types and
93-// moderate sizes. The undo system does no memory allocations, so
94-// it grows STB_TexteditState by the worst-case storage which is (in bytes):
95-//
96-// [4 + 3 * sizeof(STB_TEXTEDIT_POSITIONTYPE)] * STB_TEXTEDIT_UNDOSTATE_COUNT
97-// + sizeof(STB_TEXTEDIT_CHARTYPE) * STB_TEXTEDIT_UNDOCHAR_COUNT
98-//
99-//
100-// Implementation mode:
101-//
102-// If you define STB_TEXTEDIT_IMPLEMENTATION before including this, it
103-// will compile the implementation of the text edit widget, depending
104-// on a large number of symbols which must be defined before the include.
105-//
106-// The implementation is defined only as static functions. You will then
107-// need to provide your own APIs in the same file which will access the
108-// static functions.
109-//
110-// The basic concept is that you provide a "string" object which
111-// behaves like an array of characters. stb_textedit uses indices to
112-// refer to positions in the string, implicitly representing positions
113-// in the displayed textedit. This is true for both plain text and
114-// rich text; even with rich text stb_truetype interacts with your
115-// code as if there was an array of all the displayed characters.
116-//
117-// Symbols that must be the same in header-file and implementation mode:
118-//
119-// STB_TEXTEDIT_CHARTYPE the character type
120-// STB_TEXTEDIT_POSITIONTYPE small type that is a valid cursor position
121-// STB_TEXTEDIT_UNDOSTATECOUNT the number of undo states to allow
122-// STB_TEXTEDIT_UNDOCHARCOUNT the number of characters to store in the undo buffer
123-//
124-// Symbols you must define for implementation mode:
125-//
126-// STB_TEXTEDIT_STRING the type of object representing a string being edited,
127-// typically this is a wrapper object with other data you need
128-//
129-// STB_TEXTEDIT_STRINGLEN(obj) the length of the string (ideally O(1))
130-// STB_TEXTEDIT_LAYOUTROW(&r,obj,n) returns the results of laying out a line of characters
131-// starting from character #n (see discussion below)
132-// STB_TEXTEDIT_GETWIDTH(obj,n,i) returns the pixel delta from the xpos of the i'th character
133-// to the xpos of the i+1'th char for a line of characters
134-// starting at character #n (i.e. accounts for kerning
135-// with previous char)
136-// STB_TEXTEDIT_KEYTOTEXT(k) maps a keyboard input to an insertable character
137-// (return type is int, -1 means not valid to insert)
138-// STB_TEXTEDIT_GETCHAR(obj,i) returns the i'th character of obj, 0-based
139-// STB_TEXTEDIT_NEWLINE the character returned by _GETCHAR() we recognize
140-// as manually wordwrapping for end-of-line positioning
141-//
142-// STB_TEXTEDIT_DELETECHARS(obj,i,n) delete n characters starting at i
143-// STB_TEXTEDIT_INSERTCHARS(obj,i,c*,n) insert n characters at i (pointed to by STB_TEXTEDIT_CHARTYPE*)
144-//
145-// STB_TEXTEDIT_K_SHIFT a power of two that is or'd in to a keyboard input to represent the shift key
146-//
147-// STB_TEXTEDIT_K_LEFT keyboard input to move cursor left
148-// STB_TEXTEDIT_K_RIGHT keyboard input to move cursor right
149-// STB_TEXTEDIT_K_UP keyboard input to move cursor up
150-// STB_TEXTEDIT_K_DOWN keyboard input to move cursor down
151-// STB_TEXTEDIT_K_LINESTART keyboard input to move cursor to start of line // e.g. HOME
152-// STB_TEXTEDIT_K_LINEEND keyboard input to move cursor to end of line // e.g. END
153-// STB_TEXTEDIT_K_TEXTSTART keyboard input to move cursor to start of text // e.g. ctrl-HOME
154-// STB_TEXTEDIT_K_TEXTEND keyboard input to move cursor to end of text // e.g. ctrl-END
155-// STB_TEXTEDIT_K_DELETE keyboard input to delete selection or character under cursor
156-// STB_TEXTEDIT_K_BACKSPACE keyboard input to delete selection or character left of cursor
157-// STB_TEXTEDIT_K_UNDO keyboard input to perform undo
158-// STB_TEXTEDIT_K_REDO keyboard input to perform redo
159-//
160-// Optional:
161-// STB_TEXTEDIT_K_INSERT keyboard input to toggle insert mode
162-// STB_TEXTEDIT_IS_SPACE(ch) true if character is whitespace (e.g. 'isspace'),
163-// required for default WORDLEFT/WORDRIGHT handlers
164-// STB_TEXTEDIT_MOVEWORDLEFT(obj,i) custom handler for WORDLEFT, returns index to move cursor to
165-// STB_TEXTEDIT_MOVEWORDRIGHT(obj,i) custom handler for WORDRIGHT, returns index to move cursor to
166-// STB_TEXTEDIT_K_WORDLEFT keyboard input to move cursor left one word // e.g. ctrl-LEFT
167-// STB_TEXTEDIT_K_WORDRIGHT keyboard input to move cursor right one word // e.g. ctrl-RIGHT
168-// STB_TEXTEDIT_K_LINESTART2 secondary keyboard input to move cursor to start of line
169-// STB_TEXTEDIT_K_LINEEND2 secondary keyboard input to move cursor to end of line
170-// STB_TEXTEDIT_K_TEXTSTART2 secondary keyboard input to move cursor to start of text
171-// STB_TEXTEDIT_K_TEXTEND2 secondary keyboard input to move cursor to end of text
172-//
173-// Todo:
174-// STB_TEXTEDIT_K_PGUP keyboard input to move cursor up a page
175-// STB_TEXTEDIT_K_PGDOWN keyboard input to move cursor down a page
176-//
177-// Keyboard input must be encoded as a single integer value; e.g. a character code
178-// and some bitflags that represent shift states. to simplify the interface, SHIFT must
179-// be a bitflag, so we can test the shifted state of cursor movements to allow selection,
180-// i.e. (STB_TEXTED_K_RIGHT|STB_TEXTEDIT_K_SHIFT) should be shifted right-arrow.
181-//
182-// You can encode other things, such as CONTROL or ALT, in additional bits, and
183-// then test for their presence in e.g. STB_TEXTEDIT_K_WORDLEFT. For example,
184-// my Windows implementations add an additional CONTROL bit, and an additional KEYDOWN
185-// bit. Then all of the STB_TEXTEDIT_K_ values bitwise-or in the KEYDOWN bit,
186-// and I pass both WM_KEYDOWN and WM_CHAR events to the "key" function in the
187-// API below. The control keys will only match WM_KEYDOWN events because of the
188-// keydown bit I add, and STB_TEXTEDIT_KEYTOTEXT only tests for the KEYDOWN
189-// bit so it only decodes WM_CHAR events.
190-//
191-// STB_TEXTEDIT_LAYOUTROW returns information about the shape of one displayed
192-// row of characters assuming they start on the i'th character--the width and
193-// the height and the number of characters consumed. This allows this library
194-// to traverse the entire layout incrementally. You need to compute word-wrapping
195-// here.
196-//
197-// Each textfield keeps its own insert mode state, which is not how normal
198-// applications work. To keep an app-wide insert mode, update/copy the
199-// "insert_mode" field of STB_TexteditState before/after calling API functions.
200-//
201-// API
202-//
203-// void stb_textedit_initialize_state(STB_TexteditState *state, int is_single_line)
204-//
205-// void stb_textedit_click(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, float x, float y)
206-// void stb_textedit_drag(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, float x, float y)
207-// int stb_textedit_cut(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
208-// int stb_textedit_paste(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_CHARTYPE *text, int len)
209-// void stb_textedit_key(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXEDIT_KEYTYPE key)
210-//
211-// Each of these functions potentially updates the string and updates the
212-// state.
213-//
214-// initialize_state:
215-// set the textedit state to a known good default state when initially
216-// constructing the textedit.
217-//
218-// click:
219-// call this with the mouse x,y on a mouse down; it will update the cursor
220-// and reset the selection start/end to the cursor point. the x,y must
221-// be relative to the text widget, with (0,0) being the top left.
222-//
223-// drag:
224-// call this with the mouse x,y on a mouse drag/up; it will update the
225-// cursor and the selection end point
226-//
227-// cut:
228-// call this to delete the current selection; returns true if there was
229-// one. you should FIRST copy the current selection to the system paste buffer.
230-// (To copy, just copy the current selection out of the string yourself.)
231-//
232-// paste:
233-// call this to paste text at the current cursor point or over the current
234-// selection if there is one.
235-//
236-// key:
237-// call this for keyboard inputs sent to the textfield. you can use it
238-// for "key down" events or for "translated" key events. if you need to
239-// do both (as in Win32), or distinguish Unicode characters from control
240-// inputs, set a high bit to distinguish the two; then you can define the
241-// various definitions like STB_TEXTEDIT_K_LEFT have the is-key-event bit
242-// set, and make STB_TEXTEDIT_KEYTOCHAR check that the is-key-event bit is
243-// clear. STB_TEXTEDIT_KEYTYPE defaults to int, but you can #define it to
244-// anything other type you wante before including.
245-//
246-//
247-// When rendering, you can read the cursor position and selection state from
248-// the STB_TexteditState.
249-//
250-//
251-// Notes:
252-//
253-// This is designed to be usable in IMGUI, so it allows for the possibility of
254-// running in an IMGUI that has NOT cached the multi-line layout. For this
255-// reason, it provides an interface that is compatible with computing the
256-// layout incrementally--we try to make sure we make as few passes through
257-// as possible. (For example, to locate the mouse pointer in the text, we
258-// could define functions that return the X and Y positions of characters
259-// and binary search Y and then X, but if we're doing dynamic layout this
260-// will run the layout algorithm many times, so instead we manually search
261-// forward in one pass. Similar logic applies to e.g. up-arrow and
262-// down-arrow movement.)
263-//
264-// If it's run in a widget that *has* cached the layout, then this is less
265-// efficient, but it's not horrible on modern computers. But you wouldn't
266-// want to edit million-line files with it.
267-
268-
269-////////////////////////////////////////////////////////////////////////////
270-////////////////////////////////////////////////////////////////////////////
271-////
272-//// Header-file mode
273-////
274-////
275-
276-#ifndef INCLUDE_STB_TEXTEDIT_H
277-#define INCLUDE_STB_TEXTEDIT_H
278-
279-////////////////////////////////////////////////////////////////////////
280-//
281-// STB_TexteditState
282-//
283-// Definition of STB_TexteditState which you should store
284-// per-textfield; it includes cursor position, selection state,
285-// and undo state.
286-//
287-
288-#ifndef STB_TEXTEDIT_UNDOSTATECOUNT
289-#define STB_TEXTEDIT_UNDOSTATECOUNT 99
290-#endif
291-#ifndef STB_TEXTEDIT_UNDOCHARCOUNT
292-#define STB_TEXTEDIT_UNDOCHARCOUNT 999
293-#endif
294-#ifndef STB_TEXTEDIT_CHARTYPE
295-#define STB_TEXTEDIT_CHARTYPE int
296-#endif
297-#ifndef STB_TEXTEDIT_POSITIONTYPE
298-#define STB_TEXTEDIT_POSITIONTYPE int
299-#endif
300-
301-typedef struct
302-{
303- // private data
304- STB_TEXTEDIT_POSITIONTYPE where;
305- STB_TEXTEDIT_POSITIONTYPE insert_length;
306- STB_TEXTEDIT_POSITIONTYPE delete_length;
307- int char_storage;
308-} StbUndoRecord;
309-
310-typedef struct
311-{
312- // private data
313- StbUndoRecord undo_rec [STB_TEXTEDIT_UNDOSTATECOUNT];
314- STB_TEXTEDIT_CHARTYPE undo_char[STB_TEXTEDIT_UNDOCHARCOUNT];
315- short undo_point, redo_point;
316- int undo_char_point, redo_char_point;
317-} StbUndoState;
318-
319-typedef struct
320-{
321- /////////////////////
322- //
323- // public data
324- //
325-
326- int cursor;
327- // position of the text cursor within the string
328-
329- int select_start; // selection start point
330- int select_end;
331- // selection start and end point in characters; if equal, no selection.
332- // note that start may be less than or greater than end (e.g. when
333- // dragging the mouse, start is where the initial click was, and you
334- // can drag in either direction)
335-
336- unsigned char insert_mode;
337- // each textfield keeps its own insert mode state. to keep an app-wide
338- // insert mode, copy this value in/out of the app state
339-
340- /////////////////////
341- //
342- // private data
343- //
344- unsigned char cursor_at_end_of_line; // not implemented yet
345- unsigned char initialized;
346- unsigned char has_preferred_x;
347- unsigned char single_line;
348- unsigned char padding1, padding2, padding3;
349- float preferred_x; // this determines where the cursor up/down tries to seek to along x
350- StbUndoState undostate;
351-} STB_TexteditState;
352-
353-
354-////////////////////////////////////////////////////////////////////////
355-//
356-// StbTexteditRow
357-//
358-// Result of layout query, used by stb_textedit to determine where
359-// the text in each row is.
360-
361-// result of layout query
362-typedef struct
363-{
364- float x0,x1; // starting x location, end x location (allows for align=right, etc)
365- float baseline_y_delta; // position of baseline relative to previous row's baseline
366- float ymin,ymax; // height of row above and below baseline
367- int num_chars;
368-} StbTexteditRow;
369-#endif //INCLUDE_STB_TEXTEDIT_H
370-
371-
372-////////////////////////////////////////////////////////////////////////////
373-////////////////////////////////////////////////////////////////////////////
374-////
375-//// Implementation mode
376-////
377-////
378-
379-
380-// implementation isn't include-guarded, since it might have indirectly
381-// included just the "header" portion
382-#ifdef STB_TEXTEDIT_IMPLEMENTATION
383-
384-#ifndef STB_TEXTEDIT_memmove
385-#include <string.h>
386-#define STB_TEXTEDIT_memmove memmove
387-#endif
388-
389-
390-/////////////////////////////////////////////////////////////////////////////
391-//
392-// Mouse input handling
393-//
394-
395-// traverse the layout to locate the nearest character to a display position
396-static int stb_text_locate_coord(STB_TEXTEDIT_STRING *str, float x, float y)
397-{
398- StbTexteditRow r;
399- int n = STB_TEXTEDIT_STRINGLEN(str);
400- float base_y = 0, prev_x;
401- int i=0, k;
402-
403- r.x0 = r.x1 = 0;
404- r.ymin = r.ymax = 0;
405- r.num_chars = 0;
406-
407- // search rows to find one that straddles 'y'
408- while (i < n) {
409- STB_TEXTEDIT_LAYOUTROW(&r, str, i);
410- if (r.num_chars <= 0)
411- return n;
412-
413- if (i==0 && y < base_y + r.ymin)
414- return 0;
415-
416- if (y < base_y + r.ymax)
417- break;
418-
419- i += r.num_chars;
420- base_y += r.baseline_y_delta;
421- }
422-
423- // below all text, return 'after' last character
424- if (i >= n)
425- return n;
426-
427- // check if it's before the beginning of the line
428- if (x < r.x0)
429- return i;
430-
431- // check if it's before the end of the line
432- if (x < r.x1) {
433- // search characters in row for one that straddles 'x'
434- prev_x = r.x0;
435- for (k=0; k < r.num_chars; ++k) {
436- float w = STB_TEXTEDIT_GETWIDTH(str, i, k);
437- if (x < prev_x+w) {
438- if (x < prev_x+w/2)
439- return k+i;
440- else
441- return k+i+1;
442- }
443- prev_x += w;
444- }
445- // shouldn't happen, but if it does, fall through to end-of-line case
446- }
447-
448- // if the last character is a newline, return that. otherwise return 'after' the last character
449- if (STB_TEXTEDIT_GETCHAR(str, i+r.num_chars-1) == STB_TEXTEDIT_NEWLINE)
450- return i+r.num_chars-1;
451- else
452- return i+r.num_chars;
453-}
454-
455-// API click: on mouse down, move the cursor to the clicked location, and reset the selection
456-static void stb_textedit_click(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, float x, float y)
457-{
458- // In single-line mode, just always make y = 0. This lets the drag keep working if the mouse
459- // goes off the top or bottom of the text
460- if( state->single_line )
461- {
462- StbTexteditRow r;
463- STB_TEXTEDIT_LAYOUTROW(&r, str, 0);
464- y = r.ymin;
465- }
466-
467- state->cursor = stb_text_locate_coord(str, x, y);
468- state->select_start = state->cursor;
469- state->select_end = state->cursor;
470- state->has_preferred_x = 0;
471-}
472-
473-// API drag: on mouse drag, move the cursor and selection endpoint to the clicked location
474-static void stb_textedit_drag(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, float x, float y)
475-{
476- int p = 0;
477-
478- // In single-line mode, just always make y = 0. This lets the drag keep working if the mouse
479- // goes off the top or bottom of the text
480- if( state->single_line )
481- {
482- StbTexteditRow r;
483- STB_TEXTEDIT_LAYOUTROW(&r, str, 0);
484- y = r.ymin;
485- }
486-
487- if (state->select_start == state->select_end)
488- state->select_start = state->cursor;
489-
490- p = stb_text_locate_coord(str, x, y);
491- state->cursor = state->select_end = p;
492-}
493-
494-/////////////////////////////////////////////////////////////////////////////
495-//
496-// Keyboard input handling
497-//
498-
499-// forward declarations
500-static void stb_text_undo(STB_TEXTEDIT_STRING *str, STB_TexteditState *state);
501-static void stb_text_redo(STB_TEXTEDIT_STRING *str, STB_TexteditState *state);
502-static void stb_text_makeundo_delete(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int length);
503-static void stb_text_makeundo_insert(STB_TexteditState *state, int where, int length);
504-static void stb_text_makeundo_replace(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int old_length, int new_length);
505-
506-typedef struct
507-{
508- float x,y; // position of n'th character
509- float height; // height of line
510- int first_char, length; // first char of row, and length
511- int prev_first; // first char of previous row
512-} StbFindState;
513-
514-// find the x/y location of a character, and remember info about the previous row in
515-// case we get a move-up event (for page up, we'll have to rescan)
516-static void stb_textedit_find_charpos(StbFindState *find, STB_TEXTEDIT_STRING *str, int n, int single_line)
517-{
518- StbTexteditRow r;
519- int prev_start = 0;
520- int z = STB_TEXTEDIT_STRINGLEN(str);
521- int i=0, first;
522-
523- if (n == z) {
524- // if it's at the end, then find the last line -- simpler than trying to
525- // explicitly handle this case in the regular code
526- if (single_line) {
527- STB_TEXTEDIT_LAYOUTROW(&r, str, 0);
528- find->y = 0;
529- find->first_char = 0;
530- find->length = z;
531- find->height = r.ymax - r.ymin;
532- find->x = r.x1;
533- } else {
534- find->y = 0;
535- find->x = 0;
536- find->height = 1;
537- while (i < z) {
538- STB_TEXTEDIT_LAYOUTROW(&r, str, i);
539- prev_start = i;
540- i += r.num_chars;
541- }
542- find->first_char = i;
543- find->length = 0;
544- find->prev_first = prev_start;
545- }
546- return;
547- }
548-
549- // search rows to find the one that straddles character n
550- find->y = 0;
551-
552- for(;;) {
553- STB_TEXTEDIT_LAYOUTROW(&r, str, i);
554- if (n < i + r.num_chars)
555- break;
556- prev_start = i;
557- i += r.num_chars;
558- find->y += r.baseline_y_delta;
559- }
560-
561- find->first_char = first = i;
562- find->length = r.num_chars;
563- find->height = r.ymax - r.ymin;
564- find->prev_first = prev_start;
565-
566- // now scan to find xpos
567- find->x = r.x0;
568- for (i=0; first+i < n; ++i)
569- find->x += STB_TEXTEDIT_GETWIDTH(str, first, i);
570-}
571-
572-#define STB_TEXT_HAS_SELECTION(s) ((s)->select_start != (s)->select_end)
573-
574-// make the selection/cursor state valid if client altered the string
575-static void stb_textedit_clamp(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
576-{
577- int n = STB_TEXTEDIT_STRINGLEN(str);
578- if (STB_TEXT_HAS_SELECTION(state)) {
579- if (state->select_start > n) state->select_start = n;
580- if (state->select_end > n) state->select_end = n;
581- // if clamping forced them to be equal, move the cursor to match
582- if (state->select_start == state->select_end)
583- state->cursor = state->select_start;
584- }
585- if (state->cursor > n) state->cursor = n;
586-}
587-
588-// delete characters while updating undo
589-static void stb_textedit_delete(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int len)
590-{
591- stb_text_makeundo_delete(str, state, where, len);
592- STB_TEXTEDIT_DELETECHARS(str, where, len);
593- state->has_preferred_x = 0;
594-}
595-
596-// delete the section
597-static void stb_textedit_delete_selection(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
598-{
599- stb_textedit_clamp(str, state);
600- if (STB_TEXT_HAS_SELECTION(state)) {
601- if (state->select_start < state->select_end) {
602- stb_textedit_delete(str, state, state->select_start, state->select_end - state->select_start);
603- state->select_end = state->cursor = state->select_start;
604- } else {
605- stb_textedit_delete(str, state, state->select_end, state->select_start - state->select_end);
606- state->select_start = state->cursor = state->select_end;
607- }
608- state->has_preferred_x = 0;
609- }
610-}
611-
612-// canoncialize the selection so start <= end
613-static void stb_textedit_sortselection(STB_TexteditState *state)
614-{
615- if (state->select_end < state->select_start) {
616- int temp = state->select_end;
617- state->select_end = state->select_start;
618- state->select_start = temp;
619- }
620-}
621-
622-// move cursor to first character of selection
623-static void stb_textedit_move_to_first(STB_TexteditState *state)
624-{
625- if (STB_TEXT_HAS_SELECTION(state)) {
626- stb_textedit_sortselection(state);
627- state->cursor = state->select_start;
628- state->select_end = state->select_start;
629- state->has_preferred_x = 0;
630- }
631-}
632-
633-// move cursor to last character of selection
634-static void stb_textedit_move_to_last(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
635-{
636- if (STB_TEXT_HAS_SELECTION(state)) {
637- stb_textedit_sortselection(state);
638- stb_textedit_clamp(str, state);
639- state->cursor = state->select_end;
640- state->select_start = state->select_end;
641- state->has_preferred_x = 0;
642- }
643-}
644-
645-#ifdef STB_TEXTEDIT_IS_SPACE
646-static int is_word_boundary( STB_TEXTEDIT_STRING *str, int idx )
647-{
648- return idx > 0 ? (STB_TEXTEDIT_IS_SPACE( STB_TEXTEDIT_GETCHAR(str,idx-1) ) && !STB_TEXTEDIT_IS_SPACE( STB_TEXTEDIT_GETCHAR(str, idx) ) ) : 1;
649-}
650-
651-#ifndef STB_TEXTEDIT_MOVEWORDLEFT
652-static int stb_textedit_move_to_word_previous( STB_TEXTEDIT_STRING *str, int c )
653-{
654- --c; // always move at least one character
655- while( c >= 0 && !is_word_boundary( str, c ) )
656- --c;
657-
658- if( c < 0 )
659- c = 0;
660-
661- return c;
662-}
663-#define STB_TEXTEDIT_MOVEWORDLEFT stb_textedit_move_to_word_previous
664-#endif
665-
666-#ifndef STB_TEXTEDIT_MOVEWORDRIGHT
667-static int stb_textedit_move_to_word_next( STB_TEXTEDIT_STRING *str, int c )
668-{
669- const int len = STB_TEXTEDIT_STRINGLEN(str);
670- ++c; // always move at least one character
671- while( c < len && !is_word_boundary( str, c ) )
672- ++c;
673-
674- if( c > len )
675- c = len;
676-
677- return c;
678-}
679-#define STB_TEXTEDIT_MOVEWORDRIGHT stb_textedit_move_to_word_next
680-#endif
681-
682-#endif
683-
684-// update selection and cursor to match each other
685-static void stb_textedit_prep_selection_at_cursor(STB_TexteditState *state)
686-{
687- if (!STB_TEXT_HAS_SELECTION(state))
688- state->select_start = state->select_end = state->cursor;
689- else
690- state->cursor = state->select_end;
691-}
692-
693-// API cut: delete selection
694-static int stb_textedit_cut(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
695-{
696- if (STB_TEXT_HAS_SELECTION(state)) {
697- stb_textedit_delete_selection(str,state); // implicitly clamps
698- state->has_preferred_x = 0;
699- return 1;
700- }
701- return 0;
702-}
703-
704-// API paste: replace existing selection with passed-in text
705-static int stb_textedit_paste_internal(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_CHARTYPE *text, int len)
706-{
707- // if there's a selection, the paste should delete it
708- stb_textedit_clamp(str, state);
709- stb_textedit_delete_selection(str,state);
710- // try to insert the characters
711- if (STB_TEXTEDIT_INSERTCHARS(str, state->cursor, text, len)) {
712- stb_text_makeundo_insert(state, state->cursor, len);
713- state->cursor += len;
714- state->has_preferred_x = 0;
715- return 1;
716- }
717- // remove the undo since we didn't actually insert the characters
718- if (state->undostate.undo_point)
719- --state->undostate.undo_point;
720- return 0;
721-}
722-
723-#ifndef STB_TEXTEDIT_KEYTYPE
724-#define STB_TEXTEDIT_KEYTYPE int
725-#endif
726-
727-// API key: process a keyboard input
728-static void stb_textedit_key(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_KEYTYPE key)
729-{
730-retry:
731- switch (key) {
732- default: {
733- int c = STB_TEXTEDIT_KEYTOTEXT(key);
734- if (c > 0) {
735- STB_TEXTEDIT_CHARTYPE ch = (STB_TEXTEDIT_CHARTYPE) c;
736-
737- // can't add newline in single-line mode
738- if (c == '\n' && state->single_line)
739- break;
740-
741- if (state->insert_mode && !STB_TEXT_HAS_SELECTION(state) && state->cursor < STB_TEXTEDIT_STRINGLEN(str)) {
742- stb_text_makeundo_replace(str, state, state->cursor, 1, 1);
743- STB_TEXTEDIT_DELETECHARS(str, state->cursor, 1);
744- if (STB_TEXTEDIT_INSERTCHARS(str, state->cursor, &ch, 1)) {
745- ++state->cursor;
746- state->has_preferred_x = 0;
747- }
748- } else {
749- stb_textedit_delete_selection(str,state); // implicitly clamps
750- if (STB_TEXTEDIT_INSERTCHARS(str, state->cursor, &ch, 1)) {
751- stb_text_makeundo_insert(state, state->cursor, 1);
752- ++state->cursor;
753- state->has_preferred_x = 0;
754- }
755- }
756- }
757- break;
758- }
759-
760-#ifdef STB_TEXTEDIT_K_INSERT
761- case STB_TEXTEDIT_K_INSERT:
762- state->insert_mode = !state->insert_mode;
763- break;
764-#endif
765-
766- case STB_TEXTEDIT_K_UNDO:
767- stb_text_undo(str, state);
768- state->has_preferred_x = 0;
769- break;
770-
771- case STB_TEXTEDIT_K_REDO:
772- stb_text_redo(str, state);
773- state->has_preferred_x = 0;
774- break;
775-
776- case STB_TEXTEDIT_K_LEFT:
777- // if currently there's a selection, move cursor to start of selection
778- if (STB_TEXT_HAS_SELECTION(state))
779- stb_textedit_move_to_first(state);
780- else
781- if (state->cursor > 0)
782- --state->cursor;
783- state->has_preferred_x = 0;
784- break;
785-
786- case STB_TEXTEDIT_K_RIGHT:
787- // if currently there's a selection, move cursor to end of selection
788- if (STB_TEXT_HAS_SELECTION(state))
789- stb_textedit_move_to_last(str, state);
790- else
791- ++state->cursor;
792- stb_textedit_clamp(str, state);
793- state->has_preferred_x = 0;
794- break;
795-
796- case STB_TEXTEDIT_K_LEFT | STB_TEXTEDIT_K_SHIFT:
797- stb_textedit_clamp(str, state);
798- stb_textedit_prep_selection_at_cursor(state);
799- // move selection left
800- if (state->select_end > 0)
801- --state->select_end;
802- state->cursor = state->select_end;
803- state->has_preferred_x = 0;
804- break;
805-
806-#ifdef STB_TEXTEDIT_MOVEWORDLEFT
807- case STB_TEXTEDIT_K_WORDLEFT:
808- if (STB_TEXT_HAS_SELECTION(state))
809- stb_textedit_move_to_first(state);
810- else {
811- state->cursor = STB_TEXTEDIT_MOVEWORDLEFT(str, state->cursor);
812- stb_textedit_clamp( str, state );
813- }
814- break;
815-
816- case STB_TEXTEDIT_K_WORDLEFT | STB_TEXTEDIT_K_SHIFT:
817- if( !STB_TEXT_HAS_SELECTION( state ) )
818- stb_textedit_prep_selection_at_cursor(state);
819-
820- state->cursor = STB_TEXTEDIT_MOVEWORDLEFT(str, state->cursor);
821- state->select_end = state->cursor;
822-
823- stb_textedit_clamp( str, state );
824- break;
825-#endif
826-
827-#ifdef STB_TEXTEDIT_MOVEWORDRIGHT
828- case STB_TEXTEDIT_K_WORDRIGHT:
829- if (STB_TEXT_HAS_SELECTION(state))
830- stb_textedit_move_to_last(str, state);
831- else {
832- state->cursor = STB_TEXTEDIT_MOVEWORDRIGHT(str, state->cursor);
833- stb_textedit_clamp( str, state );
834- }
835- break;
836-
837- case STB_TEXTEDIT_K_WORDRIGHT | STB_TEXTEDIT_K_SHIFT:
838- if( !STB_TEXT_HAS_SELECTION( state ) )
839- stb_textedit_prep_selection_at_cursor(state);
840-
841- state->cursor = STB_TEXTEDIT_MOVEWORDRIGHT(str, state->cursor);
842- state->select_end = state->cursor;
843-
844- stb_textedit_clamp( str, state );
845- break;
846-#endif
847-
848- case STB_TEXTEDIT_K_RIGHT | STB_TEXTEDIT_K_SHIFT:
849- stb_textedit_prep_selection_at_cursor(state);
850- // move selection right
851- ++state->select_end;
852- stb_textedit_clamp(str, state);
853- state->cursor = state->select_end;
854- state->has_preferred_x = 0;
855- break;
856-
857- case STB_TEXTEDIT_K_DOWN:
858- case STB_TEXTEDIT_K_DOWN | STB_TEXTEDIT_K_SHIFT: {
859- StbFindState find;
860- StbTexteditRow row;
861- int i, sel = (key & STB_TEXTEDIT_K_SHIFT) != 0;
862-
863- if (state->single_line) {
864- // on windows, up&down in single-line behave like left&right
865- key = STB_TEXTEDIT_K_RIGHT | (key & STB_TEXTEDIT_K_SHIFT);
866- goto retry;
867- }
868-
869- if (sel)
870- stb_textedit_prep_selection_at_cursor(state);
871- else if (STB_TEXT_HAS_SELECTION(state))
872- stb_textedit_move_to_last(str,state);
873-
874- // compute current position of cursor point
875- stb_textedit_clamp(str, state);
876- stb_textedit_find_charpos(&find, str, state->cursor, state->single_line);
877-
878- // now find character position down a row
879- if (find.length) {
880- float goal_x = state->has_preferred_x ? state->preferred_x : find.x;
881- float x;
882- int start = find.first_char + find.length;
883- state->cursor = start;
884- STB_TEXTEDIT_LAYOUTROW(&row, str, state->cursor);
885- x = row.x0;
886- for (i=0; i < row.num_chars; ++i) {
887- float dx = STB_TEXTEDIT_GETWIDTH(str, start, i);
888- #ifdef STB_TEXTEDIT_GETWIDTH_NEWLINE
889- if (dx == STB_TEXTEDIT_GETWIDTH_NEWLINE)
890- break;
891- #endif
892- x += dx;
893- if (x > goal_x)
894- break;
895- ++state->cursor;
896- }
897- stb_textedit_clamp(str, state);
898-
899- state->has_preferred_x = 1;
900- state->preferred_x = goal_x;
901-
902- if (sel)
903- state->select_end = state->cursor;
904- }
905- break;
906- }
907-
908- case STB_TEXTEDIT_K_UP:
909- case STB_TEXTEDIT_K_UP | STB_TEXTEDIT_K_SHIFT: {
910- StbFindState find;
911- StbTexteditRow row;
912- int i, sel = (key & STB_TEXTEDIT_K_SHIFT) != 0;
913-
914- if (state->single_line) {
915- // on windows, up&down become left&right
916- key = STB_TEXTEDIT_K_LEFT | (key & STB_TEXTEDIT_K_SHIFT);
917- goto retry;
918- }
919-
920- if (sel)
921- stb_textedit_prep_selection_at_cursor(state);
922- else if (STB_TEXT_HAS_SELECTION(state))
923- stb_textedit_move_to_first(state);
924-
925- // compute current position of cursor point
926- stb_textedit_clamp(str, state);
927- stb_textedit_find_charpos(&find, str, state->cursor, state->single_line);
928-
929- // can only go up if there's a previous row
930- if (find.prev_first != find.first_char) {
931- // now find character position up a row
932- float goal_x = state->has_preferred_x ? state->preferred_x : find.x;
933- float x;
934- state->cursor = find.prev_first;
935- STB_TEXTEDIT_LAYOUTROW(&row, str, state->cursor);
936- x = row.x0;
937- for (i=0; i < row.num_chars; ++i) {
938- float dx = STB_TEXTEDIT_GETWIDTH(str, find.prev_first, i);
939- #ifdef STB_TEXTEDIT_GETWIDTH_NEWLINE
940- if (dx == STB_TEXTEDIT_GETWIDTH_NEWLINE)
941- break;
942- #endif
943- x += dx;
944- if (x > goal_x)
945- break;
946- ++state->cursor;
947- }
948- stb_textedit_clamp(str, state);
949-
950- state->has_preferred_x = 1;
951- state->preferred_x = goal_x;
952-
953- if (sel)
954- state->select_end = state->cursor;
955- }
956- break;
957- }
958-
959- case STB_TEXTEDIT_K_DELETE:
960- case STB_TEXTEDIT_K_DELETE | STB_TEXTEDIT_K_SHIFT:
961- if (STB_TEXT_HAS_SELECTION(state))
962- stb_textedit_delete_selection(str, state);
963- else {
964- int n = STB_TEXTEDIT_STRINGLEN(str);
965- if (state->cursor < n)
966- stb_textedit_delete(str, state, state->cursor, 1);
967- }
968- state->has_preferred_x = 0;
969- break;
970-
971- case STB_TEXTEDIT_K_BACKSPACE:
972- case STB_TEXTEDIT_K_BACKSPACE | STB_TEXTEDIT_K_SHIFT:
973- if (STB_TEXT_HAS_SELECTION(state))
974- stb_textedit_delete_selection(str, state);
975- else {
976- stb_textedit_clamp(str, state);
977- if (state->cursor > 0) {
978- stb_textedit_delete(str, state, state->cursor-1, 1);
979- --state->cursor;
980- }
981- }
982- state->has_preferred_x = 0;
983- break;
984-
985-#ifdef STB_TEXTEDIT_K_TEXTSTART2
986- case STB_TEXTEDIT_K_TEXTSTART2:
987-#endif
988- case STB_TEXTEDIT_K_TEXTSTART:
989- state->cursor = state->select_start = state->select_end = 0;
990- state->has_preferred_x = 0;
991- break;
992-
993-#ifdef STB_TEXTEDIT_K_TEXTEND2
994- case STB_TEXTEDIT_K_TEXTEND2:
995-#endif
996- case STB_TEXTEDIT_K_TEXTEND:
997- state->cursor = STB_TEXTEDIT_STRINGLEN(str);
998- state->select_start = state->select_end = 0;
999- state->has_preferred_x = 0;
1000- break;
1001-
1002-#ifdef STB_TEXTEDIT_K_TEXTSTART2
1003- case STB_TEXTEDIT_K_TEXTSTART2 | STB_TEXTEDIT_K_SHIFT:
1004-#endif
1005- case STB_TEXTEDIT_K_TEXTSTART | STB_TEXTEDIT_K_SHIFT:
1006- stb_textedit_prep_selection_at_cursor(state);
1007- state->cursor = state->select_end = 0;
1008- state->has_preferred_x = 0;
1009- break;
1010-
1011-#ifdef STB_TEXTEDIT_K_TEXTEND2
1012- case STB_TEXTEDIT_K_TEXTEND2 | STB_TEXTEDIT_K_SHIFT:
1013-#endif
1014- case STB_TEXTEDIT_K_TEXTEND | STB_TEXTEDIT_K_SHIFT:
1015- stb_textedit_prep_selection_at_cursor(state);
1016- state->cursor = state->select_end = STB_TEXTEDIT_STRINGLEN(str);
1017- state->has_preferred_x = 0;
1018- break;
1019-
1020-
1021-#ifdef STB_TEXTEDIT_K_LINESTART2
1022- case STB_TEXTEDIT_K_LINESTART2:
1023-#endif
1024- case STB_TEXTEDIT_K_LINESTART:
1025- stb_textedit_clamp(str, state);
1026- stb_textedit_move_to_first(state);
1027- if (state->single_line)
1028- state->cursor = 0;
1029- else while (state->cursor > 0 && STB_TEXTEDIT_GETCHAR(str, state->cursor-1) != STB_TEXTEDIT_NEWLINE)
1030- --state->cursor;
1031- state->has_preferred_x = 0;
1032- break;
1033-
1034-#ifdef STB_TEXTEDIT_K_LINEEND2
1035- case STB_TEXTEDIT_K_LINEEND2:
1036-#endif
1037- case STB_TEXTEDIT_K_LINEEND: {
1038- int n = STB_TEXTEDIT_STRINGLEN(str);
1039- stb_textedit_clamp(str, state);
1040- stb_textedit_move_to_first(state);
1041- if (state->single_line)
1042- state->cursor = n;
1043- else while (state->cursor < n && STB_TEXTEDIT_GETCHAR(str, state->cursor) != STB_TEXTEDIT_NEWLINE)
1044- ++state->cursor;
1045- state->has_preferred_x = 0;
1046- break;
1047- }
1048-
1049-#ifdef STB_TEXTEDIT_K_LINESTART2
1050- case STB_TEXTEDIT_K_LINESTART2 | STB_TEXTEDIT_K_SHIFT:
1051-#endif
1052- case STB_TEXTEDIT_K_LINESTART | STB_TEXTEDIT_K_SHIFT:
1053- stb_textedit_clamp(str, state);
1054- stb_textedit_prep_selection_at_cursor(state);
1055- if (state->single_line)
1056- state->cursor = 0;
1057- else while (state->cursor > 0 && STB_TEXTEDIT_GETCHAR(str, state->cursor-1) != STB_TEXTEDIT_NEWLINE)
1058- --state->cursor;
1059- state->select_end = state->cursor;
1060- state->has_preferred_x = 0;
1061- break;
1062-
1063-#ifdef STB_TEXTEDIT_K_LINEEND2
1064- case STB_TEXTEDIT_K_LINEEND2 | STB_TEXTEDIT_K_SHIFT:
1065-#endif
1066- case STB_TEXTEDIT_K_LINEEND | STB_TEXTEDIT_K_SHIFT: {
1067- int n = STB_TEXTEDIT_STRINGLEN(str);
1068- stb_textedit_clamp(str, state);
1069- stb_textedit_prep_selection_at_cursor(state);
1070- if (state->single_line)
1071- state->cursor = n;
1072- else while (state->cursor < n && STB_TEXTEDIT_GETCHAR(str, state->cursor) != STB_TEXTEDIT_NEWLINE)
1073- ++state->cursor;
1074- state->select_end = state->cursor;
1075- state->has_preferred_x = 0;
1076- break;
1077- }
1078-
1079-// @TODO:
1080-// STB_TEXTEDIT_K_PGUP - move cursor up a page
1081-// STB_TEXTEDIT_K_PGDOWN - move cursor down a page
1082- }
1083-}
1084-
1085-/////////////////////////////////////////////////////////////////////////////
1086-//
1087-// Undo processing
1088-//
1089-// @OPTIMIZE: the undo/redo buffer should be circular
1090-
1091-static void stb_textedit_flush_redo(StbUndoState *state)
1092-{
1093- state->redo_point = STB_TEXTEDIT_UNDOSTATECOUNT;
1094- state->redo_char_point = STB_TEXTEDIT_UNDOCHARCOUNT;
1095-}
1096-
1097-// discard the oldest entry in the undo list
1098-static void stb_textedit_discard_undo(StbUndoState *state)
1099-{
1100- if (state->undo_point > 0) {
1101- // if the 0th undo state has characters, clean those up
1102- if (state->undo_rec[0].char_storage >= 0) {
1103- int n = state->undo_rec[0].insert_length, i;
1104- // delete n characters from all other records
1105- state->undo_char_point -= n;
1106- STB_TEXTEDIT_memmove(state->undo_char, state->undo_char + n, (size_t) (state->undo_char_point*sizeof(STB_TEXTEDIT_CHARTYPE)));
1107- for (i=0; i < state->undo_point; ++i)
1108- if (state->undo_rec[i].char_storage >= 0)
1109- state->undo_rec[i].char_storage -= n; // @OPTIMIZE: get rid of char_storage and infer it
1110- }
1111- --state->undo_point;
1112- STB_TEXTEDIT_memmove(state->undo_rec, state->undo_rec+1, (size_t) (state->undo_point*sizeof(state->undo_rec[0])));
1113- }
1114-}
1115-
1116-// discard the oldest entry in the redo list--it's bad if this
1117-// ever happens, but because undo & redo have to store the actual
1118-// characters in different cases, the redo character buffer can
1119-// fill up even though the undo buffer didn't
1120-static void stb_textedit_discard_redo(StbUndoState *state)
1121-{
1122- int k = STB_TEXTEDIT_UNDOSTATECOUNT-1;
1123-
1124- if (state->redo_point <= k) {
1125- // if the k'th undo state has characters, clean those up
1126- if (state->undo_rec[k].char_storage >= 0) {
1127- int n = state->undo_rec[k].insert_length, i;
1128- // move the remaining redo character data to the end of the buffer
1129- state->redo_char_point += n;
1130- STB_TEXTEDIT_memmove(state->undo_char + state->redo_char_point, state->undo_char + state->redo_char_point-n, (size_t) ((STB_TEXTEDIT_UNDOCHARCOUNT - state->redo_char_point)*sizeof(STB_TEXTEDIT_CHARTYPE)));
1131- // adjust the position of all the other records to account for above memmove
1132- for (i=state->redo_point; i < k; ++i)
1133- if (state->undo_rec[i].char_storage >= 0)
1134- state->undo_rec[i].char_storage += n;
1135- }
1136- // now move all the redo records towards the end of the buffer; the first one is at 'redo_point'
1137- // {DEAR IMGUI]
1138- size_t move_size = (size_t)((STB_TEXTEDIT_UNDOSTATECOUNT - state->redo_point - 1) * sizeof(state->undo_rec[0]));
1139- const char* buf_begin = (char*)state->undo_rec; (void)buf_begin;
1140- const char* buf_end = (char*)state->undo_rec + sizeof(state->undo_rec); (void)buf_end;
1141- IM_ASSERT(((char*)(state->undo_rec + state->redo_point)) >= buf_begin);
1142- IM_ASSERT(((char*)(state->undo_rec + state->redo_point + 1) + move_size) <= buf_end);
1143- STB_TEXTEDIT_memmove(state->undo_rec + state->redo_point+1, state->undo_rec + state->redo_point, move_size);
1144-
1145- // now move redo_point to point to the new one
1146- ++state->redo_point;
1147- }
1148-}
1149-
1150-static StbUndoRecord *stb_text_create_undo_record(StbUndoState *state, int numchars)
1151-{
1152- // any time we create a new undo record, we discard redo
1153- stb_textedit_flush_redo(state);
1154-
1155- // if we have no free records, we have to make room, by sliding the
1156- // existing records down
1157- if (state->undo_point == STB_TEXTEDIT_UNDOSTATECOUNT)
1158- stb_textedit_discard_undo(state);
1159-
1160- // if the characters to store won't possibly fit in the buffer, we can't undo
1161- if (numchars > STB_TEXTEDIT_UNDOCHARCOUNT) {
1162- state->undo_point = 0;
1163- state->undo_char_point = 0;
1164- return NULL;
1165- }
1166-
1167- // if we don't have enough free characters in the buffer, we have to make room
1168- while (state->undo_char_point + numchars > STB_TEXTEDIT_UNDOCHARCOUNT)
1169- stb_textedit_discard_undo(state);
1170-
1171- return &state->undo_rec[state->undo_point++];
1172-}
1173-
1174-static STB_TEXTEDIT_CHARTYPE *stb_text_createundo(StbUndoState *state, int pos, int insert_len, int delete_len)
1175-{
1176- StbUndoRecord *r = stb_text_create_undo_record(state, insert_len);
1177- if (r == NULL)
1178- return NULL;
1179-
1180- r->where = pos;
1181- r->insert_length = (STB_TEXTEDIT_POSITIONTYPE) insert_len;
1182- r->delete_length = (STB_TEXTEDIT_POSITIONTYPE) delete_len;
1183-
1184- if (insert_len == 0) {
1185- r->char_storage = -1;
1186- return NULL;
1187- } else {
1188- r->char_storage = state->undo_char_point;
1189- state->undo_char_point += insert_len;
1190- return &state->undo_char[r->char_storage];
1191- }
1192-}
1193-
1194-static void stb_text_undo(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
1195-{
1196- StbUndoState *s = &state->undostate;
1197- StbUndoRecord u, *r;
1198- if (s->undo_point == 0)
1199- return;
1200-
1201- // we need to do two things: apply the undo record, and create a redo record
1202- u = s->undo_rec[s->undo_point-1];
1203- r = &s->undo_rec[s->redo_point-1];
1204- r->char_storage = -1;
1205-
1206- r->insert_length = u.delete_length;
1207- r->delete_length = u.insert_length;
1208- r->where = u.where;
1209-
1210- if (u.delete_length) {
1211- // if the undo record says to delete characters, then the redo record will
1212- // need to re-insert the characters that get deleted, so we need to store
1213- // them.
1214-
1215- // there are three cases:
1216- // there's enough room to store the characters
1217- // characters stored for *redoing* don't leave room for redo
1218- // characters stored for *undoing* don't leave room for redo
1219- // if the last is true, we have to bail
1220-
1221- if (s->undo_char_point + u.delete_length >= STB_TEXTEDIT_UNDOCHARCOUNT) {
1222- // the undo records take up too much character space; there's no space to store the redo characters
1223- r->insert_length = 0;
1224- } else {
1225- int i;
1226-
1227- // there's definitely room to store the characters eventually
1228- while (s->undo_char_point + u.delete_length > s->redo_char_point) {
1229- // should never happen:
1230- if (s->redo_point == STB_TEXTEDIT_UNDOSTATECOUNT)
1231- return;
1232- // there's currently not enough room, so discard a redo record
1233- stb_textedit_discard_redo(s);
1234- }
1235- r = &s->undo_rec[s->redo_point-1];
1236-
1237- r->char_storage = s->redo_char_point - u.delete_length;
1238- s->redo_char_point = s->redo_char_point - u.delete_length;
1239-
1240- // now save the characters
1241- for (i=0; i < u.delete_length; ++i)
1242- s->undo_char[r->char_storage + i] = STB_TEXTEDIT_GETCHAR(str, u.where + i);
1243- }
1244-
1245- // now we can carry out the deletion
1246- STB_TEXTEDIT_DELETECHARS(str, u.where, u.delete_length);
1247- }
1248-
1249- // check type of recorded action:
1250- if (u.insert_length) {
1251- // easy case: was a deletion, so we need to insert n characters
1252- STB_TEXTEDIT_INSERTCHARS(str, u.where, &s->undo_char[u.char_storage], u.insert_length);
1253- s->undo_char_point -= u.insert_length;
1254- }
1255-
1256- state->cursor = u.where + u.insert_length;
1257-
1258- s->undo_point--;
1259- s->redo_point--;
1260-}
1261-
1262-static void stb_text_redo(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
1263-{
1264- StbUndoState *s = &state->undostate;
1265- StbUndoRecord *u, r;
1266- if (s->redo_point == STB_TEXTEDIT_UNDOSTATECOUNT)
1267- return;
1268-
1269- // we need to do two things: apply the redo record, and create an undo record
1270- u = &s->undo_rec[s->undo_point];
1271- r = s->undo_rec[s->redo_point];
1272-
1273- // we KNOW there must be room for the undo record, because the redo record
1274- // was derived from an undo record
1275-
1276- u->delete_length = r.insert_length;
1277- u->insert_length = r.delete_length;
1278- u->where = r.where;
1279- u->char_storage = -1;
1280-
1281- if (r.delete_length) {
1282- // the redo record requires us to delete characters, so the undo record
1283- // needs to store the characters
1284-
1285- if (s->undo_char_point + u->insert_length > s->redo_char_point) {
1286- u->insert_length = 0;
1287- u->delete_length = 0;
1288- } else {
1289- int i;
1290- u->char_storage = s->undo_char_point;
1291- s->undo_char_point = s->undo_char_point + u->insert_length;
1292-
1293- // now save the characters
1294- for (i=0; i < u->insert_length; ++i)
1295- s->undo_char[u->char_storage + i] = STB_TEXTEDIT_GETCHAR(str, u->where + i);
1296- }
1297-
1298- STB_TEXTEDIT_DELETECHARS(str, r.where, r.delete_length);
1299- }
1300-
1301- if (r.insert_length) {
1302- // easy case: need to insert n characters
1303- STB_TEXTEDIT_INSERTCHARS(str, r.where, &s->undo_char[r.char_storage], r.insert_length);
1304- s->redo_char_point += r.insert_length;
1305- }
1306-
1307- state->cursor = r.where + r.insert_length;
1308-
1309- s->undo_point++;
1310- s->redo_point++;
1311-}
1312-
1313-static void stb_text_makeundo_insert(STB_TexteditState *state, int where, int length)
1314-{
1315- stb_text_createundo(&state->undostate, where, 0, length);
1316-}
1317-
1318-static void stb_text_makeundo_delete(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int length)
1319-{
1320- int i;
1321- STB_TEXTEDIT_CHARTYPE *p = stb_text_createundo(&state->undostate, where, length, 0);
1322- if (p) {
1323- for (i=0; i < length; ++i)
1324- p[i] = STB_TEXTEDIT_GETCHAR(str, where+i);
1325- }
1326-}
1327-
1328-static void stb_text_makeundo_replace(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int old_length, int new_length)
1329-{
1330- int i;
1331- STB_TEXTEDIT_CHARTYPE *p = stb_text_createundo(&state->undostate, where, old_length, new_length);
1332- if (p) {
1333- for (i=0; i < old_length; ++i)
1334- p[i] = STB_TEXTEDIT_GETCHAR(str, where+i);
1335- }
1336-}
1337-
1338-// reset the state to default
1339-static void stb_textedit_clear_state(STB_TexteditState *state, int is_single_line)
1340-{
1341- state->undostate.undo_point = 0;
1342- state->undostate.undo_char_point = 0;
1343- state->undostate.redo_point = STB_TEXTEDIT_UNDOSTATECOUNT;
1344- state->undostate.redo_char_point = STB_TEXTEDIT_UNDOCHARCOUNT;
1345- state->select_end = state->select_start = 0;
1346- state->cursor = 0;
1347- state->has_preferred_x = 0;
1348- state->preferred_x = 0;
1349- state->cursor_at_end_of_line = 0;
1350- state->initialized = 1;
1351- state->single_line = (unsigned char) is_single_line;
1352- state->insert_mode = 0;
1353-}
1354-
1355-// API initialize
1356-static void stb_textedit_initialize_state(STB_TexteditState *state, int is_single_line)
1357-{
1358- stb_textedit_clear_state(state, is_single_line);
1359-}
1360-
1361-#if defined(__GNUC__) || defined(__clang__)
1362-#pragma GCC diagnostic push
1363-#pragma GCC diagnostic ignored "-Wcast-qual"
1364-#endif
1365-
1366-static int stb_textedit_paste(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_CHARTYPE const *ctext, int len)
1367-{
1368- return stb_textedit_paste_internal(str, state, (STB_TEXTEDIT_CHARTYPE *) ctext, len);
1369-}
1370-
1371-#if defined(__GNUC__) || defined(__clang__)
1372-#pragma GCC diagnostic pop
1373-#endif
1374-
1375-#endif//STB_TEXTEDIT_IMPLEMENTATION
1376-
1377-/*
1378-------------------------------------------------------------------------------
1379-This software is available under 2 licenses -- choose whichever you prefer.
1380-------------------------------------------------------------------------------
1381-ALTERNATIVE A - MIT License
1382-Copyright (c) 2017 Sean Barrett
1383-Permission is hereby granted, free of charge, to any person obtaining a copy of
1384-this software and associated documentation files (the "Software"), to deal in
1385-the Software without restriction, including without limitation the rights to
1386-use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
1387-of the Software, and to permit persons to whom the Software is furnished to do
1388-so, subject to the following conditions:
1389-The above copyright notice and this permission notice shall be included in all
1390-copies or substantial portions of the Software.
1391-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1392-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1393-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1394-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1395-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
1396-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
1397-SOFTWARE.
1398-------------------------------------------------------------------------------
1399-ALTERNATIVE B - Public Domain (www.unlicense.org)
1400-This is free and unencumbered software released into the public domain.
1401-Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
1402-software, either in source code form or as a compiled binary, for any purpose,
1403-commercial or non-commercial, and by any means.
1404-In jurisdictions that recognize copyright laws, the author or authors of this
1405-software dedicate any and all copyright interest in the software to the public
1406-domain. We make this dedication for the benefit of the public at large and to
1407-the detriment of our heirs and successors. We intend this dedication to be an
1408-overt act of relinquishment in perpetuity of all present and future rights to
1409-this software under copyright law.
1410-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1411-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1412-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1413-AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
1414-ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
1415-WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1416-------------------------------------------------------------------------------
1417-*/
--- Equity10/Common/imGui/include/imconfig.h (revision 212)
+++ Equity10/Common/imGui/include/imconfig.h (revision 213)
@@ -1,59 +1,42 @@
11 //-----------------------------------------------------------------------------
2-// COMPILE-TIME OPTIONS FOR DEAR IMGUI
3-// Runtime options (clipboard callbacks, enabling various features, etc.) can generally be set via the ImGuiIO structure.
4-// You can use ImGui::SetAllocatorFunctions() before calling ImGui::CreateContext() to rewire memory allocation functions.
2+// USER IMPLEMENTATION
3+// This file contains compile-time options for ImGui.
4+// Other options (memory allocation overrides, callbacks, etc.) can be set at runtime via the ImGuiIO structure - ImGui::GetIO().
55 //-----------------------------------------------------------------------------
6-// A) You may edit imconfig.h (and not overwrite it when updating Dear ImGui, or maintain a patch/branch with your modifications to imconfig.h)
7-// B) or add configuration directives in your own file and compile with #define IMGUI_USER_CONFIG "myfilename.h"
8-// If you do so you need to make sure that configuration settings are defined consistently _everywhere_ Dear ImGui is used, which include
9-// the imgui*.cpp files but also _any_ of your code that uses Dear ImGui. This is because some compile-time options have an affect on data structures.
10-// Defining those options in imconfig.h will ensure every compilation unit gets to see the same data structure layouts.
11-// Call IMGUI_CHECKVERSION() from your .cpp files to verify that the data structures your files are using are matching the ones imgui.cpp is using.
12-//-----------------------------------------------------------------------------
136
147 #pragma once
158
169 //---- Define assertion handler. Defaults to calling assert().
1710 //#define IM_ASSERT(_EXPR) MyAssert(_EXPR)
18-//#define IM_ASSERT(_EXPR) ((void)(_EXPR)) // Disable asserts
1911
20-//---- Define attributes of all API symbols declarations, e.g. for DLL under Windows
21-// Using dear imgui via a shared library is not recommended, because of function call overhead and because we don't guarantee backward nor forward ABI compatibility.
12+//---- Define attributes of all API symbols declarations, e.g. for DLL under Windows.
2213 //#define IMGUI_API __declspec( dllexport )
2314 //#define IMGUI_API __declspec( dllimport )
2415
25-//---- Don't define obsolete functions/enums names. Consider enabling from time to time after updating to avoid using soon-to-be obsolete function/names.
16+//---- Don't define obsolete functions names. Consider enabling from time to time or when updating to reduce like hood of using already obsolete function/names
2617 //#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS
2718
28-//---- Don't implement demo windows functionality (ShowDemoWindow()/ShowStyleEditor()/ShowUserGuide() methods will be empty)
29-// It is very strongly recommended to NOT disable the demo windows during development. Please read the comments in imgui_demo.cpp.
30-//#define IMGUI_DISABLE_DEMO_WINDOWS
31-//#define IMGUI_DISABLE_METRICS_WINDOW
19+//---- Include imgui_user.h at the end of imgui.h
20+//#define IMGUI_INCLUDE_IMGUI_USER_H
3221
33-//---- Don't implement some functions to reduce linkage requirements.
34-//#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS // [Win32] Don't implement default clipboard handler. Won't use and link with OpenClipboard/GetClipboardData/CloseClipboard etc.
35-//#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS // [Win32] Don't implement default IME handler. Won't use and link with ImmGetContext/ImmSetCompositionWindow.
36-//#define IMGUI_DISABLE_WIN32_FUNCTIONS // [Win32] Won't use and link with any Win32 function (clipboard, ime).
37-//#define IMGUI_ENABLE_OSX_DEFAULT_CLIPBOARD_FUNCTIONS // [OSX] Implement default OSX clipboard handler (need to link with '-framework ApplicationServices').
38-//#define IMGUI_DISABLE_FORMAT_STRING_FUNCTIONS // Don't implement ImFormatString/ImFormatStringV so you can implement them yourself if you don't want to link with vsnprintf.
39-//#define IMGUI_DISABLE_MATH_FUNCTIONS // Don't implement ImFabs/ImSqrt/ImPow/ImFmod/ImCos/ImSin/ImAcos/ImAtan2 wrapper so you can implement them yourself. Declare your prototypes in imconfig.h.
40-//#define IMGUI_DISABLE_DEFAULT_ALLOCATORS // Don't implement default allocators calling malloc()/free() to avoid linking with them. You will need to call ImGui::SetAllocatorFunctions().
22+//---- Don't implement default handlers for Windows (so as not to link with OpenClipboard() and others Win32 functions)
23+//#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS
24+//#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS
4125
42-//---- Include imgui_user.h at the end of imgui.h as a convenience
43-//#define IMGUI_INCLUDE_IMGUI_USER_H
26+//---- Don't implement test window functionality (ShowTestWindow()/ShowStyleEditor()/ShowUserGuide() methods will be empty)
27+//---- It is very strongly recommended to NOT disable the test windows. Please read the comment at the top of imgui_demo.cpp to learn why.
28+//#define IMGUI_DISABLE_TEST_WINDOWS
4429
45-//---- Pack colors to BGRA8 instead of RGBA8 (to avoid converting from one to another)
30+//---- Don't implement ImFormatString(), ImFormatStringV() so you can reimplement them yourself.
31+//#define IMGUI_DISABLE_FORMAT_STRING_FUNCTIONS
32+
33+//---- Pack colors to BGRA instead of RGBA (remove need to post process vertex buffer in back ends)
4634 //#define IMGUI_USE_BGRA_PACKED_COLOR
4735
48-//---- Avoid multiple STB libraries implementations, or redefine path/filenames to prioritize another version
49-// By default the embedded implementations are declared static and not available outside of imgui cpp files.
50-//#define IMGUI_STB_TRUETYPE_FILENAME "my_folder/stb_truetype.h"
51-//#define IMGUI_STB_RECT_PACK_FILENAME "my_folder/stb_rect_pack.h"
52-//#define IMGUI_DISABLE_STB_TRUETYPE_IMPLEMENTATION
53-//#define IMGUI_DISABLE_STB_RECT_PACK_IMPLEMENTATION
36+//---- Implement STB libraries in a namespace to avoid linkage conflicts
37+//#define IMGUI_STB_NAMESPACE ImGuiStb
5438
55-//---- Define constructor and implicit cast operators to convert back<>forth between your math types and ImVec2/ImVec4.
56-// This will be inlined as part of ImVec2 and ImVec4 class declarations.
39+//---- Define constructor and implicit cast operators to convert back<>forth from your math types and ImVec2/ImVec4.
5740 /*
5841 #define IM_VEC2_CLASS_EXTRA \
5942 ImVec2(const MyVec2& f) { x = f.x; y = f.y; } \
@@ -64,30 +47,15 @@
6447 operator MyVec4() const { return MyVec4(x,y,z,w); }
6548 */
6649
67-//---- Using 32-bits vertex indices (default is 16-bits) is one way to allow large meshes with more than 64K vertices.
68-// Your renderer back-end will need to support it (most example renderer back-ends support both 16/32-bits indices).
69-// Another way to allow large meshes while keeping 16-bits indices is to handle ImDrawCmd::VtxOffset in your renderer.
70-// Read about ImGuiBackendFlags_RendererHasVtxOffset for details.
50+//---- Use 32-bit vertex indices (instead of default: 16-bit) to allow meshes with more than 64K vertices
7151 //#define ImDrawIdx unsigned int
7252
73-//---- Override ImDrawCallback signature (will need to modify renderer back-ends accordingly)
74-//struct ImDrawList;
75-//struct ImDrawCmd;
76-//typedef void (*MyImDrawCallback)(const ImDrawList* draw_list, const ImDrawCmd* cmd, void* my_renderer_user_data);
77-//#define ImDrawCallback MyImDrawCallback
78-
79-//---- Debug Tools
80-// Use 'Metrics->Tools->Item Picker' to pick widgets with the mouse and break into them for easy debugging.
81-//#define IM_DEBUG_BREAK IM_ASSERT(0)
82-//#define IM_DEBUG_BREAK __debugbreak()
83-// Have the Item Picker break in the ItemAdd() function instead of ItemHoverable() - which is earlier in the code, will catch a few extra items, allow picking items other than Hovered one.
84-// This adds a small runtime cost which is why it is not enabled by default.
85-//#define IMGUI_DEBUG_TOOL_ITEM_PICKER_EX
86-
8753 //---- Tip: You can add extra functions within the ImGui:: namespace, here or in your own headers files.
54+//---- e.g. create variants of the ImGui::Value() helper for your low-level math types, or your own widgets/helpers.
8855 /*
8956 namespace ImGui
9057 {
91- void MyFunction(const char* name, const MyMatrix44& v);
58+ void Value(const char* prefix, const MyMatrix44& v, const char* float_format = NULL);
9259 }
9360 */
61+
--- Equity10/Common/imGui/include/imgui.cpp (nonexistent)
+++ Equity10/Common/imGui/include/imgui.cpp (revision 213)
@@ -0,0 +1,10887 @@
1+// dear imgui, v1.52
2+// (main code and documentation)
3+
4+// See ImGui::ShowTestWindow() in imgui_demo.cpp for demo code.
5+// Newcomers, read 'Programmer guide' below for notes on how to setup Dear ImGui in your codebase.
6+// Get latest version at https://github.com/ocornut/imgui
7+// Releases change-log at https://github.com/ocornut/imgui/releases
8+// Gallery (please post your screenshots/video there!): https://github.com/ocornut/imgui/issues/1269
9+// Developed by Omar Cornut and every direct or indirect contributors to the GitHub.
10+// This library is free but I need your support to sustain development and maintenance.
11+// If you work for a company, please consider financial support, e.g: https://www.patreon.com/imgui
12+
13+/*
14+
15+ Index
16+ - MISSION STATEMENT
17+ - END-USER GUIDE
18+ - PROGRAMMER GUIDE (read me!)
19+ - Read first
20+ - How to update to a newer version of Dear ImGui
21+ - Getting started with integrating Dear ImGui in your code/engine
22+ - API BREAKING CHANGES (read me when you update!)
23+ - ISSUES & TODO LIST
24+ - FREQUENTLY ASKED QUESTIONS (FAQ), TIPS
25+ - How can I help?
26+ - What is ImTextureID and how do I display an image?
27+ - I integrated Dear ImGui in my engine and the text or lines are blurry..
28+ - I integrated Dear ImGui in my engine and some elements are clipping or disappearing when I move windows around..
29+ - How can I have multiple widgets with the same label? Can I have widget without a label? (Yes). A primer on labels/IDs.
30+ - How can I tell when Dear ImGui wants my mouse/keyboard inputs VS when I can pass them to my application?
31+ - How can I load a different font than the default?
32+ - How can I easily use icons in my application?
33+ - How can I load multiple fonts?
34+ - How can I display and input non-latin characters such as Chinese, Japanese, Korean, Cyrillic?
35+ - How can I preserve my Dear ImGui context across reloading a DLL? (loss of the global/static variables)
36+ - How can I use the drawing facilities without an ImGui window? (using ImDrawList API)
37+ - ISSUES & TODO-LIST
38+ - CODE
39+
40+
41+ MISSION STATEMENT
42+ =================
43+
44+ - Easy to use to create code-driven and data-driven tools
45+ - Easy to use to create ad hoc short-lived tools and long-lived, more elaborate tools
46+ - Easy to hack and improve
47+ - Minimize screen real-estate usage
48+ - Minimize setup and maintenance
49+ - Minimize state storage on user side
50+ - Portable, minimize dependencies, run on target (consoles, phones, etc.)
51+ - Efficient runtime and memory consumption (NB- we do allocate when "growing" content e.g. creating a window, opening a tree node
52+ for the first time, etc. but a typical frame won't allocate anything)
53+
54+ Designed for developers and content-creators, not the typical end-user! Some of the weaknesses includes:
55+ - Doesn't look fancy, doesn't animate
56+ - Limited layout features, intricate layouts are typically crafted in code
57+
58+
59+ END-USER GUIDE
60+ ==============
61+
62+ - Double-click title bar to collapse window
63+ - Click upper right corner to close a window, available when 'bool* p_open' is passed to ImGui::Begin()
64+ - Click and drag on lower right corner to resize window
65+ - Click and drag on any empty space to move window
66+ - Double-click/double-tap on lower right corner grip to auto-fit to content
67+ - TAB/SHIFT+TAB to cycle through keyboard editable fields
68+ - Use mouse wheel to scroll
69+ - Use CTRL+mouse wheel to zoom window contents (if io.FontAllowScaling is true)
70+ - CTRL+Click on a slider or drag box to input value as text
71+ - Text editor:
72+ - Hold SHIFT or use mouse to select text.
73+ - CTRL+Left/Right to word jump
74+ - CTRL+Shift+Left/Right to select words
75+ - CTRL+A our Double-Click to select all
76+ - CTRL+X,CTRL+C,CTRL+V to use OS clipboard
77+ - CTRL+Z,CTRL+Y to undo/redo
78+ - ESCAPE to revert text to its original value
79+ - You can apply arithmetic operators +,*,/ on numerical values. Use +- to subtract (because - would set a negative value!)
80+ - Controls are automatically adjusted for OSX to match standard OSX text editing operations.
81+
82+
83+ PROGRAMMER GUIDE
84+ ================
85+
86+ READ FIRST
87+
88+ - Read the FAQ below this section!
89+ - Your code creates the UI, if your code doesn't run the UI is gone! == very dynamic UI, no construction/destructions steps, less data retention
90+ on your side, no state duplication, less sync, less bugs.
91+ - Call and read ImGui::ShowTestWindow() for demo code demonstrating most features.
92+ - You can learn about immediate-mode gui principles at http://www.johno.se/book/imgui.html or watch http://mollyrocket.com/861
93+
94+ HOW TO UPDATE TO A NEWER VERSION OF DEAR IMGUI
95+
96+ - Overwrite all the sources files except for imconfig.h (if you have made modification to your copy of imconfig.h)
97+ - Read the "API BREAKING CHANGES" section (below). This is where we list occasional API breaking changes.
98+ If a function/type has been renamed / or marked obsolete, try to fix the name in your code before it is permanently removed from the public API.
99+ If you have a problem with a missing function/symbols, search for its name in the code, there will likely be a comment about it.
100+ Please report any issue to the GitHub page!
101+ - Try to keep your copy of dear imgui reasonably up to date.
102+
103+ GETTING STARTED WITH INTEGRATING DEAR IMGUI IN YOUR CODE/ENGINE
104+
105+ - Add the Dear ImGui source files to your projects, using your preferred build system.
106+ It is recommended you build the .cpp files as part of your project and not as a library.
107+ - You can later customize the imconfig.h file to tweak some compilation time behavior, such as integrating imgui types with your own maths types.
108+ - See examples/ folder for standalone sample applications. To understand the integration process, you can read examples/opengl2_example/ because
109+ it is short, then switch to the one more appropriate to your use case.
110+ - You may be able to grab and copy a ready made imgui_impl_*** file from the examples/.
111+ - When using Dear ImGui, your programming IDE is your friend: follow the declaration of variables, functions and types to find comments about them.
112+
113+ - Init: retrieve the ImGuiIO structure with ImGui::GetIO() and fill the fields marked 'Settings': at minimum you need to set io.DisplaySize
114+ (application resolution). Later on you will fill your keyboard mapping, clipboard handlers, and other advanced features but for a basic
115+ integration you don't need to worry about it all.
116+ - Init: call io.Fonts->GetTexDataAsRGBA32(...), it will build the font atlas texture, then load the texture pixels into graphics memory.
117+ - Every frame:
118+ - In your main loop as early a possible, fill the IO fields marked 'Input' (e.g. mouse position, buttons, keyboard info, etc.)
119+ - Call ImGui::NewFrame() to begin the frame
120+ - You can use any ImGui function you want between NewFrame() and Render()
121+ - Call ImGui::Render() as late as you can to end the frame and finalize render data. it will call your io.RenderDrawListFn handler.
122+ (Even if you don't render, call Render() and ignore the callback, or call EndFrame() instead. Otherwhise some features will break)
123+ - All rendering information are stored into command-lists until ImGui::Render() is called.
124+ - Dear ImGui never touches or knows about your GPU state. the only function that knows about GPU is the RenderDrawListFn handler that you provide.
125+ - Effectively it means you can create widgets at any time in your code, regardless of considerations of being in "update" vs "render" phases
126+ of your own application.
127+ - Refer to the examples applications in the examples/ folder for instruction on how to setup your code.
128+ - A minimal application skeleton may be:
129+
130+ // Application init
131+ ImGuiIO& io = ImGui::GetIO();
132+ io.DisplaySize.x = 1920.0f;
133+ io.DisplaySize.y = 1280.0f;
134+ io.RenderDrawListsFn = MyRenderFunction; // Setup a render function, or set to NULL and call GetDrawData() after Render() to access render data.
135+ // TODO: Fill others settings of the io structure later.
136+
137+ // Load texture atlas (there is a default font so you don't need to care about choosing a font yet)
138+ unsigned char* pixels;
139+ int width, height;
140+ io.Fonts->GetTexDataAsRGBA32(pixels, &width, &height);
141+ // TODO: At this points you've got the texture data and you need to upload that your your graphic system:
142+ MyTexture* texture = MyEngine::CreateTextureFromMemoryPixels(pixels, width, height, TEXTURE_TYPE_RGBA)
143+ // TODO: Store your texture pointer/identifier (whatever your engine uses) in 'io.Fonts->TexID'. This will be passed back to your via the renderer.
144+ io.Fonts->TexID = (void*)texture;
145+
146+ // Application main loop
147+ while (true)
148+ {
149+ // Setup low-level inputs (e.g. on Win32, GetKeyboardState(), or write to those fields from your Windows message loop handlers, etc.)
150+ ImGuiIO& io = ImGui::GetIO();
151+ io.DeltaTime = 1.0f/60.0f;
152+ io.MousePos = mouse_pos;
153+ io.MouseDown[0] = mouse_button_0;
154+ io.MouseDown[1] = mouse_button_1;
155+
156+ // Call NewFrame(), after this point you can use ImGui::* functions anytime
157+ ImGui::NewFrame();
158+
159+ // Most of your application code here
160+ MyGameUpdate(); // may use any ImGui functions, e.g. ImGui::Begin("My window"); ImGui::Text("Hello, world!"); ImGui::End();
161+ MyGameRender(); // may use any ImGui functions as well!
162+
163+ // Render & swap video buffers
164+ ImGui::Render();
165+ SwapBuffers();
166+ }
167+
168+ - A minimal render function skeleton may be:
169+
170+ void void MyRenderFunction(ImDrawData* draw_data)(ImDrawData* draw_data)
171+ {
172+ // TODO: Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled
173+ // TODO: Setup viewport, orthographic projection matrix
174+ // TODO: Setup shader: vertex { float2 pos, float2 uv, u32 color }, fragment shader sample color from 1 texture, multiply by vertex color.
175+ for (int n = 0; n < draw_data->CmdListsCount; n++)
176+ {
177+ const ImDrawVert* vtx_buffer = cmd_list->VtxBuffer.Data; // vertex buffer generated by ImGui
178+ const ImDrawIdx* idx_buffer = cmd_list->IdxBuffer.Data; // index buffer generated by ImGui
179+ for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
180+ {
181+ const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
182+ if (pcmd->UserCallback)
183+ {
184+ pcmd->UserCallback(cmd_list, pcmd);
185+ }
186+ else
187+ {
188+ // The texture for the draw call is specified by pcmd->TextureId.
189+ // The vast majority of draw calls with use the imgui texture atlas, which value you have set yourself during initialization.
190+ MyEngineBindTexture(pcmd->TextureId);
191+
192+ // We are using scissoring to clip some objects. All low-level graphics API supports it.
193+ // If your engine doesn't support scissoring yet, you will get some small glitches (some elements outside their bounds) which you can fix later.
194+ MyEngineScissor((int)pcmd->ClipRect.x, (int)pcmd->ClipRect.y, (int)(pcmd->ClipRect.z - pcmd->ClipRect.x), (int)(pcmd->ClipRect.w - pcmd->ClipRect.y));
195+
196+ // Render 'pcmd->ElemCount/3' indexed triangles.
197+ // By default the indices ImDrawIdx are 16-bits, you can change them to 32-bits if your engine doesn't support 16-bits indices.
198+ MyEngineDrawIndexedTriangles(pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer, vtx_buffer);
199+ }
200+ idx_buffer += pcmd->ElemCount;
201+ }
202+ }
203+ }
204+
205+ - The examples/ folders contains many functional implementation of the pseudo-code above.
206+ - When calling NewFrame(), the 'io.WantCaptureMouse'/'io.WantCaptureKeyboard'/'io.WantTextInput' flags are updated.
207+ They tell you if ImGui intends to use your inputs. So for example, if 'io.WantCaptureMouse' is set you would typically want to hide
208+ mouse inputs from the rest of your application. Read the FAQ below for more information about those flags.
209+
210+
211+
212+ API BREAKING CHANGES
213+ ====================
214+
215+ Occasionally introducing changes that are breaking the API. The breakage are generally minor and easy to fix.
216+ Here is a change-log of API breaking changes, if you are using one of the functions listed, expect to have to fix some code.
217+ Also read releases logs https://github.com/ocornut/imgui/releases for more details.
218+
219+ - 2017/10/24 (1.52) - renamed IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCS/IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCS to IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS/IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS for consistency.
220+ - 2017/10/20 (1.52) - changed IsWindowHovered() default parameters behavior to return false if an item is active in another window (e.g. click-dragging item from another window to this window). You can use the newly introduced IsWindowHovered() flags to requests this specific behavior if you need it.
221+ - 2017/10/20 (1.52) - marked IsItemHoveredRect()/IsMouseHoveringWindow() as obsolete, in favor of using the newly introduced flags for IsItemHovered() and IsWindowHovered(). See https://github.com/ocornut/imgui/issues/1382 for details.
222+ removed the IsItemRectHovered()/IsWindowRectHovered() names introduced in 1.51 since they were merely more consistent names for the two functions we are now obsoleting.
223+ - 2017/10/17 (1.52) - marked the old 5-parameters version of Begin() as obsolete (still available). Use SetNextWindowSize()+Begin() instead!
224+ - 2017/10/11 (1.52) - renamed AlignFirstTextHeightToWidgets() to AlignTextToFramePadding(). Kept inline redirection function (will obsolete).
225+ - 2017/09/25 (1.52) - removed SetNextWindowPosCenter() because SetNextWindowPos() now has the optional pivot information to do the same and more. Kept redirection function (will obsolete).
226+ - 2017/08/25 (1.52) - io.MousePos needs to be set to ImVec2(-FLT_MAX,-FLT_MAX) when mouse is unavailable/missing. Previously ImVec2(-1,-1) was enough but we now accept negative mouse coordinates. In your binding if you need to support unavailable mouse, make sure to replace "io.MousePos = ImVec2(-1,-1)" with "io.MousePos = ImVec2(-FLT_MAX,-FLT_MAX)".
227+ - 2017/08/22 (1.51) - renamed IsItemHoveredRect() to IsItemRectHovered(). Kept inline redirection function (will obsolete). -> (1.52) use IsItemHovered(ImGuiHoveredFlags_RectOnly)!
228+ - renamed IsMouseHoveringAnyWindow() to IsAnyWindowHovered() for consistency. Kept inline redirection function (will obsolete).
229+ - renamed IsMouseHoveringWindow() to IsWindowRectHovered() for consistency. Kept inline redirection function (will obsolete).
230+ - 2017/08/20 (1.51) - renamed GetStyleColName() to GetStyleColorName() for consistency.
231+ - 2017/08/20 (1.51) - added PushStyleColor(ImGuiCol idx, ImU32 col) overload, which _might_ cause an "ambiguous call" compilation error if you are using ImColor() with implicit cast. Cast to ImU32 or ImVec4 explicily to fix.
232+ - 2017/08/15 (1.51) - marked the weird IMGUI_ONCE_UPON_A_FRAME helper macro as obsolete. prefer using the more explicit ImGuiOnceUponAFrame.
233+ - 2017/08/15 (1.51) - changed parameter order for BeginPopupContextWindow() from (const char*,int buttons,bool also_over_items) to (const char*,int buttons,bool also_over_items). Note that most calls relied on default parameters completely.
234+ - 2017/08/13 (1.51) - renamed ImGuiCol_Columns*** to ImGuiCol_Separator***. Kept redirection enums (will obsolete).
235+ - 2017/08/11 (1.51) - renamed ImGuiSetCond_*** types and flags to ImGuiCond_***. Kept redirection enums (will obsolete).
236+ - 2017/08/09 (1.51) - removed ValueColor() helpers, they are equivalent to calling Text(label) + SameLine() + ColorButton().
237+ - 2017/08/08 (1.51) - removed ColorEditMode() and ImGuiColorEditMode in favor of ImGuiColorEditFlags and parameters to the various Color*() functions. The SetColorEditOptions() allows to initialize default but the user can still change them with right-click context menu.
238+ - changed prototype of 'ColorEdit4(const char* label, float col[4], bool show_alpha = true)' to 'ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flags = 0)', where passing flags = 0x01 is a safe no-op (hello dodgy backward compatibility!). - check and run the demo window, under "Color/Picker Widgets", to understand the various new options.
239+ - changed prototype of rarely used 'ColorButton(ImVec4 col, bool small_height = false, bool outline_border = true)' to 'ColorButton(const char* desc_id, ImVec4 col, ImGuiColorEditFlags flags = 0, ImVec2 size = ImVec2(0,0))'
240+ - 2017/07/20 (1.51) - removed IsPosHoveringAnyWindow(ImVec2), which was partly broken and misleading. ASSERT + redirect user to io.WantCaptureMouse
241+ - 2017/05/26 (1.50) - removed ImFontConfig::MergeGlyphCenterV in favor of a more multipurpose ImFontConfig::GlyphOffset.
242+ - 2017/05/01 (1.50) - renamed ImDrawList::PathFill() (rarely used directly) to ImDrawList::PathFillConvex() for clarity.
243+ - 2016/11/06 (1.50) - BeginChild(const char*) now applies the stack id to the provided label, consistently with other functions as it should always have been. It shouldn't affect you unless (extremely unlikely) you were appending multiple times to a same child from different locations of the stack id. If that's the case, generate an id with GetId() and use it instead of passing string to BeginChild().
244+ - 2016/10/15 (1.50) - avoid 'void* user_data' parameter to io.SetClipboardTextFn/io.GetClipboardTextFn pointers. We pass io.ClipboardUserData to it.
245+ - 2016/09/25 (1.50) - style.WindowTitleAlign is now a ImVec2 (ImGuiAlign enum was removed). set to (0.5f,0.5f) for horizontal+vertical centering, (0.0f,0.0f) for upper-left, etc.
246+ - 2016/07/30 (1.50) - SameLine(x) with x>0.0f is now relative to left of column/group if any, and not always to left of window. This was sort of always the intent and hopefully breakage should be minimal.
247+ - 2016/05/12 (1.49) - title bar (using ImGuiCol_TitleBg/ImGuiCol_TitleBgActive colors) isn't rendered over a window background (ImGuiCol_WindowBg color) anymore.
248+ If your TitleBg/TitleBgActive alpha was 1.0f or you are using the default theme it will not affect you.
249+ However if your TitleBg/TitleBgActive alpha was <1.0f you need to tweak your custom theme to readjust for the fact that we don't draw a WindowBg background behind the title bar.
250+ This helper function will convert an old TitleBg/TitleBgActive color into a new one with the same visual output, given the OLD color and the OLD WindowBg color.
251+ ImVec4 ConvertTitleBgCol(const ImVec4& win_bg_col, const ImVec4& title_bg_col)
252+ {
253+ float new_a = 1.0f - ((1.0f - win_bg_col.w) * (1.0f - title_bg_col.w)), k = title_bg_col.w / new_a;
254+ return ImVec4((win_bg_col.x * win_bg_col.w + title_bg_col.x) * k, (win_bg_col.y * win_bg_col.w + title_bg_col.y) * k, (win_bg_col.z * win_bg_col.w + title_bg_col.z) * k, new_a);
255+ }
256+ If this is confusing, pick the RGB value from title bar from an old screenshot and apply this as TitleBg/TitleBgActive. Or you may just create TitleBgActive from a tweaked TitleBg color.
257+ - 2016/05/07 (1.49) - removed confusing set of GetInternalState(), GetInternalStateSize(), SetInternalState() functions. Now using CreateContext(), DestroyContext(), GetCurrentContext(), SetCurrentContext().
258+ - 2016/05/02 (1.49) - renamed SetNextTreeNodeOpened() to SetNextTreeNodeOpen(), no redirection.
259+ - 2016/05/01 (1.49) - obsoleted old signature of CollapsingHeader(const char* label, const char* str_id = NULL, bool display_frame = true, bool default_open = false) as extra parameters were badly designed and rarely used. You can replace the "default_open = true" flag in new API with CollapsingHeader(label, ImGuiTreeNodeFlags_DefaultOpen).
260+ - 2016/04/26 (1.49) - changed ImDrawList::PushClipRect(ImVec4 rect) to ImDraw::PushClipRect(Imvec2 min,ImVec2 max,bool intersect_with_current_clip_rect=false). Note that higher-level ImGui::PushClipRect() is preferable because it will clip at logic/widget level, whereas ImDrawList::PushClipRect() only affect your renderer.
261+ - 2016/04/03 (1.48) - removed style.WindowFillAlphaDefault setting which was redundant. Bake default BG alpha inside style.Colors[ImGuiCol_WindowBg] and all other Bg color values. (ref github issue #337).
262+ - 2016/04/03 (1.48) - renamed ImGuiCol_TooltipBg to ImGuiCol_PopupBg, used by popups/menus and tooltips. popups/menus were previously using ImGuiCol_WindowBg. (ref github issue #337)
263+ - 2016/03/21 (1.48) - renamed GetWindowFont() to GetFont(), GetWindowFontSize() to GetFontSize(). Kept inline redirection function (will obsolete).
264+ - 2016/03/02 (1.48) - InputText() completion/history/always callbacks: if you modify the text buffer manually (without using DeleteChars()/InsertChars() helper) you need to maintain the BufTextLen field. added an assert.
265+ - 2016/01/23 (1.48) - fixed not honoring exact width passed to PushItemWidth(), previously it would add extra FramePadding.x*2 over that width. if you had manual pixel-perfect alignment in place it might affect you.
266+ - 2015/12/27 (1.48) - fixed ImDrawList::AddRect() which used to render a rectangle 1 px too large on each axis.
267+ - 2015/12/04 (1.47) - renamed Color() helpers to ValueColor() - dangerously named, rarely used and probably to be made obsolete.
268+ - 2015/08/29 (1.45) - with the addition of horizontal scrollbar we made various fixes to inconsistencies with dealing with cursor position.
269+ GetCursorPos()/SetCursorPos() functions now include the scrolled amount. It shouldn't affect the majority of users, but take note that SetCursorPosX(100.0f) puts you at +100 from the starting x position which may include scrolling, not at +100 from the window left side.
270+ GetContentRegionMax()/GetWindowContentRegionMin()/GetWindowContentRegionMax() functions allow include the scrolled amount. Typically those were used in cases where no scrolling would happen so it may not be a problem, but watch out!
271+ - 2015/08/29 (1.45) - renamed style.ScrollbarWidth to style.ScrollbarSize
272+ - 2015/08/05 (1.44) - split imgui.cpp into extra files: imgui_demo.cpp imgui_draw.cpp imgui_internal.h that you need to add to your project.
273+ - 2015/07/18 (1.44) - fixed angles in ImDrawList::PathArcTo(), PathArcToFast() (introduced in 1.43) being off by an extra PI for no justifiable reason
274+ - 2015/07/14 (1.43) - add new ImFontAtlas::AddFont() API. For the old AddFont***, moved the 'font_no' parameter of ImFontAtlas::AddFont** functions to the ImFontConfig structure.
275+ you need to render your textured triangles with bilinear filtering to benefit from sub-pixel positioning of text.
276+ - 2015/07/08 (1.43) - switched rendering data to use indexed rendering. this is saving a fair amount of CPU/GPU and enables us to get anti-aliasing for a marginal cost.
277+ this necessary change will break your rendering function! the fix should be very easy. sorry for that :(
278+ - if you are using a vanilla copy of one of the imgui_impl_XXXX.cpp provided in the example, you just need to update your copy and you can ignore the rest.
279+ - the signature of the io.RenderDrawListsFn handler has changed!
280+ ImGui_XXXX_RenderDrawLists(ImDrawList** const cmd_lists, int cmd_lists_count)
281+ became:
282+ ImGui_XXXX_RenderDrawLists(ImDrawData* draw_data).
283+ argument 'cmd_lists' -> 'draw_data->CmdLists'
284+ argument 'cmd_lists_count' -> 'draw_data->CmdListsCount'
285+ ImDrawList 'commands' -> 'CmdBuffer'
286+ ImDrawList 'vtx_buffer' -> 'VtxBuffer'
287+ ImDrawList n/a -> 'IdxBuffer' (new)
288+ ImDrawCmd 'vtx_count' -> 'ElemCount'
289+ ImDrawCmd 'clip_rect' -> 'ClipRect'
290+ ImDrawCmd 'user_callback' -> 'UserCallback'
291+ ImDrawCmd 'texture_id' -> 'TextureId'
292+ - each ImDrawList now contains both a vertex buffer and an index buffer. For each command, render ElemCount/3 triangles using indices from the index buffer.
293+ - if you REALLY cannot render indexed primitives, you can call the draw_data->DeIndexAllBuffers() method to de-index the buffers. This is slow and a waste of CPU/GPU. Prefer using indexed rendering!
294+ - refer to code in the examples/ folder or ask on the GitHub if you are unsure of how to upgrade. please upgrade!
295+ - 2015/07/10 (1.43) - changed SameLine() parameters from int to float.
296+ - 2015/07/02 (1.42) - renamed SetScrollPosHere() to SetScrollFromCursorPos(). Kept inline redirection function (will obsolete).
297+ - 2015/07/02 (1.42) - renamed GetScrollPosY() to GetScrollY(). Necessary to reduce confusion along with other scrolling functions, because positions (e.g. cursor position) are not equivalent to scrolling amount.
298+ - 2015/06/14 (1.41) - changed ImageButton() default bg_col parameter from (0,0,0,1) (black) to (0,0,0,0) (transparent) - makes a difference when texture have transparence
299+ - 2015/06/14 (1.41) - changed Selectable() API from (label, selected, size) to (label, selected, flags, size). Size override should have been rarely be used. Sorry!
300+ - 2015/05/31 (1.40) - renamed GetWindowCollapsed() to IsWindowCollapsed() for consistency. Kept inline redirection function (will obsolete).
301+ - 2015/05/31 (1.40) - renamed IsRectClipped() to IsRectVisible() for consistency. Note that return value is opposite! Kept inline redirection function (will obsolete).
302+ - 2015/05/27 (1.40) - removed the third 'repeat_if_held' parameter from Button() - sorry! it was rarely used and inconsistent. Use PushButtonRepeat(true) / PopButtonRepeat() to enable repeat on desired buttons.
303+ - 2015/05/11 (1.40) - changed BeginPopup() API, takes a string identifier instead of a bool. ImGui needs to manage the open/closed state of popups. Call OpenPopup() to actually set the "open" state of a popup. BeginPopup() returns true if the popup is opened.
304+ - 2015/05/03 (1.40) - removed style.AutoFitPadding, using style.WindowPadding makes more sense (the default values were already the same).
305+ - 2015/04/13 (1.38) - renamed IsClipped() to IsRectClipped(). Kept inline redirection function until 1.50.
306+ - 2015/04/09 (1.38) - renamed ImDrawList::AddArc() to ImDrawList::AddArcFast() for compatibility with future API
307+ - 2015/04/03 (1.38) - removed ImGuiCol_CheckHovered, ImGuiCol_CheckActive, replaced with the more general ImGuiCol_FrameBgHovered, ImGuiCol_FrameBgActive.
308+ - 2014/04/03 (1.38) - removed support for passing -FLT_MAX..+FLT_MAX as the range for a SliderFloat(). Use DragFloat() or Inputfloat() instead.
309+ - 2015/03/17 (1.36) - renamed GetItemBoxMin()/GetItemBoxMax()/IsMouseHoveringBox() to GetItemRectMin()/GetItemRectMax()/IsMouseHoveringRect(). Kept inline redirection function until 1.50.
310+ - 2015/03/15 (1.36) - renamed style.TreeNodeSpacing to style.IndentSpacing, ImGuiStyleVar_TreeNodeSpacing to ImGuiStyleVar_IndentSpacing
311+ - 2015/03/13 (1.36) - renamed GetWindowIsFocused() to IsWindowFocused(). Kept inline redirection function until 1.50.
312+ - 2015/03/08 (1.35) - renamed style.ScrollBarWidth to style.ScrollbarWidth (casing)
313+ - 2015/02/27 (1.34) - renamed OpenNextNode(bool) to SetNextTreeNodeOpened(bool, ImGuiSetCond). Kept inline redirection function until 1.50.
314+ - 2015/02/27 (1.34) - renamed ImGuiSetCondition_*** to ImGuiSetCond_***, and _FirstUseThisSession becomes _Once.
315+ - 2015/02/11 (1.32) - changed text input callback ImGuiTextEditCallback return type from void-->int. reserved for future use, return 0 for now.
316+ - 2015/02/10 (1.32) - renamed GetItemWidth() to CalcItemWidth() to clarify its evolving behavior
317+ - 2015/02/08 (1.31) - renamed GetTextLineSpacing() to GetTextLineHeightWithSpacing()
318+ - 2015/02/01 (1.31) - removed IO.MemReallocFn (unused)
319+ - 2015/01/19 (1.30) - renamed ImGuiStorage::GetIntPtr()/GetFloatPtr() to GetIntRef()/GetIntRef() because Ptr was conflicting with actual pointer storage functions.
320+ - 2015/01/11 (1.30) - big font/image API change! now loads TTF file. allow for multiple fonts. no need for a PNG loader.
321+ (1.30) - removed GetDefaultFontData(). uses io.Fonts->GetTextureData*() API to retrieve uncompressed pixels.
322+ this sequence:
323+ const void* png_data;
324+ unsigned int png_size;
325+ ImGui::GetDefaultFontData(NULL, NULL, &png_data, &png_size);
326+ // <Copy to GPU>
327+ became:
328+ unsigned char* pixels;
329+ int width, height;
330+ io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height);
331+ // <Copy to GPU>
332+ io.Fonts->TexID = (your_texture_identifier);
333+ you now have much more flexibility to load multiple TTF fonts and manage the texture buffer for internal needs.
334+ it is now recommended that you sample the font texture with bilinear interpolation.
335+ (1.30) - added texture identifier in ImDrawCmd passed to your render function (we can now render images). make sure to set io.Fonts->TexID.
336+ (1.30) - removed IO.PixelCenterOffset (unnecessary, can be handled in user projection matrix)
337+ (1.30) - removed ImGui::IsItemFocused() in favor of ImGui::IsItemActive() which handles all widgets
338+ - 2014/12/10 (1.18) - removed SetNewWindowDefaultPos() in favor of new generic API SetNextWindowPos(pos, ImGuiSetCondition_FirstUseEver)
339+ - 2014/11/28 (1.17) - moved IO.Font*** options to inside the IO.Font-> structure (FontYOffset, FontTexUvForWhite, FontBaseScale, FontFallbackGlyph)
340+ - 2014/11/26 (1.17) - reworked syntax of IMGUI_ONCE_UPON_A_FRAME helper macro to increase compiler compatibility
341+ - 2014/11/07 (1.15) - renamed IsHovered() to IsItemHovered()
342+ - 2014/10/02 (1.14) - renamed IMGUI_INCLUDE_IMGUI_USER_CPP to IMGUI_INCLUDE_IMGUI_USER_INL and imgui_user.cpp to imgui_user.inl (more IDE friendly)
343+ - 2014/09/25 (1.13) - removed 'text_end' parameter from IO.SetClipboardTextFn (the string is now always zero-terminated for simplicity)
344+ - 2014/09/24 (1.12) - renamed SetFontScale() to SetWindowFontScale()
345+ - 2014/09/24 (1.12) - moved IM_MALLOC/IM_REALLOC/IM_FREE preprocessor defines to IO.MemAllocFn/IO.MemReallocFn/IO.MemFreeFn
346+ - 2014/08/30 (1.09) - removed IO.FontHeight (now computed automatically)
347+ - 2014/08/30 (1.09) - moved IMGUI_FONT_TEX_UV_FOR_WHITE preprocessor define to IO.FontTexUvForWhite
348+ - 2014/08/28 (1.09) - changed the behavior of IO.PixelCenterOffset following various rendering fixes
349+
350+
351+ ISSUES & TODO-LIST
352+ ==================
353+ See TODO.txt
354+
355+
356+ FREQUENTLY ASKED QUESTIONS (FAQ), TIPS
357+ ======================================
358+
359+ Q: How can I help?
360+ A: - If you are experienced enough with Dear ImGui and with C/C++, look at the todo list and see how you want/can help!
361+ - Become a Patron/donate! Convince your company to become a Patron or provide serious funding for development time! See http://www.patreon.com/imgui
362+
363+ Q: What is ImTextureID and how do I display an image?
364+ A: ImTextureID is a void* used to pass renderer-agnostic texture references around until it hits your render function.
365+ Dear ImGui knows nothing about what those bits represent, it just passes them around. It is up to you to decide what you want the void* to carry!
366+ It could be an identifier to your OpenGL texture (cast GLuint to void*), a pointer to your custom engine material (cast MyMaterial* to void*), etc.
367+ At the end of the chain, your renderer takes this void* to cast it back into whatever it needs to select a current texture to render.
368+ Refer to examples applications, where each renderer (in a imgui_impl_xxxx.cpp file) is treating ImTextureID as a different thing.
369+ (c++ tip: OpenGL uses integers to identify textures. You can safely store an integer into a void*, just cast it to void*, don't take it's address!)
370+ To display a custom image/texture within an ImGui window, you may use ImGui::Image(), ImGui::ImageButton(), ImDrawList::AddImage() functions.
371+ Dear ImGui will generate the geometry and draw calls using the ImTextureID that you passed and which your renderer can use.
372+ It is your responsibility to get textures uploaded to your GPU.
373+
374+ Q: I integrated Dear ImGui in my engine and the text or lines are blurry..
375+ A: In your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f).
376+ Also make sure your orthographic projection matrix and io.DisplaySize matches your actual framebuffer dimension.
377+
378+ Q: I integrated Dear ImGui in my engine and some elements are clipping or disappearing when I move windows around..
379+ A: You are probably mishandling the clipping rectangles in your render function.
380+ Rectangles provided by ImGui are defined as (x1=left,y1=top,x2=right,y2=bottom) and NOT as (x1,y1,width,height).
381+
382+ Q: Can I have multiple widgets with the same label? Can I have widget without a label?
383+ A: Yes. A primer on the use of labels/IDs in Dear ImGui..
384+
385+ - Elements that are not clickable, such as Text() items don't need an ID.
386+
387+ - Interactive widgets require state to be carried over multiple frames (most typically Dear ImGui often needs to remember what is
388+ the "active" widget). to do so they need a unique ID. unique ID are typically derived from a string label, an integer index or a pointer.
389+
390+ Button("OK"); // Label = "OK", ID = hash of "OK"
391+ Button("Cancel"); // Label = "Cancel", ID = hash of "Cancel"
392+
393+ - ID are uniquely scoped within windows, tree nodes, etc. so no conflict can happen if you have two buttons called "OK"
394+ in two different windows or in two different locations of a tree.
395+
396+ - If you have a same ID twice in the same location, you'll have a conflict:
397+
398+ Button("OK");
399+ Button("OK"); // ID collision! Both buttons will be treated as the same.
400+
401+ Fear not! this is easy to solve and there are many ways to solve it!
402+
403+ - When passing a label you can optionally specify extra unique ID information within string itself.
404+ This helps solving the simpler collision cases. Use "##" to pass a complement to the ID that won't be visible to the end-user:
405+
406+ Button("Play"); // Label = "Play", ID = hash of "Play"
407+ Button("Play##foo1"); // Label = "Play", ID = hash of "Play##foo1" (different from above)
408+ Button("Play##foo2"); // Label = "Play", ID = hash of "Play##foo2" (different from above)
409+
410+ - If you want to completely hide the label, but still need an ID:
411+
412+ Checkbox("##On", &b); // Label = "", ID = hash of "##On" (no label!)
413+
414+ - Occasionally/rarely you might want change a label while preserving a constant ID. This allows you to animate labels.
415+ For example you may want to include varying information in a window title bar (and windows are uniquely identified by their ID.. obviously)
416+ Use "###" to pass a label that isn't part of ID:
417+
418+ Button("Hello###ID"; // Label = "Hello", ID = hash of "ID"
419+ Button("World###ID"; // Label = "World", ID = hash of "ID" (same as above)
420+
421+ sprintf(buf, "My game (%f FPS)###MyGame");
422+ Begin(buf); // Variable label, ID = hash of "MyGame"
423+
424+ - Use PushID() / PopID() to create scopes and avoid ID conflicts within the same Window.
425+ This is the most convenient way of distinguishing ID if you are iterating and creating many UI elements.
426+ You can push a pointer, a string or an integer value. Remember that ID are formed from the concatenation of everything in the ID stack!
427+
428+ for (int i = 0; i < 100; i++)
429+ {
430+ PushID(i);
431+ Button("Click"); // Label = "Click", ID = hash of integer + "label" (unique)
432+ PopID();
433+ }
434+
435+ for (int i = 0; i < 100; i++)
436+ {
437+ MyObject* obj = Objects[i];
438+ PushID(obj);
439+ Button("Click"); // Label = "Click", ID = hash of pointer + "label" (unique)
440+ PopID();
441+ }
442+
443+ for (int i = 0; i < 100; i++)
444+ {
445+ MyObject* obj = Objects[i];
446+ PushID(obj->Name);
447+ Button("Click"); // Label = "Click", ID = hash of string + "label" (unique)
448+ PopID();
449+ }
450+
451+ - More example showing that you can stack multiple prefixes into the ID stack:
452+
453+ Button("Click"); // Label = "Click", ID = hash of "Click"
454+ PushID("node");
455+ Button("Click"); // Label = "Click", ID = hash of "node" + "Click"
456+ PushID(my_ptr);
457+ Button("Click"); // Label = "Click", ID = hash of "node" + ptr + "Click"
458+ PopID();
459+ PopID();
460+
461+ - Tree nodes implicitly creates a scope for you by calling PushID().
462+
463+ Button("Click"); // Label = "Click", ID = hash of "Click"
464+ if (TreeNode("node"))
465+ {
466+ Button("Click"); // Label = "Click", ID = hash of "node" + "Click"
467+ TreePop();
468+ }
469+
470+ - When working with trees, ID are used to preserve the open/close state of each tree node.
471+ Depending on your use cases you may want to use strings, indices or pointers as ID.
472+ e.g. when displaying a single object that may change over time (dynamic 1-1 relationship), using a static string as ID will preserve your
473+ node open/closed state when the targeted object change.
474+ e.g. when displaying a list of objects, using indices or pointers as ID will preserve the node open/closed state differently.
475+ experiment and see what makes more sense!
476+
477+ Q: How can I tell when Dear ImGui wants my mouse/keyboard inputs VS when I can pass them to my application?
478+ A: You can read the 'io.WantCaptureMouse'/'io.WantCaptureKeyboard'/'ioWantTextInput' flags from the ImGuiIO structure.
479+ - When 'io.WantCaptureMouse' or 'io.WantCaptureKeyboard' flags are set you may want to discard/hide the inputs from the rest of your application.
480+ - When 'io.WantTextInput' is set to may want to notify your OS to popup an on-screen keyboard, if available (e.g. on a mobile phone, or console OS).
481+ Preferably read the flags after calling ImGui::NewFrame() to avoid them lagging by one frame. But reading those flags before calling NewFrame() is
482+ also generally ok, as the bool toggles fairly rarely and you don't generally expect to interact with either Dear ImGui or your application during
483+ the same frame when that transition occurs. Dear ImGui is tracking dragging and widget activity that may occur outside the boundary of a window,
484+ so 'io.WantCaptureMouse' is more accurate and correct than checking if a window is hovered.
485+ (Advanced note: text input releases focus on Return 'KeyDown', so the following Return 'KeyUp' event that your application receive will typically
486+ have 'io.WantCaptureKeyboard=false'. Depending on your application logic it may or not be inconvenient. You might want to track which key-downs
487+ were for Dear ImGui, e.g. with an array of bool, and filter out the corresponding key-ups.)
488+
489+ Q: How can I load a different font than the default? (default is an embedded version of ProggyClean.ttf, rendered at size 13)
490+ A: Use the font atlas to load the TTF/OTF file you want:
491+
492+ ImGuiIO& io = ImGui::GetIO();
493+ io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_in_pixels);
494+ io.Fonts->GetTexDataAsRGBA32() or GetTexDataAsAlpha8()
495+
496+ Q: How can I easily use icons in my application?
497+ A: The most convenient and practical way is to merge an icon font such as FontAwesome inside you main font. Then you can refer to icons within your
498+ strings. Read 'How can I load multiple fonts?' and the file 'extra_fonts/README.txt' for instructions and useful header files.
499+
500+ Q: How can I load multiple fonts?
501+ A: Use the font atlas to pack them into a single texture:
502+ (Read extra_fonts/README.txt and the code in ImFontAtlas for more details.)
503+
504+ ImGuiIO& io = ImGui::GetIO();
505+ ImFont* font0 = io.Fonts->AddFontDefault();
506+ ImFont* font1 = io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_in_pixels);
507+ ImFont* font2 = io.Fonts->AddFontFromFileTTF("myfontfile2.ttf", size_in_pixels);
508+ io.Fonts->GetTexDataAsRGBA32() or GetTexDataAsAlpha8()
509+ // the first loaded font gets used by default
510+ // use ImGui::PushFont()/ImGui::PopFont() to change the font at runtime
511+
512+ // Options
513+ ImFontConfig config;
514+ config.OversampleH = 3;
515+ config.OversampleV = 1;
516+ config.GlyphOffset.y -= 2.0f; // Move everything by 2 pixels up
517+ config.GlyphExtraSpacing.x = 1.0f; // Increase spacing between characters
518+ io.Fonts->LoadFromFileTTF("myfontfile.ttf", size_pixels, &config);
519+
520+ // Combine multiple fonts into one (e.g. for icon fonts)
521+ ImWchar ranges[] = { 0xf000, 0xf3ff, 0 };
522+ ImFontConfig config;
523+ config.MergeMode = true;
524+ io.Fonts->AddFontDefault();
525+ io.Fonts->LoadFromFileTTF("fontawesome-webfont.ttf", 16.0f, &config, ranges); // Merge icon font
526+ io.Fonts->LoadFromFileTTF("myfontfile.ttf", size_pixels, NULL, &config, io.Fonts->GetGlyphRangesJapanese()); // Merge japanese glyphs
527+
528+ Q: How can I display and input non-Latin characters such as Chinese, Japanese, Korean, Cyrillic?
529+ A: When loading a font, pass custom Unicode ranges to specify the glyphs to load.
530+
531+ // Add default Japanese ranges
532+ io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_in_pixels, NULL, io.Fonts->GetGlyphRangesJapanese());
533+
534+ // Or create your own custom ranges (e.g. for a game you can feed your entire game script and only build the characters the game need)
535+ ImVector<ImWchar> ranges;
536+ ImFontAtlas::GlyphRangesBuilder builder;
537+ builder.AddText("Hello world"); // Add a string (here "Hello world" contains 7 unique characters)
538+ builder.AddChar(0x7262); // Add a specific character
539+ builder.AddRanges(io.Fonts->GetGlyphRangesJapanese()); // Add one of the default ranges
540+ builder.BuildRanges(&ranges); // Build the final result (ordered ranges with all the unique characters submitted)
541+ io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_in_pixels, NULL, ranges.Data);
542+
543+ All your strings needs to use UTF-8 encoding. In C++11 you can encode a string literal in UTF-8 by using the u8"hello" syntax.
544+ Specifying literal in your source code using a local code page (such as CP-923 for Japanese or CP-1251 for Cyrillic) will NOT work!
545+ Otherwise you can convert yourself to UTF-8 or load text data from file already saved as UTF-8.
546+
547+ Text input: it is up to your application to pass the right character code to io.AddInputCharacter(). The applications in examples/ are doing that.
548+ For languages using IME, on Windows you can copy the Hwnd of your application to io.ImeWindowHandle.
549+ The default implementation of io.ImeSetInputScreenPosFn() on Windows will set your IME position correctly.
550+
551+ Q: How can I preserve my Dear ImGui context across reloading a DLL? (loss of the global/static variables)
552+ A: Create your own context 'ctx = CreateContext()' + 'SetCurrentContext(ctx)' and your own font atlas 'ctx->GetIO().Fonts = new ImFontAtlas()'
553+ so you don't rely on the default globals.
554+
555+ Q: How can I use the drawing facilities without an ImGui window? (using ImDrawList API)
556+ A: The easiest way is to create a dummy window. Call Begin() with NoTitleBar|NoResize|NoMove|NoScrollbar|NoSavedSettings|NoInputs flag,
557+ zero background alpha, then retrieve the ImDrawList* via GetWindowDrawList() and draw to it in any way you like.
558+ You can also perfectly create a standalone ImDrawList instance _but_ you need ImGui to be initialized because ImDrawList pulls from ImGui
559+ data to retrieve the coordinates of the white pixel.
560+
561+ - tip: you can call Begin() multiple times with the same name during the same frame, it will keep appending to the same window.
562+ this is also useful to set yourself in the context of another window (to get/set other settings)
563+ - tip: you can create widgets without a Begin()/End() block, they will go in an implicit window called "Debug".
564+ - tip: the ImGuiOnceUponAFrame helper will allow run the block of code only once a frame. You can use it to quickly add custom UI in the middle
565+ of a deep nested inner loop in your code.
566+ - tip: you can call Render() multiple times (e.g for VR renders).
567+ - tip: call and read the ShowTestWindow() code in imgui_demo.cpp for more example of how to use ImGui!
568+
569+*/
570+
571+#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
572+#define _CRT_SECURE_NO_WARNINGS
573+#endif
574+
575+#include "imgui.h"
576+#define IMGUI_DEFINE_MATH_OPERATORS
577+#define IMGUI_DEFINE_PLACEMENT_NEW
578+#include "imgui_internal.h"
579+
580+#include <ctype.h> // toupper, isprint
581+#include <stdlib.h> // NULL, malloc, free, qsort, atoi
582+#include <stdio.h> // vsnprintf, sscanf, printf
583+#include <limits.h> // INT_MIN, INT_MAX
584+#if defined(_MSC_VER) && _MSC_VER <= 1500 // MSVC 2008 or earlier
585+#include <stddef.h> // intptr_t
586+#else
587+#include <stdint.h> // intptr_t
588+#endif
589+
590+#ifdef _MSC_VER
591+#pragma warning (disable: 4127) // condition expression is constant
592+#pragma warning (disable: 4505) // unreferenced local function has been removed (stb stuff)
593+#pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen
594+#endif
595+
596+// Clang warnings with -Weverything
597+#ifdef __clang__
598+#pragma clang diagnostic ignored "-Wunknown-pragmas" // warning : unknown warning group '-Wformat-pedantic *' // not all warnings are known by all clang versions.. so ignoring warnings triggers new warnings on some configuration. great!
599+#pragma clang diagnostic ignored "-Wold-style-cast" // warning : use of old-style cast // yes, they are more terse.
600+#pragma clang diagnostic ignored "-Wfloat-equal" // warning : comparing floating point with == or != is unsafe // storing and comparing against same constants (typically 0.0f) is ok.
601+#pragma clang diagnostic ignored "-Wformat-nonliteral" // warning : format string is not a string literal // passing non-literal to vsnformat(). yes, user passing incorrect format strings can crash the code.
602+#pragma clang diagnostic ignored "-Wexit-time-destructors" // warning : declaration requires an exit-time destructor // exit-time destruction order is undefined. if MemFree() leads to users code that has been disabled before exit it might cause problems. ImGui coding style welcomes static/globals.
603+#pragma clang diagnostic ignored "-Wglobal-constructors" // warning : declaration requires a global destructor // similar to above, not sure what the exact difference it.
604+#pragma clang diagnostic ignored "-Wsign-conversion" // warning : implicit conversion changes signedness //
605+#pragma clang diagnostic ignored "-Wformat-pedantic" // warning : format specifies type 'void *' but the argument has type 'xxxx *' // unreasonable, would lead to casting every %p arg to void*. probably enabled by -pedantic.
606+#pragma clang diagnostic ignored "-Wint-to-void-pointer-cast" // warning : cast to 'void *' from smaller integer type 'int' //
607+#elif defined(__GNUC__)
608+#pragma GCC diagnostic ignored "-Wunused-function" // warning: 'xxxx' defined but not used
609+#pragma GCC diagnostic ignored "-Wint-to-pointer-cast" // warning: cast to pointer from integer of different size
610+#pragma GCC diagnostic ignored "-Wformat" // warning: format '%p' expects argument of type 'void*', but argument 6 has type 'ImGuiWindow*'
611+#pragma GCC diagnostic ignored "-Wdouble-promotion" // warning: implicit conversion from 'float' to 'double' when passing argument to function
612+#pragma GCC diagnostic ignored "-Wconversion" // warning: conversion to 'xxxx' from 'xxxx' may alter its value
613+#pragma GCC diagnostic ignored "-Wcast-qual" // warning: cast from type 'xxxx' to type 'xxxx' casts away qualifiers
614+#pragma GCC diagnostic ignored "-Wformat-nonliteral" // warning: format not a string literal, format string not checked
615+#endif
616+
617+//-------------------------------------------------------------------------
618+// Forward Declarations
619+//-------------------------------------------------------------------------
620+
621+static float GetDraggedColumnOffset(int column_index);
622+
623+static bool IsKeyPressedMap(ImGuiKey key, bool repeat = true);
624+
625+static ImFont* GetDefaultFont();
626+static void SetCurrentFont(ImFont* font);
627+static void SetCurrentWindow(ImGuiWindow* window);
628+static void SetWindowScrollY(ImGuiWindow* window, float new_scroll_y);
629+static void SetWindowPos(ImGuiWindow* window, const ImVec2& pos, ImGuiCond cond);
630+static void SetWindowSize(ImGuiWindow* window, const ImVec2& size, ImGuiCond cond);
631+static void SetWindowCollapsed(ImGuiWindow* window, bool collapsed, ImGuiCond cond);
632+static ImGuiWindow* FindHoveredWindow(ImVec2 pos);
633+static ImGuiWindow* CreateNewWindow(const char* name, ImVec2 size, ImGuiWindowFlags flags);
634+static void ClearSetNextWindowData();
635+static void CheckStacksSize(ImGuiWindow* window, bool write);
636+static ImVec2 CalcNextScrollFromScrollTargetAndClamp(ImGuiWindow* window);
637+
638+static void AddDrawListToRenderList(ImVector<ImDrawList*>& out_render_list, ImDrawList* draw_list);
639+static void AddWindowToRenderList(ImVector<ImDrawList*>& out_render_list, ImGuiWindow* window);
640+static void AddWindowToSortedBuffer(ImVector<ImGuiWindow*>& out_sorted_windows, ImGuiWindow* window);
641+
642+static ImGuiIniData* FindWindowSettings(const char* name);
643+static ImGuiIniData* AddWindowSettings(const char* name);
644+static void LoadIniSettingsFromDisk(const char* ini_filename);
645+static void SaveIniSettingsToDisk(const char* ini_filename);
646+static void MarkIniSettingsDirty(ImGuiWindow* window);
647+
648+static ImRect GetVisibleRect();
649+
650+static void CloseInactivePopups(ImGuiWindow* ref_window);
651+static void ClosePopupToLevel(int remaining);
652+static ImGuiWindow* GetFrontMostModalRootWindow();
653+static ImVec2 FindBestPopupWindowPos(const ImVec2& base_pos, const ImVec2& size, int* last_dir, const ImRect& rect_to_avoid);
654+
655+static bool InputTextFilterCharacter(unsigned int* p_char, ImGuiInputTextFlags flags, ImGuiTextEditCallback callback, void* user_data);
656+static int InputTextCalcTextLenAndLineCount(const char* text_begin, const char** out_text_end);
657+static ImVec2 InputTextCalcTextSizeW(const ImWchar* text_begin, const ImWchar* text_end, const ImWchar** remaining = NULL, ImVec2* out_offset = NULL, bool stop_on_new_line = false);
658+
659+static inline void DataTypeFormatString(ImGuiDataType data_type, void* data_ptr, const char* display_format, char* buf, int buf_size);
660+static inline void DataTypeFormatString(ImGuiDataType data_type, void* data_ptr, int decimal_precision, char* buf, int buf_size);
661+static void DataTypeApplyOp(ImGuiDataType data_type, int op, void* value1, const void* value2);
662+static bool DataTypeApplyOpFromText(const char* buf, const char* initial_value_buf, ImGuiDataType data_type, void* data_ptr, const char* scalar_format);
663+
664+namespace ImGui
665+{
666+static void FocusPreviousWindow();
667+}
668+
669+//-----------------------------------------------------------------------------
670+// Platform dependent default implementations
671+//-----------------------------------------------------------------------------
672+
673+static const char* GetClipboardTextFn_DefaultImpl(void* user_data);
674+static void SetClipboardTextFn_DefaultImpl(void* user_data, const char* text);
675+static void ImeSetInputScreenPosFn_DefaultImpl(int x, int y);
676+
677+//-----------------------------------------------------------------------------
678+// Context
679+//-----------------------------------------------------------------------------
680+
681+// Default font atlas storage.
682+// New contexts always point by default to this font atlas. It can be changed by reassigning the GetIO().Fonts variable.
683+static ImFontAtlas GImDefaultFontAtlas;
684+
685+// Default context storage + current context pointer.
686+// Implicitely used by all ImGui functions. Always assumed to be != NULL. Change to a different context by calling ImGui::SetCurrentContext()
687+// If you are hot-reloading this code in a DLL you will lose the static/global variables. Create your own context+font atlas instead of relying on those default (see FAQ entry "How can I preserve my ImGui context across reloading a DLL?").
688+// ImGui is currently not thread-safe because of this variable. If you want thread-safety to allow N threads to access N different contexts, you might work around it by:
689+// - Having multiple instances of the ImGui code compiled inside different namespace (easiest/safest, if you have a finite number of contexts)
690+// - or: Changing this variable to be TLS. You may #define GImGui in imconfig.h for further custom hackery. Future development aim to make this context pointer explicit to all calls. Also read https://github.com/ocornut/imgui/issues/586
691+#ifndef GImGui
692+static ImGuiContext GImDefaultContext;
693+ImGuiContext* GImGui = &GImDefaultContext;
694+#endif
695+
696+//-----------------------------------------------------------------------------
697+// User facing structures
698+//-----------------------------------------------------------------------------
699+
700+ImGuiStyle::ImGuiStyle()
701+{
702+ Alpha = 1.0f; // Global alpha applies to everything in ImGui
703+ WindowPadding = ImVec2(8,8); // Padding within a window
704+ WindowMinSize = ImVec2(32,32); // Minimum window size
705+ WindowRounding = 9.0f; // Radius of window corners rounding. Set to 0.0f to have rectangular windows
706+ WindowTitleAlign = ImVec2(0.0f,0.5f);// Alignment for title bar text
707+ ChildWindowRounding = 0.0f; // Radius of child window corners rounding. Set to 0.0f to have rectangular child windows
708+ FramePadding = ImVec2(4,3); // Padding within a framed rectangle (used by most widgets)
709+ FrameRounding = 0.0f; // Radius of frame corners rounding. Set to 0.0f to have rectangular frames (used by most widgets).
710+ ItemSpacing = ImVec2(8,4); // Horizontal and vertical spacing between widgets/lines
711+ ItemInnerSpacing = ImVec2(4,4); // Horizontal and vertical spacing between within elements of a composed widget (e.g. a slider and its label)
712+ TouchExtraPadding = ImVec2(0,0); // Expand reactive bounding box for touch-based system where touch position is not accurate enough. Unfortunately we don't sort widgets so priority on overlap will always be given to the first widget. So don't grow this too much!
713+ IndentSpacing = 21.0f; // Horizontal spacing when e.g. entering a tree node. Generally == (FontSize + FramePadding.x*2).
714+ ColumnsMinSpacing = 6.0f; // Minimum horizontal spacing between two columns
715+ ScrollbarSize = 16.0f; // Width of the vertical scrollbar, Height of the horizontal scrollbar
716+ ScrollbarRounding = 9.0f; // Radius of grab corners rounding for scrollbar
717+ GrabMinSize = 10.0f; // Minimum width/height of a grab box for slider/scrollbar
718+ GrabRounding = 0.0f; // Radius of grabs corners rounding. Set to 0.0f to have rectangular slider grabs.
719+ ButtonTextAlign = ImVec2(0.5f,0.5f);// Alignment of button text when button is larger than text.
720+ DisplayWindowPadding = ImVec2(22,22); // Window positions are clamped to be visible within the display area by at least this amount. Only covers regular windows.
721+ DisplaySafeAreaPadding = ImVec2(4,4); // If you cannot see the edge of your screen (e.g. on a TV) increase the safe area padding. Covers popups/tooltips as well regular windows.
722+ AntiAliasedLines = true; // Enable anti-aliasing on lines/borders. Disable if you are really short on CPU/GPU.
723+ AntiAliasedShapes = true; // Enable anti-aliasing on filled shapes (rounded rectangles, circles, etc.)
724+ CurveTessellationTol = 1.25f; // Tessellation tolerance. Decrease for highly tessellated curves (higher quality, more polygons), increase to reduce quality.
725+
726+ ImGui::StyleColorsClassic(this);
727+}
728+
729+void ImGui::StyleColorsClassic(ImGuiStyle* dst)
730+{
731+ ImGuiStyle* style = dst ? dst : &ImGui::GetStyle();
732+ ImVec4* colors = style->Colors;
733+
734+ colors[ImGuiCol_Text] = ImVec4(0.90f, 0.90f, 0.90f, 1.00f);
735+ colors[ImGuiCol_TextDisabled] = ImVec4(0.60f, 0.60f, 0.60f, 1.00f);
736+ colors[ImGuiCol_WindowBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.70f);
737+ colors[ImGuiCol_ChildWindowBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
738+ colors[ImGuiCol_PopupBg] = ImVec4(0.05f, 0.05f, 0.10f, 0.90f);
739+ colors[ImGuiCol_Border] = ImVec4(0.70f, 0.70f, 0.70f, 0.40f);
740+ colors[ImGuiCol_BorderShadow] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
741+ colors[ImGuiCol_FrameBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.30f); // Background of checkbox, radio button, plot, slider, text input
742+ colors[ImGuiCol_FrameBgHovered] = ImVec4(0.90f, 0.80f, 0.80f, 0.40f);
743+ colors[ImGuiCol_FrameBgActive] = ImVec4(0.90f, 0.65f, 0.65f, 0.45f);
744+ colors[ImGuiCol_TitleBg] = ImVec4(0.27f, 0.27f, 0.54f, 0.83f);
745+ colors[ImGuiCol_TitleBgCollapsed] = ImVec4(0.40f, 0.40f, 0.80f, 0.20f);
746+ colors[ImGuiCol_TitleBgActive] = ImVec4(0.32f, 0.32f, 0.63f, 0.87f);
747+ colors[ImGuiCol_MenuBarBg] = ImVec4(0.40f, 0.40f, 0.55f, 0.80f);
748+ colors[ImGuiCol_ScrollbarBg] = ImVec4(0.20f, 0.25f, 0.30f, 0.60f);
749+ colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.40f, 0.40f, 0.80f, 0.30f);
750+ colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.40f, 0.40f, 0.80f, 0.40f);
751+ colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.80f, 0.50f, 0.50f, 0.40f);
752+ colors[ImGuiCol_ComboBg] = ImVec4(0.20f, 0.20f, 0.20f, 0.99f);
753+ colors[ImGuiCol_CheckMark] = ImVec4(0.90f, 0.90f, 0.90f, 0.50f);
754+ colors[ImGuiCol_SliderGrab] = ImVec4(1.00f, 1.00f, 1.00f, 0.30f);
755+ colors[ImGuiCol_SliderGrabActive] = ImVec4(0.80f, 0.50f, 0.50f, 1.00f);
756+ colors[ImGuiCol_Button] = ImVec4(0.67f, 0.40f, 0.40f, 0.60f);
757+ colors[ImGuiCol_ButtonHovered] = ImVec4(0.67f, 0.40f, 0.40f, 1.00f);
758+ colors[ImGuiCol_ButtonActive] = ImVec4(0.80f, 0.50f, 0.50f, 1.00f);
759+ colors[ImGuiCol_Header] = ImVec4(0.40f, 0.40f, 0.90f, 0.45f);
760+ colors[ImGuiCol_HeaderHovered] = ImVec4(0.45f, 0.45f, 0.90f, 0.80f);
761+ colors[ImGuiCol_HeaderActive] = ImVec4(0.53f, 0.53f, 0.87f, 0.80f);
762+ colors[ImGuiCol_Separator] = ImVec4(0.50f, 0.50f, 0.50f, 1.00f);
763+ colors[ImGuiCol_SeparatorHovered] = ImVec4(0.60f, 0.60f, 0.70f, 1.00f);
764+ colors[ImGuiCol_SeparatorActive] = ImVec4(0.70f, 0.70f, 0.90f, 1.00f);
765+ colors[ImGuiCol_ResizeGrip] = ImVec4(1.00f, 1.00f, 1.00f, 0.30f);
766+ colors[ImGuiCol_ResizeGripHovered] = ImVec4(1.00f, 1.00f, 1.00f, 0.60f);
767+ colors[ImGuiCol_ResizeGripActive] = ImVec4(1.00f, 1.00f, 1.00f, 0.90f);
768+ colors[ImGuiCol_CloseButton] = ImVec4(0.50f, 0.50f, 0.90f, 0.50f);
769+ colors[ImGuiCol_CloseButtonHovered] = ImVec4(0.70f, 0.70f, 0.90f, 0.60f);
770+ colors[ImGuiCol_CloseButtonActive] = ImVec4(0.70f, 0.70f, 0.70f, 1.00f);
771+ colors[ImGuiCol_PlotLines] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f);
772+ colors[ImGuiCol_PlotLinesHovered] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f);
773+ colors[ImGuiCol_PlotHistogram] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f);
774+ colors[ImGuiCol_PlotHistogramHovered] = ImVec4(1.00f, 0.60f, 0.00f, 1.00f);
775+ colors[ImGuiCol_TextSelectedBg] = ImVec4(0.00f, 0.00f, 1.00f, 0.35f);
776+ colors[ImGuiCol_ModalWindowDarkening] = ImVec4(0.20f, 0.20f, 0.20f, 0.35f);
777+}
778+
779+// To scale your entire UI (e.g. if you want your app to use High DPI or generally be DPI aware) you may use this helper function. Scaling the fonts is done separately and is up to you.
780+// Tips: if you need to change your scale multiple times, prefer calling this on a freshly initialized ImGuiStyle structure rather than scaling multiple times (because floating point multiplications are lossy).
781+void ImGuiStyle::ScaleAllSizes(float scale_factor)
782+{
783+ WindowPadding *= scale_factor;
784+ WindowMinSize *= scale_factor;
785+ WindowRounding *= scale_factor;
786+ ChildWindowRounding *= scale_factor;
787+ FramePadding *= scale_factor;
788+ FrameRounding *= scale_factor;
789+ ItemSpacing *= scale_factor;
790+ ItemInnerSpacing *= scale_factor;
791+ TouchExtraPadding *= scale_factor;
792+ IndentSpacing *= scale_factor;
793+ ColumnsMinSpacing *= scale_factor;