texlive[61658] Build/source/texk/web2c/hitexdir/hintview: adding

commits+mruckert at tug.org commits+mruckert at tug.org
Wed Jan 19 14:28:43 CET 2022


Revision: 61658
          http://tug.org/svn/texlive?view=revision&revision=61658
Author:   mruckert
Date:     2022-01-19 14:28:43 +0100 (Wed, 19 Jan 2022)
Log Message:
-----------
adding files to build the Linux HINT viewer (independent of the TL build)

Added Paths:
-----------
    trunk/Build/source/texk/web2c/hitexdir/hintview/
    trunk/Build/source/texk/web2c/hitexdir/hintview/man/
    trunk/Build/source/texk/web2c/hitexdir/hintview/man/hintview.1
    trunk/Build/source/texk/web2c/hitexdir/hintview/src/
    trunk/Build/source/texk/web2c/hitexdir/hintview/src/Makefile
    trunk/Build/source/texk/web2c/hitexdir/hintview/src/basetypes.h
    trunk/Build/source/texk/web2c/hitexdir/hintview/src/error.h
    trunk/Build/source/texk/web2c/hitexdir/hintview/src/format.h
    trunk/Build/source/texk/web2c/hitexdir/hintview/src/get.c
    trunk/Build/source/texk/web2c/hitexdir/hintview/src/get.h
    trunk/Build/source/texk/web2c/hitexdir/hintview/src/hfonts.c
    trunk/Build/source/texk/web2c/hitexdir/hintview/src/hfonts.h
    trunk/Build/source/texk/web2c/hitexdir/hintview/src/hint.c
    trunk/Build/source/texk/web2c/hitexdir/hintview/src/hint.h
    trunk/Build/source/texk/web2c/hitexdir/hintview/src/hrender.c
    trunk/Build/source/texk/web2c/hitexdir/hintview/src/hrender.h
    trunk/Build/source/texk/web2c/hitexdir/hintview/src/htex.c
    trunk/Build/source/texk/web2c/hitexdir/hintview/src/htex.h
    trunk/Build/source/texk/web2c/hitexdir/hintview/src/main.c
    trunk/Build/source/texk/web2c/hitexdir/hintview/src/main.h
    trunk/Build/source/texk/web2c/hitexdir/hintview/src/renderOGL.c
    trunk/Build/source/texk/web2c/hitexdir/hintview/src/rendernative.h
    trunk/Build/source/texk/web2c/hitexdir/hintview/src/stb_image.h
    trunk/Build/source/texk/web2c/hitexdir/hintview/src/tables.c

Added: trunk/Build/source/texk/web2c/hitexdir/hintview/man/hintview.1
===================================================================
--- trunk/Build/source/texk/web2c/hitexdir/hintview/man/hintview.1	                        (rev 0)
+++ trunk/Build/source/texk/web2c/hitexdir/hintview/man/hintview.1	2022-01-19 13:28:43 UTC (rev 61658)
@@ -0,0 +1,228 @@
+.TH HINTVIEW1 "11 November 2021" "Version 1.0"
+.\"=====================================================================
+.if n .ds MF Metafont
+.if t .ds MF Metafont
+.if t .ds TX \fRT\\h'-0.1667m'\\v'0.20v'E\\v'-0.20v'\\h'-0.125m'X\fP
+.if n .ds TX TeX
+.ie t .ds OX \fIT\v'+0.25m'E\v'-0.25m'X\fP
+.el .ds OX TeX
+.\" BX definition must follow TX so BX can use TX
+.if t .ds BX \fRB\s-2IB\s0\fP\*(TX
+.if n .ds BX BibTeX
+.\" LX definition must follow TX so LX can use TX
+.if t .ds LX \fRL\\h'-0.36m'\\v'-0.15v'\s-2A\s0\\h'-0.15m'\\v'0.15v'\fP\*(TX
+.if n .ds LX LaTeX
+.if t .ds AX \fRA\\h'-0.1667m'\\v'0.20v'M\\v'-0.20v'\\h'-0.125m'S\fP\*(TX
+.if n .ds AX AmSTeX
+.if t .ds AY \fRA\\h'-0.1667m'\\v'0.20v'M\\v'-0.20v'\\h'-0.125m'S\fP\*(LX
+.if n .ds AY AmSLaTeX
+.if n .ds WB Web
+.if t .ds WB W\s-2EB\s0
+.\"=====================================================================
+.SH NAME
+hintview\- displaying HINT files
+.SH SYNOPSIS
+.B hintview
+.RI [ options ]
+.RI [ file ]
+.\"=====================================================================
+.SH DESCRIPTION
+.B Hintview
+displays a binary
+.B HINT
+file, usually with the
+.BR .hnt
+extension.
+.PP
+The binary
+.B HINT
+file format is designed for on-screen reading of documents.
+Using hintview to display a
+.B HINT
+file, its content will dynamically
+adapt to the available display area. For complete information on the
+.B HINT
+file format and programs to view
+.B HINT
+files, see
+.BR  https://hint.userweb.mwn.de .
+.\"=====================================================================
+.SH OPTIONS
+This version of
+.B hintview
+understands the following command line options:
+.TP
+.B -a
+Start in autoreload mode. If in autoreload mode, the viewer will check 
+the modification time of the displayed
+.B HINT
+file each time the cursor enters the window.
+If the modification time has changed, the file is reloaded.
+The viewer attempts to position the new file at about the same position
+as the old file. This attempt might fail if large scale changes have
+been made to the file. 
+.sp
+See also the 
+.B Ctrl-A
+and the
+.B Ctrl-R
+key.
+.TP
+.B -h
+Open the document on the "home" page. The home page is a location
+specified by the document author as a good starting point for reading
+the document.
+.sp
+See also the 
+.B Ctrl-H 
+key.
+.TP
+.B --help
+Print help message and exit.
+.TP
+.B -n
+Start the viewer in "night" mode. In this mode the viewer will display
+the document using a dark background and light foreground color to reduce
+eye strain in a surrounding with dim lighting.
+.sp
+See also the 
+.B Ctrl-N
+key.
+.TP
+.BI -o
+Show a clickable outline of the content. NOT YET IMPLEMENTED.
+.sp
+See also the 
+.B Ctrl-O
+key.
+.TP
+.B --version
+Print version information and exit.
+.TP
+.B -z
+Zoom to 100%. The
+.B HINT
+viewer can display a document using a given
+zoom factor to make characters appear larger or smaller to either
+improve readability or increase the amount of text that can be displayed
+in a given window. This option resets the zoom factor so that a 10pt
+font will appear on screen at the same size as it would appear in a 
+printed book.
+.sp
+See also the 
+.B Ctrl-Z
+key.
+.\"=====================================================================
+.SH KEYSTROKES
+.B Hintview
+recognizes the following keystrokes when typed in its window.
+.TP
+.B Ctrl-A
+Toggle autoreload mode. See also the
+.B -a
+option and the
+.B Ctrl-R
+key.
+.TP
+.B Ctrl-F
+Open the
+.B Find
+dialog. NOT YET IMPLEMENTED.
+.TP
+.BR Home , \ Ctrl-H
+Move to the "home" page. The home page is a location specified by the 
+document author as a good starting point for reading the document.
+.TP
+.B Ctrl-N
+Toggle between night and day mode. See also the
+.B -n
+option.
+.TP
+.B Ctrl-O
+Show a clickable outline of the content. NOT YET IMPLEMENTED.
+.TP
+.B Page-Down
+Move to the next page.
+.TP
+.B Page-Up
+Move to the previous page.
+.TP
+.B Ctrl-R
+Reload the content. The file is reloaded and the viewer
+attempts to position the new file at about the same position
+as the old file. This attempt might fail if large scale changes have
+been made to the file. See also the
+.B Ctrl-A
+key and the
+.B -a
+option.
+.TP
+.B Ctrl-Z
+Zoom to 100%. See also the
+.B -z
+option.
+.\"=====================================================================
+.SH MOUSE ACTIONS
+The following actions are executed using the 
+.BR left\ mouse\ button .
+.TP
+.B Click
+If the mouse is positioned on a link, move to the link target. Links are
+displayed in blue color.
+.TP
+.B Drag
+Dragging from the top-left to the bottom-right increases the zoom factor.
+Dragging in the opposite direction decreases the zoom factor. See also the
+.B Ctrl-Z
+key and the
+.B -z
+option.
+.\"=====================================================================
+.SH NOTES
+This is a simple, bare-bone implementation of a program to render 
+.B HINT
+files. Other programs to display 
+.B HINT
+files are available on the 
+.B HINT
+project home page at 
+.B https://hint.userweb.mwn.de/
+where you find viewers for the Windows and Android operating systems.
+.sp
+Currently the best way to produce
+.B HINT
+files is the use of 
+.BR hitex ,
+a version of \*(TX that produces 
+.B HINT
+files as its output. The 
+.B HINT
+file format is described in 
+.IR "HINT: The file format"
+which is available as a book or in electronic form from the 
+.B HINT
+project home page. The 
+.B HINT
+file format is independent of \*(TX and allows the implementation
+of generators for all kind of word-processors. The 
+.B hintview
+program however uses parts of Donald E. Knuth's implementation
+of \*(TX, notably its line breaking routine, to produce good
+quality rendering of documents.
+.\"=====================================================================
+.SH AVAILABILITY
+.B hintview
+is tested on the Linux platform but
+should compile on a large variety of machine architectures
+and operating systems.
+It is part of the \*(TX Live distribution.
+.PP
+.\"=====================================================================
+.SH "SEE ALSO"
+.BR hitex (1),
+.BR histretch (1),
+.BR hishrink (1).
+.\"=====================================================================
+.SH AUTHORS
+Martin Ruckert
+.\" vim: syntax=nroff

Added: trunk/Build/source/texk/web2c/hitexdir/hintview/src/Makefile
===================================================================
--- trunk/Build/source/texk/web2c/hitexdir/hintview/src/Makefile	                        (rev 0)
+++ trunk/Build/source/texk/web2c/hitexdir/hintview/src/Makefile	2022-01-19 13:28:43 UTC (rev 61658)
@@ -0,0 +1,77 @@
+
+CC = gcc
+CFLAGS = -g -Og -DDEBUG -Wall
+LDFLAGS = -g -Og
+#GL_DEFINES = -DGLEW_STATIC -DTW_NO_DIRECT3D -DTW_NO_LIB_PRAGMA -DTW_STATIC -D_CRT_SECURE_NO_WARNINGS
+
+FT_INCLUDES = -I/usr/include/freetype2
+GL_INCLUDES = $(FT_INCLUDES)
+
+
+HFILES =     hint.h htex.h format.h get.h basetypes.h error.h \
+	     hrender.h rendernative.h hfonts.h
+
+WFILES =     format.w hint.w htex.ch btex.w
+
+HINT_FILES = get.c hint.c tables.c htex.c hrender.c hfonts.c \
+	     $(HFILES) $(WFILES)
+
+
+OBJ=main.o  renderOGL.o get.o hint.o tables.o htex.o hrender.o hfonts.o
+
+ifeq (Msys,$(shell uname -o))
+LIBS= ../external/glfw-3.1.2/msys.build/src/libglfw3.a ../external/libglew.a  -lfreetype \
+	       -lm -lz
+#	 -ldl -lm -lX11 -lpthread -lXrandr -lXinerama -lXi -lXcursor -lGL -lz
+else
+LIBS= -l:libglfw3.a -l:libGLEW.a -ldl -lfreetype -lX11 -lXrandr -lXinerama -lXi -lXcursor -lGL -lz -lpthread -lm 
+endif
+
+all: hintview
+
+.SUFFIXES:
+
+
+hint.o: hint.c
+	$(CC) $(CFLAGS) -Wno-unused-but-set-variable -o $@ -c $<
+
+htex.o: htex.c
+	$(CC) $(CFLAGS) -Wno-parentheses -Wno-unused-but-set-variable -Wno-maybe-uninitialized -o $@ -c $<
+
+renderOGL.o: renderOGL.c
+	$(CC) $(FT_INCLUDES) $(CFLAGS) -o $@ -c $<
+
+hfonts.o: hfonts.c
+	$(CC) $(CFLAGS) $(FT_INCLUDES) -o $@ -c $<
+
+%.o: %.c
+	$(CC) $(CFLAGS) -o $@ -c $<
+
+hintview: $(OBJ)
+	$(CC) $(LDFLAGS)  $(OBJ) $(LIBS) -o $@ 
+
+SRC= $(OBJ:.o=.c) $(HFILES) main.h stb_image.h Makefile
+DIST_SRC = $(SRC:%=src/%)
+DIST_MAN = man/hintview.1
+
+hintview.tgz: 
+	tar -c -C .. --transform 's,^,hintview/,' -z -f $@ $(DIST_SRC) $(DIST_MAN) 
+
+BINDIR=/usr/local/bin
+MANDIR=/usr/local/man
+
+install: hintview
+	strip hintview
+	install -t $(BINDIR) --mode=755 hintview
+	install -t $(MANDIR)/man1 --mode=644 ../man/hintview.1
+
+
+.PHONY: www
+www: hintview hintview.tgz
+	cp hintview hintview.tgz ../man/hintview.1 ../../www/linux/
+
+clean:
+	rm -f *.o *~ *.dvi *.log *.aux
+	rm -f hintview hintview.tgz
+	$(MAKE) -C ../../hint viewlinux || true
+

Added: trunk/Build/source/texk/web2c/hitexdir/hintview/src/basetypes.h
===================================================================
--- trunk/Build/source/texk/web2c/hitexdir/hintview/src/basetypes.h	                        (rev 0)
+++ trunk/Build/source/texk/web2c/hitexdir/hintview/src/basetypes.h	2022-01-19 13:28:43 UTC (rev 61658)
@@ -0,0 +1,45 @@
+	/*503:*/
+	#line 9953 "format.w"
+
+#ifndef __BASETYPES_H__
+#define __BASETYPES_H__
+#include <stdlib.h>
+#include <stdio.h>
+#ifndef _STDLIB_H
+#define _STDLIB_H
+#endif
+#ifdef  _MSC_VER
+#include <windows.h>
+#define uint8_t UINT8
+#define uint16_t UINT16
+#define uint32_t UINT32
+#define uint64_t UINT64
+#define int8_t INT8
+#define int16_t INT16
+#define int32_t INT32
+#define bool BOOL
+#define true (0==0)
+#define false (!true)
+#define __SIZEOF_FLOAT__ 4
+#define __SIZEOF_DOUBLE__ 8
+#define PRIx64 "I64x"
+#pragma  warning( disable : 4244 4996 4127)
+#else
+#include <stdint.h>
+#include <stdbool.h>
+#include <inttypes.h>
+#include <unistd.h>
+#ifdef WIN32
+#include <io.h>
+#endif
+#endif
+typedef float float32_t;
+typedef double float64_t;
+#if __SIZEOF_FLOAT__!=4
+#error  float32 type must have size 4
+#endif
+#if __SIZEOF_DOUBLE__!=8
+#error  float64 type must have size 8
+#endif
+#endif
+	/*:503*/

Added: trunk/Build/source/texk/web2c/hitexdir/hintview/src/error.h
===================================================================
--- trunk/Build/source/texk/web2c/hitexdir/hintview/src/error.h	                        (rev 0)
+++ trunk/Build/source/texk/web2c/hitexdir/hintview/src/error.h	2022-01-19 13:28:43 UTC (rev 61658)
@@ -0,0 +1,59 @@
+/*357:*/
+#line 7147 "hint.w"
+
+#ifndef _ERROR_H
+#define _ERROR_H
+#include <stdlib.h> 
+#include <stdio.h> 
+#include <setjmp.h> 
+#define MAX_HERROR 1024
+extern char herror_string[MAX_HERROR];
+extern FILE*hlog;
+extern void hint_end(void);
+extern jmp_buf error_exit;
+
+#ifdef _MSC_VER 
+#define snprintf(S,N,F,...) _snprintf(S,N,F,__VA_ARGS__)
+#ifndef _CONSOLE
+#pragma warning(disable : 4996)
+extern void hmessage(char*title,char*format,...);
+#define MESSAGE(...)  hmessage("HINT",__VA_ARGS__)
+
+extern int herror(char*title,char*msg);
+#define ERROR_MESSAGE  herror("HINT ERROR",herror_string)
+#endif
+#endif
+
+#ifdef __ANDROID__ 
+#include <android/log.h> 
+
+#define LOG(...)      __android_log_print(ANDROID_LOG_DEBUG,__FILE__,__VA_ARGS__)
+#define MESSAGE(...)  __android_log_print(ANDROID_LOG_INFO,__FILE__, __VA_ARGS__)
+#define ERROR_MESSAGE __android_log_print(ANDROID_LOG_ERROR,__FILE__,"ERROR: %s\n", herror_string)
+
+#endif
+
+#ifndef LOG
+#define LOG(...) (fprintf(hlog,__VA_ARGS__),fflush(hlog))
+#endif
+
+#ifndef MESSAGE
+#define MESSAGE(...)  (fprintf(stderr,__VA_ARGS__),fflush(stderr))
+#endif
+
+#ifndef ERROR_MESSAGE
+#define ERROR_MESSAGE        fprintf(stderr,"ERROR: %s\n",herror_string)
+#endif
+
+#ifndef QUIT
+#define QUIT(...)    (snprintf(herror_string,MAX_HERROR-1,__VA_ARGS__),\
+                     ERROR_MESSAGE,hint_end(),longjmp(error_exit,1))
+#endif
+
+
+#ifndef HINT_TRY
+#define HINT_TRY if ((herror_string[0]= 0,setjmp(error_exit)==0))
+#endif
+
+#endif
+/*:357*/

Added: trunk/Build/source/texk/web2c/hitexdir/hintview/src/format.h
===================================================================
--- trunk/Build/source/texk/web2c/hitexdir/hintview/src/format.h	                        (rev 0)
+++ trunk/Build/source/texk/web2c/hitexdir/hintview/src/format.h	2022-01-19 13:28:43 UTC (rev 61658)
@@ -0,0 +1,357 @@
+	/*504:*/
+	#line 10003 "format.w"
+
+#ifndef _HFORMAT_H_
+#define _HFORMAT_H_
+	/*349:*/
+	#line 7407 "format.w"
+
+#define REF_RNG(K,N) if ((int)(N)>max_ref[K]) QUIT("Reference %d to %s out of range [0 - %d]",\
+  (N),definition_name[K],max_ref[K])
+	/*:349*/	/*350:*/
+	#line 7421 "format.w"
+
+#define MAX_REF(K) ((K)==label_kind?0xFFFF:0xFF)
+	/*:350*/	/*423:*/
+	#line 8876 "format.w"
+
+#ifdef WIN32
+#define SIZE_F "0x%x"
+#else
+#define SIZE_F "0x%zx"
+#endif
+#ifdef DEBUG
+#define DBG(FLAGS,...) ((debugflags & (FLAGS))?LOG(__VA_ARGS__):0)
+#else
+#define DBG(FLAGS,...) 0
+#endif
+#define DBGTAG(A,P) DBG(DBGTAGS,"tag [%s,%d] at " SIZE_F "\n",NAME(A),INFO(A),(P)-hstart)
+
+#define RNG(S,N,A,Z) \
+  if ((int)(N)<(int)(A)||(int)(N)>(int)(Z)) QUIT(S " %d out of range [%d - %d]",N,A,Z)
+
+#define TAGERR(A) QUIT("Unknown tag [%s,%d] at " SIZE_F "\n",NAME(A),INFO(A),hpos-hstart)
+	/*:423*/
+	#line 10006 "format.w"
+
+	/*410:*/
+	#line 8614 "format.w"
+
+#define DBGNONE     0x0
+#define DBGBASIC    0x1
+#define DBGTAGS     0x2
+#define DBGNODE     0x4
+#define DBGDEF      0x8
+#define DBGDIR      0x10
+#define DBGRANGE    0x20
+#define DBGFLOAT    0x40
+#define DBGCOMPRESS 0x80
+#define DBGBUFFER   0X100
+#define DBGFLEX     0x200
+#define DBGBISON    0x400
+#define DBGTEX      0x800
+#define DBGPAGE     0x1000
+#define DBGFONT     0x2000
+#define DBGRENDER   0x4000
+#define DBGLABEL    0x8000
+	/*:410*/
+	#line 10007 "format.w"
+
+	/*12:*/
+	#line 635 "format.w"
+
+#define KIND(T)      (((T)>>3)&0x1F)
+#define NAME(T)      content_name[KIND(T)]
+#define INFO(T)      ((T)&0x7)
+#define TAG(K,I)     (((K)<<3)|(I))
+	/*:12*/	/*77:*/
+	#line 1625 "format.w"
+
+#define ROUND(X)     ((int)((X)>=0.0?floor((X)+0.5):ceil((X)-0.5)))
+	/*:77*/	/*112:*/
+	#line 2126 "format.w"
+
+#define RUNNING_DIMEN 0xC0000000
+	/*:112*/	/*131:*/
+	#line 2468 "format.w"
+
+#define ZERO_GLUE(G) ((G).w.w==0  && (G).w.h==0.0  && (G).w.v==0.0  && (G).p.f==0.0 && (G).m.f==0.0)
+	/*:131*/	/*236:*/
+	#line 4700 "format.w"
+
+#define HINT_NO_POS 0xFFFFFFFF
+	/*:236*/	/*243:*/
+	#line 4898 "format.w"
+
+#define LABEL_UNDEF 0
+#define LABEL_TOP 1
+#define LABEL_BOT 2
+#define LABEL_MID 3
+	/*:243*/	/*294:*/
+	#line 6079 "format.w"
+
+#define ALLOCATE(R,S,T) ((R)= (T *)calloc((S),sizeof(T)),\
+        (((R)==NULL)?QUIT("Out of memory for " #R):0))
+#define REALLOCATE(R,S,T) ((R)= (T *)realloc((R),(S)*sizeof(T)),\
+        (((R)==NULL)?QUIT("Out of memory for " #R):0))
+	/*:294*/	/*302:*/
+	#line 6244 "format.w"
+
+#define HINT_VERSION 1
+#define HINT_SUB_VERSION 3
+#define MAX_BANNER 256
+	/*:302*/	/*315:*/
+	#line 6447 "format.w"
+
+#define MAX_TAG_DISTANCE 32
+	/*:315*/
+	#line 10008 "format.w"
+
+	/*6:*/
+	#line 487 "format.w"
+
+#define DEF_KIND(C,D,N) C##_kind= N
+typedef enum{	/*9:*/
+	#line 556 "format.w"
+
+DEF_KIND(text,text,0),
+DEF_KIND(list,list,1),
+DEF_KIND(param,param,2),
+DEF_KIND(xdimen,xdimen,3),
+DEF_KIND(adjust,adjust,4),
+DEF_KIND(glyph,font,5),
+DEF_KIND(kern,dimen,6),
+DEF_KIND(glue,glue,7),
+DEF_KIND(ligature,ligature,8),
+DEF_KIND(disc,disc,9),
+DEF_KIND(language,language,10),
+DEF_KIND(rule,rule,11),
+DEF_KIND(image,image,12),
+DEF_KIND(leaders,leaders,13),
+DEF_KIND(baseline,baseline,14),
+DEF_KIND(hbox,hbox,15),
+DEF_KIND(vbox,vbox,16),
+DEF_KIND(par,par,17),
+DEF_KIND(math,math,18),
+DEF_KIND(table,table,19),
+DEF_KIND(item,item,20),
+DEF_KIND(hset,hset,21),
+DEF_KIND(vset,vset,22),
+DEF_KIND(hpack,hpack,23),
+DEF_KIND(vpack,vpack,24),
+DEF_KIND(stream,stream,25),
+DEF_KIND(page,page,26),
+DEF_KIND(range,range,27),
+DEF_KIND(link,label,28),
+DEF_KIND(undefined2,undefined2,29),
+DEF_KIND(undefined3,undefined3,30),
+DEF_KIND(penalty,int,31)
+
+	/*:9*/
+	#line 489 "format.w"
+,	/*10:*/
+	#line 595 "format.w"
+
+font_kind= glyph_kind,int_kind= penalty_kind,dimen_kind= kern_kind,label_kind= link_kind,outline_kind= link_kind
+	/*:10*/
+	#line 489 "format.w"
+}kind_t;
+#undef DEF_KIND
+	/*:6*/	/*11:*/
+	#line 621 "format.w"
+
+typedef enum{b000= 0,b001= 1,b010= 2,b011= 3,b100= 4,b101= 5,b110= 6,b111= 7}info_t;
+	/*:11*/	/*56:*/
+	#line 1294 "format.w"
+
+
+#define FLT_M_BITS 23
+#define FLT_E_BITS 8
+#define FLT_EXCESS 127
+
+#define DBL_M_BITS 52
+#define DBL_E_BITS 11
+#define DBL_EXCESS 1023
+
+	/*:56*/	/*76:*/
+	#line 1620 "format.w"
+
+typedef int32_t scaled_t;
+#define ONE ((scaled_t)(1<<16))
+	/*:76*/	/*81:*/
+	#line 1676 "format.w"
+
+typedef scaled_t dimen_t;
+#define MAX_DIMEN ((dimen_t)(0x3FFFFFFF))
+	/*:81*/	/*86:*/
+	#line 1732 "format.w"
+
+typedef struct{
+dimen_t w;float32_t h,v;
+}xdimen_t;
+	/*:86*/	/*95:*/
+	#line 1877 "format.w"
+
+typedef enum{normal_o= 0,fil_o= 1,fill_o= 2,filll_o= 3}order_t;
+typedef struct{float64_t f;order_t o;}stretch_t;
+typedef union{float32_t f;uint32_t u;}stch_t;
+	/*:95*/	/*130:*/
+	#line 2458 "format.w"
+
+typedef struct{
+xdimen_t w;
+stretch_t p,m;
+}glue_t;
+	/*:130*/	/*180:*/
+	#line 3881 "format.w"
+
+typedef struct{
+glue_t bs,ls;
+dimen_t lsl;
+}baseline_t;
+	/*:180*/	/*242:*/
+	#line 4883 "format.w"
+
+typedef struct
+{uint32_t pos;
+uint8_t where;
+bool used;
+int next;
+uint32_t pos0;uint8_t f;
+}label_t;
+	/*:242*/	/*373:*/
+	#line 7941 "format.w"
+
+#define MAX_FONT_PARAMS 11
+	/*:373*/
+	#line 10009 "format.w"
+
+	/*385:*/
+	#line 8176 "format.w"
+
+typedef enum{
+zero_int_no= 0,
+pretolerance_no= 1,
+tolerance_no= 2,
+line_penalty_no= 3,
+hyphen_penalty_no= 4,
+ex_hyphen_penalty_no= 5,
+club_penalty_no= 6,
+widow_penalty_no= 7,
+display_widow_penalty_no= 8,
+broken_penalty_no= 9,
+pre_display_penalty_no= 10,
+post_display_penalty_no= 11,
+inter_line_penalty_no= 12,
+double_hyphen_demerits_no= 13,
+final_hyphen_demerits_no= 14,
+adj_demerits_no= 15,
+looseness_no= 16,
+time_no= 17,
+day_no= 18,
+month_no= 19,
+year_no= 20,
+hang_after_no= 21,
+floating_penalty_no= 22
+}int_no_t;
+#define MAX_INT_DEFAULT floating_penalty_no
+	/*:385*/	/*387:*/
+	#line 8249 "format.w"
+
+typedef enum{
+zero_dimen_no= 0,
+hsize_dimen_no= 1,
+vsize_dimen_no= 2,
+line_skip_limit_no= 3,
+max_depth_no= 4,
+split_max_depth_no= 5,
+hang_indent_no= 6,
+emergency_stretch_no= 7,
+quad_no= 8,
+math_quad_no= 9
+}dimen_no_t;
+#define MAX_DIMEN_DEFAULT math_quad_no
+	/*:387*/	/*389:*/
+	#line 8294 "format.w"
+
+typedef enum{
+zero_xdimen_no= 0,
+hsize_xdimen_no= 1,
+vsize_xdimen_no= 2
+}xdimen_no_t;
+#define MAX_XDIMEN_DEFAULT vsize_xdimen_no
+	/*:389*/	/*391:*/
+	#line 8318 "format.w"
+
+typedef enum{
+zero_skip_no= 0,
+fil_skip_no= 1,
+fill_skip_no= 2,
+line_skip_no= 3,
+baseline_skip_no= 4,
+above_display_skip_no= 5,
+below_display_skip_no= 6,
+above_display_short_skip_no= 7,
+below_display_short_skip_no= 8,
+left_skip_no= 9,
+right_skip_no= 10,
+top_skip_no= 11,
+split_top_skip_no= 12,
+tab_skip_no= 13,
+par_fill_skip_no= 14
+}glue_no_t;
+#define MAX_GLUE_DEFAULT par_fill_skip_no
+	/*:391*/	/*393:*/
+	#line 8404 "format.w"
+
+typedef enum{
+zero_baseline_no= 0
+}baseline_no_t;
+#define MAX_BASELINE_DEFAULT zero_baseline_no
+	/*:393*/	/*395:*/
+	#line 8429 "format.w"
+
+typedef enum{
+zero_label_no= 0
+}label_no_t;
+#define MAX_LABEL_DEFAULT zero_label_no
+	/*:395*/	/*397:*/
+	#line 8443 "format.w"
+
+typedef enum{
+zero_stream_no= 0
+}stream_no_t;
+#define MAX_STREAM_DEFAULT zero_stream_no
+	/*:397*/	/*399:*/
+	#line 8459 "format.w"
+
+typedef enum{
+zero_page_no= 0
+}page_no_t;
+#define MAX_PAGE_DEFAULT zero_page_no
+	/*:399*/	/*401:*/
+	#line 8476 "format.w"
+
+typedef enum{
+zero_range_no= 0
+}range_no_t;
+#define MAX_RANGE_DEFAULT zero_range_no
+	/*:401*/
+	#line 10010 "format.w"
+
+
+extern const char*content_name[32];
+extern const char*definition_name[32];
+extern unsigned int debugflags;
+extern FILE*hlog;
+extern int max_fixed[32],max_default[32],max_ref[32],max_outline;
+extern int32_t int_defaults[MAX_INT_DEFAULT+1];
+extern dimen_t dimen_defaults[MAX_DIMEN_DEFAULT+1];
+extern xdimen_t xdimen_defaults[MAX_XDIMEN_DEFAULT+1];
+extern glue_t glue_defaults[MAX_GLUE_DEFAULT+1];
+extern baseline_t baseline_defaults[MAX_BASELINE_DEFAULT+1];
+extern label_t label_defaults[MAX_LABEL_DEFAULT+1];
+extern signed char hnode_size[0x100];
+
+#endif
+	/*:504*/

Added: trunk/Build/source/texk/web2c/hitexdir/hintview/src/get.c
===================================================================
--- trunk/Build/source/texk/web2c/hitexdir/hintview/src/get.c	                        (rev 0)
+++ trunk/Build/source/texk/web2c/hitexdir/hintview/src/get.c	2022-01-19 13:28:43 UTC (rev 61658)
@@ -0,0 +1,624 @@
+	/*508:*/
+	#line 10151 "format.w"
+
+#include "basetypes.h"
+#include <string.h>
+#include <math.h>
+#include <zlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include "error.h"
+#include "format.h"
+#include "get.h"
+
+	/*244:*/
+	#line 4905 "format.w"
+
+label_t*labels;
+int first_label= -1;
+	/*:244*/	/*292:*/
+	#line 6068 "format.w"
+
+range_pos_t*range_pos;
+int next_range= 1,max_range;
+int*page_on;
+	/*:292*/	/*303:*/
+	#line 6254 "format.w"
+
+char hbanner[MAX_BANNER+1];
+	/*:303*/	/*310:*/
+	#line 6392 "format.w"
+
+uint8_t*hpos= NULL,*hstart= NULL,*hend= NULL,*hpos0= NULL;
+	/*:310*/	/*316:*/
+	#line 6473 "format.w"
+
+char*hin_name= NULL;
+uint64_t hin_size= 0;
+uint8_t*hin_addr= NULL;
+uint64_t hin_time= 0;
+	/*:316*/	/*372:*/
+	#line 7937 "format.w"
+
+char**hfont_name;
+	/*:372*/	/*411:*/
+	#line 8637 "format.w"
+
+unsigned int debugflags= DBGNONE;
+int option_utf8= false;
+int option_hex= false;
+int option_force= false;
+int option_global= false;
+int option_aux= false;
+int option_compress= false;
+char*stem_name= NULL;
+int stem_length= 0;
+	/*:411*/	/*414:*/
+	#line 8771 "format.w"
+
+FILE*hin= NULL,*hout= NULL,*hlog= NULL;
+	/*:414*/
+	#line 10164 "format.w"
+
+
+	/*317:*/
+	#line 6480 "format.w"
+
+#ifndef USE_MMAP
+void hget_unmap(void)
+{if(hin_addr!=NULL)free(hin_addr);
+hin_addr= NULL;
+hin_size= 0;
+}
+bool hget_map(void)
+{FILE*f;
+struct stat st;
+size_t s,t;
+uint64_t u;
+f= fopen(hin_name,"rb");
+if(f==NULL)
+{MESSAGE("Unable to open file: %s\n",hin_name);return false;}
+if(stat(hin_name,&st)<0)
+{MESSAGE("Unable to obtain file size: %s\n",hin_name);
+fclose(f);
+return false;
+}
+if(st.st_size==0)
+{MESSAGE("File %s is empty\n",hin_name);
+fclose(f);
+return false;
+}
+u= st.st_size;
+if(hin_addr!=NULL)hget_unmap();
+hin_addr= malloc(u);
+if(hin_addr==NULL)
+{MESSAGE("Unable to allocate 0x%"PRIx64" byte for File %s\n",u,hin_name);
+fclose(f);
+return 0;
+}
+t= 0;
+do{
+s= fread(hin_addr+t,1,u,f);
+if(s<=0)
+{MESSAGE("Unable to read file %s\n",hin_name);
+fclose(f);
+free(hin_addr);
+hin_addr= NULL;
+return false;
+}
+t= t+s;
+u= u-s;
+}while(u>0);
+hin_size= st.st_size;
+hin_time= st.st_mtime;
+return true;
+}
+
+#else
+
+#include <sys/mman.h>
+
+void hget_unmap(void)
+{munmap(hin_addr,hin_size);
+hin_addr= NULL;
+hin_size= 0;
+}
+
+bool hget_map(void)
+{struct stat st;
+int fd;
+fd= open(hin_name,O_RDONLY,0);
+if(fd<0)
+{MESSAGE("Unable to open file %s\n",hin_name);return false;}
+if(fstat(fd,&st)<0)
+{MESSAGE("Unable to get file size\n");
+close(fd);
+return false;
+}
+if(st.st_size==0)
+{MESSAGE("File %s is empty\n",hin_name);
+close(fd);
+return false;
+}
+if(hin_addr!=NULL)hget_unmap();
+hin_size= st.st_size;
+hin_time= st.st_mtime;
+hin_addr= mmap(NULL,hin_size,PROT_READ,MAP_PRIVATE,fd,0);
+if(hin_addr==MAP_FAILED)
+{close(fd);
+hin_addr= NULL;hin_size= 0;
+MESSAGE("Unable to map file into memory\n");
+return 0;
+}
+close(fd);
+return hin_size;
+}
+#endif
+
+	/*:317*/
+	#line 10166 "format.w"
+
+	/*304:*/
+	#line 6258 "format.w"
+
+
+bool hcheck_banner(char*magic)
+{int hbanner_size= 0;
+int v;
+char*t;
+t= hbanner;
+if(strncmp(magic,hbanner,4)!=0)
+{MESSAGE("This is not a %s file\n",magic);return false;}
+else t+= 4;
+hbanner_size= (int)strnlen(hbanner,MAX_BANNER);
+if(hbanner[hbanner_size-1]!='\n')
+{MESSAGE("Banner exceeds maximum size=0x%x\n",MAX_BANNER);return false;}
+if(*t!=' ')
+{MESSAGE("Space expected in banner after %s\n",magic);return false;}
+else t++;
+v= strtol(t,&t,10);
+if(v!=HINT_VERSION)
+{MESSAGE("Wrong HINT version: got %d, expected %d\n",v,HINT_VERSION);return false;}
+if(*t!='.')
+{MESSAGE("Dot expected in banner after HINT version number\n");return false;}
+else t++;
+v= strtol(t,&t,10);
+if(v!=HINT_SUB_VERSION)
+{MESSAGE("Wrong HINT subversion: got %d, expected %d\n",v,HINT_SUB_VERSION);return false;}
+if(*t!=' '&&*t!='\n')
+{MESSAGE("Space expected in banner after HINT subversion\n");return false;}
+LOG("%s file version %d.%d:%s",magic,HINT_VERSION,HINT_SUB_VERSION,t);
+DBG(DBGDIR,"banner size=0x%x\n",hbanner_size);
+return true;
+}
+	/*:304*/
+	#line 10167 "format.w"
+
+	/*326:*/
+	#line 6813 "format.w"
+
+entry_t*dir= NULL;
+uint16_t section_no,max_section_no;
+void new_directory(uint32_t entries)
+{DBG(DBGDIR,"Creating directory with %d entries\n",entries);
+RNG("Directory entries",entries,3,0x10000);
+max_section_no= entries-1;
+ALLOCATE(dir,entries,entry_t);
+dir[0].section_no= 0;dir[1].section_no= 1;dir[2].section_no= 2;
+}
+	/*:326*/	/*327:*/
+	#line 6826 "format.w"
+
+void hset_entry(entry_t*e,uint16_t i,uint32_t size,uint32_t xsize,char*file_name)
+{e->section_no= i;
+e->size= size;e->xsize= xsize;
+if(file_name==NULL||*file_name==0)
+e->file_name= NULL;
+else
+e->file_name= strdup(file_name);
+DBG(DBGDIR,"Creating entry %d: \"%s\" size=0x%x xsize=0x%x\n",i,file_name,size,xsize);
+}
+	/*:327*/
+	#line 10168 "format.w"
+
+
+	/*305:*/
+	#line 6298 "format.w"
+
+void hget_banner(void)
+{int i;
+for(i= 0;i<MAX_BANNER&&hpos<hend;i++)
+{hbanner[i]= HGET8;
+if(hbanner[i]=='\n')break;
+}
+hbanner[++i]= 0;
+}
+	/*:305*/	/*318:*/
+	#line 6585 "format.w"
+
+
+static void hdecompress(uint16_t n)
+{z_stream z;
+uint8_t*buffer;
+int i;
+
+DBG(DBGCOMPRESS,"Decompressing section %d from 0x%x to 0x%x byte\n",n,dir[n].size,dir[n].xsize);
+z.zalloc= (alloc_func)0;
+z.zfree= (free_func)0;
+z.opaque= (voidpf)0;
+z.next_in= hstart;
+z.avail_in= hend-hstart;
+if(inflateInit(&z)!=Z_OK)
+QUIT("Unable to initialize decompression: %s",z.msg);
+ALLOCATE(buffer,dir[n].xsize+MAX_TAG_DISTANCE,uint8_t);
+DBG(DBGBUFFER,"Allocating output buffer size=0x%x, margin=0x%x\n",dir[n].xsize,MAX_TAG_DISTANCE);
+z.next_out= buffer;
+z.avail_out= dir[n].xsize+MAX_TAG_DISTANCE;
+i= inflate(&z,Z_FINISH);
+DBG(DBGCOMPRESS,"in: avail/total=0x%x/0x%lx ""out: avail/total=0x%x/0x%lx, return %d;\n",
+z.avail_in,z.total_in,z.avail_out,z.total_out,i);
+if(i!=Z_STREAM_END)
+QUIT("Unable to complete decompression: %s",z.msg);
+if(z.avail_in!=0)
+QUIT("Decompression missed input data");
+if(z.total_out!=dir[n].xsize)
+QUIT("Decompression output size mismatch 0x%lx != 0x%x",z.total_out,dir[n].xsize);
+if(inflateEnd(&z)!=Z_OK)
+QUIT("Unable to finalize decompression: %s",z.msg);
+dir[n].buffer= buffer;
+dir[n].bsize= dir[n].xsize;
+hpos0= hpos= hstart= buffer;
+hend= hstart+dir[n].xsize;
+}
+	/*:318*/	/*320:*/
+	#line 6673 "format.w"
+
+void hget_section(uint16_t n)
+{DBG(DBGDIR,"Reading section %d\n",n);
+RNG("Section number",n,0,max_section_no);
+if(dir[n].buffer!=NULL&&dir[n].xsize>0)
+{hpos0= hpos= hstart= dir[n].buffer;
+hend= hstart+dir[n].xsize;
+}
+else
+{hpos0= hpos= hstart= hin_addr+dir[n].pos;
+hend= hstart+dir[n].size;
+if(dir[n].xsize>0)hdecompress(n);
+}
+}
+	/*:320*/	/*337:*/
+	#line 7051 "format.w"
+
+void hget_entry(entry_t*e)
+{	/*15:*/
+	#line 712 "format.w"
+
+uint8_t a,z;
+uint32_t node_pos= hpos-hstart;
+if(hpos>=hend)QUIT("Attempt to read a start byte at the end of the section");
+HGETTAG(a);
+	/*:15*/
+	#line 7053 "format.w"
+
+DBG(DBGDIR,"Reading directory entry\n");
+switch(a)
+{case TAG(0,b000+0):HGET_ENTRY(b000+0,*e);break;
+case TAG(0,b000+1):HGET_ENTRY(b000+1,*e);break;
+case TAG(0,b000+2):HGET_ENTRY(b000+2,*e);break;
+case TAG(0,b000+3):HGET_ENTRY(b000+3,*e);break;
+case TAG(0,b100+0):HGET_ENTRY(b100+0,*e);break;
+case TAG(0,b100+1):HGET_ENTRY(b100+1,*e);break;
+case TAG(0,b100+2):HGET_ENTRY(b100+2,*e);break;
+case TAG(0,b100+3):HGET_ENTRY(b100+3,*e);break;
+default:TAGERR(a);break;
+}
+	/*16:*/
+	#line 719 "format.w"
+
+HGETTAG(z);
+if(a!=z)
+QUIT("Tag mismatch [%s,%d]!=[%s,%d] at 0x%x to "SIZE_F"\n",
+NAME(a),INFO(a),NAME(z),INFO(z),node_pos,hpos-hstart-1);
+	/*:16*/
+	#line 7066 "format.w"
+
+}
+	/*:337*/	/*338:*/
+	#line 7083 "format.w"
+
+static void hget_root(entry_t*root)
+{DBG(DBGDIR,"Root entry at "SIZE_F"\n",hpos-hstart);
+hget_entry(root);
+root->pos= hpos-hstart;
+max_section_no= root->section_no;
+root->section_no= 0;
+if(max_section_no<2)QUIT("Sections 0, 1, and 2 are mandatory");
+}
+
+void hget_directory(void)
+{int i;
+entry_t root= {0};
+hget_root(&root);
+DBG(DBGDIR,"Directory\n");
+new_directory(max_section_no+1);
+dir[0]= root;
+DBG(DBGDIR,"Directory entry 1 at 0x%"PRIx64"\n",dir[0].pos);
+hget_section(0);
+for(i= 1;i<=max_section_no;i++)
+{hget_entry(&(dir[i]));
+dir[i].pos= dir[i-1].pos+dir[i-1].size;
+DBG(DBGDIR,"Section %d at 0x%"PRIx64"\n",i,dir[i].pos);
+}
+}
+
+void hclear_dir(void)
+{int i;
+if(dir==NULL)return;
+for(i= 0;i<3;i++)
+if(dir[i].xsize>0&&dir[i].buffer!=NULL)free(dir[i].buffer);
+free(dir);dir= NULL;
+}
+
+	/*:338*/	/*356:*/
+	#line 7499 "format.w"
+
+void hget_max_definitions(void)
+{kind_t k;
+	/*15:*/
+	#line 712 "format.w"
+
+uint8_t a,z;
+uint32_t node_pos= hpos-hstart;
+if(hpos>=hend)QUIT("Attempt to read a start byte at the end of the section");
+HGETTAG(a);
+	/*:15*/
+	#line 7502 "format.w"
+
+if(a!=TAG(list_kind,0))QUIT("Start of maximum list expected");
+for(k= 0;k<32;k++)max_ref[k]= max_default[k];max_outline= -1;
+while(true)
+{int n;
+if(hpos>=hend)QUIT("Unexpected end of maximum list");
+node_pos= hpos-hstart;
+HGETTAG(a);
+k= KIND(a);
+if(k==list_kind)break;
+if(INFO(a)&b001)HGET16(n);else n= HGET8;
+switch(a)
+{	/*238:*/
+	#line 4835 "format.w"
+
+
+case TAG(outline_kind,b100):
+case TAG(outline_kind,b101):max_outline= n;
+DBG(DBGDEF|DBGLABEL,"max(outline) = %d\n",max_outline);break;
+	/*:238*/
+	#line 7514 "format.w"
+
+default:
+if(max_fixed[k]>max_default[k])
+QUIT("Maximum value for kind %s not supported",definition_name[k]);
+RNG("Maximum number",n,max_default[k],MAX_REF(k));
+max_ref[k]= n;
+DBG(DBGDEF,"max(%s) = %d\n",definition_name[k],max_ref[k]);
+break;
+}
+	/*16:*/
+	#line 719 "format.w"
+
+HGETTAG(z);
+if(a!=z)
+QUIT("Tag mismatch [%s,%d]!=[%s,%d] at 0x%x to "SIZE_F"\n",
+NAME(a),INFO(a),NAME(z),INFO(z),node_pos,hpos-hstart-1);
+	/*:16*/
+	#line 7523 "format.w"
+
+}
+if(INFO(a)!=0)QUIT("End of maximum list with info %d",INFO(a));
+}
+	/*:356*/
+	#line 10170 "format.w"
+
+	/*52:*/
+	#line 1228 "format.w"
+
+#define HGET_UTF8C(X)  (X)= HGET8; if ((X&0xC0)!=0x80) \
+  QUIT("UTF8 continuation byte expected at " SIZE_F " got 0x%02X\n",hpos-hstart-1,X)
+
+uint32_t hget_utf8(void)
+{uint8_t a;
+a= HGET8;
+if(a<0x80)return a;
+else
+{if((a&0xE0)==0xC0)
+{uint8_t b;HGET_UTF8C(b);
+return((a&~0xE0)<<6)+(b&~0xC0);
+}
+else if((a&0xF0)==0xE0)
+{uint8_t b,c;HGET_UTF8C(b);HGET_UTF8C(c);
+return((a&~0xF0)<<12)+((b&~0xC0)<<6)+(c&~0xC0);
+}
+else if((a&0xF8)==0xF0)
+{uint8_t b,c,d;HGET_UTF8C(b);HGET_UTF8C(c);HGET_UTF8C(d);
+return((a&~0xF8)<<18)+((b&~0xC0)<<12)+((c&~0xC0)<<6)+(d&~0xC0);
+}
+else QUIT("UTF8 byte sequence expected");
+}
+}
+	/*:52*/	/*75:*/
+	#line 1603 "format.w"
+
+float32_t hget_float32(void)
+{union{float32_t d;uint32_t bits;}u;
+HGET32(u.bits);
+return u.d;
+}
+	/*:75*/	/*145:*/
+	#line 2822 "format.w"
+
+void hget_size_boundary(info_t info)
+{uint32_t n;
+if(info<2)return;
+n= HGET8;
+if(n-1!=0x100-info)QUIT("Size boundary byte 0x%x with info value %d at "SIZE_F,
+n,info,hpos-hstart-1);
+}
+
+uint32_t hget_list_size(info_t info)
+{uint32_t n= 0;
+if(info==1)return 0;
+else if(info==2)n= HGET8;
+else if(info==3)HGET16(n);
+else if(info==4)HGET24(n);
+else if(info==5)HGET32(n);
+else QUIT("List info %d must be 1, 2, 3, 4, or 5",info);
+return n;
+}
+
+void hget_list(list_t*l)
+{if(KIND(*hpos)!=list_kind&&
+KIND(*hpos)!=text_kind&&KIND(*hpos)!=param_kind)
+QUIT("List expected at 0x%x",(uint32_t)(hpos-hstart));
+else
+{
+	/*15:*/
+	#line 712 "format.w"
+
+uint8_t a,z;
+uint32_t node_pos= hpos-hstart;
+if(hpos>=hend)QUIT("Attempt to read a start byte at the end of the section");
+HGETTAG(a);
+	/*:15*/
+	#line 2848 "format.w"
+
+l->k= KIND(a);
+HGET_LIST(INFO(a),*l);
+	/*16:*/
+	#line 719 "format.w"
+
+HGETTAG(z);
+if(a!=z)
+QUIT("Tag mismatch [%s,%d]!=[%s,%d] at 0x%x to "SIZE_F"\n",
+NAME(a),INFO(a),NAME(z),INFO(z),node_pos,hpos-hstart-1);
+	/*:16*/
+	#line 2851 "format.w"
+
+DBG(DBGNODE,"Get list at 0x%x size=%u\n",l->p,l->s);
+}
+}
+	/*:145*/
+	#line 10171 "format.w"
+
+	/*426:*/
+	#line 8943 "format.w"
+
+uint32_t hff_list_pos= 0,hff_list_size= 0;
+uint8_t hff_tag;
+void hff_hpos(void)
+{signed char i,k;
+hff_tag= *hpos;
+DBGTAG(hff_tag,hpos);
+i= hnode_size[hff_tag];
+if(i>0){hpos= hpos+i;return;}
+else if(i<0)
+{k= 1+(i&0x3);i= i>>2;
+hpos= hpos-i;
+while(k>0)
+{hff_hpos();k--;}
+hpos++;
+return;
+}
+else if(hff_tag<=TAG(param_kind,5))
+	/*428:*/
+	#line 8988 "format.w"
+
+switch(INFO(hff_tag)){
+case 1:hff_list_pos= hpos-hstart+1;hff_list_size= 0;hpos= hpos+2;return;
+case 2:hpos++;hff_list_size= HGET8;hff_list_pos= hpos-hstart+1;hpos= hpos+1+hff_list_size+1+1+1;return;
+case 3:hpos++;HGET16(hff_list_size);hff_list_pos= hpos-hstart+1;hpos= hpos+1+hff_list_size+1+2+1;return;
+case 4:hpos++;HGET24(hff_list_size);hff_list_pos= hpos-hstart+1;hpos= hpos+1+hff_list_size+1+3+1;return;
+case 5:hpos++;HGET32(hff_list_size);hff_list_pos= hpos-hstart+1;hpos= hpos+1+hff_list_size+1+4+1;return;
+}
+	/*:428*/
+	#line 8961 "format.w"
+
+TAGERR(hff_tag);
+}
+	/*:426*/	/*457:*/
+	#line 9396 "format.w"
+
+float32_t hteg_float32(void)
+{union{float32_t d;uint32_t bits;}u;
+HTEG32(u.bits);
+return u.d;
+}
+	/*:457*/	/*495:*/
+	#line 9824 "format.w"
+
+void hteg_size_boundary(info_t info)
+{uint32_t n;
+if(info<2)return;
+n= HTEG8;
+if(n-1!=0x100-info)QUIT("List size boundary byte 0x%x does not match info value %d at "SIZE_F,
+n,info,hpos-hstart);
+}
+
+uint32_t hteg_list_size(info_t info)
+{uint32_t n;
+if(info==1)return 0;
+else if(info==2)n= HTEG8;
+else if(info==3)HTEG16(n);
+else if(info==4)HTEG24(n);
+else if(info==5)HTEG32(n);
+else QUIT("List info %d must be 1, 2, 3, 4, or 5",info);
+return n;
+}
+
+void hteg_list(list_t*l)
+{	/*454:*/
+	#line 9368 "format.w"
+
+uint8_t a,z;
+uint32_t node_pos= hpos-hstart;
+if(hpos<=hstart)return;
+HTEGTAG(z);
+	/*:454*/
+	#line 9845 "format.w"
+
+if(KIND(z)!=list_kind&&KIND(z)!=text_kind&&KIND(z)!=param_kind)
+QUIT("List expected at 0x%x",(uint32_t)(hpos-hstart));
+else
+{uint32_t s;
+l->k= KIND(z);
+l->s= hteg_list_size(INFO(z));
+hteg_size_boundary(INFO(z));
+hpos= hpos-l->s;
+l->p= hpos-hstart;
+hteg_size_boundary(INFO(z));
+s= hteg_list_size(INFO(z));
+if(s!=l->s)QUIT("List sizes at "SIZE_F" and 0x%x do not match 0x%x != 0x%x",
+hpos-hstart,node_pos-1,s,l->s);
+	/*455:*/
+	#line 9375 "format.w"
+
+HTEGTAG(a);
+if(a!=z)QUIT("Tag mismatch [%s,%d]!=[%s,%d] at "SIZE_F" to 0x%x\n",NAME(a),INFO(a),NAME(z),INFO(z),
+hpos-hstart,node_pos-1);
+	/*:455*/
+	#line 9859 "format.w"
+
+}
+}
+
+void hteg_param_list(list_t*l)
+{if(KIND(*(hpos-1))!=param_kind)return;
+hteg_list(l);
+}
+
+
+	/*:495*/
+	#line 10172 "format.w"
+
+	/*:508*/

Added: trunk/Build/source/texk/web2c/hitexdir/hintview/src/get.h
===================================================================
--- trunk/Build/source/texk/web2c/hitexdir/hintview/src/get.h	                        (rev 0)
+++ trunk/Build/source/texk/web2c/hitexdir/hintview/src/get.h	2022-01-19 13:28:43 UTC (rev 61658)
@@ -0,0 +1,190 @@
+	/*507:*/
+	#line 10106 "format.w"
+
+	/*1:*/
+	#line 328 "format.w"
+
+typedef struct{uint32_t c;uint8_t f;}glyph_t;
+	/*:1*/	/*113:*/
+	#line 2153 "format.w"
+
+typedef struct{
+dimen_t h,d,w;
+}rule_t;
+	/*:113*/	/*122:*/
+	#line 2267 "format.w"
+
+typedef struct{
+bool x;
+xdimen_t d;
+}kern_t;
+	/*:122*/	/*140:*/
+	#line 2688 "format.w"
+
+typedef struct{
+kind_t k;
+uint32_t p;
+uint32_t s;
+}list_t;
+	/*:140*/	/*148:*/
+	#line 3110 "format.w"
+
+typedef enum{txt_font= 0x00,txt_global= 0x08,txt_local= 0x11,
+txt_cc= 0x1D,txt_node= 0x1E,txt_hyphen= 0x1F,
+txt_glue= 0x20,txt_ignore= 0xFB}txt_t;
+	/*:148*/	/*159:*/
+	#line 3377 "format.w"
+
+typedef struct{kind_t k;int n;}ref_t;
+	/*:159*/	/*160:*/
+	#line 3414 "format.w"
+
+typedef struct{dimen_t h,d,w,a;float32_t r;int8_t s,o;list_t l;}box_t;
+	/*:160*/	/*187:*/
+	#line 3970 "format.w"
+
+typedef struct{uint8_t f;list_t l;}lig_t;
+	/*:187*/	/*195:*/
+	#line 4087 "format.w"
+
+typedef struct disc_t{bool x;list_t p,q;uint8_t r;}disc_t;
+	/*:195*/	/*228:*/
+	#line 4608 "format.w"
+
+typedef struct{
+uint16_t n;
+dimen_t w,h;
+stretch_t p,m;
+}image_t;
+	/*:228*/	/*264:*/
+	#line 5247 "format.w"
+
+typedef struct{
+uint8_t*t;
+int s;
+int d;
+uint16_t r;
+}outline_t;
+	/*:264*/	/*291:*/
+	#line 6063 "format.w"
+
+typedef
+struct{uint8_t pg;uint32_t pos;bool on;int link;}range_pos_t;
+	/*:291*/
+	#line 10107 "format.w"
+
+	/*325:*/
+	#line 6799 "format.w"
+
+typedef struct{
+uint64_t pos;
+uint32_t size,xsize;
+uint16_t section_no;
+char*file_name;
+uint8_t*buffer;
+uint32_t bsize;
+}entry_t;
+	/*:325*/
+	#line 10108 "format.w"
+
+	/*37:*/
+	#line 1062 "format.w"
+
+#define HGET_STRING(S) S= (char*)hpos;\
+ while(hpos<hend && *hpos!=0) { RNG("String character",*hpos,0x20,0x7E); hpos++;}\
+ hpos++;
+	/*:37*/	/*146:*/
+	#line 2857 "format.w"
+
+#define HGET_LIST(I,L) \
+    (L).s= hget_list_size(I); hget_size_boundary(I);\
+    (L).p= hpos-hstart; \
+    hpos= hpos+(L).s; hget_size_boundary(I);\
+    { uint32_t s= hget_list_size(I); \
+      if (s!=(L).s) \
+      QUIT("List sizes at 0x%x and " SIZE_F " do not match 0x%x != 0x%x",node_pos+1,hpos-hstart-I-1,(L).s,s);}
+	/*:146*/	/*311:*/
+	#line 6400 "format.w"
+
+#define HGET_ERROR  QUIT("HGET overrun in section %d at " SIZE_F "\n",section_no,hpos-hstart)
+#define HEND   ((hpos<=hend)?0:(HGET_ERROR,0))
+
+#define HGET8      ((hpos<hend)?*(hpos++):(HGET_ERROR,0))
+#define HGET16(X) ((X)= (hpos[0]<<8)+hpos[1],hpos+= 2,HEND)
+#define HGET24(X) ((X)= (hpos[0]<<16)+(hpos[1]<<8)+hpos[2],hpos+= 3,HEND)
+#define HGET32(X) ((X)= (hpos[0]<<24)+(hpos[1]<<16)+(hpos[2]<<8)+hpos[3],hpos+= 4,HEND)
+#define HGETTAG(A) A= HGET8,DBGTAG(A,hpos-1)
+	/*:311*/	/*336:*/
+	#line 7027 "format.w"
+
+#define HGET_SIZE(I) \
+  if ((I)&b100) { \
+    if (((I)&b011)==0) s= HGET8,xs= HGET8; \
+    else if (((I)&b011)==1) HGET16(s),HGET16(xs); \
+    else if (((I)&b011)==2) HGET24(s),HGET24(xs); \
+    else if (((I)&b011)==3) HGET32(s),HGET32(xs); \
+   } \
+  else { \
+    if (((I)&b011)==0) s= HGET8; \
+    else if (((I)&b011)==1) HGET16(s); \
+    else if (((I)&b011)==2) HGET24(s); \
+    else if (((I)&b011)==3) HGET32(s); \
+   }
+
+#define HGET_ENTRY(I,E) \
+{ uint16_t i; \
+  uint32_t s= 0,xs= 0; \
+  char *file_name; \
+  HGET16(i); HGET_SIZE(I); HGET_STRING(file_name); \
+  hset_entry(&(E),i,s,xs,file_name); \
+}
+	/*:336*/	/*456:*/
+	#line 9383 "format.w"
+
+#define HBACK(X) ((hpos-(X)<hstart)?(QUIT("HTEG underflow\n"),NULL):(hpos-= (X)))
+
+#define HTEG8     (HBACK(1),hpos[0])
+#define HTEG16(X) (HBACK(2),(X)= (hpos[0]<<8)+hpos[1])
+#define HTEG24(X) (HBACK(3),(X)= (hpos[0]<<16)+(hpos[1]<<8)+hpos[2])
+#define HTEG32(X) (HBACK(4),(X)= (hpos[0]<<24)+(hpos[1]<<16)+(hpos[2]<<8)+hpos[3])
+#define HTEGTAG(X) X= HTEG8,DBGTAG(X,hpos)
+	/*:456*/
+	#line 10109 "format.w"
+
+
+extern entry_t*dir;
+extern uint16_t section_no,max_section_no;
+extern uint8_t*hpos,*hstart,*hend,*hpos0;
+extern uint64_t hin_size,hin_time;
+extern uint8_t*hin_addr;
+
+extern label_t*labels;
+extern char*hin_name;
+extern bool hget_map(void);
+extern void hget_unmap(void);
+
+extern void new_directory(uint32_t entries);
+extern void hset_entry(entry_t*e,uint16_t i,uint32_t size,uint32_t xsize,char*file_name);
+
+extern void hget_banner(void);
+extern void hget_section(uint16_t n);
+extern void hget_entry(entry_t*e);
+extern void hget_directory(void);
+extern void hclear_dir(void);
+extern bool hcheck_banner(char*magic);
+
+extern void hget_max_definitions(void);
+extern uint32_t hget_utf8(void);
+extern void hget_size_boundary(info_t info);
+extern uint32_t hget_list_size(info_t info);
+extern void hget_list(list_t*l);
+extern uint32_t hget_utf8(void);
+extern float32_t hget_float32(void);
+extern float32_t hteg_float32(void);
+extern void hteg_size_boundary(info_t info);
+extern uint32_t hteg_list_size(info_t info);
+extern void hteg_list(list_t*l);
+extern void hff_hpos(void);
+extern uint32_t hff_list_pos,hff_list_size;
+extern uint8_t hff_tag;
+	/*:507*/

Added: trunk/Build/source/texk/web2c/hitexdir/hintview/src/hfonts.c
===================================================================
--- trunk/Build/source/texk/web2c/hitexdir/hintview/src/hfonts.c	                        (rev 0)
+++ trunk/Build/source/texk/web2c/hitexdir/hintview/src/hfonts.c	2022-01-19 13:28:43 UTC (rev 61658)
@@ -0,0 +1,596 @@
+/*375:*/
+#line 7596 "hint.w"
+
+#include "basetypes.h"
+#include "error.h"
+#include "format.h"
+
+#include "get.h"
+#include <ft2build.h> 
+#include FT_FREETYPE_H
+#include "hfonts.h"
+#include "hrender.h"
+#include "rendernative.h"
+
+/*308:*/
+#line 5715 "hint.w"
+
+static font_t*fonts[0x100]= {NULL};
+/*:308*//*314:*/
+#line 5844 "hint.w"
+
+static gcache_t g_undefined= {0};
+/*:314*//*348:*/
+#line 6991 "hint.w"
+
+static FT_Library ft_library= NULL;
+/*:348*/
+#line 7608 "hint.w"
+
+/*35:*/
+#line 562 "hint.w"
+
+extern uint16_t hglyph_section(uint8_t f);
+extern int32_t font_at_size(uint8_t f);
+/*:35*/
+#line 7609 "hint.w"
+
+/*313:*/
+#line 5801 "hint.w"
+
+#define G0_BITS 7
+#define G0_SIZE (1<<G0_BITS)
+#define G0_MASK (G0_SIZE-1)
+#define G123_BITS 6
+#define G123_SIZE (1<<G123_BITS)
+#define G123_MASK (G123_SIZE-1)
+
+static gcache_t*g_lookup(font_t*f,unsigned int cc)
+
+{if(cc>>G0_BITS){
+unsigned int cc1= (cc>>G0_BITS);
+if(cc1>>G123_BITS){
+unsigned int cc2= cc1>>G123_BITS;
+if(cc2>>G123_BITS){
+unsigned int cc3= cc2>>G123_BITS;
+if(cc3>>G123_BITS)return NULL;
+else if(f->g3&&
+f->g3[cc3&G123_MASK]&&
+f->g3[cc3&G123_MASK][cc2&G123_MASK]&&
+f->g3[cc3&G123_MASK][cc2&G123_MASK][cc1&G123_MASK])
+return f->g3[cc3&G123_MASK][cc2&G123_MASK][cc1&G123_MASK][cc&G0_MASK];
+}
+else if(f->g2&&f->g2[cc2&G123_MASK]&&f->g2[cc2&G123_MASK][cc1&G123_MASK])
+return f->g2[cc2&G123_MASK][cc1&G123_MASK][cc&G0_MASK];
+}
+else if(f->g1&&f->g1[cc1&G123_MASK])
+return f->g1[cc1&G123_MASK][cc&G0_MASK];
+}
+else if(f->g0)
+return f->g0[cc];
+return NULL;
+}
+/*:313*//*315:*/
+#line 5848 "hint.w"
+
+static gcache_t*hnew_g(gcache_t**g)
+{if(*g==NULL)
+*g= calloc(1,sizeof(gcache_t));
+if(*g==NULL)
+return&g_undefined;
+(*g)->ff= no_format;
+return*g;
+}
+
+static gcache_t*hnew_g0(gcache_t***g,unsigned int cc)
+{unsigned int cc0= cc&G0_MASK;
+if(*g==NULL)
+*g= calloc(G0_SIZE,sizeof(gcache_t*));
+if(*g==NULL)
+return&g_undefined;
+return hnew_g((*g)+cc0);
+}
+
+static gcache_t*hnew_g1(gcache_t****g,unsigned int cc)
+{unsigned int cc1= (cc>>G0_BITS)&G123_MASK;
+if(*g==NULL)
+*g= calloc(G123_SIZE,sizeof(gcache_t**));
+if(*g==NULL)
+return&g_undefined;
+return hnew_g0((*g)+cc1,cc);
+}
+static gcache_t*hnew_g2(gcache_t*****g,unsigned int cc)
+{unsigned int cc2= (cc>>(G123_BITS+G0_BITS))&G123_MASK;
+if(*g==NULL)
+*g= calloc(G123_SIZE,sizeof(gcache_t***));
+if(*g==NULL)
+return&g_undefined;
+return hnew_g1((*g)+cc2,cc);
+}
+
+static gcache_t*hnew_g3(gcache_t******g,unsigned int cc)
+{unsigned int cc3= (cc>>(G123_BITS+G123_BITS+G0_BITS))&G123_MASK;
+if(*g==NULL)
+*g= calloc(G123_SIZE,sizeof(gcache_t****));
+if(*g==NULL)
+return&g_undefined;
+return hnew_g2((*g)+cc3,cc);
+}
+
+
+static gcache_t*hnew_glyph(font_t*f,unsigned int cc)
+{if(cc<G0_SIZE)return hnew_g0(&(f->g0),cc);
+else if(cc<G123_SIZE*G0_SIZE)return hnew_g1(&(f->g1),cc);
+else if(cc<G123_SIZE*G123_SIZE*G0_SIZE)return hnew_g2(&(f->g2),cc);
+else if(cc<G123_SIZE*G123_SIZE*G123_SIZE*G0_SIZE)return hnew_g3(&(f->g3),cc);
+else return&g_undefined;
+}
+/*:315*/
+#line 7610 "hint.w"
+
+
+/*352:*/
+#line 7025 "hint.w"
+
+
+int unpack_ft_file(font_t*f)
+{int e;
+/*349:*/
+#line 6995 "hint.w"
+
+if(ft_library==NULL)
+{int e= FT_Init_FreeType(&ft_library);
+if(e)QUIT("Unable to initialize the FreeType library");
+}
+/*:349*/
+#line 7029 "hint.w"
+
+f->hpxs= 72.27/xdpi;
+f->vpxs= 72.27/ydpi;
+e= FT_New_Memory_Face(ft_library,
+f->font_data,f->data_size,0,&(f->tt.face));
+if(e)return 0;
+/*353:*/
+#line 7050 "hint.w"
+
+e= FT_Select_Charmap(f->tt.face,FT_ENCODING_ADOBE_CUSTOM);
+if(e)LOG("Unable to select custom encoding for font %d\n",f->n);
+/*:353*/
+#line 7035 "hint.w"
+
+/*354:*/
+#line 7058 "hint.w"
+
+e= FT_Set_Char_Size(
+f->tt.face,
+0,
+(FT_F26Dot6)(0.5+(f->s*64.0*72.0/72.27)),
+72.27/f->hpxs,
+72.27/f->vpxs);
+if(e)QUIT("Unable to set FreeType glyph size");
+FT_Set_Transform(f->tt.face,0,0);
+/*:354*/
+#line 7036 "hint.w"
+
+f->ff= ft_format;
+return 1;
+}
+/*:352*//*355:*/
+#line 7081 "hint.w"
+
+static void ft_unpack_glyph(font_t*f,gcache_t*g,uint32_t cc)
+{int e,i;
+
+i= FT_Get_Char_Index(f->tt.face,cc);
+e= FT_Load_Glyph(
+f->tt.face,
+i,
+FT_LOAD_RENDER|FT_LOAD_TARGET_NORMAL);
+if(e)QUIT("Unable to render FreeType glyph %c (%u)",(char)cc,cc);
+
+g->w= f->tt.face->glyph->bitmap.width;
+g->h= f->tt.face->glyph->bitmap.rows;
+g->hoff= -f->tt.face->glyph->bitmap_left;
+g->voff= f->tt.face->glyph->bitmap_top-1;
+g->bits= calloc(g->w*g->h,1);
+if(g->bits==NULL)QUIT("Out of memory for FreeType glyph %c (%u)",(char)cc,cc);
+memcpy(g->bits,f->tt.face->glyph->bitmap.buffer,g->w*g->h);
+
+g->ff= ft_format;
+nativeSetFreeType(g);
+}
+
+/*:355*/
+#line 7612 "hint.w"
+
+
+/*340:*/
+#line 6696 "hint.w"
+
+#define PK_READ_1_BYTE() (data[i++])
+#define PK_READ_2_BYTE() (k= PK_READ_1_BYTE(),k= k<<8,k= k+data[i++],k)
+#define PK_READ_3_BYTE() (k= PK_READ_2_BYTE(),k= k<<8,k= k+data[i++],k)
+#define PK_READ_4_BYTE() (k= PK_READ_3_BYTE(),k= k<<8,k= k+data[i++],k)
+/*:340*//*342:*/
+#line 6723 "hint.w"
+
+#define read_nybble(P) ((P).j&1?((P).data[(P).j++>>1]&0xF):(((P).data[(P).j++>>1]>>4)&0xF))
+/*:342*//*343:*/
+#line 6749 "hint.w"
+
+static int packed_number(pk_parse_t*p)
+{int i,k;
+i= read_nybble(*p);
+if(i==0)
+{do{k= read_nybble(*p);i++;}while(k==0);
+while(i--> 0)k= k*16+read_nybble(*p);
+return k-15+(13-p->f)*16+p->f;
+}
+else if(i<=p->f)return i;
+else if(i<14)return(i-p->f-1)*16+read_nybble(*p)+p->f+1;
+else
+{if(i==14)p->r= packed_number(p);
+else p->r= 1;
+return packed_number(p);
+}
+}
+/*:343*//*344:*/
+#line 6778 "hint.w"
+
+static void pk_runlength(gcache_t*g,unsigned char*data){
+pk_parse_t p;
+int x,y;
+unsigned char*bits;
+int n;
+unsigned char gray;
+bits= g->bits= (unsigned char*)calloc(g->w*g->h,1);
+if(bits==NULL){g->w= g->h= 0;return;}
+p.j= 0;
+p.r= 0;
+p.f= g->pk.flag>>4;
+p.data= data;
+n= 0;
+if((g->pk.flag>>3)&1)gray= 0x00;
+else gray= 0xff;
+y= 0;
+while(y<g->h){
+x= 0;
+while(x<(int)g->w)
+{int d;
+if(n<=0){
+n= packed_number(&p);
+gray= ~gray;
+}
+d= g->w-x;
+if(d> n)d= n;
+for(;d> 0;d--,x++,n--)
+bits[y*g->w+x]= gray;
+}
+y++;
+while(p.r> 0&&y<g->h)
+{int k;
+for(k= 0;k<g->w;k++)
+bits[y*g->w+k]= bits[(y-1)*g->w+k];
+p.r--;
+y++;
+}
+}
+}
+/*:344*//*345:*/
+#line 6830 "hint.w"
+
+static void pk_bitmap(gcache_t*g,unsigned char*data){
+unsigned char*bits;
+int x,y;
+unsigned char mask;
+
+g->bits= bits= (unsigned char*)calloc(g->w*g->h,1);
+if(bits==NULL){g->w= g->h= 0;return;}
+mask= 0x80;
+for(y= 0;y<g->h;y++)
+for(x= 0;x<g->w;x++)
+{if(*data&mask)
+bits[y*g->w+x]= 0x00;
+else
+bits[y*g->w+x]= 0xFF;
+mask= mask>>1;
+if(mask==0){data++;mask= 0x80;}
+}
+}
+/*:345*//*346:*/
+#line 6853 "hint.w"
+
+
+static void pkunpack_glyph(gcache_t*g)
+{int i,k;
+unsigned char*data;
+if(g==NULL||g->pk.encoding==NULL)return;
+g->ff= pk_format;
+if(g->bits!=NULL)return;
+#if 0
+DBG(DBGRENDER,"Unpacking glyph %c (0x%x)",g->cc,g->cc);
+#endif
+data= g->pk.encoding;
+i= 0;
+if((g->pk.flag&7)<4)
+{i= i+3;
+i= i+1;
+g->w= PK_READ_1_BYTE();
+g->h= PK_READ_1_BYTE();
+g->hoff= (signed char)PK_READ_1_BYTE();
+g->voff= (signed char)PK_READ_1_BYTE();
+}
+else if((g->pk.flag&7)<7)
+{i= i+3;
+i= i+2;
+g->w= PK_READ_2_BYTE();
+g->h= PK_READ_2_BYTE();
+g->hoff= (signed short int)PK_READ_2_BYTE();
+g->voff= (signed short int)PK_READ_2_BYTE();
+}
+else
+{i= i+4;
+i= i+8;
+g->w= PK_READ_4_BYTE();
+g->h= PK_READ_4_BYTE();
+g->hoff= (signed int)PK_READ_4_BYTE();
+g->voff= (signed int)PK_READ_4_BYTE();
+}
+if((g->pk.flag>>4)==14)pk_bitmap(g,data+i);
+else pk_runlength(g,data+i);
+nativeSetPK(g);
+}
+/*:346*//*347:*/
+#line 6898 "hint.w"
+
+
+static gcache_t*hnew_glyph(font_t*pk,unsigned int cc);
+
+
+
+#define PK_XXX1 240
+#define PK_XXX2 241
+#define PK_XXX3 242
+#define PK_XXX4 243
+#define PK_YYY  244
+#define PK_POST 245
+#define PK_NO_OP 246
+#define PK_PRE   247
+#define PK_ID    89
+
+
+int unpack_pk_file(font_t*pk)
+
+{int i,j;
+unsigned int k;
+unsigned char flag;
+unsigned char*data;
+data= pk->font_data;
+i= 0;
+while(i<pk->data_size)
+switch(flag= data[i++])
+{case PK_XXX1:j= PK_READ_1_BYTE();i= i+j;break;
+case PK_XXX2:j= PK_READ_2_BYTE();i= i+j;break;
+case PK_XXX3:j= PK_READ_3_BYTE();i= i+j;break;
+case PK_XXX4:j= PK_READ_4_BYTE();i= i+j;break;
+case PK_YYY:i= i+4;break;
+case PK_NO_OP:break;
+case PK_PRE:
+{int csize;
+pk->pk.id= PK_READ_1_BYTE();
+if(pk->pk.id!=PK_ID)return 0;
+csize= PK_READ_1_BYTE();
+pk->pk.pk_comment= pk->font_data+i;
+i= i+csize;
+pk->pk.ds= PK_READ_4_BYTE()/(double)(1<<20);
+pk->pk.cs= PK_READ_4_BYTE();
+pk->hpxs= (double)(1<<16)/PK_READ_4_BYTE();
+pk->vpxs= (double)(1<<16)/PK_READ_4_BYTE();
+if(pk->pk.ds!=pk->s)
+{double m= pk->s/pk->pk.ds;
+pk->hpxs*= m;
+pk->vpxs*= m;
+}
+#if 0    
+pk->comment[csize]= 0;
+#endif
+}
+break;
+case PK_POST:break;
+case 248:case 249:case 250:case 251:case 252:case 253:case 254:case 255:break;
+default:
+{
+unsigned int pl;
+unsigned int cc;
+gcache_t*g;
+if((flag&7)==7)
+{pl= PK_READ_4_BYTE();
+cc= PK_READ_4_BYTE();
+}else if((flag&4)==4)
+{pl= PK_READ_2_BYTE();
+cc= PK_READ_1_BYTE();
+pl= pl+((flag&3)<<16);
+}else
+{pl= PK_READ_1_BYTE();
+cc= PK_READ_1_BYTE();
+pl= pl+((flag&3)<<8);
+}
+g= hnew_glyph(pk,cc);
+g->pk.flag= flag;
+g->pk.encoding= data+i;
+g->bits= NULL;
+i= i+pl;
+}
+break;
+}
+return 1;
+}
+
+/*:347*/
+#line 7614 "hint.w"
+
+
+/*309:*/
+#line 5721 "hint.w"
+
+struct font_s*hget_font(unsigned char f)
+{font_t*fp;
+if(fonts[f]!=NULL)return fonts[f];
+DBG(DBGFONT,"Decoding new font %d\n",f);
+if(f> max_ref[font_kind])
+QUIT("Undefined font %d\n",f);
+fp= calloc(1,sizeof(*fp));
+if(fp==NULL)
+QUIT("Out of memory for font %d",f);
+else
+{unsigned char*spos,*sstart,*send;
+spos= hpos;sstart= hstart;send= hend;
+fp->n= f;
+hget_section(hglyph_section(f));
+fp->font_data= hstart;
+fp->data_size= hend-hstart;
+hpos= spos;hstart= sstart;hend= send;
+}
+fp->s= font_at_size(f)/(double)(1<<16);
+/*337:*/
+#line 6633 "hint.w"
+
+if(fp->font_data[0]==0xF7&&fp->font_data[1]==0x59)
+{fp->ff= pk_format;
+if(!unpack_pk_file(fp)){free(fp);fp= NULL;}
+}
+/*:337*//*356:*/
+#line 7108 "hint.w"
+
+else if(unpack_ft_file(fp))
+fp->ff= ft_format;
+else
+{QUIT("Font format not supported for font %d\n",fp->n);
+free(fp);fp= NULL;
+}
+/*:356*/
+#line 5741 "hint.w"
+
+fonts[f]= fp;
+return fonts[f];
+}
+/*:309*//*311:*/
+#line 5759 "hint.w"
+
+static void hfree_glyph_cache(font_t*f,bool rm);
+
+void hint_clear_fonts(bool rm)
+{int f;
+DBG(DBGFONT,rm?"Clear font data":"Clear native glyph data");
+for(f= 0;f<=max_ref[font_kind];f++)
+if(fonts[f]!=NULL)
+{hfree_glyph_cache(fonts[f],rm);
+if(rm){free(fonts[f]);fonts[f]= NULL;}
+}
+}
+/*:311*//*316:*/
+#line 5912 "hint.w"
+
+static void hfree_g0(struct gcache_s**g,bool rm)
+{int i;
+if(g==NULL)return;
+for(i= 0;i<G0_SIZE;i++)
+if(g[i]!=NULL)
+{nativeFreeGlyph(g[i]);
+if(rm){
+if(g[i]->bits!=NULL)free(g[i]->bits);
+free(g[i]);g[i]= NULL;}
+}
+}
+
+static void hfree_g1(struct gcache_s***g,bool rm)
+{int i;
+if(g==NULL)return;
+for(i= 0;i<G123_SIZE;i++)
+if(g[i]!=NULL)
+{hfree_g0(g[i],rm);
+if(rm){free(g[i]);g[i]= NULL;}
+}
+}
+
+static void hfree_g2(struct gcache_s****g,bool rm)
+{int i;
+if(g==NULL)return;
+for(i= 0;i<G123_SIZE;i++)
+if(g[i]!=NULL)
+{hfree_g1(g[i],rm);
+if(rm){free(g[i]);g[i]= NULL;}
+}
+}
+
+
+static void hfree_g3(struct gcache_s*****g,bool rm)
+{int i;
+if(g==NULL)return;
+for(i= 0;i<G123_SIZE;i++)
+if(g[i]!=NULL)
+{hfree_g2(g[i],rm);
+if(rm){free(g[i]);g[i]= NULL;}
+}
+}
+
+
+static void hfree_glyph_cache(font_t*f,bool rm)
+{if(f->g0!=NULL)
+{hfree_g0(f->g0,rm);
+if(rm){free(f->g0);f->g0= NULL;}
+}
+if(f->g1!=NULL)
+{hfree_g1(f->g1,rm);
+if(rm){free(f->g1);f->g1= NULL;}
+}
+if(f->g2!=NULL)
+{hfree_g2(f->g2,rm);
+if(rm){free(f->g2);f->g2= NULL;}
+}
+if(f->g3!=NULL)
+{hfree_g3(f->g3,rm);
+if(rm){free(f->g3);f->g3= NULL;}
+}
+}
+/*:316*//*318:*/
+#line 6038 "hint.w"
+
+gcache_t*hget_glyph(font_t*f,unsigned int cc)
+{
+gcache_t*g= NULL;
+g= g_lookup(f,cc);
+if(g==NULL)
+{if(f->ff==ft_format)
+g= hnew_glyph(f,cc);
+else
+return NULL;
+}
+if(g->ff==no_format)
+{if(f->ff==pk_format)pkunpack_glyph(g);
+else if(f->ff==ft_format)ft_unpack_glyph(f,g,cc);
+else QUIT("Font format not supported");
+}
+return g;
+}
+/*:318*//*320:*/
+#line 6070 "hint.w"
+
+void render_char(int x,int y,struct font_s*f,uint32_t cc,uint8_t s)
+
+{double w,h,dx,dy;
+gcache_t*g= hget_glyph(f,cc);
+if(g==NULL)return;
+
+dx= (double)g->hoff*f->hpxs;
+dy= (double)g->voff*f->vpxs;
+w= (double)g->w*f->hpxs;
+h= (double)g->h*f->vpxs;
+nativeGlyph(SP2PT(x),dx,SP2PT(y),dy,w,h,g,s);
+}
+
+/*:320*/
+#line 7616 "hint.w"
+
+
+/*:375*/

Added: trunk/Build/source/texk/web2c/hitexdir/hintview/src/hfonts.h
===================================================================
--- trunk/Build/source/texk/web2c/hitexdir/hintview/src/hfonts.h	                        (rev 0)
+++ trunk/Build/source/texk/web2c/hitexdir/hintview/src/hfonts.h	2022-01-19 13:28:43 UTC (rev 61658)
@@ -0,0 +1,101 @@
+/*374:*/
+#line 7585 "hint.w"
+
+#ifndef _HFONTS_H
+#define _HFONTS_H
+
+/*306:*/
+#line 5687 "hint.w"
+
+typedef enum{no_format,pk_format,ft_format}font_format_t;
+/*:306*//*307:*/
+#line 5699 "hint.w"
+
+/*338:*/
+#line 6672 "hint.w"
+
+
+typedef struct
+{unsigned char*pk_comment;
+unsigned int cs;
+double ds;
+unsigned char id;
+}pk_t;
+/*:338*//*350:*/
+#line 7003 "hint.w"
+
+typedef struct
+{FT_Face face;
+}ft_t;
+/*:350*//*351:*/
+#line 7010 "hint.w"
+
+typedef struct
+{int dummy;
+}ftg_t;
+/*:351*/
+#line 5700 "hint.w"
+
+
+typedef struct font_s{
+unsigned char n;
+unsigned char*font_data;
+int data_size;
+double s;
+double hpxs,vpxs;
+/*312:*/
+#line 5787 "hint.w"
+
+struct gcache_s**g0;
+struct gcache_s***g1;
+struct gcache_s****g2;
+struct gcache_s*****g3;
+
+/*:312*/
+#line 5708 "hint.w"
+
+font_format_t ff;
+union{pk_t pk;ft_t tt;};
+}font_t;
+/*:307*//*317:*/
+#line 5999 "hint.w"
+
+/*339:*/
+#line 6685 "hint.w"
+
+typedef struct
+{unsigned char flag;
+unsigned char*encoding;
+}pkg_t;
+/*:339*//*341:*/
+#line 6712 "hint.w"
+
+typedef struct{
+int j;
+int r;
+int f;
+unsigned char*data;
+}pk_parse_t;
+/*:341*/
+#line 6000 "hint.w"
+
+
+struct gcache_s{
+int w,h;
+int hoff,voff;
+unsigned char*bits;
+unsigned int GLtexture;
+font_format_t ff;
+union{
+pkg_t pk;
+ftg_t tt;
+};
+};
+typedef struct gcache_s gcache_t;
+/*:317*/
+#line 7589 "hint.w"
+
+
+
+#endif
+/*:374*/

Added: trunk/Build/source/texk/web2c/hitexdir/hintview/src/hint.c
===================================================================
--- trunk/Build/source/texk/web2c/hitexdir/hintview/src/hint.c	                        (rev 0)
+++ trunk/Build/source/texk/web2c/hitexdir/hintview/src/hint.c	2022-01-19 13:28:43 UTC (rev 61658)
@@ -0,0 +1,3775 @@
+/*371:*/
+#line 7506 "hint.w"
+
+#include "basetypes.h"
+#include <string.h> 
+#include <math.h> 
+#include <zlib.h> 
+#include "error.h"
+#include "format.h"
+#include "hrender.h"
+#include "get.h"
+#include "htex.h"
+#include "hint.h"
+
+/*82:*/
+#line 1279 "hint.w"
+
+#define HGET_STRING(S) S= (char*)hpos;\
+ while(hpos<hend && *hpos!=0) { RNG("String character",*hpos,0x20,0x7E); hpos++;}\
+ hpos++;
+/*:82*//*83:*/
+#line 1291 "hint.w"
+
+#define HGET_XDIMEN(I,X) \
+{ if((I)&b100) HGET32((X).w); else (X).w= 0;\
+  if((I)&b010) (X).h= hget_float32();  else (X).h= 0.0;\
+  if((I)&b001) (X).v= hget_float32(); else (X).v= 0.0;\
+}
+/*:83*//*87:*/
+#line 1394 "hint.w"
+
+#define HGET_STRETCH(F,O) { stch_t _st;  HGET32(_st.u); (O)= _st.u&3;  _st.u&= ~3; (F)= (scaled)(_st.f*ONE); }
+/*:87*//*89:*/
+#line 1405 "hint.w"
+
+#define HGET_GLYPH(I) \
+{uint8_t f; uint32_t c;\
+  if (I==1) c= HGET8;\
+  else if (I==2) HGET16(c);\
+  else if (I==3) HGET24(c);\
+  else if (I==4) HGET32(c);\
+  f= HGET8; REF_RNG(font_kind,f);\
+  tail_append(new_character(f,c));\
+}
+/*:89*//*97:*/
+#line 1487 "hint.w"
+
+#define HGET_RULE(I)\
+pointer p= new_rule();\
+if ((I)&b100) HGET32(height(p)); else height(p)= null_flag;\
+if ((I)&b010) HGET32(depth(p)); else depth(p)= null_flag;\
+if ((I)&b001) HGET32(width(p)); else width(p)= null_flag;
+/*:97*//*103:*/
+#line 1549 "hint.w"
+
+#define HGET_GLUE(I) \
+  p=  get_node(glue_spec_size); \
+  if((I)!=b111) { if ((I)&b100) HGET32(width(p)); else width(p)= 0; }\
+  if((I)&b010) HGET_STRETCH(stretch(p),stretch_order(p)) else stretch(p)= 0, stretch_order(p)= normal;\
+  if((I)&b001) HGET_STRETCH(shrink(p),shrink_order(p)) else shrink(p)= 0, shrink_order(p)= normal;\
+  if(I==b111) width(p)= hget_xdimen_node();
+/*:103*//*110:*/
+#line 1669 "hint.w"
+
+#define IS_LIST(X)  (KIND(X)==list_kind || \
+        KIND(X)==text_kind  || KIND(X)==param_kind)
+/*:110*//*115:*/
+#line 1826 "hint.w"
+
+#define HGET_BOX(I) \
+p= new_null_box();\
+HGET32(height(p));\
+if ((I)&b001) HGET32(depth(p));\
+HGET32(width(p));\
+if ((I)&b010) HGET32(shift_amount(p));\
+if ((I)&b100) {int8_t x; glue_set(p)= hget_float32();\
+  x= HGET8;  glue_order(p)= x&0xF;\
+  x= x>>4; glue_sign(p)= (x<0?shrinking:(x> 0?stretching:normal));}\
+list_ptr(p)= hget_list_pointer();
+/*:115*//*122:*/
+#line 1950 "hint.w"
+
+#define HGET_SET(I) \
+ scaled x, st, sh; uint8_t sto, sho; \
+ p= new_null_box();\
+ HGET32(height(p)); if ((I)&b001) HGET32(depth(p)); HGET32(width(p));\
+ if ((I)&b010) HGET32(shift_amount(p));\
+ HGET_STRETCH(st,sto);   HGET_STRETCH(sh,sho);\
+ if ((I)&b100) x=  hget_xdimen_node();  else x= hget_xdimen_ref(HGET8);\
+ list_ptr(p)= hget_list_pointer();
+/*:122*//*128:*/
+#line 2093 "hint.w"
+
+#define HGET_PACK(K,I) \
+{ pointer p; scaled x, s= 0, d;  uint8_t m; \
+ if ((I)&b001) m= additional; else m= exactly; \
+ if ((I)&b010) HGET32(s);\
+ if (K==vpack_kind) HGET32(d); \
+ if ((I)&b100) x=  hget_xdimen_node();  else x= hget_xdimen_ref(HGET8);\
+ p= hget_list_pointer(); \
+ if (K==vpack_kind) p= vpackage(p,x,m,d); else p= hpack(p,x,m);\
+ shift_amount(p)= s;\
+ happend_to_vlist(p);}
+/*:128*//*132:*/
+#line 2160 "hint.w"
+
+#define HGET_KERN(I) \
+pointer p; scaled x; \
+if (((I)&b011)==0) x= hget_dimen_ref(HGET8);\
+else if (((I)&b011)==1) x= hget_xdimen_ref(HGET8);\
+else if (((I)&b011)==2) HGET32(x);\
+else if (((I)&b011)==3) x= hget_xdimen_node();\
+p= new_kern(x);\
+if ((I)&b100) subtype(p)= explicit;\
+tail_append(p);
+/*:132*//*136:*/
+#line 2211 "hint.w"
+
+#define HGET_LEADERS(I) \
+{pointer p;\
+ if ((I)&b100)p= hget_glue_node(); else {p= spec2glue(zero_glue); incr(glue_ref_count(zero_glue));} \
+subtype(p)= a_leaders+((I)&b011)-1;\
+if (KIND(*hpos)==rule_kind) leader_ptr(p)= hget_rule_node(); \
+else if (KIND(*hpos)==hbox_kind) leader_ptr(p)= hget_hbox_node(); \
+else  leader_ptr(p)= hget_vbox_node();\
+tail_append(p);}
+/*:136*//*140:*/
+#line 2257 "hint.w"
+
+#define HGET_BASELINE(I) \
+  cur_list.bs_pos= hpos-1; \
+  if((I)&b001) HGET32(cur_lsl); else cur_lsl= 0; \
+  if((I)&b100) cur_bs= hget_glue_spec(); else cur_bs= zero_glue; \
+  if((I)&b010) cur_ls= hget_glue_spec(); else cur_ls= zero_glue;
+/*:140*//*145:*/
+#line 2311 "hint.w"
+
+#define HGET_LIG(I) \
+{pointer p,q;uint8_t f;\
+f= HGET8;\
+if ((I)==7) q= hget_list_pointer(); else q= hget_text_list(I);\
+if (q==null) QUIT("Ligature with empty list");\
+p= new_ligature(f, character(q), link(q)); tail_append(p);\
+link(q)= null; flush_node_list(q);\
+}
+/*:145*//*149:*/
+#line 2363 "hint.w"
+
+#define HGET_DISC(I)\
+  pointer p= new_disc(); \
+  if ((I)&b100) {uint8_t r; r= HGET8; set_replace_count(p,r); \
+                 if ((r&0x80)==0) set_auto_disc(p); }\
+  else  set_auto_disc(p); \
+  if ((I)&b010) pre_break(p)= hget_list_pointer(); \
+  if ((I)&b001) post_break(p)= hget_list_pointer();
+/*:149*//*155:*/
+#line 2436 "hint.w"
+
+#define HGET_PAR(I) \
+{ scaled x= 0;\
+  param_def_t *q;\
+  if ((I)==b100) q= hget_param_list_ref(HGET8);\
+  if ((I)&b100) x= hget_xdimen_node(); else x= hget_xdimen_ref(HGET8);\
+  if ((I)&b010) q= hget_param_list_node(); \
+  else if ((I)!=b100) q= hget_param_list_ref(HGET8);\
+  hget_paragraph(x,0,q);\
+}
+/*:155*//*172:*/
+#line 2921 "hint.w"
+
+#define HGET_MATH(I) \
+{ param_def_t *q; pointer p= null, a= null;\
+if ((I)&b100) q= hget_param_list_node(); else q= hget_param_list_ref(HGET8);\
+if ((I)&b010) a= hget_hbox_node(); \
+p= hget_list_pointer(); \
+if ((I)&b001) a= hget_hbox_node();\
+hset_param_list(q); hdisplay(p,a,((I)&b010)!=0); hrestore_param_list();\
+}
+/*:172*//*178:*/
+#line 2990 "hint.w"
+
+#define HGET_ADJUST(I) \
+{ pointer p;\
+  p= get_node(small_node_size); type(p)= adjust_node; subtype(p)= normal;\
+  adjust_ptr(p)= hget_list_pointer(); \
+  tail_append(p);\
+}
+/*:178*//*180:*/
+#line 3006 "hint.w"
+
+#define HGET_TABLE(I) \
+if(I&b010) ; else ;\
+if ((I)&b001) ; else ;\
+if ((I)&b100) hget_xdimen_node(); else hget_xdimen_ref(HGET8);\
+hget_list_pointer();  \
+hget_list_pointer(); 
+/*:180*//*185:*/
+#line 3102 "hint.w"
+
+#define HGET_STREAM(I) \
+{ param_def_t *q;  pointer p;\
+  p= get_node(ins_node_size); type(p)= ins_node;\
+  subtype(p)= HGET8;RNG("Stream",subtype(p),1,254); \
+  if ((I)&b010) q= hget_param_list_node(); else q= hget_param_list_ref(HGET8); \
+  ins_ptr(p)= hget_list_pointer(); \
+  if ((I)&b010) hset_stream_params(p,true,q); else hset_stream_params(p,false,q);\
+  tail_append(p);}
+/*:185*//*189:*/
+#line 3134 "hint.w"
+
+#define HGET_IMAGE(I) \
+{ pointer p;\
+  p= get_node(image_node_size);  type(p)= whatsit_node; subtype(p)= image_node;\
+  HGET16(image_no(p));RNG("Section number",image_no(p),3,max_section_no);  \
+  if (I&b010) {HGET32(image_width(p)); HGET32(image_height(p));} \
+  else image_width(p)= image_height(p)= 0;\
+  if (I&b001) {HGET_STRETCH(image_stretch(p),image_stretch_order(p)); \
+               HGET_STRETCH(image_shrink(p),image_shrink_order(p));}\
+  else { image_stretch(p)= image_shrink(p)= 0;image_stretch_order(p)= image_shrink_order(p)= normal;}\
+  tail_append(p);}
+/*:189*//*193:*/
+#line 3176 "hint.w"
+
+#define HGET_LINK(I) \
+{ pointer p;\
+  p= get_node(link_node_size);  type(p)= whatsit_node;\
+  if (I&b010) subtype(p)= start_link_node; else subtype(p)= end_link_node;\
+  if (I&b001) HGET16(label_ref(p)); else label_ref(p)= HGET8; \
+  RNG("label",label_ref(p),0,max_ref[label_kind]);\
+  label_has_name(p)= 0;\
+  tail_append(p);}
+/*:193*/
+#line 7518 "hint.w"
+
+/*84:*/
+#line 1299 "hint.w"
+
+#define HTEG_XDIMEN(I,X) \
+  if((I)&b001) (X).v= hteg_float32(); else (X).v= 0.0;\
+  if((I)&b010) (X).h= hteg_float32();  else (X).h= 0.0;\
+  if((I)&b100) HTEG32((X).w); else (X).w= 0;\
+/*:84*//*88:*/
+#line 1397 "hint.w"
+
+#define HTEG_STRETCH(F,O) { stch_t _st;  HTEG32(_st.u); (O)= _st.u&3;  _st.u&= ~3; (F)= (scaled)(_st.f*ONE); }
+/*:88*//*90:*/
+#line 1417 "hint.w"
+
+#define HTEG_GLYPH(I) \
+{uint8_t f; uint32_t c;\
+  f= HTEG8; REF_RNG(font_kind,f);\
+  if (I==1) c= HTEG8;\
+  else if (I==2) HTEG16(c);\
+  else if (I==3) HTEG24(c);\
+  else if (I==4) HTEG32(c);\
+  tail_append(new_character(f,c));\
+}
+/*:90*//*98:*/
+#line 1496 "hint.w"
+
+#define HTEG_RULE(I)\
+pointer p= new_rule();\
+if ((I)&b001) HTEG32(width(p)); else width(p)= null_flag;\
+if ((I)&b010) HTEG32(depth(p)); else depth(p)= null_flag;\
+if ((I)&b100) HTEG32(height(p)); else height(p)= null_flag;
+/*:98*//*105:*/
+#line 1562 "hint.w"
+
+#define HTEG_GLUE(I) \
+  p=  get_node(glue_spec_size); \
+  if(I==b111) width(p)= hget_xdimen_node();\
+  if((I)&b001) HTEG_STRETCH(shrink(p),shrink_order(p)) else shrink(p)= 0, shrink_order(p)= normal;\
+  if((I)&b010) HTEG_STRETCH(stretch(p),stretch_order(p)) else stretch(p)= 0, stretch_order(p)= normal;\
+  if((I)!=b111) { if ((I)&b100) HGET32(width(p)); else width(p)= 0; }
+/*:105*//*111:*/
+#line 1673 "hint.w"
+
+#define IS_LIST(X)  (KIND(X)==list_kind || \
+        KIND(X)==text_kind  || KIND(X)==param_kind)
+/*:111*//*116:*/
+#line 1839 "hint.w"
+
+#define HTEG_BOX(I) \
+p= new_null_box();\
+list_ptr(p)= hteg_list_pointer();\
+if ((I)&b100) {int8_t x= HTEG8; glue_order(p)= x&0xF;\
+   x= x>>4; glue_sign(p)= (x<0?shrinking:(x> 0?stretching:normal));\
+   glue_set(p)= hteg_float32(); }\
+if ((I)&b010) HTEG32(shift_amount(p));\
+HTEG32(width(p));\
+if ((I)&b001) HTEG32(depth(p));\
+HTEG32(height(p));\
+node_pos= hpos-hstart-1;
+/*:116*//*123:*/
+#line 1962 "hint.w"
+
+#define HTEG_SET(I) \
+  scaled x, st, sh; uint8_t sto, sho; \
+  p= new_null_box();\
+  list_ptr(p)= hteg_list_pointer();\
+  if ((I)&b100) x= hteg_xdimen_node(); else x= hget_xdimen_ref(HTEG8);\
+  HTEG_STRETCH(sh,sho);HTEG_STRETCH(st,sto);\
+  if ((I)&b010) HTEG32(shift_amount(p)); \
+  HTEG32(width(p));if ((I)&b001) HTEG32(depth(p));HTEG32(height(p)); \
+  node_pos= hpos-hstart-1;
+/*:123*//*129:*/
+#line 2106 "hint.w"
+
+#define HTEG_PACK(K,I) \
+{ pointer p; scaled x, s, d;  uint8_t m; \
+ p= hteg_list_pointer();\
+ if ((I)&b100) x= hteg_xdimen_node();  else x= hget_xdimen_ref(HTEG8);\
+ if (K==vpack_kind) HTEG32(d); \
+ if ((I)&b010) HTEG32(s);\
+ if ((I)&b001) m= additional; else m= exactly; \
+ node_pos= hpos-hstart-1;\
+ if (K==vpack_kind) p= vpackage(p,x,m,d); else p= hpack(p,x,m);\
+ hprepend_to_vlist(p);}
+/*:129*//*133:*/
+#line 2173 "hint.w"
+
+#define HTEG_KERN(I) \
+pointer p; scaled x; \
+if (((I)&b011)==0) x= hget_dimen_ref(HTEG8);\
+else if (((I)&b011)==1) x= hget_xdimen_ref(HTEG8);\
+else if (((I)&b011)==2) HTEG32(x);\
+else if (((I)&b011)==3) x= hteg_xdimen_node();\
+p= new_kern(x);\
+if ((I)&b100) subtype(p)= explicit;\
+tail_append(p);
+/*:133*//*137:*/
+#line 2222 "hint.w"
+
+#define HTEG_LEADERS(I) \
+{pointer p,q;\
+if (KIND(*(hpos-1))==rule_kind) q= hteg_rule_node(); \
+else if (KIND(*(hpos-1))==hbox_kind) q= hteg_hbox_node(); \
+else  q= hteg_vbox_node();\
+if ((I)&b100) p= hteg_glue_node(); else {p= spec2glue(zero_glue); incr(glue_ref_count(zero_glue));} \
+leader_ptr(p)= q;subtype(p)= a_leaders+((I)&b011)-1;\
+tail_append(p);}
+/*:137*//*141:*/
+#line 2265 "hint.w"
+
+#define HTEG_BASELINE(I) \
+  if((I)&b010) cur_ls= hteg_glue_spec(); else cur_ls= zero_glue; \
+  if((I)&b100) cur_bs= hteg_glue_spec(); else cur_bs= zero_glue; \
+  if((I)&b001) HTEG32(cur_lsl); else cur_lsl= 0; \
+  cur_list.bs_pos= hpos-1;
+/*:141*//*146:*/
+#line 2322 "hint.w"
+
+#define HTEG_LIG(I) \
+{pointer p,q;\
+if ((I)==7) q= hteg_list_pointer();\
+else {uint8_t *t= hpos; hpos= t-I; q= hget_text_list(I); hpos= t-I;}\
+if (q==null) QUIT("Ligature with empty list");\
+p= new_ligature(0, character(q), link(q)); tail_append(p);\
+link(q)= null; flush_node_list(q);\
+font(lig_char(p))= HTEG8;\
+}
+/*:146*//*150:*/
+#line 2373 "hint.w"
+
+#define HTEG_DISC(I)\
+  pointer p= new_disc(); \
+  if ((I)&b001) post_break(p)= hteg_list_pointer(); \
+  if ((I)&b010) pre_break(p)= hteg_list_pointer(); \
+  if ((I)&b100) {uint8_t r; r= HTEG8; set_replace_count(p,r); \
+                 if ((r&0x80)==0) set_auto_disc(p); }\
+  else  set_auto_disc(p);
+/*:150*//*173:*/
+#line 2932 "hint.w"
+
+#define HTEG_MATH(I) \
+{ param_def_t *q; pointer p= null, a= null;\
+if ((I)&b001) a= hteg_hbox_node();\
+p= hteg_list_pointer(); \
+if ((I)&b010) a= hteg_hbox_node(); \
+if ((I)&b100) q= hteg_param_list_node(); else q= hget_param_list_ref(HTEG8);\
+hset_param_list(q); hdisplay(p,a,((I)&b010)!=0); hrestore_param_list();\
+}
+/*:173*//*181:*/
+#line 3015 "hint.w"
+
+#define HTEG_TABLE(I) \
+if(I&b010) ; else ;\
+if ((I)&b001) ; else ;\
+hteg_list_pointer();   \
+hteg_list_pointer();  \
+if ((I)&b100) hteg_xdimen_node(); else hget_xdimen_ref(HTEG8);
+/*:181*//*186:*/
+#line 3113 "hint.w"
+
+#define HTEG_STREAM(I) \
+{pointer p= get_node(ins_node_size); type(p)= ins_node;\
+ ins_ptr(p)= hteg_list_pointer();\
+ if ((I)&b010) {param_def_t *q= hteg_param_list_node();  hset_stream_params(p,true,q);}\
+ else {param_def_t *q= hget_param_list_ref(HTEG8);  hset_stream_params(p,false,q);}\
+ subtype(p)= HTEG8;RNG("Stream",subtype(p),1,254);\
+ tail_append(p);}
+/*:186*//*190:*/
+#line 3147 "hint.w"
+
+#define HTEG_IMAGE(I) \
+{ pointer p;\
+  p= get_node(image_node_size);  type(p)= whatsit_node; subtype(p)= image_node;\
+  if (I&b001) {HTEG_STRETCH(image_shrink(p),image_shrink_order(p));\
+               HTEG_STRETCH(image_stretch(p),image_stretch_order(p)); }\
+  else { image_stretch(p)= image_shrink(p)= 0;image_stretch_order(p)= image_shrink_order(p)= normal;}\
+  if (I&b010) {HTEG32(image_height(p)); HTEG32(image_width(p)); } \
+  else image_width(p)= image_height(p)= 0;\
+  HTEG16(image_no(p));RNG("Section number",image_no(p),3,max_section_no);  \
+  tail_append(p);}
+/*:190*//*194:*/
+#line 3187 "hint.w"
+
+#define HTEG_LINK(I) \
+{ pointer p;\
+  p= get_node(link_node_size);  type(p)= whatsit_node;\
+  if (I&b010) subtype(p)= start_link_node; else subtype(p)= end_link_node;\
+  if (I&b001) HTEG16(label_ref(p)); else label_ref(p)= HTEG8; \
+  RNG("label",label_ref(p),0,max_ref[label_kind]);\
+  label_has_name(p)= 0;\
+  tail_append(p);}
+/*:194*/
+#line 7519 "hint.w"
+
+
+/*21:*/
+#line 366 "hint.w"
+
+typedef struct{pointer bs,ls;scaled lsl;}bs_t;
+/*:21*//*28:*/
+#line 476 "hint.w"
+
+typedef struct{
+char*n;
+uint16_t m,q;
+scaled s;
+pointer g;
+pointer h;
+pointer p[MAX_FONT_PARAMS+1];
+}font_def_t;
+extern font_def_t*font_def;
+/*:28*//*37:*/
+#line 581 "hint.w"
+
+typedef struct param_t{
+uint8_t n,k;
+int32_t v;
+}param_t;
+
+typedef struct param_def_t{
+struct param_def_t*next;
+param_t p;}param_def_t;
+/*:37*/
+#line 7521 "hint.w"
+
+
+
+/*2:*/
+#line 191 "hint.w"
+
+pointer*pointer_def[32]= {NULL};
+/*:2*//*6:*/
+#line 240 "hint.w"
+
+int32_t*integer_def;
+/*:6*//*10:*/
+#line 270 "hint.w"
+
+scaled*dimen_def;
+/*:10*//*14:*/
+#line 300 "hint.w"
+
+xdimen_t*xdimen_def;
+/*:14*//*22:*/
+#line 370 "hint.w"
+
+bs_t*baseline_def= NULL;
+/*:22*//*29:*/
+#line 488 "hint.w"
+
+font_def_t*font_def;
+/*:29*//*38:*/
+#line 593 "hint.w"
+
+param_def_t**param_def;
+/*:38*//*45:*/
+#line 733 "hint.w"
+
+typedef struct{
+uint8_t pg;
+uint32_t f,t;
+}range_def_t;
+range_def_t*range_def;
+/*:45*//*50:*/
+#line 790 "hint.w"
+
+stream_t*streams;
+/*:50*//*53:*/
+#line 804 "hint.w"
+
+typedef struct{
+xdimen_t x;
+int f;
+int p,n,r;
+pointer b,a;
+xdimen_t w;
+pointer g;
+pointer h;
+}stream_def_t;
+/*:53*//*57:*/
+#line 877 "hint.w"
+
+typedef struct{
+char*n;
+dimen_t d;
+pointer g;
+uint8_t p;
+uint32_t t;
+xdimen_t v,h;
+stream_def_t*s;
+}page_def_t;
+page_def_t*page_def;
+page_def_t*cur_page;
+/*:57*//*65:*/
+#line 1021 "hint.w"
+
+hint_outline_t*hint_outlines= NULL;
+int outline_no= -1;
+/*:65*//*162:*/
+#line 2762 "hint.w"
+
+static param_def_t*line_break_params= NULL;
+/*:162*//*205:*/
+#line 3487 "hint.w"
+
+static scaled page_height;
+static scaled top_so_far[8];
+/*:205*//*220:*/
+#line 3765 "hint.w"
+
+static uint32_t map[0x10000];
+/*:220*//*225:*/
+#line 3829 "hint.w"
+
+#define MAX_PAGE_POS (1<<3) 
+
+uint64_t page_loc[MAX_PAGE_POS];
+int cur_loc;
+static int lo_loc,hi_loc;
+/*:225*//*242:*/
+#line 4212 "hint.w"
+
+scaled hvsize,hhsize;
+/*:242*//*244:*/
+#line 4240 "hint.w"
+
+int page_v,page_h,offset_v,offset_h;
+/*:244*//*301:*/
+#line 5514 "hint.w"
+
+hint_link_t*hint_links= NULL;
+int max_link= -1;
+/*:301*//*358:*/
+#line 7207 "hint.w"
+
+jmp_buf error_exit;
+char herror_string[MAX_HERROR];
+/*:358*/
+#line 7524 "hint.w"
+
+/*3:*/
+#line 196 "hint.w"
+
+static void hget_font_def(uint8_t a,uint8_t n);
+static int32_t hget_integer_def(uint8_t a);
+static scaled hget_dimen_def(uint8_t a);
+static pointer hget_glue_def(uint8_t a);
+static void hget_baseline_def(uint8_t a,uint8_t n);
+static param_def_t*hget_param_list(uint8_t a);
+static void hget_range_def(uint8_t a,uint8_t pg);
+static void hget_page_def(uint8_t a,uint8_t n);
+static void hget_outline_or_label_def(info_t i,int n);
+static void hget_font_metrics();
+static pointer hget_definition(uint8_t a);
+/*:3*//*27:*/
+#line 457 "hint.w"
+
+static pointer hprepend_to_vlist(pointer b);
+/*:27*//*36:*/
+#line 569 "hint.w"
+
+static pointer hget_glue_spec(void);
+static pointer hget_disc_node(void);
+/*:36*//*104:*/
+#line 1558 "hint.w"
+
+static scaled hget_xdimen_node(void);
+/*:104*//*117:*/
+#line 1855 "hint.w"
+
+static pointer hget_list_pointer(void);
+static pointer hteg_list_pointer(void);
+/*:117*//*124:*/
+#line 1973 "hint.w"
+
+static scaled hget_xdimen_node(void);
+/*:124*/
+#line 7525 "hint.w"
+
+/*9:*/
+#line 253 "hint.w"
+
+static int32_t hget_integer_def(uint8_t a)
+{if(INFO(a)==1){int8_t n= HGET8;return n;}
+else if(INFO(a)==2){int16_t n;HGET16(n);return n;}
+else if(INFO(a)==4){int32_t n;HGET32(n);return n;}
+else TAGERR(a);
+return 0;
+}
+
+static int32_t hget_integer_ref(uint8_t n)
+{REF_RNG(int_kind,n);
+return integer_def[n];
+}
+/*:9*//*17:*/
+#line 311 "hint.w"
+
+static scaled xdimen(xdimen_t*x)
+{return round(x->w+(double)x->h*(double)hhsize+(double)x->v*(double)hvsize);
+}
+static scaled hget_xdimen_ref(uint8_t n)
+{REF_RNG(xdimen_kind,n);
+return xdimen(xdimen_def+n);
+}
+/*:17*//*19:*/
+#line 331 "hint.w"
+
+
+static pointer hget_glue_ref(uint8_t n)
+{REF_RNG(glue_kind,n);
+return pointer_def[glue_kind][n];
+}
+
+static pointer hget_glue_def(uint8_t a)
+{pointer p;
+if(INFO(a)==b000)
+{p= hget_glue_ref(HGET8);
+add_glue_ref(p);
+}
+else
+{HGET_GLUE(INFO(a));}
+return p;
+}
+
+pointer hget_param_glue(uint8_t n)
+{REF_RNG(glue_kind,n);
+return new_glue(pointer_def[glue_kind][n]);
+}
+/*:19*//*32:*/
+#line 501 "hint.w"
+
+static void hget_font_def(uint8_t a,uint8_t n)
+{char*t;
+font_def_t*f= font_def+n;
+HGET_STRING(t);f->n= strdup(t);
+DBG(DBGDEF,"Font %d: %s\n",n,t);
+HGET32(f->s);RNG("Font size",f->s,1,0x7fffffff);
+HGET16(f->m);RNG("Font metrics",f->m,3,max_section_no);
+HGET16(f->q);RNG("Font glyphs",f->q,3,max_section_no);
+f->g= hget_glue_spec();
+f->h= hget_disc_node();
+DBG(DBGDEF,"Start font parameters\n");
+while(KIND(*hpos)!=font_kind)
+{kind_t k;
+uint8_t n;
+/*74:*/
+#line 1161 "hint.w"
+
+uint8_t a,z;
+HGETTAG(a);
+/*:74*/
+#line 516 "hint.w"
+
+k= KIND(a);
+n= HGET8;
+DBG(DBGDEF,"Reading font parameter %d: %s\n",n,definition_name[k]);
+if(k!=penalty_kind&&k!=kern_kind&&k!=ligature_kind&&
+k!=disc_kind&&k!=glue_kind&&k!=language_kind&&k!=rule_kind&&k!=image_kind)
+QUIT("Font parameter %d has invalid type %s",n,content_name[n]);
+RNG("Font parameter",n,0,MAX_FONT_PARAMS);
+f->p[n]= hget_definition(a);
+/*75:*/
+#line 1166 "hint.w"
+
+HGETTAG(z);
+if(a!=z)
+QUIT("Tag mismatch [%s,%d]!=[%s,%d] at 0x%x to "SIZE_F"\n",
+NAME(a),INFO(a),NAME(z),INFO(z),node_pos,hpos-hstart-1);
+/*:75*/
+#line 525 "hint.w"
+
+}
+DBG(DBGDEF,"End font definition\n");
+}
+/*:32*//*33:*/
+#line 534 "hint.w"
+
+static void hget_font_metrics(void)
+{int i;
+for(i= 0;i<=max_ref[font_kind];i++)
+if(font_def[i].m!=0)
+{int s;
+hget_section(font_def[i].m);
+s= font_def[i].s;
+if(s==0)s= -1000;
+read_font_info(i,font_def[i].n,s);
+font_def[i].s= font_size[i];
+}
+}
+/*:33*//*41:*/
+#line 610 "hint.w"
+
+static void free_param_list(param_def_t*p)
+{while(p!=NULL)
+{param_def_t*q= p;
+p= p->next;
+free(q);
+}
+}
+/*:41*//*42:*/
+#line 622 "hint.w"
+
+static param_def_t*hget_param_list(uint8_t a)
+{uint32_t s,t;
+param_def_t*p= NULL;
+uint8_t*list_start,*list_end;
+list_start= hpos;
+s= hget_list_size(INFO(a));
+hget_size_boundary(INFO(a));
+list_end= hpos+s;
+if(list_end>=hend)
+QUIT("list end after before stream end\n");
+while(hpos<list_end)
+{param_def_t*r;param_t*q;
+/*74:*/
+#line 1161 "hint.w"
+
+uint8_t a,z;
+HGETTAG(a);
+/*:74*/
+#line 635 "hint.w"
+
+ALLOCATE(r,1,param_def_t);
+q= &(r->p);
+q->n= HGET8;
+q->k= KIND(a);
+DBG(DBGTAGS,"Defining %s %d\n",definition_name[KIND(a)],q->n);
+if(KIND(a)==int_kind)q->v= hget_integer_def(a);
+else if(KIND(a)==dimen_kind)q->v= hget_dimen_def(a);
+else if(KIND(a)==glue_kind)q->v= hget_glue_def(a);
+else TAGERR(a);
+/*75:*/
+#line 1166 "hint.w"
+
+HGETTAG(z);
+if(a!=z)
+QUIT("Tag mismatch [%s,%d]!=[%s,%d] at 0x%x to "SIZE_F"\n",
+NAME(a),INFO(a),NAME(z),INFO(z),node_pos,hpos-hstart-1);
+/*:75*/
+#line 645 "hint.w"
+
+r->next= p;
+p= r;
+}
+hget_size_boundary(INFO(a));
+t= hget_list_size(INFO(a));
+if(t!=s)
+QUIT("List sizes at "SIZE_F" and "SIZE_F" do not match 0x%x != 0x%x",list_start-hstart,list_end-hstart,s,t);
+return p;
+}
+
+param_def_t*hget_param_list_node(void)
+{if(KIND(*hpos)!=param_kind)return NULL;
+else
+{param_def_t*p;
+/*74:*/
+#line 1161 "hint.w"
+
+uint8_t a,z;
+HGETTAG(a);
+/*:74*/
+#line 660 "hint.w"
+
+p= hget_param_list(a);
+/*75:*/
+#line 1166 "hint.w"
+
+HGETTAG(z);
+if(a!=z)
+QUIT("Tag mismatch [%s,%d]!=[%s,%d] at 0x%x to "SIZE_F"\n",
+NAME(a),INFO(a),NAME(z),INFO(z),node_pos,hpos-hstart-1);
+/*:75*/
+#line 662 "hint.w"
+
+return p;
+}
+}
+
+param_def_t*hget_param_list_ref(uint8_t n)
+{REF_RNG(param_kind,n);
+return param_def[n];
+}
+/*:42*//*43:*/
+#line 684 "hint.w"
+
+#define MAX_SAVE 100
+#define SAVE_BOUNDARY 0xFF
+static param_t par_save[MAX_SAVE];
+static int par_save_ptr= 0;
+
+static void hset_param(uint8_t k,uint8_t n,int32_t v)
+{param_t*q;
+if(par_save_ptr>=MAX_SAVE)QUIT("Parameter save stack overflow");
+q= &(par_save[par_save_ptr++]);
+q->k= k;
+q->n= n;
+if(q->k==int_kind)
+{q->v= integer_def[q->n];integer_def[q->n]= v;}
+else if(q->k==dimen_kind)
+{q->v= dimen_def[q->n];dimen_def[q->n]= (scaled)v;}
+else if(q->k==glue_kind)
+{q->v= pointer_def[glue_kind][q->n];pointer_def[glue_kind][q->n]= (pointer)v;}
+}
+
+void hset_param_list(param_def_t*p)
+{hset_param(SAVE_BOUNDARY,0,0);
+while(p!=NULL)
+{hset_param(p->p.k,p->p.n,p->p.v);
+p= p->next;
+}
+}
+
+void hrestore_param_list(void)
+{
+while(par_save_ptr> 0)
+{param_t*q;
+q= &(par_save[--par_save_ptr]);
+if(q->k==SAVE_BOUNDARY)return;
+if(q->k==int_kind)
+{integer_def[q->n]= q->v;}
+else if(q->k==dimen_kind)
+{dimen_def[q->n]= (scaled)q->v;}
+else if(q->k==glue_kind)
+{pointer_def[glue_kind][q->n]= (pointer)q->v;}
+}
+QUIT("Parameter save stack flow");
+}
+/*:43*//*48:*/
+#line 748 "hint.w"
+
+static void hget_range_def(uint8_t a,uint8_t pg)
+{static uint8_t n= 0;
+uint32_t f,t;
+REF_RNG(page_kind,pg);
+REF_RNG(range_kind,n);
+if(INFO(a)&b100)
+{if(INFO(a)&b001)HGET32(f);else HGET16(f);}
+else f= 0;
+if(INFO(a)&b010)
+{if(INFO(a)&b001)HGET32(t);else HGET16(t);}
+else t= HINT_NO_POS;
+range_def[n].pg= pg;
+range_def[n].f= f;
+range_def[n].t= t;
+DBG(DBGRANGE,"Range *%d from 0x%x\n",pg,f);
+DBG(DBGRANGE,"Range *%d to 0x%x\n",pg,t);
+n++;
+}
+#if 0
+
+static uint8_t hget_page_ref(uint32_t pos)
+{int i;
+for(i= 1;i<=max_ref[range_kind];i++)
+if(range_def[i].f<=pos&&pos<range_def[i].t)return range_def[i].pg;
+return 0;
+}
+#endif
+/*:48*//*54:*/
+#line 821 "hint.w"
+
+static void hget_xdimen_def_node(xdimen_t*x);
+
+static bool hget_stream_def(stream_def_t*s)
+{if(KIND(*hpos)!=stream_kind||!(INFO(*hpos)&b100))
+return false;
+else
+{uint8_t n;
+/*74:*/
+#line 1161 "hint.w"
+
+uint8_t a,z;
+HGETTAG(a);
+/*:74*/
+#line 829 "hint.w"
+
+DBG(DBGDEF,"Defining stream %d at "SIZE_F"\n",*hpos,hpos-hstart-1);
+n= HGET8;REF_RNG(stream_kind,n);
+s= s+n;
+if(n> 0)
+{if(INFO(a)==b100)/*55:*/
+#line 852 "hint.w"
+
+{DBG(DBGDEF,"Defining normal stream %d at "SIZE_F"\n",*(hpos-1),hpos-hstart-2);
+hget_xdimen_def_node(&(s->x));
+HGET16(s->f);RNG("magnification factor",s->f,0,1000);
+s->p= HGET8;if(s->p!=255)REF_RNG(stream_kind,s->p);
+s->n= HGET8;if(s->n!=255)REF_RNG(stream_kind,s->n);
+HGET16(s->r);RNG("split ratio",s->r,0,1000);
+}
+/*:55*/
+#line 834 "hint.w"
+
+else if(INFO(a)==b101)QUIT("first stream not yet implemented");
+else if(INFO(a)==b110)QUIT("last stream not yet implemented");
+else if(INFO(a)==b111)QUIT("top stream not yet implemented");
+s->b= hget_list_pointer();
+hget_xdimen_def_node(&(s->w));
+s->g= hget_glue_spec();
+s->a= hget_list_pointer();
+s->h= hget_glue_spec();
+}
+/*75:*/
+#line 1166 "hint.w"
+
+HGETTAG(z);
+if(a!=z)
+QUIT("Tag mismatch [%s,%d]!=[%s,%d] at 0x%x to "SIZE_F"\n",
+NAME(a),INFO(a),NAME(z),INFO(z),node_pos,hpos-hstart-1);
+/*:75*/
+#line 844 "hint.w"
+
+return true;
+}
+}
+/*:54*//*61:*/
+#line 921 "hint.w"
+
+
+static void hset_cur_page(void)
+{int i;
+cur_page= &(page_def[0]);
+for(i= 1;i<=max_ref[page_kind];i++)
+if(page_def[i].p>=cur_page->p)
+cur_page= &(page_def[i]);
+}
+
+static void hskip_list(void);
+static void hget_page_def(uint8_t a,uint8_t i)
+{char*n;
+cur_page= &(page_def[i]);
+ALLOCATE(cur_page->s,max_ref[stream_kind]+1,stream_def_t);
+HGET_STRING(n);cur_page->n= strdup(n);
+cur_page->p= HGET8;
+cur_page->g= hget_glue_spec();
+HGET32(cur_page->d);
+hget_xdimen_def_node(&(cur_page->v));
+hget_xdimen_def_node(&(cur_page->h));
+cur_page->t= hpos-hstart;
+hskip_list();
+while(hget_stream_def(cur_page->s))continue;
+}
+/*:61*//*72:*/
+#line 1097 "hint.w"
+
+static pointer hget_ligature_ref(uint8_t n)
+{REF_RNG(ligature_kind,n);
+return copy_node_list(pointer_def[ligature_kind][n]);
+}
+
+static pointer hget_rule_ref(uint8_t n)
+{REF_RNG(rule_kind,n);
+return copy_node_list(pointer_def[rule_kind][n]);
+}
+
+static pointer hget_image_ref(uint16_t n)
+{REF_RNG(image_kind,n);
+return copy_node_list(pointer_def[image_kind][n]);
+}
+
+static pointer hget_hyphen_ref(uint8_t n)
+{REF_RNG(disc_kind,n);
+return copy_node_list(pointer_def[disc_kind][n]);
+}
+
+static pointer hget_leaders_ref(uint8_t n)
+{REF_RNG(leaders_kind,n);
+return copy_node_list(pointer_def[leaders_kind][n]);
+}
+
+
+
+
+/*:72*//*85:*/
+#line 1306 "hint.w"
+
+
+static void hget_xdimen_def(info_t i,xdimen_t*x)
+{switch(i)
+{
+case b000:
+{int n= HGET8;
+REF_RNG(xdimen_kind,n);
+x->w= xdimen_def[n].w;
+x->h= xdimen_def[n].h;
+x->v= xdimen_def[n].v;
+break;
+}
+case b001:HGET_XDIMEN(b001,*x);break;
+case b010:HGET_XDIMEN(b010,*x);break;
+case b011:HGET_XDIMEN(b011,*x);break;
+case b100:HGET_XDIMEN(b100,*x);break;
+case b101:HGET_XDIMEN(b101,*x);break;
+case b110:HGET_XDIMEN(b110,*x);break;
+case b111:HGET_XDIMEN(b111,*x);break;
+default:
+x->w= 0;x->h= x->v= 0.0;
+}
+}
+static scaled hget_xdimen(info_t i)
+{xdimen_t x;
+hget_xdimen_def(i,&x);
+return xdimen(&x);
+}
+
+static scaled hget_xdimen_node(void)
+{scaled x= 0;
+/*74:*/
+#line 1161 "hint.w"
+
+uint8_t a,z;
+HGETTAG(a);
+/*:74*/
+#line 1338 "hint.w"
+
+if(KIND(a)==xdimen_kind)
+x= hget_xdimen(INFO(a));
+else
+QUIT("Extent expected at 0x%x got %s",node_pos,NAME(a));
+/*75:*/
+#line 1166 "hint.w"
+
+HGETTAG(z);
+if(a!=z)
+QUIT("Tag mismatch [%s,%d]!=[%s,%d] at 0x%x to "SIZE_F"\n",
+NAME(a),INFO(a),NAME(z),INFO(z),node_pos,hpos-hstart-1);
+/*:75*/
+#line 1343 "hint.w"
+
+return x;
+}
+
+static void hget_xdimen_def_node(xdimen_t*x)
+{/*74:*/
+#line 1161 "hint.w"
+
+uint8_t a,z;
+HGETTAG(a);
+/*:74*/
+#line 1348 "hint.w"
+
+if(KIND(a)==xdimen_kind)
+hget_xdimen_def(INFO(a),x);
+else
+QUIT("Extent expected at 0x%x got %s",node_pos,NAME(a));
+/*75:*/
+#line 1166 "hint.w"
+
+HGETTAG(z);
+if(a!=z)
+QUIT("Tag mismatch [%s,%d]!=[%s,%d] at 0x%x to "SIZE_F"\n",
+NAME(a),INFO(a),NAME(z),INFO(z),node_pos,hpos-hstart-1);
+/*:75*/
+#line 1353 "hint.w"
+
+}
+
+
+/*:85*//*86:*/
+#line 1359 "hint.w"
+
+scaled hteg_xdimen(uint8_t a)
+{xdimen_t x;
+switch(a)
+{
+case TAG(xdimen_kind,b000):return hget_xdimen_ref(HTEG8);
+case TAG(xdimen_kind,b001):HTEG_XDIMEN(b001,x);break;
+case TAG(xdimen_kind,b010):HTEG_XDIMEN(b010,x);break;
+case TAG(xdimen_kind,b011):HTEG_XDIMEN(b011,x);break;
+case TAG(xdimen_kind,b100):HTEG_XDIMEN(b100,x);break;
+case TAG(xdimen_kind,b101):HTEG_XDIMEN(b101,x);break;
+case TAG(xdimen_kind,b110):HTEG_XDIMEN(b110,x);break;
+case TAG(xdimen_kind,b111):HTEG_XDIMEN(b111,x);break;
+default:
+x.w= 0;x.h= x.v= 0.0;
+QUIT("Extent expected got [%s,%d]",NAME(a),INFO(a));
+}
+return xdimen(&x);
+}
+
+scaled hteg_xdimen_node(void)
+{scaled x= 0;
+/*78:*/
+#line 1222 "hint.w"
+
+uint8_t a,z;
+z= HTEG8,DBGTAG(z,hpos);
+/*:78*/
+#line 1381 "hint.w"
+
+if(KIND(z)==xdimen_kind)
+x= hteg_xdimen(z);
+else
+QUIT("Extent expected at 0x%x got %s",node_pos,NAME(z));
+/*79:*/
+#line 1227 "hint.w"
+
+a= HTEG8,DBGTAG(a,hpos);
+if(z!=a)
+QUIT("Tag mismatch [%s,%d]!=[%s,%d] at "SIZE_F" to 0x%x\n",
+NAME(a),INFO(a),NAME(z),INFO(z),hpos-hstart,node_pos);
+
+/*:79*/
+#line 1386 "hint.w"
+
+return x;
+}
+/*:86*//*102:*/
+#line 1534 "hint.w"
+
+static pointer hteg_rule_node(void)
+{pointer q= null;
+/*78:*/
+#line 1222 "hint.w"
+
+uint8_t a,z;
+z= HTEG8,DBGTAG(z,hpos);
+/*:78*/
+#line 1537 "hint.w"
+
+if(KIND(z)==rule_kind){HTEG_RULE(INFO(z));q= p;}
+else QUIT("Rule expected at 0x%x got %s",node_pos,NAME(z));
+/*79:*/
+#line 1227 "hint.w"
+
+a= HTEG8,DBGTAG(a,hpos);
+if(z!=a)
+QUIT("Tag mismatch [%s,%d]!=[%s,%d] at "SIZE_F" to 0x%x\n",
+NAME(a),INFO(a),NAME(z),INFO(z),hpos-hstart,node_pos);
+
+/*:79*/
+#line 1540 "hint.w"
+
+return q;
+}
+/*:102*//*108:*/
+#line 1603 "hint.w"
+
+static pointer hget_glue_spec(void)
+{pointer p= null;
+uint8_t a,z;
+if(hpos>=hend||KIND(*hpos)!=glue_kind)
+{p= zero_glue;incr(glue_ref_count(p));}
+else
+{node_pos= hpos-hstart;
+HGETTAG(a);
+if(INFO(a)==b000)
+{p= hget_glue_ref(HGET8);incr(glue_ref_count(p));}
+else
+{HGET_GLUE(INFO(a));}
+/*75:*/
+#line 1166 "hint.w"
+
+HGETTAG(z);
+if(a!=z)
+QUIT("Tag mismatch [%s,%d]!=[%s,%d] at 0x%x to "SIZE_F"\n",
+NAME(a),INFO(a),NAME(z),INFO(z),node_pos,hpos-hstart-1);
+/*:75*/
+#line 1616 "hint.w"
+
+}
+return p;
+}
+
+static pointer spec2glue(pointer q)
+{pointer p;
+p= get_node(small_node_size);type(p)= glue_node;subtype(p)= normal;
+leader_ptr(p)= null;glue_ptr(p)= q;
+return p;
+}
+
+static pointer hget_glue_node(void)
+{return spec2glue(hget_glue_spec());
+}
+/*:108*//*109:*/
+#line 1633 "hint.w"
+
+static pointer hteg_glue_spec(void)
+{pointer p= null;
+uint8_t a,z;
+if(hpos<=hstart)return null;
+if(KIND(*(hpos-1))!=glue_kind)return null;
+z= HTEG8,DBGTAG(z,hpos);
+if(INFO(z)==b000)p= hget_glue_ref(HTEG8);
+else
+{HTEG_GLUE(INFO(z));}
+/*79:*/
+#line 1227 "hint.w"
+
+a= HTEG8,DBGTAG(a,hpos);
+if(z!=a)
+QUIT("Tag mismatch [%s,%d]!=[%s,%d] at "SIZE_F" to 0x%x\n",
+NAME(a),INFO(a),NAME(z),INFO(z),hpos-hstart,node_pos);
+
+/*:79*/
+#line 1643 "hint.w"
+
+return p;
+}
+
+
+static pointer hteg_glue_node(void)
+{pointer p= hteg_glue_spec();
+if(p!=null)return spec2glue(p);
+else return new_glue(zero_glue);
+}
+/*:109*//*112:*/
+#line 1678 "hint.w"
+
+static pointer hget_node_list(uint32_t s)
+{uint8_t*list_end= hpos+s;
+pointer p;
+push_nest();
+cur_list.bs_pos= NULL;
+while(hpos<list_end)
+hget_content();
+if(needs_bs)
+QUIT("Unexpected trailing baseline node");
+p= link(head);
+pop_nest();
+return p;
+}
+
+static pointer hget_text_list(uint32_t s);
+static pointer hget_list_pointer(void)
+{if(!IS_LIST(*hpos))return null;
+else
+{pointer p= null;
+uint32_t s,t;
+/*74:*/
+#line 1161 "hint.w"
+
+uint8_t a,z;
+HGETTAG(a);
+/*:74*/
+#line 1699 "hint.w"
+
+s= hget_list_size(INFO(a));
+hget_size_boundary(INFO(a));
+if(KIND(a)==list_kind)
+p= hget_node_list(s);
+else if(KIND(a)==text_kind)
+p= hget_text_list(s);
+hget_size_boundary(INFO(a));
+t= hget_list_size(INFO(a));
+if(t!=s)
+QUIT("List sizes at 0x%x and "SIZE_F" do not match 0x%x != 0x%x",node_pos+1,hpos-hstart-s-1,s,t);
+/*75:*/
+#line 1166 "hint.w"
+
+HGETTAG(z);
+if(a!=z)
+QUIT("Tag mismatch [%s,%d]!=[%s,%d] at 0x%x to "SIZE_F"\n",
+NAME(a),INFO(a),NAME(z),INFO(z),node_pos,hpos-hstart-1);
+/*:75*/
+#line 1710 "hint.w"
+
+return p;
+}
+}
+/*:112*//*113:*/
+#line 1720 "hint.w"
+
+
+static void hskip_list()
+{if(IS_LIST(*hpos))
+{uint32_t s;
+uint8_t a;
+HGETTAG(a);
+s= hget_list_size(INFO(a));
+if(s> 0)
+hpos= hpos+(1+s+1+(INFO(a)-1)+1);
+else
+hpos= hpos+1;
+}
+}
+
+static void hskip_list_back()
+{uint8_t z;
+uint32_t s;
+if(!IS_LIST(*(hpos-1)))return;
+z= HTEG8;
+s= hteg_list_size(INFO(z));
+if(s> 0)
+hpos= hpos-(1+s+1+(INFO(z)-1)+1);
+else
+hpos= hpos-1;
+}
+
+pointer hteg_list_pointer(void)
+{uint8_t*list_start;
+pointer p;
+hskip_list_back();
+list_start= hpos;
+p= hget_list_pointer();
+hpos= list_start;
+return p;
+}
+/*:113*//*114:*/
+#line 1765 "hint.w"
+
+#if 0
+static int32_t hteg_integer_def(uint8_t z)
+{if(INFO(z)==1){int8_t n= HTEG8;return n;}
+else if(INFO(z)==2){int16_t n;HTEG16(n);return n;}
+else if(INFO(z)==4){int32_t n;HTEG32(n);return n;}
+else TAGERR(z);
+return 0;
+}
+
+static param_def_t*hteg_param_list(uint8_t z)
+{uint32_t s,t;
+param_def_t*p= NULL;
+uint8_t*list_start,*list_end;
+list_end= hpos;
+s= hteg_list_size(INFO(z));
+hteg_size_boundary(INFO(z));
+list_start= hpos-s;
+if(list_start<=hstart)
+QUIT("list start before stream start\n");
+while(list_start<hpos)
+{param_def_t*r;param_t*q;
+/*78:*/
+#line 1222 "hint.w"
+
+uint8_t a,z;
+z= HTEG8,DBGTAG(z,hpos);
+/*:78*/
+#line 1787 "hint.w"
+
+ALLOCATE(r,1,param_def_t);
+q= &(r->p);
+q->k= KIND(z);
+if(KIND(z)==int_kind)q->i= hteg_integer_def(a);
+else if(KIND(a)==dimen_kind)HTEG32(q->d);
+else if(KIND(a)==glue_kind){pointer p;HTEG_GLUE(INFO(z));q->g= p;}
+else TAGERR(a);
+q->n= HTEG8;
+DBG(DBGTAGS,"Defining %s %d\n",definition_name[KIND(z)],q->n);
+/*79:*/
+#line 1227 "hint.w"
+
+a= HTEG8,DBGTAG(a,hpos);
+if(z!=a)
+QUIT("Tag mismatch [%s,%d]!=[%s,%d] at "SIZE_F" to 0x%x\n",
+NAME(a),INFO(a),NAME(z),INFO(z),hpos-hstart,node_pos);
+
+/*:79*/
+#line 1797 "hint.w"
+
+r->next= p;
+p= r;
+}
+hteg_size_boundary(INFO(z));
+t= hteg_list_size(INFO(z));
+if(t!=s)
+QUIT("List sizes at "SIZE_F" and "SIZE_F" do not match 0x%x != 0x%x",list_start-hstart,list_end-hstart,s,t);
+return p;
+}
+#endif
+
+static param_def_t*hteg_param_list_node(void)
+{param_def_t*p;
+uint8_t*list_start;
+hskip_list_back();
+list_start= hpos;
+p= hget_param_list_node();
+hpos= list_start;
+return p;
+}
+/*:114*//*121:*/
+#line 1924 "hint.w"
+
+static pointer hteg_hbox_node(void)
+{/*78:*/
+#line 1222 "hint.w"
+
+uint8_t a,z;
+z= HTEG8,DBGTAG(z,hpos);
+/*:78*/
+#line 1926 "hint.w"
+
+if(KIND(z)!=hbox_kind)QUIT("Hbox expected at 0x%x got %s",node_pos,NAME(z));
+{pointer p;
+HTEG_BOX(INFO(z));
+/*79:*/
+#line 1227 "hint.w"
+
+a= HTEG8,DBGTAG(a,hpos);
+if(z!=a)
+QUIT("Tag mismatch [%s,%d]!=[%s,%d] at "SIZE_F" to 0x%x\n",
+NAME(a),INFO(a),NAME(z),INFO(z),hpos-hstart,node_pos);
+
+/*:79*/
+#line 1930 "hint.w"
+
+return p;
+}
+}
+static pointer hteg_vbox_node(void)
+{/*78:*/
+#line 1222 "hint.w"
+
+uint8_t a,z;
+z= HTEG8,DBGTAG(z,hpos);
+/*:78*/
+#line 1935 "hint.w"
+
+if(KIND(z)!=vbox_kind)QUIT("Vbox expected at 0x%x got %s",node_pos,NAME(z));
+{pointer p;
+HTEG_BOX(INFO(z));
+/*79:*/
+#line 1227 "hint.w"
+
+a= HTEG8,DBGTAG(a,hpos);
+if(z!=a)
+QUIT("Tag mismatch [%s,%d]!=[%s,%d] at "SIZE_F" to 0x%x\n",
+NAME(a),INFO(a),NAME(z),INFO(z),hpos-hstart,node_pos);
+
+/*:79*/
+#line 1939 "hint.w"
+
+type(p)= vlist_node;
+return p;
+}
+}
+
+/*:121*//*127:*/
+#line 2021 "hint.w"
+
+static void hset(pointer p,
+uint8_t sto,scaled st,uint8_t sho,scaled sh,scaled w)
+{scaled x;
+x= width(p);
+width(p)= w;
+
+x= w-x;
+if(x==0)
+{glue_sign(p)= normal;glue_order(p)= normal;
+glue_set(p)= 0.0;
+}
+else if(x> 0)
+{glue_order(p)= sto;glue_sign(p)= stretching;
+if(st!=0)
+glue_set(p)= (float32_t)(x/(double)st);
+else
+{glue_sign(p)= normal;
+glue_set(p)= 0.0;
+}
+}
+else
+{glue_order(p)= sho;glue_sign(p)= shrinking;
+if(sh!=0)
+glue_set(p)= (float32_t)((-x)/(double)sh);
+else
+{glue_sign(p)= normal;
+glue_set(p)= 0.0;
+}
+if((sh<-x)&&(sho==normal)&&(list_ptr(p)!=null))
+glue_set(p)= 1.0;
+}
+}
+
+
+
+
+void vset(pointer p,uint8_t sto,scaled st,
+uint8_t sho,scaled sh,scaled h)
+{scaled x;
+type(p)= vlist_node;
+x= height(p);
+height(p)= h;
+x= h-x;
+if(x==0)
+{glue_sign(p)= normal;glue_order(p)= normal;
+glue_set(p)= 0.0;
+}
+else if(x> 0)
+{glue_order(p)= sto;glue_sign(p)= stretching;
+if(st!=0)
+glue_set(p)= (float32_t)(x/(double)st);
+else
+{glue_sign(p)= normal;
+glue_set(p)= 0.0;
+}
+}
+else
+{glue_order(p)= sho;glue_sign(p)= shrinking;
+if(sh!=0)
+glue_set(p)= (float32_t)((-x)/(double)sh);
+else
+{glue_sign(p)= normal;
+glue_set(p)= 0.0;
+}
+}
+}
+/*:127*//*144:*/
+#line 2300 "hint.w"
+
+static pointer hget_text_list(uint32_t s)
+{pointer p= null;
+pointer*pp= &p;
+uint8_t*t= hpos+s;
+while(hpos<t){*pp= new_character(0,hget_utf8());pp= &link(*pp);}
+return p;
+}
+/*:144*//*153:*/
+#line 2407 "hint.w"
+
+static pointer hget_disc_node(void)
+{/*74:*/
+#line 1161 "hint.w"
+
+uint8_t a,z;
+HGETTAG(a);
+/*:74*/
+#line 2409 "hint.w"
+
+if(KIND(a)!=disc_kind||INFO(a)==b000)
+QUIT("Hyphen expected at 0x%x got %s,%d",node_pos,NAME(a),INFO(a));
+{
+HGET_DISC(INFO(a));
+/*75:*/
+#line 1166 "hint.w"
+
+HGETTAG(z);
+if(a!=z)
+QUIT("Tag mismatch [%s,%d]!=[%s,%d] at 0x%x to "SIZE_F"\n",
+NAME(a),INFO(a),NAME(z),INFO(z),node_pos,hpos-hstart-1);
+/*:75*/
+#line 2414 "hint.w"
+
+return p;
+}
+}
+/*:153*//*157:*/
+#line 2482 "hint.w"
+
+static void transplant_post_break_list(void)
+{pointer r,q= link(head);
+int t= replace_count(q);
+pointer s= post_break(q);
+r= q;
+while(t> 0&&r!=null){r= link(r);t--;}
+if(s!=null)
+{while(link(s)!=null)s= link(s);
+link(s)= link(r);link(r)= post_break(q);post_break(q)= null;
+}
+q= link(r);
+if(r!=head)
+{link(r)= null;flush_node_list(link(head));
+link(head)= q;
+}
+}
+static void transplant_pre_break_list(void)
+{pointer q= tail;
+set_replace_count(q,0);
+link(q)= pre_break(q);
+pre_break(q)= null;
+while(link(q)!=null)q= link(q);
+tail= q;
+}
+
+
+static void hprune_unwanted_nodes(void)
+{pointer q,r= head;
+while(true){q= link(r);
+if(q==null)goto done;
+if(is_char_node(q))goto done;
+if(non_discardable(q))goto done;
+if(type(q)==kern_node&&subtype(q)!=explicit)goto done;
+r= q;
+}
+done:if(r!=head)
+{link(r)= null;flush_node_list(link(head));
+link(head)= q;
+}
+}
+/*:157*//*158:*/
+#line 2549 "hint.w"
+
+pointer hget_paragraph_all(scaled x)
+{
+uint32_t s,t;
+uint8_t a,z;
+if(!IS_LIST(*hpos))return null;
+HGETTAG(a);
+s= hget_list_size(INFO(a));
+hget_size_boundary(INFO(a));
+if(KIND(a)==list_kind)
+{uint8_t*list_end= hpos+s;
+cur_list.hs_field= x;
+push_nest();
+cur_list.bs_pos= NULL;
+#if 0
+if(offset> 0)hpos= hstart+node_pos1+offset;
+#endif
+while(hpos<list_end)
+{hget_content();
+if(nest_ptr==1)
+{pointer p= tail;
+if(p!=head&&!is_char_node(p)&&
+(type(p)==glue_node||type(p)==kern_node||type(p)==penalty_node
+||type(p)==disc_node||type(p)==math_node))
+store_map(p,node_pos,0);
+
+}
+}
+hget_size_boundary(INFO(a));
+t= hget_list_size(INFO(a));
+if(t!=s)
+QUIT("List sizes at 0x%x and "SIZE_F" do not match 0x%x != 0x%x",node_pos+1,hpos-hstart-s-1,s,t);
+/*75:*/
+#line 1166 "hint.w"
+
+HGETTAG(z);
+if(a!=z)
+QUIT("Tag mismatch [%s,%d]!=[%s,%d] at 0x%x to "SIZE_F"\n",
+NAME(a),INFO(a),NAME(z),INFO(z),node_pos,hpos-hstart-1);
+/*:75*/
+#line 2581 "hint.w"
+
+#if 0
+if(offset> 0&&link(head)!=null&&!is_char_node(link(head)))
+{if(type(link(head))==disc_node)
+transplant_post_break_list();
+else
+hprune_unwanted_nodes();
+}
+#endif
+if(needs_bs)
+QUIT("Unexpected trailing baseline node");
+if(head==tail)
+{pop_nest();
+return null;
+}
+else
+{pointer par_ptr= link(head);
+pop_nest();
+store_map(par_ptr,node_pos,0);
+return par_ptr;
+}
+}
+else
+QUIT("Text in paragraph not yet implemented");
+return null;
+}
+/*:158*//*159:*/
+#line 2612 "hint.w"
+
+pointer hget_paragraph_final(scaled x,uint8_t*from)
+{
+uint32_t s,t;
+uint8_t a,z;
+if(!IS_LIST(*hpos))return null;
+HGETTAG(a);
+s= hget_list_size(INFO(a));
+hget_size_boundary(INFO(a));
+if(KIND(a)==list_kind)
+{uint8_t*list_end= hpos+s;
+cur_list.hs_field= x;
+push_nest();
+cur_list.bs_pos= NULL;
+hpos= from;
+while(hpos<list_end)
+{hget_content();
+if(nest_ptr==1)
+{pointer p= tail;
+if(p!=head&&!is_char_node(p)&&
+(type(p)==glue_node||type(p)==kern_node||type(p)==penalty_node||type(p)==disc_node||type(p)==math_node))
+store_map(p,node_pos,0);
+}
+}
+hget_size_boundary(INFO(a));
+t= hget_list_size(INFO(a));
+if(t!=s)
+QUIT("List sizes at 0x%x and "SIZE_F" do not match 0x%x != 0x%x",node_pos+1,hpos-hstart-s-1,s,t);
+/*75:*/
+#line 1166 "hint.w"
+
+HGETTAG(z);
+if(a!=z)
+QUIT("Tag mismatch [%s,%d]!=[%s,%d] at 0x%x to "SIZE_F"\n",
+NAME(a),INFO(a),NAME(z),INFO(z),node_pos,hpos-hstart-1);
+/*:75*/
+#line 2640 "hint.w"
+
+if(link(head)!=null&&!is_char_node(link(head)))
+{if(type(link(head))==disc_node)
+transplant_post_break_list();
+else
+hprune_unwanted_nodes();
+}
+if(needs_bs)
+QUIT("Unexpected trailing baseline node");
+if(head==tail)
+{pop_nest();
+return null;
+}
+else
+{pointer par_ptr= link(head);
+pop_nest();
+store_map(par_ptr,node_pos,0);
+return par_ptr;
+}
+}
+else
+QUIT("Text in paragraph not yet implemented");
+return null;
+}
+/*:159*//*165:*/
+#line 2779 "hint.w"
+
+pointer hget_paragraph(scaled x,uint32_t offset,param_def_t*q)
+{
+pointer p,par_head;
+param_def_t*save_lbp= line_break_params;
+par_head= tail;
+line_break_params= q;
+if(offset==0)
+{prev_graf= 0;
+p= hget_paragraph_all(x);
+}
+else
+{prev_graf= 3;
+p= hget_paragraph_final(x,hstart+node_pos+offset);
+}
+if(p!=null)
+line_break(hget_integer_ref(widow_penalty_no),p);
+line_break_params= save_lbp;
+return par_head;
+}
+
+void hget_par_node(uint32_t offset)
+{scaled x= 0;
+param_def_t*q;
+/*74:*/
+#line 1161 "hint.w"
+
+uint8_t a,z;
+HGETTAG(a);
+/*:74*/
+#line 2803 "hint.w"
+
+if(KIND(a)!=par_kind)
+QUIT("Paragrap expected found tag [%s,%d] at "SIZE_F"\n",NAME(a),INFO(a),hpos-hstart);
+node_pos= (hpos-hstart)-1;
+if(INFO(a)==b100)q= hget_param_list_ref(HGET8);
+if(INFO(a)&b100)x= hget_xdimen_node();else x= hget_xdimen_ref(HGET8);
+if(INFO(a)&b010)q= hget_param_list_node();else q= hget_param_list_ref(HGET8);
+hget_paragraph(x,offset,q);
+/*75:*/
+#line 1166 "hint.w"
+
+HGETTAG(z);
+if(a!=z)
+QUIT("Tag mismatch [%s,%d]!=[%s,%d] at 0x%x to "SIZE_F"\n",
+NAME(a),INFO(a),NAME(z),INFO(z),node_pos,hpos-hstart-1);
+/*:75*/
+#line 2811 "hint.w"
+
+}
+/*:165*//*168:*/
+#line 2833 "hint.w"
+
+void hteg_paragraph(info_t i)
+{scaled x= 0;
+param_def_t*q= null;
+pointer par_head;
+uint8_t*bs_pos= cur_list.bs_pos;
+scaled ph= prev_height;
+uint8_t*list_start,*par_start;
+hskip_list_back();
+list_start= hpos;
+if(INFO(i)&b010)q= hteg_param_list_node();
+else if(INFO(i)!=b100)q= hget_param_list_ref(HTEG8);
+if(INFO(i)&b100)x= hteg_xdimen_node();else x= hget_xdimen_ref(HTEG8);
+if(INFO(i)==b100)q= hget_param_list_ref(HTEG8);
+par_start= hpos;
+node_pos= par_start-hstart-1;
+hpos= list_start;
+cur_list.bs_pos= NULL;
+par_head= hget_paragraph(x,0,q);
+/*169:*/
+#line 2865 "hint.w"
+
+{pointer p,r,par_tail;
+p= null;
+r= par_tail= link(par_head);
+
+tail= par_head;
+link(tail)= null;
+while(r!=null)
+{pointer q= link(r);
+link(r)= p;
+p= r;
+r= q;
+}
+cur_list.bs_pos= bs_pos;
+prev_height= ph;
+hprepend_to_vlist(p);
+tail= par_tail;
+if(type(tail)==hlist_node||type(tail)==vlist_node)
+prev_height= height(tail);
+}
+/*:169*/
+#line 2852 "hint.w"
+
+hpos= par_start;
+}
+/*:168*//*184:*/
+#line 3080 "hint.w"
+
+static void hset_stream_params(pointer p,bool f,param_def_t*q)
+{param_def_t*r;
+pointer s;
+while(q!=null)
+{r= q;
+if(q->p.k==int_kind&&q->p.n==floating_penalty_no)float_cost(p)= q->p.v;
+else if(q->p.k==dimen_kind&&q->p.n==split_max_depth_no)depth(p)= (scaled)q->p.v;
+else if(q->p.k==glue_kind&&q->p.n==split_top_skip_no)
+{split_top_ptr(p)= (pointer)q->p.v;if(!f)add_glue_ref(split_top_ptr(p));}
+else QUIT("Unexpected parameter in stream");
+q= q->next;
+if(f)free(r);
+}
+s= vpack(ins_ptr(p),natural);
+height(p)= height(s)+depth(s);
+ins_ptr(p)= list_ptr(s);
+list_ptr(s)= null;flush_node_list(s);
+}
+/*:184*//*224:*/
+#line 3807 "hint.w"
+
+
+uint64_t hlocation(pointer p)
+{return PAGE_LOC(map[p],map[p+1]);
+}
+/*:224*//*227:*/
+#line 3853 "hint.w"
+
+#define NEXT_PAGE(X) (X= (X+1)&(MAX_PAGE_POS-1))
+#define PREV_PAGE(X) (X= (X-1)&(MAX_PAGE_POS-1))
+
+void hloc_clear(void)
+{lo_loc= hi_loc= cur_loc;PREV_PAGE(lo_loc);NEXT_PAGE(hi_loc);
+}
+
+bool hloc_next(void)
+{int i= cur_loc;
+if(LOC_POS(page_loc[cur_loc])>=hend-hstart)
+return false;
+NEXT_PAGE(i);
+if(i==hi_loc)
+return false;
+cur_loc= i;
+return true;
+}
+
+bool hloc_prev(void)
+{int i= cur_loc;
+if(page_loc[cur_loc]==0)
+return false;
+PREV_PAGE(i);
+if(i==lo_loc)
+return false;
+cur_loc= i;
+return true;
+}
+
+
+/*:227*//*230:*/
+#line 3915 "hint.w"
+
+
+void hloc_set(uint64_t h)
+{int i;
+if(page_loc[cur_loc]==h)return;
+for(i= lo_loc,NEXT_PAGE(i);i!=hi_loc;NEXT_PAGE(i))
+if(page_loc[i]==h)
+{cur_loc= i;return;}
+page_loc[cur_loc]= h;
+hloc_clear();
+DBG(DBGPAGE,"loc_set: %d < %d < %d\n",lo_loc,cur_loc,hi_loc);
+}
+/*:230*//*231:*/
+#line 3939 "hint.w"
+
+
+void hloc_set_next(pointer p)
+{int i= cur_loc;
+uint64_t h= hlocation(p);
+
+NEXT_PAGE(i);
+if(i==hi_loc)
+{if(hi_loc==lo_loc)
+NEXT_PAGE(lo_loc);
+NEXT_PAGE(hi_loc);
+page_loc[i]= h;
+}
+else if(h!=page_loc[i])
+{page_loc[i]= h;
+NEXT_PAGE(i);
+hi_loc= i;
+}
+DBG(DBGPAGE,"loc_set_next: %d < %d < %d\n",lo_loc,cur_loc,hi_loc);
+}
+/*:231*//*232:*/
+#line 3975 "hint.w"
+
+void hloc_set_prev(pointer p)
+{int i= cur_loc;
+uint64_t h= hlocation(p);
+PREV_PAGE(i);
+if(i==lo_loc)
+{if(lo_loc==hi_loc)
+PREV_PAGE(hi_loc);
+PREV_PAGE(lo_loc);
+page_loc[i]= h;
+}
+else if(h!=page_loc[i])
+{page_loc[i]= h;
+lo_loc= i;
+PREV_PAGE(lo_loc);
+}
+hi_loc= cur_loc;
+NEXT_PAGE(hi_loc);
+cur_loc= i;
+DBG(DBGPAGE,"loc_set_prev: %d < %d < %d\n",lo_loc,cur_loc,hi_loc);
+}
+/*:232*//*245:*/
+#line 4250 "hint.w"
+
+static void hset_margins(void)
+{if(cur_page==&(page_def[0])){
+offset_h= page_h/8-0x48000;
+if(offset_h<0)offset_h= 0;
+offset_v= page_v/8-0x48000;
+if(offset_v<0)offset_v= 0;
+if(offset_h> offset_v)offset_h= offset_v;
+else offset_v= offset_h;
+hhsize= page_h-2*offset_h;
+hvsize= page_v-2*offset_v;
+if(hhsize<=0)hhsize= page_h,offset_h= 0;
+if(hvsize<=0)hvsize= page_v,offset_v= 0;
+}
+else
+{hhsize= round((double)(page_h-cur_page->h.w)/(double)cur_page->h.h);
+if(hhsize> page_h)hhsize= page_h;
+hvsize= round((double)(page_v-cur_page->v.w)/(double)cur_page->v.v);
+if(hvsize> page_v)hvsize= page_v;
+}
+}
+/*:245*//*247:*/
+#line 4280 "hint.w"
+
+static void houtput_template0(void)
+{pointer p,q,r;
+if(streams[0].p==null)return;
+p= streams[0].p;streams[0].p= null;
+p= vpackage(p,hvsize,exactly,page_max_depth);
+r= new_kern(offset_v);
+link(r)= p;
+q= new_null_box();
+type(q)= vlist_node;
+width(q)= width(p)+offset_h;
+height(q)= height(p)+offset_v;depth(q)= depth(p);
+list_ptr(q)= r;
+shift_amount(p)+= offset_h;
+streams[0].p= q;
+}
+/*:247*//*272:*/
+#line 4923 "hint.w"
+
+static int trv_string_size= 0;
+static char trv_string[256];
+#define TRV_UTF8(C) (trv_string[trv_string_size++]= (C))
+static void trv_string_collect(uint32_t c)
+{if(trv_string_size<256-5)
+{if(c<0x80)
+TRV_UTF8(c);
+else if(c<0x800)
+{TRV_UTF8(0xC0|(c>>6));TRV_UTF8(0x80|(c&0x3F));}
+else if(c<0x10000)
+{TRV_UTF8(0xE0|(c>>12));TRV_UTF8(0x80|((c>>6)&0x3F));TRV_UTF8(0x80|(c&0x3F));}
+else if(c<0x200000)
+{TRV_UTF8(0xF0|(c>>18));TRV_UTF8(0x80|((c>>12)&0x3F));
+TRV_UTF8(0x80|((c>>6)&0x3F));TRV_UTF8(0x80|(c&0x3F));}
+else
+RNG("character code in outline",c,0,0x1FFFFF);
+}
+}
+
+char*hlist_to_string(pointer p)
+{trv_string_size= 0;
+trv_init(trv_string_collect);
+trv_hlist(p);
+trv_string[trv_string_size]= 0;
+return trv_string;
+}
+/*:272*//*368:*/
+#line 7435 "hint.w"
+
+static pointer leaks[1<<16]= {0};
+
+static void leak_clear(void)
+{
+#ifdef DEBUG
+int i;
+for(i= 0;i<0x10000;i++)
+leaks[i]= 0;
+#endif
+}
+
+void leak_in(pointer p,int s)
+{
+#ifdef DEBUG
+if(0!=leaks[p])
+fprintf(stderr,"ERROR leak in: p=%d, s in=%d, leaks[p]= %d != 0\n",p,s,leaks[p]);
+leaks[p]= s;
+#endif
+}
+
+void leak_out(pointer p,int s)
+{
+#ifdef DEBUG
+if(s!=leaks[p])
+fprintf(stderr,"ERROR: leak out: p=%d, s out=%d != %d = s in\n",p,s,leaks[p]);
+leaks[p]= 0;
+#endif
+}
+
+static void list_leaks(void)
+{
+#ifdef DEBUG
+int i;
+for(i= 0;i<0x10000;i++)
+if(leaks[i]!=0)
+fprintf(stderr,"ERROR:leak final: p=%d, s=%d\n",i,leaks[i]);
+#endif
+}
+/*:368*/
+#line 7526 "hint.w"
+
+/*1:*/
+#line 111 "hint.w"
+
+void hget_def_node(void)
+{kind_t k;
+int n;
+/*74:*/
+#line 1161 "hint.w"
+
+uint8_t a,z;
+HGETTAG(a);
+/*:74*/
+#line 115 "hint.w"
+
+k= KIND(a);
+if(k==label_kind&&(INFO(a)&b001))HGET16(n);
+else n= HGET8;
+if(k!=range_kind)REF_RNG(k,n);
+DBG(DBGTAGS,"Defining %s %d\n",definition_name[KIND(a)],n);
+switch(KIND(a))
+{case language_kind:{char*t;HGET_STRING(t);break;}
+case font_kind:hget_font_def(a,n);break;
+case int_kind:integer_def[n]= hget_integer_def(a);break;
+case dimen_kind:dimen_def[n]= hget_dimen_def(a);break;
+case xdimen_kind:hget_xdimen_def(INFO(a),&(xdimen_def[n]));break;
+case baseline_kind:hget_baseline_def(a,n);break;
+case glue_kind:pointer_def[glue_kind][n]= hget_glue_def(a);break;
+case param_kind:param_def[n]= hget_param_list(a);break;
+case range_kind:hget_range_def(a,n);break;
+case page_kind:hget_page_def(a,n);break;
+case label_kind:hget_outline_or_label_def(INFO(a),n);break;
+default:pointer_def[KIND(a)][n]= hget_definition(a);break;
+}
+if(max_fixed[k]> max_default[k])
+QUIT("Definitions for kind %s not supported",definition_name[k]);
+if(n> max_ref[k]||n<=max_fixed[k])
+QUIT("Definition %d for %s out of range [%d - %d]",
+n,definition_name[k],max_fixed[k]+1,max_ref[k]);
+/*75:*/
+#line 1166 "hint.w"
+
+HGETTAG(z);
+if(a!=z)
+QUIT("Tag mismatch [%s,%d]!=[%s,%d] at 0x%x to "SIZE_F"\n",
+NAME(a),INFO(a),NAME(z),INFO(z),node_pos,hpos-hstart-1);
+/*:75*/
+#line 140 "hint.w"
+
+}
+
+pointer hset_glue(glue_t*g)
+{if(ZERO_GLUE(*g))
+{add_glue_ref(zero_glue);
+return zero_glue;
+}
+else
+{pointer p= get_node(glue_spec_size);
+width(p)= g->w.w;
+stretch(p)= round(g->p.f*ONE);stretch_order(p)= g->p.o;
+shrink(p)= round(g->m.f*ONE);shrink_order(p)= g->m.o;
+return p;
+}
+}
+
+void hset_default_definitions(void)
+{int i;
+for(i= 0;i<=MAX_INT_DEFAULT;i++)integer_def[i]= int_defaults[i];
+for(i= 0;i<=MAX_DIMEN_DEFAULT;i++)dimen_def[i]= dimen_defaults[i];
+for(i= 0;i<=MAX_XDIMEN_DEFAULT;i++)xdimen_def[i]= xdimen_defaults[i];
+for(i= 0;i<=MAX_GLUE_DEFAULT;i++)pointer_def[glue_kind][i]= hset_glue(&(glue_defaults[i]));
+for(i= 0;i<=MAX_BASELINE_DEFAULT;i++)
+{baseline_def[i].bs= hset_glue(&(baseline_defaults[i].bs));
+baseline_def[i].ls= hset_glue(&(baseline_defaults[i].ls));
+baseline_def[i].lsl= baseline_defaults[i].lsl;
+}
+}
+
+void free_definitions(void)
+{/*5:*/
+#line 226 "hint.w"
+
+{int k;
+for(k= 0;k<32;k++)
+{free(pointer_def[k]);pointer_def[k]= NULL;}
+}
+/*:5*//*8:*/
+#line 249 "hint.w"
+
+free(integer_def);integer_def= NULL;
+/*:8*//*12:*/
+#line 278 "hint.w"
+
+free(dimen_def);dimen_def= NULL;
+/*:12*//*16:*/
+#line 307 "hint.w"
+
+free(xdimen_def);xdimen_def= NULL;
+/*:16*//*24:*/
+#line 378 "hint.w"
+
+free(baseline_def);baseline_def= NULL;
+/*:24*//*31:*/
+#line 496 "hint.w"
+
+free(font_def);font_def= NULL;
+/*:31*//*40:*/
+#line 601 "hint.w"
+
+if(param_def!=NULL)
+{int i;
+for(i= 0;i<=max_ref[param_kind];i++)
+free_param_list(param_def[i]);
+}
+free(param_def);param_def= NULL;
+/*:40*//*47:*/
+#line 744 "hint.w"
+
+free(range_def);range_def= NULL;
+/*:47*//*52:*/
+#line 798 "hint.w"
+
+free(streams);streams= NULL;
+/*:52*//*60:*/
+#line 911 "hint.w"
+
+if(page_def!=NULL)
+{int k;
+for(k= 0;k<=max_ref[page_kind];k++)
+{free(page_def[k].s);free(page_def[k].n);
+}
+free(page_def);page_def= NULL;cur_page= NULL;
+}
+/*:60*//*67:*/
+#line 1033 "hint.w"
+
+free(labels);labels= NULL;
+{int k;
+for(k= 0;k<=max_outline;k++)free(hint_outlines[k].title);
+}
+free(hint_outlines);hint_outlines= NULL;outline_no= -1;
+max_outline= -1;
+/*:67*/
+#line 171 "hint.w"
+
+}
+
+void hget_definition_section(void)
+{DBG(DBGDEF,"Definitions\n");
+hget_section(1);
+DBG(DBGDEF,"Reading list of maximum values\n");
+free_definitions();
+hget_max_definitions();
+/*4:*/
+#line 211 "hint.w"
+
+{kind_t k;
+for(k= 0;k<32;k++)
+{if(k==font_kind||k==int_kind||k==dimen_kind||k==xdimen_kind||
+k==glue_kind||k==baseline_kind||k==range_kind||k==page_kind||k==param_kind||k==stream_kind||k==label_kind)
+continue;
+if(max_ref[k]>=0&&max_ref[k]<=256)
+{DBG(DBGDEF,"Allocating definitions for %s (kind %d): %d entries of "SIZE_F" byte each\n",
+definition_name[k],k,max_ref[k]+1,sizeof(pointer));
+ALLOCATE(pointer_def[k],max_ref[k]+1,pointer);
+}
+}
+}
+/*:4*//*7:*/
+#line 245 "hint.w"
+
+ALLOCATE(integer_def,max_ref[int_kind]+1,int32_t);
+/*:7*//*11:*/
+#line 274 "hint.w"
+
+ALLOCATE(dimen_def,max_ref[dimen_kind]+1,dimen_t);
+/*:11*//*15:*/
+#line 304 "hint.w"
+
+ALLOCATE(xdimen_def,max_ref[xdimen_kind]+1,xdimen_t);
+/*:15*//*20:*/
+#line 355 "hint.w"
+
+ALLOCATE(pointer_def[glue_kind],max_ref[glue_kind]+1,pointer);
+/*:20*//*23:*/
+#line 374 "hint.w"
+
+ALLOCATE(baseline_def,max_ref[baseline_kind]+1,bs_t);
+/*:23*//*30:*/
+#line 492 "hint.w"
+
+ALLOCATE(font_def,max_ref[font_kind]+1,font_def_t);
+/*:30*//*39:*/
+#line 597 "hint.w"
+
+ALLOCATE(param_def,max_ref[param_kind]+1,param_def_t*);
+/*:39*//*46:*/
+#line 740 "hint.w"
+
+ALLOCATE(range_def,max_ref[range_kind]+1,range_def_t);
+/*:46*//*51:*/
+#line 794 "hint.w"
+
+ALLOCATE(streams,max_ref[stream_kind]+1,stream_t);
+/*:51*//*58:*/
+#line 891 "hint.w"
+
+ALLOCATE(page_def,max_ref[page_kind]+1,page_def_t);
+/*:58*//*66:*/
+#line 1026 "hint.w"
+
+if(max_ref[label_kind]>=0)
+ALLOCATE(labels,max_ref[label_kind]+1,label_t);
+if(max_outline>=0)
+ALLOCATE(hint_outlines,max_outline+1,hint_outline_t);
+/*:66*/
+#line 180 "hint.w"
+
+hset_default_definitions();
+DBG(DBGDEF,"Reading list of definitions\n");
+while(hpos<hend)
+hget_def_node();
+hget_font_metrics();
+/*59:*/
+#line 895 "hint.w"
+
+page_def[0].d= max_depth;
+page_def[0].g= top_skip;add_glue_ref(top_skip);
+page_def[0].p= 0;
+page_def[0].n= strdup("default");
+page_def[0].v.w= -9*ONE;
+page_def[0].v.h= 0.0;
+page_def[0].v.v= 1.25;
+page_def[0].h.w= -9*ONE;
+page_def[0].h.h= 1.25;
+page_def[0].h.v= 0.0;
+page_def[0].t= 0;
+ALLOCATE(page_def[0].s,max_ref[stream_kind]+1,stream_def_t);
+cur_page= &(page_def[0]);
+/*:59*/
+#line 186 "hint.w"
+
+}
+/*:1*//*13:*/
+#line 282 "hint.w"
+
+scaled hget_dimen_ref(uint8_t n)
+{REF_RNG(dimen_kind,n);
+return dimen_def[n];
+}
+
+static scaled hget_dimen_def(uint8_t a)
+{if(INFO(a)==b000)
+return hget_dimen_ref(HGET8);
+else
+{scaled d;HGET32(d);return d;}
+}
+/*:13*//*25:*/
+#line 382 "hint.w"
+
+static void hget_baseline_def(uint8_t a,uint8_t n)
+{HGET_BASELINE(INFO(a));
+baseline_def[n].bs= cur_bs;add_glue_ref(cur_bs);
+baseline_def[n].ls= cur_ls;add_glue_ref(cur_ls);
+baseline_def[n].lsl= cur_lsl;
+}
+
+void hget_baseline_ref(uint8_t n)
+{REF_RNG(baseline_kind,n);
+cur_bs= baseline_def[n].bs;
+cur_ls= baseline_def[n].ls;
+cur_lsl= baseline_def[n].lsl;
+}
+
+pointer happend_to_vlist(pointer b)
+{scaled d;
+pointer p= null;
+
+if(needs_bs&&prev_depth> ignore_depth)
+{d= width(cur_bs)-prev_depth-height(b);
+if(d<cur_lsl)p= new_glue(cur_ls);
+else{pointer q= new_spec(cur_bs);
+width(q)= d;p= new_glue(q);glue_ref_count(q)= null;
+}
+link(tail)= p;tail= p;
+if(nest_ptr==0)
+store_map(p,cur_list.bs_pos-hstart,0);
+}
+link(tail)= b;tail= b;prev_depth= depth(b);
+cur_list.bs_pos= NULL;
+return p;
+}
+/*:25*//*26:*/
+#line 436 "hint.w"
+
+static pointer hprepend_to_vlist(pointer b)
+{scaled d;
+pointer p= null;
+
+if(needs_bs&&prev_height> ignore_depth)
+{d= width(cur_bs)-prev_height-depth(b);
+if(d<cur_lsl)p= new_glue(cur_ls);
+else{pointer q= new_spec(cur_bs);
+width(q)= d;p= new_glue(q);glue_ref_count(q)= null;
+}
+link(tail)= p;tail= p;
+if(nest_ptr==0)
+store_map(p,cur_list.bs_pos-hstart,0);
+}
+link(tail)= b;tail= b;prev_height= height(b);
+cur_list.bs_pos= NULL;
+return p;
+}
+/*:26*//*68:*/
+#line 1046 "hint.w"
+
+void hget_outline_or_label_def(info_t i,int n)
+{if(i&b100)
+/*70:*/
+#line 1067 "hint.w"
+
+{hint_outline_t*t;
+uint64_t pos;
+uint8_t where;
+outline_no++;
+RNG("Outline",outline_no,0,max_outline);
+t= hint_outlines+outline_no;
+t->depth= HGET8;
+t->p= hget_list_pointer();
+t->title= strdup(hlist_to_string(t->p));
+/*71:*/
+#line 1083 "hint.w"
+
+where= labels[n].where;
+#if 1
+pos= ((uint64_t)labels[n].pos<<32)+(labels[n].pos-labels[n].pos0);
+#else
+pos= ((uint64_t)labels[n].pos0<<32);
+#endif
+/*:71*/
+#line 1077 "hint.w"
+
+t->where= where;
+t->pos= pos;
+}
+/*:70*/
+#line 1049 "hint.w"
+
+else
+/*69:*/
+#line 1055 "hint.w"
+
+{label_t*t= labels+n;
+HGET32(t->pos);
+t->where= HGET8;
+if(t->where> LABEL_MID)t->where= LABEL_UNDEF;
+if(i&b010)
+{HGET32(t->pos0);t->f= HGET8;}
+else t->pos0= t->pos;
+DBG(DBGDEF,"Label 0x%x+0x%x where=%d font=%d\n",t->pos0,t->pos,t->where,t->f);
+}
+/*:69*/
+#line 1051 "hint.w"
+
+}
+/*:68*//*73:*/
+#line 1147 "hint.w"
+
+static void hget_content_section()
+{DBG(DBGDIR,"Reading Content Section\n");
+hget_section(2);
+}
+/*:73*//*101:*/
+#line 1523 "hint.w"
+
+pointer hget_rule_node(void)
+{pointer q= null;
+/*74:*/
+#line 1161 "hint.w"
+
+uint8_t a,z;
+HGETTAG(a);
+/*:74*/
+#line 1526 "hint.w"
+
+if(KIND(a)==rule_kind){HGET_RULE(INFO(a));q= p;}
+else QUIT("Rule expected at 0x%x got %s",node_pos,NAME(a));
+/*75:*/
+#line 1166 "hint.w"
+
+HGETTAG(z);
+if(a!=z)
+QUIT("Tag mismatch [%s,%d]!=[%s,%d] at 0x%x to "SIZE_F"\n",
+NAME(a),INFO(a),NAME(z),INFO(z),node_pos,hpos-hstart-1);
+/*:75*/
+#line 1529 "hint.w"
+
+return q;
+}
+/*:101*//*120:*/
+#line 1899 "hint.w"
+
+pointer hget_hbox_node(void)
+{/*74:*/
+#line 1161 "hint.w"
+
+uint8_t a,z;
+HGETTAG(a);
+/*:74*/
+#line 1901 "hint.w"
+
+if(KIND(a)!=hbox_kind)QUIT("Hbox expected at 0x%x got %s",node_pos,NAME(a));
+{pointer p;
+HGET_BOX(INFO(a));
+/*75:*/
+#line 1166 "hint.w"
+
+HGETTAG(z);
+if(a!=z)
+QUIT("Tag mismatch [%s,%d]!=[%s,%d] at 0x%x to "SIZE_F"\n",
+NAME(a),INFO(a),NAME(z),INFO(z),node_pos,hpos-hstart-1);
+/*:75*/
+#line 1905 "hint.w"
+
+return p;
+}
+}
+
+
+pointer hget_vbox_node(void)
+{
+/*74:*/
+#line 1161 "hint.w"
+
+uint8_t a,z;
+HGETTAG(a);
+/*:74*/
+#line 1913 "hint.w"
+
+if(KIND(a)!=vbox_kind)QUIT("Vbox expected at 0x%x got %s",node_pos,NAME(a));
+{pointer p;
+HGET_BOX(INFO(a));
+/*75:*/
+#line 1166 "hint.w"
+
+HGETTAG(z);
+if(a!=z)
+QUIT("Tag mismatch [%s,%d]!=[%s,%d] at 0x%x to "SIZE_F"\n",
+NAME(a),INFO(a),NAME(z),INFO(z),node_pos,hpos-hstart-1);
+/*:75*/
+#line 1917 "hint.w"
+
+type(p)= vlist_node;
+return p;
+}
+}
+/*:120*//*160:*/
+#line 2667 "hint.w"
+
+pointer hget_paragraph_initial(scaled x,uint8_t*to)
+{
+uint8_t*node_start;
+uint32_t s,t;
+uint8_t a,z;
+node_start= hpos;
+HGETTAG(a);
+if(!IS_LIST(a))
+{hpos= node_start;return null;}
+s= hget_list_size(INFO(a));
+hget_size_boundary(INFO(a));
+if(KIND(a)==list_kind)
+{uint8_t*list_end= hpos+s;if(to> list_end){LOG("Value of to greater than list_end");to= list_end;}
+cur_list.hs_field= x;
+push_nest();
+cur_list.bs_pos= NULL;
+while(hpos<to)
+{hget_content();
+if(nest_ptr==1)
+{pointer p= tail;
+if(p!=head&&!is_char_node(p)&&
+(type(p)==glue_node||type(p)==kern_node||type(p)==penalty_node||type(p)==disc_node||type(p)==math_node))
+store_map(p,node_pos,0);
+}
+}
+if(KIND(*to)==disc_kind)
+{hget_content();
+store_map(tail,node_pos,0);
+transplant_pre_break_list();
+}
+hpos= list_end;
+hget_size_boundary(INFO(a));
+t= hget_list_size(INFO(a));
+if(t!=s)
+QUIT("List sizes at 0x%x and "SIZE_F" do not match 0x%x != 0x%x",node_pos+1,hpos-hstart-s-1,s,t);
+/*75:*/
+#line 1166 "hint.w"
+
+HGETTAG(z);
+if(a!=z)
+QUIT("Tag mismatch [%s,%d]!=[%s,%d] at 0x%x to "SIZE_F"\n",
+NAME(a),INFO(a),NAME(z),INFO(z),node_pos,hpos-hstart-1);
+/*:75*/
+#line 2703 "hint.w"
+
+if(needs_bs)
+QUIT("Unexpected trailing baseline node");
+if(head==tail)
+{pop_nest();
+return null;
+}
+else
+{pointer par_ptr= link(head);
+/*161:*/
+#line 2731 "hint.w"
+
+if(is_char_node(tail))tail_append(new_penalty(inf_penalty))
+else if(type(tail)!=glue_node)tail_append(new_penalty(inf_penalty))
+else
+{type(tail)= penalty_node;delete_glue_ref(glue_ptr(tail));
+flush_node_list(leader_ptr(tail));penalty(tail)= inf_penalty;
+}
+tail_append(new_glue(zero_glue));
+/*:161*/
+#line 2712 "hint.w"
+
+pop_nest();
+store_map(par_ptr,node_pos,0);
+return par_ptr;
+}
+}
+else
+QUIT("Text in paragraph not yet implemented");
+return null;
+}
+/*:160*/
+#line 7527 "hint.w"
+
+/*80:*/
+#line 1241 "hint.w"
+
+static void hteg_node(uint8_t z)
+{switch(z)
+{
+/*92:*/
+#line 1435 "hint.w"
+
+case TAG(glyph_kind,1):HTEG_GLYPH(1);break;
+case TAG(glyph_kind,2):HTEG_GLYPH(2);break;
+case TAG(glyph_kind,3):HTEG_GLYPH(3);break;
+case TAG(glyph_kind,4):HTEG_GLYPH(4);break;
+/*:92*//*94:*/
+#line 1450 "hint.w"
+
+case TAG(penalty_kind,0):tail_append(new_penalty(hget_integer_ref(HTEG8)));break;
+case TAG(penalty_kind,1):{tail_append(new_penalty(HTEG8));}break;
+case TAG(penalty_kind,2):{int16_t n;HTEG16(n);RNG("Penalty",n,-20000,+20000);tail_append(new_penalty(n));}break;
+/*:94*//*96:*/
+#line 1470 "hint.w"
+
+case TAG(language_kind,b000):(void)HTEG8;
+case TAG(language_kind,1):
+case TAG(language_kind,2):
+case TAG(language_kind,3):
+case TAG(language_kind,4):
+case TAG(language_kind,5):
+case TAG(language_kind,6):
+case TAG(language_kind,7):break;
+/*:96*//*100:*/
+#line 1513 "hint.w"
+
+case TAG(rule_kind,b000):tail_append(hget_rule_ref(HTEG8));prev_height= ignore_depth;break;
+case TAG(rule_kind,b011):{HTEG_RULE(b011);tail_append(p);prev_height= ignore_depth;}break;
+case TAG(rule_kind,b101):{HTEG_RULE(b101);tail_append(p);prev_height= ignore_depth;}break;
+case TAG(rule_kind,b001):{HTEG_RULE(b001);tail_append(p);prev_height= ignore_depth;}break;
+case TAG(rule_kind,b110):{HTEG_RULE(b110);tail_append(p);prev_height= ignore_depth;}break;
+case TAG(rule_kind,b111):{HTEG_RULE(b111);tail_append(p);prev_height= ignore_depth;}break;
+/*:100*//*107:*/
+#line 1584 "hint.w"
+
+case TAG(glue_kind,b000):tail_append(new_glue(hget_glue_ref(HTEG8)));break;
+case TAG(glue_kind,b001):{pointer p;HTEG_GLUE(b001);tail_append(spec2glue(p));}break;
+case TAG(glue_kind,b010):{pointer p;HTEG_GLUE(b010);tail_append(spec2glue(p));}break;
+case TAG(glue_kind,b011):{pointer p;HTEG_GLUE(b011);tail_append(spec2glue(p));}break;
+case TAG(glue_kind,b100):{pointer p;HTEG_GLUE(b100);tail_append(spec2glue(p));}break;
+case TAG(glue_kind,b101):{pointer p;HTEG_GLUE(b101);tail_append(spec2glue(p));}break;
+case TAG(glue_kind,b110):{pointer p;HTEG_GLUE(b110);tail_append(spec2glue(p));}break;
+case TAG(glue_kind,b111):{pointer p;HTEG_GLUE(b111);tail_append(spec2glue(p));}break;
+/*:107*//*119:*/
+#line 1880 "hint.w"
+
+case TAG(hbox_kind,b000):{pointer p;HTEG_BOX(b000);hprepend_to_vlist(p);}break;
+case TAG(hbox_kind,b001):{pointer p;HTEG_BOX(b001);hprepend_to_vlist(p);}break;
+case TAG(hbox_kind,b010):{pointer p;HTEG_BOX(b010);hprepend_to_vlist(p);}break;
+case TAG(hbox_kind,b011):{pointer p;HTEG_BOX(b011);hprepend_to_vlist(p);}break;
+case TAG(hbox_kind,b100):{pointer p;HTEG_BOX(b100);hprepend_to_vlist(p);}break;
+case TAG(hbox_kind,b101):{pointer p;HTEG_BOX(b101);hprepend_to_vlist(p);}break;
+case TAG(hbox_kind,b110):{pointer p;HTEG_BOX(b110);hprepend_to_vlist(p);}break;
+case TAG(hbox_kind,b111):{pointer p;HTEG_BOX(b111);hprepend_to_vlist(p);}break;
+case TAG(vbox_kind,b000):{pointer p;HTEG_BOX(b000);type(p)= vlist_node;hprepend_to_vlist(p);}break;
+case TAG(vbox_kind,b001):{pointer p;HTEG_BOX(b001);type(p)= vlist_node;hprepend_to_vlist(p);}break;
+case TAG(vbox_kind,b010):{pointer p;HTEG_BOX(b010);type(p)= vlist_node;hprepend_to_vlist(p);}break;
+case TAG(vbox_kind,b011):{pointer p;HTEG_BOX(b011);type(p)= vlist_node;hprepend_to_vlist(p);}break;
+case TAG(vbox_kind,b100):{pointer p;HTEG_BOX(b100);type(p)= vlist_node;hprepend_to_vlist(p);}break;
+case TAG(vbox_kind,b101):{pointer p;HTEG_BOX(b101);type(p)= vlist_node;hprepend_to_vlist(p);}break;
+case TAG(vbox_kind,b110):{pointer p;HTEG_BOX(b110);type(p)= vlist_node;hprepend_to_vlist(p);}break;
+case TAG(vbox_kind,b111):{pointer p;HTEG_BOX(b111);type(p)= vlist_node;hprepend_to_vlist(p);}break;
+/*:119*//*126:*/
+#line 1998 "hint.w"
+
+case TAG(hset_kind,b000):{pointer p;HTEG_SET(b000);hset(p,sto,st,sho,sh,x);hprepend_to_vlist(p);}break;
+case TAG(hset_kind,b001):{pointer p;HTEG_SET(b001);hset(p,sto,st,sho,sh,x);hprepend_to_vlist(p);}break;
+case TAG(hset_kind,b010):{pointer p;HTEG_SET(b010);hset(p,sto,st,sho,sh,x);hprepend_to_vlist(p);}break;
+case TAG(hset_kind,b011):{pointer p;HTEG_SET(b011);hset(p,sto,st,sho,sh,x);hprepend_to_vlist(p);}break;
+case TAG(hset_kind,b100):{pointer p;HTEG_SET(b100);hset(p,sto,st,sho,sh,x);hprepend_to_vlist(p);}break;
+case TAG(hset_kind,b101):{pointer p;HTEG_SET(b101);hset(p,sto,st,sho,sh,x);hprepend_to_vlist(p);}break;
+case TAG(hset_kind,b110):{pointer p;HTEG_SET(b110);hset(p,sto,st,sho,sh,x);hprepend_to_vlist(p);}break;
+case TAG(hset_kind,b111):{pointer p;HTEG_SET(b111);hset(p,sto,st,sho,sh,x);hprepend_to_vlist(p);}break;
+
+case TAG(vset_kind,b000):{pointer p;HTEG_SET(b000);vset(p,sto,st,sho,sh,x);hprepend_to_vlist(p);}break;
+case TAG(vset_kind,b001):{pointer p;HTEG_SET(b001);vset(p,sto,st,sho,sh,x);hprepend_to_vlist(p);}break;
+case TAG(vset_kind,b010):{pointer p;HTEG_SET(b010);vset(p,sto,st,sho,sh,x);hprepend_to_vlist(p);}break;
+case TAG(vset_kind,b011):{pointer p;HTEG_SET(b011);vset(p,sto,st,sho,sh,x);hprepend_to_vlist(p);}break;
+case TAG(vset_kind,b100):{pointer p;HTEG_SET(b100);vset(p,sto,st,sho,sh,x);hprepend_to_vlist(p);}break;
+case TAG(vset_kind,b101):{pointer p;HTEG_SET(b101);vset(p,sto,st,sho,sh,x);hprepend_to_vlist(p);}break;
+case TAG(vset_kind,b110):{pointer p;HTEG_SET(b110);vset(p,sto,st,sho,sh,x);hprepend_to_vlist(p);}break;
+case TAG(vset_kind,b111):{pointer p;HTEG_SET(b111);vset(p,sto,st,sho,sh,x);hprepend_to_vlist(p);}break;
+/*:126*//*131:*/
+#line 2138 "hint.w"
+
+case TAG(hpack_kind,b000):HTEG_PACK(hpack_kind,b000);break;
+case TAG(hpack_kind,b010):HTEG_PACK(hpack_kind,b010);break;
+case TAG(hpack_kind,b100):HTEG_PACK(hpack_kind,b100);break;
+case TAG(hpack_kind,b110):HTEG_PACK(hpack_kind,b110);break;
+case TAG(hpack_kind,b001):HTEG_PACK(hpack_kind,b001);break;
+case TAG(hpack_kind,b011):HTEG_PACK(hpack_kind,b011);break;
+case TAG(hpack_kind,b101):HTEG_PACK(hpack_kind,b101);break;
+case TAG(hpack_kind,b111):HTEG_PACK(hpack_kind,b111);break;
+
+case TAG(vpack_kind,b000):HTEG_PACK(vpack_kind,b000);break;
+case TAG(vpack_kind,b010):HTEG_PACK(vpack_kind,b010);break;
+case TAG(vpack_kind,b100):HTEG_PACK(vpack_kind,b100);break;
+case TAG(vpack_kind,b110):HTEG_PACK(vpack_kind,b110);break;
+case TAG(vpack_kind,b001):HTEG_PACK(vpack_kind,b001);break;
+case TAG(vpack_kind,b011):HTEG_PACK(vpack_kind,b011);break;
+case TAG(vpack_kind,b101):HTEG_PACK(vpack_kind,b101);break;
+case TAG(vpack_kind,b111):HTEG_PACK(vpack_kind,b111);break;
+/*:131*//*135:*/
+#line 2197 "hint.w"
+
+case TAG(kern_kind,b000):{HTEG_KERN(b000);}break;
+case TAG(kern_kind,b001):{HTEG_KERN(b001);}break;
+case TAG(kern_kind,b010):{HTEG_KERN(b010);}break;
+case TAG(kern_kind,b011):{HTEG_KERN(b011);}break;
+case TAG(kern_kind,b100):{HTEG_KERN(b100);}break;
+case TAG(kern_kind,b101):{HTEG_KERN(b101);}break;
+case TAG(kern_kind,b110):{HTEG_KERN(b110);}break;
+case TAG(kern_kind,b111):{HTEG_KERN(b111);}break;
+/*:135*//*139:*/
+#line 2244 "hint.w"
+
+case TAG(leaders_kind,0):tail_append(hget_leaders_ref(HTEG8));break;
+case TAG(leaders_kind,1):HTEG_LEADERS(1);break;
+case TAG(leaders_kind,2):HTEG_LEADERS(2);break;
+case TAG(leaders_kind,3):HTEG_LEADERS(3);break;
+case TAG(leaders_kind,b100|1):HTEG_LEADERS(b100|1);break;
+case TAG(leaders_kind,b100|2):HTEG_LEADERS(b100|2);break;
+case TAG(leaders_kind,b100|3):HTEG_LEADERS(b100|3);break;
+/*:139*//*143:*/
+#line 2285 "hint.w"
+
+case TAG(baseline_kind,b000):{hget_baseline_ref(HTEG8);cur_list.bs_pos= hpos-1;}break;
+case TAG(baseline_kind,b010):{HTEG_BASELINE(b010);}break;
+case TAG(baseline_kind,b011):{HTEG_BASELINE(b011);}break;
+case TAG(baseline_kind,b100):{HTEG_BASELINE(b100);}break;
+case TAG(baseline_kind,b101):{HTEG_BASELINE(b101);}break;
+case TAG(baseline_kind,b110):{HTEG_BASELINE(b110);}break;
+case TAG(baseline_kind,b111):{HTEG_BASELINE(b111);}break;
+/*:143*//*148:*/
+#line 2346 "hint.w"
+
+case TAG(ligature_kind,0):tail_append(hget_ligature_ref(HTEG8));break;
+case TAG(ligature_kind,1):HTEG_LIG(1);break;
+case TAG(ligature_kind,2):HTEG_LIG(2);break;
+case TAG(ligature_kind,3):HTEG_LIG(3);break;
+case TAG(ligature_kind,4):HTEG_LIG(4);break;
+case TAG(ligature_kind,5):HTEG_LIG(5);break;
+case TAG(ligature_kind,6):HTEG_LIG(6);break;
+case TAG(ligature_kind,7):HTEG_LIG(7);break;
+/*:148*//*152:*/
+#line 2395 "hint.w"
+
+case TAG(disc_kind,b000):tail_append(hget_hyphen_ref(HTEG8));break;
+case TAG(disc_kind,b001):{HTEG_DISC(b001);tail_append(p);}break;
+case TAG(disc_kind,b010):{HTEG_DISC(b010);tail_append(p);}break;
+case TAG(disc_kind,b011):{HTEG_DISC(b011);tail_append(p);}break;
+case TAG(disc_kind,b100):{HTEG_DISC(b100);tail_append(p);}break;
+case TAG(disc_kind,b101):{HTEG_DISC(b101);tail_append(p);}break;
+case TAG(disc_kind,b110):{HTEG_DISC(b110);tail_append(p);}break;
+case TAG(disc_kind,b111):{HTEG_DISC(b111);tail_append(p);}break;
+/*:152*//*167:*/
+#line 2820 "hint.w"
+
+case TAG(par_kind,b000):hteg_paragraph(b000);break;
+case TAG(par_kind,b010):hteg_paragraph(b010);break;
+case TAG(par_kind,b100):hteg_paragraph(b100);break;
+case TAG(par_kind,b110):hteg_paragraph(b110);break;
+/*:167*//*175:*/
+#line 2953 "hint.w"
+
+case TAG(math_kind,b000):HTEG_MATH(b000);break;
+case TAG(math_kind,b001):HTEG_MATH(b001);break;
+case TAG(math_kind,b010):HTEG_MATH(b010);break;
+case TAG(math_kind,b100):HTEG_MATH(b100);break;
+case TAG(math_kind,b101):HTEG_MATH(b101);break;
+case TAG(math_kind,b110):HTEG_MATH(b110);break;
+/*:175*//*177:*/
+#line 2977 "hint.w"
+
+case TAG(math_kind,b111):tail_append(new_math(0,before));break;
+case TAG(math_kind,b011):tail_append(new_math(0,after));break;
+/*:177*//*183:*/
+#line 3047 "hint.w"
+
+case TAG(table_kind,b000):HTEG_TABLE(b000);break;
+case TAG(table_kind,b001):HTEG_TABLE(b001);break;
+case TAG(table_kind,b010):HTEG_TABLE(b010);break;
+case TAG(table_kind,b011):HTEG_TABLE(b011);break;
+case TAG(table_kind,b100):HTEG_TABLE(b100);break;
+case TAG(table_kind,b101):HTEG_TABLE(b101);break;
+case TAG(table_kind,b110):HTEG_TABLE(b110);break;
+case TAG(table_kind,b111):HTEG_TABLE(b111);break;
+
+case TAG(item_kind,b000):hteg_list_pointer();break;
+case TAG(item_kind,b001):hteg_content();break;
+case TAG(item_kind,b010):hteg_content();break;
+case TAG(item_kind,b011):hteg_content();break;
+case TAG(item_kind,b100):hteg_content();break;
+case TAG(item_kind,b101):hteg_content();break;
+case TAG(item_kind,b110):hteg_content();break;
+case TAG(item_kind,b111):hteg_content();(void)HTEG8;break;
+/*:183*//*188:*/
+#line 3128 "hint.w"
+
+case TAG(stream_kind,b000):HTEG_STREAM(b000);break;
+case TAG(stream_kind,b010):HTEG_STREAM(b010);break;
+/*:188*//*192:*/
+#line 3167 "hint.w"
+
+case TAG(image_kind,b000):hget_image_ref(HTEG8);break;
+case TAG(image_kind,b100):HTEG_IMAGE(b100);break;
+case TAG(image_kind,b101):HTEG_IMAGE(b101);break;
+case TAG(image_kind,b110):HTEG_IMAGE(b110);break;
+case TAG(image_kind,b111):HTEG_IMAGE(b111);break;
+/*:192*//*196:*/
+#line 3204 "hint.w"
+
+case TAG(link_kind,b000):HTEG_LINK(b000);break;
+case TAG(link_kind,b001):HTEG_LINK(b001);break;
+case TAG(link_kind,b010):HTEG_LINK(b010);break;
+case TAG(link_kind,b011):HTEG_LINK(b011);break;
+/*:196*/
+#line 1245 "hint.w"
+
+default:
+TAGERR(z);
+}
+}
+
+void hteg_content(void)
+{/*78:*/
+#line 1222 "hint.w"
+
+uint8_t a,z;
+z= HTEG8,DBGTAG(z,hpos);
+/*:78*/
+#line 1252 "hint.w"
+
+node_pos= hpos-hstart;
+hteg_node(z);
+/*79:*/
+#line 1227 "hint.w"
+
+a= HTEG8,DBGTAG(a,hpos);
+if(z!=a)
+QUIT("Tag mismatch [%s,%d]!=[%s,%d] at "SIZE_F" to 0x%x\n",
+NAME(a),INFO(a),NAME(z),INFO(z),hpos-hstart,node_pos);
+
+/*:79*/
+#line 1255 "hint.w"
+
+node_pos= hpos-hstart;
+if(nest_ptr==0&&tail!=head
+#if 0
+&&(type(tail)==penalty_node||type(tail)==glue_node
+||type(tail)==hlist_node||type(tail)==vlist_node
+||type(tail)==kern_node)
+#endif
+)
+store_map(tail,node_pos,0);
+}
+/*:80*//*154:*/
+#line 2420 "hint.w"
+
+pointer hteg_disc_node(void)
+{/*78:*/
+#line 1222 "hint.w"
+
+uint8_t a,z;
+z= HTEG8,DBGTAG(z,hpos);
+/*:78*/
+#line 2422 "hint.w"
+
+if(KIND(z)!=disc_kind||INFO(z)==b000)
+QUIT("Hyphen expected at 0x%x got %s,%d",node_pos,NAME(z),INFO(z));
+{
+HTEG_DISC(INFO(z));
+/*79:*/
+#line 1227 "hint.w"
+
+a= HTEG8,DBGTAG(a,hpos);
+if(z!=a)
+QUIT("Tag mismatch [%s,%d]!=[%s,%d] at "SIZE_F" to 0x%x\n",
+NAME(a),INFO(a),NAME(z),INFO(z),hpos-hstart,node_pos);
+
+/*:79*/
+#line 2427 "hint.w"
+
+return p;
+}
+}
+/*:154*//*170:*/
+#line 2889 "hint.w"
+
+void hteg_par_node(uint32_t offset)
+{scaled x= 0;
+param_def_t*save_lbp= line_break_params;
+pointer p;
+pointer par_head= tail;
+uint8_t*bs_pos= cur_list.bs_pos;
+scaled ph= prev_height;
+/*74:*/
+#line 1161 "hint.w"
+
+uint8_t a,z;
+HGETTAG(a);
+/*:74*/
+#line 2897 "hint.w"
+
+node_pos= (hpos-hstart)-1;
+if(INFO(a)&b100)x= hget_xdimen_node();else x= hget_xdimen_ref(HGET8);
+if(INFO(a)&b010)line_break_params= hget_param_list_node();else line_break_params= hget_param_list_ref(HGET8);
+prev_graf= 0;
+p= hget_paragraph_initial(x,hstart+node_pos+offset);
+/*75:*/
+#line 1166 "hint.w"
+
+HGETTAG(z);
+if(a!=z)
+QUIT("Tag mismatch [%s,%d]!=[%s,%d] at 0x%x to "SIZE_F"\n",
+NAME(a),INFO(a),NAME(z),INFO(z),node_pos,hpos-hstart-1);
+/*:75*/
+#line 2903 "hint.w"
+
+cur_list.bs_pos= NULL;
+if(p!=null)
+line_break(hget_integer_ref(widow_penalty_no),p);
+if(par_head!=tail)
+/*169:*/
+#line 2865 "hint.w"
+
+{pointer p,r,par_tail;
+p= null;
+r= par_tail= link(par_head);
+
+tail= par_head;
+link(tail)= null;
+while(r!=null)
+{pointer q= link(r);
+link(r)= p;
+p= r;
+r= q;
+}
+cur_list.bs_pos= bs_pos;
+prev_height= ph;
+hprepend_to_vlist(p);
+tail= par_tail;
+if(type(tail)==hlist_node||type(tail)==vlist_node)
+prev_height= height(tail);
+}
+/*:169*/
+#line 2908 "hint.w"
+
+hpos= hstart+node_pos;
+line_break_params= save_lbp;
+}
+
+/*:170*/
+#line 7528 "hint.w"
+
+
+/*18:*/
+#line 323 "hint.w"
+
+void print_xdimen(int i)
+{}
+/*:18*//*34:*/
+#line 552 "hint.w"
+
+uint16_t hglyph_section(uint8_t f)
+{return font_def[f].q;
+}
+
+int32_t font_at_size(uint8_t f)
+{return font_def[f].s;
+}
+/*:34*//*62:*/
+#line 949 "hint.w"
+
+static void hinsert_stream(uint8_t n)
+{REF_RNG(stream_kind,n);
+if(streams[n].p==null)return;
+DBG(DBGPAGE,"Filling in stream %d\n",n);
+if(n> 0&&cur_page->s[n].b!=0)
+{pointer p= copy_node_list(cur_page->s[n].b);
+link(tail)= p;
+while(link(p)!=null)p= link(p);
+tail= p;
+DBG(DBGPAGE,"Filling in before list %d\n",n);
+}
+link(tail)= streams[n].p;
+tail= streams[n].t;
+if(tail==null)QUIT("Tail of nonempty stream %d is null\n",n);
+streams[n].p= streams[n].t= null;
+DBG(DBGPAGE,"Filling in content list %d\n",n);
+if(n> 0&&cur_page->s[n].a!=0)
+{pointer p= copy_node_list(cur_page->s[n].a);
+link(tail)= p;
+while(link(p)!=null)p= link(p);
+tail= p;
+DBG(DBGPAGE,"Filling in after list %d\n",n);
+}
+}
+/*:62*//*63:*/
+#line 979 "hint.w"
+
+void hfill_page_template(void)
+{pointer p;
+#if 0
+print_str("\npage_head:\n");
+show_box(link(page_head));
+print_str("\nstream 0:\n");
+show_box(streams[0].p);
+print_str("\nstream 1:\n");
+show_box(streams[1].p);
+print_str("\ncontributions:\n");
+show_box(link(contrib_head));
+#endif
+if(cur_page->t!=0)
+{
+uint8_t*spos= hpos,*sstart= hstart,*send= hend;
+hget_section(1);
+hpos= hpos+cur_page->t;
+p= hget_list_pointer();
+hpos= spos,hstart= sstart,hend= send;
+if(streams[0].p!=null)flush_node_list(streams[0].p);
+streams[0].p= streams[0].t= null;
+streams[0].p= vpackage(p,page_v,exactly,page_max_depth);
+}
+else
+houtput_template0();
+hmark_page();
+}
+/*:63*//*76:*/
+#line 1181 "hint.w"
+
+
+static void hget_node(uint8_t a)
+{switch(a)
+{
+/*56:*/
+#line 870 "hint.w"
+
+case TAG(stream_kind,b100):hinsert_stream(HGET8);break;
+/*:56*//*91:*/
+#line 1429 "hint.w"
+
+case TAG(glyph_kind,1):HGET_GLYPH(1);break;
+case TAG(glyph_kind,2):HGET_GLYPH(2);break;
+case TAG(glyph_kind,3):HGET_GLYPH(3);break;
+case TAG(glyph_kind,4):HGET_GLYPH(4);break;
+/*:91*//*93:*/
+#line 1444 "hint.w"
+
+case TAG(penalty_kind,0):tail_append(new_penalty(hget_integer_ref(HGET8)));break;
+case TAG(penalty_kind,1):{tail_append(new_penalty(HGET8));}break;
+case TAG(penalty_kind,2):{int16_t n;HGET16(n);RNG("Penalty",n,-20000,+20000);tail_append(new_penalty(n));}break;
+/*:93*//*95:*/
+#line 1458 "hint.w"
+
+case TAG(language_kind,b000):(void)HGET8;
+case TAG(language_kind,1):
+case TAG(language_kind,2):
+case TAG(language_kind,3):
+case TAG(language_kind,4):
+case TAG(language_kind,5):
+case TAG(language_kind,6):
+case TAG(language_kind,7):break;
+/*:95*//*99:*/
+#line 1504 "hint.w"
+
+case TAG(rule_kind,b000):tail_append(hget_rule_ref(HGET8));prev_depth= ignore_depth;break;
+case TAG(rule_kind,b011):{HGET_RULE(b011);tail_append(p);prev_depth= ignore_depth;}break;
+case TAG(rule_kind,b101):{HGET_RULE(b101);tail_append(p);prev_depth= ignore_depth;}break;
+case TAG(rule_kind,b001):{HGET_RULE(b001);tail_append(p);prev_depth= ignore_depth;}break;
+case TAG(rule_kind,b110):{HGET_RULE(b110);tail_append(p);prev_depth= ignore_depth;}break;
+case TAG(rule_kind,b111):{HGET_RULE(b111);tail_append(p);prev_depth= ignore_depth;}break;
+/*:99*//*106:*/
+#line 1572 "hint.w"
+
+case TAG(glue_kind,b000):tail_append(new_glue(hget_glue_ref(HGET8)));break;
+case TAG(glue_kind,b001):{pointer p;HGET_GLUE(b001);tail_append(spec2glue(p));}break;
+case TAG(glue_kind,b010):{pointer p;HGET_GLUE(b010);tail_append(spec2glue(p));}break;
+case TAG(glue_kind,b011):{pointer p;HGET_GLUE(b011);tail_append(spec2glue(p));}break;
+case TAG(glue_kind,b100):{pointer p;HGET_GLUE(b100);tail_append(spec2glue(p));}break;
+case TAG(glue_kind,b101):{pointer p;HGET_GLUE(b101);tail_append(spec2glue(p));}break;
+case TAG(glue_kind,b110):{pointer p;HGET_GLUE(b110);tail_append(spec2glue(p));}break;
+case TAG(glue_kind,b111):{pointer p;HGET_GLUE(b111);tail_append(spec2glue(p));}break;
+/*:106*//*118:*/
+#line 1861 "hint.w"
+
+case TAG(hbox_kind,b000):{pointer p;HGET_BOX(b000);happend_to_vlist(p);}break;
+case TAG(hbox_kind,b001):{pointer p;HGET_BOX(b001);happend_to_vlist(p);}break;
+case TAG(hbox_kind,b010):{pointer p;HGET_BOX(b010);happend_to_vlist(p);}break;
+case TAG(hbox_kind,b011):{pointer p;HGET_BOX(b011);happend_to_vlist(p);}break;
+case TAG(hbox_kind,b100):{pointer p;HGET_BOX(b100);happend_to_vlist(p);}break;
+case TAG(hbox_kind,b101):{pointer p;HGET_BOX(b101);happend_to_vlist(p);}break;
+case TAG(hbox_kind,b110):{pointer p;HGET_BOX(b110);happend_to_vlist(p);}break;
+case TAG(hbox_kind,b111):{pointer p;HGET_BOX(b111);happend_to_vlist(p);}break;
+case TAG(vbox_kind,b000):{pointer p;HGET_BOX(b000);type(p)= vlist_node;happend_to_vlist(p);}break;
+case TAG(vbox_kind,b001):{pointer p;HGET_BOX(b001);type(p)= vlist_node;happend_to_vlist(p);}break;
+case TAG(vbox_kind,b010):{pointer p;HGET_BOX(b010);type(p)= vlist_node;happend_to_vlist(p);}break;
+case TAG(vbox_kind,b011):{pointer p;HGET_BOX(b011);type(p)= vlist_node;happend_to_vlist(p);}break;
+case TAG(vbox_kind,b100):{pointer p;HGET_BOX(b100);type(p)= vlist_node;happend_to_vlist(p);}break;
+case TAG(vbox_kind,b101):{pointer p;HGET_BOX(b101);type(p)= vlist_node;happend_to_vlist(p);}break;
+case TAG(vbox_kind,b110):{pointer p;HGET_BOX(b110);type(p)= vlist_node;happend_to_vlist(p);}break;
+case TAG(vbox_kind,b111):{pointer p;HGET_BOX(b111);type(p)= vlist_node;happend_to_vlist(p);}break;
+/*:118*//*125:*/
+#line 1977 "hint.w"
+
+case TAG(hset_kind,b000):{pointer p;HGET_SET(b000);hset(p,sto,st,sho,sh,x);happend_to_vlist(p);}break;
+case TAG(hset_kind,b001):{pointer p;HGET_SET(b001);hset(p,sto,st,sho,sh,x);happend_to_vlist(p);}break;
+case TAG(hset_kind,b010):{pointer p;HGET_SET(b010);hset(p,sto,st,sho,sh,x);happend_to_vlist(p);}break;
+case TAG(hset_kind,b011):{pointer p;HGET_SET(b011);hset(p,sto,st,sho,sh,x);happend_to_vlist(p);}break;
+case TAG(hset_kind,b100):{pointer p;HGET_SET(b100);hset(p,sto,st,sho,sh,x);happend_to_vlist(p);}break;
+case TAG(hset_kind,b101):{pointer p;HGET_SET(b101);hset(p,sto,st,sho,sh,x);happend_to_vlist(p);}break;
+case TAG(hset_kind,b110):{pointer p;HGET_SET(b110);hset(p,sto,st,sho,sh,x);happend_to_vlist(p);}break;
+case TAG(hset_kind,b111):{pointer p;HGET_SET(b111);hset(p,sto,st,sho,sh,x);happend_to_vlist(p);}break;
+
+case TAG(vset_kind,b000):{pointer p;HGET_SET(b000);vset(p,sto,st,sho,sh,x);happend_to_vlist(p);}break;
+case TAG(vset_kind,b001):{pointer p;HGET_SET(b001);vset(p,sto,st,sho,sh,x);happend_to_vlist(p);}break;
+case TAG(vset_kind,b010):{pointer p;HGET_SET(b010);vset(p,sto,st,sho,sh,x);happend_to_vlist(p);}break;
+case TAG(vset_kind,b011):{pointer p;HGET_SET(b011);vset(p,sto,st,sho,sh,x);happend_to_vlist(p);}break;
+case TAG(vset_kind,b100):{pointer p;HGET_SET(b100);vset(p,sto,st,sho,sh,x);happend_to_vlist(p);}break;
+case TAG(vset_kind,b101):{pointer p;HGET_SET(b101);vset(p,sto,st,sho,sh,x);happend_to_vlist(p);}break;
+case TAG(vset_kind,b110):{pointer p;HGET_SET(b110);vset(p,sto,st,sho,sh,x);happend_to_vlist(p);}break;
+case TAG(vset_kind,b111):{pointer p;HGET_SET(b111);vset(p,sto,st,sho,sh,x);happend_to_vlist(p);}break;
+/*:125*//*130:*/
+#line 2119 "hint.w"
+
+case TAG(hpack_kind,b000):HGET_PACK(hpack_kind,b000);break;
+case TAG(hpack_kind,b010):HGET_PACK(hpack_kind,b010);break;
+case TAG(hpack_kind,b100):HGET_PACK(hpack_kind,b100);break;
+case TAG(hpack_kind,b110):HGET_PACK(hpack_kind,b110);break;
+case TAG(hpack_kind,b001):HGET_PACK(hpack_kind,b001);break;
+case TAG(hpack_kind,b011):HGET_PACK(hpack_kind,b011);break;
+case TAG(hpack_kind,b101):HGET_PACK(hpack_kind,b101);break;
+case TAG(hpack_kind,b111):HGET_PACK(hpack_kind,b111);break;
+
+case TAG(vpack_kind,b000):HGET_PACK(vpack_kind,b000);break;
+case TAG(vpack_kind,b010):HGET_PACK(vpack_kind,b010);break;
+case TAG(vpack_kind,b100):HGET_PACK(vpack_kind,b100);break;
+case TAG(vpack_kind,b110):HGET_PACK(vpack_kind,b110);break;
+case TAG(vpack_kind,b001):HGET_PACK(vpack_kind,b001);break;
+case TAG(vpack_kind,b011):HGET_PACK(vpack_kind,b011);break;
+case TAG(vpack_kind,b101):HGET_PACK(vpack_kind,b101);break;
+case TAG(vpack_kind,b111):HGET_PACK(vpack_kind,b111);break;
+/*:130*//*134:*/
+#line 2186 "hint.w"
+
+case TAG(kern_kind,b000):{HGET_KERN(b000);}break;
+case TAG(kern_kind,b001):{HGET_KERN(b001);}break;
+case TAG(kern_kind,b010):{HGET_KERN(b010);}break;
+case TAG(kern_kind,b011):{HGET_KERN(b011);}break;
+case TAG(kern_kind,b100):{HGET_KERN(b100);}break;
+case TAG(kern_kind,b101):{HGET_KERN(b101);}break;
+case TAG(kern_kind,b110):{HGET_KERN(b110);}break;
+case TAG(kern_kind,b111):{HGET_KERN(b111);}break;
+/*:134*//*138:*/
+#line 2235 "hint.w"
+
+case TAG(leaders_kind,0):tail_append(hget_leaders_ref(HGET8));break;
+case TAG(leaders_kind,1):HGET_LEADERS(1);break;
+case TAG(leaders_kind,2):HGET_LEADERS(2);break;
+case TAG(leaders_kind,3):HGET_LEADERS(3);break;
+case TAG(leaders_kind,b100|1):HGET_LEADERS(b100|1);break;
+case TAG(leaders_kind,b100|2):HGET_LEADERS(b100|2);break;
+case TAG(leaders_kind,b100|3):HGET_LEADERS(b100|3);break;
+/*:138*//*142:*/
+#line 2275 "hint.w"
+
+case TAG(baseline_kind,b000):{cur_list.bs_pos= hpos-1;hget_baseline_ref(HGET8);}break;
+case TAG(baseline_kind,b010):{HGET_BASELINE(b010);}break;
+case TAG(baseline_kind,b011):{HGET_BASELINE(b011);}break;
+case TAG(baseline_kind,b100):{HGET_BASELINE(b100);}break;
+case TAG(baseline_kind,b101):{HGET_BASELINE(b101);}break;
+case TAG(baseline_kind,b110):{HGET_BASELINE(b110);}break;
+case TAG(baseline_kind,b111):{HGET_BASELINE(b111);}break;
+/*:142*//*147:*/
+#line 2335 "hint.w"
+
+case TAG(ligature_kind,0):tail_append(hget_ligature_ref(HGET8));break;
+case TAG(ligature_kind,1):HGET_LIG(1);break;
+case TAG(ligature_kind,2):HGET_LIG(2);break;
+case TAG(ligature_kind,3):HGET_LIG(3);break;
+case TAG(ligature_kind,4):HGET_LIG(4);break;
+case TAG(ligature_kind,5):HGET_LIG(5);break;
+case TAG(ligature_kind,6):HGET_LIG(6);break;
+case TAG(ligature_kind,7):HGET_LIG(7);break;
+/*:147*//*151:*/
+#line 2385 "hint.w"
+
+case TAG(disc_kind,b000):tail_append(hget_hyphen_ref(HGET8));break;
+case TAG(disc_kind,b001):{HGET_DISC(b001);tail_append(p);}break;
+case TAG(disc_kind,b010):{HGET_DISC(b010);tail_append(p);}break;
+case TAG(disc_kind,b011):{HGET_DISC(b011);tail_append(p);}break;
+case TAG(disc_kind,b100):{HGET_DISC(b100);tail_append(p);}break;
+case TAG(disc_kind,b101):{HGET_DISC(b101);tail_append(p);}break;
+case TAG(disc_kind,b110):{HGET_DISC(b110);tail_append(p);}break;
+case TAG(disc_kind,b111):{HGET_DISC(b111);tail_append(p);}break;
+/*:151*//*156:*/
+#line 2448 "hint.w"
+
+case TAG(par_kind,b000):HGET_PAR(b000);break;
+case TAG(par_kind,b010):HGET_PAR(b010);break;
+case TAG(par_kind,b100):HGET_PAR(b100);break;
+case TAG(par_kind,b110):HGET_PAR(b110);break;
+/*:156*//*174:*/
+#line 2944 "hint.w"
+
+case TAG(math_kind,b000):HGET_MATH(b000);break;
+case TAG(math_kind,b001):HGET_MATH(b001);break;
+case TAG(math_kind,b010):HGET_MATH(b010);break;
+case TAG(math_kind,b100):HGET_MATH(b100);break;
+case TAG(math_kind,b101):HGET_MATH(b101);break;
+case TAG(math_kind,b110):HGET_MATH(b110);break;
+/*:174*//*176:*/
+#line 2973 "hint.w"
+
+case TAG(math_kind,b111):tail_append(new_math(0,before));break;
+case TAG(math_kind,b011):tail_append(new_math(0,after));break;
+/*:176*//*179:*/
+#line 2999 "hint.w"
+
+case TAG(adjust_kind,1):HGET_ADJUST(1);break;
+/*:179*//*182:*/
+#line 3027 "hint.w"
+
+case TAG(table_kind,b000):HGET_TABLE(b000);break;
+case TAG(table_kind,b001):HGET_TABLE(b001);break;
+case TAG(table_kind,b010):HGET_TABLE(b010);break;
+case TAG(table_kind,b011):HGET_TABLE(b011);break;
+case TAG(table_kind,b100):HGET_TABLE(b100);break;
+case TAG(table_kind,b101):HGET_TABLE(b101);break;
+case TAG(table_kind,b110):HGET_TABLE(b110);break;
+case TAG(table_kind,b111):HGET_TABLE(b111);break;
+
+case TAG(item_kind,b000):hget_list_pointer();break;
+case TAG(item_kind,b001):hget_content();break;
+case TAG(item_kind,b010):hget_content();break;
+case TAG(item_kind,b011):hget_content();break;
+case TAG(item_kind,b100):hget_content();break;
+case TAG(item_kind,b101):hget_content();break;
+case TAG(item_kind,b110):hget_content();break;
+case TAG(item_kind,b111):(void)HGET8;hget_content();break;
+/*:182*//*187:*/
+#line 3123 "hint.w"
+
+case TAG(stream_kind,b000):HGET_STREAM(b000);break;
+case TAG(stream_kind,b010):HGET_STREAM(b010);break;
+/*:187*//*191:*/
+#line 3160 "hint.w"
+
+case TAG(image_kind,b000):hget_image_ref(HGET8);break;
+case TAG(image_kind,b100):HGET_IMAGE(b100);break;
+case TAG(image_kind,b101):HGET_IMAGE(b101);break;
+case TAG(image_kind,b110):HGET_IMAGE(b110);break;
+case TAG(image_kind,b111):HGET_IMAGE(b111);break;
+/*:191*//*195:*/
+#line 3198 "hint.w"
+
+case TAG(link_kind,b000):HGET_LINK(b000);break;
+case TAG(link_kind,b001):HGET_LINK(b001);break;
+case TAG(link_kind,b010):HGET_LINK(b010);break;
+case TAG(link_kind,b011):HGET_LINK(b011);break;
+/*:195*/
+#line 1186 "hint.w"
+
+default:
+TAGERR(a);
+}
+}
+
+void hget_content(void)
+{/*74:*/
+#line 1161 "hint.w"
+
+uint8_t a,z;
+HGETTAG(a);
+/*:74*/
+#line 1193 "hint.w"
+
+node_pos= (hpos-hstart)-1;
+hget_node(a);
+/*75:*/
+#line 1166 "hint.w"
+
+HGETTAG(z);
+if(a!=z)
+QUIT("Tag mismatch [%s,%d]!=[%s,%d] at 0x%x to "SIZE_F"\n",
+NAME(a),INFO(a),NAME(z),INFO(z),node_pos,hpos-hstart-1);
+/*:75*/
+#line 1196 "hint.w"
+
+if(nest_ptr==0&&tail!=head&&(type(tail)==penalty_node||type(tail)==glue_node||type(tail)==kern_node))
+store_map(tail,node_pos,0);
+}
+
+static pointer hget_definition(uint8_t a)
+{pointer p;
+if(link(head)!=null)QUIT("Calling get_node with nonempty curent list");
+hget_node(a);
+p= link(head);
+if(p!=null&&link(p)!=null)QUIT("get_node returns multiple nodes");
+link(head)= null;
+tail= head;
+return p;
+}
+/*:76*//*163:*/
+#line 2769 "hint.w"
+
+void set_line_break_params(void)
+{hset_param_list(line_break_params);
+}
+/*:163*//*199:*/
+#line 3331 "hint.w"
+
+pointer skip(uint8_t n)
+{return cur_page->s[n].g;}
+pointer*box_ptr(uint8_t n)
+{return&streams[n].p;}
+int count(uint8_t n)
+{return cur_page->s[n].f;}
+scaled dimen(uint8_t n)
+{return xdimen(&cur_page->s[n].x);}
+
+/*:199*//*200:*/
+#line 3356 "hint.w"
+
+void hpage_init(void)
+{int i;
+if(streams==NULL||cur_page==NULL)return;
+for(i= 0;i<=max_ref[stream_kind];i++)
+if(streams[i].p!=null)
+{flush_node_list(streams[i].p);
+streams[i].p= streams[i].t= null;
+}
+page_contents= empty;page_tail= page_head;link(page_head)= null;
+hset_cur_page();
+hset_margins();
+page_depth= page_height= 0;
+memset(top_so_far,0,sizeof(top_so_far));
+max_depth= cur_page->d;
+if(top_skip!=cur_page->g)
+{delete_glue_ref(top_skip);
+top_skip= cur_page->g;
+add_glue_ref(top_skip);
+}
+}
+/*:200*//*202:*/
+#line 3387 "hint.w"
+
+void hflush_contribution_list(void)
+{if(link(contrib_head)!=null)
+{flush_node_list(link(contrib_head));
+link(contrib_head)= null;tail= contrib_head;
+}
+}
+/*:202*//*204:*/
+#line 3431 "hint.w"
+
+static bool hbuild_page_up(void)
+{
+static scaled page_top_height;
+pointer p;
+pointer q,r;
+int b,c;
+int pi= 0;
+if(link(contrib_head)==null)return false;
+do{p= link(contrib_head);
+/*209:*/
+#line 3553 "hint.w"
+
+switch(type(p)){
+case hlist_node:case vlist_node:case rule_node:
+/*206:*/
+#line 3497 "hint.w"
+
+if(page_contents<box_there)
+{if(page_contents==empty)freeze_page_specs(box_there);
+else page_contents= box_there;
+if(depth(p)> page_max_depth)
+page_total= depth(p)-page_max_depth;
+depth(p)= 0;
+/*207:*/
+#line 3523 "hint.w"
+
+{page_top_height= width(top_skip);
+page_total= page_total+page_top_height;
+}
+/*:207*/
+#line 3504 "hint.w"
+
+}
+/*208:*/
+#line 3532 "hint.w"
+
+{int i;
+for(i= 1;i<=6;i++)
+{page_so_far[i]+= top_so_far[i];
+top_so_far[i]= 0;
+}
+}
+/*:208*/
+#line 3506 "hint.w"
+
+page_total+= page_height+depth(p);
+if(height(p)> page_top_height)
+{page_total= page_total+height(p)-page_top_height;
+page_height= page_top_height;
+}
+else
+page_height= height(p);
+/*:206*/
+#line 3556 "hint.w"
+goto contribute;
+case whatsit_node:goto contribute;
+case glue_node:/*212:*/
+#line 3591 "hint.w"
+
+if(link(p)==null)return false;
+/*213:*/
+#line 3598 "hint.w"
+
+#define top_shrink top_so_far[6]
+#define top_total top_so_far[1]
+
+{pointer q= glue_ptr(p);
+top_so_far[2+stretch_order(q)]+= stretch(q);
+if((shrink_order(q)!=normal)&&(shrink(q)!=0))
+DBG(DBGTEX,"Infinite glue shrinkage found on current page");
+top_shrink+= shrink(q);
+top_total+= width(q);
+}
+/*:213*/
+#line 3593 "hint.w"
+
+if(page_contents==empty||!precedes_break(link(p)))goto contribute;
+pi= 0;
+/*:212*/
+#line 3558 "hint.w"
+break;
+case kern_node:/*214:*/
+#line 3614 "hint.w"
+
+top_total+= width(p);
+if(page_contents==empty||
+link(page_head)==null||
+type(link(page_head))!=glue_node)
+goto contribute;
+pi= 0;
+/*:214*/
+#line 3559 "hint.w"
+break;
+case penalty_node:if(page_contents==empty)goto done1;else pi= penalty(p);break;
+case ins_node:happend_insertion(p);goto contribute;
+default:DBG(DBGTEX,"Unexpected node type %d in build_page_up ignored\n",type(p));
+}
+/*217:*/
+#line 3648 "hint.w"
+
+if(pi<inf_penalty)
+{/*215:*/
+#line 3628 "hint.w"
+
+/*216:*/
+#line 3639 "hint.w"
+
+if(page_total<page_goal)
+{if((page_so_far[3]!=0)||(page_so_far[4]!=0)||(page_so_far[5]!=0))b= 0;
+else b= badness(page_goal-page_total,page_so_far[2]);
+}
+else if(page_total-page_goal> page_shrink)b= awful_bad;
+else b= badness(page_total-page_goal,page_shrink)
+/*:216*/
+#line 3629 "hint.w"
+;
+if(b<awful_bad)
+{if(pi<=eject_penalty)c= pi;
+else if(b<inf_bad)c= b+pi+insert_penalties;
+else c= deplorable;
+}
+else c= b;
+if(insert_penalties>=10000)c= awful_bad;
+/*:215*/
+#line 3650 "hint.w"
+
+if(c<=least_page_cost)
+{best_page_break= p;best_size= page_goal;
+least_page_cost= c;
+r= link(page_ins_head);
+while(r!=page_ins_head)
+{best_ins_ptr(r)= last_ins_ptr(r);
+r= link(r);
+}
+}
+if((c==awful_bad)||(pi<=eject_penalty))
+{
+/*218:*/
+#line 3678 "hint.w"
+
+if(p!=best_page_break)
+{while(link(page_head)!=best_page_break)
+{q= link(page_head);
+link(page_head)= link(q);
+link(q)= null;
+link(q)= link(head);
+link(head)= q;
+}
+}
+/*:218*/
+#line 3662 "hint.w"
+
+/*219:*/
+#line 3696 "hint.w"
+
+hloc_set_prev(link(page_head));
+while(true){
+q= link(page_head);
+if(q==null)return false;
+else if(q==best_page_break)
+break;
+else if(type(q)==penalty_node||type(q)==glue_node||type(q)==kern_node)
+{link(page_head)= link(q);link(q)= null;flush_node_list(q);}
+else break;
+}
+temp_ptr= new_spec(top_skip);
+q= new_glue(temp_ptr);glue_ref_count(temp_ptr)= null;
+if(width(temp_ptr)> page_height)width(temp_ptr)= width(temp_ptr)-page_height;
+else width(temp_ptr)= 0;
+link(q)= link(page_head);
+link(page_head)= q;
+best_page_break= null;
+/*:219*/
+#line 3663 "hint.w"
+
+hpack_page();
+hfill_page_template();
+return true;
+}
+}
+/*:217*/
+#line 3564 "hint.w"
+
+contribute:
+/*210:*/
+#line 3571 "hint.w"
+
+link(contrib_head)= link(p);
+link(p)= link(page_head);
+if(link(page_head)==null)page_tail= p;
+link(page_head)= p;
+goto done;
+/*:210*/
+#line 3566 "hint.w"
+
+done1:/*211:*/
+#line 3579 "hint.w"
+
+link(contrib_head)= link(p);link(p)= null;flush_node_list(p);
+/*:211*/
+#line 3567 "hint.w"
+
+done:
+/*:209*/
+#line 3441 "hint.w"
+;
+}while(link(contrib_head)!=null);
+tail= contrib_head;
+return false;
+}
+/*:204*//*221:*/
+#line 3772 "hint.w"
+
+static void clear_map(void)
+{memset(map,0,sizeof(map));
+}
+/*:221*//*222:*/
+#line 3785 "hint.w"
+
+void store_map(pointer p,uint32_t pos0,uint32_t offset)
+{map[p]= pos0;
+map[p+1]= offset;
+}
+
+uint32_t hposition(pointer p)
+{return map[p];
+}
+/*:222*//*229:*/
+#line 3895 "hint.w"
+
+void hloc_init(void)
+{cur_loc= 0;
+hloc_clear();
+page_loc[cur_loc]= 0;
+DBG(DBGPAGE,"loc_init: %d < %d < %d\n",lo_loc,cur_loc,hi_loc);
+}
+/*:229*//*234:*/
+#line 4031 "hint.w"
+
+int hint_begin(void)
+{if(!hint_map())return 0;
+hpos= hstart= hin_addr;
+hend= hstart+hin_size;
+hflush_contribution_list();hpage_init();
+flush_node_list(link(page_head));
+free_definitions();
+mem_init();
+list_init();
+hclear_dir();
+hclear_fonts();
+hget_banner();
+if(!hcheck_banner("hint"))
+{hint_unmap();return 0;}
+hget_directory();
+hget_definition_section();
+hget_content_section();
+leak_clear();
+clear_map();
+hloc_init();
+return 1;
+}
+
+void hint_end(void)
+{if(hin_addr==NULL)return;
+hint_unmap();
+hin_addr= hpos= hstart= hend= NULL;
+hflush_contribution_list();hpage_init();
+flush_node_list(link(page_head));
+free_definitions();
+list_leaks();
+hclear_dir();
+}
+/*:234*//*238:*/
+#line 4125 "hint.w"
+
+bool hint_forward(void)
+{hpage_init();
+if(hbuild_page())return true;
+while(hpos<hend)
+{hget_content();
+if(hbuild_page())return true;
+}
+while(!flush_pages(hend-hstart))
+if(hbuild_page())return true;
+return false;
+}
+/*:238*//*239:*/
+#line 4166 "hint.w"
+
+bool hint_backward(void)
+{hpage_init();
+if(hbuild_page_up())return true;
+while(hpos> hstart)
+{hteg_content();
+if(hbuild_page_up())return true;
+}
+while(!flush_pages(0x0))
+if(hbuild_page_up())return true;
+return false;
+}
+/*:239*//*241:*/
+#line 4194 "hint.w"
+
+bool flush_pages(uint32_t pos)
+{pointer p= link(head);
+while(p!=null&&
+(type(p)==penalty_node||type(p)==glue_node||type(p)==kern_node))
+p= link(p);
+if(p==null&&link(page_head)==null)return true;
+tail_append(new_null_box());
+width(tail)= hhsize;
+tail_append(hget_param_glue(fill_skip_no));
+store_map(tail,pos,0);
+tail_append(new_penalty(-010000000000));
+store_map(tail,pos,0);
+return false;
+}
+/*:241*//*263:*/
+#line 4707 "hint.w"
+
+int hint_get_outline_max(void)
+{return max_outline;}
+/*:263*//*268:*/
+#line 4787 "hint.w"
+
+hint_outline_t*hint_get_outlines(void)
+{return hint_outlines;
+}
+/*:268*//*270:*/
+#line 4846 "hint.w"
+
+static bool trv_ignore= false;
+static bool trv_skip_space= false;
+static void(*trv_stream)(uint32_t c);
+void trv_init(void(*f)(uint32_t c))
+{trv_ignore= false;trv_skip_space= false;trv_stream= f;}
+
+static void trv_char(uint32_t c)
+{if(c==0x20)trv_skip_space= true;
+else
+{if(trv_skip_space)
+{trv_skip_space= false;trv_stream(0x20);}
+trv_stream(c);
+}
+}
+
+void trv_hlist(pointer p)
+{while(p!=null)
+{if(is_char_node(p))
+{if(!trv_ignore)trv_char(character(p));
+}
+else switch(type(p))
+{case hlist_node:if(list_ptr(p)!=null)trv_hlist(list_ptr(p));break;
+case vlist_node:if(list_ptr(p)!=null)trv_vlist(list_ptr(p));break;
+case ligature_node:
+if(!trv_ignore)
+{pointer q= lig_ptr(p);
+while(q!=null)
+{trv_char(character(q));
+q= link(q);
+}
+}
+break;
+case glue_node:
+if(!trv_ignore)trv_skip_space= true;
+break;
+case whatsit_node:
+if(subtype(p)==ignore_node)
+{if(ignore_info(p)==1)
+{trv_hlist(ignore_list(p));
+trv_ignore= true;
+}
+else
+trv_ignore= false;
+}
+break;
+default:break;
+}
+p= link(p);
+}
+}
+
+void trv_vlist(pointer p)
+{while(p!=null)
+{switch(type(p))
+{case hlist_node:if(list_ptr(p)!=null)trv_hlist(list_ptr(p));
+if(!trv_ignore)trv_skip_space= true;
+break;
+case vlist_node:if(list_ptr(p)!=null)trv_vlist(list_ptr(p));break;
+default:break;
+}
+p= link(p);
+}
+}
+/*:270*/
+#line 7530 "hint.w"
+
+
+/*:371*/

Added: trunk/Build/source/texk/web2c/hitexdir/hintview/src/hint.h
===================================================================
--- trunk/Build/source/texk/web2c/hitexdir/hintview/src/hint.h	                        (rev 0)
+++ trunk/Build/source/texk/web2c/hitexdir/hintview/src/hint.h	2022-01-19 13:28:43 UTC (rev 61658)
@@ -0,0 +1,167 @@
+/*370:*/
+#line 7493 "hint.w"
+
+#ifndef _HINT_H_
+#define _HINT_H_
+
+typedef uint16_t pointer;
+typedef int scaled;
+
+/*44:*/
+#line 728 "hint.w"
+
+extern void hrestore_param_list(void);
+/*:44*//*49:*/
+#line 783 "hint.w"
+
+typedef struct{
+pointer p,t;
+}stream_t;
+extern stream_t*streams;
+/*:49*//*64:*/
+#line 1009 "hint.w"
+
+extern void hfill_page_template(void);
+/*:64*//*77:*/
+#line 1213 "hint.w"
+
+void hget_content(void);
+/*:77*//*81:*/
+#line 1268 "hint.w"
+
+extern void hteg_content(void);
+/*:81*//*164:*/
+#line 2774 "hint.w"
+
+extern void set_line_break_params(void);
+/*:164*//*166:*/
+#line 2814 "hint.w"
+
+extern void hget_par_node(uint32_t offset);
+/*:166*//*171:*/
+#line 2914 "hint.w"
+
+extern void hteg_par_node(uint32_t offset);
+/*:171*//*197:*/
+#line 3267 "hint.w"
+
+extern pointer*pointer_def[32];
+extern scaled*dimen_def;
+extern int32_t*integer_def;
+/*:197*//*198:*/
+#line 3322 "hint.w"
+
+extern stream_t*streams;
+extern bool flush_pages(uint32_t pos);
+extern pointer skip(uint8_t n);
+extern pointer*box_ptr(uint8_t n);
+extern int count(uint8_t n);
+extern scaled dimen(uint8_t n);
+/*:198*//*201:*/
+#line 3379 "hint.w"
+
+extern void hpage_init(void);
+/*:201*//*203:*/
+#line 3396 "hint.w"
+
+extern void hflush_contribution_list(void);
+/*:203*//*223:*/
+#line 3799 "hint.w"
+
+#define HINT_NO_LOC 0xFFFFFFFFFFFFFFFF
+#define PAGE_LOC(POS0,OFF) (((uint64_t)((POS0)+(OFF))<<32) + (uint64_t)(OFF))
+#define LOC_POS(P) ((P)>>32) 
+#define LOC_OFF(P) ((P)&0xFFFFFFFF) 
+#define LOC_POS0(P) (LOC_POS(P)-LOC_OFF(P)) 
+/*:223*//*226:*/
+#line 3836 "hint.w"
+
+extern uint64_t page_loc[];
+extern int cur_loc;
+/*:226*//*228:*/
+#line 3885 "hint.w"
+
+extern void hloc_clear(void);
+extern bool hloc_next(void);
+extern bool hloc_prev(void);
+extern uint64_t hlocation(pointer p);
+/*:228*//*233:*/
+#line 4000 "hint.w"
+
+extern void hloc_init(void);
+extern void store_map(pointer p,uint32_t pos,uint32_t offset);
+extern uint32_t hposition(pointer p);
+extern void hloc_set(uint64_t h);
+extern void hloc_set_next(pointer p);
+/*:233*//*235:*/
+#line 4068 "hint.w"
+
+extern int hint_begin(void);
+extern void hint_end(void);
+extern bool hint_map(void);
+extern void hint_unmap(void);
+/*:235*//*240:*/
+#line 4184 "hint.w"
+
+extern bool hint_forward(void);
+extern bool hint_backward(void);
+/*:240*//*243:*/
+#line 4215 "hint.w"
+
+extern scaled hvsize,hhsize;
+/*:243*//*264:*/
+#line 4720 "hint.w"
+
+typedef struct{
+uint64_t pos;
+uint8_t depth;
+uint8_t where;
+int p;
+char*title;
+}hint_outline_t;
+extern hint_outline_t*hint_outlines;
+/*:264*//*265:*/
+#line 4738 "hint.w"
+
+#define LABEL_UNDEF 0
+#define LABEL_TOP 1
+#define LABEL_BOT 2
+#define LABEL_MID 3
+/*:265*//*269:*/
+#line 4797 "hint.w"
+
+extern int hint_get_outline_max(void);
+extern hint_outline_t*hint_get_outlines(void);
+extern uint64_t hint_outline_page(int i);
+/*:269*//*271:*/
+#line 4912 "hint.w"
+
+extern void trv_init(void(*f)(uint32_t c));
+extern void trv_vlist(pointer p);
+extern void trv_hlist(pointer p);
+/*:271*//*300:*/
+#line 5504 "hint.w"
+
+typedef struct{
+uint64_t pos;
+uint8_t where;
+int top,bottom,left,right;
+}hint_link_t;
+extern hint_link_t*hint_links;
+extern int max_link;
+/*:300*//*305:*/
+#line 5666 "hint.w"
+
+extern int hint_find_link(scaled x,scaled y,scaled precission);
+extern uint64_t hint_link_page(int i);
+/*:305*//*369:*/
+#line 7476 "hint.w"
+
+extern void leak_in(pointer p,int s);
+extern void leak_out(pointer p,int s);
+/*:369*/
+#line 7500 "hint.w"
+
+
+#endif
+/*:370*/

Added: trunk/Build/source/texk/web2c/hitexdir/hintview/src/hrender.c
===================================================================
--- trunk/Build/source/texk/web2c/hitexdir/hintview/src/hrender.c	                        (rev 0)
+++ trunk/Build/source/texk/web2c/hitexdir/hintview/src/hrender.c	2022-01-19 13:28:43 UTC (rev 61658)
@@ -0,0 +1,1436 @@
+/*373:*/
+#line 7565 "hint.w"
+
+#include "basetypes.h"
+#include "error.h"
+#include "format.h"
+#include <string.h> 
+#include <math.h> 
+#include "get.h"
+#include "hrender.h"
+#include "rendernative.h"
+#include "htex.h"
+#include "hint.h"
+
+/*310:*/
+#line 5748 "hint.w"
+
+extern struct font_s*hget_font(unsigned char f);
+/*:310*//*321:*/
+#line 6086 "hint.w"
+
+extern void render_char(int x,int y,struct font_s*f,uint32_t cc,uint8_t s);
+/*:321*/
+#line 7577 "hint.w"
+
+
+/*236:*/
+#line 4097 "hint.w"
+
+double xdpi= 600.0,ydpi= 600.0;
+/*:236*//*254:*/
+#line 4447 "hint.w"
+
+static bool forward_mode= false,backward_mode= false;
+/*:254*//*273:*/
+#line 4959 "hint.w"
+
+static char*m_str;
+static int m_length,m_chars;
+/*:273*//*277:*/
+#line 5030 "hint.w"
+
+#define MAX_M_DIST 512
+static uint8_t m_dist[MAX_M_DIST+5];
+static int m_ptr,m_max;
+/*:277*//*280:*/
+#line 5131 "hint.w"
+
+static int m_state,m_spaces;
+static uint32_t m_d;
+/*:280*//*285:*/
+#line 5253 "hint.w"
+
+static int m_focus;
+static uint64_t m_page;
+/*:285*//*288:*/
+#line 5289 "hint.w"
+
+static bool c_ignore;
+static int m_style;
+/*:288*//*296:*/
+#line 5458 "hint.w"
+
+static int cur_link= -1;
+/*:296*//*324:*/
+#line 6128 "hint.w"
+
+static scaled cur_h,cur_v;
+static scaled rule_ht,rule_dp,rule_wd;
+static int cur_f;
+static struct font_s*cur_fp;
+static uint8_t cur_style= 0;
+/*:324*/
+#line 7579 "hint.w"
+
+/*237:*/
+#line 4101 "hint.w"
+
+void hint_resize(int px_h,int px_v,double x_dpi,double y_dpi)
+{static int old_px_h= 0,old_px_v= 0;
+static double old_xdpi= 0.0,old_ydpi= 0.0;
+if(old_px_h==px_h&&old_px_v==px_v&&old_xdpi==x_dpi&&old_ydpi==y_dpi)return;
+old_px_h= px_h;old_px_v= px_v;old_xdpi= xdpi= x_dpi;old_ydpi= ydpi= y_dpi;
+nativeSetSize(px_h,px_v,xdpi,ydpi);
+hloc_clear();
+hflush_contribution_list();hpage_init();
+forward_mode= false;
+backward_mode= false;
+}
+/*:237*//*248:*/
+#line 4312 "hint.w"
+
+
+uint64_t hint_page_top(uint64_t h)
+{if(hin_addr==NULL)return 0;
+hpos= hstart+LOC_POS0(h);
+if(hpos>=hend)
+return hint_page_bottom(hend-hstart);
+hflush_contribution_list();
+hloc_set(h);
+if(LOC_OFF(h))
+hget_par_node(LOC_OFF(h));
+hint_forward();
+#if 0
+show_box(streams[0].p);
+#endif
+forward_mode= true;
+backward_mode= false;
+return h;
+}
+/*:248*//*249:*/
+#line 4335 "hint.w"
+
+uint64_t hint_page_get(void)
+{
+DBG(DBGPAGE,"page_get: %d : 0x%"PRIx64"\n",cur_loc,page_loc[cur_loc]);
+
+if(hin_addr==NULL)return 0;
+return page_loc[cur_loc];
+}
+/*:249*//*250:*/
+#line 4351 "hint.w"
+
+uint64_t hint_page(void)
+{uint64_t i;
+if(streams==NULL)return 0;
+i= hint_page_get();
+if(streams[0].p!=null)
+return i;
+else
+return hint_page_top(i);
+}
+/*:250*//*251:*/
+#line 4367 "hint.w"
+
+uint64_t hint_page_home(void)
+{uint64_t pos;
+uint8_t where;
+int n= zero_label_no;
+/*71:*/
+#line 1083 "hint.w"
+
+where= labels[n].where;
+#if 1
+pos= ((uint64_t)labels[n].pos<<32)+(labels[n].pos-labels[n].pos0);
+#else
+pos= ((uint64_t)labels[n].pos0<<32);
+#endif
+/*:71*/
+#line 4372 "hint.w"
+
+/*267:*/
+#line 4760 "hint.w"
+
+if(where==LABEL_TOP)return hint_page_top(pos);
+else if(where==LABEL_BOT)return hint_page_bottom(pos);
+else if(where==LABEL_MID)return hint_page_middle(pos);
+else return hint_page_get();
+/*:267*/
+#line 4373 "hint.w"
+
+}
+/*:251*//*252:*/
+#line 4394 "hint.w"
+
+double hint_get_fpos(void)
+{
+DBG(DBGPAGE,"get_fpos: %d : 0x%"PRIx64"\n",cur_loc,page_loc[cur_loc]);
+
+if(hin_addr==NULL)return 0.0;
+return(double)LOC_POS(page_loc[cur_loc])/(double)(hend-hstart);
+}
+/*:252*//*253:*/
+#line 4408 "hint.w"
+
+uint64_t hint_set_fpos(double fpos)
+{uint32_t pos,pos0;
+uint8_t*p,*q;
+DBG(DBGPAGE,"set_fpos: %f\n",fpos);
+if(hin_addr==NULL)return 0;
+if(fpos<0.0)fpos= 0.0;
+if(fpos> 1.0)fpos= 1.0;
+pos= round((hend-hstart)*fpos);
+p= hstart+pos;
+q= hpos= hstart;
+while(hpos<p)
+{q= hpos;hff_hpos();}
+if(hpos> p)
+{pos= pos0= q-hstart;
+if(KIND(*q)==par_kind&&KIND(hff_tag)==list_kind&&hff_list_size> 0)
+{if(p>=hstart+hff_list_pos+hff_list_size)
+pos= pos0= hpos-hstart;
+else
+{q= hpos= hstart+hff_list_pos;
+while(hpos<=p)
+{if(KIND(*hpos)==glue_kind||KIND(*hpos)==penalty_kind||KIND(*hpos)==disc_kind)
+q= hpos;
+hff_hpos();
+}
+pos= q-hstart;
+}
+}
+}
+else
+pos= pos0= hpos-hstart;
+return hint_page_top(PAGE_LOC(pos0,pos-pos0));
+}
+/*:253*//*255:*/
+#line 4452 "hint.w"
+
+uint64_t hint_page_next(void)
+{if(hin_addr==NULL)return 0;
+if(hloc_next()&&forward_mode)
+{if(!hint_forward())
+{hloc_prev();return hint_page();}
+forward_mode= true;
+backward_mode= false;
+return hint_page_get();
+}
+else
+{hflush_contribution_list();hpage_init();
+return hint_page();
+}
+}
+/*:255*//*256:*/
+#line 4477 "hint.w"
+
+uint64_t hint_page_prev(void)
+{if(hin_addr==NULL)return 0;
+if(hloc_prev())
+{hflush_contribution_list();hpage_init();
+return hint_page();
+}
+else if(backward_mode)
+{if(!hint_backward())return hint_page_top(0);
+backward_mode= true;
+forward_mode= false;
+return hint_page_get();
+}
+else
+return hint_page_bottom(hint_page_get());
+}
+/*:256*//*257:*/
+#line 4503 "hint.w"
+
+uint64_t hint_page_bottom(uint64_t h)
+{if(hin_addr==NULL)return 0;
+hloc_set(h);
+hflush_contribution_list();
+hpos= hstart+LOC_POS0(h);
+if(LOC_OFF(h))
+hteg_par_node(LOC_OFF(h));
+if(!hint_backward())return hint_page();
+backward_mode= true;
+forward_mode= false;
+return hint_page_get();
+}
+/*:257*//*258:*/
+#line 4528 "hint.w"
+
+uint64_t hint_page_middle(uint64_t l)
+{uint32_t pos,pos0,offset;
+pointer p,tp= null;
+scaled h= 0,d= 0,ht= 0,hp,dp;
+int pi= 0;
+if(hin_addr==NULL)return 0;
+pos= LOC_POS(l);
+offset= LOC_OFF(l);
+pos0= LOC_POS0(l);
+if(hstart+pos0+offset>=hend)
+return hint_page_bottom(hend-hstart);
+hflush_contribution_list();
+hpos= hstart+pos0;
+hget_content();
+p= link(contrib_head);
+if(offset> 0)
+{/*259:*/
+#line 4567 "hint.w"
+
+{while(p!=null)
+{/*260:*/
+#line 4594 "hint.w"
+
+switch(type(p))
+{case hlist_node:case vlist_node:case rule_node:
+hp= height(p);dp= depth(p);
+pi= inf_penalty;
+break;
+case glue_node:
+hp= width(glue_ptr(p));dp= 0;
+pi= 0;
+break;
+case kern_node:
+hp= width(p);dp= 0;
+pi= inf_penalty;
+break;
+case penalty_node:
+hp= dp= 0;
+pi= penalty(p);
+break;
+default:
+pi= hp= dp= 0;
+}
+/*:260*/
+#line 4569 "hint.w"
+
+h+= d+hp;
+d= dp;
+if(pi<=0&&tp==null)
+{uint32_t t= LOC_POS(hlocation(p));
+if(t> pos)
+{tp= p;ht= h;
+break;
+}
+}
+p= link(p);
+}
+if(tp==null)ht= h;
+if(ht>=hvsize)
+{/*261:*/
+#line 4621 "hint.w"
+
+pointer q= contrib_head;
+scaled dh= ht-hvsize/2;
+p= link(contrib_head);
+h= d= 0;
+while(p!=null)
+{/*260:*/
+#line 4594 "hint.w"
+
+switch(type(p))
+{case hlist_node:case vlist_node:case rule_node:
+hp= height(p);dp= depth(p);
+pi= inf_penalty;
+break;
+case glue_node:
+hp= width(glue_ptr(p));dp= 0;
+pi= 0;
+break;
+case kern_node:
+hp= width(p);dp= 0;
+pi= inf_penalty;
+break;
+case penalty_node:
+hp= dp= 0;
+pi= penalty(p);
+break;
+default:
+pi= hp= dp= 0;
+}
+/*:260*/
+#line 4627 "hint.w"
+
+h= h+d+hp;
+d= dp;
+if(pi<=0&&h>=dh)break;
+q= p;
+p= link(p);
+}
+if(p!=null)
+{offset= LOC_OFF(hlocation(p));
+link(q)= null;
+flush_node_list(link(contrib_head));
+link(contrib_head)= p;
+}
+/*:261*/
+#line 4583 "hint.w"
+
+goto found;
+}
+}
+/*:259*/
+#line 4545 "hint.w"
+
+}
+else if(p!=null&&type(p)==penalty_node)
+pi= penalty(p);
+/*262:*/
+#line 4646 "hint.w"
+
+{pointer save_h= link(contrib_head);
+pointer save_t= tail;
+uint8_t*save_hpos= hpos;
+pointer best_p= null;
+int best_pi= pi;
+link(contrib_head)= null;p= tail= contrib_head;
+hpos= hstart+pos0;
+h= ht;
+while(h<(hvsize/4*3))
+{while(link(p)==null&&hpos> 0)
+hteg_content();
+if(link(p)==null)
+break;
+else
+p= link(p);
+/*260:*/
+#line 4594 "hint.w"
+
+switch(type(p))
+{case hlist_node:case vlist_node:case rule_node:
+hp= height(p);dp= depth(p);
+pi= inf_penalty;
+break;
+case glue_node:
+hp= width(glue_ptr(p));dp= 0;
+pi= 0;
+break;
+case kern_node:
+hp= width(p);dp= 0;
+pi= inf_penalty;
+break;
+case penalty_node:
+hp= dp= 0;
+pi= penalty(p);
+break;
+default:
+pi= hp= dp= 0;
+}
+/*:260*/
+#line 4662 "hint.w"
+
+h= h+dp+hp;
+if(pi<best_pi)
+{best_pi= pi;
+best_p= p;
+if(best_pi<=eject_penalty)break;
+}
+}
+if(best_p==null)
+{flush_node_list(link(contrib_head));
+hpos= hstart+pos0;
+}
+else
+{p= link(contrib_head);
+do{pointer q;
+q= link(p);
+link(p)= save_h;
+save_h= p;
+p= q;
+}while(save_h!=best_p);
+flush_node_list(p);
+pos0= LOC_POS0(hlocation(best_p));
+offset= 0;
+}
+link(contrib_head)= save_h;
+if(save_t!=contrib_head)
+tail= save_t;
+hpos= save_hpos;
+}
+/*:262*/
+#line 4549 "hint.w"
+
+found:
+hloc_set(PAGE_LOC(pos0,offset));
+if(!hint_forward())return hint_page_top(0);
+forward_mode= true;
+backward_mode= false;
+return hint_page_get();
+}
+/*:258*//*266:*/
+#line 4749 "hint.w"
+
+uint64_t hint_outline_page(int i)
+{uint64_t pos;
+uint8_t where;
+if(i<0||i> max_outline)return hint_page_get();
+pos= hint_outlines[i].pos;
+where= hint_outlines[i].where;
+/*267:*/
+#line 4760 "hint.w"
+
+if(where==LABEL_TOP)return hint_page_top(pos);
+else if(where==LABEL_BOT)return hint_page_bottom(pos);
+else if(where==LABEL_MID)return hint_page_middle(pos);
+else return hint_page_get();
+/*:267*/
+#line 4756 "hint.w"
+
+}
+/*:266*//*274:*/
+#line 4964 "hint.w"
+
+void hint_set_mark(char*m,int s)
+{m_str= m;
+m_length= s;
+/*275:*/
+#line 4975 "hint.w"
+
+if(m_length> 0)
+{int i,j,k;
+for(i= j= k= 0;i<m_length&&m_str[i]==' ';i++)continue;
+for(;i<m_length;i++)
+if(m_str[i]!=' '||m_str[i+1]!=' ')
+{m_str[k]= m_str[i];
+if(m_str[k]==' ')j++;
+k++;
+}
+m_str[k]= 0;
+m_length= k;
+m_chars= m_length-j;
+}
+/*:275*/
+#line 4968 "hint.w"
+
+hmark_page();
+}
+/*:274*//*278:*/
+#line 5064 "hint.w"
+
+static void m_put(uint32_t d)
+{if(m_ptr<MAX_M_DIST)
+{if(d==0xFF)
+m_dist[m_max= m_ptr]= 0xFF;
+else if(d<0x7F)
+m_dist[m_ptr++]= 0x80+d;
+else
+{if(d<(1<<14))
+{
+two_byte:
+m_dist[m_ptr++]= d>>7;
+m_dist[m_ptr++]= 0x80+(d&0x7F);
+return;
+}
+if(d>=(1<<28))m_dist[m_ptr++]= d>>28;
+if(d>=(1<<21))m_dist[m_ptr++]= (d>>21)&0x7F;
+if(d>=(1<<14))m_dist[m_ptr++]= (d>>14)&0x7F;
+d= d&((1<<14)-1);
+goto two_byte;
+}
+}
+}
+
+static uint32_t m_get(void)
+{uint32_t x,y;
+x= m_dist[m_ptr++];
+if(x==0xFF)return HINT_NO_POS;
+if(x&0x80)return x&0x7F;
+while(true)
+{y= m_dist[m_ptr++];
+if(y&0x80)return(x<<7)+(y&0x7F);
+x= (x<<7)+y;
+}
+}
+/*:278*//*279:*/
+#line 5105 "hint.w"
+
+static int m_next(int i)
+{while((0x80&m_dist[i])==0)i++;
+if(m_dist[i]==0xFF)return 0;
+else return i+1;
+}
+
+static int m_prev(int i)
+{if(i<=0)return m_max;
+i--;
+while(i> 0&&(0x80&m_dist[i-1])==0)i--;
+return i;
+}
+/*:279*//*281:*/
+#line 5136 "hint.w"
+
+static void next_m_char(uint32_t c)
+{
+reconsider:
+
+if(m_state==0&&c!=m_str[0])
+{if(c!=' ')
+m_d++;
+}
+else if(c==m_str[m_state])
+{if(m_state==0)m_spaces= 0;
+m_state++;
+if(m_state==m_length)
+{m_put(m_d);
+m_d= 0;
+m_state= 0;
+}
+}
+else
+/*282:*/
+#line 5170 "hint.w"
+
+{int i= 0,j= 0;
+do{
+if(m_str[i]==' ')j++;
+i++;
+}while(i<m_state&&strncmp(m_str,m_str+i,m_state-i)!=0);
+m_d= m_d+i-j;
+m_state= m_state-i;
+goto reconsider;
+}
+/*:282*/
+#line 5155 "hint.w"
+
+
+
+}
+/*:281*//*283:*/
+#line 5183 "hint.w"
+
+#if 0
+static void next_m_space(void)
+{if(m_state==0&&m_str[0]==' ')
+{m_state= -1;m_spaces= 1;}
+else if(m_state>=0&&m_str[m_state]==' ')
+{if(m_state==0)m_spaces= 0;
+m_state++;m_spaces++;
+if(m_state==m_length)
+{m_put(m_d);
+m_d= 0;
+m_state= 0;
+}
+else
+m_state= -m_state;
+}
+else if(m_state> 0)
+{m_d= m_d+m_state-m_spaces;m_state= 0;}
+}
+#endif
+/*:283*//*284:*/
+#line 5206 "hint.w"
+
+#if 0
+static void vlist_mark(pointer p);
+static void hlist_mark(pointer p)
+{while(p!=null)
+{if(is_char_node(p)&&!m_ignore)next_m_char(character(p));
+else switch(type(p))
+{case hlist_node:if(list_ptr(p)!=null)hlist_mark(list_ptr(p));break;
+case vlist_node:if(list_ptr(p)!=null)vlist_mark(list_ptr(p));break;
+case ligature_node:
+{pointer q= lig_ptr(p);
+while(q!=null)
+{if(!m_ignore)next_m_char(character(q));q= link(q);
+}
+}
+break;
+case glue_node:if(!m_ignore)next_m_space();break;
+case whatsit_node:
+if(subtype(p)==ignore_node)
+{if(ignore_info(p)==1)
+{hlist_mark(ignore_list(p));
+m_ignore= 1;
+}
+else
+m_ignore= 0;
+}
+break;
+default:break;
+}
+p= link(p);
+}
+}
+
+static void vlist_mark(pointer p)
+{while(p!=null)
+{switch(type(p))
+{case hlist_node:if(list_ptr(p)!=null)hlist_mark(list_ptr(p));
+if(!m_ignore)next_m_space();break;
+case vlist_node:if(list_ptr(p)!=null)vlist_mark(list_ptr(p));break;
+default:break;
+}
+p= link(p);
+}
+}
+#endif
+/*:284*//*286:*/
+#line 5259 "hint.w"
+
+void hmark_page(void)
+{if(streams==NULL||streams[0].p==null)return;
+m_ptr= 0;
+if(m_page!=page_loc[cur_loc])
+{m_page= page_loc[cur_loc];
+m_focus= 0;
+}
+if(m_length> 0)
+{m_d= 0;
+m_state= 0;
+trv_init(next_m_char);
+if(type(streams[0].p)==vlist_node)
+trv_vlist(list_ptr(streams[0].p));
+else
+trv_hlist(list_ptr(streams[0].p));
+}
+m_put(0xFF);
+if(m_focus>=m_max)m_focus= 0;
+}
+/*:286*//*293:*/
+#line 5374 "hint.w"
+
+void c_ignore_list(pointer p)
+{while(p!=null)
+{if(is_char_node(p))
+{/*290:*/
+#line 5314 "hint.w"
+
+{while(m_d==0)
+{m_style^= MARK_BIT;
+if(m_style&MARK_BIT)
+{if(m_ptr==m_focus)m_style|= FOCUS_BIT;else m_style&= ~FOCUS_BIT;
+m_d= m_chars;
+}
+else
+{m_style&= ~FOCUS_BIT;
+m_d= m_get();
+}
+}
+m_d--;
+}
+/*:290*/
+#line 5378 "hint.w"
+
+cur_style|= m_style;
+}
+else
+{switch(type(p))
+{case hlist_node:
+case vlist_node:c_ignore_list(list_ptr(p));break;
+case ligature_node:
+{pointer q= lig_ptr(p);
+while(q!=null)
+{/*290:*/
+#line 5314 "hint.w"
+
+{while(m_d==0)
+{m_style^= MARK_BIT;
+if(m_style&MARK_BIT)
+{if(m_ptr==m_focus)m_style|= FOCUS_BIT;else m_style&= ~FOCUS_BIT;
+m_d= m_chars;
+}
+else
+{m_style&= ~FOCUS_BIT;
+m_d= m_get();
+}
+}
+m_d--;
+}
+/*:290*/
+#line 5388 "hint.w"
+
+cur_style|= m_style;
+q= link(q);
+}
+}
+break;
+}
+}
+p= link(p);
+}
+}
+/*:293*//*294:*/
+#line 5421 "hint.w"
+
+bool hint_prev_mark(void)
+{m_focus= m_prev(m_focus);
+while(m_focus==0&&m_page> 0)
+{hint_page_prev();
+m_focus= m_prev(0);
+}
+return(m_focus!=0);
+}
+
+bool hint_next_mark(void)
+{m_focus= m_next(m_focus);
+while(m_focus==0)
+{uint64_t p= m_page;
+if(p==hint_page_next())break;
+m_focus= m_next(0);
+}
+return(m_focus!=0);
+}
+/*:294*//*302:*/
+#line 5522 "hint.w"
+
+static int links_allocated= 0;
+void add_new_link(int n,pointer p,scaled h,scaled v)
+{hint_link_t*t;
+uint64_t pos;
+uint8_t where;
+max_link++;
+if(max_link>=links_allocated)
+{if(links_allocated<=0)
+{links_allocated= 32;
+ALLOCATE(hint_links,links_allocated,hint_link_t);
+}
+else
+{links_allocated= links_allocated*1.4142136+0.5;
+REALLOCATE(hint_links,links_allocated,hint_link_t);
+}
+}
+t= hint_links+max_link;
+REF_RNG(label_kind,n);
+/*71:*/
+#line 1083 "hint.w"
+
+where= labels[n].where;
+#if 1
+pos= ((uint64_t)labels[n].pos<<32)+(labels[n].pos-labels[n].pos0);
+#else
+pos= ((uint64_t)labels[n].pos0<<32);
+#endif
+/*:71*/
+#line 5541 "hint.w"
+
+t->where= where;
+t->pos= pos;
+if(type(p)==hlist_node)
+{scaled hp= height(p),dp= depth(p);
+t->top= v-hp;
+t->bottom= v+dp;
+t->left= h;
+t->right= h;
+}
+else
+{t->top= v;
+t->bottom= v;
+t->left= h;
+t->right= h+width(p);
+}
+}
+
+void end_new_link(int n,pointer p,scaled h,scaled v)
+{hint_link_t*t;
+t= hint_links+max_link;
+if(type(p)==hlist_node)
+t->right= h;
+else
+t->bottom= v;
+}
+/*:302*//*303:*/
+#line 5591 "hint.w"
+
+static scaled hlink_distance(scaled x,scaled y,hint_link_t*t)
+{scaled d,dx= 0,dy= 0;
+d= t->top-y;
+if(d> 0)dy= d;
+else
+{d= y-t->bottom;
+if(d> 0)dy= d;
+}
+d= x-t->right;
+if(d> 0)dx= d;
+else
+{d= t->left-x;
+if(d> 0)dx= d;
+}
+if(dx> dy)return dx;
+else return dy;
+
+}
+int hint_find_link(scaled x,scaled y,scaled precission)
+{static int last_hit= -1;
+int i;
+hint_link_t*t;
+if(max_link<0)return-1;
+if(last_hit<0||last_hit> max_link)last_hit= max_link/2;
+i= last_hit;
+t= hint_links+i;
+if(hlink_distance(x,y,t)<=precission)
+return i;
+else if(y<t->top)
+{while(i> 0)
+{i--;
+t= hint_links+i;
+if(hlink_distance(x,y,t)<=precission)
+{last_hit= i;return i;}
+}
+return-1;
+}
+else
+{int k;
+scaled d,min_d= precission;
+int min_i= -1;
+for(k= 0;k<=max_link;k++)
+{i= i+1;
+if(i> max_link)i= 0;
+t= hint_links+i;
+d= hlink_distance(x,y,t);
+if(d<min_d)
+{min_d= d;min_i= i;}
+}
+last_hit= min_i;
+return last_hit;
+}
+}
+/*:303*//*304:*/
+#line 5651 "hint.w"
+
+uint64_t hint_link_page(int i)
+{uint64_t h;
+uint8_t w;
+if(i<0||i> max_link)return hint_page_get();
+h= hint_links[i].pos;
+w= hint_links[i].where;
+if(w==LABEL_TOP)return hint_page_top(h);
+else if(w==LABEL_BOT)return hint_page_bottom(h);
+else if(w==LABEL_MID)return hint_page_middle(h);
+else return hint_page_get();
+}
+/*:304*//*322:*/
+#line 6093 "hint.w"
+
+static void render_rule(int x,int y,int w,int h)
+{if(w> 0&&h> 0)
+nativeRule(SP2PT(x),SP2PT(y),SP2PT(w),SP2PT(h));
+}
+/*:322*//*323:*/
+#line 6104 "hint.w"
+
+void render_image(int x,int y,int w,int h,uint32_t n)
+{
+uint8_t*spos,*sstart,*send;
+spos= hpos;sstart= hstart;send= hend;
+hget_section(n);
+nativeImage(SP2PT(x),SP2PT(y),SP2PT(w),SP2PT(h),hstart,hend);
+hpos= spos;hstart= sstart;hend= send;
+}
+/*:323*//*325:*/
+#line 6136 "hint.w"
+
+static void vlist_render(pointer this_box);
+
+static void hlist_render(pointer this_box)
+{scaled base_line;
+scaled left_edge;
+scaled save_h;
+glue_ord g_order;
+uint8_t g_sign;
+pointer p;
+pointer leader_box;
+scaled leader_wd;
+scaled lx;
+scaled edge;
+double glue_temp;
+double cur_glue;
+scaled cur_g;
+int local_link= -1;
+uint8_t f;
+uint32_t c;
+
+cur_g= 0;
+cur_glue= 0.0;
+g_order= glue_order(this_box);
+g_sign= glue_sign(this_box);
+p= list_ptr(this_box);
+#ifdef DEBUG
+if(p==0xffff)
+QUIT("Undefined list pointer in hbox 0x%x-> mem[0x%x] -> 0x%x\n",
+this_box,mem[this_box].i,p);
+#endif
+base_line= cur_v;
+left_edge= cur_h;
+/*299:*/
+#line 5488 "hint.w"
+
+if(cur_link>=0)
+{add_new_link(cur_link,this_box,cur_h,cur_v);
+local_link= cur_link;
+cur_link= -1;
+}
+/*:299*/
+#line 6169 "hint.w"
+
+while(p!=null)
+{
+#ifdef DEBUG
+if(p==0xffff)
+QUIT("Undefined pointer in hlist 0x%x\n",p);
+if(link(p)==0xffff)
+QUIT("Undefined link in hlist mem[0x%x]=0x%x\n",p,mem[p].i);
+#endif
+if(is_char_node(p))
+{do
+{f= font(p);
+c= character(p);
+if(!c_ignore&&c!=' ')
+{cur_style= cur_style&~(MARK_BIT|FOCUS_BIT);
+/*290:*/
+#line 5314 "hint.w"
+
+{while(m_d==0)
+{m_style^= MARK_BIT;
+if(m_style&MARK_BIT)
+{if(m_ptr==m_focus)m_style|= FOCUS_BIT;else m_style&= ~FOCUS_BIT;
+m_d= m_chars;
+}
+else
+{m_style&= ~FOCUS_BIT;
+m_d= m_get();
+}
+}
+m_d--;
+}
+/*:290*/
+#line 6184 "hint.w"
+
+cur_style|= m_style;
+}
+
+render_c:
+if(f!=cur_f)
+{
+#ifdef DEBUG
+if(f> max_ref[font_kind])
+QUIT("Undefined Font %d mem[0x%x]=0x%x\n",
+f,p,mem[p].i);
+#endif
+cur_fp= hget_font(f);
+cur_f= f;
+}
+render_char(cur_h,cur_v,cur_fp,c,cur_style);
+cur_h= cur_h+char_width(f,char_info(f,c));
+#ifdef DEBUG
+if(link(p)==0xffff)
+QUIT("Undefined link in charlist mem[0x%x]=0x%x\n",p,mem[p].i);
+#endif
+p= link(p);
+}while(is_char_node(p));
+}
+else
+{switch(type(p))
+{case hlist_node:
+case vlist_node:
+#ifdef DEBUG
+if(list_ptr(p)==0xffff)
+QUIT("Undefined list pointer in hlist mem[0x%x] = 0x%x -> 0x%x\n",
+p,mem[p].i,list_ptr(p));
+#endif
+if(list_ptr(p)==null)cur_h= cur_h+width(p);
+else
+{cur_v= base_line+shift_amount(p);
+edge= cur_h;
+if(type(p)==vlist_node)
+vlist_render(p);
+else
+hlist_render(p);
+cur_h= edge+width(p);cur_v= base_line;
+}
+break;
+case rule_node:
+rule_ht= height(p);rule_dp= depth(p);rule_wd= width(p);
+goto fin_rule;
+case whatsit_node:
+/*292:*/
+#line 5351 "hint.w"
+
+if(subtype(p)==ignore_node)
+{if(ignore_info(p)==1)
+{cur_style= cur_style&~(MARK_BIT|FOCUS_BIT);
+c_ignore_list(ignore_list(p));
+c_ignore= true;
+}
+else
+c_ignore= false;
+}
+/*:292*/
+#line 6232 "hint.w"
+
+else/*297:*/
+#line 5462 "hint.w"
+
+if(subtype(p)==start_link_node)
+{cur_style|= LINK_BIT;
+local_link= label_ref(p);
+add_new_link(local_link,this_box,cur_h,cur_v);
+}
+else if(subtype(p)==end_link_node)
+{cur_style&= ~LINK_BIT;
+end_new_link(local_link,this_box,cur_h,cur_v);
+local_link= -1;
+}
+/*:297*/
+#line 6233 "hint.w"
+
+else if(subtype(p)==image_node)
+{scaled h,w;
+w= image_width(p);
+h= image_height(p);
+if(g_sign!=normal)
+{if(g_sign==stretching)
+{if(image_stretch_order(p)==g_order)
+{vet_glue((double)(glue_set(this_box))*image_stretch(p));
+w= w+round(glue_temp);
+}
+}
+else if(image_shrink_order(p)==g_order)
+{vet_glue((double)(glue_set(this_box))*image_shrink(p));
+w= w-round(glue_temp);
+}
+}
+if(w!=image_width(p))
+{double f;
+f= (double)w/(double)image_width(p);
+h= round((double)h*f);
+}
+render_image(cur_h,cur_v,w,h,image_no(p));
+cur_h= cur_h+w;
+}
+break;
+case glue_node:
+{pointer g;
+g= glue_ptr(p);rule_wd= width(g)-cur_g;
+if(g_sign!=normal)
+{if(g_sign==stretching)
+{if(stretch_order(g)==g_order)
+{cur_glue= cur_glue+stretch(g);
+vet_glue((double)(glue_set(this_box))*cur_glue);
+cur_g= round(glue_temp);
+}
+}
+else if(shrink_order(g)==g_order)
+{cur_glue= cur_glue-shrink(g);
+vet_glue((double)(glue_set(this_box))*cur_glue);
+cur_g= round(glue_temp);
+}
+}
+rule_wd= rule_wd+cur_g;
+if(subtype(p)>=a_leaders)
+{leader_box= leader_ptr(p);
+if(type(leader_box)==rule_node)
+{rule_ht= height(leader_box);rule_dp= depth(leader_box);
+goto fin_rule;
+}
+leader_wd= width(leader_box);
+if((leader_wd> 0)&&(rule_wd> 0))
+{rule_wd= rule_wd+10;
+edge= cur_h+rule_wd;lx= 0;
+
+if(subtype(p)==a_leaders)
+{save_h= cur_h;
+cur_h= left_edge+leader_wd*((cur_h-left_edge)/leader_wd);
+if(cur_h<save_h)cur_h= cur_h+leader_wd;
+}
+else
+{int lq= rule_wd/leader_wd;
+int lr= rule_wd%leader_wd;
+if(subtype(p)==c_leaders)cur_h= cur_h+(lr/2);
+else{lx= lr/(lq+1);
+cur_h= cur_h+((lr-(lq-1)*lx)/2);
+}
+}
+while(cur_h+leader_wd<=edge)
+
+{cur_v= base_line+shift_amount(leader_box);
+save_h= cur_h;
+c_ignore= true;
+if(type(leader_box)==vlist_node)
+vlist_render(leader_box);
+else
+hlist_render(leader_box);
+c_ignore= false;
+cur_v= base_line;
+cur_h= save_h+leader_wd+lx;
+}
+cur_h= edge-10;goto next_p;
+}
+}
+goto move_past;
+}
+case kern_node:
+case math_node:
+cur_h= cur_h+width(p);
+break;
+case ligature_node:
+f= font(lig_char(p));
+c= character(lig_char(p));
+/*291:*/
+#line 5333 "hint.w"
+
+if(!c_ignore)
+{pointer q;
+cur_style= cur_style&~(MARK_BIT|FOCUS_BIT);
+q= lig_ptr(p);
+while(q!=null)
+{/*290:*/
+#line 5314 "hint.w"
+
+{while(m_d==0)
+{m_style^= MARK_BIT;
+if(m_style&MARK_BIT)
+{if(m_ptr==m_focus)m_style|= FOCUS_BIT;else m_style&= ~FOCUS_BIT;
+m_d= m_chars;
+}
+else
+{m_style&= ~FOCUS_BIT;
+m_d= m_get();
+}
+}
+m_d--;
+}
+/*:290*/
+#line 5339 "hint.w"
+
+cur_style|= m_style;
+q= link(q);
+}
+}
+/*:291*/
+#line 6326 "hint.w"
+
+goto render_c;
+default:;
+}
+goto next_p;
+fin_rule:
+if(is_running(rule_ht))
+rule_ht= height(this_box);
+if(is_running(rule_dp))
+rule_dp= depth(this_box);
+rule_ht= rule_ht+rule_dp;
+if((rule_ht> 0)&&(rule_wd> 0))
+{cur_v= base_line+rule_dp;
+render_rule(cur_h,cur_v,rule_wd,rule_ht);
+cur_v= base_line;
+}
+move_past:cur_h= cur_h+rule_wd;
+next_p:
+#ifdef DEBUG
+if(link(p)==0xffff)
+QUIT("Undefined link in hlist mem[0x%x]=0x%x\n",p,mem[p].i);
+#endif
+p= link(p);
+}
+}
+/*298:*/
+#line 5478 "hint.w"
+
+if(local_link>=0)
+{end_new_link(local_link,this_box,cur_h,cur_v);
+cur_link= local_link;
+}
+/*:298*/
+#line 6351 "hint.w"
+
+}
+
+static void vlist_render(pointer this_box)
+{
+scaled left_edge;
+scaled top_edge;
+scaled save_v;
+glue_ord g_order;
+uint8_t g_sign;
+pointer p;
+pointer leader_box;
+scaled leader_ht;
+scaled lx;
+scaled edge;
+double glue_temp;
+double cur_glue;
+scaled cur_g;
+
+cur_g= 0;cur_glue= float_constant(0);
+g_order= glue_order(this_box);
+g_sign= glue_sign(this_box);p= list_ptr(this_box);
+#ifdef DEBUG
+if(p==0xffff)
+QUIT("Undefined list pointer in vbox 0x%x-> mem[0x%x] -> 0x%x\n",
+this_box,mem[this_box].i,p);
+#endif
+left_edge= cur_h;cur_v= cur_v-height(this_box);
+top_edge= cur_v;
+while(p!=null)
+{if(is_char_node(p))DBG(DBGTEX,"Glyph in vertical list ignored");
+else
+{switch(type(p))
+{case hlist_node:
+case vlist_node:
+#ifdef DEBUG
+if(list_ptr(p)==0xffff)
+QUIT("Undefined list pointer in vlist mem[0x%x] = 0x%x -> 0x%x\n",
+p,mem[p].i,list_ptr(p));
+#endif
+if(list_ptr(p)==null)cur_v= cur_v+height(p)+depth(p);
+else
+{cur_v= cur_v+height(p);save_v= cur_v;
+cur_h= left_edge+shift_amount(p);
+if(type(p)==vlist_node)vlist_render(p);
+else
+hlist_render(p);
+cur_v= save_v+depth(p);cur_h= left_edge;
+}
+break;
+case rule_node:
+rule_ht= height(p);rule_dp= depth(p);rule_wd= width(p);
+goto fin_rule;
+case whatsit_node:
+if(subtype(p)==image_node)
+{scaled h,w;
+w= image_width(p);
+h= image_height(p);
+if(g_sign!=normal)
+{if(g_sign==stretching)
+{if(image_stretch_order(p)==g_order)
+{vet_glue((double)(glue_set(this_box))*image_stretch(p));
+h= h+round(glue_temp);
+}
+}
+else if(image_shrink_order(p)==g_order)
+{vet_glue((double)(glue_set(this_box))*image_shrink(p));
+h= h-round(glue_temp);
+}
+}
+if(h!=image_height(p))
+{double f;
+f= (double)h/(double)image_height(p);
+w= round((double)w*f);
+}
+cur_v= cur_v+h;
+render_image(cur_h,cur_v,w,h,image_no(p));
+}
+break;
+case glue_node:
+{pointer g= glue_ptr(p);rule_ht= width(g)-cur_g;
+if(g_sign!=normal)
+{if(g_sign==stretching)
+{if(stretch_order(g)==g_order)
+{cur_glue= cur_glue+stretch(g);
+vet_glue((double)(glue_set(this_box))*cur_glue);
+cur_g= round(glue_temp);
+}
+}
+else if(shrink_order(g)==g_order)
+{cur_glue= cur_glue-shrink(g);
+vet_glue((double)(glue_set(this_box))*cur_glue);
+cur_g= round(glue_temp);
+}
+}
+rule_ht= rule_ht+cur_g;
+if(subtype(p)>=a_leaders)
+{leader_box= leader_ptr(p);
+if(type(leader_box)==rule_node)
+{rule_wd= width(leader_box);rule_dp= 0;
+goto fin_rule;
+}
+leader_ht= height(leader_box)+depth(leader_box);
+if((leader_ht> 0)&&(rule_ht> 0))
+{rule_ht= rule_ht+10;
+edge= cur_v+rule_ht;lx= 0;
+if(subtype(p)==a_leaders)
+{save_v= cur_v;
+cur_v= top_edge+leader_ht*((cur_v-top_edge)/leader_ht);
+if(cur_v<save_v)cur_v= cur_v+leader_ht;
+}
+else
+{int lq= rule_ht/leader_ht;
+int lr= rule_ht%leader_ht;
+if(subtype(p)==c_leaders)cur_v= cur_v+(lr/2);
+else
+{lx= lr/(lq+1);
+cur_v= cur_v+((lr-(lq-1)*lx)/2);
+}
+}
+while(cur_v+leader_ht<=edge)
+{cur_h= left_edge+shift_amount(leader_box);
+cur_v= cur_v+height(leader_box);save_v= cur_v;
+c_ignore= true;
+if(type(leader_box)==vlist_node)
+vlist_render(leader_box);
+else
+hlist_render(leader_box);
+c_ignore= false;
+cur_h= left_edge;
+cur_v= save_v-height(leader_box)+leader_ht+lx;
+}
+cur_v= edge-10;goto next_p;
+}
+}
+}
+goto move_past;
+case kern_node:
+cur_v= cur_v+width(p);
+break;
+default:;
+}
+goto next_p;
+
+fin_rule:
+if(is_running(rule_wd))rule_wd= width(this_box);
+rule_ht= rule_ht+rule_dp;
+cur_v= cur_v+rule_ht;
+if((rule_ht> 0)&&(rule_wd> 0))
+{render_rule(cur_h,cur_v,rule_wd,rule_ht);
+}
+goto next_p;
+
+move_past:
+cur_v= cur_v+rule_ht;
+}
+next_p:
+#if 0
+if(link(p)==1||link(p)==0xffff){
+show_box(streams[0].p);
+QUIT("vertical node mem[0x%x] =0x%x ->linking to node 0x%x\n",
+p,mem[p].i,link(p));
+}
+#endif
+p= link(p);
+}
+}
+
+/*:325*//*326:*/
+#line 6526 "hint.w"
+
+uint64_t hint_blank(void)
+{nativeBlank();
+return 0;
+}
+/*:326*//*327:*/
+#line 6535 "hint.w"
+
+
+void hint_render(void)
+{nativeBlank();
+if(streams==NULL||streams[0].p==null)return;
+cur_h= 0;
+cur_v= height(streams[0].p);
+cur_f= -1;cur_fp= NULL;
+cur_link= -1;max_link= -1;
+/*289:*/
+#line 5307 "hint.w"
+
+m_ptr= 0;m_d= 0;m_style= MARK_BIT;c_ignore= false;cur_style= 0;
+/*:289*/
+#line 6544 "hint.w"
+
+if(type(streams[0].p)==vlist_node)
+vlist_render(streams[0].p);
+else
+hlist_render(streams[0].p);
+}
+/*:327*/
+#line 7580 "hint.w"
+
+/*:373*/

Added: trunk/Build/source/texk/web2c/hitexdir/hintview/src/hrender.h
===================================================================
--- trunk/Build/source/texk/web2c/hitexdir/hintview/src/hrender.h	                        (rev 0)
+++ trunk/Build/source/texk/web2c/hitexdir/hintview/src/hrender.h	2022-01-19 13:28:43 UTC (rev 61658)
@@ -0,0 +1,45 @@
+/*372:*/
+#line 7535 "hint.w"
+
+#ifndef _HRENDER_H
+#define _HRENDER_H
+/*276:*/
+#line 4997 "hint.w"
+
+#define MARK_BIT 0x1
+#define FOCUS_BIT 0x2
+/*:276*//*295:*/
+#line 5447 "hint.w"
+
+#define LINK_BIT 0x4
+/*:295*//*319:*/
+#line 6067 "hint.w"
+
+#define SP2PT(X) ((X)/(double)(1<<16))
+/*:319*/
+#line 7538 "hint.w"
+
+
+extern int page_h,page_v;
+extern double xdpi,ydpi;
+extern uint64_t hint_blank(void);
+extern void hint_render(void);
+extern uint64_t hint_page_get(void);
+extern uint64_t hint_page_top(uint64_t h);
+extern uint64_t hint_page_middle(uint64_t h);
+extern uint64_t hint_page_bottom(uint64_t h);
+extern uint64_t hint_page(void);
+extern uint64_t hint_page_next(void);
+extern uint64_t hint_page_prev(void);
+extern uint64_t hint_page_home(void);
+extern void hint_resize(int px_h,int px_v,double xdpi,double ydpi);
+extern void hint_clear_fonts(bool rm);
+extern void hmark_page(void);
+extern void hint_set_mark(char*m,int s);
+extern bool hint_prev_mark(void);
+extern bool hint_next_mark(void);
+extern double hint_get_fpos(void);
+extern uint64_t hint_set_fpos(double fpos);
+
+#endif
+/*:372*/

Added: trunk/Build/source/texk/web2c/hitexdir/hintview/src/htex.c
===================================================================
--- trunk/Build/source/texk/web2c/hitexdir/hintview/src/htex.c	                        (rev 0)
+++ trunk/Build/source/texk/web2c/hitexdir/hintview/src/htex.c	2022-01-19 13:28:43 UTC (rev 61658)
@@ -0,0 +1,3757 @@
+/*4:*/
+#line 16 "htex.ch"
+
+#ifndef _HETX_H_
+#define _HTEX_H_
+
+#include "basetypes.h"
+#include <string.h> 
+#include <math.h> 
+
+#include "error.h"
+#include "format.h"
+#include "get.h"
+#include "htex.h"
+#include "hint.h"
+/*120:*/
+#line 262 "htex.ch"
+
+pointer temp_ptr;
+#line 2494 "btex.w"
+
+/*:120*//*121:*/
+#line 272 "htex.ch"
+
+memory_word mem0[mem_max-mem_min+1],*const mem= mem0-mem_min;
+pointer lo_mem_max;
+pointer hi_mem_min;
+#line 2528 "btex.w"
+
+/*:121*//*122:*/
+#line 282 "htex.ch"
+
+static int var_used,dyn_used;
+#line 2539 "btex.w"
+#ifdef STAT
+#define incr_dyn_used incr(dyn_used)
+#define decr_dyn_used decr(dyn_used)
+#else
+#define incr_dyn_used
+#define decr_dyn_used
+#endif
+
+/*:122*//*123:*/
+#line 292 "htex.ch"
+
+static pointer avail;
+#line 2563 "btex.w"
+
+/*:123*//*129:*/
+#line 329 "htex.ch"
+
+static pointer rover;
+#line 2667 "btex.w"
+
+/*:129*//*658:*/
+#line 1085 "htex.ch"
+
+static scaled total_stretch0[filll-normal+1],*const total_stretch= total_stretch0-normal,total_shrink0[filll-normal+1],*const total_shrink= total_shrink0-normal;
+
+#line 12902 "btex.w"
+
+/*:658*//*660:*/
+#line 1093 "htex.ch"
+
+pointer adjust_tail= null;
+#line 12910 "btex.w"
+
+/*:660*//*829:*/
+#line 1208 "htex.ch"
+
+pointer just_box;
+#line 16025 "btex.w"
+
+/*:829*//*837:*/
+#line 1258 "htex.ch"
+
+static pointer passive;
+#line 16168 "btex.w"
+static pointer printed_node;
+static halfword pass_number;
+
+/*:837*//*840:*/
+#line 1265 "htex.ch"
+
+static scaled active_width0[6],*const active_width= active_width0-1;
+#line 16207 "btex.w"
+
+static scaled cur_active_width0[6],*const cur_active_width= cur_active_width0-1;
+static scaled background0[6],*const background= background0-1;
+static scaled break_width0[6],*const break_width= break_width0-1;
+
+/*:840*//*843:*/
+#line 1272 "htex.ch"
+
+static bool no_shrink_error_yet;
+#line 16264 "btex.w"
+
+/*:843*//*847:*/
+#line 1303 "htex.ch"
+
+static pointer cur_p;
+#line 16324 "btex.w"
+static bool second_pass;
+static bool final_pass;
+static int threshold;
+
+/*:847*//*853:*/
+#line 1311 "htex.ch"
+
+static int minimal_demerits0[tight_fit-very_loose_fit+1],*const minimal_demerits= minimal_demerits0-very_loose_fit;
+
+#line 16426 "btex.w"
+static int minimum_demerits;
+
+static pointer best_place0[tight_fit-very_loose_fit+1],*const best_place= best_place0-very_loose_fit;
+
+static halfword best_pl_line0[tight_fit-very_loose_fit+1],*const best_pl_line= best_pl_line0-very_loose_fit;
+
+
+/*:853*//*860:*/
+#line 1319 "htex.ch"
+
+static scaled disc_width;
+#line 16543 "btex.w"
+
+/*:860*//*869:*/
+#line 1326 "htex.ch"
+
+static halfword easy_line;
+#line 16683 "btex.w"
+static halfword last_special_line;
+
+static scaled first_width;
+
+static scaled second_width;
+static scaled first_indent;
+static scaled second_indent;
+
+/*:869*//*895:*/
+#line 1430 "htex.ch"
+
+static pointer best_bet;
+#line 17193 "btex.w"
+static int fewest_demerits;
+static halfword best_line;
+static int actual_looseness;
+
+static int line_diff;
+
+
+/*:895*//*996:*/
+#line 1625 "htex.ch"
+
+scaled best_height_plus_depth;
+
+#line 18940 "btex.w"
+
+/*:996*//*1005:*/
+#line 1655 "htex.ch"
+
+pointer page_tail;
+#line 19146 "btex.w"
+int page_contents;
+scaled page_max_depth;
+pointer best_page_break;
+int least_page_cost;
+scaled best_size;
+
+/*:1005*//*1007:*/
+#line 1666 "htex.ch"
+
+scaled page_so_far[8];
+#line 19231 "btex.w"
+int insert_penalties;
+
+
+/*:1007*/
+#line 29 "htex.ch"
+
+
+/*97:*/
+#line 164 "htex.ch"
+
+void overflow(char*s,int n)
+{QUIT("Capacity exceeded, sorry [%s=%d=0x%X]\n",s,n,n);
+}
+#line 2026 "btex.w"
+
+/*:97*//*98:*/
+#line 188 "htex.ch"
+
+void confusion(char*s)
+
+{QUIT("This can't happen(%s)",s);}
+#line 2051 "btex.w"
+
+/*:98*/
+#line 31 "htex.ch"
+
+#endif
+#line 268 "btex.w"
+
+/*:4*//*103:*/
+#line 197 "htex.ch"
+
+
+static int half(int x)
+#line 2115 "btex.w"
+{if(odd(x))return(x+1)/2;
+else return x/2;
+}
+
+/*:103*//*108:*/
+#line 233 "htex.ch"
+
+static bool arith_error;
+static scaled rem;
+#line 2199 "btex.w"
+
+/*:108*//*110:*/
+#line 241 "htex.ch"
+
+static scaled x_over_n(scaled x,int n)
+#line 2221 "btex.w"
+{bool negative;
+scaled x_over_n;
+negative= false;
+if(n==0)
+{arith_error= true;x_over_n= 0;rem= x;
+}
+else{if(n<0)
+{negate(x);negate(n);negative= true;
+}
+if(x>=0)
+{x_over_n= x/n;rem= x%n;
+}
+else{x_over_n= -((-x)/n);rem= -((-x)%n);
+}
+}
+if(negative)negate(rem);
+return x_over_n;}
+
+/*:110*//*111:*/
+#line 248 "htex.ch"
+
+static scaled xn_over_d(scaled x,int n,int d)
+#line 2247 "btex.w"
+{bool positive;
+nonnegative_integer t,u,v;
+scaled xn_over_d;
+if(x>=0)positive= true;
+else{negate(x);positive= false;
+}
+t= (x%0100000)*n;
+u= (x/0100000)*n+(t/0100000);
+v= (u%d)*0100000+(t%0100000);
+if(u/d>=0100000)arith_error= true;
+else u= 0100000*(u/d)+(v/d);
+if(positive)
+{xn_over_d= u;rem= v%d;
+}
+else{xn_over_d= -u;rem= -(v%d);
+}
+return xn_over_d;}
+
+/*:111*//*112:*/
+#line 255 "htex.ch"
+
+halfword badness(scaled t,scaled s)
+#line 2286 "btex.w"
+{int r;
+
+if(t==0)return 0;
+else if(s<=0)return inf_bad;
+else{if(t<=7230584)r= (t*297)/s;
+else if(s>=1663497)r= t/(s/297);
+else r= t;
+if(r> 1290)return inf_bad;
+else return(r*r*r+0400000)/01000000;
+}
+}
+
+/*:112*//*125:*/
+#line 299 "htex.ch"
+
+static pointer get_avail(void)
+#line 2581 "btex.w"
+{pointer p;
+p= avail;
+if(p!=null)avail= link(avail);
+#line 311 "htex.ch"
+else{decr(hi_mem_min);p= hi_mem_min;
+if(hi_mem_min<=lo_mem_max)
+{
+#line 2590 "btex.w"
+overflow("main memory size",mem_max+1-mem_min);
+
+
+}
+}
+link(p)= null;
+#ifdef STAT
+incr(dyn_used);
+#endif
+
+return p;
+}
+
+/*:125*//*128:*/
+#line 320 "htex.ch"
+
+static void flush_list(pointer p)
+
+#line 2631 "btex.w"
+{pointer q,r;
+if(p!=null)
+{r= p;
+do{q= r;r= link(r);
+#ifdef STAT
+decr(dyn_used);
+#endif
+}while(!(r==null));
+link(q)= avail;avail= p;
+}
+}
+
+/*:128*//*130:*/
+#line 336 "htex.ch"
+
+pointer get_node(int s)
+#line 2677 "btex.w"
+{
+pointer p;
+pointer q;
+int r;
+int t;
+restart:p= rover;
+do{/*132:*/
+#line 2726 "btex.w"
+
+q= p+node_size(p);
+
+while(is_empty(q))
+{t= rlink(q);
+if(q==rover)rover= t;
+llink(t)= llink(q);rlink(llink(q))= t;
+q= q+node_size(q);
+}
+r= q-s;
+if(r> p+1)/*133:*/
+#line 2741 "btex.w"
+
+{node_size(p)= r-p;
+
+rover= p;
+goto found;
+}
+
+/*:133*/
+#line 2736 "btex.w"
+;
+if(r==p)if(rlink(p)!=p)
+/*134:*/
+#line 2750 "btex.w"
+
+{rover= rlink(p);t= llink(p);
+llink(rover)= t;rlink(t)= rover;
+goto found;
+}
+
+/*:134*/
+#line 2738 "btex.w"
+;
+node_size(p)= q-p
+
+/*:132*/
+#line 2684 "btex.w"
+;
+
+p= rlink(p);
+}while(!(p==rover));
+if(s==010000000000)
+{return max_halfword;
+}
+if(lo_mem_max+2<hi_mem_min)if(lo_mem_max+2<=mem_bot+max_halfword)
+/*131:*/
+#line 2711 "btex.w"
+
+{if(hi_mem_min-lo_mem_max>=1998)t= lo_mem_max+1000;
+else t= lo_mem_max+1+(hi_mem_min-lo_mem_max)/2;
+
+p= llink(rover);q= lo_mem_max;rlink(p)= q;llink(rover)= q;
+if(t> mem_bot+max_halfword)t= mem_bot+max_halfword;
+rlink(q)= rover;llink(q)= p;link(q)= empty_flag;node_size(q)= t-lo_mem_max;
+lo_mem_max= t;link(lo_mem_max)= null;info(lo_mem_max)= null;
+rover= q;goto restart;
+}
+
+/*:131*/
+#line 2692 "btex.w"
+;
+overflow("main memory size",mem_max+1-mem_min);
+
+
+found:link(r)= null;
+#ifdef STAT
+var_used= var_used+s;
+#endif
+
+#line 343 "htex.ch"
+leak_in(r,s);
+return r;
+#line 2702 "btex.w"
+}
+
+/*:130*//*135:*/
+#line 352 "htex.ch"
+
+static void free_node(pointer p,halfword s)
+
+{pointer q;
+leak_out(p,s);
+store_map(p,0,0);
+#line 2764 "btex.w"
+node_size(p)= s;link(p)= empty_flag;
+q= llink(rover);llink(p)= q;rlink(p)= rover;
+llink(rover)= p;rlink(q)= p;
+#ifdef STAT
+var_used= var_used-s;
+#endif
+
+}
+
+/*:135*//*141:*/
+#line 369 "htex.ch"
+
+pointer new_null_box(void)
+#line 2910 "btex.w"
+{pointer p;
+p= get_node(box_node_size);type(p)= hlist_node;
+subtype(p)= min_quarterword;
+width(p)= 0;depth(p)= 0;height(p)= 0;shift_amount(p)= 0;list_ptr(p)= null;
+glue_sign(p)= normal;glue_order(p)= normal;set_glue_ratio_zero(glue_set(p));
+return p;
+}
+
+/*:141*//*144:*/
+#line 376 "htex.ch"
+
+pointer new_rule(void)
+#line 2940 "btex.w"
+{pointer p;
+p= get_node(rule_node_size);type(p)= rule_node;
+subtype(p)= 0;
+width(p)= null_flag;depth(p)= null_flag;height(p)= null_flag;
+return p;
+}
+
+/*:144*//*149:*/
+#line 383 "htex.ch"
+
+pointer new_ligature(quarterword f,quarterword c,pointer q)
+#line 3009 "btex.w"
+{pointer p;
+p= get_node(small_node_size);type(p)= ligature_node;
+font(lig_char(p))= f;character(lig_char(p))= c;lig_ptr(p)= q;
+subtype(p)= 0;return p;
+}
+
+#line 3020 "btex.w"
+
+/*:149*//*150:*/
+#line 408 "htex.ch"
+
+pointer new_disc(void)
+#line 3044 "btex.w"
+{pointer p;
+p= get_node(small_node_size);type(p)= disc_node;
+#line 415 "htex.ch"
+subtype(p)= 0;pre_break(p)= null;post_break(p)= null;
+#line 3047 "btex.w"
+return p;
+}
+
+/*:150*//*152:*/
+#line 421 "htex.ch"
+
+pointer new_math(scaled w,small_number s)
+#line 3078 "btex.w"
+{pointer p;
+p= get_node(small_node_size);type(p)= math_node;
+subtype(p)= s;width(p)= w;return p;
+}
+
+/*:152*//*156:*/
+#line 428 "htex.ch"
+
+pointer new_spec(pointer p)
+#line 3160 "btex.w"
+{pointer q;
+q= get_node(glue_spec_size);
+mem[q]= mem[p];glue_ref_count(q)= null;
+width(q)= width(p);stretch(q)= stretch(p);shrink(q)= shrink(p);
+return q;
+}
+
+/*:156*//*158:*/
+#line 435 "htex.ch"
+
+pointer new_glue(pointer q)
+#line 3186 "btex.w"
+{pointer p;
+p= get_node(small_node_size);type(p)= glue_node;subtype(p)= normal;
+leader_ptr(p)= null;glue_ptr(p)= q;incr(glue_ref_count(q));
+return p;
+}
+
+/*:158*//*161:*/
+#line 442 "htex.ch"
+
+pointer new_kern(scaled w)
+#line 3224 "btex.w"
+{pointer p;
+p= get_node(small_node_size);type(p)= kern_node;
+subtype(p)= normal;
+width(p)= w;
+return p;
+}
+
+/*:161*//*163:*/
+#line 449 "htex.ch"
+
+pointer new_penalty(int m)
+#line 3247 "btex.w"
+{pointer p;
+p= get_node(small_node_size);type(p)= penalty_node;
+subtype(p)= 0;
+penalty(p)= m;return p;
+}
+
+/*:163*//*169:*/
+#line 469 "htex.ch"
+
+void mem_init(void)
+{int k;
+/*170:*/
+#line 475 "htex.ch"
+
+#line 3331 "btex.w"
+for(k= mem_bot+1;k<=lo_mem_stat_max;k++)mem[k].sc= 0;
+
+
+k= mem_bot;while(k<=lo_mem_stat_max)
+
+{glue_ref_count(k)= null+1;
+stretch_order(k)= normal;shrink_order(k)= normal;
+k= k+glue_spec_size;
+}
+#line 3345 "btex.w"
+rover= lo_mem_stat_max+1;
+link(rover)= empty_flag;
+node_size(rover)= 1000;
+llink(rover)= rover;rlink(rover)= rover;
+lo_mem_max= rover+1000;link(lo_mem_max)= null;info(lo_mem_max)= null;
+for(k= hi_mem_stat_min;k<=mem_top;k++)
+mem[k]= mem[lo_mem_max];
+/*804:*/
+#line 15568 "btex.w"
+
+info(omit_template)= end_template_token;
+
+/*:804*//*811:*/
+#line 15675 "btex.w"
+
+link(end_span)= max_quarterword+1;info(end_span)= null;
+
+/*:811*//*835:*/
+#line 16136 "btex.w"
+
+type(last_active)= hyphenated;line_number(last_active)= max_halfword;
+subtype(last_active)= 0;
+
+/*:835*//*1006:*/
+#line 19197 "btex.w"
+
+subtype(page_ins_head)= qi(255);
+type(page_ins_head)= split_up;link(page_ins_head)= page_ins_head;
+
+/*:1006*//*1013:*/
+#line 19354 "btex.w"
+
+type(page_head)= glue_node;subtype(page_head)= normal;
+
+/*:1013*/
+#line 3352 "btex.w"
+;
+#line 490 "htex.ch"
+avail= null;
+#line 3354 "btex.w"
+hi_mem_min= hi_mem_stat_min;
+var_used= lo_mem_stat_max+1-mem_bot;dyn_used= hi_mem_stat_usage;
+
+
+/*:170*/
+#line 472 "htex.ch"
+
+}
+
+/*:169*//*209:*/
+#line 642 "htex.ch"
+
+static void delete_token_ref(pointer p)
+
+#line 3888 "btex.w"
+{if(token_ref_count(p)==null)flush_list(p);
+else decr(token_ref_count(p));
+}
+
+/*:209*//*210:*/
+#line 651 "htex.ch"
+
+void delete_glue_ref(pointer p)
+fast_delete_glue_ref(p)
+static void delete_xdimen_ref(pointer p)
+{if(xdimen_ref_count(p)==null)free_node(p,xdimen_node_size);
+else decr(xdimen_ref_count(p));
+}
+#line 3902 "btex.w"
+
+/*:210*//*211:*/
+#line 663 "htex.ch"
+
+void flush_node_list(pointer p)
+#line 3909 "btex.w"
+{
+pointer q;
+while(p!=null)
+
+{q= link(p);
+if(is_char_node(p))free_avail(p)
+else{switch(type(p)){
+case hlist_node:case vlist_node:case unset_node:{flush_node_list(list_ptr(p));
+free_node(p,box_node_size);goto done;
+}
+case rule_node:{free_node(p,rule_node_size);goto done;
+}
+case ins_node:{flush_node_list(ins_ptr(p));
+delete_glue_ref(split_top_ptr(p));
+free_node(p,ins_node_size);goto done;
+}
+case whatsit_node:/*1387:*/
+#line 24761 "btex.w"
+
+{switch(subtype(p)){
+#line 2512 "htex.ch"
+case close_node:case language_node:free_node(p,small_node_size);break;
+case par_node:
+if(par_type(p)==glue_type)fast_delete_glue_ref(par_value(p).i);
+free_node(p,par_node_size);break;
+case graf_node:
+delete_xdimen_ref(graf_extent(p));
+flush_node_list(graf_params(p));
+flush_node_list(graf_list(p));
+free_node(p,graf_node_size);break;
+case disp_node:
+flush_node_list(display_eqno(p));
+flush_node_list(display_formula(p));
+flush_node_list(display_params(p));
+free_node(p,disp_node_size);break;
+case baseline_node:
+free_node(p,baseline_node_size);break;
+case hpack_node:case vpack_node:
+delete_xdimen_ref(pack_extent(p));
+flush_node_list(list_ptr(p));
+free_node(p,pack_node_size);break;
+case hset_node:case vset_node:
+delete_xdimen_ref(set_extent(p));
+flush_node_list(list_ptr(p));
+free_node(p,set_node_size);break;
+case image_node:
+free_node(p,image_node_size);break;
+case align_node:
+delete_xdimen_ref(align_extent(p));
+flush_node_list(align_preamble(p));
+flush_node_list(align_list(p));
+free_node(p,align_node_size);break;
+case setpage_node:
+delete_glue_ref(setpage_topskip(p));
+delete_xdimen_ref(setpage_height(p));
+delete_xdimen_ref(setpage_width(p));
+flush_node_list(setpage_list(p));
+flush_node_list(setpage_streams(p));
+free_node(p,setpage_node_size);break;
+case setstream_node:
+delete_xdimen_ref(setstream_max(p));
+delete_xdimen_ref(setstream_width(p));
+delete_glue_ref(setstream_topskip(p));
+delete_glue_ref(setstream_height(p));
+flush_node_list(setstream_before(p));
+flush_node_list(setstream_after(p));
+free_node(p,setstream_node_size);break;
+case ignore_node:
+flush_node_list(ignore_list(p));
+free_node(p,ignore_node_size);break;
+case start_link_node:
+if(label_has_name(p))delete_token_ref(label_ptr(p));
+free_node(p,link_node_size);break;
+case end_link_node:
+free_node(p,link_node_size);break;
+case label_node:
+if(label_has_name(p))delete_token_ref(label_ptr(p));
+free_node(p,label_node_size);break;
+case outline_node:
+if(label_has_name(p))delete_token_ref(label_ptr(p));
+flush_node_list(outline_ptr(p));
+free_node(p,outline_node_size);break;
+case stream_node:
+free_node(p,stream_node_size);break;
+case xdimen_node:
+free_node(p,xdimen_node_size);
+#line 24768 "btex.w"
+default:confusion("ext3");
+
+}
+goto done;
+}
+
+#line 2582 "htex.ch"
+/*:1387*/
+#line 3925 "btex.w"
+
+case glue_node:{fast_delete_glue_ref(glue_ptr(p));
+if(leader_ptr(p)!=null)flush_node_list(leader_ptr(p));
+}break;
+case kern_node:case math_node:case penalty_node:do_nothing;break;
+case ligature_node:flush_node_list(lig_ptr(p));break;
+#line 3932 "btex.w"
+case disc_node:{flush_node_list(pre_break(p));
+flush_node_list(post_break(p));
+}break;
+case adjust_node:flush_node_list(adjust_ptr(p));break;
+#line 676 "htex.ch"
+default:QUIT("Confusion while flushing node list");
+#line 3938 "btex.w"
+
+}
+free_node(p,small_node_size);
+done:;}
+p= q;
+}
+}
+
+/*:211*//*213:*/
+#line 690 "htex.ch"
+
+pointer copy_node_list(pointer p)
+
+#line 3972 "btex.w"
+{pointer h;
+pointer q;
+pointer r;
+int words;
+h= get_avail();q= h;
+while(p!=null)
+{/*214:*/
+#line 3985 "btex.w"
+
+words= 1;
+if(is_char_node(p))r= get_avail();
+else/*215:*/
+#line 3994 "btex.w"
+
+switch(type(p)){
+case hlist_node:case vlist_node:case unset_node:{r= get_node(box_node_size);
+mem[r+6]= mem[p+6];mem[r+5]= mem[p+5];
+list_ptr(r)= copy_node_list(list_ptr(p));
+words= 5;
+}break;
+case rule_node:{r= get_node(rule_node_size);words= rule_node_size;
+}break;
+case ins_node:{r= get_node(ins_node_size);mem[r+4]= mem[p+4];
+add_glue_ref(split_top_ptr(p));
+ins_ptr(r)= copy_node_list(ins_ptr(p));
+words= ins_node_size-1;
+}break;
+case whatsit_node:/*1386:*/
+#line 24747 "btex.w"
+
+switch(subtype(p)){
+case open_node:{r= get_node(open_node_size);words= open_node_size;
+}break;
+case write_node:case special_node:{r= get_node(write_node_size);
+add_token_ref(write_tokens(p));words= write_node_size;
+}break;
+case close_node:case language_node:{r= get_node(small_node_size);
+words= small_node_size;
+}break;
+#line 2398 "htex.ch"
+case par_node:
+{r= get_node(par_node_size);
+if(par_type(p)==glue_type)add_glue_ref(par_value(p).i);
+words= par_node_size;
+}break;
+case graf_node:
+{r= get_node(graf_node_size);
+add_xdimen_ref(graf_extent(p));
+graf_params(r)= copy_node_list(graf_params(p));
+graf_list(r)= copy_node_list(graf_list(p));
+words= graf_node_size-1;
+}break;
+case disp_node:
+{r= get_node(disp_node_size);
+display_left(r)= display_left(p);
+display_no_bs(r)= display_no_bs(p);
+display_eqno(r)= copy_node_list(display_eqno(p));
+display_formula(r)= copy_node_list(display_formula(p));
+display_params(r)= copy_node_list(display_params(p));
+words= disp_node_size-2;
+}break;
+case baseline_node:
+{r= get_node(baseline_node_size);
+words= baseline_node_size;
+}break;
+case hpack_node:case vpack_node:
+{r= get_node(pack_node_size);
+pack_m(r)= pack_m(p);
+list_ptr(r)= copy_node_list(list_ptr(p));
+add_xdimen_ref(pack_extent(p));
+pack_limit(r)= pack_limit(p);
+words= pack_node_size-3;
+}break;
+case hset_node:case vset_node:
+{r= get_node(set_node_size);
+mem[r+8]= mem[p+8];mem[r+7]= mem[p+7];mem[r+6]= mem[p+6];mem[r+5]= mem[p+5];
+add_xdimen_ref(set_extent(p));
+list_ptr(r)= copy_node_list(list_ptr(p));
+words= 5;
+}break;
+case image_node:
+r= get_node(image_node_size);
+words= image_node_size;
+break;
+case align_node:
+{r= get_node(align_node_size);
+align_preamble(r)= copy_node_list(align_preamble(p));
+align_list(r)= copy_node_list(align_list(p));
+add_xdimen_ref(align_extent(p));
+words= align_node_size-1;
+}break;
+case setpage_node:
+{r= get_node(setpage_node_size);
+add_glue_ref(setpage_topskip(p));
+add_xdimen_ref(setpage_height(p));
+add_xdimen_ref(setpage_width(p));
+setpage_list(r)= copy_node_list(setpage_list(p));
+setpage_streams(r)= copy_node_list(setpage_streams(p));
+words= setpage_node_size-1;
+}break;
+case setstream_node:
+{r= get_node(setstream_node_size);
+add_xdimen_ref(setstream_max(p));
+add_xdimen_ref(setstream_width(p));
+add_glue_ref(setstream_topskip(p));
+add_glue_ref(setstream_height(p));
+setstream_before(r)= copy_node_list(setstream_before(p));
+setstream_after(r)= copy_node_list(setstream_after(p));
+words= setstream_node_size-1;
+}break;
+case ignore_node:
+r= get_node(ignore_node_size);
+ignore_info(r)= ignore_info(p);
+ignore_list(r)= copy_node_list(ignore_list(p));
+words= ignore_node_size-1;
+break;
+case start_link_node:
+r= get_node(link_node_size);
+if(label_has_name(p))add_token_ref(label_ptr(p));
+words= link_node_size;
+break;
+case end_link_node:
+r= get_node(link_node_size);
+words= link_node_size;
+break;
+case label_node:
+r= get_node(label_node_size);
+if(label_has_name(p))add_token_ref(label_ptr(p));
+words= label_node_size;
+break;
+case outline_node:
+r= get_node(outline_node_size);
+if(label_has_name(p))add_token_ref(label_ptr(p));
+outline_ptr(r)= copy_node_list(outline_ptr(p));
+words= outline_node_size-1;
+break;
+case stream_node:
+r= get_node(stream_node_size);
+words= stream_node_size;
+break;
+case xdimen_node:
+r= get_node(xdimen_node_size);
+words= xdimen_node_size;
+break;
+default:confusion("ext2");
+#line 24758 "btex.w"
+
+}
+
+/*:1386*/
+#line 4009 "btex.w"
+break;
+case glue_node:{r= get_node(small_node_size);add_glue_ref(glue_ptr(p));
+glue_ptr(r)= glue_ptr(p);leader_ptr(r)= copy_node_list(leader_ptr(p));
+}break;
+case kern_node:case math_node:case penalty_node:{r= get_node(small_node_size);
+words= small_node_size;
+}break;
+case ligature_node:{r= get_node(small_node_size);
+mem[lig_char(r)]= mem[lig_char(p)];
+lig_ptr(r)= copy_node_list(lig_ptr(p));
+}break;
+case disc_node:{r= get_node(small_node_size);
+pre_break(r)= copy_node_list(pre_break(p));
+post_break(r)= copy_node_list(post_break(p));
+}break;
+case mark_node:{r= get_node(small_node_size);add_token_ref(mark_ptr(p));
+words= small_node_size;
+}break;
+case adjust_node:{r= get_node(small_node_size);
+adjust_ptr(r)= copy_node_list(adjust_ptr(p));
+}break;
+default:confusion("copying");
+
+}
+
+/*:215*/
+#line 3989 "btex.w"
+;
+while(words> 0)
+{decr(words);mem[r+words]= mem[p+words];
+}
+
+/*:214*/
+#line 3978 "btex.w"
+;
+link(q)= r;q= r;p= link(p);
+}
+link(q)= null;q= link(h);free_avail(h);
+return q;
+}
+
+/*:213*//*224:*/
+#line 742 "htex.ch"
+
+
+/*222:*/
+#line 728 "htex.ch"
+
+static list_state_record nest[nest_size+1];
+int nest_ptr;
+static int max_nest_stack;
+list_state_record cur_list;
+#line 4333 "btex.w"
+
+/*:222*/
+#line 744 "htex.ch"
+
+
+void list_init(void)
+{
+nest_ptr= 0;max_nest_stack= 0;
+memset(&cur_list,0,sizeof(cur_list));
+mode= vmode;head= contrib_head;tail= contrib_head;
+prev_height= prev_depth= ignore_depth;
+}
+/*:224*//*226:*/
+#line 761 "htex.ch"
+
+void push_nest(void)
+#line 4359 "btex.w"
+{if(nest_ptr> max_nest_stack)
+{max_nest_stack= nest_ptr;
+if(nest_ptr==nest_size)overflow("semantic nest size",nest_size);
+
+}
+nest[nest_ptr]= cur_list;
+#line 768 "htex.ch"
+incr(nest_ptr);head= get_avail();tail= head;prev_graf= 0;
+cur_list.bs_pos= NULL;cur_bs= baseline_skip;cur_ls= line_skip;cur_lsl= line_skip_limit;
+#line 4366 "btex.w"
+}
+
+/*:226*//*227:*/
+#line 775 "htex.ch"
+
+void pop_nest(void)
+#line 4374 "btex.w"
+{free_avail(head);decr(nest_ptr);cur_list= nest[nest_ptr];
+}
+
+/*:227*//*560:*/
+#line 952 "htex.ch"
+
+memory_word font_info[font_mem_size+1];
+
+static font_index fmem_ptr= 0;
+
+void hclear_fonts(void)
+{fmem_ptr= 0;
+}
+#line 10740 "btex.w"
+static internal_font_number font_ptr;
+static four_quarters font_check0[font_max-font_base+1],*const font_check= font_check0-font_base;
+scaled font_size0[font_max-font_base+1],*const font_size= font_size0-font_base;
+static scaled font_dsize0[font_max-font_base+1],*const font_dsize= font_dsize0-font_base;
+static font_index font_params0[font_max-font_base+1],*const font_params= font_params0-font_base;
+
+#line 966 "htex.ch"
+char*font_name0[font_max-font_base+1],**const font_name= font_name0-font_base;
+#line 10748 "btex.w"
+static eight_bits font_bc0[font_max-font_base+1],*const font_bc= font_bc0-font_base;
+
+static eight_bits font_ec0[font_max-font_base+1],*const font_ec= font_ec0-font_base;
+
+static pointer font_glue0[font_max-font_base+1],*const font_glue= font_glue0-font_base;
+
+static bool font_used0[font_max-font_base+1],*const font_used= font_used0-font_base;
+
+static int hyphen_char0[font_max-font_base+1],*const hyphen_char= hyphen_char0-font_base;
+
+static int skew_char0[font_max-font_base+1],*const skew_char= skew_char0-font_base;
+
+static font_index bchar_label0[font_max-font_base+1],*const bchar_label= bchar_label0-font_base;
+
+
+static int16_t font_bchar0[font_max-font_base+1],*const font_bchar= font_bchar0-font_base;
+
+static int16_t font_false_bchar0[font_max-font_base+1],*const font_false_bchar= font_false_bchar0-font_base;
+
+
+/*:560*//*561:*/
+#line 973 "htex.ch"
+
+int char_base0[font_max-font_base+1],*const char_base= char_base0-font_base;
+#line 10779 "btex.w"
+
+int width_base0[font_max-font_base+1],*const width_base= width_base0-font_base;
+
+static int height_base0[font_max-font_base+1],*const height_base= height_base0-font_base;
+
+static int depth_base0[font_max-font_base+1],*const depth_base= depth_base0-font_base;
+
+static int italic_base0[font_max-font_base+1],*const italic_base= italic_base0-font_base;
+
+static int lig_kern_base0[font_max-font_base+1],*const lig_kern_base= lig_kern_base0-font_base;
+
+static int kern_base0[font_max-font_base+1],*const kern_base= kern_base0-font_base;
+
+static int exten_base0[font_max-font_base+1],*const exten_base= exten_base0-font_base;
+
+static int param_base0[font_max-font_base+1],*const param_base= param_base0-font_base;
+
+
+/*:561*//*571:*/
+#line 981 "htex.ch"
+
+void read_font_info(int f,char*nom,scaled s)
+#line 10925 "btex.w"
+{
+int k;
+bool file_opened;
+halfword lf,lh,bc,ec,nw,nh,nd,ni,nl,nk,ne,np;
+
+#line 10932 "btex.w"
+eight_bits a,b,c,d;
+four_quarters qw;scaled sw;
+int bch_label;
+int bchar;
+scaled z;
+int alpha;int beta;
+
+#line 10940 "btex.w"
+/*573:*/
+#line 10976 "btex.w"
+
+/*574:*/
+#line 1013 "htex.ch"
+
+file_opened= true
+#line 10994 "btex.w"
+
+/*:574*/
+#line 10977 "btex.w"
+;
+/*576:*/
+#line 11016 "btex.w"
+
+{read_sixteen(lf);
+fget;read_sixteen(lh);
+fget;read_sixteen(bc);
+fget;read_sixteen(ec);
+if((bc> ec+1)||(ec> 255))abort;
+if(bc> 255)
+{bc= 1;ec= 0;
+}
+fget;read_sixteen(nw);
+fget;read_sixteen(nh);
+fget;read_sixteen(nd);
+fget;read_sixteen(ni);
+fget;read_sixteen(nl);
+fget;read_sixteen(nk);
+fget;read_sixteen(ne);
+fget;read_sixteen(np);
+if(lf!=6+lh+(ec-bc+1)+nw+nh+nd+ni+nl+nk+ne+np)abort;
+if((nw==0)||(nh==0)||(nd==0)||(ni==0))abort;
+}
+
+/*:576*/
+#line 10978 "btex.w"
+;
+/*577:*/
+#line 11043 "btex.w"
+
+lf= lf-6-lh;
+if(np<7)lf= lf+7-np;
+if((font_ptr==font_max)||(fmem_ptr+lf> font_mem_size))
+#line 1029 "htex.ch"
+QUIT("Not enough room left for font %s\n",nom);
+#line 11049 "btex.w"
+char_base[f]= fmem_ptr-bc;
+width_base[f]= char_base[f]+ec+1;
+height_base[f]= width_base[f]+nw;
+depth_base[f]= height_base[f]+nh;
+italic_base[f]= depth_base[f]+nd;
+lig_kern_base[f]= italic_base[f]+ni;
+kern_base[f]= lig_kern_base[f]+nl-kern_base_offset;
+exten_base[f]= kern_base[f]+kern_base_offset+nk;
+param_base[f]= exten_base[f]+ne
+
+/*:577*/
+#line 10979 "btex.w"
+;
+/*579:*/
+#line 11072 "btex.w"
+
+{if(lh<2)abort;
+store_four_quarters(font_check[f]);
+fget;read_sixteen(z);
+fget;z= z*0400+fbyte;fget;z= (z*020)+(fbyte/020);
+if(z<unity)abort;
+while(lh> 2)
+{fget;fget;fget;fget;decr(lh);
+}
+font_dsize[f]= z;
+if(s!=-1000)
+if(s>=0)z= s;
+else z= xn_over_d(z,-s,1000);
+font_size[f]= z;
+}
+
+/*:579*/
+#line 10980 "btex.w"
+;
+/*580:*/
+#line 11088 "btex.w"
+
+for(k= fmem_ptr;k<=width_base[f]-1;k++)
+{store_four_quarters(font_info[k].qqqq);
+if((a>=nw)||(b/020>=nh)||(b%020>=nd)||
+(c/4>=ni))abort;
+switch(c%4){
+case lig_tag:if(d>=nl)abort;break;
+case ext_tag:if(d>=ne)abort;break;
+case list_tag:/*581:*/
+#line 11109 "btex.w"
+
+{check_byte_range(d);
+while(d<current_character_being_worked_on)
+{qw= char_info(f,d);
+
+if(char_tag(qw)!=list_tag)goto not_found;
+d= qo(rem_byte(qw));
+}
+if(d==current_character_being_worked_on)abort;
+not_found:;}
+
+/*:581*/
+#line 11096 "btex.w"
+break;
+default:do_nothing;
+}
+}
+
+/*:580*/
+#line 10981 "btex.w"
+;
+/*582:*/
+#line 11144 "btex.w"
+
+{/*583:*/
+#line 11154 "btex.w"
+
+{alpha= 16;
+while(z>=040000000)
+{z= z/2;alpha= alpha+alpha;
+}
+beta= 256/alpha;alpha= alpha*z;
+}
+
+/*:583*/
+#line 11145 "btex.w"
+;
+for(k= width_base[f];k<=lig_kern_base[f]-1;k++)
+store_scaled(font_info[k].sc);
+if(font_info[width_base[f]].sc!=0)abort;
+if(font_info[height_base[f]].sc!=0)abort;
+if(font_info[depth_base[f]].sc!=0)abort;
+if(font_info[italic_base[f]].sc!=0)abort;
+}
+
+/*:582*/
+#line 10982 "btex.w"
+;
+/*584:*/
+#line 11168 "btex.w"
+
+bch_label= 077777;bchar= 256;
+if(nl> 0)
+{for(k= lig_kern_base[f];k<=kern_base[f]+kern_base_offset-1;k++)
+{store_four_quarters(font_info[k].qqqq);
+if(a> 128)
+{if(256*c+d>=nl)abort;
+if(a==255)if(k==lig_kern_base[f])bchar= b;
+}
+else{if(b!=bchar)check_existence(b);
+if(c<128)check_existence(d)
+else if(256*(c-128)+d>=nk)abort;
+if(a<128)if(k-lig_kern_base[f]+a+1>=nl)abort;
+}
+}
+if(a==255)bch_label= 256*c+d;
+}
+for(k= kern_base[f]+kern_base_offset;k<=exten_base[f]-1;k++)
+store_scaled(font_info[k].sc);
+
+/*:584*/
+#line 10983 "btex.w"
+;
+/*585:*/
+#line 11188 "btex.w"
+
+for(k= exten_base[f];k<=param_base[f]-1;k++)
+{store_four_quarters(font_info[k].qqqq);
+if(a!=0)check_existence(a);
+if(b!=0)check_existence(b);
+if(c!=0)check_existence(c);
+check_existence(d);
+}
+
+/*:585*/
+#line 10984 "btex.w"
+;
+/*586:*/
+#line 11200 "btex.w"
+
+{for(k= 1;k<=np;k++)
+if(k==1)
+{fget;sw= fbyte;if(sw> 127)sw= sw-256;
+fget;sw= sw*0400+fbyte;fget;sw= sw*0400+fbyte;
+fget;font_info[param_base[f]].sc= 
+(sw*020)+(fbyte/020);
+}
+else store_scaled(font_info[param_base[f]+k-1].sc);
+#line 1035 "htex.ch"
+if(hpos>=hend)abort;
+#line 11210 "btex.w"
+for(k= np+1;k<=7;k++)font_info[param_base[f]+k-1].sc= 0;
+}
+
+/*:586*/
+#line 10985 "btex.w"
+;
+/*587:*/
+#line 11220 "btex.w"
+
+if(np>=7)font_params[f]= np;else font_params[f]= 7;
+#line 1041 "htex.ch"
+hyphen_char[f]= skew_char[f]= -1;
+#line 11223 "btex.w"
+if(bch_label<nl)bchar_label[f]= bch_label+lig_kern_base[f];
+else bchar_label[f]= non_address;
+font_bchar[f]= qi(bchar);
+font_false_bchar[f]= qi(bchar);
+if(bchar<=ec)if(bchar>=bc)
+{qw= char_info(f,bchar);
+if(char_exists(qw))font_false_bchar[f]= non_char;
+}
+font_name[f]= nom;
+#line 11233 "btex.w"
+font_bc[f]= bc;font_ec[f]= ec;font_glue[f]= null;
+adjust(char_base);adjust(width_base);adjust(lig_kern_base);
+adjust(kern_base);adjust(exten_base);
+decr(param_base[f]);
+#line 1052 "htex.ch"
+fmem_ptr= fmem_ptr+lf;goto done
+#line 11238 "btex.w"
+
+/*:587*/
+#line 10986 "btex.w"
+
+
+#line 1013 "htex.ch"
+/*:573*/
+#line 10942 "btex.w"
+;
+#line 1001 "htex.ch"
+bad_tfm:QUIT("Bad tfm file: %s\n",nom);
+done:;
+#line 10946 "btex.w"
+}
+
+/*:571*//*593:*/
+#line 1068 "htex.ch"
+
+pointer new_character(internal_font_number f,eight_bits c)
+{pointer p;
+#ifdef DEBUG
+if(font_bc[f]> c||font_ec[f]<c||!char_exists(char_info(f,qi(c))))
+DBG(DBGFONT,"Warning: Character 0x%0X in font %d does not exist\n",c,f);
+#endif
+p= get_avail();font(p)= f;character(p)= qi(c);
+return p;
+}
+#line 11335 "btex.w"
+
+/*:593*//*662:*/
+#line 1100 "htex.ch"
+
+pointer hpack(pointer p,scaled w,small_number m)
+#line 12916 "btex.w"
+{
+pointer r;
+pointer q;
+scaled h,d,x;
+scaled s;
+pointer g;
+glue_ord o;
+internal_font_number f;
+four_quarters i;
+eight_bits hd;
+#line 1107 "htex.ch"
+r= get_node(box_node_size);type(r)= hlist_node;
+#line 12927 "btex.w"
+subtype(r)= min_quarterword;shift_amount(r)= 0;
+q= r+list_offset;link(q)= p;
+h= 0;/*663:*/
+#line 12942 "btex.w"
+
+d= 0;x= 0;
+total_stretch[normal]= 0;total_shrink[normal]= 0;
+total_stretch[fil]= 0;total_shrink[fil]= 0;
+total_stretch[fill]= 0;total_shrink[fill]= 0;
+total_stretch[filll]= 0;total_shrink[filll]= 0
+
+/*:663*/
+#line 12929 "btex.w"
+;
+while(p!=null)/*664:*/
+#line 12949 "btex.w"
+
+
+{reswitch:while(is_char_node(p))
+/*667:*/
+#line 12992 "btex.w"
+
+{f= font(p);i= char_info(f,character(p));hd= height_depth(i);
+x= x+char_width(f,i);
+s= char_height(f,hd);if(s> h)h= s;
+s= char_depth(f,hd);if(s> d)d= s;
+p= link(p);
+}
+
+/*:667*/
+#line 12953 "btex.w"
+;
+if(p!=null)
+{switch(type(p)){
+case hlist_node:case vlist_node:case rule_node:case unset_node:
+/*666:*/
+#line 12980 "btex.w"
+
+{x= x+width(p);
+if(type(p)>=rule_node)s= 0;else s= shift_amount(p);
+if(height(p)-s> h)h= height(p)-s;
+if(depth(p)+s> d)d= depth(p)+s;
+}
+
+/*:666*/
+#line 12957 "btex.w"
+break;
+case ins_node:case mark_node:case adjust_node:if(adjust_tail!=null)
+/*668:*/
+#line 13007 "btex.w"
+
+{while(link(q)!=p)q= link(q);
+if(type(p)==adjust_node)
+{link(adjust_tail)= adjust_ptr(p);
+while(link(adjust_tail)!=null)adjust_tail= link(adjust_tail);
+p= link(p);free_node(link(q),small_node_size);
+}
+else{link(adjust_tail)= p;adjust_tail= p;p= link(p);
+}
+link(q)= p;p= q;
+}
+
+/*:668*/
+#line 12959 "btex.w"
+break;
+case whatsit_node:/*1389:*/
+#line 2595 "htex.ch"
+
+if(subtype(p)==image_node)
+{glue_ord o;
+if(image_height(p)> h)h= image_height(p);
+x= x+image_width(p);
+o= image_stretch_order(p);total_stretch[o]= total_stretch[o]+image_stretch(p);
+o= image_shrink_order(p);total_shrink[o]= total_shrink[o]+image_shrink(p);
+}
+#line 24777 "btex.w"
+
+/*:1389*/
+#line 12960 "btex.w"
+;break;
+case glue_node:/*669:*/
+#line 13019 "btex.w"
+
+{g= glue_ptr(p);x= x+width(g);
+o= stretch_order(g);total_stretch[o]= total_stretch[o]+stretch(g);
+o= shrink_order(g);total_shrink[o]= total_shrink[o]+shrink(g);
+if(subtype(p)>=a_leaders)
+{g= leader_ptr(p);
+if(height(g)> h)h= height(g);
+if(depth(g)> d)d= depth(g);
+}
+}
+
+/*:669*/
+#line 12961 "btex.w"
+break;
+case kern_node:case math_node:x= x+width(p);break;
+case ligature_node:/*665:*/
+#line 12971 "btex.w"
+
+{mem[lig_trick]= mem[lig_char(p)];link(lig_trick)= link(p);
+p= lig_trick;goto reswitch;
+}
+
+/*:665*/
+#line 12963 "btex.w"
+
+default:do_nothing;
+}
+p= link(p);
+}
+}
+
+
+/*:664*/
+#line 12932 "btex.w"
+;
+if(adjust_tail!=null)link(adjust_tail)= null;
+height(r)= h;depth(r)= d;
+/*670:*/
+#line 13033 "btex.w"
+
+if(m==additional)w= x+w;
+width(r)= w;x= w-x;
+if(x==0)
+{glue_sign(r)= normal;glue_order(r)= normal;
+set_glue_ratio_zero(glue_set(r));
+goto end;
+}
+else if(x> 0)/*671:*/
+#line 13045 "btex.w"
+
+{/*672:*/
+#line 13059 "btex.w"
+
+if(total_stretch[filll]!=0)o= filll;
+else if(total_stretch[fill]!=0)o= fill;
+else if(total_stretch[fil]!=0)o= fil;
+else o= normal
+
+/*:672*/
+#line 13046 "btex.w"
+;
+glue_order(r)= o;glue_sign(r)= stretching;
+if(total_stretch[o]!=0)glue_set(r)= unfloat(x/(double)total_stretch[o]);
+
+else{glue_sign(r)= normal;
+set_glue_ratio_zero(glue_set(r));
+}
+#line 13056 "btex.w"
+goto end;
+}
+
+/*:671*/
+#line 13042 "btex.w"
+
+else/*677:*/
+#line 13104 "btex.w"
+
+{/*678:*/
+#line 13123 "btex.w"
+
+if(total_shrink[filll]!=0)o= filll;
+else if(total_shrink[fill]!=0)o= fill;
+else if(total_shrink[fil]!=0)o= fil;
+else o= normal
+
+/*:678*/
+#line 13105 "btex.w"
+;
+glue_order(r)= o;glue_sign(r)= shrinking;
+if(total_shrink[o]!=0)glue_set(r)= unfloat((-x)/(double)total_shrink[o]);
+
+else{glue_sign(r)= normal;
+set_glue_ratio_zero(glue_set(r));
+}
+if((total_shrink[o]<-x)&&(o==normal)&&(list_ptr(r)!=null))
+#line 1132 "htex.ch"
+set_glue_ratio_one(glue_set(r));
+#line 13120 "btex.w"
+goto end;
+}
+
+/*:677*/
+#line 13043 "btex.w"
+
+
+/*:670*/
+#line 12936 "btex.w"
+;
+#line 12939 "btex.w"
+end:return r;
+}
+
+/*:662*//*682:*/
+#line 1142 "htex.ch"
+
+pointer vpackage(pointer p,scaled h,small_number m,scaled l)
+#line 13162 "btex.w"
+{
+pointer r;
+scaled w,d,x;
+scaled s;
+pointer g;
+glue_ord o;
+#line 1149 "htex.ch"
+r= get_node(box_node_size);type(r)= vlist_node;
+#line 13169 "btex.w"
+subtype(r)= min_quarterword;shift_amount(r)= 0;
+list_ptr(r)= p;
+w= 0;/*663:*/
+#line 12942 "btex.w"
+
+d= 0;x= 0;
+total_stretch[normal]= 0;total_shrink[normal]= 0;
+total_stretch[fil]= 0;total_shrink[fil]= 0;
+total_stretch[fill]= 0;total_shrink[fill]= 0;
+total_stretch[filll]= 0;total_shrink[filll]= 0
+
+/*:663*/
+#line 13171 "btex.w"
+;
+while(p!=null)/*683:*/
+#line 13186 "btex.w"
+
+{if(is_char_node(p))confusion("vpack");
+
+else switch(type(p)){
+case hlist_node:case vlist_node:case rule_node:case unset_node:
+/*684:*/
+#line 13201 "btex.w"
+
+{x= x+d+height(p);d= depth(p);
+if(type(p)>=rule_node)s= 0;else s= shift_amount(p);
+if(width(p)+s> w)w= width(p)+s;
+}
+
+/*:684*/
+#line 13191 "btex.w"
+break;
+case whatsit_node:/*1388:*/
+#line 2582 "htex.ch"
+
+if(subtype(p)==image_node)
+{glue_ord o;
+if(image_width(p)> w)w= image_width(p);
+x= x+d+image_height(p);d= 0;
+o= image_stretch_order(p);total_stretch[o]= total_stretch[o]+image_stretch(p);
+o= image_shrink_order(p);total_shrink[o]= total_shrink[o]+image_shrink(p);
+}
+#line 24775 "btex.w"
+
+#line 2595 "htex.ch"
+/*:1388*/
+#line 13192 "btex.w"
+;break;
+case glue_node:/*685:*/
+#line 13207 "btex.w"
+
+{x= x+d;d= 0;
+g= glue_ptr(p);x= x+width(g);
+o= stretch_order(g);total_stretch[o]= total_stretch[o]+stretch(g);
+o= shrink_order(g);total_shrink[o]= total_shrink[o]+shrink(g);
+if(subtype(p)>=a_leaders)
+{g= leader_ptr(p);
+if(width(g)> w)w= width(g);
+}
+}
+
+/*:685*/
+#line 13193 "btex.w"
+break;
+case kern_node:{x= x+d+width(p);d= 0;
+}break;
+default:do_nothing;
+}
+p= link(p);
+}
+
+/*:683*/
+#line 13173 "btex.w"
+;
+width(r)= w;
+if(d> l)
+{x= x+d-l;depth(r)= l;
+}
+else depth(r)= d;
+/*686:*/
+#line 13221 "btex.w"
+
+if(m==additional)h= x+h;
+height(r)= h;x= h-x;
+if(x==0)
+{glue_sign(r)= normal;glue_order(r)= normal;
+set_glue_ratio_zero(glue_set(r));
+goto end;
+}
+else if(x> 0)/*687:*/
+#line 13233 "btex.w"
+
+{/*672:*/
+#line 13059 "btex.w"
+
+if(total_stretch[filll]!=0)o= filll;
+else if(total_stretch[fill]!=0)o= fill;
+else if(total_stretch[fil]!=0)o= fil;
+else o= normal
+
+/*:672*/
+#line 13234 "btex.w"
+;
+glue_order(r)= o;glue_sign(r)= stretching;
+if(total_stretch[o]!=0)glue_set(r)= unfloat(x/(double)total_stretch[o]);
+
+else{glue_sign(r)= normal;
+set_glue_ratio_zero(glue_set(r));
+}
+#line 13244 "btex.w"
+goto end;
+}
+
+/*:687*/
+#line 13230 "btex.w"
+
+else/*690:*/
+#line 13272 "btex.w"
+
+{/*678:*/
+#line 13123 "btex.w"
+
+if(total_shrink[filll]!=0)o= filll;
+else if(total_shrink[fill]!=0)o= fill;
+else if(total_shrink[fil]!=0)o= fil;
+else o= normal
+
+/*:678*/
+#line 13273 "btex.w"
+;
+glue_order(r)= o;glue_sign(r)= shrinking;
+if(total_shrink[o]!=0)glue_set(r)= unfloat((-x)/(double)total_shrink[o]);
+
+else{glue_sign(r)= normal;
+set_glue_ratio_zero(glue_set(r));
+}
+if((total_shrink[o]<-x)&&(o==normal)&&(list_ptr(r)!=null))
+#line 1174 "htex.ch"
+set_glue_ratio_one(glue_set(r));
+#line 13288 "btex.w"
+goto end;
+}
+
+/*:690*/
+#line 13231 "btex.w"
+
+
+/*:686*/
+#line 13180 "btex.w"
+;
+#line 13183 "btex.w"
+end:return r;
+}
+
+/*:682*//*830:*/
+#line 1217 "htex.ch"
+
+
+/*693:*/
+#line 1180 "htex.ch"
+
+extern pointer happend_to_vlist(pointer b);
+void append_to_vlist(pointer b,uint32_t offset)
+#line 13312 "btex.w"
+{scaled d;
+pointer p;
+if(prev_depth> ignore_depth)
+{d= width(baseline_skip)-prev_depth-height(b);
+#line 1191 "htex.ch"
+if(d<line_skip_limit)p= new_glue(line_skip);
+else{temp_ptr= new_spec(baseline_skip);
+p= new_glue(temp_ptr);glue_ref_count(temp_ptr)= null;
+width(temp_ptr)= d;
+}
+store_map(p,node_pos,offset);
+#line 13320 "btex.w"
+link(tail)= p;tail= p;
+}
+link(tail)= b;tail= b;prev_depth= depth(b);
+}
+
+/*:693*//*844:*/
+#line 16265 "btex.w"
+
+static pointer finite_shrink(pointer p)
+{pointer q;
+#line 1297 "htex.ch"
+QUIT("Infinite glue shrinkage found in a paragraph");
+#line 16287 "btex.w"
+q= new_spec(p);shrink_order(q)= normal;
+delete_glue_ref(p);return q;
+}
+
+/*:844*//*848:*/
+#line 16345 "btex.w"
+
+static void try_break(int pi,small_number break_type)
+{
+pointer r;
+pointer prev_r;
+halfword old_l;
+bool no_break_yet;
+/*849:*/
+#line 16373 "btex.w"
+
+pointer prev_prev_r;
+pointer s;
+pointer q;
+pointer v;
+int t;
+internal_font_number f;
+halfword l;
+bool node_r_stays_active;
+scaled line_width;
+int fit_class;
+halfword b;
+int d;
+bool artificial_demerits;
+#ifdef STAT
+pointer save_link;
+#endif
+scaled shortfall;
+
+/*:849*/
+#line 16352 "btex.w"
+
+/*850:*/
+#line 16392 "btex.w"
+
+if(abs(pi)>=inf_penalty)
+if(pi> 0)goto end;
+else pi= eject_penalty
+
+/*:850*/
+#line 16353 "btex.w"
+;
+no_break_yet= true;prev_r= active;old_l= 0;
+do_all_six(copy_to_cur_active);
+loop{resume:r= link(prev_r);
+/*851:*/
+#line 16402 "btex.w"
+
+
+if(type(r)==delta_node)
+{do_all_six(update_width);
+prev_prev_r= prev_r;prev_r= r;goto resume;
+}
+
+/*:851*/
+#line 16358 "btex.w"
+;
+/*855:*/
+#line 16447 "btex.w"
+
+{l= line_number(r);
+if(l> old_l)
+{
+if((minimum_demerits<awful_bad)&&
+((old_l!=easy_line)||(r==last_active)))
+/*856:*/
+#line 16465 "btex.w"
+
+{if(no_break_yet)/*857:*/
+#line 16501 "btex.w"
+
+{no_break_yet= false;do_all_six(set_break_width_to_background);
+s= cur_p;
+if(break_type> unhyphenated)if(cur_p!=null)
+/*861:*/
+#line 16544 "btex.w"
+
+{t= replace_count(cur_p);v= cur_p;s= post_break(cur_p);
+while(t> 0)
+{decr(t);v= link(v);
+/*862:*/
+#line 16562 "btex.w"
+
+if(is_char_node(v))
+{f= font(v);
+break_width[1]= break_width[1]-char_width(f,char_info(f,character(v)));
+}
+else switch(type(v)){
+case ligature_node:{f= font(lig_char(v));
+break_width[1]= break_width[1]-
+char_width(f,char_info(f,character(lig_char(v))));
+}break;
+case hlist_node:case vlist_node:case rule_node:case kern_node:
+break_width[1]= break_width[1]-width(v);break;
+default:confusion("disc1");
+
+}
+
+/*:862*/
+#line 16548 "btex.w"
+;
+}
+while(s!=null)
+{/*863:*/
+#line 16578 "btex.w"
+
+if(is_char_node(s))
+{f= font(s);
+break_width[1]= break_width[1]+char_width(f,char_info(f,character(s)));
+}
+else switch(type(s)){
+case ligature_node:{f= font(lig_char(s));
+break_width[1]= break_width[1]+
+char_width(f,char_info(f,character(lig_char(s))));
+}break;
+case hlist_node:case vlist_node:case rule_node:case kern_node:
+break_width[1]= break_width[1]+width(s);break;
+default:confusion("disc2");
+
+}
+
+/*:863*/
+#line 16551 "btex.w"
+;
+s= link(s);
+}
+break_width[1]= break_width[1]+disc_width;
+if(post_break(cur_p)==null)s= link(v);
+
+}
+
+/*:861*/
+#line 16505 "btex.w"
+;
+while(s!=null)
+{if(is_char_node(s))goto done;
+switch(type(s)){
+case glue_node:/*858:*/
+#line 16520 "btex.w"
+
+{v= glue_ptr(s);break_width[1]= break_width[1]-width(v);
+break_width[2+stretch_order(v)]= break_width[2+stretch_order(v)]-stretch(v);
+break_width[6]= break_width[6]-shrink(v);
+}
+
+/*:858*/
+#line 16509 "btex.w"
+break;
+case penalty_node:do_nothing;break;
+case math_node:break_width[1]= break_width[1]-width(s);break;
+case kern_node:if(subtype(s)!=explicit)goto done;
+else break_width[1]= break_width[1]-width(s);break;
+default:goto done;
+}
+s= link(s);
+}
+done:;}
+
+/*:857*/
+#line 16466 "btex.w"
+;
+/*864:*/
+#line 16603 "btex.w"
+
+if(type(prev_r)==delta_node)
+{do_all_six(convert_to_break_width);
+}
+else if(prev_r==active)
+{do_all_six(store_break_width);
+}
+else{q= get_node(delta_node_size);link(q)= r;type(q)= delta_node;
+subtype(q)= 0;
+do_all_six(new_delta_to_break_width);
+link(prev_r)= q;prev_prev_r= prev_r;prev_r= q;
+}
+
+/*:864*/
+#line 16467 "btex.w"
+;
+if(abs(adj_demerits)>=awful_bad-minimum_demerits)
+minimum_demerits= awful_bad-1;
+else minimum_demerits= minimum_demerits+abs(adj_demerits);
+for(fit_class= very_loose_fit;fit_class<=tight_fit;fit_class++)
+{if(minimal_demerits[fit_class]<=minimum_demerits)
+/*866:*/
+#line 16633 "btex.w"
+
+{q= get_node(passive_node_size);
+link(q)= passive;passive= q;cur_break(q)= cur_p;
+#ifdef STAT
+incr(pass_number);serial(q)= pass_number;
+#endif
+
+prev_break(q)= best_place[fit_class];
+q= get_node(active_node_size);break_node(q)= passive;
+line_number(q)= best_pl_line[fit_class]+1;
+fitness(q)= fit_class;type(q)= break_type;
+total_demerits(q)= minimal_demerits[fit_class];
+link(q)= r;link(prev_r)= q;prev_r= q;
+#ifdef STAT
+if(tracing_paragraphs> 0)
+/*867:*/
+#line 16653 "btex.w"
+
+{print_nl("@@");print_int(serial(passive));
+
+print(": line ");print_int(line_number(q)-1);
+print_char('.');print_int(fit_class);
+if(break_type==hyphenated)print_char('-');
+print(" t=");print_int(total_demerits(q));
+print(" -> @@");
+if(prev_break(passive)==null)print_char('0');
+else print_int(serial(prev_break(passive)));
+}
+
+/*:867*/
+#line 16648 "btex.w"
+;
+#endif
+
+}
+
+/*:866*/
+#line 16473 "btex.w"
+;
+minimal_demerits[fit_class]= awful_bad;
+}
+minimum_demerits= awful_bad;
+/*865:*/
+#line 16622 "btex.w"
+
+if(r!=last_active)
+{q= get_node(delta_node_size);link(q)= r;type(q)= delta_node;
+subtype(q)= 0;
+do_all_six(new_delta_from_break_width);
+link(prev_r)= q;prev_prev_r= prev_r;prev_r= q;
+}
+
+/*:865*/
+#line 16477 "btex.w"
+;
+}
+
+/*:856*/
+#line 16453 "btex.w"
+;
+if(r==last_active)goto end;
+/*872:*/
+#line 16729 "btex.w"
+
+if(l> easy_line)
+{line_width= second_width;old_l= max_halfword-1;
+}
+else{old_l= l;
+if(l> last_special_line)line_width= second_width;
+else if(par_shape_ptr==null)line_width= first_width;
+else line_width= mem[par_shape_ptr+2*l].sc;
+}
+
+/*:872*/
+#line 16455 "btex.w"
+;
+}
+}
+
+/*:855*/
+#line 16361 "btex.w"
+;
+/*873:*/
+#line 16749 "btex.w"
+
+{artificial_demerits= false;
+
+shortfall= line_width-cur_active_width[1];
+if(shortfall> 0)
+/*874:*/
+#line 16779 "btex.w"
+
+if((cur_active_width[3]!=0)||(cur_active_width[4]!=0)||
+(cur_active_width[5]!=0))
+{b= 0;fit_class= decent_fit;
+}
+else{if(shortfall> 7230584)if(cur_active_width[2]<1663497)
+{b= inf_bad;fit_class= very_loose_fit;goto done1;
+}
+b= badness(shortfall,cur_active_width[2]);
+if(b> 12)
+if(b> 99)fit_class= very_loose_fit;
+else fit_class= loose_fit;
+else fit_class= decent_fit;
+done1:;
+}
+
+/*:874*/
+#line 16755 "btex.w"
+
+else/*875:*/
+#line 16798 "btex.w"
+
+{if(-shortfall> cur_active_width[6])b= inf_bad+1;
+else b= badness(-shortfall,cur_active_width[6]);
+if(b> 12)fit_class= tight_fit;else fit_class= decent_fit;
+}
+
+/*:875*/
+#line 16757 "btex.w"
+;
+if((b> inf_bad)||(pi==eject_penalty))
+/*876:*/
+#line 16813 "btex.w"
+
+{if(final_pass&&(minimum_demerits==awful_bad)&&
+(link(r)==last_active)&&
+(prev_r==active))
+artificial_demerits= true;
+else if(b> threshold)goto deactivate;
+node_r_stays_active= false;
+}
+
+/*:876*/
+#line 16760 "btex.w"
+
+else{prev_r= r;
+if(b> threshold)goto resume;
+node_r_stays_active= true;
+}
+/*877:*/
+#line 16829 "btex.w"
+
+if(artificial_demerits)d= 0;
+else/*881:*/
+#line 16890 "btex.w"
+
+{d= line_penalty+b;
+if(abs(d)>=10000)d= 100000000;else d= d*d;
+if(pi!=0)
+if(pi> 0)d= d+pi*pi;
+else if(pi> eject_penalty)d= d-pi*pi;
+if((break_type==hyphenated)&&(type(r)==hyphenated))
+if(cur_p!=null)d= d+double_hyphen_demerits;
+else d= d+final_hyphen_demerits;
+if(abs(fit_class-fitness(r))> 1)d= d+adj_demerits;
+}
+
+/*:881*/
+#line 16831 "btex.w"
+;
+#ifdef STAT
+if(tracing_paragraphs> 0)
+/*878:*/
+#line 16845 "btex.w"
+
+{if(printed_node!=cur_p)
+/*879:*/
+#line 16867 "btex.w"
+
+{print_nl("");
+if(cur_p==null)short_display(link(printed_node));
+else{save_link= link(cur_p);
+link(cur_p)= null;print_nl("");short_display(link(printed_node));
+link(cur_p)= save_link;
+}
+printed_node= cur_p;
+}
+
+/*:879*/
+#line 16847 "btex.w"
+;
+print_nl("@");
+
+if(cur_p==null)print_esc("par");
+else if(type(cur_p)!=glue_node)
+{if(type(cur_p)==penalty_node)print_esc("penalty");
+else if(type(cur_p)==disc_node)print_esc("discretionary");
+else if(type(cur_p)==kern_node)print_esc("kern");
+else print_esc("math");
+}
+print(" via @@");
+if(break_node(r)==null)print_char('0');
+else print_int(serial(break_node(r)));
+print(" b=");
+if(b> inf_bad)print_char('*');else print_int(b);
+
+print(" p=");print_int(pi);print(" d=");
+if(artificial_demerits)print_char('*');else print_int(d);
+}
+
+/*:878*/
+#line 16834 "btex.w"
+;
+#endif
+
+d= d+total_demerits(r);
+
+if(d<=minimal_demerits[fit_class])
+{minimal_demerits[fit_class]= d;
+best_place[fit_class]= break_node(r);best_pl_line[fit_class]= l;
+if(d<minimum_demerits)minimum_demerits= d;
+}
+
+/*:877*/
+#line 16765 "btex.w"
+;
+if(node_r_stays_active)goto resume;
+deactivate:/*882:*/
+#line 16912 "btex.w"
+
+link(prev_r)= link(r);free_node(r,active_node_size);
+if(prev_r==active)/*883:*/
+#line 16937 "btex.w"
+
+{r= link(active);
+if(type(r)==delta_node)
+{do_all_six(update_active);
+do_all_six(copy_to_cur_active);
+link(active)= link(r);free_node(r,delta_node_size);
+}
+}
+
+/*:883*/
+#line 16915 "btex.w"
+
+else if(type(prev_r)==delta_node)
+{r= link(prev_r);
+if(r==last_active)
+{do_all_six(downdate_width);
+link(prev_prev_r)= last_active;
+free_node(prev_r,delta_node_size);prev_r= prev_prev_r;
+}
+else if(type(r)==delta_node)
+{do_all_six(update_width);
+do_all_six(combine_two_deltas);
+link(prev_r)= link(r);free_node(r,delta_node_size);
+}
+}
+
+/*:882*/
+#line 16767 "btex.w"
+;
+}
+
+/*:873*/
+#line 16364 "btex.w"
+;
+}
+end:;
+#ifdef STAT
+/*880:*/
+#line 16882 "btex.w"
+
+if(cur_p==printed_node)if(cur_p!=null)if(type(cur_p)==disc_node)
+{t= replace_count(cur_p);
+while(t> 0)
+{decr(t);printed_node= link(printed_node);
+}
+}
+
+/*:880*/
+#line 16368 "btex.w"
+;
+#endif
+
+}
+
+/*:848*//*900:*/
+#line 17262 "btex.w"
+
+static void post_line_break(int final_widow_penalty)
+{
+pointer q,r,s;
+bool disc_break;
+#line 1437 "htex.ch"
+bool post_disc_break;
+bool first_line= true;
+uint32_t line_offset,next_offset;
+#line 17268 "btex.w"
+scaled cur_width;
+scaled cur_indent;
+quarterword t;
+int pen;
+halfword cur_line;
+/*901:*/
+#line 17293 "btex.w"
+
+q= break_node(best_bet);cur_p= null;
+do{r= q;q= prev_break(q);next_break(r)= cur_p;cur_p= r;
+}while(!(q==null))
+
+/*:901*/
+#line 17273 "btex.w"
+;
+cur_line= prev_graf+1;
+#line 1446 "htex.ch"
+next_offset= hposition(link(temp_head));
+if(next_offset> node_pos)
+next_offset= next_offset-node_pos;
+else
+next_offset= 0;
+do{
+line_offset= next_offset;
+{pointer q= cur_break(cur_p);
+if(q==null)
+next_offset= (hstart-hpos);
+else
+next_offset= hposition(q);
+if(next_offset> node_pos)
+next_offset= next_offset-node_pos;
+else
+next_offset= 0;
+}
+/*903:*/
+#line 17330 "btex.w"
+
+/*904:*/
+#line 17342 "btex.w"
+
+q= cur_break(cur_p);disc_break= false;post_disc_break= false;
+if(q!=null)
+if(type(q)==glue_node)
+{delete_glue_ref(glue_ptr(q));
+glue_ptr(q)= right_skip;
+subtype(q)= right_skip_code+1;add_glue_ref(right_skip);
+goto done;
+}
+else{if(type(q)==disc_node)
+/*905:*/
+#line 1476 "htex.ch"
+
+{pointer pre_q= pre_break(q);
+pointer post_q= post_break(q);
+t= replace_count(q);
+type(q)= whatsit_node;
+subtype(q)= ignore_node;
+ignore_info(q)= 1;
+/*906:*/
+#line 1508 "htex.ch"
+
+if(t==0){ignore_list(q)= null;r= link(q);}
+else{r= q;
+while(t> 1)
+{r= link(r);decr(t);
+}
+s= link(r);
+r= link(s);link(s)= null;
+ignore_list(q)= link(q);
+}
+#line 17379 "btex.w"
+
+/*:906*/
+#line 1483 "htex.ch"
+;
+s= get_node(ignore_node_size);
+type(s)= whatsit_node;
+subtype(s)= ignore_node;
+ignore_info(s)= 0;
+ignore_list(s)= null;
+link(s)= r;r= s;
+if(post_q!=null)/*907:*/
+#line 1527 "htex.ch"
+
+{s= post_q;
+while(link(s)!=null)s= link(s);
+link(s)= r;r= post_q;post_disc_break= true;
+}
+#line 17388 "btex.w"
+
+/*:907*/
+#line 1490 "htex.ch"
+;
+if(pre_q!=null)/*908:*/
+#line 1541 "htex.ch"
+
+{s= pre_q;link(q)= s;
+while(link(s)!=null)s= link(s);
+q= s;
+}
+#line 17397 "btex.w"
+
+/*:908*/
+#line 1491 "htex.ch"
+;
+link(q)= r;disc_break= true;
+}
+#line 17368 "btex.w"
+
+#line 1508 "htex.ch"
+/*:905*/
+#line 17352 "btex.w"
+
+else if((type(q)==math_node)||(type(q)==kern_node))width(q)= 0;
+}
+else{q= temp_head;
+while(link(q)!=null)q= link(q);
+}
+/*909:*/
+#line 17398 "btex.w"
+
+#line 1551 "htex.ch"
+r= new_glue(right_skip);link(r)= link(q);link(q)= r;q= r
+#line 17400 "btex.w"
+
+/*:909*/
+#line 17358 "btex.w"
+;
+done:
+
+#line 1476 "htex.ch"
+/*:904*/
+#line 17332 "btex.w"
+;
+/*910:*/
+#line 17405 "btex.w"
+
+r= link(q);link(q)= null;q= link(temp_head);link(temp_head)= r;
+if(left_skip!=zero_glue)
+#line 1557 "htex.ch"
+{r= new_glue(left_skip);
+#line 17409 "btex.w"
+link(r)= q;q= r;
+}
+
+/*:910*/
+#line 17333 "btex.w"
+;
+/*912:*/
+#line 17424 "btex.w"
+
+if(cur_line> last_special_line)
+{cur_width= second_width;cur_indent= second_indent;
+}
+else if(par_shape_ptr==null)
+{cur_width= first_width;cur_indent= first_indent;
+}
+else{cur_width= mem[par_shape_ptr+2*cur_line].sc;
+cur_indent= mem[par_shape_ptr+2*cur_line-1].sc;
+}
+adjust_tail= adjust_head;just_box= hpack(q,cur_width,exactly);
+shift_amount(just_box)= cur_indent
+
+/*:912*/
+#line 17334 "btex.w"
+;
+/*911:*/
+#line 17412 "btex.w"
+
+#line 1563 "htex.ch"
+if(first_line)
+{pointer p= happend_to_vlist(just_box);
+uint32_t pos= hposition(p);
+store_map(p,pos,line_offset);
+first_line= false;
+}
+else
+append_to_vlist(just_box,line_offset);
+#line 17414 "btex.w"
+if(adjust_head!=adjust_tail)
+{link(tail)= link(adjust_head);tail= adjust_tail;
+}
+adjust_tail= null
+
+/*:911*/
+#line 17336 "btex.w"
+;
+/*913:*/
+#line 17444 "btex.w"
+
+if(cur_line+1!=best_line)
+{pen= inter_line_penalty;
+if(cur_line==prev_graf+1)pen= pen+club_penalty;
+if(cur_line+2==best_line)pen= pen+final_widow_penalty;
+if(disc_break)pen= pen+broken_penalty;
+if(pen!=0)
+#line 1576 "htex.ch"
+{r= new_penalty(pen);store_map(r,node_pos,next_offset);
+#line 17452 "btex.w"
+link(tail)= r;tail= r;
+}
+}
+
+/*:913*/
+#line 17337 "btex.w"
+
+
+/*:903*/
+#line 1464 "htex.ch"
+;
+#line 17277 "btex.w"
+incr(cur_line);cur_p= next_break(cur_p);
+if(cur_p!=null)if(!post_disc_break)
+/*902:*/
+#line 17305 "btex.w"
+
+{r= temp_head;
+loop{q= link(r);
+if(q==cur_break(cur_p))goto done1;
+
+
+if(is_char_node(q))goto done1;
+if(non_discardable(q))goto done1;
+if(type(q)==kern_node)if(subtype(q)!=explicit)goto done1;
+r= q;
+}
+done1:if(r!=temp_head)
+{link(r)= null;flush_node_list(link(temp_head));
+link(temp_head)= q;
+}
+}
+
+/*:902*/
+#line 17279 "btex.w"
+;
+}while(!(cur_p==null));
+if((cur_line!=best_line)||(link(temp_head)!=null))
+confusion("line breaking");
+
+prev_graf= best_line-1;
+}
+
+/*:900*//*918:*/
+#line 17558 "btex.w"
+
+#line 1588 "htex.ch"
+/*:918*//*966:*/
+#line 18371 "btex.w"
+
+#ifdef INIT
+#line 18374 "btex.w"
+#endif
+
+/*:966*/
+#line 1219 "htex.ch"
+
+
+void line_break(int final_widow_penalty,pointer par_ptr)
+{scaled x= cur_list.hs_field;
+#line 16034 "btex.w"
+/*884:*/
+#line 16966 "btex.w"
+
+bool auto_breaking;
+pointer prev_p;
+#line 1366 "htex.ch"
+pointer q,r,s;
+#line 16970 "btex.w"
+internal_font_number f;
+
+/*:884*//*916:*/
+#line 17539 "btex.w"
+
+#line 17542 "btex.w"
+
+/*:916*/
+#line 16034 "btex.w"
+
+#line 1228 "htex.ch"
+set_line_break_params();
+#line 16036 "btex.w"
+/*831:*/
+#line 1251 "htex.ch"
+
+link(temp_head)= par_ptr;
+#line 16067 "btex.w"
+
+/*:831*//*845:*/
+#line 16291 "btex.w"
+
+no_shrink_error_yet= true;
+check_shrinkage(left_skip);check_shrinkage(right_skip);
+q= left_skip;r= right_skip;background[1]= width(q)+width(r);
+background[2]= 0;background[3]= 0;background[4]= 0;background[5]= 0;
+background[2+stretch_order(q)]= stretch(q);
+background[2+stretch_order(r)]= background[2+stretch_order(r)]+stretch(r);
+background[6]= shrink(q)+shrink(r);
+
+/*:845*//*854:*/
+#line 16433 "btex.w"
+
+minimum_demerits= awful_bad;
+minimal_demerits[tight_fit]= awful_bad;
+minimal_demerits[decent_fit]= awful_bad;
+minimal_demerits[loose_fit]= awful_bad;
+minimal_demerits[very_loose_fit]= awful_bad;
+
+/*:854*//*870:*/
+#line 16694 "btex.w"
+
+if(par_shape_ptr==null)
+if(hang_indent==0)
+#line 1333 "htex.ch"
+{last_special_line= 0;second_width= x;
+#line 16698 "btex.w"
+second_indent= 0;
+}
+else/*871:*/
+#line 16708 "btex.w"
+
+{last_special_line= abs(hang_after);
+if(hang_after<0)
+#line 1348 "htex.ch"
+{first_width= x-abs(hang_indent);
+#line 16712 "btex.w"
+if(hang_indent>=0)first_indent= hang_indent;
+else first_indent= 0;
+#line 1357 "htex.ch"
+second_width= x;second_indent= 0;
+}
+else{first_width= x;first_indent= 0;
+second_width= x-abs(hang_indent);
+#line 16718 "btex.w"
+if(hang_indent>=0)second_indent= hang_indent;
+else second_indent= 0;
+}
+}
+
+/*:871*/
+#line 16700 "btex.w"
+
+#line 1342 "htex.ch"
+else QUIT("parshape not yet implemented");
+#line 16705 "btex.w"
+if(looseness==0)easy_line= last_special_line;
+else easy_line= max_halfword
+
+/*:870*/
+#line 16036 "btex.w"
+;
+/*885:*/
+#line 16976 "btex.w"
+
+threshold= pretolerance;
+if(threshold>=0)
+{
+#ifdef STAT
+#line 1373 "htex.ch"
+ if(tracing_paragraphs> 0)
+{print_nl("@firstpass");}
+#line 16983 "btex.w"
+#endif
+
+second_pass= false;final_pass= false;
+}
+else{threshold= tolerance;second_pass= true;
+final_pass= (emergency_stretch<=0);
+#ifdef STAT
+#line 16991 "btex.w"
+#endif
+
+}
+loop{if(threshold> inf_bad)threshold= inf_bad;
+#line 16996 "btex.w"
+/*886:*/
+#line 17034 "btex.w"
+
+q= get_node(active_node_size);
+type(q)= unhyphenated;fitness(q)= decent_fit;
+link(q)= last_active;break_node(q)= null;
+line_number(q)= prev_graf+1;total_demerits(q)= 0;link(active)= q;
+do_all_six(store_background);
+passive= null;printed_node= temp_head;pass_number= 0;
+#line 17042 "btex.w"
+
+/*:886*/
+#line 16996 "btex.w"
+;
+cur_p= link(temp_head);auto_breaking= true;
+prev_p= cur_p;
+while((cur_p!=null)&&(link(active)!=last_active))
+/*888:*/
+#line 17070 "btex.w"
+
+{if(is_char_node(cur_p))
+/*889:*/
+#line 17104 "btex.w"
+
+{prev_p= cur_p;
+do{f= font(cur_p);
+act_width= act_width+char_width(f,char_info(f,character(cur_p)));
+cur_p= link(cur_p);
+}while(!(!is_char_node(cur_p)));
+}
+
+/*:889*/
+#line 17072 "btex.w"
+;
+switch(type(cur_p)){
+case hlist_node:case vlist_node:case rule_node:act_width= act_width+width(cur_p);break;
+case whatsit_node:/*1391:*/
+#line 24783 "btex.w"
+
+adv_past(cur_p)
+
+/*:1391*/
+#line 17075 "btex.w"
+break;
+case glue_node:{/*890:*/
+#line 17115 "btex.w"
+
+if(auto_breaking)
+{if(is_char_node(prev_p))try_break(0,unhyphenated);
+else if(precedes_break(prev_p))try_break(0,unhyphenated);
+else if((type(prev_p)==kern_node)&&(subtype(prev_p)!=explicit))
+try_break(0,unhyphenated);
+}
+check_shrinkage(glue_ptr(cur_p));q= glue_ptr(cur_p);
+act_width= act_width+width(q);
+active_width[2+stretch_order(q)]= 
+active_width[2+stretch_order(q)]+stretch(q);
+active_width[6]= active_width[6]+shrink(q)
+
+/*:890*/
+#line 17077 "btex.w"
+;
+#line 17080 "btex.w"
+}break;
+case kern_node:if(subtype(cur_p)==explicit)kern_break
+else act_width= act_width+width(cur_p);break;
+case ligature_node:{f= font(lig_char(cur_p));
+act_width= act_width+char_width(f,char_info(f,character(lig_char(cur_p))));
+}break;
+case disc_node:/*891:*/
+#line 17131 "btex.w"
+
+#line 1416 "htex.ch"
+{if(!is_auto_disc(cur_p)||second_pass||final_pass)
+{s= pre_break(cur_p);disc_width= 0;
+#line 17133 "btex.w"
+if(s==null)try_break(ex_hyphen_penalty,hyphenated);
+else{do{/*892:*/
+#line 17149 "btex.w"
+
+if(is_char_node(s))
+{f= font(s);
+disc_width= disc_width+char_width(f,char_info(f,character(s)));
+}
+else switch(type(s)){
+case ligature_node:{f= font(lig_char(s));
+disc_width= disc_width+
+char_width(f,char_info(f,character(lig_char(s))));
+}break;
+case hlist_node:case vlist_node:case rule_node:case kern_node:
+disc_width= disc_width+width(s);break;
+default:confusion("disc3");
+
+}
+
+/*:892*/
+#line 17134 "btex.w"
+;
+s= link(s);
+}while(!(s==null));
+act_width= act_width+disc_width;
+try_break(hyphen_penalty,hyphenated);
+act_width= act_width-disc_width;
+}
+#line 1423 "htex.ch"
+}
+r= replace_count(cur_p);s= link(cur_p);
+#line 17142 "btex.w"
+while(r> 0)
+{/*893:*/
+#line 17165 "btex.w"
+
+if(is_char_node(s))
+{f= font(s);
+act_width= act_width+char_width(f,char_info(f,character(s)));
+}
+else switch(type(s)){
+case ligature_node:{f= font(lig_char(s));
+act_width= act_width+
+char_width(f,char_info(f,character(lig_char(s))));
+}break;
+case hlist_node:case vlist_node:case rule_node:case kern_node:
+act_width= act_width+width(s);break;
+default:confusion("disc4");
+
+}
+
+/*:893*/
+#line 17143 "btex.w"
+;
+decr(r);s= link(s);
+}
+prev_p= cur_p;cur_p= s;goto done5;
+}
+
+/*:891*/
+#line 17086 "btex.w"
+
+case math_node:{auto_breaking= (subtype(cur_p)==after);kern_break;
+}break;
+case penalty_node:try_break(penalty(cur_p),unhyphenated);break;
+case mark_node:case ins_node:case adjust_node:do_nothing;break;
+default:confusion("paragraph");
+
+}
+prev_p= cur_p;cur_p= link(cur_p);
+done5:;}
+
+/*:888*/
+#line 17002 "btex.w"
+;
+if(cur_p==null)
+/*896:*/
+#line 17200 "btex.w"
+
+{try_break(eject_penalty,hyphenated);
+if(link(active)!=last_active)
+{/*897:*/
+#line 17210 "btex.w"
+
+r= link(active);fewest_demerits= awful_bad;
+do{if(type(r)!=delta_node)if(total_demerits(r)<fewest_demerits)
+{fewest_demerits= total_demerits(r);best_bet= r;
+}
+r= link(r);
+}while(!(r==last_active));
+best_line= line_number(best_bet)
+
+/*:897*/
+#line 17203 "btex.w"
+;
+if(looseness==0)goto done;
+/*898:*/
+#line 17224 "btex.w"
+
+{r= link(active);actual_looseness= 0;
+do{if(type(r)!=delta_node)
+{line_diff= line_number(r)-best_line;
+if(((line_diff<actual_looseness)&&(looseness<=line_diff))||
+((line_diff> actual_looseness)&&(looseness>=line_diff)))
+{best_bet= r;actual_looseness= line_diff;
+fewest_demerits= total_demerits(r);
+}
+else if((line_diff==actual_looseness)&&
+(total_demerits(r)<fewest_demerits))
+{best_bet= r;fewest_demerits= total_demerits(r);
+}
+}
+r= link(r);
+}while(!(r==last_active));
+best_line= line_number(best_bet);
+}
+
+/*:898*/
+#line 17205 "btex.w"
+;
+if((actual_looseness==looseness)||final_pass)goto done;
+}
+}
+
+/*:896*/
+#line 17005 "btex.w"
+;
+/*887:*/
+#line 17043 "btex.w"
+
+q= link(active);
+while(q!=last_active)
+{cur_p= link(q);
+if(type(q)==delta_node)free_node(q,delta_node_size);
+else free_node(q,active_node_size);
+q= cur_p;
+}
+q= passive;
+while(q!=null)
+{cur_p= link(q);
+free_node(q,passive_node_size);
+q= cur_p;
+}
+
+/*:887*/
+#line 17006 "btex.w"
+;
+if(!second_pass)
+{
+#ifdef STAT
+if(tracing_paragraphs> 0)print_nl("@secondpass");
+#endif
+threshold= tolerance;second_pass= true;final_pass= (emergency_stretch<=0);
+}
+else{
+#ifdef STAT
+#line 1391 "htex.ch"
+ if(tracing_paragraphs> 0)
+print_nl("@emergencypass");
+#line 17018 "btex.w"
+#endif
+background[2]= background[2]+emergency_stretch;final_pass= true;
+}
+}
+done:
+#ifdef STAT
+#line 17027 "btex.w"
+#endif
+
+/*:885*/
+#line 16037 "btex.w"
+;
+/*899:*/
+#line 17248 "btex.w"
+
+post_line_break(final_widow_penalty)
+
+/*:899*/
+#line 16039 "btex.w"
+;
+/*887:*/
+#line 17043 "btex.w"
+
+q= link(active);
+while(q!=last_active)
+{cur_p= link(q);
+if(type(q)==delta_node)free_node(q,delta_node_size);
+else free_node(q,active_node_size);
+q= cur_p;
+}
+q= passive;
+while(q!=null)
+{cur_p= link(q);
+free_node(q,passive_node_size);
+q= cur_p;
+}
+
+/*:887*/
+#line 16040 "btex.w"
+;
+#line 1234 "htex.ch"
+hrestore_param_list();
+#line 16042 "btex.w"
+}
+
+/*:830*//*992:*/
+#line 1600 "htex.ch"
+
+
+#define ensure_vbox(N) 
+
+static pointer prune_page_top(pointer p)
+#line 18869 "btex.w"
+{pointer prev_p;
+pointer q;
+prev_p= temp_head;link(temp_head)= p;
+while(p!=null)
+switch(type(p)){
+case hlist_node:case vlist_node:case rule_node:/*993:*/
+#line 18887 "btex.w"
+
+#line 1610 "htex.ch"
+{temp_ptr= new_spec(pointer_def[glue_kind][split_top_skip_no]);
+q= new_glue(temp_ptr);glue_ref_count(temp_ptr)= null;link(prev_p)= q;link(q)= p;
+#line 18889 "btex.w"
+
+if(width(temp_ptr)> height(p))width(temp_ptr)= width(temp_ptr)-height(p);
+else width(temp_ptr)= 0;
+p= null;
+}
+
+/*:993*/
+#line 18875 "btex.w"
+break;
+case whatsit_node:case mark_node:case ins_node:{prev_p= p;p= link(prev_p);
+}break;
+case glue_node:case kern_node:case penalty_node:{q= p;p= link(q);link(q)= null;
+link(prev_p)= p;flush_node_list(q);
+}break;
+default:confusion("pruning");
+
+}
+return link(temp_head);
+}
+
+/*:992*//*994:*/
+#line 1617 "htex.ch"
+
+static pointer vert_break(pointer p,scaled h,scaled d)
+#line 18912 "btex.w"
+
+{
+pointer prev_p;
+
+pointer q,r;
+int pi;
+int b;
+int least_cost;
+pointer best_place;
+scaled prev_dp;
+small_number t;
+prev_p= p;
+least_cost= awful_bad;do_all_six(set_height_zero);prev_dp= 0;
+loop{/*997:*/
+#line 18945 "btex.w"
+
+if(p==null)pi= eject_penalty;
+else/*998:*/
+#line 18960 "btex.w"
+
+switch(type(p)){
+case hlist_node:case vlist_node:case rule_node:{
+cur_height= cur_height+prev_dp+height(p);prev_dp= depth(p);
+goto not_found;
+}
+case whatsit_node:/*1394:*/
+#line 24792 "btex.w"
+
+goto not_found
+
+/*:1394*/
+#line 18966 "btex.w"
+;
+case glue_node:if(precedes_break(prev_p))pi= 0;
+else goto update_heights;break;
+case kern_node:{if(link(p)==null)t= penalty_node;
+else t= type(link(p));
+if(t==glue_node)pi= 0;else goto update_heights;
+}break;
+case penalty_node:pi= penalty(p);break;
+case mark_node:case ins_node:goto not_found;
+default:confusion("vertbreak");
+
+}
+
+/*:998*/
+#line 18949 "btex.w"
+;
+/*999:*/
+#line 18981 "btex.w"
+
+if(pi<inf_penalty)
+{/*1000:*/
+#line 18995 "btex.w"
+
+if(cur_height<h)
+if((active_height[3]!=0)||(active_height[4]!=0)||
+(active_height[5]!=0))b= 0;
+else b= badness(h-cur_height,active_height[2]);
+else if(cur_height-h> active_height[6])b= awful_bad;
+else b= badness(cur_height-h,active_height[6])
+
+/*:1000*/
+#line 18983 "btex.w"
+;
+if(b<awful_bad)
+if(pi<=eject_penalty)b= pi;
+else if(b<inf_bad)b= b+pi;
+else b= deplorable;
+if(b<=least_cost)
+{best_place= p;least_cost= b;
+best_height_plus_depth= cur_height+prev_dp;
+}
+if((b==awful_bad)||(pi<=eject_penalty))goto done;
+}
+
+/*:999*/
+#line 18951 "btex.w"
+;
+if((type(p)<glue_node)||(type(p)> kern_node))goto not_found;
+update_heights:/*1001:*/
+#line 19007 "btex.w"
+
+if(type(p)==kern_node)q= p;
+else{q= glue_ptr(p);
+active_height[2+stretch_order(q)]= 
+active_height[2+stretch_order(q)]+stretch(q);
+active_height[6]= active_height[6]+shrink(q);
+#line 1643 "htex.ch"
+if((shrink_order(q)!=normal)&&(shrink(q)!=0))
+{
+DBG(DBGTEX,"Infinite glue shrinkage found in box being split");
+r= new_spec(q);shrink_order(r)= normal;delete_glue_ref(q);
+glue_ptr(p)= r;q= r;
+}
+#line 19024 "btex.w"
+}
+cur_height= cur_height+prev_dp+width(q);prev_dp= 0
+
+/*:1001*/
+#line 18954 "btex.w"
+;
+not_found:if(prev_dp> d)
+{cur_height= cur_height+prev_dp-d;
+prev_dp= d;
+}
+
+/*:997*/
+#line 18927 "btex.w"
+;
+prev_p= p;p= link(prev_p);
+}
+done:return best_place;
+}
+
+/*:994*//*1012:*/
+#line 1673 "htex.ch"
+
+void freeze_page_specs(small_number s)
+#line 19314 "btex.w"
+{page_contents= s;
+#line 1680 "htex.ch"
+page_goal= hvsize;page_max_depth= max_depth;
+#line 19316 "btex.w"
+page_depth= 0;do_all_six(set_page_so_far_zero);
+least_page_cost= awful_bad;
+#line 19327 "btex.w"
+
+}
+
+/*:1012*//*1020:*/
+#line 1706 "htex.ch"
+
+bool hbuild_page(void)
+#line 19412 "btex.w"
+{
+pointer p;
+pointer q,r;
+int b,c;
+int pi;
+#line 1715 "htex.ch"
+if(link(contrib_head)==null)return false;
+#line 19420 "btex.w"
+do{resume:p= link(contrib_head);
+#line 19422 "btex.w"
+/*1023:*/
+#line 19452 "btex.w"
+
+/*1026:*/
+#line 19480 "btex.w"
+
+switch(type(p)){
+case hlist_node:case vlist_node:case rule_node:if(page_contents<box_there)
+/*1027:*/
+#line 19501 "btex.w"
+
+{if(page_contents==empty)freeze_page_specs(box_there);
+else page_contents= box_there;
+#line 1745 "htex.ch"
+temp_ptr= new_spec(pointer_def[glue_kind][top_skip_no]);
+q= new_glue(temp_ptr);glue_ref_count(temp_ptr)= null;
+#line 19505 "btex.w"
+if(width(temp_ptr)> height(p))width(temp_ptr)= width(temp_ptr)-height(p);
+else width(temp_ptr)= 0;
+link(q)= p;link(contrib_head)= q;goto resume;
+}
+
+/*:1027*/
+#line 19484 "btex.w"
+
+else/*1028:*/
+#line 19510 "btex.w"
+
+{page_total= page_total+page_depth+height(p);
+page_depth= depth(p);
+goto contribute;
+}
+
+/*:1028*/
+#line 19485 "btex.w"
+break;
+case whatsit_node:/*1393:*/
+#line 24789 "btex.w"
+
+goto contribute
+
+/*:1393*/
+#line 19486 "btex.w"
+;
+case glue_node:if(page_contents<box_there)goto done1;
+else if(precedes_break(page_tail))pi= 0;
+else goto update_heights;break;
+case kern_node:if(page_contents<box_there)goto done1;
+#line 1733 "htex.ch"
+else if(link(p)==null)return false;
+#line 19492 "btex.w"
+else if(type(link(p))==glue_node)pi= 0;
+else goto update_heights;break;
+case penalty_node:if(page_contents<box_there)goto done1;else pi= penalty(p);break;
+case mark_node:goto contribute;
+#line 1739 "htex.ch"
+case ins_node:happend_insertion(p);goto contribute;
+#line 19497 "btex.w"
+default:confusion("page");
+
+}
+
+/*:1026*/
+#line 19456 "btex.w"
+;
+/*1031:*/
+#line 19544 "btex.w"
+
+if(pi<inf_penalty)
+{/*1033:*/
+#line 19588 "btex.w"
+
+if(page_total<page_goal)
+if((page_so_far[3]!=0)||(page_so_far[4]!=0)||
+(page_so_far[5]!=0))b= 0;
+else b= badness(page_goal-page_total,page_so_far[2]);
+else if(page_total-page_goal> page_shrink)b= awful_bad;
+else b= badness(page_total-page_goal,page_shrink)
+
+#line 1796 "htex.ch"
+/*:1033*/
+#line 19547 "btex.w"
+;
+if(b<awful_bad)
+if(pi<=eject_penalty)c= pi;
+else if(b<inf_bad)c= b+pi+insert_penalties;
+else c= deplorable;
+else c= b;
+if(insert_penalties>=10000)c= awful_bad;
+#line 19557 "btex.w"
+
+if(c<=least_page_cost)
+{best_page_break= p;best_size= page_goal;
+least_page_cost= c;
+r= link(page_ins_head);
+while(r!=page_ins_head)
+{best_ins_ptr(r)= last_ins_ptr(r);
+r= link(r);
+}
+}
+if((c==awful_bad)||(pi<=eject_penalty))
+#line 1784 "htex.ch"
+{hloc_set_next(best_page_break);
+if(p==best_page_break)best_page_break= null;
+hpack_page();
+hfill_page_template();
+return true;
+}
+#line 19572 "btex.w"
+}
+
+/*:1031*/
+#line 19459 "btex.w"
+;
+if((type(p)<glue_node)||(type(p)> kern_node))goto contribute;
+update_heights:/*1030:*/
+#line 19523 "btex.w"
+
+if(type(p)==kern_node)q= p;
+else{q= glue_ptr(p);
+page_so_far[2+stretch_order(q)]= 
+page_so_far[2+stretch_order(q)]+stretch(q);
+page_shrink= page_shrink+shrink(q);
+#line 1763 "htex.ch"
+if((shrink_order(q)!=normal)&&(shrink(q)!=0))
+{
+DBG(DBGTEX,"Infinite glue shrinkage found on current page");
+r= new_spec(q);shrink_order(r)= normal;fast_delete_glue_ref(q);
+glue_ptr(p)= r;q= r;
+}
+#line 19541 "btex.w"
+}
+page_total= page_total+page_depth+width(q);page_depth= 0
+
+/*:1030*/
+#line 19462 "btex.w"
+;
+contribute:/*1029:*/
+#line 19516 "btex.w"
+
+if(page_depth> page_max_depth)
+{page_total= 
+page_total+page_depth-page_max_depth;
+page_depth= page_max_depth;
+}
+
+/*:1029*/
+#line 19463 "btex.w"
+;
+/*1024:*/
+#line 19468 "btex.w"
+
+link(page_tail)= p;page_tail= p;
+link(contrib_head)= link(p);link(p)= null;goto done
+
+/*:1024*/
+#line 19464 "btex.w"
+;
+done1:/*1025:*/
+#line 19472 "btex.w"
+
+link(contrib_head)= link(p);link(p)= null;flush_node_list(p)
+
+/*:1025*/
+#line 19465 "btex.w"
+;
+done:
+
+/*:1023*/
+#line 19424 "btex.w"
+;
+}while(!(link(contrib_head)==null));
+/*1021:*/
+#line 19431 "btex.w"
+
+if(nest_ptr==0)tail= contrib_head;
+else contrib_tail= contrib_head
+
+/*:1021*/
+#line 19426 "btex.w"
+;
+#line 1726 "htex.ch"
+return false;
+}
+#line 19428 "btex.w"
+
+/*:1020*//*1034:*/
+#line 1796 "htex.ch"
+
+void happend_insertion(pointer p)
+{uint8_t n;
+scaled delta,h,w;
+pointer q,r;
+if(page_contents==empty)freeze_page_specs(inserts_only);
+#line 19598 "btex.w"
+n= subtype(p);r= page_ins_head;
+while(n>=subtype(link(r)))r= link(r);
+n= qo(n);
+if(subtype(r)!=qi(n))
+/*1035:*/
+#line 19624 "btex.w"
+
+{q= get_node(page_ins_node_size);link(q)= link(r);link(r)= q;r= q;
+subtype(r)= qi(n);type(r)= inserting;ensure_vbox(n);
+if(box(n)==null)height(r)= 0;
+else height(r)= height(box(n))+depth(box(n));
+best_ins_ptr(r)= null;
+q= skip(n);
+if(count(n)==1000)h= height(r);
+else h= x_over_n(height(r),1000)*count(n);
+page_goal= page_goal-h-width(q);
+page_so_far[2+stretch_order(q)]= page_so_far[2+stretch_order(q)]+stretch(q);
+page_shrink= page_shrink+shrink(q);
+#line 1820 "htex.ch"
+if((shrink_order(q)!=normal)&&(shrink(q)!=0))
+DBG(DBGTEX,"Infinite glue shrinkage inserted from stream %d",n);
+#line 19645 "btex.w"
+}
+
+/*:1035*/
+#line 19603 "btex.w"
+;
+if(type(r)==split_up)insert_penalties= insert_penalties+float_cost(p);
+else{last_ins_ptr(r)= p;
+delta= page_goal-page_total-page_depth+page_shrink;
+
+if(count(n)==1000)h= height(p);
+else h= x_over_n(height(p),1000)*count(n);
+if(((h<=0)||(h<=delta))&&(height(p)+height(r)<=dimen(n)))
+{page_goal= page_goal-h;height(r)= height(r)+height(p);
+}
+else/*1036:*/
+#line 19657 "btex.w"
+
+{if(count(n)<=0)w= max_dimen;
+else{w= page_goal-page_total-page_depth;
+if(count(n)!=1000)w= x_over_n(w,count(n))*1000;
+}
+if(w> dimen(n)-height(r))w= dimen(n)-height(r);
+q= vert_break(ins_ptr(p),w,depth(p));
+height(r)= height(r)+best_height_plus_depth;
+#line 19668 "btex.w"
+
+if(count(n)!=1000)
+best_height_plus_depth= x_over_n(best_height_plus_depth,1000)*count(n);
+page_goal= page_goal-best_height_plus_depth;
+type(r)= split_up;broken_ptr(r)= q;broken_ins(r)= p;
+if(q==null)insert_penalties= insert_penalties+eject_penalty;
+else if(type(q)==penalty_node)insert_penalties= insert_penalties+penalty(q);
+}
+
+/*:1036*/
+#line 19613 "btex.w"
+;
+}
+#line 19616 "btex.w"
+}
+
+/*:1034*//*1041:*/
+#line 1854 "htex.ch"
+
+void hpack_page(void)
+{
+pointer p,q,r,s;
+pointer prev_p;
+uint8_t n;
+bool wait;
+pointer save_split_top_skip;
+#if 0
+print_str("\npage_head:\n");
+show_box(link(page_head));
+print_str("\nstream 0:\n");
+show_box(streams[0].p);
+print_str("\nstream 1:\n");
+show_box(streams[1].p);
+#endif
+if(box(0)!=null)
+{flush_node_list(box(0));box(0)= null;}
+insert_penalties= 0;
+save_split_top_skip= split_top_skip;
+/*1045:*/
+#line 19821 "btex.w"
+
+{r= link(page_ins_head);
+while(r!=page_ins_head)
+{if(best_ins_ptr(r)!=null)
+{n= qo(subtype(r));ensure_vbox(n);
+if(box(n)==null)box(n)= new_null_box();
+p= box(n)+list_offset;
+while(link(p)!=null)p= link(p);
+last_ins_ptr(r)= p;
+}
+r= link(r);
+}
+}
+
+/*:1045*/
+#line 1874 "htex.ch"
+;
+q= hold_head;link(q)= null;prev_p= page_head;p= link(prev_p);
+while(p!=best_page_break)
+{if(type(p)==ins_node)
+{/*1047:*/
+#line 19847 "btex.w"
+
+{r= link(page_ins_head);
+while(subtype(r)!=subtype(p))r= link(r);
+if(best_ins_ptr(r)==null)wait= true;
+else{wait= false;s= last_ins_ptr(r);link(s)= ins_ptr(p);
+if(best_ins_ptr(r)==p)
+/*1048:*/
+#line 19863 "btex.w"
+
+{if(type(r)==split_up)
+if((broken_ins(r)==p)&&(broken_ptr(r)!=null))
+{while(link(s)!=broken_ptr(r))s= link(s);
+link(s)= null;
+split_top_skip= split_top_ptr(p);
+ins_ptr(p)= prune_page_top(broken_ptr(r));
+if(ins_ptr(p)!=null)
+{temp_ptr= vpack(ins_ptr(p),natural);
+height(p)= height(temp_ptr)+depth(temp_ptr);
+free_node(temp_ptr,box_node_size);wait= true;
+}
+}
+#line 1912 "htex.ch"
+while(link(s)!=null)s= link(s);
+best_ins_ptr(r)= null;
+#line 19877 "btex.w"
+n= qo(subtype(r));
+temp_ptr= list_ptr(box(n));
+free_node(box(n),box_node_size);
+#line 1919 "htex.ch"
+streams[n].p= temp_ptr;
+streams[n].t= s;
+#line 19881 "btex.w"
+}
+
+/*:1048*/
+#line 19854 "btex.w"
+
+else{while(link(s)!=null)s= link(s);
+last_ins_ptr(r)= s;
+}
+}
+/*1049:*/
+#line 19883 "btex.w"
+
+link(prev_p)= link(p);link(p)= null;
+if(wait)
+{link(q)= p;q= p;incr(insert_penalties);
+}
+else{delete_glue_ref(split_top_ptr(p));
+free_node(p,ins_node_size);
+}
+p= prev_p
+
+/*:1049*/
+#line 19860 "btex.w"
+;
+}
+
+/*:1047*/
+#line 1879 "htex.ch"
+;
+}
+prev_p= p;p= link(prev_p);
+}
+split_top_skip= save_split_top_skip;
+/*1044:*/
+#line 19796 "btex.w"
+
+if(p!=null)
+{if(link(contrib_head)==null)
+if(nest_ptr==0)tail= page_tail;
+else contrib_tail= page_tail;
+link(page_tail)= link(contrib_head);
+link(contrib_head)= p;
+link(prev_p)= null;
+}
+#line 1901 "htex.ch"
+streams[0].p= link(page_head);link(page_head)= null;page_tail= page_head;
+streams[0].t= prev_p;
+if(q!=hold_head)
+{link(q)= link(contrib_head);
+link(contrib_head)= link(hold_head);
+}
+#line 19814 "btex.w"
+
+/*:1044*/
+#line 1885 "htex.ch"
+;
+/*1046:*/
+#line 19835 "btex.w"
+
+r= link(page_ins_head);
+while(r!=page_ins_head)
+{q= link(r);free_node(r,page_ins_node_size);r= q;
+}
+link(page_ins_head)= page_ins_head
+
+/*:1046*/
+#line 1886 "htex.ch"
+;
+}
+#line 19766 "btex.w"
+
+/*:1041*//*1173:*/
+#line 1936 "htex.ch"
+
+void hdisplay(pointer p,pointer a,bool l)
+{
+scaled x;
+uint32_t offset= node_pos-node_pos1;
+{scaled w;
+scaled l;
+scaled s;
+pointer p;
+pointer q;
+internal_font_number f;
+int n;
+scaled v;
+scaled d;
+
+if(head==tail)
+{pop_nest();w= -max_dimen;x= cur_list.hs_field;offset= 0;
+}
+else{pointer par_ptr= link(head);
+pop_nest();
+store_map(par_ptr,node_pos,0);
+line_break(display_widow_penalty,par_ptr);
+x= cur_list.hs_field;
+#line 21742 "btex.w"
+/*1174:*/
+#line 21757 "btex.w"
+
+#line 1976 "htex.ch"
+v= shift_amount(just_box)+2*dimen_def[quad_no];w= -max_dimen;
+#line 21759 "btex.w"
+p= list_ptr(just_box);
+while(p!=null)
+{/*1175:*/
+#line 21774 "btex.w"
+
+reswitch:if(is_char_node(p))
+{f= font(p);d= char_width(f,char_info(f,character(p)));
+goto found;
+}
+switch(type(p)){
+case hlist_node:case vlist_node:case rule_node:{d= width(p);goto found;
+}
+case ligature_node:/*665:*/
+#line 12971 "btex.w"
+
+{mem[lig_trick]= mem[lig_char(p)];link(lig_trick)= link(p);
+p= lig_trick;goto reswitch;
+}
+
+/*:665*/
+#line 21782 "btex.w"
+
+case kern_node:case math_node:d= width(p);break;
+case glue_node:/*1176:*/
+#line 21796 "btex.w"
+
+{q= glue_ptr(p);d= width(q);
+if(glue_sign(just_box)==stretching)
+{if((glue_order(just_box)==stretch_order(q))&&
+(stretch(q)!=0))
+v= max_dimen;
+}
+else if(glue_sign(just_box)==shrinking)
+{if((glue_order(just_box)==shrink_order(q))&&
+(shrink(q)!=0))
+v= max_dimen;
+}
+if(subtype(p)>=a_leaders)goto found;
+}
+
+/*:1176*/
+#line 21785 "btex.w"
+break;
+case whatsit_node:/*1390:*/
+#line 24778 "btex.w"
+d= 0
+
+#line 2609 "htex.ch"
+/*:1390*/
+#line 21786 "btex.w"
+;break;
+default:d= 0;
+}
+
+/*:1175*/
+#line 21762 "btex.w"
+;
+if(v<max_dimen)v= v+d;
+goto not_found;
+found:if(v<max_dimen)
+{v= v+d;w= v;
+}
+else{w= max_dimen;goto done;
+}
+not_found:p= link(p);
+}
+done:
+
+/*:1174*/
+#line 21744 "btex.w"
+;
+}
+
+/*1177:*/
+#line 21814 "btex.w"
+
+if(par_shape_ptr==null)
+if((hang_indent!=0)&&
+(((hang_after>=0)&&(prev_graf+2> hang_after))||
+(prev_graf+1<-hang_after)))
+#line 1982 "htex.ch"
+{l= x-abs(hang_indent);
+#line 21820 "btex.w"
+if(hang_indent> 0)s= hang_indent;else s= 0;
+}
+#line 1988 "htex.ch"
+else{l= x;s= 0;
+#line 21823 "btex.w"
+}
+else{n= info(par_shape_ptr);
+if(prev_graf+2>=n)p= par_shape_ptr+2*n;
+else p= par_shape_ptr+2*(prev_graf+2);
+s= mem[p-1].sc;l= mem[p].sc;
+}
+
+/*:1177*/
+#line 21747 "btex.w"
+;
+#line 1970 "htex.ch"
+pre_display_size= w;display_width= l;display_indent= s;
+#line 21755 "btex.w"
+}
+
+/*:1173*//*1228:*/
+#line 2000 "htex.ch"
+
+{/*1226:*/
+#line 22463 "btex.w"
+
+pointer b;
+scaled w;
+scaled z;
+scaled e;
+scaled q;
+scaled d;
+scaled s;
+small_number g1,g2;
+pointer r;
+pointer t;
+
+/*:1226*/
+#line 2001 "htex.ch"
+
+adjust_tail= adjust_head;b= hpack(p,natural);p= list_ptr(b);
+t= adjust_tail;adjust_tail= null;
+w= width(b);z= display_width;s= display_indent;
+#line 2010 "htex.ch"
+if(a==null)
+#line 22486 "btex.w"
+{e= 0;q= 0;
+}
+#line 2016 "htex.ch"
+else{e= width(a);q= e+math_quad;
+#line 22489 "btex.w"
+}
+if(w+q> z)
+/*1230:*/
+#line 22515 "btex.w"
+
+{if((e!=0)&&((w-total_shrink[normal]+q<=z)||
+(total_shrink[fil]!=0)||(total_shrink[fill]!=0)||
+(total_shrink[filll]!=0)))
+{free_node(b,box_node_size);
+b= hpack(p,z-q,exactly);
+}
+else{e= 0;
+if(w> z)
+{free_node(b,box_node_size);
+b= hpack(p,z,exactly);
+}
+}
+w= width(b);
+}
+
+/*:1230*/
+#line 22492 "btex.w"
+;
+/*1231:*/
+#line 22539 "btex.w"
+
+d= half(z-w);
+if((e> 0)&&(d<2*e))
+{d= half(z-w-e);
+if(p!=null)if(!is_char_node(p))if(type(p)==glue_node)d= 0;
+}
+
+/*:1231*/
+#line 22494 "btex.w"
+;
+/*1232:*/
+#line 22552 "btex.w"
+
+#line 2043 "htex.ch"
+tail_append(new_penalty(pre_display_penalty));
+store_map(tail,node_pos,offset);
+if((d+s<=pre_display_size)||l)
+{g1= above_display_skip_no;g2= below_display_skip_no;
+}
+else{g1= above_display_short_skip_no;
+g2= below_display_short_skip_no;
+}
+if(l&&(e==0))
+{shift_amount(a)= s;append_to_vlist(a,offset);
+tail_append(new_penalty(inf_penalty));store_map(tail,node_pos,offset);
+}
+else{tail_append(new_glue(pointer_def[glue_kind][g1]));store_map(tail,node_pos,offset);}
+#line 22565 "btex.w"
+
+/*:1232*/
+#line 22495 "btex.w"
+;
+/*1233:*/
+#line 22566 "btex.w"
+
+if(e!=0)
+{r= new_kern(z-w-e-d);
+if(l)
+{link(a)= r;link(r)= b;b= a;d= 0;
+}
+else{link(b)= r;link(r)= a;
+}
+b= hpack(b,natural);
+}
+#line 2061 "htex.ch"
+shift_amount(b)= s+d;append_to_vlist(b,offset)
+#line 22577 "btex.w"
+
+/*:1233*/
+#line 22496 "btex.w"
+;
+/*1234:*/
+#line 22578 "btex.w"
+
+if((a!=null)&&(e==0)&&!l)
+{tail_append(new_penalty(inf_penalty));
+shift_amount(a)= s+z-width(a);
+#line 2067 "htex.ch"
+append_to_vlist(a,offset);
+#line 22583 "btex.w"
+g2= 0;
+}
+if(t!=adjust_head)
+{link(tail)= link(adjust_head);tail= t;
+}
+#line 2074 "htex.ch"
+tail_append(new_penalty(post_display_penalty));
+offset= (hpos-hstart)+1-node_pos;
+store_map(tail,node_pos,offset);
+if(g2> 0){tail_append(new_glue(pointer_def[glue_kind][g2]));store_map(tail,node_pos,offset);}
+#line 22590 "btex.w"
+
+/*:1234*/
+#line 22497 "btex.w"
+;
+#line 2022 "htex.ch"
+prev_graf= prev_graf+3;
+cur_list.bs_pos= hpos+node_pos;
+push_nest();mode= hmode;
+}
+}
+#line 22499 "btex.w"
+
+/*:1228*/

Added: trunk/Build/source/texk/web2c/hitexdir/hintview/src/htex.h
===================================================================
--- trunk/Build/source/texk/web2c/hitexdir/hintview/src/htex.h	                        (rev 0)
+++ trunk/Build/source/texk/web2c/hitexdir/hintview/src/htex.h	2022-01-19 13:28:43 UTC (rev 61658)
@@ -0,0 +1,1958 @@
+/*1410:*/
+#line 2624 "htex.ch"
+
+#define banner "This is TeX, Version 3.141592653 (HINT)" \
+
+#define odd(X) ((X) &1) 
+#define chr(X) ((unsigned char) (X) ) 
+#define ord(X) ((unsigned int) (X) ) 
+#define abs(X) ((X) > -(X) ?(X) :-(X) ) 
+#define round(X) ((int) ((X) >=0.0?floor((X) +0.5) :ceil((X) -0.5) ) )  \
+
+#define mem_bot 0 \
+
+#define mem_top mem_max \
+ \
+
+#define font_base 0 \
+
+#define hash_size 15000 \
+
+#define hash_prime 12721
+#define hyph_size 607 \
+ \
+
+#define incr(A) A= A+1
+#define decr(A) A= A-1
+#define negate(A) A= -A
+#define loop while(true) 
+#define do_nothing 
+#define empty 0 \
+
+#define text_char unsigned char
+#define first_text_char 0
+#define last_text_char 255 \
+
+#define null_code 00
+#define carriage_return 015
+#define invalid_code 0177 \
+
+#define reset_OK(A) erstat(A) ==0
+#define rewrite_OK(A) erstat(A) ==0 \
+
+#define t_open_in term_in.f= stdin
+#define t_open_out term_out.f= stdout \
+
+#define update_terminal fflush(term_out.f) 
+#define clear_terminal fflush(term_in.f) 
+#define wake_up_terminal do_nothing \
+
+#define loc cur_input.loc_field \
+
+#define si(A) A
+#define so(A) A \
+
+#define length(A) (str_start[A+1]-str_start[A])  \
+ \
+
+#define cur_length (pool_ptr-str_start[str_ptr])  \
+
+#define append_char(A)  \
+{str_pool[pool_ptr]= si(A) ;incr(pool_ptr) ; \
+}
+#define flush_char decr(pool_ptr) 
+#define str_room(A)  \
+{if(pool_ptr+A> pool_size)  \
+overflow("pool size",pool_size-init_pool_ptr) ; \
+ \
+} \
+
+#define flush_string {decr(str_ptr) ;pool_ptr= str_start[str_ptr]; \
+} \
+
+#define app_lc_hex(A) l= A; \
+if(l<10) append_char(l+'0') else append_char(l-10+'a')  \
+
+#define no_print 16
+#define term_only 17
+#define log_only 18
+#define term_and_log 19
+#define pseudo 20
+#define new_string 21
+#define max_selector 21 \
+
+#define print_lc_hex(A)  \
+if((A) <10) print_char((A) +'0') ;else print_char((A) -10+'a') 
+#define print_ASCII(k)  \
+if((k<' ') ||(k> '~') )  \
+{print("^^") ; \
+if(k<0100) print_char(k+0100) ; \
+else if(k<0200) print_char(k-0100) ; \
+else{print_lc_hex(k/16) ;print_lc_hex(k%16) ;} \
+} \
+else print_char(k)  \
+
+#define prompt_input(A) {wake_up_terminal;print(A) ;term_input() ; \
+} \
+
+#define batch_mode 0
+#define nonstop_mode 1
+#define scroll_mode 2
+#define error_stop_mode 3 \
+
+#define spotless 0
+#define warning_issued 1
+#define error_message_issued 2
+#define fatal_error_stop 3 \
+
+#define hlp1(A) help_line[0]= A;}
+#define hlp2(A,B) help_line[1]= A;help_line[0]= B;}
+#define hlp3(A,B,C) help_line[2]= A;help_line[1]= B;help_line[0]= C;}
+#define hlp4(A,B,C,D) help_line[3]= A;help_line[2]= B;help_line[1]= C;help_line[0]= D;}
+#define hlp5(A,B,C,D,E) help_line[4]= A;help_line[3]= B;help_line[2]= C;help_line[1]= D;help_line[0]= E;}
+#define hlp6(A,B,C,D,E,F) help_line[5]= A;help_line[4]= B;help_line[3]= C;help_line[2]= D;help_line[1]= E;help_line[0]= F;}
+#define help0 help_ptr= 0
+#define help1(A) {help_ptr= 1;hlp1(A) 
+#define help2(A,B) {help_ptr= 2;hlp2(A,B) 
+#define help3(A,B,C) {help_ptr= 3;hlp3(A,B,C) 
+#define help4(A,B,C,D) {help_ptr= 4;hlp4(A,B,C,D) 
+#define help5(A,B,C,D,E) {help_ptr= 5;hlp5(A,B,C,D,E) 
+#define help6(A,B,C,D,E,F) {help_ptr= 6;hlp6(A,B,C,D,E,F)  \
+
+#define succumb {if(interaction==error_stop_mode)  \
+interaction= scroll_mode; \
+if(log_opened) error() ; \
+if(interaction> batch_mode) debug_help() ; \
+history= fatal_error_stop;jump_out() ; \
+} \
+
+#define check_interrupt {if(interrupt!=0) pause_for_instructions() ; \
+} \
+
+#define unity 0200000
+#define two 0400000 \
+
+#define nx_plus_y(A,B,C) mult_and_add(A,B,C,07777777777) 
+#define mult_integers(A,B) mult_and_add(A,B,0,017777777777)  \
+
+#define inf_bad 10000 \
+
+#define set_glue_ratio_zero(A) A= 0.0
+#define set_glue_ratio_one(A) A= 1.0
+#define float(A) ((double) (A) ) 
+#define unfloat(A) ((glue_ratio) (A) ) 
+#define float_constant(A) ((double) (A) )  \
+
+#define min_quarterword 0
+#define max_quarterword 255
+#define min_halfword 0
+#define max_halfword 65535 \
+
+#define qi(A) A+min_quarterword \
+
+#define qo(A) A-min_quarterword \
+
+#define hi(A) A+min_halfword \
+
+#define ho(A) A-min_halfword \
+ \
+
+#define sc i \
+
+#define pointer halfword
+#define null min_halfword \
+
+#define link(A) mem[A].hh.rh
+#define info(A) mem[A].hh.lh \
+
+#define mem_end mem_top
+#define free_avail(A)  \
+{link(A) = avail;avail= A; \
+decr_dyn_used; \
+} \
+
+#define fast_get_avail(A)  \
+{A= avail; \
+if(A==null) A= get_avail() ; \
+else{avail= link(A) ;link(A) = null; \
+incr_dyn_used; \
+} \
+} \
+
+#define empty_flag max_halfword
+#define is_empty(A) (link(A) ==empty_flag) 
+#define node_size(A) info(A) 
+#define llink(A) info(A+1) 
+#define rlink(A) link(A+1)  \
+
+#define type(A) mem[A].hh.b0
+#define subtype(A) mem[A].hh.b1 \
+
+#define is_char_node(A) (A>=hi_mem_min)  \
+
+#define font(A) type(A) 
+#define character(A) subtype(A)  \
+
+#define hlist_node 0
+#define box_node_size 9
+#define width_offset 1
+#define depth_offset 2
+#define height_offset 3
+#define width(A) mem[A+width_offset].sc
+#define depth(A) mem[A+depth_offset].sc
+#define height(A) mem[A+height_offset].sc
+#define shift_amount(A) mem[A+4].sc
+#define list_offset 5
+#define list_ptr(A) link(A+list_offset) 
+#define glue_order(A) subtype(A+list_offset) 
+#define glue_sign(A) type(A+list_offset) 
+#define normal 0
+#define stretching 1
+#define shrinking 2
+#define glue_offset 6
+#define glue_set(A) mem[A+glue_offset].gr \
+ \
+
+#define vlist_node 1 \
+
+#define rule_node 2
+#define rule_node_size 4
+#define null_flag -010000000000
+#define is_running(A) (A==null_flag)  \
+
+#define ins_node 3
+#define ins_node_size 5
+#define float_cost(A) mem[A+1].i
+#define ins_ptr(A) info(A+4) 
+#define split_top_ptr(A) link(A+4)  \
+
+#define mark_node 4
+#define small_node_size 2
+#define mark_ptr(A) mem[A+1].i \
+
+#define adjust_node 5
+#define adjust_ptr(A) mark_ptr(A)  \
+
+#define ligature_node 6
+#define lig_char(A) A+1
+#define lig_ptr(A) link(lig_char(A) )  \
+
+#define disc_node 7
+#define replace_count(A) (subtype(A) &0x7F) 
+#define set_replace_count(A,B) (subtype(A) = (B) &0x7F) 
+#define set_auto_disc(A) (subtype(A) |= 0x80) 
+#define is_auto_disc(A) (subtype(A) &0x80) 
+#define pre_break(A) llink(A) 
+#define post_break(A) rlink(A)  \
+
+#define whatsit_node 8 \
+
+#define math_node 9
+#define before 0
+#define after 1 \
+
+#define precedes_break(A) (type(A) <math_node) 
+#define non_discardable(A) (type(A) <math_node)  \
+
+#define glue_node 10
+#define cond_math_glue 98
+#define mu_glue 99
+#define a_leaders 100
+#define c_leaders 101
+#define x_leaders 102
+#define glue_ptr(A) llink(A) 
+#define leader_ptr(A) rlink(A)  \
+
+#define glue_spec_size 4
+#define glue_ref_count(A) link(A) 
+#define stretch(A) mem[A+2].sc
+#define shrink(A) mem[A+3].sc
+#define stretch_order(A) type(A) 
+#define shrink_order(A) subtype(A) 
+#define fil 1
+#define fill 2
+#define filll 3 \
+
+#define kern_node 11
+#define explicit 1
+#define acc_kern 2 \
+
+#define penalty_node 12
+#define inf_penalty inf_bad
+#define eject_penalty (-inf_penalty) 
+#define penalty(A) mem[A+1].i \
+
+#define unset_node 13
+#define glue_stretch(A) mem[A+glue_offset].sc
+#define glue_shrink(A) shift_amount(A) 
+#define span_count(A) subtype(A)  \
+
+#define zero_glue mem_bot
+#define lo_mem_stat_max zero_glue+glue_spec_size-1 \
+
+#define page_ins_head mem_top
+#define contrib_head mem_top-1
+#define page_head mem_top-2
+#define temp_head mem_top-3
+#define hold_head mem_top-4
+#define adjust_head mem_top-5
+#define active mem_top-7
+#define align_head mem_top-8
+#define end_span mem_top-9
+#define omit_template mem_top-10
+#define null_list mem_top-11
+#define lig_trick mem_top-12
+#define garbage mem_top-12
+#define backup_head mem_top-13
+#define hi_mem_stat_min mem_top-13 \
+
+#define hi_mem_stat_usage 14 \
+
+#define node_list_display(A)  \
+{depth_level++;show_node_list(A) ;depth_level--; \
+}
+#define print_current_indent  \
+{int i; \
+for(i= 0;i<depth_level;i++)  \
+print_char('.') ;} \
+
+#define token_ref_count(A) info(A)  \
+
+#define fast_delete_glue_ref(A)  \
+{if(glue_ref_count(A) ==null) free_node(A,glue_spec_size) ; \
+else decr(glue_ref_count(A) ) ; \
+} \
+
+#define add_token_ref(A) incr(token_ref_count(A) ) 
+#define add_glue_ref(A) incr(glue_ref_count(A) ) 
+#define add_xdimen_ref(A) incr(xdimen_ref_count(A) )  \
+
+#define escape 0 \
+
+#define relax 0
+#define left_brace 1
+#define right_brace 2
+#define math_shift 3
+#define tab_mark 4
+#define car_ret 5
+#define out_param 5
+#define mac_param 6
+#define sup_mark 7
+#define sub_mark 8
+#define ignore 9
+#define endv 9
+#define spacer 10
+#define letter 11
+#define other_char 12
+#define active_char 13
+#define par_end 13
+#define match 13
+#define comment 14
+#define end_match 14
+#define stop 14
+#define invalid_char 15
+#define delim_num 15
+#define max_char_code 15 \
+
+#define char_num 16
+#define math_char_num 17
+#define mark 18
+#define xray 19
+#define make_box 20
+#define hmove 21
+#define vmove 22
+#define un_hbox 23
+#define un_vbox 24
+#define remove_item 25 \
+
+#define hskip 26
+#define vskip 27
+#define mskip 28
+#define kern 29
+#define mkern 30
+#define leader_ship 31
+#define halign 32
+#define valign 33
+#define no_align 34
+#define vrule 35
+#define hrule 36
+#define insert 37
+#define vadjust 38
+#define ignore_spaces 39
+#define after_assignment 40
+#define after_group 41
+#define break_penalty 42
+#define start_par 43
+#define ital_corr 44
+#define accent 45
+#define math_accent 46
+#define discretionary 47
+#define eq_no 48
+#define left_right 49
+#define math_comp 50
+#define limit_switch 51
+#define above 52
+#define math_style 53
+#define math_choice 54
+#define non_script 55
+#define vcenter 56
+#define case_shift 57
+#define message 58
+#define extension 59
+#define in_stream 60
+#define begin_group 61
+#define end_group 62
+#define omit 63
+#define ex_space 64
+#define no_boundary 65
+#define radical 66
+#define end_cs_name 67
+#define min_internal 68
+#define char_given 68
+#define math_given 69
+#define last_item 70 \
+
+#define max_non_prefixed_command 70 \
+
+#define toks_register 71
+#define assign_toks 72
+#define assign_int 73
+#define assign_dimen 74
+#define assign_glue 75
+#define assign_mu_glue 76
+#define assign_font_dimen 77
+#define assign_font_int 78 \
+
+#define set_aux 79
+#define set_prev_graf 80
+#define set_page_dimen 81
+#define set_page_int 82 \
+
+#define set_box_dimen 83
+#define set_shape 84
+#define def_code 85
+#define def_family 86
+#define set_font 87
+#define def_font 88
+#define internal_register 89
+#define max_internal 89
+#define advance 90
+#define multiply 91
+#define divide 92
+#define prefix 93
+#define let 94
+#define shorthand_def 95
+#define read_to_cs 96
+#define def 97
+#define set_box 98
+#define hyph_data 99
+#define set_interaction 100
+#define max_command 100 \
+
+#define undefined_cs (max_command+1) 
+#define expand_after (max_command+2) 
+#define no_expand (max_command+3) 
+#define input (max_command+4) 
+#define if_test (max_command+5) 
+#define fi_or_else (max_command+6) 
+#define cs_name (max_command+7) 
+#define convert (max_command+8) 
+#define the (max_command+9) 
+#define top_bot_mark (max_command+10) 
+#define call (max_command+11) 
+#define long_call (max_command+12) 
+#define outer_call (max_command+13) 
+#define long_outer_call (max_command+14) 
+#define end_template (max_command+15) 
+#define dont_expand (max_command+16) 
+#define glue_ref (max_command+17) 
+#define shape_ref (max_command+18) 
+#define box_ref (max_command+19) 
+#define data (max_command+20)  \
+
+#define vmode 1
+#define hmode (vmode+max_command+1) 
+#define mmode (hmode+max_command+1)  \
+
+#define ignore_depth -65536000 \
+
+#define mode cur_list.mode_field
+#define head cur_list.head_field
+#define tail cur_list.tail_field
+#define prev_graf cur_list.pg_field
+#define aux cur_list.aux_field
+#define prev_depth aux.sc
+#define space_factor aux.hh.lh
+#define clang aux.hh.rh
+#define incompleat_noad aux.i
+#define cur_bs cur_list.bs_field
+#define cur_ls cur_list.ls_field
+#define cur_lsl cur_list.lsl_field
+#define needs_bs (cur_list.bs_pos!=NULL) 
+#define prev_height cur_list.ht_field
+#define node_pos cur_list.np_field
+#define node_pos1 (nest_ptr==0?0:nest[nest_ptr-1].np_field)  \
+
+#define tail_append(A) {link(tail) = A;tail= link(tail) ; \
+} \
+
+#define eq_level_field(A) A.hh.b1
+#define eq_type_field(A) A.hh.b0
+#define equiv_field(A) A.hh.rh
+#define eq_level(A) eq_level_field(eqtb[A]) 
+#define eq_type(A) eq_type_field(eqtb[A]) 
+#define equiv(A) equiv_field(eqtb[A]) 
+#define level_zero min_quarterword
+#define level_one (level_zero+1)  \
+
+#define active_base 1
+#define single_base (active_base+256) 
+#define null_cs (single_base+256) 
+#define hash_base (null_cs+1) 
+#define frozen_control_sequence (hash_base+hash_size) 
+#define frozen_protection frozen_control_sequence
+#define frozen_cr (frozen_control_sequence+1) 
+#define frozen_end_group (frozen_control_sequence+2) 
+#define frozen_right (frozen_control_sequence+3) 
+#define frozen_fi (frozen_control_sequence+4) 
+#define frozen_end_template (frozen_control_sequence+5) 
+#define frozen_endv (frozen_control_sequence+6) 
+#define frozen_relax (frozen_control_sequence+7) 
+#define end_write (frozen_control_sequence+8) 
+#define frozen_dont_expand (frozen_control_sequence+9)  \
+
+#define frozen_null_font (frozen_control_sequence+10)  \
+
+#define font_id_base (frozen_null_font-font_base)  \
+
+#define undefined_control_sequence (frozen_null_font+257) 
+#define glue_base (undefined_control_sequence+1)  \
+
+#define line_skip_code 0
+#define baseline_skip_code 1
+#define par_skip_code 2
+#define above_display_skip_code 3
+#define below_display_skip_code 4
+#define above_display_short_skip_code 5 \
+
+#define below_display_short_skip_code 6 \
+
+#define left_skip_code 7
+#define right_skip_code 8
+#define top_skip_code 9
+#define split_top_skip_code 10
+#define tab_skip_code 11
+#define space_skip_code 12
+#define xspace_skip_code 13
+#define par_fill_skip_code 14
+#define thin_mu_skip_code 15
+#define med_mu_skip_code 16
+#define thick_mu_skip_code 17
+#define glue_pars 18
+#define skip_base (glue_base+glue_pars) 
+#define mu_skip_base (skip_base+256) 
+#define local_base (mu_skip_base+256)  \
+
+#define mu_skip(A) equiv(mu_skip_base+A) 
+#define glue_par(A) equiv(glue_base+A) 
+#define line_skip pointer_def[glue_kind][line_skip_no]
+#define baseline_skip pointer_def[glue_kind][baseline_skip_no]
+#define above_display_skip pointer_def[glue_kind][above_display_skip_no]
+#define below_display_skip pointer_def[glue_kind][below_display_skip_no]
+#define above_display_short_skip pointer_def[glue_kind][above_display_short_skip_no]
+#define below_display_short_skip pointer_def[glue_kind][below_display_short_skip_no]
+#define left_skip pointer_def[glue_kind][left_skip_no]
+#define right_skip pointer_def[glue_kind][right_skip_no]
+#define top_skip pointer_def[glue_kind][top_skip_no]
+#define split_top_skip pointer_def[glue_kind][split_top_skip_no]
+#define tab_skip pointer_def[glue_kind][tab_skip_no]
+#define par_fill_skip pointer_def[glue_kind][par_fill_skip_no]
+#define thin_mu_skip glue_par(thin_mu_skip_code) 
+#define med_mu_skip glue_par(med_mu_skip_code) 
+#define thick_mu_skip glue_par(thick_mu_skip_code)  \
+
+#define par_shape_loc local_base
+#define output_routine_loc (local_base+1) 
+#define every_par_loc (local_base+2) 
+#define every_math_loc (local_base+3) 
+#define every_display_loc (local_base+4) 
+#define every_hbox_loc (local_base+5) 
+#define every_vbox_loc (local_base+6) 
+#define every_job_loc (local_base+7) 
+#define every_cr_loc (local_base+8) 
+#define err_help_loc (local_base+9) 
+#define toks_base (local_base+10) 
+#define box_base (toks_base+256) 
+#define cur_font_loc (box_base+256) 
+#define math_font_base (cur_font_loc+1) 
+#define cat_code_base (math_font_base+48)  \
+
+#define lc_code_base (cat_code_base+256) 
+#define uc_code_base (lc_code_base+256) 
+#define sf_code_base (uc_code_base+256) 
+#define math_code_base (sf_code_base+256) 
+#define int_base (math_code_base+256)  \
+
+#define par_shape_ptr null
+#define output_routine equiv(output_routine_loc) 
+#define every_par equiv(every_par_loc) 
+#define every_math equiv(every_math_loc) 
+#define every_display equiv(every_display_loc) 
+#define every_hbox equiv(every_hbox_loc) 
+#define every_vbox equiv(every_vbox_loc) 
+#define every_job equiv(every_job_loc) 
+#define every_cr equiv(every_cr_loc) 
+#define err_help equiv(err_help_loc) 
+#define toks(X) equiv(toks_base+X) 
+#define box(A) (*box_ptr(A) ) 
+#define cur_font equiv(cur_font_loc) 
+#define fam_fnt(A) equiv(math_font_base+A) 
+#define cat_code(A) equiv(cat_code_base+A) 
+#define lc_code(A) equiv(lc_code_base+A) 
+#define uc_code(A) equiv(uc_code_base+A) 
+#define sf_code(A) equiv(sf_code_base+A) 
+#define math_code(A) equiv(math_code_base+A)  \
+ \
+
+#define null_font font_base
+#define var_code 070000 \
+
+#define pretolerance_code 0
+#define tolerance_code 1
+#define line_penalty_code 2
+#define hyphen_penalty_code 3
+#define ex_hyphen_penalty_code 4
+#define club_penalty_code 5
+#define widow_penalty_code 6
+#define display_widow_penalty_code 7
+#define broken_penalty_code 8
+#define bin_op_penalty_code 9
+#define rel_penalty_code 10
+#define pre_display_penalty_code 11 \
+
+#define post_display_penalty_code 12 \
+
+#define inter_line_penalty_code 13
+#define double_hyphen_demerits_code 14
+#define final_hyphen_demerits_code 15
+#define adj_demerits_code 16
+#define mag_code 17
+#define delimiter_factor_code 18
+#define looseness_code 19
+#define time_code 20
+#define day_code 21
+#define month_code 22
+#define year_code 23
+#define show_box_breadth_code 24
+#define show_box_depth_code 25
+#define hbadness_code 26
+#define vbadness_code 27
+#define pausing_code 28
+#define tracing_online_code 29
+#define tracing_macros_code 30
+#define tracing_stats_code 31
+#define tracing_paragraphs_code 32
+#define tracing_pages_code 33
+#define tracing_output_code 34
+#define tracing_lost_chars_code 35
+#define tracing_commands_code 36
+#define tracing_restores_code 37
+#define uc_hyph_code 38
+#define output_penalty_code 39
+#define max_dead_cycles_code 40
+#define hang_after_code 41
+#define floating_penalty_code 42
+#define global_defs_code 43
+#define cur_fam_code 44
+#define escape_char_code 45
+#define default_hyphen_char_code 46
+#define default_skew_char_code 47
+#define end_line_char_code 48
+#define new_line_char_code 49
+#define language_code 50
+#define left_hyphen_min_code 51
+#define right_hyphen_min_code 52
+#define holding_inserts_code 53
+#define error_context_lines_code 54
+#define int_pars 55
+#define count_base (int_base+int_pars) 
+#define del_code_base (count_base+256) 
+#define dimen_base (del_code_base+256)  \
+
+#define del_code(A) eqtb[del_code_base+A].i
+#define int_par(A) eqtb[int_base+A].i
+#define pretolerance integer_def[pretolerance_no]
+#define tolerance integer_def[tolerance_no]
+#define line_penalty integer_def[line_penalty_no]
+#define hyphen_penalty integer_def[hyphen_penalty_no]
+#define ex_hyphen_penalty integer_def[ex_hyphen_penalty_no]
+#define club_penalty integer_def[club_penalty_no]
+#define widow_penalty integer_def[widow_penalty_no]
+#define display_widow_penalty integer_def[display_widow_penalty_no]
+#define broken_penalty integer_def[broken_penalty_no]
+#define pre_display_penalty integer_def[pre_display_penalty_no]
+#define post_display_penalty integer_def[post_display_penalty_no]
+#define inter_line_penalty integer_def[inter_line_penalty_no]
+#define double_hyphen_demerits integer_def[double_hyphen_demerits_no]
+#define final_hyphen_demerits integer_def[final_hyphen_demerits_no]
+#define adj_demerits integer_def[adj_demerits_no]
+#define looseness integer_def[looseness_no]
+#define time integer_def[time_no]
+#define day integer_def[day_no]
+#define month integer_def[month_no]
+#define year integer_def[year_no]
+#define show_box_breadth int_par(show_box_breadth_code) 
+#define show_box_depth int_par(show_box_depth_code) 
+#define hbadness int_par(hbadness_code) 
+#define vbadness int_par(vbadness_code) 
+#define pausing int_par(pausing_code) 
+#define tracing_online int_par(tracing_online_code) 
+#define tracing_macros int_par(tracing_macros_code) 
+#define tracing_stats int_par(tracing_stats_code) 
+#define tracing_paragraphs (debugflags&DBGTEX) 
+#define tracing_pages int_par(tracing_pages_code) 
+#define tracing_output int_par(tracing_output_code) 
+#define tracing_lost_chars int_par(tracing_lost_chars_code) 
+#define tracing_commands int_par(tracing_commands_code) 
+#define tracing_restores int_par(tracing_restores_code) 
+#define uc_hyph int_par(uc_hyph_code) 
+#define output_penalty int_par(output_penalty_code) 
+#define max_dead_cycles int_par(max_dead_cycles_code) 
+#define hang_after integer_def[hang_after_no]
+#define floating_penalty int_par(floating_penalty_code) 
+#define global_defs int_par(global_defs_code) 
+#define cur_fam int_par(cur_fam_code) 
+#define escape_char int_par(escape_char_code) 
+#define default_hyphen_char int_par(default_hyphen_char_code) 
+#define default_skew_char int_par(default_skew_char_code) 
+#define end_line_char int_par(end_line_char_code) 
+#define new_line_char int_par(new_line_char_code) 
+#define language int_par(language_code) 
+#define left_hyphen_min int_par(left_hyphen_min_code) 
+#define right_hyphen_min int_par(right_hyphen_min_code) 
+#define error_context_lines int_par(error_context_lines_code)  \
+
+#define par_indent_code 0
+#define math_surround_code 1
+#define line_skip_limit_code 2
+#define hsize_code 3
+#define vsize_code 4
+#define max_depth_code 5
+#define split_max_depth_code 6
+#define box_max_depth_code 7
+#define hfuzz_code 8
+#define vfuzz_code 9
+#define delimiter_shortfall_code 10
+#define null_delimiter_space_code 11
+#define script_space_code 12
+#define pre_display_size_code 13
+#define display_width_code 14
+#define display_indent_code 15
+#define overfull_rule_code 16
+#define hang_indent_code 17
+#define h_offset_code 18
+#define v_offset_code 19
+#define emergency_stretch_code 20
+#define dimen_pars 21
+#define scaled_base (dimen_base+dimen_pars)  \
+
+#define eqtb_size (scaled_base+255)  \
+
+#define dimen_par(A) eqtb[dimen_base+A].sc
+#define par_indent dimen_par(par_indent_code) 
+#define math_surround dimen_par(math_surround_code) 
+#define line_skip_limit dimen_def[line_skip_limit_no]
+#define hsize dimen_par(hsize_code) 
+#define vsize dimen_par(vsize_code) 
+#define max_depth dimen_def[max_depth_no]
+#define split_max_depth dimen_par(split_max_depth_code) 
+#define box_max_depth dimen_par(box_max_depth_code) 
+#define hfuzz dimen_par(hfuzz_code) 
+#define vfuzz dimen_par(vfuzz_code) 
+#define delimiter_shortfall dimen_par(delimiter_shortfall_code) 
+#define null_delimiter_space dimen_par(null_delimiter_space_code) 
+#define script_space dimen_par(script_space_code) 
+#define pre_display_size cur_list.ds_field
+#define display_width cur_list.dw_field
+#define display_indent cur_list.di_field
+#define overfull_rule dimen_par(overfull_rule_code) 
+#define hang_indent dimen_def[hang_indent_no]
+#define h_offset dimen_par(h_offset_code) 
+#define v_offset dimen_par(v_offset_code) 
+#define emergency_stretch dimen_def[emergency_stretch_no] \
+
+#define next(A) hash[A].lh
+#define text(A) hash[A].rh
+#define hash_is_full (hash_used==hash_base) 
+#define font_id_text(A) text(font_id_base+A)  \
+
+#define save_type(A) save_stack[A].hh.b0
+#define save_level(A) save_stack[A].hh.b1 \
+
+#define save_index(A) save_stack[A].hh.rh \
+
+#define restore_old_value 0
+#define restore_zero 1
+#define insert_token 2
+#define level_boundary 3 \
+
+#define bottom_level 0
+#define simple_group 1
+#define hbox_group 2
+#define adjusted_hbox_group 3
+#define vbox_group 4
+#define vtop_group 5
+#define align_group 6
+#define no_align_group 7
+#define output_group 8
+#define math_group 9
+#define disc_group 10
+#define insert_group 11
+#define vcenter_group 12
+#define math_choice_group 13
+#define semi_simple_group 14
+#define math_shift_group 15
+#define math_left_group 16
+#define max_group_code 16 \
+
+#define check_full_save_stack if(save_ptr> max_save_stack)  \
+{max_save_stack= save_ptr; \
+if(max_save_stack> save_size-6) overflow("save size",save_size) ; \
+ \
+} \
+
+#define saved(A) save_stack[save_ptr+A].i \
+
+#define cs_token_flag 07777 \
+
+#define left_brace_token 00400
+#define left_brace_limit 01000
+#define right_brace_token 01000
+#define right_brace_limit 01400
+#define math_shift_token 01400
+#define tab_token 02000
+#define out_param_token 02400
+#define space_token 05040
+#define letter_token 05400
+#define other_token 06000
+#define match_token 06400
+#define end_match_token 07000 \
+
+#define chr_cmd(A) {print(A) ;print_ASCII(chr_code) ; \
+} \
+
+#define state cur_input.state_field
+#define index cur_input.index_field
+#define start cur_input.start_field
+#define limit cur_input.limit_field
+#define name cur_input.name_field \
+
+#define mid_line 1
+#define skip_blanks (2+max_char_code) 
+#define new_line (3+max_char_code+max_char_code)  \
+
+#define terminal_input (name==0) 
+#define cur_file input_file[index] \
+
+#define skipping 1
+#define defining 2
+#define matching 3
+#define aligning 4
+#define absorbing 5 \
+
+#define token_list 0
+#define token_type index
+#define param_start limit
+#define parameter 0
+#define u_template 1
+#define v_template 2
+#define backed_up 3
+#define inserted 4
+#define macro 5
+#define output_text 6
+#define every_par_text 7
+#define every_math_text 8
+#define every_display_text 9
+#define every_hbox_text 10
+#define every_vbox_text 11
+#define every_job_text 12
+#define every_cr_text 13
+#define mark_text 14
+#define write_text 15 \
+
+#define begin_pseudoprint  \
+{l= tally;tally= 0;selector= pseudo; \
+trick_count= 1000000; \
+}
+#define set_trick_count  \
+{first_count= tally; \
+trick_count= tally+1+error_line-half_error_line; \
+if(trick_count<error_line) trick_count= error_line; \
+} \
+
+#define push_input  \
+{if(input_ptr> max_in_stack)  \
+{max_in_stack= input_ptr; \
+if(input_ptr==stack_size) overflow("input stack size",stack_size) ; \
+ \
+} \
+input_stack[input_ptr]= cur_input; \
+incr(input_ptr) ; \
+} \
+
+#define pop_input  \
+{decr(input_ptr) ;cur_input= input_stack[input_ptr]; \
+} \
+
+#define back_list(A) begin_token_list(A,backed_up) 
+#define ins_list(A) begin_token_list(A,inserted)  \
+
+#define any_state_plus(A) case mid_line+A:case skip_blanks+A:case new_line+A \
+
+#define add_delims_to(A) A+math_shift:A+tab_mark:A+mac_param: \
+A+sub_mark:A+letter:A+other_char \
+
+#define is_hex(A) (((A>='0') &&(A<='9') ) ||((A>='a') &&(A<='f') ) ) 
+#define hex_to_cur_chr  \
+if(c<='9') cur_chr= c-'0';else cur_chr= c-'a'+10; \
+if(cc<='9') cur_chr= 16*cur_chr+cc-'0'; \
+else cur_chr= 16*cur_chr+cc-'a'+10 \
+
+#define no_expand_flag 257 \
+
+#define end_line_char_inactive (end_line_char<0) ||(end_line_char> 255)  \
+
+#define store_new_token(A) {q= get_avail() ;link(p) = q;info(q) = A; \
+p= q; \
+}
+#define fast_store_new_token(A) {fast_get_avail(q) ;link(p) = q;info(q) = A; \
+p= q; \
+} \
+
+#define top_mark_code 0
+#define first_mark_code 1
+#define bot_mark_code 2
+#define split_first_mark_code 3
+#define split_bot_mark_code 4
+#define top_mark cur_mark[top_mark_code]
+#define first_mark cur_mark[first_mark_code]
+#define bot_mark cur_mark[bot_mark_code]
+#define split_first_mark cur_mark[split_first_mark_code]
+#define split_bot_mark cur_mark[split_bot_mark_code] \
+
+#define int_val 0
+#define dimen_val 1
+#define glue_val 2
+#define mu_val 3
+#define ident_val 4
+#define tok_val 5 \
+
+#define scanned_result(A,B) {cur_val= A;cur_val_level= B;} \
+
+#define input_line_no_code (glue_val+1) 
+#define badness_code (glue_val+2)  \
+
+#define max_dimen 07777777777 \
+
+#define octal_token (other_token+'\'') 
+#define hex_token (other_token+'"') 
+#define alpha_token (other_token+'`') 
+#define point_token (other_token+'.') 
+#define continental_point_token (other_token+',')  \
+
+#define infinity 017777777777
+#define zero_token (other_token+'0') 
+#define A_token (letter_token+'A') 
+#define other_A_token (other_token+'A')  \
+
+#define scan_normal_dimen scan_dimen(false,false,false)  \
+
+#define set_conversion(A,B) {num= A;denom= B;} \
+
+#define default_rule 26214 \
+
+#define number_code 0
+#define roman_numeral_code 1
+#define string_code 2
+#define meaning_code 3
+#define font_name_code 4
+#define job_name_code 5 \
+
+#define closed 2
+#define just_open 1 \
+
+#define if_char_code 0
+#define if_cat_code 1
+#define if_int_code 2
+#define if_dim_code 3
+#define if_odd_code 4
+#define if_vmode_code 5
+#define if_hmode_code 6
+#define if_mmode_code 7
+#define if_inner_code 8
+#define if_void_code 9
+#define if_hbox_code 10
+#define if_vbox_code 11
+#define ifx_code 12
+#define if_eof_code 13
+#define if_true_code 14
+#define if_false_code 15
+#define if_case_code 16 \
+
+#define if_node_size 2
+#define if_line_field(A) mem[A+1].i
+#define if_code 1
+#define fi_code 2
+#define else_code 3
+#define or_code 4 \
+
+#define get_x_token_or_active_char  \
+{get_x_token() ; \
+if(cur_cmd==relax) if(cur_chr==no_expand_flag)  \
+{cur_cmd= active_char; \
+cur_chr= cur_tok-cs_token_flag-active_base; \
+} \
+} \
+
+#define TEX_area "TeXinputs/" \
+
+#define TEX_font_area "TeXfonts/" \
+ \
+
+#define MAX_CUR_FILE_NAME 1024 \
+
+#define append_to_name(A) {c= A;incr(k) ; \
+if(k<=file_name_size) name_of_file[k]= xchr[c]; \
+} \
+
+#define format_default_length 20
+#define format_area_length 11
+#define format_ext_length 4
+#define format_extension ".fmt" \
+
+#define pack_cur_name pack_file_name(cur_name,cur_area,cur_ext)  \
+
+#define ensure_dvi_open if(output_file_name==0)  \
+{if(job_name==0) open_log_file() ; \
+pack_job_name(".dvi") ; \
+while(!b_open_out(&dvi_file) )  \
+prompt_file_name("file name for output",".dvi") ; \
+output_file_name= b_make_name_string(&dvi_file) ; \
+} \
+
+#define no_tag 0
+#define lig_tag 1
+#define list_tag 2
+#define ext_tag 3 \
+
+#define stop_flag qi(128) 
+#define kern_flag qi(128) 
+#define skip_byte(A) A.b0
+#define next_char(A) A.b1
+#define op_byte(A) A.b2
+#define rem_byte(A) A.b3 \
+
+#define ext_top(A) A.b0
+#define ext_mid(A) A.b1
+#define ext_bot(A) A.b2
+#define ext_rep(A) A.b3 \
+
+#define slant_code 1
+#define space_code 2
+#define space_stretch_code 3
+#define space_shrink_code 4
+#define x_height_code 5
+#define quad_code 6
+#define extra_space_code 7 \
+
+#define non_char qi(256) 
+#define non_address 0 \
+
+#define char_info(A,B) font_info[char_base[A]+B].qqqq
+#define char_width(A,B) font_info[width_base[A]+B.b0].sc
+#define char_exists(A) (A.b0> min_quarterword) 
+#define char_italic(A,B) font_info[italic_base[A]+(qo(B.b2) ) /4].sc
+#define height_depth(A) qo(A.b1) 
+#define char_height(A,B) font_info[height_base[A]+(B) /16].sc
+#define char_depth(A,B) font_info[depth_base[A]+(B) %16].sc
+#define char_tag(A) ((qo(A.b2) ) %4)  \
+
+#define char_kern(A,B) font_info[kern_base[A]+256*op_byte(B) +rem_byte(B) ].sc
+#define kern_base_offset 256*(128+min_quarterword) 
+#define lig_kern_start(A,B) lig_kern_base[A]+B.b3
+#define lig_kern_restart(A,B) lig_kern_base[A]+256*op_byte(B) +rem_byte(B) +32768-kern_base_offset \
+
+#define param_end(A) param_base[A]].sc
+#define param(A) font_info[A+param_end
+#define slant param(slant_code) 
+#define space param(space_code) 
+#define space_stretch param(space_stretch_code) 
+#define space_shrink param(space_shrink_code) 
+#define x_height param(x_height_code) 
+#define quad param(quad_code) 
+#define extra_space param(extra_space_code)  \
+
+#define abort goto bad_tfm \
+
+#define start_font_error_message print_err("Font ") ;sprint_cs(u) ; \
+print_char('=') ;print_file_name(nom,aire,"") ; \
+if(s>=0)  \
+{print(" at ") ;print_scaled(s) ;print("pt") ; \
+} \
+else if(s!=-1000)  \
+{print(" scaled ") ;print_int(-s) ; \
+} \
+
+#define fget (hpos++) 
+#define fbyte (*hpos) 
+#define read_sixteen(A) {A= fbyte; \
+if(A> 127) abort; \
+fget;A= A*0400+fbyte; \
+}
+#define store_four_quarters(A) {fget;a= fbyte;qw.b0= qi(a) ; \
+fget;b= fbyte;qw.b1= qi(b) ; \
+fget;c= fbyte;qw.b2= qi(c) ; \
+fget;d= fbyte;qw.b3= qi(d) ; \
+A= qw; \
+} \
+
+#define check_byte_range(A) {if((A<bc) ||(A> ec) ) abort;}
+#define current_character_being_worked_on k+bc-fmem_ptr \
+
+#define store_scaled(A) {fget;a= fbyte;fget;b= fbyte; \
+fget;c= fbyte;fget;d= fbyte; \
+sw= (((((d*z) /0400) +(c*z) ) /0400) +(b*z) ) /beta; \
+if(a==0) A= sw;else if(a==255) A= sw-alpha;else abort; \
+} \
+
+#define check_existence(A)  \
+{check_byte_range(A) ; \
+qw= char_info(f,A) ; \
+if(!char_exists(qw) ) abort; \
+} \
+
+#define adjust(A) A[f]= qo(A[f])  \
+ \
+
+#define set_char_0 0
+#define set1 128
+#define set_rule 132
+#define put_rule 137
+#define nop 138
+#define bop 139
+#define eop 140
+#define push 141
+#define pop 142
+#define right1 143
+#define w0 147
+#define w1 148
+#define x0 152
+#define x1 153
+#define down1 157
+#define y0 161
+#define y1 162
+#define z0 166
+#define z1 167
+#define fnt_num_0 171
+#define fnt1 235
+#define xxx1 239
+#define xxx4 242
+#define fnt_def1 243
+#define pre 247
+#define post 248
+#define post_post 249 \
+
+#define id_byte 2 \
+
+#define dvi_out(A) {dvi_buf[dvi_ptr]= A;incr(dvi_ptr) ; \
+if(dvi_ptr==dvi_limit) dvi_swap() ; \
+} \
+
+#define movement_node_size 3
+#define location(A) mem[A+2].i \
+
+#define y_here 1
+#define z_here 2
+#define yz_OK 3
+#define y_OK 4
+#define z_OK 5
+#define d_fixed 6 \
+
+#define none_seen 0
+#define y_seen 6
+#define z_seen 12 \
+
+#define synch_h if(cur_h!=dvi_h)  \
+{movement(cur_h-dvi_h,right1) ;dvi_h= cur_h; \
+}
+#define synch_v if(cur_v!=dvi_v)  \
+{movement(cur_v-dvi_v,down1) ;dvi_v= cur_v; \
+} \
+
+#define billion float_constant(1000000000) 
+#define vet_glue(A) glue_temp= A; \
+if(glue_temp> billion)  \
+glue_temp= billion; \
+else if(glue_temp<-billion)  \
+glue_temp= -billion \
+
+#define exactly 0
+#define additional 1
+#define natural 0,additional \
+
+#define vpack(A,B) vpackage(A,B,max_dimen)  \
+
+#define noad_size 4
+#define nucleus(A) A+1
+#define supscr(A) A+2
+#define subscr(A) A+3
+#define math_type(A) link(A) 
+#define fam font
+#define math_char 1
+#define sub_box 2
+#define sub_mlist 3
+#define math_text_char 4 \
+
+#define ord_noad (unset_node+3) 
+#define op_noad (ord_noad+1) 
+#define bin_noad (ord_noad+2) 
+#define rel_noad (ord_noad+3) 
+#define open_noad (ord_noad+4) 
+#define close_noad (ord_noad+5) 
+#define punct_noad (ord_noad+6) 
+#define inner_noad (ord_noad+7) 
+#define limits 1
+#define no_limits 2 \
+
+#define left_delimiter(A) A+4
+#define right_delimiter(A) A+5
+#define radical_noad (inner_noad+1) 
+#define radical_noad_size 5
+#define fraction_noad (radical_noad+1) 
+#define fraction_noad_size 6
+#define small_fam(A) mem[A].qqqq.b0
+#define small_char(A) mem[A].qqqq.b1
+#define large_fam(A) mem[A].qqqq.b2
+#define large_char(A) mem[A].qqqq.b3
+#define thickness(A) width(A) 
+#define default_code 010000000000
+#define numerator(A) supscr(A) 
+#define denominator(A) subscr(A)  \
+
+#define under_noad (fraction_noad+1) 
+#define over_noad (under_noad+1) 
+#define accent_noad (over_noad+1) 
+#define accent_noad_size 5
+#define accent_chr(A) A+4
+#define vcenter_noad (accent_noad+1) 
+#define left_noad (vcenter_noad+1) 
+#define right_noad (left_noad+1) 
+#define delimiter(A) nucleus(A) 
+#define scripts_allowed(A) (type(A) >=ord_noad) &&(type(A) <left_noad)  \
+
+#define style_node (unset_node+1) 
+#define style_node_size 3
+#define display_style 0
+#define text_style 2
+#define script_style 4
+#define script_script_style 6
+#define cramped 1 \
+
+#define choice_node (unset_node+2) 
+#define display_mlist(A) info(A+1) 
+#define text_mlist(A) link(A+1) 
+#define script_mlist(A) info(A+2) 
+#define script_script_mlist(A) link(A+2)  \
+
+#define text_size 0
+#define script_size 16
+#define script_script_size 32 \
+
+#define mathsy_end(A) fam_fnt(2+A) ]].sc
+#define mathsy(A) font_info[A+param_base[mathsy_end
+#define math_x_height mathsy(5) 
+#define math_quad dimen_def[math_quad_no]
+#define num1 mathsy(8) 
+#define num2 mathsy(9) 
+#define num3 mathsy(10) 
+#define denom1 mathsy(11) 
+#define denom2 mathsy(12) 
+#define sup1 mathsy(13) 
+#define sup2 mathsy(14) 
+#define sup3 mathsy(15) 
+#define sub1 mathsy(16) 
+#define sub2 mathsy(17) 
+#define sup_drop mathsy(18) 
+#define sub_drop mathsy(19) 
+#define delim1 mathsy(20)  \
+
+#define delim2 mathsy(21) 
+#define axis_height mathsy(22) 
+#define total_mathsy_params 22 \
+
+#define mathex(A) font_info[A+param_base[fam_fnt(3+cur_size) ]].sc
+#define default_rule_thickness mathex(8) 
+#define big_op_spacing1 mathex(9) 
+#define big_op_spacing2 mathex(10) 
+#define big_op_spacing3 mathex(11) 
+#define big_op_spacing4 mathex(12) 
+#define big_op_spacing5 mathex(13) 
+#define total_mathex_params 13 \
+
+#define cramped_style(A) 2*(A/2) +cramped
+#define sub_style(A) 2*(A/4) +script_style+cramped
+#define sup_style(A) 2*(A/4) +script_style+(A%2) 
+#define num_style(A) A+2-2*(A/6) 
+#define denom_style(A) 2*(A/2) +cramped+2-2*(A/6)  \
+
+#define mu_mult(A) nx_plus_y(n,A,xn_over_d(A,f,0200000) )  \
+
+#define new_hlist(A) mem[nucleus(A) ].i \
+
+#define choose_mlist(A) {p= A(q) ;A(q) = null;} \
+
+#define math_spacing  \
+ \
+"0234000122*4000133**3**344*0400400*000000234000111*1111112341011" \
+ \
+
+#define u_part(A) mem[A+height_offset].i
+#define v_part(A) mem[A+depth_offset].i
+#define extra_info(A) info(A+list_offset)  \
+
+#define preamble link(align_head) 
+#define align_stack_node_size 5 \
+
+#define span_code 256
+#define cr_code 257
+#define cr_cr_code (cr_code+1) 
+#define end_template_token cs_token_flag+frozen_end_template \
+
+#define span_node_size 2 \
+
+#define tight_fit 3 \
+
+#define loose_fit 1 \
+
+#define very_loose_fit 0 \
+
+#define decent_fit 2 \
+
+#define active_node_size 3
+#define fitness(A) subtype(A) 
+#define break_node(A) rlink(A) 
+#define line_number(A) llink(A) 
+#define total_demerits(A) mem[A+2].i
+#define unhyphenated 0
+#define hyphenated 1
+#define last_active active \
+
+#define passive_node_size 2
+#define cur_break(A) rlink(A) 
+#define prev_break(A) llink(A) 
+#define serial(A) info(A)  \
+
+#define delta_node_size 7
+#define delta_node 2 \
+
+#define do_all_six(A) A(1) ;A(2) ;A(3) ;A(4) ;A(5) ;A(6)  \
+
+#define check_shrinkage(A) if((shrink_order(A) !=normal) &&(shrink(A) !=0) )  \
+{A= finite_shrink(A) ; \
+} \
+
+#define copy_to_cur_active(A) cur_active_width[A]= active_width[A]
+#define update_width(A)  \
+cur_active_width[A]= cur_active_width[A]+mem[r+A].sc \
+
+#define awful_bad 07777777777 \
+
+#define set_break_width_to_background(A) break_width[A]= background[A] \
+
+#define convert_to_break_width(A)  \
+mem[prev_r+A].sc= mem[prev_r+A].sc \
+-cur_active_width[A]+break_width[A]
+#define store_break_width(A) active_width[A]= break_width[A]
+#define new_delta_to_break_width(A)  \
+mem[q+A].sc= break_width[A]-cur_active_width[A] \
+
+#define new_delta_from_break_width(A) mem[q+A].sc=  \
+cur_active_width[A]-break_width[A] \
+
+#define combine_two_deltas(A) mem[prev_r+A].sc= mem[prev_r+A].sc+mem[r+A].sc
+#define downdate_width(A) cur_active_width[A]= cur_active_width[A]- \
+mem[prev_r+A].sc \
+
+#define update_active(A) active_width[A]= active_width[A]+mem[r+A].sc \
+
+#define store_background(A) active_width[A]= background[A] \
+
+#define act_width active_width[1]
+#define kern_break {if(!is_char_node(link(cur_p) ) &&auto_breaking)  \
+if(type(link(cur_p) ) ==glue_node) try_break(0,unhyphenated) ; \
+act_width= act_width+width(cur_p) ; \
+} \
+
+#define next_break prev_break \
+
+#define append_charnode_to_t(A) {link(t) = get_avail() ;t= link(t) ; \
+font(t) = hf;character(t) = A; \
+}
+#define set_cur_r {if(j<n) cur_r= qi(hu[j+1]) ;else cur_r= bchar; \
+if(odd(hyf[j]) ) cur_rh= hchar;else cur_rh= non_char; \
+} \
+
+#define wrap_lig(A) if(ligature_present)  \
+{p= new_ligature(hf,cur_l,link(cur_q) ) ; \
+if(lft_hit)  \
+{subtype(p) = 2;lft_hit= false; \
+} \
+if(A) if(lig_stack==null)  \
+{incr(subtype(p) ) ;rt_hit= false; \
+} \
+link(cur_q) = p;t= p;ligature_present= false; \
+}
+#define pop_lig_stack {if(lig_ptr(lig_stack) > null)  \
+{link(t) = lig_ptr(lig_stack) ; \
+t= link(t) ;incr(j) ; \
+} \
+p= lig_stack;lig_stack= link(p) ;free_node(p,small_node_size) ; \
+if(lig_stack==null) set_cur_r else cur_r= character(lig_stack) ; \
+} \
+
+#define advance_major_tail {major_tail= link(major_tail) ;incr(r_count) ; \
+} \
+
+#define trie_link(A) trie[A].rh
+#define trie_char(A) trie[A].b1
+#define trie_op(A) trie[A].b0 \
+
+#define set_cur_lang if(language<=0) cur_lang= 0; \
+else if(language> 255) cur_lang= 0; \
+else cur_lang= language \
+
+#define trie_root trie_l[0] \
+
+#define trie_ref trie_hash
+#define trie_back(A) trie[A].lh \
+
+#define active_height active_width
+#define cur_height active_height[1]
+#define set_height_zero(A) active_height[A]= 0 \
+
+#define deplorable 100000 \
+
+#define inserts_only 1 \
+
+#define box_there 2 \
+
+#define page_ins_node_size 4
+#define inserting 0
+#define split_up 1
+#define broken_ptr(A) link(A+1)  \
+
+#define broken_ins(A) info(A+1) 
+#define last_ins_ptr(A) link(A+2) 
+#define best_ins_ptr(A) info(A+2)  \
+
+#define page_goal page_so_far[0]
+#define page_total page_so_far[1]
+#define page_shrink page_so_far[6]
+#define page_depth page_so_far[7] \
+
+#define print_plus(A,B) if(page_so_far[A]!=0)  \
+{print(" plus ") ;print_scaled(page_so_far[A]) ;print(B) ;} \
+
+#define set_page_so_far_zero(A) page_so_far[A]= 0 \
+
+#define contrib_tail nest[0].tail_field \
+
+#define adjust_space_factor  \
+main_s= sf_code(cur_chr) ; \
+if(main_s==1000) space_factor= 1000; \
+else if(main_s<1000)  \
+{if(main_s> 0) space_factor= main_s; \
+} \
+else if(space_factor<1000) space_factor= 1000; \
+else space_factor= main_s \
+
+#define pack_lig(X)  \
+{main_p= new_ligature(main_f,cur_l,link(cur_q) ) ; \
+if(lft_hit)  \
+{subtype(main_p) = 2;lft_hit= false; \
+} \
+if(X) if(lig_stack==null)  \
+{incr(subtype(main_p) ) ;rt_hit= false; \
+} \
+link(cur_q) = main_p;tail= main_p;ligature_present= false; \
+} \
+
+#define wrapup(A) if(cur_l<non_char)  \
+{if(link(cur_q) > null)  \
+if(character(tail) ==qi(hyphen_char[main_f]) ) ins_disc= true; \
+if(ligature_present) pack_lig(A) ; \
+if(ins_disc)  \
+{ins_disc= false; \
+if(mode> 0) tail_append(new_disc() ) ; \
+} \
+} \
+
+#define any_mode(A) case vmode+A:case hmode+A:case mmode+A \
+
+#define non_math(A) case vmode+A:case hmode+A \
+
+#define fil_code 0
+#define fill_code 1
+#define ss_code 2
+#define fil_neg_code 3
+#define skip_code 4
+#define mskip_code 5 \
+
+#define box_flag 010000000000
+#define ship_out_flag box_flag+512
+#define leader_flag box_flag+513
+#define box_code 0
+#define copy_code 1
+#define last_box_code 2
+#define vsplit_code 3
+#define vtop_code 4 \
+
+#define fam_in_range ((cur_fam>=0) &&(cur_fam<16) )  \
+
+#define above_code 0
+#define over_code 1
+#define atop_code 2
+#define delimited_code 3 \
+
+#define global (a>=4) 
+#define define(A,B,C) if(global) geq_define(A,B,C) ;else eq_define(A,B,C) 
+#define word_define(A,B) if(global) geq_word_define(A,B) ;else eq_word_define(A,B)  \
+
+#define char_def_code 0
+#define math_char_def_code 1
+#define count_def_code 2
+#define dimen_def_code 3
+#define skip_def_code 4
+#define mu_skip_def_code 5
+#define toks_def_code 6 \
+
+#define show_code 0
+#define show_box_code 1
+#define show_the_code 2
+#define show_lists_code 3 \
+
+#define too_small(X) {wake_up_terminal; \
+wterm_ln("---! Must increase the %s",X) ; \
+ \
+goto bad_fmt; \
+} \
+
+#define dump_wd(A) {fmt_file.d= A;put(fmt_file) ;}
+#define dump_int(A) {fmt_file.d.i= A;put(fmt_file) ;}
+#define dump_hh(A) {fmt_file.d.hh= A;put(fmt_file) ;}
+#define dump_qqqq(A) {fmt_file.d.qqqq= A;put(fmt_file) ;} \
+
+#define undump_wd(A) {get(fmt_file) ;A= fmt_file.d;}
+#define undump_int(A) {get(fmt_file) ;A= fmt_file.d.i;}
+#define undump_hh(A) {get(fmt_file) ;A= fmt_file.d.hh;}
+#define undump_qqqq(A) {get(fmt_file) ;A= fmt_file.d.qqqq;}
+#define undump(A,B,C) {undump_int(x) ;if((x<A) ||(x> B) ) goto bad_fmt;else C= x;}
+#define undump_size(A,B,C,D) {undump_int(x) ; \
+if(x<A) goto bad_fmt;if(x> B) too_small(C) else D= x;} \
+
+#define dump_four_ASCII  \
+w.b0= qi(so(str_pool[k]) ) ;w.b1= qi(so(str_pool[k+1]) ) ; \
+w.b2= qi(so(str_pool[k+2]) ) ;w.b3= qi(so(str_pool[k+3]) ) ; \
+dump_qqqq(w)  \
+
+#define undump_four_ASCII  \
+undump_qqqq(w) ; \
+str_pool[k]= si(qo(w.b0) ) ;str_pool[k+1]= si(qo(w.b1) ) ; \
+str_pool[k+2]= si(qo(w.b2) ) ;str_pool[k+3]= si(qo(w.b3) )  \
+
+#define write_node_size 2
+#define open_node_size 3
+#define open_node 0
+#define write_node 1
+#define close_node 2
+#define special_node 3
+#define language_node 4
+#define what_lang(A) link(A+1) 
+#define what_lhm(A) type(A+1) 
+#define what_rhm(A) subtype(A+1) 
+#define write_tokens(A) link(A+1) 
+#define write_stream(A) info(A+1) 
+#define open_name(A) link(A+1) 
+#define open_area(A) info(A+2) 
+#define open_ext(A) link(A+2)  \
+
+#define hitex_ext language_node+1
+#define par_node hitex_ext
+#define par_node_size 3
+#define par_type(A) type(A+1) 
+#define int_type 0
+#define dimen_type 1
+#define glue_type 2
+#define par_number(A) subtype(A+1) 
+#define par_value(A) mem[A+2] \
+
+#define graf_node hitex_ext+1
+#define graf_node_size 5
+#define graf_penalty(A) mem[A+1].i
+#define graf_extent(A) link(A+3) 
+#define graf_params(A) info(A+4) 
+#define graf_list(A) link(A+4)  \
+
+#define disp_node hitex_ext+2
+#define disp_node_size 3
+#define display_left(A) type(A+1) 
+#define display_no_bs(A) subtype(A+1) 
+#define display_params(A) link(A+1) 
+#define display_formula(A) link(A+2) 
+#define display_eqno(A) info(A+2)  \
+
+#define baseline_node hitex_ext+3
+#define baseline_node_size small_node_size
+#define baseline_node_no(A) mem[A+1].i \
+
+#define image_node hitex_ext+4
+#define image_node_size 9
+#define image_width(A) width(A) 
+#define image_height(A) height(A) 
+#define image_depth(A) depth(A) 
+#define image_no(A) mem[A+4].i
+#define image_stretch(A) mem[A+5].sc
+#define image_shrink(A) mem[A+6].sc
+#define image_stretch_order(A) stretch_order(A+7) 
+#define image_shrink_order(A) shrink_order(A+7) 
+#define image_name(A) link(A+7) 
+#define image_area(A) info(A+8) 
+#define image_ext(A) link(A+8)  \
+
+#define hpack_node hitex_ext+5
+#define vpack_node hitex_ext+6
+#define pack_node_size box_node_size
+#define pack_m(A) type(A+list_offset) 
+#define pack_limit(A) mem[(A) +1+list_offset].sc
+#define pack_extent(A) link(A+2+list_offset)  \
+
+#define hset_node hitex_ext+7
+#define vset_node hitex_ext+8
+#define set_node_size box_node_size
+#define set_stretch_order glue_sign
+#define set_shrink_order glue_order
+#define set_stretch(A) mem[(A) +1+list_offset].sc
+#define set_extent(A) pack_extent(A) 
+#define set_shrink(A) mem[(A) +3+list_offset].sc \
+
+#define align_node hitex_ext+9
+#define align_node_size 4
+#define align_extent(A) link(A+2) 
+#define align_m(A) type(A+2) 
+#define align_v(A) subtype(A+2) 
+#define align_preamble(A) info(A+3) 
+#define align_list(A) link(A+3)  \
+
+#define setpage_node hitex_ext+10
+#define setpage_node_size 6
+#define setpage_name(A) link(A+1) 
+#define setpage_number(A) type(A+1) 
+#define setpage_id(A) subtype(A+1) 
+#define setpage_priority(A) info(A+2) 
+#define setpage_topskip(A) link(A+2) 
+#define setpage_depth(A) mem[A+3].sc
+#define setpage_height(A) info(A+4) 
+#define setpage_width(A) link(A+4) 
+#define setpage_list(A) info(A+5) 
+#define setpage_streams(A) link(A+5)  \
+
+#define setstream_node hitex_ext+11
+#define setstream_node_size 6
+#define setstream_number(A) type(A+1) 
+#define setstream_insertion(A) subtype(A+1) 
+#define setstream_mag(A) link(A+1) 
+#define setstream_prefered(A) type(A+2) 
+#define setstream_next(A) subtype(A+2) 
+#define setstream_ratio(A) link(A+2) 
+#define setstream_max(A) info(A+3) 
+#define setstream_width(A) link(A+3) 
+#define setstream_topskip(A) info(A+4) 
+#define setstream_height(A) link(A+4) 
+#define setstream_before(A) info(A+5) 
+#define setstream_after(A) link(A+5)  \
+
+#define stream_node hitex_ext+12
+#define stream_node_size 2
+#define stream_number(A) type(A+1) 
+#define stream_insertion(A) subtype(A+1)  \
+
+#define stream_after_node hitex_ext+13
+#define stream_before_node hitex_ext+14 \
+
+#define xdimen_node hitex_ext+15
+#define xdimen_node_size 4
+#define xdimen_ref_count(A) link(A) 
+#define xdimen_width(A) mem[A+1].sc
+#define xdimen_hfactor(A) mem[A+2].sc
+#define xdimen_vfactor(A) mem[A+3].sc \
+
+#define ignore_node hitex_ext+16
+#define ignore_node_size small_node_size
+#define ignore_info(A) type(A+1) 
+#define ignore_list(A) link(A+1)  \
+
+#define label_node hitex_ext+17
+#define label_node_size 2
+#define label_has_name(A) type(A+1) 
+#define label_where(A) subtype(A+1) 
+#define label_ptr(A) link(A+1) 
+#define label_ref(A) link(A+1)  \
+
+#define start_link_node hitex_ext+18
+#define end_link_node hitex_ext+19
+#define link_node_size 2 \
+
+#define outline_node hitex_ext+20
+#define outline_node_size 4
+#define outline_ptr(A) link(A+2) 
+#define outline_depth(A) mem[A+3].i \
+ \
+
+#define immediate_code 4
+#define set_language_code 5 \
+
+#define adv_past(A) {} \
+
+#define end_write_token cs_token_flag+end_write \
+
+
+#line 2625 "htex.ch"
+
+enum{/*11:*/
+#line 355 "btex.w"
+
+mem_max= 65534,
+
+
+mem_min= 0,
+
+
+buf_size= 2048,
+
+
+error_line= 72,
+half_error_line= 42,
+
+max_print_line= 79,
+stack_size= 200,
+max_in_open= 6,
+
+font_max= 255,
+
+font_mem_size= 65535,
+param_size= 60,
+nest_size= 400,
+max_strings= 30000,
+string_vacancies= 75000,
+
+
+pool_size= 400000,
+
+
+
+save_size= 600,
+
+trie_size= 65534,
+
+trie_op_size= 65534,
+dvi_buf_size= 8,
+file_name_size= 1024,
+empty_string= 256
+
+/*:11*/
+#line 2626 "htex.ch"
+};
+/*18:*/
+#line 495 "btex.w"
+
+typedef uint8_t ASCII_code;
+
+/*:18*//*25:*/
+#line 731 "btex.w"
+
+typedef uint8_t eight_bits;
+typedef struct{FILE*f;text_char d;}alpha_file;
+typedef struct{FILE*f;eight_bits d;}byte_file;
+
+/*:25*//*38:*/
+#line 1091 "btex.w"
+
+typedef int32_t pool_pointer;
+typedef int16_t str_number;
+typedef uint8_t packed_ASCII_code;
+
+/*:38*//*104:*/
+#line 2126 "btex.w"
+
+typedef int scaled;
+typedef int32_t nonnegative_integer;
+typedef int8_t small_number;
+
+/*:104*//*113:*/
+#line 2320 "btex.w"
+
+#if __SIZEOF_FLOAT__==4
+typedef float float32_t;
+#else
+#error  float type must have size 4
+#endif
+typedef float glue_ratio;
+
+/*:113*//*117:*/
+#line 2429 "btex.w"
+
+typedef uint8_t quarterword;
+typedef uint16_t halfword;
+typedef int8_t two_choices;
+typedef int8_t four_choices;
+typedef struct{
+halfword rh;
+union{
+halfword lh;
+struct{quarterword b0;quarterword b1;};
+};}two_halves;
+typedef struct{
+quarterword b0;
+quarterword b1;
+quarterword b2;
+quarterword b3;
+}four_quarters;
+typedef struct{
+union{
+int i;
+glue_ratio gr;
+two_halves hh;
+four_quarters qqqq;
+};}memory_word;
+typedef struct{FILE*f;memory_word d;}word_file;
+
+/*:117*//*155:*/
+#line 3152 "btex.w"
+
+typedef int8_t glue_ord;
+
+/*:155*//*221:*/
+#line 4309 "btex.w"
+
+typedef struct{int16_t mode_field;
+pointer head_field,tail_field;
+#line 698 "htex.ch"
+int pg_field;
+pointer bs_field,ls_field;
+scaled lsl_field;
+uint8_t*bs_pos;
+scaled hs_field;
+scaled ds_field,dw_field,di_field;
+scaled ht_field;
+uint32_t np_field;
+#line 4313 "btex.w"
+memory_word aux_field;
+}list_state_record;
+
+/*:221*//*279:*/
+#line 5881 "btex.w"
+
+typedef int8_t group_code;
+
+/*:279*//*310:*/
+#line 6457 "btex.w"
+
+typedef struct{
+quarterword state_field,index_field;
+halfword start_field,loc_field,limit_field,name_field;
+}in_state_record;
+
+/*:310*//*558:*/
+#line 10727 "btex.w"
+
+typedef uint8_t internal_font_number;
+typedef uint16_t font_index;
+
+/*:558*//*605:*/
+#line 11900 "btex.w"
+
+typedef int8_t dvi_index;
+
+/*:605*//*944:*/
+#line 18120 "btex.w"
+
+typedef uint16_t trie_pointer;
+
+/*:944*//*949:*/
+#line 18186 "btex.w"
+
+typedef int16_t hyph_pointer;
+
+/*:949*/
+#line 2627 "htex.ch"
+
+extern void list_init(void);
+extern void hpack_page(void);
+extern void happend_insertion(pointer p);
+extern bool hbuild_page(void);
+extern void hdisplay(pointer p,pointer a,bool l);
+extern void mem_init(void);
+#line 25006 "btex.w"
+extern pointer copy_node_list(pointer p);
+extern void flush_node_list(pointer p);
+extern
+pointer vpackage(pointer p,scaled h,small_number m,scaled l);
+extern pointer hpack(pointer p,scaled w,small_number m);
+extern pointer new_math(scaled w,small_number s);
+extern pointer new_ligature(quarterword f,quarterword c,pointer q);
+extern pointer new_penalty(int m);
+extern pointer new_spec(pointer p);
+extern pointer new_kern(scaled w);
+extern pointer new_disc(void);
+extern pointer new_null_box(void);
+extern pointer new_rule(void);
+extern pointer new_glue(pointer q);
+extern pointer new_character(internal_font_number f,eight_bits c);
+extern int*const char_base;
+extern int*const width_base;
+extern memory_word font_info[];
+extern scaled*const font_size;
+#line 2641 "htex.ch"
+extern char**const font_name;
+extern void hclear_fonts(void);
+extern void read_font_info(int f,char*nom,scaled s);
+#line 25028 "btex.w"
+extern list_state_record cur_list;
+extern pointer get_node(int s);
+extern pointer lo_mem_max;
+extern pointer hi_mem_min;
+extern memory_word*const mem;
+extern pointer just_box;
+#line 2649 "htex.ch"
+extern void append_to_vlist(pointer b,uint32_t offset);
+#line 25035 "btex.w"
+extern pointer adjust_tail;
+extern void freeze_page_specs(small_number s);
+extern pointer page_tail;
+extern scaled best_height_plus_depth;
+extern halfword badness(scaled t,scaled s);
+extern void show_box(pointer p);
+extern pointer temp_ptr;
+extern scaled best_size;
+extern pointer best_page_break;
+extern int least_page_cost;
+extern int insert_penalties;
+extern scaled page_so_far[];
+extern int page_contents;
+extern scaled page_max_depth;
+extern int nest_ptr;
+extern void pop_nest(void);
+extern void push_nest(void);
+extern void delete_glue_ref(pointer p);
+#line 2655 "htex.ch"
+void line_break(int final_widow_penalty,pointer par_ptr);/*:1410*/

Added: trunk/Build/source/texk/web2c/hitexdir/hintview/src/main.c
===================================================================
--- trunk/Build/source/texk/web2c/hitexdir/hintview/src/main.c	                        (rev 0)
+++ trunk/Build/source/texk/web2c/hitexdir/hintview/src/main.c	2022-01-19 13:28:43 UTC (rev 61658)
@@ -0,0 +1,406 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <setjmp.h>
+#include <string.h>
+#include <stdarg.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <math.h>
+
+#include <GL/glew.h>
+#include <GLFW/glfw3.h>
+
+#define VERSION 1
+#define REVISION 0
+#define PATCHLEVEL 0
+
+#if 0
+#include "rendernative.h" /* rendernative needs gcache_s */
+#else
+extern void nativeInit(void);
+extern void nativeClear(void);
+extern void nativeSetDark(int dark);
+#endif
+#include "error.h"
+#include "basetypes.h"
+#include "format.h"
+#include "get.h"
+#include "hint.h"
+#include "hrender.h"
+
+FILE* hlog;
+jmp_buf error_exit;
+
+/* Error Handling */
+int herror(const char *title, const char *message)
+{ fprintf(stderr,"ERROR %s: %s\n",title,message);
+  return 0;
+}
+
+int hmessage(char *title, char *format, ...)
+{ va_list vargs;
+  va_start(vargs,format);
+  vfprintf(stderr, format, vargs);
+  return 0;
+}
+
+void error_callback(int error, const char* description)
+{ herror("OpenGL",description);
+  longjmp(error_exit,1);
+}
+
+GLFWwindow* window;
+int px_h=1024, px_v=768; // size in pixel
+int page_h, page_v; // size in scaled points
+double x_dpi, y_dpi;
+#define SCALE_MIN 0.2
+#define SCALE_NORMAL 1.0
+#define SCALE_MAX 5.0
+double scale=SCALE_NORMAL;
+uint64_t pos; /* position of current page */
+
+void framebuffer_size_callback(GLFWwindow* window, int w, int h)
+{ px_h=w; px_v=h;
+  glViewport(0, 0, w, h);
+  //LOG("w=%d, h=%d\n",w,h);
+  hint_resize(px_h,px_v,scale*x_dpi,scale*y_dpi);
+  hint_page();
+}
+
+void getDPI(void)
+{ int widthMM, heightMM;
+  GLFWmonitor* monitor = glfwGetPrimaryMonitor();
+  glfwGetMonitorPhysicalSize(monitor, &widthMM, &heightMM);
+  const GLFWvidmode* mode = glfwGetVideoMode(monitor);
+  x_dpi = mode->width / (widthMM / 25.4);
+  y_dpi = mode->height / (heightMM / 25.4);
+  //LOG("xdpi=%f, ydpi=%f\n",x_dpi,y_dpi);
+}
+
+void hint_unmap(void)
+{ hget_unmap();
+}
+
+bool hint_map(void)
+{ return hget_map();
+}
+
+int open_file(int home)
+{ hint_clear_fonts(true);
+  if (!hint_begin()) return 0;
+  if (home)
+    hint_page_home();
+  else
+    hint_page_top(0);
+    //  strncpy(title_name,hin_name,MAX_PATH);
+    //	SetNavigationTree();
+   //SetWindowText(hMainWnd,title_name);
+return 1;
+} 
+
+static void reload_file(void)
+{ double fpos=hint_get_fpos();
+  hint_begin();
+  pos=hint_set_fpos(fpos);
+  //LOG("reloading...\n");
+}
+
+static int new_file_time(void)
+{ struct stat st;
+  if (hin_name!=NULL &&
+      stat(hin_name,&st)==0 &&
+      st.st_size>0)
+  {
+    //LOG("file %s %lu\n",hin_name,st.st_mtime);
+    if (st.st_mtime>hin_time)
+    return 1;
+  else
+    return 0;
+  }
+  return 0;
+}
+
+int dark = 0, loading=0, autoreload=0, home=0;
+
+int usage(void)
+{    return herror("Usage:", "hintview [options] file\n"
+		  "Call 'hintview --help' for details.\n");
+}
+
+int help(void)
+{ fprintf(stdout,"%s",
+   "Usage: hintview [options] file\n"
+   "Options:\n"
+   "  -a         Start in autoreload mode.\n"	  
+   "  -h         Start with the documents home page.\n"	  
+   "  -n         Start in night mode.\n"	  
+#if 0
+   "  -o         Show the documents outline.\n"
+#endif
+   "  -z         Start with zoom level 100%.\n"	  
+   "  --help     Display this message.\n"	  
+   "  --version  Display the version.\n"	  
+   "\n"
+   "See the hintview man page for more details.\n"
+  );
+  return 0;
+}
+
+int command_line(int argc, char *argv[])
+{ size_t sl;
+  int i;
+  for (i=1; argv[i]!=NULL && argv[i][0]=='-'; i++)
+    { switch (argv[i][1])
+      { case '-':
+	    if (strcmp(argv[i]+2,"help")==0) return help();
+	    else if (strcmp(argv[i]+2,"version")==0)
+	      { fprintf(stdout,"hintview version %d.%d.%d\n", VERSION, REVISION, PATCHLEVEL);
+	        return 0;
+	      }
+	    else
+	      return usage();
+	case 'a': autoreload=1; break;
+        case 'n': dark=1; break;
+        case 'o': break;
+        case 'z': scale=SCALE_NORMAL; break;
+        case 'h': home=1; break;  
+        default: return usage();
+      }
+    }
+  if (argv[i]==NULL)
+    return usage();
+  if (hin_name!=NULL) free(hin_name);
+  hin_name=malloc(strlen(argv[i])+1);
+  if (hin_name==NULL)
+    return herror("Out of memory for file name", argv[i]);
+  strcpy(hin_name,argv[i]);
+  sl=strlen(hin_name);
+  if (sl>4 && strncmp(hin_name+sl-4,".hnt",4)!=0)
+    return herror("Unknown File Type,I dont know how to open this file", argv[1]);
+return 1;	
+}
+
+GLFWcursor *drag_cursor, *hand_cursor, *arrow_cursor;
+int mouse_down=0, drag=0, on_link=0;
+
+void clear_cursor(void)
+{ if (on_link||drag) 
+  { glfwSetCursor(window, arrow_cursor); on_link=drag=0;}
+}
+
+/* combining the key with the shift, control, alt or super flag */
+#define KEY_MOD(K,M) (((K)<<4)|((M)&0xF))
+#define KEY(K) KEY_MOD(K,0)
+#define CTRL(K) KEY_MOD(K,GLFW_MOD_CONTROL)
+
+void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
+{ if (action!=GLFW_PRESS) return;
+  switch (KEY_MOD(key,mods)) {
+  case CTRL(GLFW_KEY_Q):
+    glfwSetWindowShouldClose(window,1);
+    break;
+  case CTRL(GLFW_KEY_N):
+    dark=!dark;
+    nativeSetDark(dark);
+    break;
+  case KEY(GLFW_KEY_HOME):
+  case CTRL(GLFW_KEY_H):
+    hint_page_home();
+    clear_cursor();
+    break;
+  case CTRL(GLFW_KEY_Z): 
+  case CTRL(GLFW_KEY_Y): /* US keyboard */
+    scale=SCALE_NORMAL;
+    hint_resize(px_h,px_v,scale*x_dpi,scale*y_dpi);
+    hint_page();
+    hint_clear_fonts(true);
+    clear_cursor();
+    break;
+  case KEY(GLFW_KEY_PAGE_DOWN):
+    pos=hint_page_next();
+    hint_page();
+    clear_cursor();
+    break;
+  case KEY(GLFW_KEY_PAGE_UP):
+    pos=hint_page_prev();
+    hint_page();
+    clear_cursor();
+    break;
+  case CTRL(GLFW_KEY_A): /* auto reload */
+    autoreload=!autoreload;
+    if (!autoreload)
+      break; /* else fall through to reload */
+  case CTRL(GLFW_KEY_R): /* reload */
+    if (!loading)
+    { loading=1;
+      HINT_TRY reload_file();
+      loading=0;
+    }
+    clear_cursor();
+    break;
+    break;
+  case CTRL(GLFW_KEY_F): /* find */
+    break;
+  case CTRL(GLFW_KEY_O): /* outlines */
+    break;
+  default:
+    // LOG("key %d, scan %d, action %d, mosd %d\n",key, scancode, action, mods);
+    break;
+  }
+}
+
+/* convert pixel to scaled points (including scale) */
+
+#define PX2SP(X,DPI) floor((X)*ONE*72.27/((DPI)*scale))
+
+void mouse_click(void)
+{ double x,y;
+  int link;
+  glfwGetCursorPos(window, &x, &y);
+  //LOG("xy= %fx%f\n", x,y);
+  HINT_TRY {
+    link=hint_find_link(PX2SP(x,x_dpi),PX2SP(y,y_dpi),2*ONE);
+    if (link>=0)
+    { hint_link_page(link);
+      clear_cursor();
+    }
+  }
+}
+
+double x_start, y_start, xy_start, scale_start, time_start;
+#define DELTA_T 0.4
+#define DELTA_XY 16.0
+
+static void cursor_position_callback(GLFWwindow* window, double x, double y)
+{ //LOG("xy= %fx%f\n", x-x_start,y-y_start);
+  double f;
+  if (!mouse_down)
+  { int link;
+    link=hint_find_link(PX2SP(x,x_dpi),PX2SP(y,y_dpi),2*ONE);
+    if (link>=0 && !on_link)
+    { glfwSetCursor(window, hand_cursor); on_link=1; }
+    else if (link<0 && on_link)
+    { glfwSetCursor(window, arrow_cursor); on_link=0; }
+    return;
+  }
+  if (!drag) /* we dont know whether this is a click or a drag */  
+  { double d = (x-x_start)*(x-x_start)+(y-y_start)*(y-y_start);
+    if (d<= DELTA_XY)
+    { double t=glfwGetTime();
+      if (t<=time_start+DELTA_T)
+	return;
+    }
+    /* start dragging */
+    drag=1;
+    glfwSetCursor(window, drag_cursor);
+    xy_start=x_start*x_start+y_start*y_start;
+  }
+    /* dragging */
+  f=(x_start*x+y_start*y)/xy_start; /* projection of (x,y) on (x_start,y_start) */
+  scale=scale_start*f;
+  if (scale < SCALE_MIN) scale=SCALE_MIN;
+  if (scale > SCALE_MAX) scale=SCALE_MAX;
+  hint_resize(px_h,px_v,scale*x_dpi,scale*y_dpi);
+  hint_page();
+}
+
+
+void mouse_button_callback(GLFWwindow* window, int button, int action, int mods)
+{ if (button == GLFW_MOUSE_BUTTON_LEFT)
+  { if (action == GLFW_PRESS)
+    { glfwGetCursorPos(window, &x_start, &y_start);
+      time_start=glfwGetTime();
+      scale_start=scale;
+      drag=0;
+      mouse_down =1;
+    }
+    else if (action == GLFW_RELEASE)
+    { mouse_down=0;
+      if (drag) /* end dragging */
+      {	hint_clear_fonts(true);
+        clear_cursor();
+      }
+      else
+        mouse_click();
+    }
+  }      
+}
+
+void cursor_enter_callback(GLFWwindow* window, int entered)
+{ if (entered && autoreload && new_file_time())
+    reload_file();
+  //LOG("entered=%d auto=%d\n",entered, autoreload);
+}
+
+int create_window(void)
+{ if( !glfwInit() )
+  {
+    herror("GLFW", "Failed to initialize GLFW\n" );
+    getchar();
+    return 0;
+  }
+  glfwSetErrorCallback(error_callback);
+  glfwWindowHint(GLFW_SAMPLES, 4);
+  glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
+  glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
+  glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // To make MacOS happy; should not be needed
+  glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
+  
+  /* Open a window and create its OpenGL context */
+  window = glfwCreateWindow( px_h, px_v, "HintView", NULL, NULL);
+  if( window == NULL ){
+    herror("GLFW","Failed to open GLFW window.\n"
+	   "If you have an Intel GPU, they are not 3.3 compatible.\n"
+	   "Try the 2.1 version of the tutorials.\n" );
+    glfwTerminate();
+    return 0;
+  }
+  glfwMakeContextCurrent(window);
+      
+  glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE);
+  glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
+  
+  drag_cursor = glfwCreateStandardCursor(GLFW_HRESIZE_CURSOR);
+  hand_cursor = glfwCreateStandardCursor(GLFW_HAND_CURSOR);
+  arrow_cursor = glfwCreateStandardCursor(GLFW_ARROW_CURSOR);
+
+  getDPI();
+ 
+  glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
+  glfwSetKeyCallback(window, key_callback);
+  glfwSetCursorEnterCallback(window,cursor_enter_callback);
+  glfwSetMouseButtonCallback(window, mouse_button_callback);
+  glfwSetCursorPosCallback(window, cursor_position_callback);
+
+  glfwSetCursorPos(window, px_h/2, px_v/2);
+ 
+  nativeInit();
+  return 1;
+}
+
+int main(int argc, char *argv[])
+{ hlog=stderr;
+  if (setjmp(error_exit)!=0) return 1;
+  if (!command_line(argc,argv))
+    return 1;
+   if (!create_window())
+    return 1;
+  nativeSetDark(dark);
+  hint_resize(px_h,px_v,scale*x_dpi,scale*y_dpi);
+  if (!open_file(home))
+    return 1;
+  hint_page_home();
+  if (setjmp(error_exit)==0)
+    do
+    { hint_render();
+      glfwSwapBuffers(window);
+      glfwWaitEvents();
+    } // Check if the ESC key was pressed or the window was closed
+    while(glfwWindowShouldClose(window) == 0 );
+  nativeClear();
+  glfwDestroyWindow(window); // part of glfwTerminate
+  glfwTerminate();
+  return 0;
+}
+

Added: trunk/Build/source/texk/web2c/hitexdir/hintview/src/main.h
===================================================================
--- trunk/Build/source/texk/web2c/hitexdir/hintview/src/main.h	                        (rev 0)
+++ trunk/Build/source/texk/web2c/hitexdir/hintview/src/main.h	2022-01-19 13:28:43 UTC (rev 61658)
@@ -0,0 +1,22 @@
+#ifndef MAIN_H
+#define MAIN_H
+
+#define VERSION "Version 1.1"
+
+/* colors foreground and background for day and night mode */
+#define RGB(R,G,B) (((((R)<<8)| G)<<8) | B)
+#define GET_R(C) (((C)>>16)&0xFF)
+#define GET_G(C) (((C)>>8)&0xFF)
+#define GET_B(C) ((C)&0xFF)
+#define FG_DAY RGB(0x00,0x00,0x00) /* black */
+#define BG_DAY RGB(0xFF,0xFF,0xFF) /* white */
+#define FG_NIGHT RGB(0xFF,0xFF,0xE8) /* warm white */
+#define BG_NIGHT RGB(0x00,0x00,0x08) /* dark blue */
+
+#define BF_ON_DAY RGB(0xD0,0xD0,0xD0) /* lighter grey */
+#define BF_OFF_DAY RGB(0xA0,0xA0,0xA0) /* light grey */
+#define BF_ON_NIGHT RGB(0x90,0x90, 0x90) /* medium grey */
+#define BF_OFF_NIGHT RGB(0x60,0x60, 0x60) /* dark grey */
+
+
+#endif /*MAIN_H*/ 

Added: trunk/Build/source/texk/web2c/hitexdir/hintview/src/renderOGL.c
===================================================================
--- trunk/Build/source/texk/web2c/hitexdir/hintview/src/renderOGL.c	                        (rev 0)
+++ trunk/Build/source/texk/web2c/hitexdir/hintview/src/renderOGL.c	2022-01-19 13:28:43 UTC (rev 61658)
@@ -0,0 +1,553 @@
+#include <GL/glew.h>
+
+#include "basetypes.h"
+#include "main.h"
+#include "error.h"
+#include <ft2build.h>
+#include FT_FREETYPE_H
+#include "hint.h"
+#include "hfonts.h"
+#include "hrender.h"
+#include "rendernative.h"
+#define STB_IMAGE_IMPLEMENTATION
+#include "stb_image.h"
+
+
+#ifdef DEBUG
+static void checkGlError(const char *op) 
+{ GLint error;
+  while( (error= glGetError())!= GL_NO_ERROR)
+	  MESSAGE("OGL Error after %s: 0x%x\n", op, error);
+}
+#else
+#define checkGlError(OP)	(void)0
+#endif
+
+#define MAX_INFOLOG 512
+static 	GLuint ProgramID, MatrixID, RuleID, GammaID, FGcolorID, ImageID, PictureID=0;
+
+#define xyID 0
+#define uvID 1
+
+#define STR(X) QUOTE(X)
+#define QUOTE(X) #X
+static const char VertexShader[]=
+  "#version 330 core\n"
+
+  /* Input */
+  "layout(location = " STR(xyID) ") in vec2 vertexXY;\n"
+  "layout(location = " STR(uvID) ") in vec2 vertexUV;\n"
+  /* output */
+   "out vec2 UV;\n"
+  /* Constants for the current triangles */
+  "uniform mat4 MVP;\n"
+
+  "void main()\n"
+  "{\n"
+      "gl_Position = MVP * vec4(vertexXY,-1.0f,1.0f);\n"
+      "UV = vertexUV;\n"
+  "}\n";
+
+  
+static const char FragmentShader[]=
+  "#version 330 core\n"
+
+  /* Input */
+  "in vec2 UV;\n"
+  /* Output */
+  "out vec4 color;\n"
+  /* Constants for the current triangles */
+  "uniform sampler2D theTexture;\n"
+  "uniform vec3 FGcolor;\n"
+  "uniform float Gamma;\n"
+  "uniform int Image;\n"
+
+  "void main()\n"
+  "{ vec4 texColor = texture2D( theTexture, UV );\n"
+    "if (Image==1) color = texColor;\n"
+    "else\n"
+    "{ color.a = pow(texColor.r,Gamma);\n"
+      "color.rgb = FGcolor;\n"
+    "}\n"
+  "}\n"
+;
+
+/* The Fragment shader should do Gamma correct (GC) blending.
+   The theory says transform FGcolor and BGcolor to linear space
+   FGlin = pow(FGcolor,2.2); BGlin=pow(BGcolor,2.2);
+   BlendLin = FGlin*alpha + BGlin*(1-alpha);
+   Blend = pow(BlendLin,1/2.2);
+   
+   But, the alpha values delivered by the freetype font rasterizer
+   are actually brightness values! And our foreground and background
+   values are pretty much either black (0.0) or white (1.0) or plain 
+   Blue (0.0,0.0,1.0) or things like that. So pow(FGcolor,2.2) will do
+   nothing or little to them. But we should transform the alpha to 
+   linear space before blending. So we have
+   AlphaLin = pow(alpha,2.2)
+   BlendLin = FGcolor*alphaLin + BGcolor*(1-AlphaLin);
+   Blend = pow(BlendLin, 1/2.2);
+   The last line will be done automatically by the hardware if we specify
+   an GL_FRAMBUFFER_SRGB. The second last line is the normal blending
+   if we change the alpha value to linear.
+   Using this will require that images are also converted to linear textures
+   in sRGB space.
+*/
+
+static GLuint loadShader(GLenum type, char const *source)
+{ GLuint shaderID;
+  GLint result =GL_FALSE;
+
+  /* Compile and check vertex shader */
+  shaderID = glCreateShader(type);
+  glShaderSource(shaderID, 1, &source , NULL);
+  glCompileShader(shaderID);
+  glGetShaderiv(shaderID, GL_COMPILE_STATUS, &result);
+  if (!result)
+  { char InfoLog[MAX_INFOLOG];
+    glGetShaderInfoLog(shaderID, MAX_INFOLOG, NULL, InfoLog);
+    QUIT("Error compiling shader (%d): %s\n", type, InfoLog);
+  }
+  return shaderID;
+}
+
+static void createProgram(void)
+{ GLuint vertexID=loadShader(GL_VERTEX_SHADER,VertexShader);
+  GLuint fragmentID=loadShader(GL_FRAGMENT_SHADER,FragmentShader);
+  GLint result =GL_FALSE;
+
+	
+  /* Create, linking, and check the program */
+  ProgramID = glCreateProgram();
+  glAttachShader(ProgramID, vertexID);
+  glAttachShader(ProgramID, fragmentID);
+  glLinkProgram(ProgramID);
+  glGetProgramiv(ProgramID, GL_LINK_STATUS, &result);
+  if (!result)
+  { char InfoLog[MAX_INFOLOG];
+    glGetProgramInfoLog(ProgramID, MAX_INFOLOG, NULL, InfoLog);
+    QUIT("Error linking shader program: %s\n", InfoLog);
+  }
+	
+  glDetachShader(ProgramID, vertexID);
+  glDetachShader(ProgramID, fragmentID);
+	
+  glDeleteShader(vertexID);
+  glDeleteShader(fragmentID);
+  //LOG("createProgram Done\n");
+}
+
+/* the 4x4 Model-View-Projection Matrix */
+static GLfloat MVP[4][4] = {
+  {0.5, 0.0, 0.0, 0.0 }, // x scale
+  {0.0, 0.5, 0.0, 0.0 }, // y scale
+  {0.0, 0.0, 0.0, 0.0 }, // z scale
+  {0.0, 0.0, 0.0, 1.0 }}; // translation x, y, z
+
+/* The XY coordinates */
+static GLfloat xy[6][2] = { 
+  {-1.0f, 1.0f}, // top left
+  {-1.0f, -1.0f}, //bot left
+  {1.0f, -1.0f},  // bot right
+
+  {1.0f, 1.0f}, //top right
+  {-1.0f, 1.0f}, //top left
+  {1.0f, -1.0f}  //bot right
+};
+
+/* The UV coordinates */
+static const GLfloat uv[6][2] = { 
+  {0.0f, 1.0f},  //left top
+  {0.0f, 0.0f}, //left bot
+  {1.0f, 0.0f}, //right bot
+
+  {1.0f, 1.0f}, //right top 
+  {0.0f, 1.0f}, //left top 
+  {1.0f, 0.0f} //right bot 
+};
+
+static GLuint xybuffer, uvbuffer;
+
+
+static void mkRuleTexture() /* the texture used for rules */
+{
+#define NO_TEST 1  
+#if NO_TEST	
+  GLubyte rule[1][1][1]={{{0xFF}}};
+  /* for testing only */
+#else /* for testing only */
+  GLubyte rule[2][2][3]={{{0}}};
+  rule[0][0][0]=0xFF; // red top left
+  rule[0][1][0]=rule[0][1][1]=0xFF; // yellow top right
+  rule[1][0][2]=0xFF; // blue bottom left
+  rule[1][1][1]=0xFF; // green bottom right
+#endif
+	// Create one OpenGL texture
+  glPixelStorei(GL_UNPACK_ALIGNMENT, 1); // select byte alignment
+  checkGlError("glPixelStorei");
+
+  glGenTextures(1, &RuleID);
+  glBindTexture(GL_TEXTURE_2D, RuleID);
+  checkGlError("glBindTexture RuleID");
+
+#if NO_TEST
+  glTexImage2D(GL_TEXTURE_2D, 0,GL_R8, 1, 1 , 0, GL_RED, GL_UNSIGNED_BYTE, rule);
+#else
+  glTexImage2D(GL_TEXTURE_2D, 0,GL_RGB, 2, 2 , 0, GL_RGB, GL_UNSIGNED_BYTE, rule);
+#endif
+    checkGlError("glTeXImage2D Rule");
+  /* Set texture options */
+  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+  //LOG("mkRuleTexture Done\n");
+}
+
+
+void nativeInit(void)
+{ GLuint VertexArrayID;
+  static int glewInitialized=0;
+  /* Initialize GLEW */
+  glewExperimental = true; /* Needed for core profile */
+  if (!glewInitialized &&glewInit() != GLEW_OK) 
+    QUIT("Failed to initialize GLEW\n");
+  glewInitialized=1;
+  while(glGetError()!= GL_NO_ERROR)
+    continue; /* ignore errors in glewInit */
+  
+  /* Create the vertex array object (VAO) */
+  glGenVertexArrays(1, &VertexArrayID);
+  glBindVertexArray(VertexArrayID);
+
+  createProgram();
+
+  MatrixID = glGetUniformLocation(ProgramID, "MVP");
+  FGcolorID  = glGetUniformLocation(ProgramID, "FGcolor");
+  GammaID  = glGetUniformLocation(ProgramID, "Gamma");
+  ImageID  = glGetUniformLocation(ProgramID, "Image");
+  checkGlError("get IDs"); 
+
+  glGenBuffers(1, &xybuffer);
+  glBindBuffer(GL_ARRAY_BUFFER, xybuffer);
+  glBufferData(GL_ARRAY_BUFFER, sizeof(xy), xy, GL_STREAM_DRAW);
+  
+  glGenBuffers(1, &uvbuffer);
+  glBindBuffer(GL_ARRAY_BUFFER, uvbuffer);
+  glBufferData(GL_ARRAY_BUFFER, sizeof(uv), uv, GL_STATIC_DRAW);
+
+  glUseProgram(ProgramID);
+
+
+  glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &MVP[0][0]);
+  glUniform1f(GammaID, 1.0f/2.2f);
+  glUniform1i(ImageID, 0);
+  glUniform3f(FGcolorID, 0.0, 0.0, 0.0); // black as default foreground
+  glClearColor(1.0f, 1.0f, 1.0f, 0.0f); // white as default background
+
+   /* 1rst attribute buffer : XYs */
+  glEnableVertexAttribArray(xyID);
+  glBindBuffer(GL_ARRAY_BUFFER, xybuffer);
+  glBufferData(GL_ARRAY_BUFFER, sizeof(xy), xy, GL_STREAM_DRAW);
+  glVertexAttribPointer(xyID, 2, GL_FLOAT, GL_FALSE, 0, (void*)0);
+  checkGlError("glVertexAttribPointer xy");
+
+  /* 2nd attribute buffer : UVs */
+  glEnableVertexAttribArray(uvID);
+  glBindBuffer(GL_ARRAY_BUFFER, uvbuffer);
+  glBufferData(GL_ARRAY_BUFFER, sizeof(uv), uv, GL_STATIC_READ);
+  glVertexAttribPointer(uvID,2,GL_FLOAT,GL_FALSE, 0, (void*)0);
+  checkGlError("glVertexAttribPointer uv");
+
+  /* Make the alpha channel work */
+  glEnable(GL_BLEND);
+  checkGlError("glEnable BLEND");
+  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+  checkGlError("glBlendFunc");
+  glEnable(GL_MULTISAMPLE);
+  checkGlError("GL_MULTISAMPLE");
+  glEnable(GL_FRAMEBUFFER_SRGB);
+  checkGlError("GL_FRAMEBUFFER_SRGB");
+
+  hint_clear_fonts(false);
+  mkRuleTexture();
+  //LOG("nativeInit Done\n");
+}
+
+
+void nativeClear(void)
+{ glDeleteBuffers(1, &xybuffer);
+  glDeleteBuffers(1, &uvbuffer);
+  glDeleteProgram(ProgramID);
+  glDeleteTextures(1, &RuleID);
+   if (PictureID != 0) {
+        glDeleteTextures(1, &PictureID);
+        PictureID = 0;
+   }
+}
+
+void nativeBlank(void)
+{ glClear(GL_COLOR_BUFFER_BIT);
+  //LOG("nativeBlank Done\n");
+}
+
+void nativeSetGamma(double gamma)
+{ glUniform1f(GammaID, 1.0/gamma);
+  checkGlError("glsetgamma");
+}
+
+static GLfloat curfr, curfg, curfb;
+static uint8_t last_style=0;
+static void nativeSetColors(GLfloat fr, GLfloat fg, GLfloat fb, GLfloat br, GLfloat bg, GLfloat bb)
+/* set foreground and background rgb colors */
+{
+  glClearColor(br, bg, bb, 1.0f);
+  curfr=fr; curfg=fg; curfb=fb;
+  glUniform3f(FGcolorID, curfr, curfg, curfb);
+  last_style=0;
+}
+
+static int dark_mode;
+
+void nativeSetDark(int on)
+{   if (on) {
+        int ourModeLocation = glGetUniformLocation(ProgramID, "ourMode");
+        glUniform1i(ourModeLocation, true);
+        dark_mode = true;
+        nativeSetColors(
+			GET_R(FG_NIGHT)/255.0f, 
+			GET_G(FG_NIGHT)/255.0f, 
+			GET_B(FG_NIGHT)/255.0f, 
+			GET_R(BG_NIGHT)/255.0f, 
+			GET_G(BG_NIGHT)/255.0f, 
+			GET_B(BG_NIGHT)/255.0f);
+    } else {
+        int ourModeLocation = glGetUniformLocation(ProgramID, "ourMode");
+        glUniform1i(ourModeLocation, false);
+        dark_mode = false;
+        nativeSetColors(
+			GET_R(FG_DAY)/255.0f, 
+			GET_G(FG_DAY)/255.0f, 
+			GET_B(FG_DAY)/255.0f, 
+			GET_R(BG_DAY)/255.0f, 
+			GET_G(BG_DAY)/255.0f, 
+			GET_B(BG_DAY)/255.0f);
+     }
+}
+
+static float pt_h=600.0, pt_v=800.0;
+
+void nativeSetSize(int px_h, int px_v, double x_dpi, double y_dpi)
+{  pt_h = px_h * 72.27 / x_dpi;
+   pt_v = px_v * 72.27 / y_dpi; 
+   page_h = round(pt_h * (1 << 16));
+   page_v = round(pt_v * (1 << 16));
+   MVP[0][0]=2.0/pt_h; // x: scale to -1 to +1
+   MVP[1][1]=-2.0/pt_v; // y: scale to 1 to -1
+   //MVP[2][2]=0.0f; // z: don't care
+   MVP[3][0]=-1.0f; // x position: left
+   MVP[3][1]=1.0f; // y position: up
+   //MVP[3][2]=-1.0f; // don't care
+   //MVP[3][3]=1.0f; // w: identity, already there
+   glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &MVP[0][0]);
+   glViewport(0, 0, px_h, px_v);
+}
+
+void nativeRule(double x, double y, double w, double h)
+/* Using GL to render a rule (a black rectangle)
+   Coordinates in points, origin bottom left, x and w right, y and h up
+   x,y position
+   w,h width and height
+  */
+{ /* Moving using the vertex buffer */
+  xy[0][0]=x;   xy[0][1]=y;   // xy top left
+  xy[1][0]=x;   xy[1][1]=y-h; // xy bot left 0
+  xy[2][0]=x+w; xy[2][1]=y-h; // xy bot right 0
+
+  xy[3][0]=x+w; xy[3][1]=y;    // xy top right 1
+  xy[4][0]=x;   xy[4][1]=y;    // xy top left 1
+  xy[5][0]=x+w;  xy[5][1]=y-h; // xy bot right 1
+  glBindTexture(GL_TEXTURE_2D, RuleID);
+  checkGlError("glBindTexture RuleID");
+
+  glBindBuffer(GL_ARRAY_BUFFER, xybuffer);
+  glBufferData(GL_ARRAY_BUFFER, sizeof(xy), xy, GL_STREAM_DRAW);
+  glDrawArrays(GL_TRIANGLES, 0, 2*3);
+  //LOG("nativeRule %f@%f %fx%f Done\n",x,y,w,h);
+}
+
+void nativeImage(double x, double y, double w, double h, unsigned char *b, unsigned char *e)
+/* render the image found between *b and *e at x,y with size w,h.
+   x, y, w, h are given in point
+*/
+{
+  static unsigned char *last_b=NULL;
+  GLenum format, internal_format;
+  int width, height, nrChannels;
+  unsigned char *data;
+  static unsigned char grey[4]={0,0,0,0x80};
+  if (b!=last_b)
+  { if (PictureID != 0) {
+        glDeleteTextures(1, &PictureID);
+        PictureID = 0;
+    }
+    last_b=b;
+    data = stbi_load_from_memory(b, (int) (e - b), &width, &height, &nrChannels, 0);
+    if (data == NULL)
+      {
+      LOG("Unable to display image\n");
+      data=grey; width=height=1; nrChannels=4;
+    }
+    //LOG("nativeImage %d chanels\n",nrChannels);	
+    internal_format=GL_SRGB;
+    if (nrChannels == 4)
+    { format = GL_RGBA; internal_format=GL_SRGB_ALPHA;}
+    else if (nrChannels == 3) 
+      format = GL_RGB;
+    else if (nrChannels == 2) 
+      format = GL_RG;
+    else
+      format = GL_RED;
+    glGenTextures(1, &PictureID);
+    glBindTexture(GL_TEXTURE_2D, PictureID);
+    checkGlError("glBindTexture PictureID");
+
+    glTexImage2D(GL_TEXTURE_2D, 0, internal_format, width, height, 0, format, GL_UNSIGNED_BYTE, data);
+    checkGlError("glTexImage2D(image)");
+    if (data!=grey) stbi_image_free(data);
+    glGenerateMipmap(GL_TEXTURE_2D);
+    checkGlError("glGenerateMipmap(image)");
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+  }
+  else
+  {  glBindTexture(GL_TEXTURE_2D, PictureID);
+     checkGlError("glBindTexture old PictureID");
+  }
+
+  xy[0][0]=x;	  xy[0][1]=y;
+  xy[1][0]=x;	  xy[1][1]=y-h;
+  xy[2][0]=x+w;   xy[2][1]=y-h;
+
+  xy[3][0]=x+w;	  xy[3][1]=y;
+  xy[4][0]=x;     xy[4][1]=y;
+  xy[5][0]=x+w;   xy[5][1]=y-h;
+
+  glBindBuffer(GL_ARRAY_BUFFER, xybuffer);
+  glBufferData(GL_ARRAY_BUFFER, sizeof(xy), xy, GL_STREAM_DRAW);
+
+  glUniform1i(ImageID, 1);
+  glDrawArrays(GL_TRIANGLES, 0, 2*3);
+  glUniform1i(ImageID, 0);
+
+}
+
+
+static void GLtexture(gcache_t *g) {
+    unsigned texID;
+    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+    checkGlError("glPixelStorei");
+    glGenTextures(1, &texID);
+    checkGlError("glGenTextures");
+    glBindTexture(GL_TEXTURE_2D, texID);
+    checkGlError("glBindTexture texID");
+	
+
+    /* the first element in g->bits corresponds to the lower left pixel,
+     * the last element in g->bits to the upper right pixel. */
+  glTexImage2D(
+	    GL_TEXTURE_2D,
+            0,
+            GL_R8,
+            g->w,
+            g->h,
+            0,
+            GL_RED,
+            GL_UNSIGNED_BYTE,
+            g->bits
+  );
+  checkGlError("glTeXImage2D Glyph");
+    
+
+  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+  g->GLtexture = texID;
+  //MESSAGE("Generated GL texture %d",g->GLtexture);
+}
+
+
+
+void nativeSetPK(struct gcache_s *g)
+/* the bits, w and h fields in g are already set, but the rows needs to be DWORD aligned
+   the bitmap is already bottom up */
+{ GLtexture(g);
+}
+
+void nativeSetFreeType(struct gcache_s *g)
+/* the bits, w and h fields in g are already set, but the rows needs to be DWORD aligned
+   and converted to a bottom up DIB
+*/
+{GLtexture(g);}
+
+int round_to_pixel=1; /* makes sense only if using the native dpi, if using a multiple its of not much use*/
+double pixel_size_threshold= 72.27/150; /*round to pixel only if pixel size in pt is below threshold*/
+void nativeGlyph(double x, double dx, double y, double dy, double w, double h, struct gcache_s *g, uint8_t s)
+/* given glyph g, display g at position x,y in size w,h. x, y, w, h are given in point */
+{  
+	if (g->GLtexture == 0)
+        GLtexture(g);
+	x=x-dx;
+	y=y+h-dy;
+	if (round_to_pixel)
+	{ double pxs;
+	  pxs = 72.27/xdpi; /* pixel size in point */
+	  if (pxs>=pixel_size_threshold)
+	  { x=x/pxs;
+	    x=floor(x+0.5);
+	    x=x*pxs;
+	  }
+	  pxs = 72.27/ydpi; /* pixel size in point */
+	  if (pxs>=pixel_size_threshold)
+	  { y=y/pxs;
+	    y=floor(y+0.5);
+	    y=y*pxs;
+	  }
+	}
+  	xy[0][0]=x;	  xy[0][1]=y;
+	xy[1][0]=x;	  xy[1][1]=y-h;
+	xy[2][0]=x+w;     xy[2][1]=y-h;
+
+	xy[3][0]=x+w;	  xy[3][1]=y;
+	xy[4][0]=x;       xy[4][1]=y;
+	xy[5][0]=x+w;     xy[5][1]=y-h;
+
+    glBindTexture(GL_TEXTURE_2D, g->GLtexture);
+    checkGlError("glBindTexture g->GLtexture");
+    
+	if (s!=last_style)
+	{ if (s&FOCUS_BIT)
+	      glUniform3f(FGcolorID, 0.0, 1.0,0.0); 
+	  else if (s&MARK_BIT)
+ 	      glUniform3f(FGcolorID, 1.0, 0.0,0.0); 
+	  else if (s&LINK_BIT)
+ 	      glUniform3f(FGcolorID, 0.0, 0.0,1.0); 
+	  else
+  	      glUniform3f(FGcolorID, curfr, curfg,curfb);
+	  last_style=s;
+	}
+    glBindBuffer(GL_ARRAY_BUFFER, xybuffer);
+    glBufferData(GL_ARRAY_BUFFER, sizeof(xy), xy, GL_STREAM_DRAW);
+    glDrawArrays(GL_TRIANGLES, 0, 2*3);
+    //LOG("nativeGlyph %f@%f %fx%f Done\n",x,y,w,h);
+}
+
+void nativeFreeGlyph(struct gcache_s*g)
+{    if (g->GLtexture != 0) {
+        glDeleteTextures(1, &(g->GLtexture)); // probably not needed
+        g->GLtexture = 0;
+    }
+}

Added: trunk/Build/source/texk/web2c/hitexdir/hintview/src/rendernative.h
===================================================================
--- trunk/Build/source/texk/web2c/hitexdir/hintview/src/rendernative.h	                        (rev 0)
+++ trunk/Build/source/texk/web2c/hitexdir/hintview/src/rendernative.h	2022-01-19 13:28:43 UTC (rev 61658)
@@ -0,0 +1,52 @@
+/*376:*/
+#line 7624 "hint.w"
+
+#ifndef _RENDERNATIVE_H
+#define _RENDERNATIVE_H
+
+/*328:*/
+#line 6556 "hint.w"
+
+extern void nativeInit(void);
+extern void nativeClear(void);
+/*:328*//*329:*/
+#line 6563 "hint.w"
+
+extern void nativeSetSize(int px_h,int px_v,double xdpi,double ydpi);
+/*:329*//*330:*/
+#line 6568 "hint.w"
+
+extern void nativeSetDark(int dark);
+/*:330*//*331:*/
+#line 6573 "hint.w"
+
+extern void nativeBlank(void);
+/*:331*//*332:*/
+#line 6583 "hint.w"
+
+typedef struct gcache_s*gcache_s_ptr;
+
+extern void nativeGlyph(double x,double dx,double y,double dy,double w,double h,struct gcache_s*g,uint8_t s);
+/*:332*//*333:*/
+#line 6594 "hint.w"
+
+void nativeRule(double x,double y,double w,double h);
+/*:333*//*334:*/
+#line 6600 "hint.w"
+
+void nativeImage(double x,double y,double w,double h,unsigned char*istart,unsigned char*iend);
+/*:334*//*335:*/
+#line 6606 "hint.w"
+
+extern void nativeSetPK(struct gcache_s*g);
+extern void nativeSetFreeType(struct gcache_s*g);
+/*:335*//*336:*/
+#line 6613 "hint.w"
+
+void nativeFreeGlyph(struct gcache_s*g);
+/*:336*/
+#line 7628 "hint.w"
+
+
+#endif
+/*:376*/

Added: trunk/Build/source/texk/web2c/hitexdir/hintview/src/stb_image.h
===================================================================
--- trunk/Build/source/texk/web2c/hitexdir/hintview/src/stb_image.h	                        (rev 0)
+++ trunk/Build/source/texk/web2c/hitexdir/hintview/src/stb_image.h	2022-01-19 13:28:43 UTC (rev 61658)
@@ -0,0 +1,7559 @@
+/* stb_image - v2.23 - public domain image loader - http://nothings.org/stb
+                                  no warranty implied; use at your own risk
+
+   Do this:
+      #define STB_IMAGE_IMPLEMENTATION
+   before you include this file in *one* C or C++ file to create the implementation.
+
+   // i.e. it should look like this:
+   #include ...
+   #include ...
+   #include ...
+   #define STB_IMAGE_IMPLEMENTATION
+   #include "stb_image.h"
+
+   You can #define STBI_ASSERT(x) before the #include to avoid using assert.h.
+   And #define STBI_MALLOC, STBI_REALLOC, and STBI_FREE to avoid using malloc,realloc,free
+
+
+   QUICK NOTES:
+      Primarily of interest to game developers and other people who can
+          avoid problematic images and only need the trivial interface
+
+      JPEG baseline & progressive (12 bpc/arithmetic not supported, same as stock IJG lib)
+      PNG 1/2/4/8/16-bit-per-channel
+
+      TGA (not sure what subset, if a subset)
+      BMP non-1bpp, non-RLE
+      PSD (composited view only, no extra channels, 8/16 bit-per-channel)
+
+      GIF (*comp always reports as 4-channel)
+      HDR (radiance rgbE format)
+      PIC (Softimage PIC)
+      PNM (PPM and PGM binary only)
+
+      Animated GIF still needs a proper API, but here's one way to do it:
+          http://gist.github.com/urraka/685d9a6340b26b830d49
+
+      - decode from memory or through FILE (define STBI_NO_STDIO to remove code)
+      - decode from arbitrary I/O callbacks
+      - SIMD acceleration on x86/x64 (SSE2) and ARM (NEON)
+
+   Full documentation under "DOCUMENTATION" below.
+
+
+LICENSE
+
+  See end of file for license information.
+
+RECENT REVISION HISTORY:
+
+      2.23  (2019-08-11) fix clang static analysis warning
+      2.22  (2019-03-04) gif fixes, fix warnings
+      2.21  (2019-02-25) fix typo in comment
+      2.20  (2019-02-07) support utf8 filenames in Windows; fix warnings and platform ifdefs 
+      2.19  (2018-02-11) fix warning
+      2.18  (2018-01-30) fix warnings
+      2.17  (2018-01-29) bugfix, 1-bit BMP, 16-bitness query, fix warnings
+      2.16  (2017-07-23) all functions have 16-bit variants; optimizations; bugfixes
+      2.15  (2017-03-18) fix png-1,2,4; all Imagenet JPGs; no runtime SSE detection on GCC
+      2.14  (2017-03-03) remove deprecated STBI_JPEG_OLD; fixes for Imagenet JPGs
+      2.13  (2016-12-04) experimental 16-bit API, only for PNG so far; fixes
+      2.12  (2016-04-02) fix typo in 2.11 PSD fix that caused crashes
+      2.11  (2016-04-02) 16-bit PNGS; enable SSE2 in non-gcc x64
+                         RGB-format JPEG; remove white matting in PSD;
+                         allocate large structures on the stack;
+                         correct channel count for PNG & BMP
+      2.10  (2016-01-22) avoid warning introduced in 2.09
+      2.09  (2016-01-16) 16-bit TGA; comments in PNM files; STBI_REALLOC_SIZED
+
+   See end of file for full revision history.
+
+
+ ============================    Contributors    =========================
+
+ Image formats                          Extensions, features
+    Sean Barrett (jpeg, png, bmp)          Jetro Lauha (stbi_info)
+    Nicolas Schulz (hdr, psd)              Martin "SpartanJ" Golini (stbi_info)
+    Jonathan Dummer (tga)                  James "moose2000" Brown (iPhone PNG)
+    Jean-Marc Lienher (gif)                Ben "Disch" Wenger (io callbacks)
+    Tom Seddon (pic)                       Omar Cornut (1/2/4-bit PNG)
+    Thatcher Ulrich (psd)                  Nicolas Guillemot (vertical flip)
+    Ken Miller (pgm, ppm)                  Richard Mitton (16-bit PSD)
+    github:urraka (animated gif)           Junggon Kim (PNM comments)
+    Christopher Forseth (animated gif)     Daniel Gibson (16-bit TGA)
+                                           socks-the-fox (16-bit PNG)
+                                           Jeremy Sawicki (handle all ImageNet JPGs)
+ Optimizations & bugfixes                  Mikhail Morozov (1-bit BMP)
+    Fabian "ryg" Giesen                    Anael Seghezzi (is-16-bit query)
+    Arseny Kapoulkine
+    John-Mark Allen
+    Carmelo J Fdez-Aguera
+
+ Bug & warning fixes
+    Marc LeBlanc            David Woo          Guillaume George   Martins Mozeiko
+    Christpher Lloyd        Jerry Jansson      Joseph Thomson     Phil Jordan
+    Dave Moore              Roy Eltham         Hayaki Saito       Nathan Reed
+    Won Chun                Luke Graham        Johan Duparc       Nick Verigakis
+    the Horde3D community   Thomas Ruf         Ronny Chevalier    github:rlyeh
+    Janez Zemva             John Bartholomew   Michal Cichon      github:romigrou
+    Jonathan Blow           Ken Hamada         Tero Hanninen      github:svdijk
+    Laurent Gomila          Cort Stratton      Sergio Gonzalez    github:snagar
+    Aruelien Pocheville     Thibault Reuille   Cass Everitt       github:Zelex
+    Ryamond Barbiero        Paul Du Bois       Engin Manap        github:grim210
+    Aldo Culquicondor       Philipp Wiesemann  Dale Weiler        github:sammyhw
+    Oriol Ferrer Mesia      Josh Tobin         Matthew Gregan     github:phprus
+    Julian Raschke          Gregory Mullen     Baldur Karlsson    github:poppolopoppo
+    Christian Floisand      Kevin Schmidt      JR Smith           github:darealshinji
+    Blazej Dariusz Roszkowski                                     github:Michaelangel007
+*/
+
+#ifndef STBI_INCLUDE_STB_IMAGE_H
+#define STBI_INCLUDE_STB_IMAGE_H
+
+// DOCUMENTATION
+//
+// Limitations:
+//    - no 12-bit-per-channel JPEG
+//    - no JPEGs with arithmetic coding
+//    - GIF always returns *comp=4
+//
+// Basic usage (see HDR discussion below for HDR usage):
+//    int x,y,n;
+//    unsigned char *data = stbi_load(filename, &x, &y, &n, 0);
+//    // ... process data if not NULL ...
+//    // ... x = width, y = height, n = # 8-bit components per pixel ...
+//    // ... replace '0' with '1'..'4' to force that many components per pixel
+//    // ... but 'n' will always be the number that it would have been if you said 0
+//    stbi_image_free(data)
+//
+// Standard parameters:
+//    int *x                 -- outputs image width in pixels
+//    int *y                 -- outputs image height in pixels
+//    int *channels_in_file  -- outputs # of image components in image file
+//    int desired_channels   -- if non-zero, # of image components requested in result
+//
+// The return value from an image loader is an 'unsigned char *' which points
+// to the pixel data, or NULL on an allocation failure or if the image is
+// corrupt or invalid. The pixel data consists of *y scanlines of *x pixels,
+// with each pixel consisting of N interleaved 8-bit components; the first
+// pixel pointed to is top-left-most in the image. There is no padding between
+// image scanlines or between pixels, regardless of format. The number of
+// components N is 'desired_channels' if desired_channels is non-zero, or
+// *channels_in_file otherwise. If desired_channels is non-zero,
+// *channels_in_file has the number of components that _would_ have been
+// output otherwise. E.g. if you set desired_channels to 4, you will always
+// get RGBA output, but you can check *channels_in_file to see if it's trivially
+// opaque because e.g. there were only 3 channels in the source image.
+//
+// An output image with N components has the following components interleaved
+// in this order in each pixel:
+//
+//     N=#comp     components
+//       1           grey
+//       2           grey, alpha
+//       3           red, green, blue
+//       4           red, green, blue, alpha
+//
+// If image loading fails for any reason, the return value will be NULL,
+// and *x, *y, *channels_in_file will be unchanged. The function
+// stbi_failure_reason() can be queried for an extremely brief, end-user
+// unfriendly explanation of why the load failed. Define STBI_NO_FAILURE_STRINGS
+// to avoid compiling these strings at all, and STBI_FAILURE_USERMSG to get slightly
+// more user-friendly ones.
+//
+// Paletted PNG, BMP, GIF, and PIC images are automatically depalettized.
+//
+// ===========================================================================
+//
+// UNICODE:
+//
+//   If compiling for Windows and you wish to use Unicode filenames, compile
+//   with
+//       #define STBI_WINDOWS_UTF8
+//   and pass utf8-encoded filenames. Call stbi_convert_wchar_to_utf8 to convert
+//   Windows wchar_t filenames to utf8.
+//
+// ===========================================================================
+//
+// Philosophy
+//
+// stb libraries are designed with the following priorities:
+//
+//    1. easy to use
+//    2. easy to maintain
+//    3. good performance
+//
+// Sometimes I let "good performance" creep up in priority over "easy to maintain",
+// and for best performance I may provide less-easy-to-use APIs that give higher
+// performance, in addition to the easy-to-use ones. Nevertheless, it's important
+// to keep in mind that from the standpoint of you, a client of this library,
+// all you care about is #1 and #3, and stb libraries DO NOT emphasize #3 above all.
+//
+// Some secondary priorities arise directly from the first two, some of which
+// provide more explicit reasons why performance can't be emphasized.
+//
+//    - Portable ("ease of use")
+//    - Small source code footprint ("easy to maintain")
+//    - No dependencies ("ease of use")
+//
+// ===========================================================================
+//
+// I/O callbacks
+//
+// I/O callbacks allow you to read from arbitrary sources, like packaged
+// files or some other source. Data read from callbacks are processed
+// through a small internal buffer (currently 128 bytes) to try to reduce
+// overhead.
+//
+// The three functions you must define are "read" (reads some bytes of data),
+// "skip" (skips some bytes of data), "eof" (reports if the stream is at the end).
+//
+// ===========================================================================
+//
+// SIMD support
+//
+// The JPEG decoder will try to automatically use SIMD kernels on x86 when
+// supported by the compiler. For ARM Neon support, you must explicitly
+// request it.
+//
+// (The old do-it-yourself SIMD API is no longer supported in the current
+// code.)
+//
+// On x86, SSE2 will automatically be used when available based on a run-time
+// test; if not, the generic C versions are used as a fall-back. On ARM targets,
+// the typical path is to have separate builds for NEON and non-NEON devices
+// (at least this is true for iOS and Android). Therefore, the NEON support is
+// toggled by a build flag: define STBI_NEON to get NEON loops.
+//
+// If for some reason you do not want to use any of SIMD code, or if
+// you have issues compiling it, you can disable it entirely by
+// defining STBI_NO_SIMD.
+//
+// ===========================================================================
+//
+// HDR image support   (disable by defining STBI_NO_HDR)
+//
+// stb_image supports loading HDR images in general, and currently the Radiance
+// .HDR file format specifically. You can still load any file through the existing
+// interface; if you attempt to load an HDR file, it will be automatically remapped
+// to LDR, assuming gamma 2.2 and an arbitrary scale factor defaulting to 1;
+// both of these constants can be reconfigured through this interface:
+//
+//     stbi_hdr_to_ldr_gamma(2.2f);
+//     stbi_hdr_to_ldr_scale(1.0f);
+//
+// (note, do not use _inverse_ constants; stbi_image will invert them
+// appropriately).
+//
+// Additionally, there is a new, parallel interface for loading files as
+// (linear) floats to preserve the full dynamic range:
+//
+//    float *data = stbi_loadf(filename, &x, &y, &n, 0);
+//
+// If you load LDR images through this interface, those images will
+// be promoted to floating point values, run through the inverse of
+// constants corresponding to the above:
+//
+//     stbi_ldr_to_hdr_scale(1.0f);
+//     stbi_ldr_to_hdr_gamma(2.2f);
+//
+// Finally, given a filename (or an open file or memory block--see header
+// file for details) containing image data, you can query for the "most
+// appropriate" interface to use (that is, whether the image is HDR or
+// not), using:
+//
+//     stbi_is_hdr(char *filename);
+//
+// ===========================================================================
+//
+// iPhone PNG support:
+//
+// By default we convert iphone-formatted PNGs back to RGB, even though
+// they are internally encoded differently. You can disable this conversion
+// by calling stbi_convert_iphone_png_to_rgb(0), in which case
+// you will always just get the native iphone "format" through (which
+// is BGR stored in RGB).
+//
+// Call stbi_set_unpremultiply_on_load(1) as well to force a divide per
+// pixel to remove any premultiplied alpha *only* if the image file explicitly
+// says there's premultiplied data (currently only happens in iPhone images,
+// and only if iPhone convert-to-rgb processing is on).
+//
+// ===========================================================================
+//
+// ADDITIONAL CONFIGURATION
+//
+//  - You can suppress implementation of any of the decoders to reduce
+//    your code footprint by #defining one or more of the following
+//    symbols before creating the implementation.
+//
+//        STBI_NO_JPEG
+//        STBI_NO_PNG
+//        STBI_NO_BMP
+//        STBI_NO_PSD
+//        STBI_NO_TGA
+//        STBI_NO_GIF
+//        STBI_NO_HDR
+//        STBI_NO_PIC
+//        STBI_NO_PNM   (.ppm and .pgm)
+//
+//  - You can request *only* certain decoders and suppress all other ones
+//    (this will be more forward-compatible, as addition of new decoders
+//    doesn't require you to disable them explicitly):
+//
+//        STBI_ONLY_JPEG
+//        STBI_ONLY_PNG
+//        STBI_ONLY_BMP
+//        STBI_ONLY_PSD
+//        STBI_ONLY_TGA
+//        STBI_ONLY_GIF
+//        STBI_ONLY_HDR
+//        STBI_ONLY_PIC
+//        STBI_ONLY_PNM   (.ppm and .pgm)
+//
+//   - If you use STBI_NO_PNG (or _ONLY_ without PNG), and you still
+//     want the zlib decoder to be available, #define STBI_SUPPORT_ZLIB
+//
+
+
+#ifndef STBI_NO_STDIO
+#include <stdio.h>
+#endif // STBI_NO_STDIO
+
+#define STBI_VERSION 1
+
+enum
+{
+   STBI_default = 0, // only used for desired_channels
+
+   STBI_grey       = 1,
+   STBI_grey_alpha = 2,
+   STBI_rgb        = 3,
+   STBI_rgb_alpha  = 4
+};
+
+#include <stdlib.h>
+typedef unsigned char stbi_uc;
+typedef unsigned short stbi_us;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef STBIDEF
+#ifdef STB_IMAGE_STATIC
+#define STBIDEF static
+#else
+#define STBIDEF extern
+#endif
+#endif
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// PRIMARY API - works on images of any type
+//
+
+//
+// load image by filename, open file, or memory buffer
+//
+
+typedef struct
+{
+   int      (*read)  (void *user,char *data,int size);   // fill 'data' with 'size' bytes.  return number of bytes actually read
+   void     (*skip)  (void *user,int n);                 // skip the next 'n' bytes, or 'unget' the last -n bytes if negative
+   int      (*eof)   (void *user);                       // returns nonzero if we are at end of file/data
+} stbi_io_callbacks;
+
+////////////////////////////////////
+//
+// 8-bits-per-channel interface
+//
+
+STBIDEF stbi_uc *stbi_load_from_memory   (stbi_uc           const *buffer, int len   , int *x, int *y, int *channels_in_file, int desired_channels);
+STBIDEF stbi_uc *stbi_load_from_callbacks(stbi_io_callbacks const *clbk  , void *user, int *x, int *y, int *channels_in_file, int desired_channels);
+
+#ifndef STBI_NO_STDIO
+STBIDEF stbi_uc *stbi_load            (char const *filename, int *x, int *y, int *channels_in_file, int desired_channels);
+STBIDEF stbi_uc *stbi_load_from_file  (FILE *f, int *x, int *y, int *channels_in_file, int desired_channels);
+// for stbi_load_from_file, file pointer is left pointing immediately after image
+#endif
+
+#ifndef STBI_NO_GIF
+STBIDEF stbi_uc *stbi_load_gif_from_memory(stbi_uc const *buffer, int len, int **delays, int *x, int *y, int *z, int *comp, int req_comp);
+#endif
+
+#ifdef STBI_WINDOWS_UTF8
+STBIDEF int stbi_convert_wchar_to_utf8(char *buffer, size_t bufferlen, const wchar_t* input);
+#endif
+
+////////////////////////////////////
+//
+// 16-bits-per-channel interface
+//
+
+STBIDEF stbi_us *stbi_load_16_from_memory   (stbi_uc const *buffer, int len, int *x, int *y, int *channels_in_file, int desired_channels);
+STBIDEF stbi_us *stbi_load_16_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *channels_in_file, int desired_channels);
+
+#ifndef STBI_NO_STDIO
+STBIDEF stbi_us *stbi_load_16          (char const *filename, int *x, int *y, int *channels_in_file, int desired_channels);
+STBIDEF stbi_us *stbi_load_from_file_16(FILE *f, int *x, int *y, int *channels_in_file, int desired_channels);
+#endif
+
+////////////////////////////////////
+//
+// float-per-channel interface
+//
+#ifndef STBI_NO_LINEAR
+   STBIDEF float *stbi_loadf_from_memory     (stbi_uc const *buffer, int len, int *x, int *y, int *channels_in_file, int desired_channels);
+   STBIDEF float *stbi_loadf_from_callbacks  (stbi_io_callbacks const *clbk, void *user, int *x, int *y,  int *channels_in_file, int desired_channels);
+
+   #ifndef STBI_NO_STDIO
+   STBIDEF float *stbi_loadf            (char const *filename, int *x, int *y, int *channels_in_file, int desired_channels);
+   STBIDEF float *stbi_loadf_from_file  (FILE *f, int *x, int *y, int *channels_in_file, int desired_channels);
+   #endif
+#endif
+
+#ifndef STBI_NO_HDR
+   STBIDEF void   stbi_hdr_to_ldr_gamma(float gamma);
+   STBIDEF void   stbi_hdr_to_ldr_scale(float scale);
+#endif // STBI_NO_HDR
+
+#ifndef STBI_NO_LINEAR
+   STBIDEF void   stbi_ldr_to_hdr_gamma(float gamma);
+   STBIDEF void   stbi_ldr_to_hdr_scale(float scale);
+#endif // STBI_NO_LINEAR
+
+// stbi_is_hdr is always defined, but always returns false if STBI_NO_HDR
+STBIDEF int    stbi_is_hdr_from_callbacks(stbi_io_callbacks const *clbk, void *user);
+STBIDEF int    stbi_is_hdr_from_memory(stbi_uc const *buffer, int len);
+#ifndef STBI_NO_STDIO
+STBIDEF int      stbi_is_hdr          (char const *filename);
+STBIDEF int      stbi_is_hdr_from_file(FILE *f);
+#endif // STBI_NO_STDIO
+
+
+// get a VERY brief reason for failure
+// NOT THREADSAFE
+STBIDEF const char *stbi_failure_reason  (void);
+
+// free the loaded image -- this is just free()
+STBIDEF void     stbi_image_free      (void *retval_from_stbi_load);
+
+// get image dimensions & components without fully decoding
+STBIDEF int      stbi_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp);
+STBIDEF int      stbi_info_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp);
+STBIDEF int      stbi_is_16_bit_from_memory(stbi_uc const *buffer, int len);
+STBIDEF int      stbi_is_16_bit_from_callbacks(stbi_io_callbacks const *clbk, void *user);
+
+#ifndef STBI_NO_STDIO
+STBIDEF int      stbi_info               (char const *filename,     int *x, int *y, int *comp);
+STBIDEF int      stbi_info_from_file     (FILE *f,                  int *x, int *y, int *comp);
+STBIDEF int      stbi_is_16_bit          (char const *filename);
+STBIDEF int      stbi_is_16_bit_from_file(FILE *f);
+#endif
+
+
+
+// for image formats that explicitly notate that they have premultiplied alpha,
+// we just return the colors as stored in the file. set this flag to force
+// unpremultiplication. results are undefined if the unpremultiply overflow.
+STBIDEF void stbi_set_unpremultiply_on_load(int flag_true_if_should_unpremultiply);
+
+// indicate whether we should process iphone images back to canonical format,
+// or just pass them through "as-is"
+STBIDEF void stbi_convert_iphone_png_to_rgb(int flag_true_if_should_convert);
+
+// flip the image vertically, so the first pixel in the output array is the bottom left
+STBIDEF void stbi_set_flip_vertically_on_load(int flag_true_if_should_flip);
+
+// ZLIB client - used by PNG, available for other purposes
+
+STBIDEF char *stbi_zlib_decode_malloc_guesssize(const char *buffer, int len, int initial_size, int *outlen);
+STBIDEF char *stbi_zlib_decode_malloc_guesssize_headerflag(const char *buffer, int len, int initial_size, int *outlen, int parse_header);
+STBIDEF char *stbi_zlib_decode_malloc(const char *buffer, int len, int *outlen);
+STBIDEF int   stbi_zlib_decode_buffer(char *obuffer, int olen, const char *ibuffer, int ilen);
+
+STBIDEF char *stbi_zlib_decode_noheader_malloc(const char *buffer, int len, int *outlen);
+STBIDEF int   stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const char *ibuffer, int ilen);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+//
+//
+////   end header file   /////////////////////////////////////////////////////
+#endif // STBI_INCLUDE_STB_IMAGE_H
+
+#ifdef STB_IMAGE_IMPLEMENTATION
+
+#if defined(STBI_ONLY_JPEG) || defined(STBI_ONLY_PNG) || defined(STBI_ONLY_BMP) \
+  || defined(STBI_ONLY_TGA) || defined(STBI_ONLY_GIF) || defined(STBI_ONLY_PSD) \
+  || defined(STBI_ONLY_HDR) || defined(STBI_ONLY_PIC) || defined(STBI_ONLY_PNM) \
+  || defined(STBI_ONLY_ZLIB)
+   #ifndef STBI_ONLY_JPEG
+   #define STBI_NO_JPEG
+   #endif
+   #ifndef STBI_ONLY_PNG
+   #define STBI_NO_PNG
+   #endif
+   #ifndef STBI_ONLY_BMP
+   #define STBI_NO_BMP
+   #endif
+   #ifndef STBI_ONLY_PSD
+   #define STBI_NO_PSD
+   #endif
+   #ifndef STBI_ONLY_TGA
+   #define STBI_NO_TGA
+   #endif
+   #ifndef STBI_ONLY_GIF
+   #define STBI_NO_GIF
+   #endif
+   #ifndef STBI_ONLY_HDR
+   #define STBI_NO_HDR
+   #endif
+   #ifndef STBI_ONLY_PIC
+   #define STBI_NO_PIC
+   #endif
+   #ifndef STBI_ONLY_PNM
+   #define STBI_NO_PNM
+   #endif
+#endif
+
+#if defined(STBI_NO_PNG) && !defined(STBI_SUPPORT_ZLIB) && !defined(STBI_NO_ZLIB)
+#define STBI_NO_ZLIB
+#endif
+
+
+#include <stdarg.h>
+#include <stddef.h> // ptrdiff_t on osx
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+
+#if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR)
+#include <math.h>  // ldexp, pow
+#endif
+
+#ifndef STBI_NO_STDIO
+#include <stdio.h>
+#endif
+
+#ifndef STBI_ASSERT
+#include <assert.h>
+#define STBI_ASSERT(x) assert(x)
+#endif
+
+#ifdef __cplusplus
+#define STBI_EXTERN extern "C"
+#else
+#define STBI_EXTERN extern
+#endif
+
+
+#ifndef _MSC_VER
+   #ifdef __cplusplus
+   #define stbi_inline inline
+   #else
+   #define stbi_inline
+   #endif
+#else
+   #define stbi_inline __forceinline
+#endif
+
+
+#ifdef _MSC_VER
+typedef unsigned short stbi__uint16;
+typedef   signed short stbi__int16;
+typedef unsigned int   stbi__uint32;
+typedef   signed int   stbi__int32;
+#else
+#include <stdint.h>
+typedef uint16_t stbi__uint16;
+typedef int16_t  stbi__int16;
+typedef uint32_t stbi__uint32;
+typedef int32_t  stbi__int32;
+#endif
+
+// should produce compiler error if size is wrong
+typedef unsigned char validate_uint32[sizeof(stbi__uint32)==4 ? 1 : -1];
+
+#ifdef _MSC_VER
+#define STBI_NOTUSED(v)  (void)(v)
+#else
+#define STBI_NOTUSED(v)  (void)sizeof(v)
+#endif
+
+#ifdef _MSC_VER
+#define STBI_HAS_LROTL
+#endif
+
+#ifdef STBI_HAS_LROTL
+   #define stbi_lrot(x,y)  _lrotl(x,y)
+#else
+   #define stbi_lrot(x,y)  (((x) << (y)) | ((x) >> (32 - (y))))
+#endif
+
+#if defined(STBI_MALLOC) && defined(STBI_FREE) && (defined(STBI_REALLOC) || defined(STBI_REALLOC_SIZED))
+// ok
+#elif !defined(STBI_MALLOC) && !defined(STBI_FREE) && !defined(STBI_REALLOC) && !defined(STBI_REALLOC_SIZED)
+// ok
+#else
+#error "Must define all or none of STBI_MALLOC, STBI_FREE, and STBI_REALLOC (or STBI_REALLOC_SIZED)."
+#endif
+
+#ifndef STBI_MALLOC
+#define STBI_MALLOC(sz)           malloc(sz)
+#define STBI_REALLOC(p,newsz)     realloc(p,newsz)
+#define STBI_FREE(p)              free(p)
+#endif
+
+#ifndef STBI_REALLOC_SIZED
+#define STBI_REALLOC_SIZED(p,oldsz,newsz) STBI_REALLOC(p,newsz)
+#endif
+
+// x86/x64 detection
+#if defined(__x86_64__) || defined(_M_X64)
+#define STBI__X64_TARGET
+#elif defined(__i386) || defined(_M_IX86)
+#define STBI__X86_TARGET
+#endif
+
+#if defined(__GNUC__) && defined(STBI__X86_TARGET) && !defined(__SSE2__) && !defined(STBI_NO_SIMD)
+// gcc doesn't support sse2 intrinsics unless you compile with -msse2,
+// which in turn means it gets to use SSE2 everywhere. This is unfortunate,
+// but previous attempts to provide the SSE2 functions with runtime
+// detection caused numerous issues. The way architecture extensions are
+// exposed in GCC/Clang is, sadly, not really suited for one-file libs.
+// New behavior: if compiled with -msse2, we use SSE2 without any
+// detection; if not, we don't use it at all.
+#define STBI_NO_SIMD
+#endif
+
+#if defined(__MINGW32__) && defined(STBI__X86_TARGET) && !defined(STBI_MINGW_ENABLE_SSE2) && !defined(STBI_NO_SIMD)
+// Note that __MINGW32__ doesn't actually mean 32-bit, so we have to avoid STBI__X64_TARGET
+//
+// 32-bit MinGW wants ESP to be 16-byte aligned, but this is not in the
+// Windows ABI and VC++ as well as Windows DLLs don't maintain that invariant.
+// As a result, enabling SSE2 on 32-bit MinGW is dangerous when not
+// simultaneously enabling "-mstackrealign".
+//
+// See https://github.com/nothings/stb/issues/81 for more information.
+//
+// So default to no SSE2 on 32-bit MinGW. If you've read this far and added
+// -mstackrealign to your build settings, feel free to #define STBI_MINGW_ENABLE_SSE2.
+#define STBI_NO_SIMD
+#endif
+
+#if !defined(STBI_NO_SIMD) && (defined(STBI__X86_TARGET) || defined(STBI__X64_TARGET))
+#define STBI_SSE2
+#include <emmintrin.h>
+
+#ifdef _MSC_VER
+
+#if _MSC_VER >= 1400  // not VC6
+#include <intrin.h> // __cpuid
+static int stbi__cpuid3(void)
+{
+   int info[4];
+   __cpuid(info,1);
+   return info[3];
+}
+#else
+static int stbi__cpuid3(void)
+{
+   int res;
+   __asm {
+      mov  eax,1
+      cpuid
+      mov  res,edx
+   }
+   return res;
+}
+#endif
+
+#define STBI_SIMD_ALIGN(type, name) __declspec(align(16)) type name
+
+#if !defined(STBI_NO_JPEG) && defined(STBI_SSE2)
+static int stbi__sse2_available(void)
+{
+   int info3 = stbi__cpuid3();
+   return ((info3 >> 26) & 1) != 0;
+}
+#endif
+
+#else // assume GCC-style if not VC++
+#define STBI_SIMD_ALIGN(type, name) type name __attribute__((aligned(16)))
+
+#if !defined(STBI_NO_JPEG) && defined(STBI_SSE2)
+static int stbi__sse2_available(void)
+{
+   // If we're even attempting to compile this on GCC/Clang, that means
+   // -msse2 is on, which means the compiler is allowed to use SSE2
+   // instructions at will, and so are we.
+   return 1;
+}
+#endif
+
+#endif
+#endif
+
+// ARM NEON
+#if defined(STBI_NO_SIMD) && defined(STBI_NEON)
+#undef STBI_NEON
+#endif
+
+#ifdef STBI_NEON
+#include <arm_neon.h>
+// assume GCC or Clang on ARM targets
+#define STBI_SIMD_ALIGN(type, name) type name __attribute__((aligned(16)))
+#endif
+
+#ifndef STBI_SIMD_ALIGN
+#define STBI_SIMD_ALIGN(type, name) type name
+#endif
+
+///////////////////////////////////////////////
+//
+//  stbi__context struct and start_xxx functions
+
+// stbi__context structure is our basic context used by all images, so it
+// contains all the IO context, plus some basic image information
+typedef struct
+{
+   stbi__uint32 img_x, img_y;
+   int img_n, img_out_n;
+
+   stbi_io_callbacks io;
+   void *io_user_data;
+
+   int read_from_callbacks;
+   int buflen;
+   stbi_uc buffer_start[128];
+
+   stbi_uc *img_buffer, *img_buffer_end;
+   stbi_uc *img_buffer_original, *img_buffer_original_end;
+} stbi__context;
+
+
+static void stbi__refill_buffer(stbi__context *s);
+
+// initialize a memory-decode context
+static void stbi__start_mem(stbi__context *s, stbi_uc const *buffer, int len)
+{
+   s->io.read = NULL;
+   s->read_from_callbacks = 0;
+   s->img_buffer = s->img_buffer_original = (stbi_uc *) buffer;
+   s->img_buffer_end = s->img_buffer_original_end = (stbi_uc *) buffer+len;
+}
+
+// initialize a callback-based context
+static void stbi__start_callbacks(stbi__context *s, stbi_io_callbacks *c, void *user)
+{
+   s->io = *c;
+   s->io_user_data = user;
+   s->buflen = sizeof(s->buffer_start);
+   s->read_from_callbacks = 1;
+   s->img_buffer_original = s->buffer_start;
+   stbi__refill_buffer(s);
+   s->img_buffer_original_end = s->img_buffer_end;
+}
+
+#ifndef STBI_NO_STDIO
+
+static int stbi__stdio_read(void *user, char *data, int size)
+{
+   return (int) fread(data,1,size,(FILE*) user);
+}
+
+static void stbi__stdio_skip(void *user, int n)
+{
+   fseek((FILE*) user, n, SEEK_CUR);
+}
+
+static int stbi__stdio_eof(void *user)
+{
+   return feof((FILE*) user);
+}
+
+static stbi_io_callbacks stbi__stdio_callbacks =
+{
+   stbi__stdio_read,
+   stbi__stdio_skip,
+   stbi__stdio_eof,
+};
+
+static void stbi__start_file(stbi__context *s, FILE *f)
+{
+   stbi__start_callbacks(s, &stbi__stdio_callbacks, (void *) f);
+}
+
+//static void stop_file(stbi__context *s) { }
+
+#endif // !STBI_NO_STDIO
+
+static void stbi__rewind(stbi__context *s)
+{
+   // conceptually rewind SHOULD rewind to the beginning of the stream,
+   // but we just rewind to the beginning of the initial buffer, because
+   // we only use it after doing 'test', which only ever looks at at most 92 bytes
+   s->img_buffer = s->img_buffer_original;
+   s->img_buffer_end = s->img_buffer_original_end;
+}
+
+enum
+{
+   STBI_ORDER_RGB,
+   STBI_ORDER_BGR
+};
+
+typedef struct
+{
+   int bits_per_channel;
+   int num_channels;
+   int channel_order;
+} stbi__result_info;
+
+#ifndef STBI_NO_JPEG
+static int      stbi__jpeg_test(stbi__context *s);
+static void    *stbi__jpeg_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri);
+static int      stbi__jpeg_info(stbi__context *s, int *x, int *y, int *comp);
+#endif
+
+#ifndef STBI_NO_PNG
+static int      stbi__png_test(stbi__context *s);
+static void    *stbi__png_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri);
+static int      stbi__png_info(stbi__context *s, int *x, int *y, int *comp);
+static int      stbi__png_is16(stbi__context *s);
+#endif
+
+#ifndef STBI_NO_BMP
+static int      stbi__bmp_test(stbi__context *s);
+static void    *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri);
+static int      stbi__bmp_info(stbi__context *s, int *x, int *y, int *comp);
+#endif
+
+#ifndef STBI_NO_TGA
+static int      stbi__tga_test(stbi__context *s);
+static void    *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri);
+static int      stbi__tga_info(stbi__context *s, int *x, int *y, int *comp);
+#endif
+
+#ifndef STBI_NO_PSD
+static int      stbi__psd_test(stbi__context *s);
+static void    *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri, int bpc);
+static int      stbi__psd_info(stbi__context *s, int *x, int *y, int *comp);
+static int      stbi__psd_is16(stbi__context *s);
+#endif
+
+#ifndef STBI_NO_HDR
+static int      stbi__hdr_test(stbi__context *s);
+static float   *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri);
+static int      stbi__hdr_info(stbi__context *s, int *x, int *y, int *comp);
+#endif
+
+#ifndef STBI_NO_PIC
+static int      stbi__pic_test(stbi__context *s);
+static void    *stbi__pic_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri);
+static int      stbi__pic_info(stbi__context *s, int *x, int *y, int *comp);
+#endif
+
+#ifndef STBI_NO_GIF
+static int      stbi__gif_test(stbi__context *s);
+static void    *stbi__gif_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri);
+static void    *stbi__load_gif_main(stbi__context *s, int **delays, int *x, int *y, int *z, int *comp, int req_comp);
+static int      stbi__gif_info(stbi__context *s, int *x, int *y, int *comp);
+#endif
+
+#ifndef STBI_NO_PNM
+static int      stbi__pnm_test(stbi__context *s);
+static void    *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri);
+static int      stbi__pnm_info(stbi__context *s, int *x, int *y, int *comp);
+#endif
+
+// this is not threadsafe
+static const char *stbi__g_failure_reason;
+
+STBIDEF const char *stbi_failure_reason(void)
+{
+   return stbi__g_failure_reason;
+}
+
+static int stbi__err(const char *str)
+{
+   stbi__g_failure_reason = str;
+   return 0;
+}
+
+static void *stbi__malloc(size_t size)
+{
+    return STBI_MALLOC(size);
+}
+
+// stb_image uses ints pervasively, including for offset calculations.
+// therefore the largest decoded image size we can support with the
+// current code, even on 64-bit targets, is INT_MAX. this is not a
+// significant limitation for the intended use case.
+//
+// we do, however, need to make sure our size calculations don't
+// overflow. hence a few helper functions for size calculations that
+// multiply integers together, making sure that they're non-negative
+// and no overflow occurs.
+
+// return 1 if the sum is valid, 0 on overflow.
+// negative terms are considered invalid.
+static int stbi__addsizes_valid(int a, int b)
+{
+   if (b < 0) return 0;
+   // now 0 <= b <= INT_MAX, hence also
+   // 0 <= INT_MAX - b <= INTMAX.
+   // And "a + b <= INT_MAX" (which might overflow) is the
+   // same as a <= INT_MAX - b (no overflow)
+   return a <= INT_MAX - b;
+}
+
+// returns 1 if the product is valid, 0 on overflow.
+// negative factors are considered invalid.
+static int stbi__mul2sizes_valid(int a, int b)
+{
+   if (a < 0 || b < 0) return 0;
+   if (b == 0) return 1; // mul-by-0 is always safe
+   // portable way to check for no overflows in a*b
+   return a <= INT_MAX/b;
+}
+
+// returns 1 if "a*b + add" has no negative terms/factors and doesn't overflow
+static int stbi__mad2sizes_valid(int a, int b, int add)
+{
+   return stbi__mul2sizes_valid(a, b) && stbi__addsizes_valid(a*b, add);
+}
+
+// returns 1 if "a*b*c + add" has no negative terms/factors and doesn't overflow
+static int stbi__mad3sizes_valid(int a, int b, int c, int add)
+{
+   return stbi__mul2sizes_valid(a, b) && stbi__mul2sizes_valid(a*b, c) &&
+      stbi__addsizes_valid(a*b*c, add);
+}
+
+// returns 1 if "a*b*c*d + add" has no negative terms/factors and doesn't overflow
+#if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR)
+static int stbi__mad4sizes_valid(int a, int b, int c, int d, int add)
+{
+   return stbi__mul2sizes_valid(a, b) && stbi__mul2sizes_valid(a*b, c) &&
+      stbi__mul2sizes_valid(a*b*c, d) && stbi__addsizes_valid(a*b*c*d, add);
+}
+#endif
+
+// mallocs with size overflow checking
+static void *stbi__malloc_mad2(int a, int b, int add)
+{
+   if (!stbi__mad2sizes_valid(a, b, add)) return NULL;
+   return stbi__malloc(a*b + add);
+}
+
+static void *stbi__malloc_mad3(int a, int b, int c, int add)
+{
+   if (!stbi__mad3sizes_valid(a, b, c, add)) return NULL;
+   return stbi__malloc(a*b*c + add);
+}
+
+#if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR)
+static void *stbi__malloc_mad4(int a, int b, int c, int d, int add)
+{
+   if (!stbi__mad4sizes_valid(a, b, c, d, add)) return NULL;
+   return stbi__malloc(a*b*c*d + add);
+}
+#endif
+
+// stbi__err - error
+// stbi__errpf - error returning pointer to float
+// stbi__errpuc - error returning pointer to unsigned char
+
+#ifdef STBI_NO_FAILURE_STRINGS
+   #define stbi__err(x,y)  0
+#elif defined(STBI_FAILURE_USERMSG)
+   #define stbi__err(x,y)  stbi__err(y)
+#else
+   #define stbi__err(x,y)  stbi__err(x)
+#endif
+
+#define stbi__errpf(x,y)   ((float *)(size_t) (stbi__err(x,y)?NULL:NULL))
+#define stbi__errpuc(x,y)  ((unsigned char *)(size_t) (stbi__err(x,y)?NULL:NULL))
+
+STBIDEF void stbi_image_free(void *retval_from_stbi_load)
+{
+   STBI_FREE(retval_from_stbi_load);
+}
+
+#ifndef STBI_NO_LINEAR
+static float   *stbi__ldr_to_hdr(stbi_uc *data, int x, int y, int comp);
+#endif
+
+#ifndef STBI_NO_HDR
+static stbi_uc *stbi__hdr_to_ldr(float   *data, int x, int y, int comp);
+#endif
+
+static int stbi__vertically_flip_on_load = 0;
+
+STBIDEF void stbi_set_flip_vertically_on_load(int flag_true_if_should_flip)
+{
+    stbi__vertically_flip_on_load = flag_true_if_should_flip;
+}
+
+static void *stbi__load_main(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri, int bpc)
+{
+   memset(ri, 0, sizeof(*ri)); // make sure it's initialized if we add new fields
+   ri->bits_per_channel = 8; // default is 8 so most paths don't have to be changed
+   ri->channel_order = STBI_ORDER_RGB; // all current input & output are this, but this is here so we can add BGR order
+   ri->num_channels = 0;
+
+   #ifndef STBI_NO_JPEG
+   if (stbi__jpeg_test(s)) return stbi__jpeg_load(s,x,y,comp,req_comp, ri);
+   #endif
+   #ifndef STBI_NO_PNG
+   if (stbi__png_test(s))  return stbi__png_load(s,x,y,comp,req_comp, ri);
+   #endif
+   #ifndef STBI_NO_BMP
+   if (stbi__bmp_test(s))  return stbi__bmp_load(s,x,y,comp,req_comp, ri);
+   #endif
+   #ifndef STBI_NO_GIF
+   if (stbi__gif_test(s))  return stbi__gif_load(s,x,y,comp,req_comp, ri);
+   #endif
+   #ifndef STBI_NO_PSD
+   if (stbi__psd_test(s))  return stbi__psd_load(s,x,y,comp,req_comp, ri, bpc);
+   #endif
+   #ifndef STBI_NO_PIC
+   if (stbi__pic_test(s))  return stbi__pic_load(s,x,y,comp,req_comp, ri);
+   #endif
+   #ifndef STBI_NO_PNM
+   if (stbi__pnm_test(s))  return stbi__pnm_load(s,x,y,comp,req_comp, ri);
+   #endif
+
+   #ifndef STBI_NO_HDR
+   if (stbi__hdr_test(s)) {
+      float *hdr = stbi__hdr_load(s, x,y,comp,req_comp, ri);
+      return stbi__hdr_to_ldr(hdr, *x, *y, req_comp ? req_comp : *comp);
+   }
+   #endif
+
+   #ifndef STBI_NO_TGA
+   // test tga last because it's a crappy test!
+   if (stbi__tga_test(s))
+      return stbi__tga_load(s,x,y,comp,req_comp, ri);
+   #endif
+
+   return stbi__errpuc("unknown image type", "Image not of any known type, or corrupt");
+}
+
+static stbi_uc *stbi__convert_16_to_8(stbi__uint16 *orig, int w, int h, int channels)
+{
+   int i;
+   int img_len = w * h * channels;
+   stbi_uc *reduced;
+
+   reduced = (stbi_uc *) stbi__malloc(img_len);
+   if (reduced == NULL) return stbi__errpuc("outofmem", "Out of memory");
+
+   for (i = 0; i < img_len; ++i)
+      reduced[i] = (stbi_uc)((orig[i] >> 8) & 0xFF); // top half of each byte is sufficient approx of 16->8 bit scaling
+
+   STBI_FREE(orig);
+   return reduced;
+}
+
+static stbi__uint16 *stbi__convert_8_to_16(stbi_uc *orig, int w, int h, int channels)
+{
+   int i;
+   int img_len = w * h * channels;
+   stbi__uint16 *enlarged;
+
+   enlarged = (stbi__uint16 *) stbi__malloc(img_len*2);
+   if (enlarged == NULL) return (stbi__uint16 *) stbi__errpuc("outofmem", "Out of memory");
+
+   for (i = 0; i < img_len; ++i)
+      enlarged[i] = (stbi__uint16)((orig[i] << 8) + orig[i]); // replicate to high and low byte, maps 0->0, 255->0xffff
+
+   STBI_FREE(orig);
+   return enlarged;
+}
+
+static void stbi__vertical_flip(void *image, int w, int h, int bytes_per_pixel)
+{
+   int row;
+   size_t bytes_per_row = (size_t)w * bytes_per_pixel;
+   stbi_uc temp[2048];
+   stbi_uc *bytes = (stbi_uc *)image;
+
+   for (row = 0; row < (h>>1); row++) {
+      stbi_uc *row0 = bytes + row*bytes_per_row;
+      stbi_uc *row1 = bytes + (h - row - 1)*bytes_per_row;
+      // swap row0 with row1
+      size_t bytes_left = bytes_per_row;
+      while (bytes_left) {
+         size_t bytes_copy = (bytes_left < sizeof(temp)) ? bytes_left : sizeof(temp);
+         memcpy(temp, row0, bytes_copy);
+         memcpy(row0, row1, bytes_copy);
+         memcpy(row1, temp, bytes_copy);
+         row0 += bytes_copy;
+         row1 += bytes_copy;
+         bytes_left -= bytes_copy;
+      }
+   }
+}
+
+#ifndef STBI_NO_GIF
+static void stbi__vertical_flip_slices(void *image, int w, int h, int z, int bytes_per_pixel)
+{
+   int slice;
+   int slice_size = w * h * bytes_per_pixel;
+
+   stbi_uc *bytes = (stbi_uc *)image;
+   for (slice = 0; slice < z; ++slice) {
+      stbi__vertical_flip(bytes, w, h, bytes_per_pixel); 
+      bytes += slice_size; 
+   }
+}
+#endif
+
+static unsigned char *stbi__load_and_postprocess_8bit(stbi__context *s, int *x, int *y, int *comp, int req_comp)
+{
+   stbi__result_info ri;
+   void *result = stbi__load_main(s, x, y, comp, req_comp, &ri, 8);
+
+   if (result == NULL)
+      return NULL;
+
+   if (ri.bits_per_channel != 8) {
+      STBI_ASSERT(ri.bits_per_channel == 16);
+      result = stbi__convert_16_to_8((stbi__uint16 *) result, *x, *y, req_comp == 0 ? *comp : req_comp);
+      ri.bits_per_channel = 8;
+   }
+
+   // @TODO: move stbi__convert_format to here
+
+   if (stbi__vertically_flip_on_load) {
+      int channels = req_comp ? req_comp : *comp;
+      stbi__vertical_flip(result, *x, *y, channels * sizeof(stbi_uc));
+   }
+
+   return (unsigned char *) result;
+}
+
+static stbi__uint16 *stbi__load_and_postprocess_16bit(stbi__context *s, int *x, int *y, int *comp, int req_comp)
+{
+   stbi__result_info ri;
+   void *result = stbi__load_main(s, x, y, comp, req_comp, &ri, 16);
+
+   if (result == NULL)
+      return NULL;
+
+   if (ri.bits_per_channel != 16) {
+      STBI_ASSERT(ri.bits_per_channel == 8);
+      result = stbi__convert_8_to_16((stbi_uc *) result, *x, *y, req_comp == 0 ? *comp : req_comp);
+      ri.bits_per_channel = 16;
+   }
+
+   // @TODO: move stbi__convert_format16 to here
+   // @TODO: special case RGB-to-Y (and RGBA-to-YA) for 8-bit-to-16-bit case to keep more precision
+
+   if (stbi__vertically_flip_on_load) {
+      int channels = req_comp ? req_comp : *comp;
+      stbi__vertical_flip(result, *x, *y, channels * sizeof(stbi__uint16));
+   }
+
+   return (stbi__uint16 *) result;
+}
+
+#if !defined(STBI_NO_HDR) && !defined(STBI_NO_LINEAR)
+static void stbi__float_postprocess(float *result, int *x, int *y, int *comp, int req_comp)
+{
+   if (stbi__vertically_flip_on_load && result != NULL) {
+      int channels = req_comp ? req_comp : *comp;
+      stbi__vertical_flip(result, *x, *y, channels * sizeof(float));
+   }
+}
+#endif
+
+#ifndef STBI_NO_STDIO
+
+#if defined(_MSC_VER) && defined(STBI_WINDOWS_UTF8)
+STBI_EXTERN __declspec(dllimport) int __stdcall MultiByteToWideChar(unsigned int cp, unsigned long flags, const char *str, int cbmb, wchar_t *widestr, int cchwide);
+STBI_EXTERN __declspec(dllimport) int __stdcall WideCharToMultiByte(unsigned int cp, unsigned long flags, const wchar_t *widestr, int cchwide, char *str, int cbmb, const char *defchar, int *used_default);
+#endif
+
+#if defined(_MSC_VER) && defined(STBI_WINDOWS_UTF8)
+STBIDEF int stbi_convert_wchar_to_utf8(char *buffer, size_t bufferlen, const wchar_t* input)
+{
+	return WideCharToMultiByte(65001 /* UTF8 */, 0, input, -1, buffer, (int) bufferlen, NULL, NULL);
+}
+#endif
+
+static FILE *stbi__fopen(char const *filename, char const *mode)
+{
+   FILE *f;
+#if defined(_MSC_VER) && defined(STBI_WINDOWS_UTF8)
+   wchar_t wMode[64];
+   wchar_t wFilename[1024];
+	if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, filename, -1, wFilename, sizeof(wFilename)))
+      return 0;
+	
+	if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, mode, -1, wMode, sizeof(wMode)))
+      return 0;
+
+#if _MSC_VER >= 1400
+	if (0 != _wfopen_s(&f, wFilename, wMode))
+		f = 0;
+#else
+   f = _wfopen(wFilename, wMode);
+#endif
+
+#elif defined(_MSC_VER) && _MSC_VER >= 1400
+   if (0 != fopen_s(&f, filename, mode))
+      f=0;
+#else
+   f = fopen(filename, mode);
+#endif
+   return f;
+}
+
+
+STBIDEF stbi_uc *stbi_load(char const *filename, int *x, int *y, int *comp, int req_comp)
+{
+   FILE *f = stbi__fopen(filename, "rb");
+   unsigned char *result;
+   if (!f) return stbi__errpuc("can't fopen", "Unable to open file");
+   result = stbi_load_from_file(f,x,y,comp,req_comp);
+   fclose(f);
+   return result;
+}
+
+STBIDEF stbi_uc *stbi_load_from_file(FILE *f, int *x, int *y, int *comp, int req_comp)
+{
+   unsigned char *result;
+   stbi__context s;
+   stbi__start_file(&s,f);
+   result = stbi__load_and_postprocess_8bit(&s,x,y,comp,req_comp);
+   if (result) {
+      // need to 'unget' all the characters in the IO buffer
+      fseek(f, - (int) (s.img_buffer_end - s.img_buffer), SEEK_CUR);
+   }
+   return result;
+}
+
+STBIDEF stbi__uint16 *stbi_load_from_file_16(FILE *f, int *x, int *y, int *comp, int req_comp)
+{
+   stbi__uint16 *result;
+   stbi__context s;
+   stbi__start_file(&s,f);
+   result = stbi__load_and_postprocess_16bit(&s,x,y,comp,req_comp);
+   if (result) {
+      // need to 'unget' all the characters in the IO buffer
+      fseek(f, - (int) (s.img_buffer_end - s.img_buffer), SEEK_CUR);
+   }
+   return result;
+}
+
+STBIDEF stbi_us *stbi_load_16(char const *filename, int *x, int *y, int *comp, int req_comp)
+{
+   FILE *f = stbi__fopen(filename, "rb");
+   stbi__uint16 *result;
+   if (!f) return (stbi_us *) stbi__errpuc("can't fopen", "Unable to open file");
+   result = stbi_load_from_file_16(f,x,y,comp,req_comp);
+   fclose(f);
+   return result;
+}
+
+
+#endif //!STBI_NO_STDIO
+
+STBIDEF stbi_us *stbi_load_16_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *channels_in_file, int desired_channels)
+{
+   stbi__context s;
+   stbi__start_mem(&s,buffer,len);
+   return stbi__load_and_postprocess_16bit(&s,x,y,channels_in_file,desired_channels);
+}
+
+STBIDEF stbi_us *stbi_load_16_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *channels_in_file, int desired_channels)
+{
+   stbi__context s;
+   stbi__start_callbacks(&s, (stbi_io_callbacks *)clbk, user);
+   return stbi__load_and_postprocess_16bit(&s,x,y,channels_in_file,desired_channels);
+}
+
+STBIDEF stbi_uc *stbi_load_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp)
+{
+   stbi__context s;
+   stbi__start_mem(&s,buffer,len);
+   return stbi__load_and_postprocess_8bit(&s,x,y,comp,req_comp);
+}
+
+STBIDEF stbi_uc *stbi_load_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp)
+{
+   stbi__context s;
+   stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user);
+   return stbi__load_and_postprocess_8bit(&s,x,y,comp,req_comp);
+}
+
+#ifndef STBI_NO_GIF
+STBIDEF stbi_uc *stbi_load_gif_from_memory(stbi_uc const *buffer, int len, int **delays, int *x, int *y, int *z, int *comp, int req_comp)
+{
+   unsigned char *result;
+   stbi__context s; 
+   stbi__start_mem(&s,buffer,len); 
+   
+   result = (unsigned char*) stbi__load_gif_main(&s, delays, x, y, z, comp, req_comp);
+   if (stbi__vertically_flip_on_load) {
+      stbi__vertical_flip_slices( result, *x, *y, *z, *comp ); 
+   }
+
+   return result; 
+}
+#endif
+
+#ifndef STBI_NO_LINEAR
+static float *stbi__loadf_main(stbi__context *s, int *x, int *y, int *comp, int req_comp)
+{
+   unsigned char *data;
+   #ifndef STBI_NO_HDR
+   if (stbi__hdr_test(s)) {
+      stbi__result_info ri;
+      float *hdr_data = stbi__hdr_load(s,x,y,comp,req_comp, &ri);
+      if (hdr_data)
+         stbi__float_postprocess(hdr_data,x,y,comp,req_comp);
+      return hdr_data;
+   }
+   #endif
+   data = stbi__load_and_postprocess_8bit(s, x, y, comp, req_comp);
+   if (data)
+      return stbi__ldr_to_hdr(data, *x, *y, req_comp ? req_comp : *comp);
+   return stbi__errpf("unknown image type", "Image not of any known type, or corrupt");
+}
+
+STBIDEF float *stbi_loadf_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp)
+{
+   stbi__context s;
+   stbi__start_mem(&s,buffer,len);
+   return stbi__loadf_main(&s,x,y,comp,req_comp);
+}
+
+STBIDEF float *stbi_loadf_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp)
+{
+   stbi__context s;
+   stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user);
+   return stbi__loadf_main(&s,x,y,comp,req_comp);
+}
+
+#ifndef STBI_NO_STDIO
+STBIDEF float *stbi_loadf(char const *filename, int *x, int *y, int *comp, int req_comp)
+{
+   float *result;
+   FILE *f = stbi__fopen(filename, "rb");
+   if (!f) return stbi__errpf("can't fopen", "Unable to open file");
+   result = stbi_loadf_from_file(f,x,y,comp,req_comp);
+   fclose(f);
+   return result;
+}
+
+STBIDEF float *stbi_loadf_from_file(FILE *f, int *x, int *y, int *comp, int req_comp)
+{
+   stbi__context s;
+   stbi__start_file(&s,f);
+   return stbi__loadf_main(&s,x,y,comp,req_comp);
+}
+#endif // !STBI_NO_STDIO
+
+#endif // !STBI_NO_LINEAR
+
+// these is-hdr-or-not is defined independent of whether STBI_NO_LINEAR is
+// defined, for API simplicity; if STBI_NO_LINEAR is defined, it always
+// reports false!
+
+STBIDEF int stbi_is_hdr_from_memory(stbi_uc const *buffer, int len)
+{
+   #ifndef STBI_NO_HDR
+   stbi__context s;
+   stbi__start_mem(&s,buffer,len);
+   return stbi__hdr_test(&s);
+   #else
+   STBI_NOTUSED(buffer);
+   STBI_NOTUSED(len);
+   return 0;
+   #endif
+}
+
+#ifndef STBI_NO_STDIO
+STBIDEF int      stbi_is_hdr          (char const *filename)
+{
+   FILE *f = stbi__fopen(filename, "rb");
+   int result=0;
+   if (f) {
+      result = stbi_is_hdr_from_file(f);
+      fclose(f);
+   }
+   return result;
+}
+
+STBIDEF int stbi_is_hdr_from_file(FILE *f)
+{
+   #ifndef STBI_NO_HDR
+   long pos = ftell(f);
+   int res;
+   stbi__context s;
+   stbi__start_file(&s,f);
+   res = stbi__hdr_test(&s);
+   fseek(f, pos, SEEK_SET);
+   return res;
+   #else
+   STBI_NOTUSED(f);
+   return 0;
+   #endif
+}
+#endif // !STBI_NO_STDIO
+
+STBIDEF int      stbi_is_hdr_from_callbacks(stbi_io_callbacks const *clbk, void *user)
+{
+   #ifndef STBI_NO_HDR
+   stbi__context s;
+   stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user);
+   return stbi__hdr_test(&s);
+   #else
+   STBI_NOTUSED(clbk);
+   STBI_NOTUSED(user);
+   return 0;
+   #endif
+}
+
+#ifndef STBI_NO_LINEAR
+static float stbi__l2h_gamma=2.2f, stbi__l2h_scale=1.0f;
+
+STBIDEF void   stbi_ldr_to_hdr_gamma(float gamma) { stbi__l2h_gamma = gamma; }
+STBIDEF void   stbi_ldr_to_hdr_scale(float scale) { stbi__l2h_scale = scale; }
+#endif
+
+static float stbi__h2l_gamma_i=1.0f/2.2f, stbi__h2l_scale_i=1.0f;
+
+STBIDEF void   stbi_hdr_to_ldr_gamma(float gamma) { stbi__h2l_gamma_i = 1/gamma; }
+STBIDEF void   stbi_hdr_to_ldr_scale(float scale) { stbi__h2l_scale_i = 1/scale; }
+
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// Common code used by all image loaders
+//
+
+enum
+{
+   STBI__SCAN_load=0,
+   STBI__SCAN_type,
+   STBI__SCAN_header
+};
+
+static void stbi__refill_buffer(stbi__context *s)
+{
+   int n = (s->io.read)(s->io_user_data,(char*)s->buffer_start,s->buflen);
+   if (n == 0) {
+      // at end of file, treat same as if from memory, but need to handle case
+      // where s->img_buffer isn't pointing to safe memory, e.g. 0-byte file
+      s->read_from_callbacks = 0;
+      s->img_buffer = s->buffer_start;
+      s->img_buffer_end = s->buffer_start+1;
+      *s->img_buffer = 0;
+   } else {
+      s->img_buffer = s->buffer_start;
+      s->img_buffer_end = s->buffer_start + n;
+   }
+}
+
+stbi_inline static stbi_uc stbi__get8(stbi__context *s)
+{
+   if (s->img_buffer < s->img_buffer_end)
+      return *s->img_buffer++;
+   if (s->read_from_callbacks) {
+      stbi__refill_buffer(s);
+      return *s->img_buffer++;
+   }
+   return 0;
+}
+
+stbi_inline static int stbi__at_eof(stbi__context *s)
+{
+   if (s->io.read) {
+      if (!(s->io.eof)(s->io_user_data)) return 0;
+      // if feof() is true, check if buffer = end
+      // special case: we've only got the special 0 character at the end
+      if (s->read_from_callbacks == 0) return 1;
+   }
+
+   return s->img_buffer >= s->img_buffer_end;
+}
+
+static void stbi__skip(stbi__context *s, int n)
+{
+   if (n < 0) {
+      s->img_buffer = s->img_buffer_end;
+      return;
+   }
+   if (s->io.read) {
+      int blen = (int) (s->img_buffer_end - s->img_buffer);
+      if (blen < n) {
+         s->img_buffer = s->img_buffer_end;
+         (s->io.skip)(s->io_user_data, n - blen);
+         return;
+      }
+   }
+   s->img_buffer += n;
+}
+
+static int stbi__getn(stbi__context *s, stbi_uc *buffer, int n)
+{
+   if (s->io.read) {
+      int blen = (int) (s->img_buffer_end - s->img_buffer);
+      if (blen < n) {
+         int res, count;
+
+         memcpy(buffer, s->img_buffer, blen);
+
+         count = (s->io.read)(s->io_user_data, (char*) buffer + blen, n - blen);
+         res = (count == (n-blen));
+         s->img_buffer = s->img_buffer_end;
+         return res;
+      }
+   }
+
+   if (s->img_buffer+n <= s->img_buffer_end) {
+      memcpy(buffer, s->img_buffer, n);
+      s->img_buffer += n;
+      return 1;
+   } else
+      return 0;
+}
+
+static int stbi__get16be(stbi__context *s)
+{
+   int z = stbi__get8(s);
+   return (z << 8) + stbi__get8(s);
+}
+
+static stbi__uint32 stbi__get32be(stbi__context *s)
+{
+   stbi__uint32 z = stbi__get16be(s);
+   return (z << 16) + stbi__get16be(s);
+}
+
+#if defined(STBI_NO_BMP) && defined(STBI_NO_TGA) && defined(STBI_NO_GIF)
+// nothing
+#else
+static int stbi__get16le(stbi__context *s)
+{
+   int z = stbi__get8(s);
+   return z + (stbi__get8(s) << 8);
+}
+#endif
+
+#ifndef STBI_NO_BMP
+static stbi__uint32 stbi__get32le(stbi__context *s)
+{
+   stbi__uint32 z = stbi__get16le(s);
+   return z + (stbi__get16le(s) << 16);
+}
+#endif
+
+#define STBI__BYTECAST(x)  ((stbi_uc) ((x) & 255))  // truncate int to byte without warnings
+
+
+//////////////////////////////////////////////////////////////////////////////
+//
+//  generic converter from built-in img_n to req_comp
+//    individual types do this automatically as much as possible (e.g. jpeg
+//    does all cases internally since it needs to colorspace convert anyway,
+//    and it never has alpha, so very few cases ). png can automatically
+//    interleave an alpha=255 channel, but falls back to this for other cases
+//
+//  assume data buffer is malloced, so malloc a new one and free that one
+//  only failure mode is malloc failing
+
+static stbi_uc stbi__compute_y(int r, int g, int b)
+{
+   return (stbi_uc) (((r*77) + (g*150) +  (29*b)) >> 8);
+}
+
+static unsigned char *stbi__convert_format(unsigned char *data, int img_n, int req_comp, unsigned int x, unsigned int y)
+{
+   int i,j;
+   unsigned char *good;
+
+   if (req_comp == img_n) return data;
+   STBI_ASSERT(req_comp >= 1 && req_comp <= 4);
+
+   good = (unsigned char *) stbi__malloc_mad3(req_comp, x, y, 0);
+   if (good == NULL) {
+      STBI_FREE(data);
+      return stbi__errpuc("outofmem", "Out of memory");
+   }
+
+   for (j=0; j < (int) y; ++j) {
+      unsigned char *src  = data + j * x * img_n   ;
+      unsigned char *dest = good + j * x * req_comp;
+
+      #define STBI__COMBO(a,b)  ((a)*8+(b))
+      #define STBI__CASE(a,b)   case STBI__COMBO(a,b): for(i=x-1; i >= 0; --i, src += a, dest += b)
+      // convert source image with img_n components to one with req_comp components;
+      // avoid switch per pixel, so use switch per scanline and massive macros
+      switch (STBI__COMBO(img_n, req_comp)) {
+         STBI__CASE(1,2) { dest[0]=src[0]; dest[1]=255;                                     } break;
+         STBI__CASE(1,3) { dest[0]=dest[1]=dest[2]=src[0];                                  } break;
+         STBI__CASE(1,4) { dest[0]=dest[1]=dest[2]=src[0]; dest[3]=255;                     } break;
+         STBI__CASE(2,1) { dest[0]=src[0];                                                  } break;
+         STBI__CASE(2,3) { dest[0]=dest[1]=dest[2]=src[0];                                  } break;
+         STBI__CASE(2,4) { dest[0]=dest[1]=dest[2]=src[0]; dest[3]=src[1];                  } break;
+         STBI__CASE(3,4) { dest[0]=src[0];dest[1]=src[1];dest[2]=src[2];dest[3]=255;        } break;
+         STBI__CASE(3,1) { dest[0]=stbi__compute_y(src[0],src[1],src[2]);                   } break;
+         STBI__CASE(3,2) { dest[0]=stbi__compute_y(src[0],src[1],src[2]); dest[1] = 255;    } break;
+         STBI__CASE(4,1) { dest[0]=stbi__compute_y(src[0],src[1],src[2]);                   } break;
+         STBI__CASE(4,2) { dest[0]=stbi__compute_y(src[0],src[1],src[2]); dest[1] = src[3]; } break;
+         STBI__CASE(4,3) { dest[0]=src[0];dest[1]=src[1];dest[2]=src[2];                    } break;
+         default: STBI_ASSERT(0);
+      }
+      #undef STBI__CASE
+   }
+
+   STBI_FREE(data);
+   return good;
+}
+
+static stbi__uint16 stbi__compute_y_16(int r, int g, int b)
+{
+   return (stbi__uint16) (((r*77) + (g*150) +  (29*b)) >> 8);
+}
+
+static stbi__uint16 *stbi__convert_format16(stbi__uint16 *data, int img_n, int req_comp, unsigned int x, unsigned int y)
+{
+   int i,j;
+   stbi__uint16 *good;
+
+   if (req_comp == img_n) return data;
+   STBI_ASSERT(req_comp >= 1 && req_comp <= 4);
+
+   good = (stbi__uint16 *) stbi__malloc(req_comp * x * y * 2);
+   if (good == NULL) {
+      STBI_FREE(data);
+      return (stbi__uint16 *) stbi__errpuc("outofmem", "Out of memory");
+   }
+
+   for (j=0; j < (int) y; ++j) {
+      stbi__uint16 *src  = data + j * x * img_n   ;
+      stbi__uint16 *dest = good + j * x * req_comp;
+
+      #define STBI__COMBO(a,b)  ((a)*8+(b))
+      #define STBI__CASE(a,b)   case STBI__COMBO(a,b): for(i=x-1; i >= 0; --i, src += a, dest += b)
+      // convert source image with img_n components to one with req_comp components;
+      // avoid switch per pixel, so use switch per scanline and massive macros
+      switch (STBI__COMBO(img_n, req_comp)) {
+         STBI__CASE(1,2) { dest[0]=src[0]; dest[1]=0xffff;                                     } break;
+         STBI__CASE(1,3) { dest[0]=dest[1]=dest[2]=src[0];                                     } break;
+         STBI__CASE(1,4) { dest[0]=dest[1]=dest[2]=src[0]; dest[3]=0xffff;                     } break;
+         STBI__CASE(2,1) { dest[0]=src[0];                                                     } break;
+         STBI__CASE(2,3) { dest[0]=dest[1]=dest[2]=src[0];                                     } break;
+         STBI__CASE(2,4) { dest[0]=dest[1]=dest[2]=src[0]; dest[3]=src[1];                     } break;
+         STBI__CASE(3,4) { dest[0]=src[0];dest[1]=src[1];dest[2]=src[2];dest[3]=0xffff;        } break;
+         STBI__CASE(3,1) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]);                   } break;
+         STBI__CASE(3,2) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); dest[1] = 0xffff; } break;
+         STBI__CASE(4,1) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]);                   } break;
+         STBI__CASE(4,2) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); dest[1] = src[3]; } break;
+         STBI__CASE(4,3) { dest[0]=src[0];dest[1]=src[1];dest[2]=src[2];                       } break;
+         default: STBI_ASSERT(0);
+      }
+      #undef STBI__CASE
+   }
+
+   STBI_FREE(data);
+   return good;
+}
+
+#ifndef STBI_NO_LINEAR
+static float   *stbi__ldr_to_hdr(stbi_uc *data, int x, int y, int comp)
+{
+   int i,k,n;
+   float *output;
+   if (!data) return NULL;
+   output = (float *) stbi__malloc_mad4(x, y, comp, sizeof(float), 0);
+   if (output == NULL) { STBI_FREE(data); return stbi__errpf("outofmem", "Out of memory"); }
+   // compute number of non-alpha components
+   if (comp & 1) n = comp; else n = comp-1;
+   for (i=0; i < x*y; ++i) {
+      for (k=0; k < n; ++k) {
+         output[i*comp + k] = (float) (pow(data[i*comp+k]/255.0f, stbi__l2h_gamma) * stbi__l2h_scale);
+      }
+   }
+   if (n < comp) {
+      for (i=0; i < x*y; ++i) {
+         output[i*comp + n] = data[i*comp + n]/255.0f;
+      }
+   }
+   STBI_FREE(data);
+   return output;
+}
+#endif
+
+#ifndef STBI_NO_HDR
+#define stbi__float2int(x)   ((int) (x))
+static stbi_uc *stbi__hdr_to_ldr(float   *data, int x, int y, int comp)
+{
+   int i,k,n;
+   stbi_uc *output;
+   if (!data) return NULL;
+   output = (stbi_uc *) stbi__malloc_mad3(x, y, comp, 0);
+   if (output == NULL) { STBI_FREE(data); return stbi__errpuc("outofmem", "Out of memory"); }
+   // compute number of non-alpha components
+   if (comp & 1) n = comp; else n = comp-1;
+   for (i=0; i < x*y; ++i) {
+      for (k=0; k < n; ++k) {
+         float z = (float) pow(data[i*comp+k]*stbi__h2l_scale_i, stbi__h2l_gamma_i) * 255 + 0.5f;
+         if (z < 0) z = 0;
+         if (z > 255) z = 255;
+         output[i*comp + k] = (stbi_uc) stbi__float2int(z);
+      }
+      if (k < comp) {
+         float z = data[i*comp+k] * 255 + 0.5f;
+         if (z < 0) z = 0;
+         if (z > 255) z = 255;
+         output[i*comp + k] = (stbi_uc) stbi__float2int(z);
+      }
+   }
+   STBI_FREE(data);
+   return output;
+}
+#endif
+
+//////////////////////////////////////////////////////////////////////////////
+//
+//  "baseline" JPEG/JFIF decoder
+//
+//    simple implementation
+//      - doesn't support delayed output of y-dimension
+//      - simple interface (only one output format: 8-bit interleaved RGB)
+//      - doesn't try to recover corrupt jpegs
+//      - doesn't allow partial loading, loading multiple at once
+//      - still fast on x86 (copying globals into locals doesn't help x86)
+//      - allocates lots of intermediate memory (full size of all components)
+//        - non-interleaved case requires this anyway
+//        - allows good upsampling (see next)
+//    high-quality
+//      - upsampled channels are bilinearly interpolated, even across blocks
+//      - quality integer IDCT derived from IJG's 'slow'
+//    performance
+//      - fast huffman; reasonable integer IDCT
+//      - some SIMD kernels for common paths on targets with SSE2/NEON
+//      - uses a lot of intermediate memory, could cache poorly
+
+#ifndef STBI_NO_JPEG
+
+// huffman decoding acceleration
+#define FAST_BITS   9  // larger handles more cases; smaller stomps less cache
+
+typedef struct
+{
+   stbi_uc  fast[1 << FAST_BITS];
+   // weirdly, repacking this into AoS is a 10% speed loss, instead of a win
+   stbi__uint16 code[256];
+   stbi_uc  values[256];
+   stbi_uc  size[257];
+   unsigned int maxcode[18];
+   int    delta[17];   // old 'firstsymbol' - old 'firstcode'
+} stbi__huffman;
+
+typedef struct
+{
+   stbi__context *s;
+   stbi__huffman huff_dc[4];
+   stbi__huffman huff_ac[4];
+   stbi__uint16 dequant[4][64];
+   stbi__int16 fast_ac[4][1 << FAST_BITS];
+
+// sizes for components, interleaved MCUs
+   int img_h_max, img_v_max;
+   int img_mcu_x, img_mcu_y;
+   int img_mcu_w, img_mcu_h;
+
+// definition of jpeg image component
+   struct
+   {
+      int id;
+      int h,v;
+      int tq;
+      int hd,ha;
+      int dc_pred;
+
+      int x,y,w2,h2;
+      stbi_uc *data;
+      void *raw_data, *raw_coeff;
+      stbi_uc *linebuf;
+      short   *coeff;   // progressive only
+      int      coeff_w, coeff_h; // number of 8x8 coefficient blocks
+   } img_comp[4];
+
+   stbi__uint32   code_buffer; // jpeg entropy-coded buffer
+   int            code_bits;   // number of valid bits
+   unsigned char  marker;      // marker seen while filling entropy buffer
+   int            nomore;      // flag if we saw a marker so must stop
+
+   int            progressive;
+   int            spec_start;
+   int            spec_end;
+   int            succ_high;
+   int            succ_low;
+   int            eob_run;
+   int            jfif;
+   int            app14_color_transform; // Adobe APP14 tag
+   int            rgb;
+
+   int scan_n, order[4];
+   int restart_interval, todo;
+
+// kernels
+   void (*idct_block_kernel)(stbi_uc *out, int out_stride, short data[64]);
+   void (*YCbCr_to_RGB_kernel)(stbi_uc *out, const stbi_uc *y, const stbi_uc *pcb, const stbi_uc *pcr, int count, int step);
+   stbi_uc *(*resample_row_hv_2_kernel)(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs);
+} stbi__jpeg;
+
+static int stbi__build_huffman(stbi__huffman *h, int *count)
+{
+   int i,j,k=0;
+   unsigned int code;
+   // build size list for each symbol (from JPEG spec)
+   for (i=0; i < 16; ++i)
+      for (j=0; j < count[i]; ++j)
+         h->size[k++] = (stbi_uc) (i+1);
+   h->size[k] = 0;
+
+   // compute actual symbols (from jpeg spec)
+   code = 0;
+   k = 0;
+   for(j=1; j <= 16; ++j) {
+      // compute delta to add to code to compute symbol id
+      h->delta[j] = k - code;
+      if (h->size[k] == j) {
+         while (h->size[k] == j)
+            h->code[k++] = (stbi__uint16) (code++);
+         if (code-1 >= (1u << j)) return stbi__err("bad code lengths","Corrupt JPEG");
+      }
+      // compute largest code + 1 for this size, preshifted as needed later
+      h->maxcode[j] = code << (16-j);
+      code <<= 1;
+   }
+   h->maxcode[j] = 0xffffffff;
+
+   // build non-spec acceleration table; 255 is flag for not-accelerated
+   memset(h->fast, 255, 1 << FAST_BITS);
+   for (i=0; i < k; ++i) {
+      int s = h->size[i];
+      if (s <= FAST_BITS) {
+         int c = h->code[i] << (FAST_BITS-s);
+         int m = 1 << (FAST_BITS-s);
+         for (j=0; j < m; ++j) {
+            h->fast[c+j] = (stbi_uc) i;
+         }
+      }
+   }
+   return 1;
+}
+
+// build a table that decodes both magnitude and value of small ACs in
+// one go.
+static void stbi__build_fast_ac(stbi__int16 *fast_ac, stbi__huffman *h)
+{
+   int i;
+   for (i=0; i < (1 << FAST_BITS); ++i) {
+      stbi_uc fast = h->fast[i];
+      fast_ac[i] = 0;
+      if (fast < 255) {
+         int rs = h->values[fast];
+         int run = (rs >> 4) & 15;
+         int magbits = rs & 15;
+         int len = h->size[fast];
+
+         if (magbits && len + magbits <= FAST_BITS) {
+            // magnitude code followed by receive_extend code
+            int k = ((i << len) & ((1 << FAST_BITS) - 1)) >> (FAST_BITS - magbits);
+            int m = 1 << (magbits - 1);
+            if (k < m) k += (~0U << magbits) + 1;
+            // if the result is small enough, we can fit it in fast_ac table
+            if (k >= -128 && k <= 127)
+               fast_ac[i] = (stbi__int16) ((k * 256) + (run * 16) + (len + magbits));
+         }
+      }
+   }
+}
+
+static void stbi__grow_buffer_unsafe(stbi__jpeg *j)
+{
+   do {
+      unsigned int b = j->nomore ? 0 : stbi__get8(j->s);
+      if (b == 0xff) {
+         int c = stbi__get8(j->s);
+         while (c == 0xff) c = stbi__get8(j->s); // consume fill bytes
+         if (c != 0) {
+            j->marker = (unsigned char) c;
+            j->nomore = 1;
+            return;
+         }
+      }
+      j->code_buffer |= b << (24 - j->code_bits);
+      j->code_bits += 8;
+   } while (j->code_bits <= 24);
+}
+
+// (1 << n) - 1
+static const stbi__uint32 stbi__bmask[17]={0,1,3,7,15,31,63,127,255,511,1023,2047,4095,8191,16383,32767,65535};
+
+// decode a jpeg huffman value from the bitstream
+stbi_inline static int stbi__jpeg_huff_decode(stbi__jpeg *j, stbi__huffman *h)
+{
+   unsigned int temp;
+   int c,k;
+
+   if (j->code_bits < 16) stbi__grow_buffer_unsafe(j);
+
+   // look at the top FAST_BITS and determine what symbol ID it is,
+   // if the code is <= FAST_BITS
+   c = (j->code_buffer >> (32 - FAST_BITS)) & ((1 << FAST_BITS)-1);
+   k = h->fast[c];
+   if (k < 255) {
+      int s = h->size[k];
+      if (s > j->code_bits)
+         return -1;
+      j->code_buffer <<= s;
+      j->code_bits -= s;
+      return h->values[k];
+   }
+
+   // naive test is to shift the code_buffer down so k bits are
+   // valid, then test against maxcode. To speed this up, we've
+   // preshifted maxcode left so that it has (16-k) 0s at the
+   // end; in other words, regardless of the number of bits, it
+   // wants to be compared against something shifted to have 16;
+   // that way we don't need to shift inside the loop.
+   temp = j->code_buffer >> 16;
+   for (k=FAST_BITS+1 ; ; ++k)
+      if (temp < h->maxcode[k])
+         break;
+   if (k == 17) {
+      // error! code not found
+      j->code_bits -= 16;
+      return -1;
+   }
+
+   if (k > j->code_bits)
+      return -1;
+
+   // convert the huffman code to the symbol id
+   c = ((j->code_buffer >> (32 - k)) & stbi__bmask[k]) + h->delta[k];
+   STBI_ASSERT((((j->code_buffer) >> (32 - h->size[c])) & stbi__bmask[h->size[c]]) == h->code[c]);
+
+   // convert the id to a symbol
+   j->code_bits -= k;
+   j->code_buffer <<= k;
+   return h->values[c];
+}
+
+// bias[n] = (-1<<n) + 1
+static const int stbi__jbias[16] = {0,-1,-3,-7,-15,-31,-63,-127,-255,-511,-1023,-2047,-4095,-8191,-16383,-32767};
+
+// combined JPEG 'receive' and JPEG 'extend', since baseline
+// always extends everything it receives.
+stbi_inline static int stbi__extend_receive(stbi__jpeg *j, int n)
+{
+   unsigned int k;
+   int sgn;
+   if (j->code_bits < n) stbi__grow_buffer_unsafe(j);
+
+   sgn = (stbi__int32)j->code_buffer >> 31; // sign bit is always in MSB
+   k = stbi_lrot(j->code_buffer, n);
+   STBI_ASSERT(n >= 0 && n < (int) (sizeof(stbi__bmask)/sizeof(*stbi__bmask)));
+   j->code_buffer = k & ~stbi__bmask[n];
+   k &= stbi__bmask[n];
+   j->code_bits -= n;
+   return k + (stbi__jbias[n] & ~sgn);
+}
+
+// get some unsigned bits
+stbi_inline static int stbi__jpeg_get_bits(stbi__jpeg *j, int n)
+{
+   unsigned int k;
+   if (j->code_bits < n) stbi__grow_buffer_unsafe(j);
+   k = stbi_lrot(j->code_buffer, n);
+   j->code_buffer = k & ~stbi__bmask[n];
+   k &= stbi__bmask[n];
+   j->code_bits -= n;
+   return k;
+}
+
+stbi_inline static int stbi__jpeg_get_bit(stbi__jpeg *j)
+{
+   unsigned int k;
+   if (j->code_bits < 1) stbi__grow_buffer_unsafe(j);
+   k = j->code_buffer;
+   j->code_buffer <<= 1;
+   --j->code_bits;
+   return k & 0x80000000;
+}
+
+// given a value that's at position X in the zigzag stream,
+// where does it appear in the 8x8 matrix coded as row-major?
+static const stbi_uc stbi__jpeg_dezigzag[64+15] =
+{
+    0,  1,  8, 16,  9,  2,  3, 10,
+   17, 24, 32, 25, 18, 11,  4,  5,
+   12, 19, 26, 33, 40, 48, 41, 34,
+   27, 20, 13,  6,  7, 14, 21, 28,
+   35, 42, 49, 56, 57, 50, 43, 36,
+   29, 22, 15, 23, 30, 37, 44, 51,
+   58, 59, 52, 45, 38, 31, 39, 46,
+   53, 60, 61, 54, 47, 55, 62, 63,
+   // let corrupt input sample past end
+   63, 63, 63, 63, 63, 63, 63, 63,
+   63, 63, 63, 63, 63, 63, 63
+};
+
+// decode one 64-entry block--
+static int stbi__jpeg_decode_block(stbi__jpeg *j, short data[64], stbi__huffman *hdc, stbi__huffman *hac, stbi__int16 *fac, int b, stbi__uint16 *dequant)
+{
+   int diff,dc,k;
+   int t;
+
+   if (j->code_bits < 16) stbi__grow_buffer_unsafe(j);
+   t = stbi__jpeg_huff_decode(j, hdc);
+   if (t < 0) return stbi__err("bad huffman code","Corrupt JPEG");
+
+   // 0 all the ac values now so we can do it 32-bits at a time
+   memset(data,0,64*sizeof(data[0]));
+
+   diff = t ? stbi__extend_receive(j, t) : 0;
+   dc = j->img_comp[b].dc_pred + diff;
+   j->img_comp[b].dc_pred = dc;
+   data[0] = (short) (dc * dequant[0]);
+
+   // decode AC components, see JPEG spec
+   k = 1;
+   do {
+      unsigned int zig;
+      int c,r,s;
+      if (j->code_bits < 16) stbi__grow_buffer_unsafe(j);
+      c = (j->code_buffer >> (32 - FAST_BITS)) & ((1 << FAST_BITS)-1);
+      r = fac[c];
+      if (r) { // fast-AC path
+         k += (r >> 4) & 15; // run
+         s = r & 15; // combined length
+         j->code_buffer <<= s;
+         j->code_bits -= s;
+         // decode into unzigzag'd location
+         zig = stbi__jpeg_dezigzag[k++];
+         data[zig] = (short) ((r >> 8) * dequant[zig]);
+      } else {
+         int rs = stbi__jpeg_huff_decode(j, hac);
+         if (rs < 0) return stbi__err("bad huffman code","Corrupt JPEG");
+         s = rs & 15;
+         r = rs >> 4;
+         if (s == 0) {
+            if (rs != 0xf0) break; // end block
+            k += 16;
+         } else {
+            k += r;
+            // decode into unzigzag'd location
+            zig = stbi__jpeg_dezigzag[k++];
+            data[zig] = (short) (stbi__extend_receive(j,s) * dequant[zig]);
+         }
+      }
+   } while (k < 64);
+   return 1;
+}
+
+static int stbi__jpeg_decode_block_prog_dc(stbi__jpeg *j, short data[64], stbi__huffman *hdc, int b)
+{
+   int diff,dc;
+   int t;
+   if (j->spec_end != 0) return stbi__err("can't merge dc and ac", "Corrupt JPEG");
+
+   if (j->code_bits < 16) stbi__grow_buffer_unsafe(j);
+
+   if (j->succ_high == 0) {
+      // first scan for DC coefficient, must be first
+      memset(data,0,64*sizeof(data[0])); // 0 all the ac values now
+      t = stbi__jpeg_huff_decode(j, hdc);
+      diff = t ? stbi__extend_receive(j, t) : 0;
+
+      dc = j->img_comp[b].dc_pred + diff;
+      j->img_comp[b].dc_pred = dc;
+      data[0] = (short) (dc << j->succ_low);
+   } else {
+      // refinement scan for DC coefficient
+      if (stbi__jpeg_get_bit(j))
+         data[0] += (short) (1 << j->succ_low);
+   }
+   return 1;
+}
+
+// @OPTIMIZE: store non-zigzagged during the decode passes,
+// and only de-zigzag when dequantizing
+static int stbi__jpeg_decode_block_prog_ac(stbi__jpeg *j, short data[64], stbi__huffman *hac, stbi__int16 *fac)
+{
+   int k;
+   if (j->spec_start == 0) return stbi__err("can't merge dc and ac", "Corrupt JPEG");
+
+   if (j->succ_high == 0) {
+      int shift = j->succ_low;
+
+      if (j->eob_run) {
+         --j->eob_run;
+         return 1;
+      }
+
+      k = j->spec_start;
+      do {
+         unsigned int zig;
+         int c,r,s;
+         if (j->code_bits < 16) stbi__grow_buffer_unsafe(j);
+         c = (j->code_buffer >> (32 - FAST_BITS)) & ((1 << FAST_BITS)-1);
+         r = fac[c];
+         if (r) { // fast-AC path
+            k += (r >> 4) & 15; // run
+            s = r & 15; // combined length
+            j->code_buffer <<= s;
+            j->code_bits -= s;
+            zig = stbi__jpeg_dezigzag[k++];
+            data[zig] = (short) ((r >> 8) << shift);
+         } else {
+            int rs = stbi__jpeg_huff_decode(j, hac);
+            if (rs < 0) return stbi__err("bad huffman code","Corrupt JPEG");
+            s = rs & 15;
+            r = rs >> 4;
+            if (s == 0) {
+               if (r < 15) {
+                  j->eob_run = (1 << r);
+                  if (r)
+                     j->eob_run += stbi__jpeg_get_bits(j, r);
+                  --j->eob_run;
+                  break;
+               }
+               k += 16;
+            } else {
+               k += r;
+               zig = stbi__jpeg_dezigzag[k++];
+               data[zig] = (short) (stbi__extend_receive(j,s) << shift);
+            }
+         }
+      } while (k <= j->spec_end);
+   } else {
+      // refinement scan for these AC coefficients
+
+      short bit = (short) (1 << j->succ_low);
+
+      if (j->eob_run) {
+         --j->eob_run;
+         for (k = j->spec_start; k <= j->spec_end; ++k) {
+            short *p = &data[stbi__jpeg_dezigzag[k]];
+            if (*p != 0)
+               if (stbi__jpeg_get_bit(j))
+                  if ((*p & bit)==0) {
+                     if (*p > 0)
+                        *p += bit;
+                     else
+                        *p -= bit;
+                  }
+         }
+      } else {
+         k = j->spec_start;
+         do {
+            int r,s;
+            int rs = stbi__jpeg_huff_decode(j, hac); // @OPTIMIZE see if we can use the fast path here, advance-by-r is so slow, eh
+            if (rs < 0) return stbi__err("bad huffman code","Corrupt JPEG");
+            s = rs & 15;
+            r = rs >> 4;
+            if (s == 0) {
+               if (r < 15) {
+                  j->eob_run = (1 << r) - 1;
+                  if (r)
+                     j->eob_run += stbi__jpeg_get_bits(j, r);
+                  r = 64; // force end of block
+               } else {
+                  // r=15 s=0 should write 16 0s, so we just do
+                  // a run of 15 0s and then write s (which is 0),
+                  // so we don't have to do anything special here
+               }
+            } else {
+               if (s != 1) return stbi__err("bad huffman code", "Corrupt JPEG");
+               // sign bit
+               if (stbi__jpeg_get_bit(j))
+                  s = bit;
+               else
+                  s = -bit;
+            }
+
+            // advance by r
+            while (k <= j->spec_end) {
+               short *p = &data[stbi__jpeg_dezigzag[k++]];
+               if (*p != 0) {
+                  if (stbi__jpeg_get_bit(j))
+                     if ((*p & bit)==0) {
+                        if (*p > 0)
+                           *p += bit;
+                        else
+                           *p -= bit;
+                     }
+               } else {
+                  if (r == 0) {
+                     *p = (short) s;
+                     break;
+                  }
+                  --r;
+               }
+            }
+         } while (k <= j->spec_end);
+      }
+   }
+   return 1;
+}
+
+// take a -128..127 value and stbi__clamp it and convert to 0..255
+stbi_inline static stbi_uc stbi__clamp(int x)
+{
+   // trick to use a single test to catch both cases
+   if ((unsigned int) x > 255) {
+      if (x < 0) return 0;
+      if (x > 255) return 255;
+   }
+   return (stbi_uc) x;
+}
+
+#define stbi__f2f(x)  ((int) (((x) * 4096 + 0.5)))
+#define stbi__fsh(x)  ((x) * 4096)
+
+// derived from jidctint -- DCT_ISLOW
+#define STBI__IDCT_1D(s0,s1,s2,s3,s4,s5,s6,s7) \
+   int t0,t1,t2,t3,p1,p2,p3,p4,p5,x0,x1,x2,x3; \
+   p2 = s2;                                    \
+   p3 = s6;                                    \
+   p1 = (p2+p3) * stbi__f2f(0.5411961f);       \
+   t2 = p1 + p3*stbi__f2f(-1.847759065f);      \
+   t3 = p1 + p2*stbi__f2f( 0.765366865f);      \
+   p2 = s0;                                    \
+   p3 = s4;                                    \
+   t0 = stbi__fsh(p2+p3);                      \
+   t1 = stbi__fsh(p2-p3);                      \
+   x0 = t0+t3;                                 \
+   x3 = t0-t3;                                 \
+   x1 = t1+t2;                                 \
+   x2 = t1-t2;                                 \
+   t0 = s7;                                    \
+   t1 = s5;                                    \
+   t2 = s3;                                    \
+   t3 = s1;                                    \
+   p3 = t0+t2;                                 \
+   p4 = t1+t3;                                 \
+   p1 = t0+t3;                                 \
+   p2 = t1+t2;                                 \
+   p5 = (p3+p4)*stbi__f2f( 1.175875602f);      \
+   t0 = t0*stbi__f2f( 0.298631336f);           \
+   t1 = t1*stbi__f2f( 2.053119869f);           \
+   t2 = t2*stbi__f2f( 3.072711026f);           \
+   t3 = t3*stbi__f2f( 1.501321110f);           \
+   p1 = p5 + p1*stbi__f2f(-0.899976223f);      \
+   p2 = p5 + p2*stbi__f2f(-2.562915447f);      \
+   p3 = p3*stbi__f2f(-1.961570560f);           \
+   p4 = p4*stbi__f2f(-0.390180644f);           \
+   t3 += p1+p4;                                \
+   t2 += p2+p3;                                \
+   t1 += p2+p4;                                \
+   t0 += p1+p3;
+
+static void stbi__idct_block(stbi_uc *out, int out_stride, short data[64])
+{
+   int i,val[64],*v=val;
+   stbi_uc *o;
+   short *d = data;
+
+   // columns
+   for (i=0; i < 8; ++i,++d, ++v) {
+      // if all zeroes, shortcut -- this avoids dequantizing 0s and IDCTing
+      if (d[ 8]==0 && d[16]==0 && d[24]==0 && d[32]==0
+           && d[40]==0 && d[48]==0 && d[56]==0) {
+         //    no shortcut                 0     seconds
+         //    (1|2|3|4|5|6|7)==0          0     seconds
+         //    all separate               -0.047 seconds
+         //    1 && 2|3 && 4|5 && 6|7:    -0.047 seconds
+         int dcterm = d[0]*4;
+         v[0] = v[8] = v[16] = v[24] = v[32] = v[40] = v[48] = v[56] = dcterm;
+      } else {
+         STBI__IDCT_1D(d[ 0],d[ 8],d[16],d[24],d[32],d[40],d[48],d[56])
+         // constants scaled things up by 1<<12; let's bring them back
+         // down, but keep 2 extra bits of precision
+         x0 += 512; x1 += 512; x2 += 512; x3 += 512;
+         v[ 0] = (x0+t3) >> 10;
+         v[56] = (x0-t3) >> 10;
+         v[ 8] = (x1+t2) >> 10;
+         v[48] = (x1-t2) >> 10;
+         v[16] = (x2+t1) >> 10;
+         v[40] = (x2-t1) >> 10;
+         v[24] = (x3+t0) >> 10;
+         v[32] = (x3-t0) >> 10;
+      }
+   }
+
+   for (i=0, v=val, o=out; i < 8; ++i,v+=8,o+=out_stride) {
+      // no fast case since the first 1D IDCT spread components out
+      STBI__IDCT_1D(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7])
+      // constants scaled things up by 1<<12, plus we had 1<<2 from first
+      // loop, plus horizontal and vertical each scale by sqrt(8) so together
+      // we've got an extra 1<<3, so 1<<17 total we need to remove.
+      // so we want to round that, which means adding 0.5 * 1<<17,
+      // aka 65536. Also, we'll end up with -128 to 127 that we want
+      // to encode as 0..255 by adding 128, so we'll add that before the shift
+      x0 += 65536 + (128<<17);
+      x1 += 65536 + (128<<17);
+      x2 += 65536 + (128<<17);
+      x3 += 65536 + (128<<17);
+      // tried computing the shifts into temps, or'ing the temps to see
+      // if any were out of range, but that was slower
+      o[0] = stbi__clamp((x0+t3) >> 17);
+      o[7] = stbi__clamp((x0-t3) >> 17);
+      o[1] = stbi__clamp((x1+t2) >> 17);
+      o[6] = stbi__clamp((x1-t2) >> 17);
+      o[2] = stbi__clamp((x2+t1) >> 17);
+      o[5] = stbi__clamp((x2-t1) >> 17);
+      o[3] = stbi__clamp((x3+t0) >> 17);
+      o[4] = stbi__clamp((x3-t0) >> 17);
+   }
+}
+
+#ifdef STBI_SSE2
+// sse2 integer IDCT. not the fastest possible implementation but it
+// produces bit-identical results to the generic C version so it's
+// fully "transparent".
+static void stbi__idct_simd(stbi_uc *out, int out_stride, short data[64])
+{
+   // This is constructed to match our regular (generic) integer IDCT exactly.
+   __m128i row0, row1, row2, row3, row4, row5, row6, row7;
+   __m128i tmp;
+
+   // dot product constant: even elems=x, odd elems=y
+   #define dct_const(x,y)  _mm_setr_epi16((x),(y),(x),(y),(x),(y),(x),(y))
+
+   // out(0) = c0[even]*x + c0[odd]*y   (c0, x, y 16-bit, out 32-bit)
+   // out(1) = c1[even]*x + c1[odd]*y
+   #define dct_rot(out0,out1, x,y,c0,c1) \
+      __m128i c0##lo = _mm_unpacklo_epi16((x),(y)); \
+      __m128i c0##hi = _mm_unpackhi_epi16((x),(y)); \
+      __m128i out0##_l = _mm_madd_epi16(c0##lo, c0); \
+      __m128i out0##_h = _mm_madd_epi16(c0##hi, c0); \
+      __m128i out1##_l = _mm_madd_epi16(c0##lo, c1); \
+      __m128i out1##_h = _mm_madd_epi16(c0##hi, c1)
+
+   // out = in << 12  (in 16-bit, out 32-bit)
+   #define dct_widen(out, in) \
+      __m128i out##_l = _mm_srai_epi32(_mm_unpacklo_epi16(_mm_setzero_si128(), (in)), 4); \
+      __m128i out##_h = _mm_srai_epi32(_mm_unpackhi_epi16(_mm_setzero_si128(), (in)), 4)
+
+   // wide add
+   #define dct_wadd(out, a, b) \
+      __m128i out##_l = _mm_add_epi32(a##_l, b##_l); \
+      __m128i out##_h = _mm_add_epi32(a##_h, b##_h)
+
+   // wide sub
+   #define dct_wsub(out, a, b) \
+      __m128i out##_l = _mm_sub_epi32(a##_l, b##_l); \
+      __m128i out##_h = _mm_sub_epi32(a##_h, b##_h)
+
+   // butterfly a/b, add bias, then shift by "s" and pack
+   #define dct_bfly32o(out0, out1, a,b,bias,s) \
+      { \
+         __m128i abiased_l = _mm_add_epi32(a##_l, bias); \
+         __m128i abiased_h = _mm_add_epi32(a##_h, bias); \
+         dct_wadd(sum, abiased, b); \
+         dct_wsub(dif, abiased, b); \
+         out0 = _mm_packs_epi32(_mm_srai_epi32(sum_l, s), _mm_srai_epi32(sum_h, s)); \
+         out1 = _mm_packs_epi32(_mm_srai_epi32(dif_l, s), _mm_srai_epi32(dif_h, s)); \
+      }
+
+   // 8-bit interleave step (for transposes)
+   #define dct_interleave8(a, b) \
+      tmp = a; \
+      a = _mm_unpacklo_epi8(a, b); \
+      b = _mm_unpackhi_epi8(tmp, b)
+
+   // 16-bit interleave step (for transposes)
+   #define dct_interleave16(a, b) \
+      tmp = a; \
+      a = _mm_unpacklo_epi16(a, b); \
+      b = _mm_unpackhi_epi16(tmp, b)
+
+   #define dct_pass(bias,shift) \
+      { \
+         /* even part */ \
+         dct_rot(t2e,t3e, row2,row6, rot0_0,rot0_1); \
+         __m128i sum04 = _mm_add_epi16(row0, row4); \
+         __m128i dif04 = _mm_sub_epi16(row0, row4); \
+         dct_widen(t0e, sum04); \
+         dct_widen(t1e, dif04); \
+         dct_wadd(x0, t0e, t3e); \
+         dct_wsub(x3, t0e, t3e); \
+         dct_wadd(x1, t1e, t2e); \
+         dct_wsub(x2, t1e, t2e); \
+         /* odd part */ \
+         dct_rot(y0o,y2o, row7,row3, rot2_0,rot2_1); \
+         dct_rot(y1o,y3o, row5,row1, rot3_0,rot3_1); \
+         __m128i sum17 = _mm_add_epi16(row1, row7); \
+         __m128i sum35 = _mm_add_epi16(row3, row5); \
+         dct_rot(y4o,y5o, sum17,sum35, rot1_0,rot1_1); \
+         dct_wadd(x4, y0o, y4o); \
+         dct_wadd(x5, y1o, y5o); \
+         dct_wadd(x6, y2o, y5o); \
+         dct_wadd(x7, y3o, y4o); \
+         dct_bfly32o(row0,row7, x0,x7,bias,shift); \
+         dct_bfly32o(row1,row6, x1,x6,bias,shift); \
+         dct_bfly32o(row2,row5, x2,x5,bias,shift); \
+         dct_bfly32o(row3,row4, x3,x4,bias,shift); \
+      }
+
+   __m128i rot0_0 = dct_const(stbi__f2f(0.5411961f), stbi__f2f(0.5411961f) + stbi__f2f(-1.847759065f));
+   __m128i rot0_1 = dct_const(stbi__f2f(0.5411961f) + stbi__f2f( 0.765366865f), stbi__f2f(0.5411961f));
+   __m128i rot1_0 = dct_const(stbi__f2f(1.175875602f) + stbi__f2f(-0.899976223f), stbi__f2f(1.175875602f));
+   __m128i rot1_1 = dct_const(stbi__f2f(1.175875602f), stbi__f2f(1.175875602f) + stbi__f2f(-2.562915447f));
+   __m128i rot2_0 = dct_const(stbi__f2f(-1.961570560f) + stbi__f2f( 0.298631336f), stbi__f2f(-1.961570560f));
+   __m128i rot2_1 = dct_const(stbi__f2f(-1.961570560f), stbi__f2f(-1.961570560f) + stbi__f2f( 3.072711026f));
+   __m128i rot3_0 = dct_const(stbi__f2f(-0.390180644f) + stbi__f2f( 2.053119869f), stbi__f2f(-0.390180644f));
+   __m128i rot3_1 = dct_const(stbi__f2f(-0.390180644f), stbi__f2f(-0.390180644f) + stbi__f2f( 1.501321110f));
+
+   // rounding biases in column/row passes, see stbi__idct_block for explanation.
+   __m128i bias_0 = _mm_set1_epi32(512);
+   __m128i bias_1 = _mm_set1_epi32(65536 + (128<<17));
+
+   // load
+   row0 = _mm_load_si128((const __m128i *) (data + 0*8));
+   row1 = _mm_load_si128((const __m128i *) (data + 1*8));
+   row2 = _mm_load_si128((const __m128i *) (data + 2*8));
+   row3 = _mm_load_si128((const __m128i *) (data + 3*8));
+   row4 = _mm_load_si128((const __m128i *) (data + 4*8));
+   row5 = _mm_load_si128((const __m128i *) (data + 5*8));
+   row6 = _mm_load_si128((const __m128i *) (data + 6*8));
+   row7 = _mm_load_si128((const __m128i *) (data + 7*8));
+
+   // column pass
+   dct_pass(bias_0, 10);
+
+   {
+      // 16bit 8x8 transpose pass 1
+      dct_interleave16(row0, row4);
+      dct_interleave16(row1, row5);
+      dct_interleave16(row2, row6);
+      dct_interleave16(row3, row7);
+
+      // transpose pass 2
+      dct_interleave16(row0, row2);
+      dct_interleave16(row1, row3);
+      dct_interleave16(row4, row6);
+      dct_interleave16(row5, row7);
+
+      // transpose pass 3
+      dct_interleave16(row0, row1);
+      dct_interleave16(row2, row3);
+      dct_interleave16(row4, row5);
+      dct_interleave16(row6, row7);
+   }
+
+   // row pass
+   dct_pass(bias_1, 17);
+
+   {
+      // pack
+      __m128i p0 = _mm_packus_epi16(row0, row1); // a0a1a2a3...a7b0b1b2b3...b7
+      __m128i p1 = _mm_packus_epi16(row2, row3);
+      __m128i p2 = _mm_packus_epi16(row4, row5);
+      __m128i p3 = _mm_packus_epi16(row6, row7);
+
+      // 8bit 8x8 transpose pass 1
+      dct_interleave8(p0, p2); // a0e0a1e1...
+      dct_interleave8(p1, p3); // c0g0c1g1...
+
+      // transpose pass 2
+      dct_interleave8(p0, p1); // a0c0e0g0...
+      dct_interleave8(p2, p3); // b0d0f0h0...
+
+      // transpose pass 3
+      dct_interleave8(p0, p2); // a0b0c0d0...
+      dct_interleave8(p1, p3); // a4b4c4d4...
+
+      // store
+      _mm_storel_epi64((__m128i *) out, p0); out += out_stride;
+      _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p0, 0x4e)); out += out_stride;
+      _mm_storel_epi64((__m128i *) out, p2); out += out_stride;
+      _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p2, 0x4e)); out += out_stride;
+      _mm_storel_epi64((__m128i *) out, p1); out += out_stride;
+      _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p1, 0x4e)); out += out_stride;
+      _mm_storel_epi64((__m128i *) out, p3); out += out_stride;
+      _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p3, 0x4e));
+   }
+
+#undef dct_const
+#undef dct_rot
+#undef dct_widen
+#undef dct_wadd
+#undef dct_wsub
+#undef dct_bfly32o
+#undef dct_interleave8
+#undef dct_interleave16
+#undef dct_pass
+}
+
+#endif // STBI_SSE2
+
+#ifdef STBI_NEON
+
+// NEON integer IDCT. should produce bit-identical
+// results to the generic C version.
+static void stbi__idct_simd(stbi_uc *out, int out_stride, short data[64])
+{
+   int16x8_t row0, row1, row2, row3, row4, row5, row6, row7;
+
+   int16x4_t rot0_0 = vdup_n_s16(stbi__f2f(0.5411961f));
+   int16x4_t rot0_1 = vdup_n_s16(stbi__f2f(-1.847759065f));
+   int16x4_t rot0_2 = vdup_n_s16(stbi__f2f( 0.765366865f));
+   int16x4_t rot1_0 = vdup_n_s16(stbi__f2f( 1.175875602f));
+   int16x4_t rot1_1 = vdup_n_s16(stbi__f2f(-0.899976223f));
+   int16x4_t rot1_2 = vdup_n_s16(stbi__f2f(-2.562915447f));
+   int16x4_t rot2_0 = vdup_n_s16(stbi__f2f(-1.961570560f));
+   int16x4_t rot2_1 = vdup_n_s16(stbi__f2f(-0.390180644f));
+   int16x4_t rot3_0 = vdup_n_s16(stbi__f2f( 0.298631336f));
+   int16x4_t rot3_1 = vdup_n_s16(stbi__f2f( 2.053119869f));
+   int16x4_t rot3_2 = vdup_n_s16(stbi__f2f( 3.072711026f));
+   int16x4_t rot3_3 = vdup_n_s16(stbi__f2f( 1.501321110f));
+
+#define dct_long_mul(out, inq, coeff) \
+   int32x4_t out##_l = vmull_s16(vget_low_s16(inq), coeff); \
+   int32x4_t out##_h = vmull_s16(vget_high_s16(inq), coeff)
+
+#define dct_long_mac(out, acc, inq, coeff) \
+   int32x4_t out##_l = vmlal_s16(acc##_l, vget_low_s16(inq), coeff); \
+   int32x4_t out##_h = vmlal_s16(acc##_h, vget_high_s16(inq), coeff)
+
+#define dct_widen(out, inq) \
+   int32x4_t out##_l = vshll_n_s16(vget_low_s16(inq), 12); \
+   int32x4_t out##_h = vshll_n_s16(vget_high_s16(inq), 12)
+
+// wide add
+#define dct_wadd(out, a, b) \
+   int32x4_t out##_l = vaddq_s32(a##_l, b##_l); \
+   int32x4_t out##_h = vaddq_s32(a##_h, b##_h)
+
+// wide sub
+#define dct_wsub(out, a, b) \
+   int32x4_t out##_l = vsubq_s32(a##_l, b##_l); \
+   int32x4_t out##_h = vsubq_s32(a##_h, b##_h)
+
+// butterfly a/b, then shift using "shiftop" by "s" and pack
+#define dct_bfly32o(out0,out1, a,b,shiftop,s) \
+   { \
+      dct_wadd(sum, a, b); \
+      dct_wsub(dif, a, b); \
+      out0 = vcombine_s16(shiftop(sum_l, s), shiftop(sum_h, s)); \
+      out1 = vcombine_s16(shiftop(dif_l, s), shiftop(dif_h, s)); \
+   }
+
+#define dct_pass(shiftop, shift) \
+   { \
+      /* even part */ \
+      int16x8_t sum26 = vaddq_s16(row2, row6); \
+      dct_long_mul(p1e, sum26, rot0_0); \
+      dct_long_mac(t2e, p1e, row6, rot0_1); \
+      dct_long_mac(t3e, p1e, row2, rot0_2); \
+      int16x8_t sum04 = vaddq_s16(row0, row4); \
+      int16x8_t dif04 = vsubq_s16(row0, row4); \
+      dct_widen(t0e, sum04); \
+      dct_widen(t1e, dif04); \
+      dct_wadd(x0, t0e, t3e); \
+      dct_wsub(x3, t0e, t3e); \
+      dct_wadd(x1, t1e, t2e); \
+      dct_wsub(x2, t1e, t2e); \
+      /* odd part */ \
+      int16x8_t sum15 = vaddq_s16(row1, row5); \
+      int16x8_t sum17 = vaddq_s16(row1, row7); \
+      int16x8_t sum35 = vaddq_s16(row3, row5); \
+      int16x8_t sum37 = vaddq_s16(row3, row7); \
+      int16x8_t sumodd = vaddq_s16(sum17, sum35); \
+      dct_long_mul(p5o, sumodd, rot1_0); \
+      dct_long_mac(p1o, p5o, sum17, rot1_1); \
+      dct_long_mac(p2o, p5o, sum35, rot1_2); \
+      dct_long_mul(p3o, sum37, rot2_0); \
+      dct_long_mul(p4o, sum15, rot2_1); \
+      dct_wadd(sump13o, p1o, p3o); \
+      dct_wadd(sump24o, p2o, p4o); \
+      dct_wadd(sump23o, p2o, p3o); \
+      dct_wadd(sump14o, p1o, p4o); \
+      dct_long_mac(x4, sump13o, row7, rot3_0); \
+      dct_long_mac(x5, sump24o, row5, rot3_1); \
+      dct_long_mac(x6, sump23o, row3, rot3_2); \
+      dct_long_mac(x7, sump14o, row1, rot3_3); \
+      dct_bfly32o(row0,row7, x0,x7,shiftop,shift); \
+      dct_bfly32o(row1,row6, x1,x6,shiftop,shift); \
+      dct_bfly32o(row2,row5, x2,x5,shiftop,shift); \
+      dct_bfly32o(row3,row4, x3,x4,shiftop,shift); \
+   }
+
+   // load
+   row0 = vld1q_s16(data + 0*8);
+   row1 = vld1q_s16(data + 1*8);
+   row2 = vld1q_s16(data + 2*8);
+   row3 = vld1q_s16(data + 3*8);
+   row4 = vld1q_s16(data + 4*8);
+   row5 = vld1q_s16(data + 5*8);
+   row6 = vld1q_s16(data + 6*8);
+   row7 = vld1q_s16(data + 7*8);
+
+   // add DC bias
+   row0 = vaddq_s16(row0, vsetq_lane_s16(1024, vdupq_n_s16(0), 0));
+
+   // column pass
+   dct_pass(vrshrn_n_s32, 10);
+
+   // 16bit 8x8 transpose
+   {
+// these three map to a single VTRN.16, VTRN.32, and VSWP, respectively.
+// whether compilers actually get this is another story, sadly.
+#define dct_trn16(x, y) { int16x8x2_t t = vtrnq_s16(x, y); x = t.val[0]; y = t.val[1]; }
+#define dct_trn32(x, y) { int32x4x2_t t = vtrnq_s32(vreinterpretq_s32_s16(x), vreinterpretq_s32_s16(y)); x = vreinterpretq_s16_s32(t.val[0]); y = vreinterpretq_s16_s32(t.val[1]); }
+#define dct_trn64(x, y) { int16x8_t x0 = x; int16x8_t y0 = y; x = vcombine_s16(vget_low_s16(x0), vget_low_s16(y0)); y = vcombine_s16(vget_high_s16(x0), vget_high_s16(y0)); }
+
+      // pass 1
+      dct_trn16(row0, row1); // a0b0a2b2a4b4a6b6
+      dct_trn16(row2, row3);
+      dct_trn16(row4, row5);
+      dct_trn16(row6, row7);
+
+      // pass 2
+      dct_trn32(row0, row2); // a0b0c0d0a4b4c4d4
+      dct_trn32(row1, row3);
+      dct_trn32(row4, row6);
+      dct_trn32(row5, row7);
+
+      // pass 3
+      dct_trn64(row0, row4); // a0b0c0d0e0f0g0h0
+      dct_trn64(row1, row5);
+      dct_trn64(row2, row6);
+      dct_trn64(row3, row7);
+
+#undef dct_trn16
+#undef dct_trn32
+#undef dct_trn64
+   }
+
+   // row pass
+   // vrshrn_n_s32 only supports shifts up to 16, we need
+   // 17. so do a non-rounding shift of 16 first then follow
+   // up with a rounding shift by 1.
+   dct_pass(vshrn_n_s32, 16);
+
+   {
+      // pack and round
+      uint8x8_t p0 = vqrshrun_n_s16(row0, 1);
+      uint8x8_t p1 = vqrshrun_n_s16(row1, 1);
+      uint8x8_t p2 = vqrshrun_n_s16(row2, 1);
+      uint8x8_t p3 = vqrshrun_n_s16(row3, 1);
+      uint8x8_t p4 = vqrshrun_n_s16(row4, 1);
+      uint8x8_t p5 = vqrshrun_n_s16(row5, 1);
+      uint8x8_t p6 = vqrshrun_n_s16(row6, 1);
+      uint8x8_t p7 = vqrshrun_n_s16(row7, 1);
+
+      // again, these can translate into one instruction, but often don't.
+#define dct_trn8_8(x, y) { uint8x8x2_t t = vtrn_u8(x, y); x = t.val[0]; y = t.val[1]; }
+#define dct_trn8_16(x, y) { uint16x4x2_t t = vtrn_u16(vreinterpret_u16_u8(x), vreinterpret_u16_u8(y)); x = vreinterpret_u8_u16(t.val[0]); y = vreinterpret_u8_u16(t.val[1]); }
+#define dct_trn8_32(x, y) { uint32x2x2_t t = vtrn_u32(vreinterpret_u32_u8(x), vreinterpret_u32_u8(y)); x = vreinterpret_u8_u32(t.val[0]); y = vreinterpret_u8_u32(t.val[1]); }
+
+      // sadly can't use interleaved stores here since we only write
+      // 8 bytes to each scan line!
+
+      // 8x8 8-bit transpose pass 1
+      dct_trn8_8(p0, p1);
+      dct_trn8_8(p2, p3);
+      dct_trn8_8(p4, p5);
+      dct_trn8_8(p6, p7);
+
+      // pass 2
+      dct_trn8_16(p0, p2);
+      dct_trn8_16(p1, p3);
+      dct_trn8_16(p4, p6);
+      dct_trn8_16(p5, p7);
+
+      // pass 3
+      dct_trn8_32(p0, p4);
+      dct_trn8_32(p1, p5);
+      dct_trn8_32(p2, p6);
+      dct_trn8_32(p3, p7);
+
+      // store
+      vst1_u8(out, p0); out += out_stride;
+      vst1_u8(out, p1); out += out_stride;
+      vst1_u8(out, p2); out += out_stride;
+      vst1_u8(out, p3); out += out_stride;
+      vst1_u8(out, p4); out += out_stride;
+      vst1_u8(out, p5); out += out_stride;
+      vst1_u8(out, p6); out += out_stride;
+      vst1_u8(out, p7);
+
+#undef dct_trn8_8
+#undef dct_trn8_16
+#undef dct_trn8_32
+   }
+
+#undef dct_long_mul
+#undef dct_long_mac
+#undef dct_widen
+#undef dct_wadd
+#undef dct_wsub
+#undef dct_bfly32o
+#undef dct_pass
+}
+
+#endif // STBI_NEON
+
+#define STBI__MARKER_none  0xff
+// if there's a pending marker from the entropy stream, return that
+// otherwise, fetch from the stream and get a marker. if there's no
+// marker, return 0xff, which is never a valid marker value
+static stbi_uc stbi__get_marker(stbi__jpeg *j)
+{
+   stbi_uc x;
+   if (j->marker != STBI__MARKER_none) { x = j->marker; j->marker = STBI__MARKER_none; return x; }
+   x = stbi__get8(j->s);
+   if (x != 0xff) return STBI__MARKER_none;
+   while (x == 0xff)
+      x = stbi__get8(j->s); // consume repeated 0xff fill bytes
+   return x;
+}
+
+// in each scan, we'll have scan_n components, and the order
+// of the components is specified by order[]
+#define STBI__RESTART(x)     ((x) >= 0xd0 && (x) <= 0xd7)
+
+// after a restart interval, stbi__jpeg_reset the entropy decoder and
+// the dc prediction
+static void stbi__jpeg_reset(stbi__jpeg *j)
+{
+   j->code_bits = 0;
+   j->code_buffer = 0;
+   j->nomore = 0;
+   j->img_comp[0].dc_pred = j->img_comp[1].dc_pred = j->img_comp[2].dc_pred = j->img_comp[3].dc_pred = 0;
+   j->marker = STBI__MARKER_none;
+   j->todo = j->restart_interval ? j->restart_interval : 0x7fffffff;
+   j->eob_run = 0;
+   // no more than 1<<31 MCUs if no restart_interal? that's plenty safe,
+   // since we don't even allow 1<<30 pixels
+}
+
+static int stbi__parse_entropy_coded_data(stbi__jpeg *z)
+{
+   stbi__jpeg_reset(z);
+   if (!z->progressive) {
+      if (z->scan_n == 1) {
+         int i,j;
+         STBI_SIMD_ALIGN(short, data[64]);
+         int n = z->order[0];
+         // non-interleaved data, we just need to process one block at a time,
+         // in trivial scanline order
+         // number of blocks to do just depends on how many actual "pixels" this
+         // component has, independent of interleaved MCU blocking and such
+         int w = (z->img_comp[n].x+7) >> 3;
+         int h = (z->img_comp[n].y+7) >> 3;
+         for (j=0; j < h; ++j) {
+            for (i=0; i < w; ++i) {
+               int ha = z->img_comp[n].ha;
+               if (!stbi__jpeg_decode_block(z, data, z->huff_dc+z->img_comp[n].hd, z->huff_ac+ha, z->fast_ac[ha], n, z->dequant[z->img_comp[n].tq])) return 0;
+               z->idct_block_kernel(z->img_comp[n].data+z->img_comp[n].w2*j*8+i*8, z->img_comp[n].w2, data);
+               // every data block is an MCU, so countdown the restart interval
+               if (--z->todo <= 0) {
+                  if (z->code_bits < 24) stbi__grow_buffer_unsafe(z);
+                  // if it's NOT a restart, then just bail, so we get corrupt data
+                  // rather than no data
+                  if (!STBI__RESTART(z->marker)) return 1;
+                  stbi__jpeg_reset(z);
+               }
+            }
+         }
+         return 1;
+      } else { // interleaved
+         int i,j,k,x,y;
+         STBI_SIMD_ALIGN(short, data[64]);
+         for (j=0; j < z->img_mcu_y; ++j) {
+            for (i=0; i < z->img_mcu_x; ++i) {
+               // scan an interleaved mcu... process scan_n components in order
+               for (k=0; k < z->scan_n; ++k) {
+                  int n = z->order[k];
+                  // scan out an mcu's worth of this component; that's just determined
+                  // by the basic H and V specified for the component
+                  for (y=0; y < z->img_comp[n].v; ++y) {
+                     for (x=0; x < z->img_comp[n].h; ++x) {
+                        int x2 = (i*z->img_comp[n].h + x)*8;
+                        int y2 = (j*z->img_comp[n].v + y)*8;
+                        int ha = z->img_comp[n].ha;
+                        if (!stbi__jpeg_decode_block(z, data, z->huff_dc+z->img_comp[n].hd, z->huff_ac+ha, z->fast_ac[ha], n, z->dequant[z->img_comp[n].tq])) return 0;
+                        z->idct_block_kernel(z->img_comp[n].data+z->img_comp[n].w2*y2+x2, z->img_comp[n].w2, data);
+                     }
+                  }
+               }
+               // after all interleaved components, that's an interleaved MCU,
+               // so now count down the restart interval
+               if (--z->todo <= 0) {
+                  if (z->code_bits < 24) stbi__grow_buffer_unsafe(z);
+                  if (!STBI__RESTART(z->marker)) return 1;
+                  stbi__jpeg_reset(z);
+               }
+            }
+         }
+         return 1;
+      }
+   } else {
+      if (z->scan_n == 1) {
+         int i,j;
+         int n = z->order[0];
+         // non-interleaved data, we just need to process one block at a time,
+         // in trivial scanline order
+         // number of blocks to do just depends on how many actual "pixels" this
+         // component has, independent of interleaved MCU blocking and such
+         int w = (z->img_comp[n].x+7) >> 3;
+         int h = (z->img_comp[n].y+7) >> 3;
+         for (j=0; j < h; ++j) {
+            for (i=0; i < w; ++i) {
+               short *data = z->img_comp[n].coeff + 64 * (i + j * z->img_comp[n].coeff_w);
+               if (z->spec_start == 0) {
+                  if (!stbi__jpeg_decode_block_prog_dc(z, data, &z->huff_dc[z->img_comp[n].hd], n))
+                     return 0;
+               } else {
+                  int ha = z->img_comp[n].ha;
+                  if (!stbi__jpeg_decode_block_prog_ac(z, data, &z->huff_ac[ha], z->fast_ac[ha]))
+                     return 0;
+               }
+               // every data block is an MCU, so countdown the restart interval
+               if (--z->todo <= 0) {
+                  if (z->code_bits < 24) stbi__grow_buffer_unsafe(z);
+                  if (!STBI__RESTART(z->marker)) return 1;
+                  stbi__jpeg_reset(z);
+               }
+            }
+         }
+         return 1;
+      } else { // interleaved
+         int i,j,k,x,y;
+         for (j=0; j < z->img_mcu_y; ++j) {
+            for (i=0; i < z->img_mcu_x; ++i) {
+               // scan an interleaved mcu... process scan_n components in order
+               for (k=0; k < z->scan_n; ++k) {
+                  int n = z->order[k];
+                  // scan out an mcu's worth of this component; that's just determined
+                  // by the basic H and V specified for the component
+                  for (y=0; y < z->img_comp[n].v; ++y) {
+                     for (x=0; x < z->img_comp[n].h; ++x) {
+                        int x2 = (i*z->img_comp[n].h + x);
+                        int y2 = (j*z->img_comp[n].v + y);
+                        short *data = z->img_comp[n].coeff + 64 * (x2 + y2 * z->img_comp[n].coeff_w);
+                        if (!stbi__jpeg_decode_block_prog_dc(z, data, &z->huff_dc[z->img_comp[n].hd], n))
+                           return 0;
+                     }
+                  }
+               }
+               // after all interleaved components, that's an interleaved MCU,
+               // so now count down the restart interval
+               if (--z->todo <= 0) {
+                  if (z->code_bits < 24) stbi__grow_buffer_unsafe(z);
+                  if (!STBI__RESTART(z->marker)) return 1;
+                  stbi__jpeg_reset(z);
+               }
+            }
+         }
+         return 1;
+      }
+   }
+}
+
+static void stbi__jpeg_dequantize(short *data, stbi__uint16 *dequant)
+{
+   int i;
+   for (i=0; i < 64; ++i)
+      data[i] *= dequant[i];
+}
+
+static void stbi__jpeg_finish(stbi__jpeg *z)
+{
+   if (z->progressive) {
+      // dequantize and idct the data
+      int i,j,n;
+      for (n=0; n < z->s->img_n; ++n) {
+         int w = (z->img_comp[n].x+7) >> 3;
+         int h = (z->img_comp[n].y+7) >> 3;
+         for (j=0; j < h; ++j) {
+            for (i=0; i < w; ++i) {
+               short *data = z->img_comp[n].coeff + 64 * (i + j * z->img_comp[n].coeff_w);
+               stbi__jpeg_dequantize(data, z->dequant[z->img_comp[n].tq]);
+               z->idct_block_kernel(z->img_comp[n].data+z->img_comp[n].w2*j*8+i*8, z->img_comp[n].w2, data);
+            }
+         }
+      }
+   }
+}
+
+static int stbi__process_marker(stbi__jpeg *z, int m)
+{
+   int L;
+   switch (m) {
+      case STBI__MARKER_none: // no marker found
+         return stbi__err("expected marker","Corrupt JPEG");
+
+      case 0xDD: // DRI - specify restart interval
+         if (stbi__get16be(z->s) != 4) return stbi__err("bad DRI len","Corrupt JPEG");
+         z->restart_interval = stbi__get16be(z->s);
+         return 1;
+
+      case 0xDB: // DQT - define quantization table
+         L = stbi__get16be(z->s)-2;
+         while (L > 0) {
+            int q = stbi__get8(z->s);
+            int p = q >> 4, sixteen = (p != 0);
+            int t = q & 15,i;
+            if (p != 0 && p != 1) return stbi__err("bad DQT type","Corrupt JPEG");
+            if (t > 3) return stbi__err("bad DQT table","Corrupt JPEG");
+
+            for (i=0; i < 64; ++i)
+               z->dequant[t][stbi__jpeg_dezigzag[i]] = (stbi__uint16)(sixteen ? stbi__get16be(z->s) : stbi__get8(z->s));
+            L -= (sixteen ? 129 : 65);
+         }
+         return L==0;
+
+      case 0xC4: // DHT - define huffman table
+         L = stbi__get16be(z->s)-2;
+         while (L > 0) {
+            stbi_uc *v;
+            int sizes[16],i,n=0;
+            int q = stbi__get8(z->s);
+            int tc = q >> 4;
+            int th = q & 15;
+            if (tc > 1 || th > 3) return stbi__err("bad DHT header","Corrupt JPEG");
+            for (i=0; i < 16; ++i) {
+               sizes[i] = stbi__get8(z->s);
+               n += sizes[i];
+            }
+            L -= 17;
+            if (tc == 0) {
+               if (!stbi__build_huffman(z->huff_dc+th, sizes)) return 0;
+               v = z->huff_dc[th].values;
+            } else {
+               if (!stbi__build_huffman(z->huff_ac+th, sizes)) return 0;
+               v = z->huff_ac[th].values;
+            }
+            for (i=0; i < n; ++i)
+               v[i] = stbi__get8(z->s);
+            if (tc != 0)
+               stbi__build_fast_ac(z->fast_ac[th], z->huff_ac + th);
+            L -= n;
+         }
+         return L==0;
+   }
+
+   // check for comment block or APP blocks
+   if ((m >= 0xE0 && m <= 0xEF) || m == 0xFE) {
+      L = stbi__get16be(z->s);
+      if (L < 2) {
+         if (m == 0xFE)
+            return stbi__err("bad COM len","Corrupt JPEG");
+         else
+            return stbi__err("bad APP len","Corrupt JPEG");
+      }
+      L -= 2;
+
+      if (m == 0xE0 && L >= 5) { // JFIF APP0 segment
+         static const unsigned char tag[5] = {'J','F','I','F','\0'};
+         int ok = 1;
+         int i;
+         for (i=0; i < 5; ++i)
+            if (stbi__get8(z->s) != tag[i])
+               ok = 0;
+         L -= 5;
+         if (ok)
+            z->jfif = 1;
+      } else if (m == 0xEE && L >= 12) { // Adobe APP14 segment
+         static const unsigned char tag[6] = {'A','d','o','b','e','\0'};
+         int ok = 1;
+         int i;
+         for (i=0; i < 6; ++i)
+            if (stbi__get8(z->s) != tag[i])
+               ok = 0;
+         L -= 6;
+         if (ok) {
+            stbi__get8(z->s); // version
+            stbi__get16be(z->s); // flags0
+            stbi__get16be(z->s); // flags1
+            z->app14_color_transform = stbi__get8(z->s); // color transform
+            L -= 6;
+         }
+      }
+
+      stbi__skip(z->s, L);
+      return 1;
+   }
+
+   return stbi__err("unknown marker","Corrupt JPEG");
+}
+
+// after we see SOS
+static int stbi__process_scan_header(stbi__jpeg *z)
+{
+   int i;
+   int Ls = stbi__get16be(z->s);
+   z->scan_n = stbi__get8(z->s);
+   if (z->scan_n < 1 || z->scan_n > 4 || z->scan_n > (int) z->s->img_n) return stbi__err("bad SOS component count","Corrupt JPEG");
+   if (Ls != 6+2*z->scan_n) return stbi__err("bad SOS len","Corrupt JPEG");
+   for (i=0; i < z->scan_n; ++i) {
+      int id = stbi__get8(z->s), which;
+      int q = stbi__get8(z->s);
+      for (which = 0; which < z->s->img_n; ++which)
+         if (z->img_comp[which].id == id)
+            break;
+      if (which == z->s->img_n) return 0; // no match
+      z->img_comp[which].hd = q >> 4;   if (z->img_comp[which].hd > 3) return stbi__err("bad DC huff","Corrupt JPEG");
+      z->img_comp[which].ha = q & 15;   if (z->img_comp[which].ha > 3) return stbi__err("bad AC huff","Corrupt JPEG");
+      z->order[i] = which;
+   }
+
+   {
+      int aa;
+      z->spec_start = stbi__get8(z->s);
+      z->spec_end   = stbi__get8(z->s); // should be 63, but might be 0
+      aa = stbi__get8(z->s);
+      z->succ_high = (aa >> 4);
+      z->succ_low  = (aa & 15);
+      if (z->progressive) {
+         if (z->spec_start > 63 || z->spec_end > 63  || z->spec_start > z->spec_end || z->succ_high > 13 || z->succ_low > 13)
+            return stbi__err("bad SOS", "Corrupt JPEG");
+      } else {
+         if (z->spec_start != 0) return stbi__err("bad SOS","Corrupt JPEG");
+         if (z->succ_high != 0 || z->succ_low != 0) return stbi__err("bad SOS","Corrupt JPEG");
+         z->spec_end = 63;
+      }
+   }
+
+   return 1;
+}
+
+static int stbi__free_jpeg_components(stbi__jpeg *z, int ncomp, int why)
+{
+   int i;
+   for (i=0; i < ncomp; ++i) {
+      if (z->img_comp[i].raw_data) {
+         STBI_FREE(z->img_comp[i].raw_data);
+         z->img_comp[i].raw_data = NULL;
+         z->img_comp[i].data = NULL;
+      }
+      if (z->img_comp[i].raw_coeff) {
+         STBI_FREE(z->img_comp[i].raw_coeff);
+         z->img_comp[i].raw_coeff = 0;
+         z->img_comp[i].coeff = 0;
+      }
+      if (z->img_comp[i].linebuf) {
+         STBI_FREE(z->img_comp[i].linebuf);
+         z->img_comp[i].linebuf = NULL;
+      }
+   }
+   return why;
+}
+
+static int stbi__process_frame_header(stbi__jpeg *z, int scan)
+{
+   stbi__context *s = z->s;
+   int Lf,p,i,q, h_max=1,v_max=1,c;
+   Lf = stbi__get16be(s);         if (Lf < 11) return stbi__err("bad SOF len","Corrupt JPEG"); // JPEG
+   p  = stbi__get8(s);            if (p != 8) return stbi__err("only 8-bit","JPEG format not supported: 8-bit only"); // JPEG baseline
+   s->img_y = stbi__get16be(s);   if (s->img_y == 0) return stbi__err("no header height", "JPEG format not supported: delayed height"); // Legal, but we don't handle it--but neither does IJG
+   s->img_x = stbi__get16be(s);   if (s->img_x == 0) return stbi__err("0 width","Corrupt JPEG"); // JPEG requires
+   c = stbi__get8(s);
+   if (c != 3 && c != 1 && c != 4) return stbi__err("bad component count","Corrupt JPEG");
+   s->img_n = c;
+   for (i=0; i < c; ++i) {
+      z->img_comp[i].data = NULL;
+      z->img_comp[i].linebuf = NULL;
+   }
+
+   if (Lf != 8+3*s->img_n) return stbi__err("bad SOF len","Corrupt JPEG");
+
+   z->rgb = 0;
+   for (i=0; i < s->img_n; ++i) {
+      static const unsigned char rgb[3] = { 'R', 'G', 'B' };
+      z->img_comp[i].id = stbi__get8(s);
+      if (s->img_n == 3 && z->img_comp[i].id == rgb[i])
+         ++z->rgb;
+      q = stbi__get8(s);
+      z->img_comp[i].h = (q >> 4);  if (!z->img_comp[i].h || z->img_comp[i].h > 4) return stbi__err("bad H","Corrupt JPEG");
+      z->img_comp[i].v = q & 15;    if (!z->img_comp[i].v || z->img_comp[i].v > 4) return stbi__err("bad V","Corrupt JPEG");
+      z->img_comp[i].tq = stbi__get8(s);  if (z->img_comp[i].tq > 3) return stbi__err("bad TQ","Corrupt JPEG");
+   }
+
+   if (scan != STBI__SCAN_load) return 1;
+
+   if (!stbi__mad3sizes_valid(s->img_x, s->img_y, s->img_n, 0)) return stbi__err("too large", "Image too large to decode");
+
+   for (i=0; i < s->img_n; ++i) {
+      if (z->img_comp[i].h > h_max) h_max = z->img_comp[i].h;
+      if (z->img_comp[i].v > v_max) v_max = z->img_comp[i].v;
+   }
+
+   // compute interleaved mcu info
+   z->img_h_max = h_max;
+   z->img_v_max = v_max;
+   z->img_mcu_w = h_max * 8;
+   z->img_mcu_h = v_max * 8;
+   // these sizes can't be more than 17 bits
+   z->img_mcu_x = (s->img_x + z->img_mcu_w-1) / z->img_mcu_w;
+   z->img_mcu_y = (s->img_y + z->img_mcu_h-1) / z->img_mcu_h;
+
+   for (i=0; i < s->img_n; ++i) {
+      // number of effective pixels (e.g. for non-interleaved MCU)
+      z->img_comp[i].x = (s->img_x * z->img_comp[i].h + h_max-1) / h_max;
+      z->img_comp[i].y = (s->img_y * z->img_comp[i].v + v_max-1) / v_max;
+      // to simplify generation, we'll allocate enough memory to decode
+      // the bogus oversized data from using interleaved MCUs and their
+      // big blocks (e.g. a 16x16 iMCU on an image of width 33); we won't
+      // discard the extra data until colorspace conversion
+      //
+      // img_mcu_x, img_mcu_y: <=17 bits; comp[i].h and .v are <=4 (checked earlier)
+      // so these muls can't overflow with 32-bit ints (which we require)
+      z->img_comp[i].w2 = z->img_mcu_x * z->img_comp[i].h * 8;
+      z->img_comp[i].h2 = z->img_mcu_y * z->img_comp[i].v * 8;
+      z->img_comp[i].coeff = 0;
+      z->img_comp[i].raw_coeff = 0;
+      z->img_comp[i].linebuf = NULL;
+      z->img_comp[i].raw_data = stbi__malloc_mad2(z->img_comp[i].w2, z->img_comp[i].h2, 15);
+      if (z->img_comp[i].raw_data == NULL)
+         return stbi__free_jpeg_components(z, i+1, stbi__err("outofmem", "Out of memory"));
+      // align blocks for idct using mmx/sse
+      z->img_comp[i].data = (stbi_uc*) (((size_t) z->img_comp[i].raw_data + 15) & ~15);
+      if (z->progressive) {
+         // w2, h2 are multiples of 8 (see above)
+         z->img_comp[i].coeff_w = z->img_comp[i].w2 / 8;
+         z->img_comp[i].coeff_h = z->img_comp[i].h2 / 8;
+         z->img_comp[i].raw_coeff = stbi__malloc_mad3(z->img_comp[i].w2, z->img_comp[i].h2, sizeof(short), 15);
+         if (z->img_comp[i].raw_coeff == NULL)
+            return stbi__free_jpeg_components(z, i+1, stbi__err("outofmem", "Out of memory"));
+         z->img_comp[i].coeff = (short*) (((size_t) z->img_comp[i].raw_coeff + 15) & ~15);
+      }
+   }
+
+   return 1;
+}
+
+// use comparisons since in some cases we handle more than one case (e.g. SOF)
+#define stbi__DNL(x)         ((x) == 0xdc)
+#define stbi__SOI(x)         ((x) == 0xd8)
+#define stbi__EOI(x)         ((x) == 0xd9)
+#define stbi__SOF(x)         ((x) == 0xc0 || (x) == 0xc1 || (x) == 0xc2)
+#define stbi__SOS(x)         ((x) == 0xda)
+
+#define stbi__SOF_progressive(x)   ((x) == 0xc2)
+
+static int stbi__decode_jpeg_header(stbi__jpeg *z, int scan)
+{
+   int m;
+   z->jfif = 0;
+   z->app14_color_transform = -1; // valid values are 0,1,2
+   z->marker = STBI__MARKER_none; // initialize cached marker to empty
+   m = stbi__get_marker(z);
+   if (!stbi__SOI(m)) return stbi__err("no SOI","Corrupt JPEG");
+   if (scan == STBI__SCAN_type) return 1;
+   m = stbi__get_marker(z);
+   while (!stbi__SOF(m)) {
+      if (!stbi__process_marker(z,m)) return 0;
+      m = stbi__get_marker(z);
+      while (m == STBI__MARKER_none) {
+         // some files have extra padding after their blocks, so ok, we'll scan
+         if (stbi__at_eof(z->s)) return stbi__err("no SOF", "Corrupt JPEG");
+         m = stbi__get_marker(z);
+      }
+   }
+   z->progressive = stbi__SOF_progressive(m);
+   if (!stbi__process_frame_header(z, scan)) return 0;
+   return 1;
+}
+
+// decode image to YCbCr format
+static int stbi__decode_jpeg_image(stbi__jpeg *j)
+{
+   int m;
+   for (m = 0; m < 4; m++) {
+      j->img_comp[m].raw_data = NULL;
+      j->img_comp[m].raw_coeff = NULL;
+   }
+   j->restart_interval = 0;
+   if (!stbi__decode_jpeg_header(j, STBI__SCAN_load)) return 0;
+   m = stbi__get_marker(j);
+   while (!stbi__EOI(m)) {
+      if (stbi__SOS(m)) {
+         if (!stbi__process_scan_header(j)) return 0;
+         if (!stbi__parse_entropy_coded_data(j)) return 0;
+         if (j->marker == STBI__MARKER_none ) {
+            // handle 0s at the end of image data from IP Kamera 9060
+            while (!stbi__at_eof(j->s)) {
+               int x = stbi__get8(j->s);
+               if (x == 255) {
+                  j->marker = stbi__get8(j->s);
+                  break;
+               }
+            }
+            // if we reach eof without hitting a marker, stbi__get_marker() below will fail and we'll eventually return 0
+         }
+      } else if (stbi__DNL(m)) {
+         int Ld = stbi__get16be(j->s);
+         stbi__uint32 NL = stbi__get16be(j->s);
+         if (Ld != 4) return stbi__err("bad DNL len", "Corrupt JPEG");
+         if (NL != j->s->img_y) return stbi__err("bad DNL height", "Corrupt JPEG");
+      } else {
+         if (!stbi__process_marker(j, m)) return 0;
+      }
+      m = stbi__get_marker(j);
+   }
+   if (j->progressive)
+      stbi__jpeg_finish(j);
+   return 1;
+}
+
+// static jfif-centered resampling (across block boundaries)
+
+typedef stbi_uc *(*resample_row_func)(stbi_uc *out, stbi_uc *in0, stbi_uc *in1,
+                                    int w, int hs);
+
+#define stbi__div4(x) ((stbi_uc) ((x) >> 2))
+
+static stbi_uc *resample_row_1(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs)
+{
+   STBI_NOTUSED(out);
+   STBI_NOTUSED(in_far);
+   STBI_NOTUSED(w);
+   STBI_NOTUSED(hs);
+   return in_near;
+}
+
+static stbi_uc* stbi__resample_row_v_2(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs)
+{
+   // need to generate two samples vertically for every one in input
+   int i;
+   STBI_NOTUSED(hs);
+   for (i=0; i < w; ++i)
+      out[i] = stbi__div4(3*in_near[i] + in_far[i] + 2);
+   return out;
+}
+
+static stbi_uc*  stbi__resample_row_h_2(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs)
+{
+   // need to generate two samples horizontally for every one in input
+   int i;
+   stbi_uc *input = in_near;
+
+   if (w == 1) {
+      // if only one sample, can't do any interpolation
+      out[0] = out[1] = input[0];
+      return out;
+   }
+
+   out[0] = input[0];
+   out[1] = stbi__div4(input[0]*3 + input[1] + 2);
+   for (i=1; i < w-1; ++i) {
+      int n = 3*input[i]+2;
+      out[i*2+0] = stbi__div4(n+input[i-1]);
+      out[i*2+1] = stbi__div4(n+input[i+1]);
+   }
+   out[i*2+0] = stbi__div4(input[w-2]*3 + input[w-1] + 2);
+   out[i*2+1] = input[w-1];
+
+   STBI_NOTUSED(in_far);
+   STBI_NOTUSED(hs);
+
+   return out;
+}
+
+#define stbi__div16(x) ((stbi_uc) ((x) >> 4))
+
+static stbi_uc *stbi__resample_row_hv_2(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs)
+{
+   // need to generate 2x2 samples for every one in input
+   int i,t0,t1;
+   if (w == 1) {
+      out[0] = out[1] = stbi__div4(3*in_near[0] + in_far[0] + 2);
+      return out;
+   }
+
+   t1 = 3*in_near[0] + in_far[0];
+   out[0] = stbi__div4(t1+2);
+   for (i=1; i < w; ++i) {
+      t0 = t1;
+      t1 = 3*in_near[i]+in_far[i];
+      out[i*2-1] = stbi__div16(3*t0 + t1 + 8);
+      out[i*2  ] = stbi__div16(3*t1 + t0 + 8);
+   }
+   out[w*2-1] = stbi__div4(t1+2);
+
+   STBI_NOTUSED(hs);
+
+   return out;
+}
+
+#if defined(STBI_SSE2) || defined(STBI_NEON)
+static stbi_uc *stbi__resample_row_hv_2_simd(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs)
+{
+   // need to generate 2x2 samples for every one in input
+   int i=0,t0,t1;
+
+   if (w == 1) {
+      out[0] = out[1] = stbi__div4(3*in_near[0] + in_far[0] + 2);
+      return out;
+   }
+
+   t1 = 3*in_near[0] + in_far[0];
+   // process groups of 8 pixels for as long as we can.
+   // note we can't handle the last pixel in a row in this loop
+   // because we need to handle the filter boundary conditions.
+   for (; i < ((w-1) & ~7); i += 8) {
+#if defined(STBI_SSE2)
+      // load and perform the vertical filtering pass
+      // this uses 3*x + y = 4*x + (y - x)
+      __m128i zero  = _mm_setzero_si128();
+      __m128i farb  = _mm_loadl_epi64((__m128i *) (in_far + i));
+      __m128i nearb = _mm_loadl_epi64((__m128i *) (in_near + i));
+      __m128i farw  = _mm_unpacklo_epi8(farb, zero);
+      __m128i nearw = _mm_unpacklo_epi8(nearb, zero);
+      __m128i diff  = _mm_sub_epi16(farw, nearw);
+      __m128i nears = _mm_slli_epi16(nearw, 2);
+      __m128i curr  = _mm_add_epi16(nears, diff); // current row
+
+      // horizontal filter works the same based on shifted vers of current
+      // row. "prev" is current row shifted right by 1 pixel; we need to
+      // insert the previous pixel value (from t1).
+      // "next" is current row shifted left by 1 pixel, with first pixel
+      // of next block of 8 pixels added in.
+      __m128i prv0 = _mm_slli_si128(curr, 2);
+      __m128i nxt0 = _mm_srli_si128(curr, 2);
+      __m128i prev = _mm_insert_epi16(prv0, t1, 0);
+      __m128i next = _mm_insert_epi16(nxt0, 3*in_near[i+8] + in_far[i+8], 7);
+
+      // horizontal filter, polyphase implementation since it's convenient:
+      // even pixels = 3*cur + prev = cur*4 + (prev - cur)
+      // odd  pixels = 3*cur + next = cur*4 + (next - cur)
+      // note the shared term.
+      __m128i bias  = _mm_set1_epi16(8);
+      __m128i curs = _mm_slli_epi16(curr, 2);
+      __m128i prvd = _mm_sub_epi16(prev, curr);
+      __m128i nxtd = _mm_sub_epi16(next, curr);
+      __m128i curb = _mm_add_epi16(curs, bias);
+      __m128i even = _mm_add_epi16(prvd, curb);
+      __m128i odd  = _mm_add_epi16(nxtd, curb);
+
+      // interleave even and odd pixels, then undo scaling.
+      __m128i int0 = _mm_unpacklo_epi16(even, odd);
+      __m128i int1 = _mm_unpackhi_epi16(even, odd);
+      __m128i de0  = _mm_srli_epi16(int0, 4);
+      __m128i de1  = _mm_srli_epi16(int1, 4);
+
+      // pack and write output
+      __m128i outv = _mm_packus_epi16(de0, de1);
+      _mm_storeu_si128((__m128i *) (out + i*2), outv);
+#elif defined(STBI_NEON)
+      // load and perform the vertical filtering pass
+      // this uses 3*x + y = 4*x + (y - x)
+      uint8x8_t farb  = vld1_u8(in_far + i);
+      uint8x8_t nearb = vld1_u8(in_near + i);
+      int16x8_t diff  = vreinterpretq_s16_u16(vsubl_u8(farb, nearb));
+      int16x8_t nears = vreinterpretq_s16_u16(vshll_n_u8(nearb, 2));
+      int16x8_t curr  = vaddq_s16(nears, diff); // current row
+
+      // horizontal filter works the same based on shifted vers of current
+      // row. "prev" is current row shifted right by 1 pixel; we need to
+      // insert the previous pixel value (from t1).
+      // "next" is current row shifted left by 1 pixel, with first pixel
+      // of next block of 8 pixels added in.
+      int16x8_t prv0 = vextq_s16(curr, curr, 7);
+      int16x8_t nxt0 = vextq_s16(curr, curr, 1);
+      int16x8_t prev = vsetq_lane_s16(t1, prv0, 0);
+      int16x8_t next = vsetq_lane_s16(3*in_near[i+8] + in_far[i+8], nxt0, 7);
+
+      // horizontal filter, polyphase implementation since it's convenient:
+      // even pixels = 3*cur + prev = cur*4 + (prev - cur)
+      // odd  pixels = 3*cur + next = cur*4 + (next - cur)
+      // note the shared term.
+      int16x8_t curs = vshlq_n_s16(curr, 2);
+      int16x8_t prvd = vsubq_s16(prev, curr);
+      int16x8_t nxtd = vsubq_s16(next, curr);
+      int16x8_t even = vaddq_s16(curs, prvd);
+      int16x8_t odd  = vaddq_s16(curs, nxtd);
+
+      // undo scaling and round, then store with even/odd phases interleaved
+      uint8x8x2_t o;
+      o.val[0] = vqrshrun_n_s16(even, 4);
+      o.val[1] = vqrshrun_n_s16(odd,  4);
+      vst2_u8(out + i*2, o);
+#endif
+
+      // "previous" value for next iter
+      t1 = 3*in_near[i+7] + in_far[i+7];
+   }
+
+   t0 = t1;
+   t1 = 3*in_near[i] + in_far[i];
+   out[i*2] = stbi__div16(3*t1 + t0 + 8);
+
+   for (++i; i < w; ++i) {
+      t0 = t1;
+      t1 = 3*in_near[i]+in_far[i];
+      out[i*2-1] = stbi__div16(3*t0 + t1 + 8);
+      out[i*2  ] = stbi__div16(3*t1 + t0 + 8);
+   }
+   out[w*2-1] = stbi__div4(t1+2);
+
+   STBI_NOTUSED(hs);
+
+   return out;
+}
+#endif
+
+static stbi_uc *stbi__resample_row_generic(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs)
+{
+   // resample with nearest-neighbor
+   int i,j;
+   STBI_NOTUSED(in_far);
+   for (i=0; i < w; ++i)
+      for (j=0; j < hs; ++j)
+         out[i*hs+j] = in_near[i];
+   return out;
+}
+
+// this is a reduced-precision calculation of YCbCr-to-RGB introduced
+// to make sure the code produces the same results in both SIMD and scalar
+#define stbi__float2fixed(x)  (((int) ((x) * 4096.0f + 0.5f)) << 8)
+static void stbi__YCbCr_to_RGB_row(stbi_uc *out, const stbi_uc *y, const stbi_uc *pcb, const stbi_uc *pcr, int count, int step)
+{
+   int i;
+   for (i=0; i < count; ++i) {
+      int y_fixed = (y[i] << 20) + (1<<19); // rounding
+      int r,g,b;
+      int cr = pcr[i] - 128;
+      int cb = pcb[i] - 128;
+      r = y_fixed +  cr* stbi__float2fixed(1.40200f);
+      g = y_fixed + (cr*-stbi__float2fixed(0.71414f)) + ((cb*-stbi__float2fixed(0.34414f)) & 0xffff0000);
+      b = y_fixed                                     +   cb* stbi__float2fixed(1.77200f);
+      r >>= 20;
+      g >>= 20;
+      b >>= 20;
+      if ((unsigned) r > 255) { if (r < 0) r = 0; else r = 255; }
+      if ((unsigned) g > 255) { if (g < 0) g = 0; else g = 255; }
+      if ((unsigned) b > 255) { if (b < 0) b = 0; else b = 255; }
+      out[0] = (stbi_uc)r;
+      out[1] = (stbi_uc)g;
+      out[2] = (stbi_uc)b;
+      out[3] = 255;
+      out += step;
+   }
+}
+
+#if defined(STBI_SSE2) || defined(STBI_NEON)
+static void stbi__YCbCr_to_RGB_simd(stbi_uc *out, stbi_uc const *y, stbi_uc const *pcb, stbi_uc const *pcr, int count, int step)
+{
+   int i = 0;
+
+#ifdef STBI_SSE2
+   // step == 3 is pretty ugly on the final interleave, and i'm not convinced
+   // it's useful in practice (you wouldn't use it for textures, for example).
+   // so just accelerate step == 4 case.
+   if (step == 4) {
+      // this is a fairly straightforward implementation and not super-optimized.
+      __m128i signflip  = _mm_set1_epi8(-0x80);
+      __m128i cr_const0 = _mm_set1_epi16(   (short) ( 1.40200f*4096.0f+0.5f));
+      __m128i cr_const1 = _mm_set1_epi16( - (short) ( 0.71414f*4096.0f+0.5f));
+      __m128i cb_const0 = _mm_set1_epi16( - (short) ( 0.34414f*4096.0f+0.5f));
+      __m128i cb_const1 = _mm_set1_epi16(   (short) ( 1.77200f*4096.0f+0.5f));
+      __m128i y_bias = _mm_set1_epi8((char) (unsigned char) 128);
+      __m128i xw = _mm_set1_epi16(255); // alpha channel
+
+      for (; i+7 < count; i += 8) {
+         // load
+         __m128i y_bytes = _mm_loadl_epi64((__m128i *) (y+i));
+         __m128i cr_bytes = _mm_loadl_epi64((__m128i *) (pcr+i));
+         __m128i cb_bytes = _mm_loadl_epi64((__m128i *) (pcb+i));
+         __m128i cr_biased = _mm_xor_si128(cr_bytes, signflip); // -128
+         __m128i cb_biased = _mm_xor_si128(cb_bytes, signflip); // -128
+
+         // unpack to short (and left-shift cr, cb by 8)
+         __m128i yw  = _mm_unpacklo_epi8(y_bias, y_bytes);
+         __m128i crw = _mm_unpacklo_epi8(_mm_setzero_si128(), cr_biased);
+         __m128i cbw = _mm_unpacklo_epi8(_mm_setzero_si128(), cb_biased);
+
+         // color transform
+         __m128i yws = _mm_srli_epi16(yw, 4);
+         __m128i cr0 = _mm_mulhi_epi16(cr_const0, crw);
+         __m128i cb0 = _mm_mulhi_epi16(cb_const0, cbw);
+         __m128i cb1 = _mm_mulhi_epi16(cbw, cb_const1);
+         __m128i cr1 = _mm_mulhi_epi16(crw, cr_const1);
+         __m128i rws = _mm_add_epi16(cr0, yws);
+         __m128i gwt = _mm_add_epi16(cb0, yws);
+         __m128i bws = _mm_add_epi16(yws, cb1);
+         __m128i gws = _mm_add_epi16(gwt, cr1);
+
+         // descale
+         __m128i rw = _mm_srai_epi16(rws, 4);
+         __m128i bw = _mm_srai_epi16(bws, 4);
+         __m128i gw = _mm_srai_epi16(gws, 4);
+
+         // back to byte, set up for transpose
+         __m128i brb = _mm_packus_epi16(rw, bw);
+         __m128i gxb = _mm_packus_epi16(gw, xw);
+
+         // transpose to interleave channels
+         __m128i t0 = _mm_unpacklo_epi8(brb, gxb);
+         __m128i t1 = _mm_unpackhi_epi8(brb, gxb);
+         __m128i o0 = _mm_unpacklo_epi16(t0, t1);
+         __m128i o1 = _mm_unpackhi_epi16(t0, t1);
+
+         // store
+         _mm_storeu_si128((__m128i *) (out + 0), o0);
+         _mm_storeu_si128((__m128i *) (out + 16), o1);
+         out += 32;
+      }
+   }
+#endif
+
+#ifdef STBI_NEON
+   // in this version, step=3 support would be easy to add. but is there demand?
+   if (step == 4) {
+      // this is a fairly straightforward implementation and not super-optimized.
+      uint8x8_t signflip = vdup_n_u8(0x80);
+      int16x8_t cr_const0 = vdupq_n_s16(   (short) ( 1.40200f*4096.0f+0.5f));
+      int16x8_t cr_const1 = vdupq_n_s16( - (short) ( 0.71414f*4096.0f+0.5f));
+      int16x8_t cb_const0 = vdupq_n_s16( - (short) ( 0.34414f*4096.0f+0.5f));
+      int16x8_t cb_const1 = vdupq_n_s16(   (short) ( 1.77200f*4096.0f+0.5f));
+
+      for (; i+7 < count; i += 8) {
+         // load
+         uint8x8_t y_bytes  = vld1_u8(y + i);
+         uint8x8_t cr_bytes = vld1_u8(pcr + i);
+         uint8x8_t cb_bytes = vld1_u8(pcb + i);
+         int8x8_t cr_biased = vreinterpret_s8_u8(vsub_u8(cr_bytes, signflip));
+         int8x8_t cb_biased = vreinterpret_s8_u8(vsub_u8(cb_bytes, signflip));
+
+         // expand to s16
+         int16x8_t yws = vreinterpretq_s16_u16(vshll_n_u8(y_bytes, 4));
+         int16x8_t crw = vshll_n_s8(cr_biased, 7);
+         int16x8_t cbw = vshll_n_s8(cb_biased, 7);
+
+         // color transform
+         int16x8_t cr0 = vqdmulhq_s16(crw, cr_const0);
+         int16x8_t cb0 = vqdmulhq_s16(cbw, cb_const0);
+         int16x8_t cr1 = vqdmulhq_s16(crw, cr_const1);
+         int16x8_t cb1 = vqdmulhq_s16(cbw, cb_const1);
+         int16x8_t rws = vaddq_s16(yws, cr0);
+         int16x8_t gws = vaddq_s16(vaddq_s16(yws, cb0), cr1);
+         int16x8_t bws = vaddq_s16(yws, cb1);
+
+         // undo scaling, round, convert to byte
+         uint8x8x4_t o;
+         o.val[0] = vqrshrun_n_s16(rws, 4);
+         o.val[1] = vqrshrun_n_s16(gws, 4);
+         o.val[2] = vqrshrun_n_s16(bws, 4);
+         o.val[3] = vdup_n_u8(255);
+
+         // store, interleaving r/g/b/a
+         vst4_u8(out, o);
+         out += 8*4;
+      }
+   }
+#endif
+
+   for (; i < count; ++i) {
+      int y_fixed = (y[i] << 20) + (1<<19); // rounding
+      int r,g,b;
+      int cr = pcr[i] - 128;
+      int cb = pcb[i] - 128;
+      r = y_fixed + cr* stbi__float2fixed(1.40200f);
+      g = y_fixed + cr*-stbi__float2fixed(0.71414f) + ((cb*-stbi__float2fixed(0.34414f)) & 0xffff0000);
+      b = y_fixed                                   +   cb* stbi__float2fixed(1.77200f);
+      r >>= 20;
+      g >>= 20;
+      b >>= 20;
+      if ((unsigned) r > 255) { if (r < 0) r = 0; else r = 255; }
+      if ((unsigned) g > 255) { if (g < 0) g = 0; else g = 255; }
+      if ((unsigned) b > 255) { if (b < 0) b = 0; else b = 255; }
+      out[0] = (stbi_uc)r;
+      out[1] = (stbi_uc)g;
+      out[2] = (stbi_uc)b;
+      out[3] = 255;
+      out += step;
+   }
+}
+#endif
+
+// set up the kernels
+static void stbi__setup_jpeg(stbi__jpeg *j)
+{
+   j->idct_block_kernel = stbi__idct_block;
+   j->YCbCr_to_RGB_kernel = stbi__YCbCr_to_RGB_row;
+   j->resample_row_hv_2_kernel = stbi__resample_row_hv_2;
+
+#ifdef STBI_SSE2
+   if (stbi__sse2_available()) {
+      j->idct_block_kernel = stbi__idct_simd;
+      j->YCbCr_to_RGB_kernel = stbi__YCbCr_to_RGB_simd;
+      j->resample_row_hv_2_kernel = stbi__resample_row_hv_2_simd;
+   }
+#endif
+
+#ifdef STBI_NEON
+   j->idct_block_kernel = stbi__idct_simd;
+   j->YCbCr_to_RGB_kernel = stbi__YCbCr_to_RGB_simd;
+   j->resample_row_hv_2_kernel = stbi__resample_row_hv_2_simd;
+#endif
+}
+
+// clean up the temporary component buffers
+static void stbi__cleanup_jpeg(stbi__jpeg *j)
+{
+   stbi__free_jpeg_components(j, j->s->img_n, 0);
+}
+
+typedef struct
+{
+   resample_row_func resample;
+   stbi_uc *line0,*line1;
+   int hs,vs;   // expansion factor in each axis
+   int w_lores; // horizontal pixels pre-expansion
+   int ystep;   // how far through vertical expansion we are
+   int ypos;    // which pre-expansion row we're on
+} stbi__resample;
+
+// fast 0..255 * 0..255 => 0..255 rounded multiplication
+static stbi_uc stbi__blinn_8x8(stbi_uc x, stbi_uc y)
+{
+   unsigned int t = x*y + 128;
+   return (stbi_uc) ((t + (t >>8)) >> 8);
+}
+
+static stbi_uc *load_jpeg_image(stbi__jpeg *z, int *out_x, int *out_y, int *comp, int req_comp)
+{
+   int n, decode_n, is_rgb;
+   z->s->img_n = 0; // make stbi__cleanup_jpeg safe
+
+   // validate req_comp
+   if (req_comp < 0 || req_comp > 4) return stbi__errpuc("bad req_comp", "Internal error");
+
+   // load a jpeg image from whichever source, but leave in YCbCr format
+   if (!stbi__decode_jpeg_image(z)) { stbi__cleanup_jpeg(z); return NULL; }
+
+   // determine actual number of components to generate
+   n = req_comp ? req_comp : z->s->img_n >= 3 ? 3 : 1;
+
+   is_rgb = z->s->img_n == 3 && (z->rgb == 3 || (z->app14_color_transform == 0 && !z->jfif));
+
+   if (z->s->img_n == 3 && n < 3 && !is_rgb)
+      decode_n = 1;
+   else
+      decode_n = z->s->img_n;
+
+   // resample and color-convert
+   {
+      int k;
+      unsigned int i,j;
+      stbi_uc *output;
+      stbi_uc *coutput[4] = { NULL, NULL, NULL, NULL };
+
+      stbi__resample res_comp[4];
+
+      for (k=0; k < decode_n; ++k) {
+         stbi__resample *r = &res_comp[k];
+
+         // allocate line buffer big enough for upsampling off the edges
+         // with upsample factor of 4
+         z->img_comp[k].linebuf = (stbi_uc *) stbi__malloc(z->s->img_x + 3);
+         if (!z->img_comp[k].linebuf) { stbi__cleanup_jpeg(z); return stbi__errpuc("outofmem", "Out of memory"); }
+
+         r->hs      = z->img_h_max / z->img_comp[k].h;
+         r->vs      = z->img_v_max / z->img_comp[k].v;
+         r->ystep   = r->vs >> 1;
+         r->w_lores = (z->s->img_x + r->hs-1) / r->hs;
+         r->ypos    = 0;
+         r->line0   = r->line1 = z->img_comp[k].data;
+
+         if      (r->hs == 1 && r->vs == 1) r->resample = resample_row_1;
+         else if (r->hs == 1 && r->vs == 2) r->resample = stbi__resample_row_v_2;
+         else if (r->hs == 2 && r->vs == 1) r->resample = stbi__resample_row_h_2;
+         else if (r->hs == 2 && r->vs == 2) r->resample = z->resample_row_hv_2_kernel;
+         else                               r->resample = stbi__resample_row_generic;
+      }
+
+      // can't error after this so, this is safe
+      output = (stbi_uc *) stbi__malloc_mad3(n, z->s->img_x, z->s->img_y, 1);
+      if (!output) { stbi__cleanup_jpeg(z); return stbi__errpuc("outofmem", "Out of memory"); }
+
+      // now go ahead and resample
+      for (j=0; j < z->s->img_y; ++j) {
+         stbi_uc *out = output + n * z->s->img_x * j;
+         for (k=0; k < decode_n; ++k) {
+            stbi__resample *r = &res_comp[k];
+            int y_bot = r->ystep >= (r->vs >> 1);
+            coutput[k] = r->resample(z->img_comp[k].linebuf,
+                                     y_bot ? r->line1 : r->line0,
+                                     y_bot ? r->line0 : r->line1,
+                                     r->w_lores, r->hs);
+            if (++r->ystep >= r->vs) {
+               r->ystep = 0;
+               r->line0 = r->line1;
+               if (++r->ypos < z->img_comp[k].y)
+                  r->line1 += z->img_comp[k].w2;
+            }
+         }
+         if (n >= 3) {
+            stbi_uc *y = coutput[0];
+            if (z->s->img_n == 3) {
+               if (is_rgb) {
+                  for (i=0; i < z->s->img_x; ++i) {
+                     out[0] = y[i];
+                     out[1] = coutput[1][i];
+                     out[2] = coutput[2][i];
+                     out[3] = 255;
+                     out += n;
+                  }
+               } else {
+                  z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n);
+               }
+            } else if (z->s->img_n == 4) {
+               if (z->app14_color_transform == 0) { // CMYK
+                  for (i=0; i < z->s->img_x; ++i) {
+                     stbi_uc m = coutput[3][i];
+                     out[0] = stbi__blinn_8x8(coutput[0][i], m);
+                     out[1] = stbi__blinn_8x8(coutput[1][i], m);
+                     out[2] = stbi__blinn_8x8(coutput[2][i], m);
+                     out[3] = 255;
+                     out += n;
+                  }
+               } else if (z->app14_color_transform == 2) { // YCCK
+                  z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n);
+                  for (i=0; i < z->s->img_x; ++i) {
+                     stbi_uc m = coutput[3][i];
+                     out[0] = stbi__blinn_8x8(255 - out[0], m);
+                     out[1] = stbi__blinn_8x8(255 - out[1], m);
+                     out[2] = stbi__blinn_8x8(255 - out[2], m);
+                     out += n;
+                  }
+               } else { // YCbCr + alpha?  Ignore the fourth channel for now
+                  z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n);
+               }
+            } else
+               for (i=0; i < z->s->img_x; ++i) {
+                  out[0] = out[1] = out[2] = y[i];
+                  out[3] = 255; // not used if n==3
+                  out += n;
+               }
+         } else {
+            if (is_rgb) {
+               if (n == 1)
+                  for (i=0; i < z->s->img_x; ++i)
+                     *out++ = stbi__compute_y(coutput[0][i], coutput[1][i], coutput[2][i]);
+               else {
+                  for (i=0; i < z->s->img_x; ++i, out += 2) {
+                     out[0] = stbi__compute_y(coutput[0][i], coutput[1][i], coutput[2][i]);
+                     out[1] = 255;
+                  }
+               }
+            } else if (z->s->img_n == 4 && z->app14_color_transform == 0) {
+               for (i=0; i < z->s->img_x; ++i) {
+                  stbi_uc m = coutput[3][i];
+                  stbi_uc r = stbi__blinn_8x8(coutput[0][i], m);
+                  stbi_uc g = stbi__blinn_8x8(coutput[1][i], m);
+                  stbi_uc b = stbi__blinn_8x8(coutput[2][i], m);
+                  out[0] = stbi__compute_y(r, g, b);
+                  out[1] = 255;
+                  out += n;
+               }
+            } else if (z->s->img_n == 4 && z->app14_color_transform == 2) {
+               for (i=0; i < z->s->img_x; ++i) {
+                  out[0] = stbi__blinn_8x8(255 - coutput[0][i], coutput[3][i]);
+                  out[1] = 255;
+                  out += n;
+               }
+            } else {
+               stbi_uc *y = coutput[0];
+               if (n == 1)
+                  for (i=0; i < z->s->img_x; ++i) out[i] = y[i];
+               else
+                  for (i=0; i < z->s->img_x; ++i) { *out++ = y[i]; *out++ = 255; }
+            }
+         }
+      }
+      stbi__cleanup_jpeg(z);
+      *out_x = z->s->img_x;
+      *out_y = z->s->img_y;
+      if (comp) *comp = z->s->img_n >= 3 ? 3 : 1; // report original components, not output
+      return output;
+   }
+}
+
+static void *stbi__jpeg_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri)
+{
+   unsigned char* result;
+   stbi__jpeg* j = (stbi__jpeg*) stbi__malloc(sizeof(stbi__jpeg));
+   STBI_NOTUSED(ri);
+   j->s = s;
+   stbi__setup_jpeg(j);
+   result = load_jpeg_image(j, x,y,comp,req_comp);
+   STBI_FREE(j);
+   return result;
+}
+
+static int stbi__jpeg_test(stbi__context *s)
+{
+   int r;
+   stbi__jpeg* j = (stbi__jpeg*)stbi__malloc(sizeof(stbi__jpeg));
+   j->s = s;
+   stbi__setup_jpeg(j);
+   r = stbi__decode_jpeg_header(j, STBI__SCAN_type);
+   stbi__rewind(s);
+   STBI_FREE(j);
+   return r;
+}
+
+static int stbi__jpeg_info_raw(stbi__jpeg *j, int *x, int *y, int *comp)
+{
+   if (!stbi__decode_jpeg_header(j, STBI__SCAN_header)) {
+      stbi__rewind( j->s );
+      return 0;
+   }
+   if (x) *x = j->s->img_x;
+   if (y) *y = j->s->img_y;
+   if (comp) *comp = j->s->img_n >= 3 ? 3 : 1;
+   return 1;
+}
+
+static int stbi__jpeg_info(stbi__context *s, int *x, int *y, int *comp)
+{
+   int result;
+   stbi__jpeg* j = (stbi__jpeg*) (stbi__malloc(sizeof(stbi__jpeg)));
+   j->s = s;
+   result = stbi__jpeg_info_raw(j, x, y, comp);
+   STBI_FREE(j);
+   return result;
+}
+#endif
+
+// public domain zlib decode    v0.2  Sean Barrett 2006-11-18
+//    simple implementation
+//      - all input must be provided in an upfront buffer
+//      - all output is written to a single output buffer (can malloc/realloc)
+//    performance
+//      - fast huffman
+
+#ifndef STBI_NO_ZLIB
+
+// fast-way is faster to check than jpeg huffman, but slow way is slower
+#define STBI__ZFAST_BITS  9 // accelerate all cases in default tables
+#define STBI__ZFAST_MASK  ((1 << STBI__ZFAST_BITS) - 1)
+
+// zlib-style huffman encoding
+// (jpegs packs from left, zlib from right, so can't share code)
+typedef struct
+{
+   stbi__uint16 fast[1 << STBI__ZFAST_BITS];
+   stbi__uint16 firstcode[16];
+   int maxcode[17];
+   stbi__uint16 firstsymbol[16];
+   stbi_uc  size[288];
+   stbi__uint16 value[288];
+} stbi__zhuffman;
+
+stbi_inline static int stbi__bitreverse16(int n)
+{
+  n = ((n & 0xAAAA) >>  1) | ((n & 0x5555) << 1);
+  n = ((n & 0xCCCC) >>  2) | ((n & 0x3333) << 2);
+  n = ((n & 0xF0F0) >>  4) | ((n & 0x0F0F) << 4);
+  n = ((n & 0xFF00) >>  8) | ((n & 0x00FF) << 8);
+  return n;
+}
+
+stbi_inline static int stbi__bit_reverse(int v, int bits)
+{
+   STBI_ASSERT(bits <= 16);
+   // to bit reverse n bits, reverse 16 and shift
+   // e.g. 11 bits, bit reverse and shift away 5
+   return stbi__bitreverse16(v) >> (16-bits);
+}
+
+static int stbi__zbuild_huffman(stbi__zhuffman *z, const stbi_uc *sizelist, int num)
+{
+   int i,k=0;
+   int code, next_code[16], sizes[17];
+
+   // DEFLATE spec for generating codes
+   memset(sizes, 0, sizeof(sizes));
+   memset(z->fast, 0, sizeof(z->fast));
+   for (i=0; i < num; ++i)
+      ++sizes[sizelist[i]];
+   sizes[0] = 0;
+   for (i=1; i < 16; ++i)
+      if (sizes[i] > (1 << i))
+         return stbi__err("bad sizes", "Corrupt PNG");
+   code = 0;
+   for (i=1; i < 16; ++i) {
+      next_code[i] = code;
+      z->firstcode[i] = (stbi__uint16) code;
+      z->firstsymbol[i] = (stbi__uint16) k;
+      code = (code + sizes[i]);
+      if (sizes[i])
+         if (code-1 >= (1 << i)) return stbi__err("bad codelengths","Corrupt PNG");
+      z->maxcode[i] = code << (16-i); // preshift for inner loop
+      code <<= 1;
+      k += sizes[i];
+   }
+   z->maxcode[16] = 0x10000; // sentinel
+   for (i=0; i < num; ++i) {
+      int s = sizelist[i];
+      if (s) {
+         int c = next_code[s] - z->firstcode[s] + z->firstsymbol[s];
+         stbi__uint16 fastv = (stbi__uint16) ((s << 9) | i);
+         z->size [c] = (stbi_uc     ) s;
+         z->value[c] = (stbi__uint16) i;
+         if (s <= STBI__ZFAST_BITS) {
+            int j = stbi__bit_reverse(next_code[s],s);
+            while (j < (1 << STBI__ZFAST_BITS)) {
+               z->fast[j] = fastv;
+               j += (1 << s);
+            }
+         }
+         ++next_code[s];
+      }
+   }
+   return 1;
+}
+
+// zlib-from-memory implementation for PNG reading
+//    because PNG allows splitting the zlib stream arbitrarily,
+//    and it's annoying structurally to have PNG call ZLIB call PNG,
+//    we require PNG read all the IDATs and combine them into a single
+//    memory buffer
+
+typedef struct
+{
+   stbi_uc *zbuffer, *zbuffer_end;
+   int num_bits;
+   stbi__uint32 code_buffer;
+
+   char *zout;
+   char *zout_start;
+   char *zout_end;
+   int   z_expandable;
+
+   stbi__zhuffman z_length, z_distance;
+} stbi__zbuf;
+
+stbi_inline static stbi_uc stbi__zget8(stbi__zbuf *z)
+{
+   if (z->zbuffer >= z->zbuffer_end) return 0;
+   return *z->zbuffer++;
+}
+
+static void stbi__fill_bits(stbi__zbuf *z)
+{
+   do {
+      STBI_ASSERT(z->code_buffer < (1U << z->num_bits));
+      z->code_buffer |= (unsigned int) stbi__zget8(z) << z->num_bits;
+      z->num_bits += 8;
+   } while (z->num_bits <= 24);
+}
+
+stbi_inline static unsigned int stbi__zreceive(stbi__zbuf *z, int n)
+{
+   unsigned int k;
+   if (z->num_bits < n) stbi__fill_bits(z);
+   k = z->code_buffer & ((1 << n) - 1);
+   z->code_buffer >>= n;
+   z->num_bits -= n;
+   return k;
+}
+
+static int stbi__zhuffman_decode_slowpath(stbi__zbuf *a, stbi__zhuffman *z)
+{
+   int b,s,k;
+   // not resolved by fast table, so compute it the slow way
+   // use jpeg approach, which requires MSbits at top
+   k = stbi__bit_reverse(a->code_buffer, 16);
+   for (s=STBI__ZFAST_BITS+1; ; ++s)
+      if (k < z->maxcode[s])
+         break;
+   if (s == 16) return -1; // invalid code!
+   // code size is s, so:
+   b = (k >> (16-s)) - z->firstcode[s] + z->firstsymbol[s];
+   STBI_ASSERT(z->size[b] == s);
+   a->code_buffer >>= s;
+   a->num_bits -= s;
+   return z->value[b];
+}
+
+stbi_inline static int stbi__zhuffman_decode(stbi__zbuf *a, stbi__zhuffman *z)
+{
+   int b,s;
+   if (a->num_bits < 16) stbi__fill_bits(a);
+   b = z->fast[a->code_buffer & STBI__ZFAST_MASK];
+   if (b) {
+      s = b >> 9;
+      a->code_buffer >>= s;
+      a->num_bits -= s;
+      return b & 511;
+   }
+   return stbi__zhuffman_decode_slowpath(a, z);
+}
+
+static int stbi__zexpand(stbi__zbuf *z, char *zout, int n)  // need to make room for n bytes
+{
+   char *q;
+   int cur, limit, old_limit;
+   z->zout = zout;
+   if (!z->z_expandable) return stbi__err("output buffer limit","Corrupt PNG");
+   cur   = (int) (z->zout     - z->zout_start);
+   limit = old_limit = (int) (z->zout_end - z->zout_start);
+   while (cur + n > limit)
+      limit *= 2;
+   q = (char *) STBI_REALLOC_SIZED(z->zout_start, old_limit, limit);
+   STBI_NOTUSED(old_limit);
+   if (q == NULL) return stbi__err("outofmem", "Out of memory");
+   z->zout_start = q;
+   z->zout       = q + cur;
+   z->zout_end   = q + limit;
+   return 1;
+}
+
+static const int stbi__zlength_base[31] = {
+   3,4,5,6,7,8,9,10,11,13,
+   15,17,19,23,27,31,35,43,51,59,
+   67,83,99,115,131,163,195,227,258,0,0 };
+
+static const int stbi__zlength_extra[31]=
+{ 0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0 };
+
+static const int stbi__zdist_base[32] = { 1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,
+257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577,0,0};
+
+static const int stbi__zdist_extra[32] =
+{ 0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13};
+
+static int stbi__parse_huffman_block(stbi__zbuf *a)
+{
+   char *zout = a->zout;
+   for(;;) {
+      int z = stbi__zhuffman_decode(a, &a->z_length);
+      if (z < 256) {
+         if (z < 0) return stbi__err("bad huffman code","Corrupt PNG"); // error in huffman codes
+         if (zout >= a->zout_end) {
+            if (!stbi__zexpand(a, zout, 1)) return 0;
+            zout = a->zout;
+         }
+         *zout++ = (char) z;
+      } else {
+         stbi_uc *p;
+         int len,dist;
+         if (z == 256) {
+            a->zout = zout;
+            return 1;
+         }
+         z -= 257;
+         len = stbi__zlength_base[z];
+         if (stbi__zlength_extra[z]) len += stbi__zreceive(a, stbi__zlength_extra[z]);
+         z = stbi__zhuffman_decode(a, &a->z_distance);
+         if (z < 0) return stbi__err("bad huffman code","Corrupt PNG");
+         dist = stbi__zdist_base[z];
+         if (stbi__zdist_extra[z]) dist += stbi__zreceive(a, stbi__zdist_extra[z]);
+         if (zout - a->zout_start < dist) return stbi__err("bad dist","Corrupt PNG");
+         if (zout + len > a->zout_end) {
+            if (!stbi__zexpand(a, zout, len)) return 0;
+            zout = a->zout;
+         }
+         p = (stbi_uc *) (zout - dist);
+         if (dist == 1) { // run of one byte; common in images.
+            stbi_uc v = *p;
+            if (len) { do *zout++ = v; while (--len); }
+         } else {
+            if (len) { do *zout++ = *p++; while (--len); }
+         }
+      }
+   }
+}
+
+static int stbi__compute_huffman_codes(stbi__zbuf *a)
+{
+   static const stbi_uc length_dezigzag[19] = { 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15 };
+   stbi__zhuffman z_codelength;
+   stbi_uc lencodes[286+32+137];//padding for maximum single op
+   stbi_uc codelength_sizes[19];
+   int i,n;
+
+   int hlit  = stbi__zreceive(a,5) + 257;
+   int hdist = stbi__zreceive(a,5) + 1;
+   int hclen = stbi__zreceive(a,4) + 4;
+   int ntot  = hlit + hdist;
+
+   memset(codelength_sizes, 0, sizeof(codelength_sizes));
+   for (i=0; i < hclen; ++i) {
+      int s = stbi__zreceive(a,3);
+      codelength_sizes[length_dezigzag[i]] = (stbi_uc) s;
+   }
+   if (!stbi__zbuild_huffman(&z_codelength, codelength_sizes, 19)) return 0;
+
+   n = 0;
+   while (n < ntot) {
+      int c = stbi__zhuffman_decode(a, &z_codelength);
+      if (c < 0 || c >= 19) return stbi__err("bad codelengths", "Corrupt PNG");
+      if (c < 16)
+         lencodes[n++] = (stbi_uc) c;
+      else {
+         stbi_uc fill = 0;
+         if (c == 16) {
+            c = stbi__zreceive(a,2)+3;
+            if (n == 0) return stbi__err("bad codelengths", "Corrupt PNG");
+            fill = lencodes[n-1];
+         } else if (c == 17)
+            c = stbi__zreceive(a,3)+3;
+         else {
+            STBI_ASSERT(c == 18);
+            c = stbi__zreceive(a,7)+11;
+         }
+         if (ntot - n < c) return stbi__err("bad codelengths", "Corrupt PNG");
+         memset(lencodes+n, fill, c);
+         n += c;
+      }
+   }
+   if (n != ntot) return stbi__err("bad codelengths","Corrupt PNG");
+   if (!stbi__zbuild_huffman(&a->z_length, lencodes, hlit)) return 0;
+   if (!stbi__zbuild_huffman(&a->z_distance, lencodes+hlit, hdist)) return 0;
+   return 1;
+}
+
+static int stbi__parse_uncompressed_block(stbi__zbuf *a)
+{
+   stbi_uc header[4];
+   int len,nlen,k;
+   if (a->num_bits & 7)
+      stbi__zreceive(a, a->num_bits & 7); // discard
+   // drain the bit-packed data into header
+   k = 0;
+   while (a->num_bits > 0) {
+      header[k++] = (stbi_uc) (a->code_buffer & 255); // suppress MSVC run-time check
+      a->code_buffer >>= 8;
+      a->num_bits -= 8;
+   }
+   STBI_ASSERT(a->num_bits == 0);
+   // now fill header the normal way
+   while (k < 4)
+      header[k++] = stbi__zget8(a);
+   len  = header[1] * 256 + header[0];
+   nlen = header[3] * 256 + header[2];
+   if (nlen != (len ^ 0xffff)) return stbi__err("zlib corrupt","Corrupt PNG");
+   if (a->zbuffer + len > a->zbuffer_end) return stbi__err("read past buffer","Corrupt PNG");
+   if (a->zout + len > a->zout_end)
+      if (!stbi__zexpand(a, a->zout, len)) return 0;
+   memcpy(a->zout, a->zbuffer, len);
+   a->zbuffer += len;
+   a->zout += len;
+   return 1;
+}
+
+static int stbi__parse_zlib_header(stbi__zbuf *a)
+{
+   int cmf   = stbi__zget8(a);
+   int cm    = cmf & 15;
+   /* int cinfo = cmf >> 4; */
+   int flg   = stbi__zget8(a);
+   if ((cmf*256+flg) % 31 != 0) return stbi__err("bad zlib header","Corrupt PNG"); // zlib spec
+   if (flg & 32) return stbi__err("no preset dict","Corrupt PNG"); // preset dictionary not allowed in png
+   if (cm != 8) return stbi__err("bad compression","Corrupt PNG"); // DEFLATE required for png
+   // window = 1 << (8 + cinfo)... but who cares, we fully buffer output
+   return 1;
+}
+
+static const stbi_uc stbi__zdefault_length[288] =
+{
+   8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+   8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+   8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+   8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+   8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
+   9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
+   9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
+   9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
+   7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,8,8,8,8,8,8,8,8
+};
+static const stbi_uc stbi__zdefault_distance[32] =
+{
+   5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5
+};
+/*
+Init algorithm:
+{
+   int i;   // use <= to match clearly with spec
+   for (i=0; i <= 143; ++i)     stbi__zdefault_length[i]   = 8;
+   for (   ; i <= 255; ++i)     stbi__zdefault_length[i]   = 9;
+   for (   ; i <= 279; ++i)     stbi__zdefault_length[i]   = 7;
+   for (   ; i <= 287; ++i)     stbi__zdefault_length[i]   = 8;
+
+   for (i=0; i <=  31; ++i)     stbi__zdefault_distance[i] = 5;
+}
+*/
+
+static int stbi__parse_zlib(stbi__zbuf *a, int parse_header)
+{
+   int final, type;
+   if (parse_header)
+      if (!stbi__parse_zlib_header(a)) return 0;
+   a->num_bits = 0;
+   a->code_buffer = 0;
+   do {
+      final = stbi__zreceive(a,1);
+      type = stbi__zreceive(a,2);
+      if (type == 0) {
+         if (!stbi__parse_uncompressed_block(a)) return 0;
+      } else if (type == 3) {
+         return 0;
+      } else {
+         if (type == 1) {
+            // use fixed code lengths
+            if (!stbi__zbuild_huffman(&a->z_length  , stbi__zdefault_length  , 288)) return 0;
+            if (!stbi__zbuild_huffman(&a->z_distance, stbi__zdefault_distance,  32)) return 0;
+         } else {
+            if (!stbi__compute_huffman_codes(a)) return 0;
+         }
+         if (!stbi__parse_huffman_block(a)) return 0;
+      }
+   } while (!final);
+   return 1;
+}
+
+static int stbi__do_zlib(stbi__zbuf *a, char *obuf, int olen, int exp, int parse_header)
+{
+   a->zout_start = obuf;
+   a->zout       = obuf;
+   a->zout_end   = obuf + olen;
+   a->z_expandable = exp;
+
+   return stbi__parse_zlib(a, parse_header);
+}
+
+STBIDEF char *stbi_zlib_decode_malloc_guesssize(const char *buffer, int len, int initial_size, int *outlen)
+{
+   stbi__zbuf a;
+   char *p = (char *) stbi__malloc(initial_size);
+   if (p == NULL) return NULL;
+   a.zbuffer = (stbi_uc *) buffer;
+   a.zbuffer_end = (stbi_uc *) buffer + len;
+   if (stbi__do_zlib(&a, p, initial_size, 1, 1)) {
+      if (outlen) *outlen = (int) (a.zout - a.zout_start);
+      return a.zout_start;
+   } else {
+      STBI_FREE(a.zout_start);
+      return NULL;
+   }
+}
+
+STBIDEF char *stbi_zlib_decode_malloc(char const *buffer, int len, int *outlen)
+{
+   return stbi_zlib_decode_malloc_guesssize(buffer, len, 16384, outlen);
+}
+
+STBIDEF char *stbi_zlib_decode_malloc_guesssize_headerflag(const char *buffer, int len, int initial_size, int *outlen, int parse_header)
+{
+   stbi__zbuf a;
+   char *p = (char *) stbi__malloc(initial_size);
+   if (p == NULL) return NULL;
+   a.zbuffer = (stbi_uc *) buffer;
+   a.zbuffer_end = (stbi_uc *) buffer + len;
+   if (stbi__do_zlib(&a, p, initial_size, 1, parse_header)) {
+      if (outlen) *outlen = (int) (a.zout - a.zout_start);
+      return a.zout_start;
+   } else {
+      STBI_FREE(a.zout_start);
+      return NULL;
+   }
+}
+
+STBIDEF int stbi_zlib_decode_buffer(char *obuffer, int olen, char const *ibuffer, int ilen)
+{
+   stbi__zbuf a;
+   a.zbuffer = (stbi_uc *) ibuffer;
+   a.zbuffer_end = (stbi_uc *) ibuffer + ilen;
+   if (stbi__do_zlib(&a, obuffer, olen, 0, 1))
+      return (int) (a.zout - a.zout_start);
+   else
+      return -1;
+}
+
+STBIDEF char *stbi_zlib_decode_noheader_malloc(char const *buffer, int len, int *outlen)
+{
+   stbi__zbuf a;
+   char *p = (char *) stbi__malloc(16384);
+   if (p == NULL) return NULL;
+   a.zbuffer = (stbi_uc *) buffer;
+   a.zbuffer_end = (stbi_uc *) buffer+len;
+   if (stbi__do_zlib(&a, p, 16384, 1, 0)) {
+      if (outlen) *outlen = (int) (a.zout - a.zout_start);
+      return a.zout_start;
+   } else {
+      STBI_FREE(a.zout_start);
+      return NULL;
+   }
+}
+
+STBIDEF int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const char *ibuffer, int ilen)
+{
+   stbi__zbuf a;
+   a.zbuffer = (stbi_uc *) ibuffer;
+   a.zbuffer_end = (stbi_uc *) ibuffer + ilen;
+   if (stbi__do_zlib(&a, obuffer, olen, 0, 0))
+      return (int) (a.zout - a.zout_start);
+   else
+      return -1;
+}
+#endif
+
+// public domain "baseline" PNG decoder   v0.10  Sean Barrett 2006-11-18
+//    simple implementation
+//      - only 8-bit samples
+//      - no CRC checking
+//      - allocates lots of intermediate memory
+//        - avoids problem of streaming data between subsystems
+//        - avoids explicit window management
+//    performance
+//      - uses stb_zlib, a PD zlib implementation with fast huffman decoding
+
+#ifndef STBI_NO_PNG
+typedef struct
+{
+   stbi__uint32 length;
+   stbi__uint32 type;
+} stbi__pngchunk;
+
+static stbi__pngchunk stbi__get_chunk_header(stbi__context *s)
+{
+   stbi__pngchunk c;
+   c.length = stbi__get32be(s);
+   c.type   = stbi__get32be(s);
+   return c;
+}
+
+static int stbi__check_png_header(stbi__context *s)
+{
+   static const stbi_uc png_sig[8] = { 137,80,78,71,13,10,26,10 };
+   int i;
+   for (i=0; i < 8; ++i)
+      if (stbi__get8(s) != png_sig[i]) return stbi__err("bad png sig","Not a PNG");
+   return 1;
+}
+
+typedef struct
+{
+   stbi__context *s;
+   stbi_uc *idata, *expanded, *out;
+   int depth;
+} stbi__png;
+
+
+enum {
+   STBI__F_none=0,
+   STBI__F_sub=1,
+   STBI__F_up=2,
+   STBI__F_avg=3,
+   STBI__F_paeth=4,
+   // synthetic filters used for first scanline to avoid needing a dummy row of 0s
+   STBI__F_avg_first,
+   STBI__F_paeth_first
+};
+
+static stbi_uc first_row_filter[5] =
+{
+   STBI__F_none,
+   STBI__F_sub,
+   STBI__F_none,
+   STBI__F_avg_first,
+   STBI__F_paeth_first
+};
+
+static int stbi__paeth(int a, int b, int c)
+{
+   int p = a + b - c;
+   int pa = abs(p-a);
+   int pb = abs(p-b);
+   int pc = abs(p-c);
+   if (pa <= pb && pa <= pc) return a;
+   if (pb <= pc) return b;
+   return c;
+}
+
+static const stbi_uc stbi__depth_scale_table[9] = { 0, 0xff, 0x55, 0, 0x11, 0,0,0, 0x01 };
+
+// create the png data from post-deflated data
+static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 raw_len, int out_n, stbi__uint32 x, stbi__uint32 y, int depth, int color)
+{
+   int bytes = (depth == 16? 2 : 1);
+   stbi__context *s = a->s;
+   stbi__uint32 i,j,stride = x*out_n*bytes;
+   stbi__uint32 img_len, img_width_bytes;
+   int k;
+   int img_n = s->img_n; // copy it into a local for later
+
+   int output_bytes = out_n*bytes;
+   int filter_bytes = img_n*bytes;
+   int width = x;
+
+   STBI_ASSERT(out_n == s->img_n || out_n == s->img_n+1);
+   a->out = (stbi_uc *) stbi__malloc_mad3(x, y, output_bytes, 0); // extra bytes to write off the end into
+   if (!a->out) return stbi__err("outofmem", "Out of memory");
+
+   if (!stbi__mad3sizes_valid(img_n, x, depth, 7)) return stbi__err("too large", "Corrupt PNG");
+   img_width_bytes = (((img_n * x * depth) + 7) >> 3);
+   img_len = (img_width_bytes + 1) * y;
+
+   // we used to check for exact match between raw_len and img_len on non-interlaced PNGs,
+   // but issue #276 reported a PNG in the wild that had extra data at the end (all zeros),
+   // so just check for raw_len < img_len always.
+   if (raw_len < img_len) return stbi__err("not enough pixels","Corrupt PNG");
+
+   for (j=0; j < y; ++j) {
+      stbi_uc *cur = a->out + stride*j;
+      stbi_uc *prior;
+      int filter = *raw++;
+
+      if (filter > 4)
+         return stbi__err("invalid filter","Corrupt PNG");
+
+      if (depth < 8) {
+         STBI_ASSERT(img_width_bytes <= x);
+         cur += x*out_n - img_width_bytes; // store output to the rightmost img_len bytes, so we can decode in place
+         filter_bytes = 1;
+         width = img_width_bytes;
+      }
+      prior = cur - stride; // bugfix: need to compute this after 'cur +=' computation above
+
+      // if first row, use special filter that doesn't sample previous row
+      if (j == 0) filter = first_row_filter[filter];
+
+      // handle first byte explicitly
+      for (k=0; k < filter_bytes; ++k) {
+         switch (filter) {
+            case STBI__F_none       : cur[k] = raw[k]; break;
+            case STBI__F_sub        : cur[k] = raw[k]; break;
+            case STBI__F_up         : cur[k] = STBI__BYTECAST(raw[k] + prior[k]); break;
+            case STBI__F_avg        : cur[k] = STBI__BYTECAST(raw[k] + (prior[k]>>1)); break;
+            case STBI__F_paeth      : cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(0,prior[k],0)); break;
+            case STBI__F_avg_first  : cur[k] = raw[k]; break;
+            case STBI__F_paeth_first: cur[k] = raw[k]; break;
+         }
+      }
+
+      if (depth == 8) {
+         if (img_n != out_n)
+            cur[img_n] = 255; // first pixel
+         raw += img_n;
+         cur += out_n;
+         prior += out_n;
+      } else if (depth == 16) {
+         if (img_n != out_n) {
+            cur[filter_bytes]   = 255; // first pixel top byte
+            cur[filter_bytes+1] = 255; // first pixel bottom byte
+         }
+         raw += filter_bytes;
+         cur += output_bytes;
+         prior += output_bytes;
+      } else {
+         raw += 1;
+         cur += 1;
+         prior += 1;
+      }
+
+      // this is a little gross, so that we don't switch per-pixel or per-component
+      if (depth < 8 || img_n == out_n) {
+         int nk = (width - 1)*filter_bytes;
+         #define STBI__CASE(f) \
+             case f:     \
+                for (k=0; k < nk; ++k)
+         switch (filter) {
+            // "none" filter turns into a memcpy here; make that explicit.
+            case STBI__F_none:         memcpy(cur, raw, nk); break;
+            STBI__CASE(STBI__F_sub)          { cur[k] = STBI__BYTECAST(raw[k] + cur[k-filter_bytes]); } break;
+            STBI__CASE(STBI__F_up)           { cur[k] = STBI__BYTECAST(raw[k] + prior[k]); } break;
+            STBI__CASE(STBI__F_avg)          { cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k-filter_bytes])>>1)); } break;
+            STBI__CASE(STBI__F_paeth)        { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-filter_bytes],prior[k],prior[k-filter_bytes])); } break;
+            STBI__CASE(STBI__F_avg_first)    { cur[k] = STBI__BYTECAST(raw[k] + (cur[k-filter_bytes] >> 1)); } break;
+            STBI__CASE(STBI__F_paeth_first)  { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-filter_bytes],0,0)); } break;
+         }
+         #undef STBI__CASE
+         raw += nk;
+      } else {
+         STBI_ASSERT(img_n+1 == out_n);
+         #define STBI__CASE(f) \
+             case f:     \
+                for (i=x-1; i >= 1; --i, cur[filter_bytes]=255,raw+=filter_bytes,cur+=output_bytes,prior+=output_bytes) \
+                   for (k=0; k < filter_bytes; ++k)
+         switch (filter) {
+            STBI__CASE(STBI__F_none)         { cur[k] = raw[k]; } break;
+            STBI__CASE(STBI__F_sub)          { cur[k] = STBI__BYTECAST(raw[k] + cur[k- output_bytes]); } break;
+            STBI__CASE(STBI__F_up)           { cur[k] = STBI__BYTECAST(raw[k] + prior[k]); } break;
+            STBI__CASE(STBI__F_avg)          { cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k- output_bytes])>>1)); } break;
+            STBI__CASE(STBI__F_paeth)        { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k- output_bytes],prior[k],prior[k- output_bytes])); } break;
+            STBI__CASE(STBI__F_avg_first)    { cur[k] = STBI__BYTECAST(raw[k] + (cur[k- output_bytes] >> 1)); } break;
+            STBI__CASE(STBI__F_paeth_first)  { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k- output_bytes],0,0)); } break;
+         }
+         #undef STBI__CASE
+
+         // the loop above sets the high byte of the pixels' alpha, but for
+         // 16 bit png files we also need the low byte set. we'll do that here.
+         if (depth == 16) {
+            cur = a->out + stride*j; // start at the beginning of the row again
+            for (i=0; i < x; ++i,cur+=output_bytes) {
+               cur[filter_bytes+1] = 255;
+            }
+         }
+      }
+   }
+
+   // we make a separate pass to expand bits to pixels; for performance,
+   // this could run two scanlines behind the above code, so it won't
+   // intefere with filtering but will still be in the cache.
+   if (depth < 8) {
+      for (j=0; j < y; ++j) {
+         stbi_uc *cur = a->out + stride*j;
+         stbi_uc *in  = a->out + stride*j + x*out_n - img_width_bytes;
+         // unpack 1/2/4-bit into a 8-bit buffer. allows us to keep the common 8-bit path optimal at minimal cost for 1/2/4-bit
+         // png guarante byte alignment, if width is not multiple of 8/4/2 we'll decode dummy trailing data that will be skipped in the later loop
+         stbi_uc scale = (color == 0) ? stbi__depth_scale_table[depth] : 1; // scale grayscale values to 0..255 range
+
+         // note that the final byte might overshoot and write more data than desired.
+         // we can allocate enough data that this never writes out of memory, but it
+         // could also overwrite the next scanline. can it overwrite non-empty data
+         // on the next scanline? yes, consider 1-pixel-wide scanlines with 1-bit-per-pixel.
+         // so we need to explicitly clamp the final ones
+
+         if (depth == 4) {
+            for (k=x*img_n; k >= 2; k-=2, ++in) {
+               *cur++ = scale * ((*in >> 4)       );
+               *cur++ = scale * ((*in     ) & 0x0f);
+            }
+            if (k > 0) *cur++ = scale * ((*in >> 4)       );
+         } else if (depth == 2) {
+            for (k=x*img_n; k >= 4; k-=4, ++in) {
+               *cur++ = scale * ((*in >> 6)       );
+               *cur++ = scale * ((*in >> 4) & 0x03);
+               *cur++ = scale * ((*in >> 2) & 0x03);
+               *cur++ = scale * ((*in     ) & 0x03);
+            }
+            if (k > 0) *cur++ = scale * ((*in >> 6)       );
+            if (k > 1) *cur++ = scale * ((*in >> 4) & 0x03);
+            if (k > 2) *cur++ = scale * ((*in >> 2) & 0x03);
+         } else if (depth == 1) {
+            for (k=x*img_n; k >= 8; k-=8, ++in) {
+               *cur++ = scale * ((*in >> 7)       );
+               *cur++ = scale * ((*in >> 6) & 0x01);
+               *cur++ = scale * ((*in >> 5) & 0x01);
+               *cur++ = scale * ((*in >> 4) & 0x01);
+               *cur++ = scale * ((*in >> 3) & 0x01);
+               *cur++ = scale * ((*in >> 2) & 0x01);
+               *cur++ = scale * ((*in >> 1) & 0x01);
+               *cur++ = scale * ((*in     ) & 0x01);
+            }
+            if (k > 0) *cur++ = scale * ((*in >> 7)       );
+            if (k > 1) *cur++ = scale * ((*in >> 6) & 0x01);
+            if (k > 2) *cur++ = scale * ((*in >> 5) & 0x01);
+            if (k > 3) *cur++ = scale * ((*in >> 4) & 0x01);
+            if (k > 4) *cur++ = scale * ((*in >> 3) & 0x01);
+            if (k > 5) *cur++ = scale * ((*in >> 2) & 0x01);
+            if (k > 6) *cur++ = scale * ((*in >> 1) & 0x01);
+         }
+         if (img_n != out_n) {
+            int q;
+            // insert alpha = 255
+            cur = a->out + stride*j;
+            if (img_n == 1) {
+               for (q=x-1; q >= 0; --q) {
+                  cur[q*2+1] = 255;
+                  cur[q*2+0] = cur[q];
+               }
+            } else {
+               STBI_ASSERT(img_n == 3);
+               for (q=x-1; q >= 0; --q) {
+                  cur[q*4+3] = 255;
+                  cur[q*4+2] = cur[q*3+2];
+                  cur[q*4+1] = cur[q*3+1];
+                  cur[q*4+0] = cur[q*3+0];
+               }
+            }
+         }
+      }
+   } else if (depth == 16) {
+      // force the image data from big-endian to platform-native.
+      // this is done in a separate pass due to the decoding relying
+      // on the data being untouched, but could probably be done
+      // per-line during decode if care is taken.
+      stbi_uc *cur = a->out;
+      stbi__uint16 *cur16 = (stbi__uint16*)cur;
+
+      for(i=0; i < x*y*out_n; ++i,cur16++,cur+=2) {
+         *cur16 = (cur[0] << 8) | cur[1];
+      }
+   }
+
+   return 1;
+}
+
+static int stbi__create_png_image(stbi__png *a, stbi_uc *image_data, stbi__uint32 image_data_len, int out_n, int depth, int color, int interlaced)
+{
+   int bytes = (depth == 16 ? 2 : 1);
+   int out_bytes = out_n * bytes;
+   stbi_uc *final;
+   int p;
+   if (!interlaced)
+      return stbi__create_png_image_raw(a, image_data, image_data_len, out_n, a->s->img_x, a->s->img_y, depth, color);
+
+   // de-interlacing
+   final = (stbi_uc *) stbi__malloc_mad3(a->s->img_x, a->s->img_y, out_bytes, 0);
+   for (p=0; p < 7; ++p) {
+      int xorig[] = { 0,4,0,2,0,1,0 };
+      int yorig[] = { 0,0,4,0,2,0,1 };
+      int xspc[]  = { 8,8,4,4,2,2,1 };
+      int yspc[]  = { 8,8,8,4,4,2,2 };
+      int i,j,x,y;
+      // pass1_x[4] = 0, pass1_x[5] = 1, pass1_x[12] = 1
+      x = (a->s->img_x - xorig[p] + xspc[p]-1) / xspc[p];
+      y = (a->s->img_y - yorig[p] + yspc[p]-1) / yspc[p];
+      if (x && y) {
+         stbi__uint32 img_len = ((((a->s->img_n * x * depth) + 7) >> 3) + 1) * y;
+         if (!stbi__create_png_image_raw(a, image_data, image_data_len, out_n, x, y, depth, color)) {
+            STBI_FREE(final);
+            return 0;
+         }
+         for (j=0; j < y; ++j) {
+            for (i=0; i < x; ++i) {
+               int out_y = j*yspc[p]+yorig[p];
+               int out_x = i*xspc[p]+xorig[p];
+               memcpy(final + out_y*a->s->img_x*out_bytes + out_x*out_bytes,
+                      a->out + (j*x+i)*out_bytes, out_bytes);
+            }
+         }
+         STBI_FREE(a->out);
+         image_data += img_len;
+         image_data_len -= img_len;
+      }
+   }
+   a->out = final;
+
+   return 1;
+}
+
+static int stbi__compute_transparency(stbi__png *z, stbi_uc tc[3], int out_n)
+{
+   stbi__context *s = z->s;
+   stbi__uint32 i, pixel_count = s->img_x * s->img_y;
+   stbi_uc *p = z->out;
+
+   // compute color-based transparency, assuming we've
+   // already got 255 as the alpha value in the output
+   STBI_ASSERT(out_n == 2 || out_n == 4);
+
+   if (out_n == 2) {
+      for (i=0; i < pixel_count; ++i) {
+         p[1] = (p[0] == tc[0] ? 0 : 255);
+         p += 2;
+      }
+   } else {
+      for (i=0; i < pixel_count; ++i) {
+         if (p[0] == tc[0] && p[1] == tc[1] && p[2] == tc[2])
+            p[3] = 0;
+         p += 4;
+      }
+   }
+   return 1;
+}
+
+static int stbi__compute_transparency16(stbi__png *z, stbi__uint16 tc[3], int out_n)
+{
+   stbi__context *s = z->s;
+   stbi__uint32 i, pixel_count = s->img_x * s->img_y;
+   stbi__uint16 *p = (stbi__uint16*) z->out;
+
+   // compute color-based transparency, assuming we've
+   // already got 65535 as the alpha value in the output
+   STBI_ASSERT(out_n == 2 || out_n == 4);
+
+   if (out_n == 2) {
+      for (i = 0; i < pixel_count; ++i) {
+         p[1] = (p[0] == tc[0] ? 0 : 65535);
+         p += 2;
+      }
+   } else {
+      for (i = 0; i < pixel_count; ++i) {
+         if (p[0] == tc[0] && p[1] == tc[1] && p[2] == tc[2])
+            p[3] = 0;
+         p += 4;
+      }
+   }
+   return 1;
+}
+
+static int stbi__expand_png_palette(stbi__png *a, stbi_uc *palette, int len, int pal_img_n)
+{
+   stbi__uint32 i, pixel_count = a->s->img_x * a->s->img_y;
+   stbi_uc *p, *temp_out, *orig = a->out;
+
+   p = (stbi_uc *) stbi__malloc_mad2(pixel_count, pal_img_n, 0);
+   if (p == NULL) return stbi__err("outofmem", "Out of memory");
+
+   // between here and free(out) below, exitting would leak
+   temp_out = p;
+
+   if (pal_img_n == 3) {
+      for (i=0; i < pixel_count; ++i) {
+         int n = orig[i]*4;
+         p[0] = palette[n  ];
+         p[1] = palette[n+1];
+         p[2] = palette[n+2];
+         p += 3;
+      }
+   } else {
+      for (i=0; i < pixel_count; ++i) {
+         int n = orig[i]*4;
+         p[0] = palette[n  ];
+         p[1] = palette[n+1];
+         p[2] = palette[n+2];
+         p[3] = palette[n+3];
+         p += 4;
+      }
+   }
+   STBI_FREE(a->out);
+   a->out = temp_out;
+
+   STBI_NOTUSED(len);
+
+   return 1;
+}
+
+static int stbi__unpremultiply_on_load = 0;
+static int stbi__de_iphone_flag = 0;
+
+STBIDEF void stbi_set_unpremultiply_on_load(int flag_true_if_should_unpremultiply)
+{
+   stbi__unpremultiply_on_load = flag_true_if_should_unpremultiply;
+}
+
+STBIDEF void stbi_convert_iphone_png_to_rgb(int flag_true_if_should_convert)
+{
+   stbi__de_iphone_flag = flag_true_if_should_convert;
+}
+
+static void stbi__de_iphone(stbi__png *z)
+{
+   stbi__context *s = z->s;
+   stbi__uint32 i, pixel_count = s->img_x * s->img_y;
+   stbi_uc *p = z->out;
+
+   if (s->img_out_n == 3) {  // convert bgr to rgb
+      for (i=0; i < pixel_count; ++i) {
+         stbi_uc t = p[0];
+         p[0] = p[2];
+         p[2] = t;
+         p += 3;
+      }
+   } else {
+      STBI_ASSERT(s->img_out_n == 4);
+      if (stbi__unpremultiply_on_load) {
+         // convert bgr to rgb and unpremultiply
+         for (i=0; i < pixel_count; ++i) {
+            stbi_uc a = p[3];
+            stbi_uc t = p[0];
+            if (a) {
+               stbi_uc half = a / 2;
+               p[0] = (p[2] * 255 + half) / a;
+               p[1] = (p[1] * 255 + half) / a;
+               p[2] = ( t   * 255 + half) / a;
+            } else {
+               p[0] = p[2];
+               p[2] = t;
+            }
+            p += 4;
+         }
+      } else {
+         // convert bgr to rgb
+         for (i=0; i < pixel_count; ++i) {
+            stbi_uc t = p[0];
+            p[0] = p[2];
+            p[2] = t;
+            p += 4;
+         }
+      }
+   }
+}
+
+#define STBI__PNG_TYPE(a,b,c,d)  (((unsigned) (a) << 24) + ((unsigned) (b) << 16) + ((unsigned) (c) << 8) + (unsigned) (d))
+
+static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp)
+{
+   stbi_uc palette[1024], pal_img_n=0;
+   stbi_uc has_trans=0, tc[3]={0};
+   stbi__uint16 tc16[3];
+   stbi__uint32 ioff=0, idata_limit=0, i, pal_len=0;
+   int first=1,k,interlace=0, color=0, is_iphone=0;
+   stbi__context *s = z->s;
+
+   z->expanded = NULL;
+   z->idata = NULL;
+   z->out = NULL;
+
+   if (!stbi__check_png_header(s)) return 0;
+
+   if (scan == STBI__SCAN_type) return 1;
+
+   for (;;) {
+      stbi__pngchunk c = stbi__get_chunk_header(s);
+      switch (c.type) {
+         case STBI__PNG_TYPE('C','g','B','I'):
+            is_iphone = 1;
+            stbi__skip(s, c.length);
+            break;
+         case STBI__PNG_TYPE('I','H','D','R'): {
+            int comp,filter;
+            if (!first) return stbi__err("multiple IHDR","Corrupt PNG");
+            first = 0;
+            if (c.length != 13) return stbi__err("bad IHDR len","Corrupt PNG");
+            s->img_x = stbi__get32be(s); if (s->img_x > (1 << 24)) return stbi__err("too large","Very large image (corrupt?)");
+            s->img_y = stbi__get32be(s); if (s->img_y > (1 << 24)) return stbi__err("too large","Very large image (corrupt?)");
+            z->depth = stbi__get8(s);  if (z->depth != 1 && z->depth != 2 && z->depth != 4 && z->depth != 8 && z->depth != 16)  return stbi__err("1/2/4/8/16-bit only","PNG not supported: 1/2/4/8/16-bit only");
+            color = stbi__get8(s);  if (color > 6)         return stbi__err("bad ctype","Corrupt PNG");
+            if (color == 3 && z->depth == 16)                  return stbi__err("bad ctype","Corrupt PNG");
+            if (color == 3) pal_img_n = 3; else if (color & 1) return stbi__err("bad ctype","Corrupt PNG");
+            comp  = stbi__get8(s);  if (comp) return stbi__err("bad comp method","Corrupt PNG");
+            filter= stbi__get8(s);  if (filter) return stbi__err("bad filter method","Corrupt PNG");
+            interlace = stbi__get8(s); if (interlace>1) return stbi__err("bad interlace method","Corrupt PNG");
+            if (!s->img_x || !s->img_y) return stbi__err("0-pixel image","Corrupt PNG");
+            if (!pal_img_n) {
+               s->img_n = (color & 2 ? 3 : 1) + (color & 4 ? 1 : 0);
+               if ((1 << 30) / s->img_x / s->img_n < s->img_y) return stbi__err("too large", "Image too large to decode");
+               if (scan == STBI__SCAN_header) return 1;
+            } else {
+               // if paletted, then pal_n is our final components, and
+               // img_n is # components to decompress/filter.
+               s->img_n = 1;
+               if ((1 << 30) / s->img_x / 4 < s->img_y) return stbi__err("too large","Corrupt PNG");
+               // if SCAN_header, have to scan to see if we have a tRNS
+            }
+            break;
+         }
+
+         case STBI__PNG_TYPE('P','L','T','E'):  {
+            if (first) return stbi__err("first not IHDR", "Corrupt PNG");
+            if (c.length > 256*3) return stbi__err("invalid PLTE","Corrupt PNG");
+            pal_len = c.length / 3;
+            if (pal_len * 3 != c.length) return stbi__err("invalid PLTE","Corrupt PNG");
+            for (i=0; i < pal_len; ++i) {
+               palette[i*4+0] = stbi__get8(s);
+               palette[i*4+1] = stbi__get8(s);
+               palette[i*4+2] = stbi__get8(s);
+               palette[i*4+3] = 255;
+            }
+            break;
+         }
+
+         case STBI__PNG_TYPE('t','R','N','S'): {
+            if (first) return stbi__err("first not IHDR", "Corrupt PNG");
+            if (z->idata) return stbi__err("tRNS after IDAT","Corrupt PNG");
+            if (pal_img_n) {
+               if (scan == STBI__SCAN_header) { s->img_n = 4; return 1; }
+               if (pal_len == 0) return stbi__err("tRNS before PLTE","Corrupt PNG");
+               if (c.length > pal_len) return stbi__err("bad tRNS len","Corrupt PNG");
+               pal_img_n = 4;
+               for (i=0; i < c.length; ++i)
+                  palette[i*4+3] = stbi__get8(s);
+            } else {
+               if (!(s->img_n & 1)) return stbi__err("tRNS with alpha","Corrupt PNG");
+               if (c.length != (stbi__uint32) s->img_n*2) return stbi__err("bad tRNS len","Corrupt PNG");
+               has_trans = 1;
+               if (z->depth == 16) {
+                  for (k = 0; k < s->img_n; ++k) tc16[k] = (stbi__uint16)stbi__get16be(s); // copy the values as-is
+               } else {
+                  for (k = 0; k < s->img_n; ++k) tc[k] = (stbi_uc)(stbi__get16be(s) & 255) * stbi__depth_scale_table[z->depth]; // non 8-bit images will be larger
+               }
+            }
+            break;
+         }
+
+         case STBI__PNG_TYPE('I','D','A','T'): {
+            if (first) return stbi__err("first not IHDR", "Corrupt PNG");
+            if (pal_img_n && !pal_len) return stbi__err("no PLTE","Corrupt PNG");
+            if (scan == STBI__SCAN_header) { s->img_n = pal_img_n; return 1; }
+            if ((int)(ioff + c.length) < (int)ioff) return 0;
+            if (ioff + c.length > idata_limit) {
+               stbi__uint32 idata_limit_old = idata_limit;
+               stbi_uc *p;
+               if (idata_limit == 0) idata_limit = c.length > 4096 ? c.length : 4096;
+               while (ioff + c.length > idata_limit)
+                  idata_limit *= 2;
+               STBI_NOTUSED(idata_limit_old);
+               p = (stbi_uc *) STBI_REALLOC_SIZED(z->idata, idata_limit_old, idata_limit); if (p == NULL) return stbi__err("outofmem", "Out of memory");
+               z->idata = p;
+            }
+            if (!stbi__getn(s, z->idata+ioff,c.length)) return stbi__err("outofdata","Corrupt PNG");
+            ioff += c.length;
+            break;
+         }
+
+         case STBI__PNG_TYPE('I','E','N','D'): {
+            stbi__uint32 raw_len, bpl;
+            if (first) return stbi__err("first not IHDR", "Corrupt PNG");
+            if (scan != STBI__SCAN_load) return 1;
+            if (z->idata == NULL) return stbi__err("no IDAT","Corrupt PNG");
+            // initial guess for decoded data size to avoid unnecessary reallocs
+            bpl = (s->img_x * z->depth + 7) / 8; // bytes per line, per component
+            raw_len = bpl * s->img_y * s->img_n /* pixels */ + s->img_y /* filter mode per row */;
+            z->expanded = (stbi_uc *) stbi_zlib_decode_malloc_guesssize_headerflag((char *) z->idata, ioff, raw_len, (int *) &raw_len, !is_iphone);
+            if (z->expanded == NULL) return 0; // zlib should set error
+            STBI_FREE(z->idata); z->idata = NULL;
+            if ((req_comp == s->img_n+1 && req_comp != 3 && !pal_img_n) || has_trans)
+               s->img_out_n = s->img_n+1;
+            else
+               s->img_out_n = s->img_n;
+            if (!stbi__create_png_image(z, z->expanded, raw_len, s->img_out_n, z->depth, color, interlace)) return 0;
+            if (has_trans) {
+               if (z->depth == 16) {
+                  if (!stbi__compute_transparency16(z, tc16, s->img_out_n)) return 0;
+               } else {
+                  if (!stbi__compute_transparency(z, tc, s->img_out_n)) return 0;
+               }
+            }
+            if (is_iphone && stbi__de_iphone_flag && s->img_out_n > 2)
+               stbi__de_iphone(z);
+            if (pal_img_n) {
+               // pal_img_n == 3 or 4
+               s->img_n = pal_img_n; // record the actual colors we had
+               s->img_out_n = pal_img_n;
+               if (req_comp >= 3) s->img_out_n = req_comp;
+               if (!stbi__expand_png_palette(z, palette, pal_len, s->img_out_n))
+                  return 0;
+            } else if (has_trans) {
+               // non-paletted image with tRNS -> source image has (constant) alpha
+               ++s->img_n;
+            }
+            STBI_FREE(z->expanded); z->expanded = NULL;
+            return 1;
+         }
+
+         default:
+            // if critical, fail
+            if (first) return stbi__err("first not IHDR", "Corrupt PNG");
+            if ((c.type & (1 << 29)) == 0) {
+               #ifndef STBI_NO_FAILURE_STRINGS
+               // not threadsafe
+               static char invalid_chunk[] = "XXXX PNG chunk not known";
+               invalid_chunk[0] = STBI__BYTECAST(c.type >> 24);
+               invalid_chunk[1] = STBI__BYTECAST(c.type >> 16);
+               invalid_chunk[2] = STBI__BYTECAST(c.type >>  8);
+               invalid_chunk[3] = STBI__BYTECAST(c.type >>  0);
+               #endif
+               return stbi__err(invalid_chunk, "PNG not supported: unknown PNG chunk type");
+            }
+            stbi__skip(s, c.length);
+            break;
+      }
+      // end of PNG chunk, read and skip CRC
+      stbi__get32be(s);
+   }
+}
+
+static void *stbi__do_png(stbi__png *p, int *x, int *y, int *n, int req_comp, stbi__result_info *ri)
+{
+   void *result=NULL;
+   if (req_comp < 0 || req_comp > 4) return stbi__errpuc("bad req_comp", "Internal error");
+   if (stbi__parse_png_file(p, STBI__SCAN_load, req_comp)) {
+      if (p->depth < 8)
+         ri->bits_per_channel = 8;
+      else
+         ri->bits_per_channel = p->depth;
+      result = p->out;
+      p->out = NULL;
+      if (req_comp && req_comp != p->s->img_out_n) {
+         if (ri->bits_per_channel == 8)
+            result = stbi__convert_format((unsigned char *) result, p->s->img_out_n, req_comp, p->s->img_x, p->s->img_y);
+         else
+            result = stbi__convert_format16((stbi__uint16 *) result, p->s->img_out_n, req_comp, p->s->img_x, p->s->img_y);
+         p->s->img_out_n = req_comp;
+         if (result == NULL) return result;
+      }
+      *x = p->s->img_x;
+      *y = p->s->img_y;
+      if (n) *n = p->s->img_n;
+   }
+   STBI_FREE(p->out);      p->out      = NULL;
+   STBI_FREE(p->expanded); p->expanded = NULL;
+   STBI_FREE(p->idata);    p->idata    = NULL;
+
+   return result;
+}
+
+static void *stbi__png_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri)
+{
+   stbi__png p;
+   p.s = s;
+   return stbi__do_png(&p, x,y,comp,req_comp, ri);
+}
+
+static int stbi__png_test(stbi__context *s)
+{
+   int r;
+   r = stbi__check_png_header(s);
+   stbi__rewind(s);
+   return r;
+}
+
+static int stbi__png_info_raw(stbi__png *p, int *x, int *y, int *comp)
+{
+   if (!stbi__parse_png_file(p, STBI__SCAN_header, 0)) {
+      stbi__rewind( p->s );
+      return 0;
+   }
+   if (x) *x = p->s->img_x;
+   if (y) *y = p->s->img_y;
+   if (comp) *comp = p->s->img_n;
+   return 1;
+}
+
+static int stbi__png_info(stbi__context *s, int *x, int *y, int *comp)
+{
+   stbi__png p;
+   p.s = s;
+   return stbi__png_info_raw(&p, x, y, comp);
+}
+
+static int stbi__png_is16(stbi__context *s)
+{
+   stbi__png p;
+   p.s = s;
+   if (!stbi__png_info_raw(&p, NULL, NULL, NULL))
+	   return 0;
+   if (p.depth != 16) {
+      stbi__rewind(p.s);
+      return 0;
+   }
+   return 1;
+}
+#endif
+
+// Microsoft/Windows BMP image
+
+#ifndef STBI_NO_BMP
+static int stbi__bmp_test_raw(stbi__context *s)
+{
+   int r;
+   int sz;
+   if (stbi__get8(s) != 'B') return 0;
+   if (stbi__get8(s) != 'M') return 0;
+   stbi__get32le(s); // discard filesize
+   stbi__get16le(s); // discard reserved
+   stbi__get16le(s); // discard reserved
+   stbi__get32le(s); // discard data offset
+   sz = stbi__get32le(s);
+   r = (sz == 12 || sz == 40 || sz == 56 || sz == 108 || sz == 124);
+   return r;
+}
+
+static int stbi__bmp_test(stbi__context *s)
+{
+   int r = stbi__bmp_test_raw(s);
+   stbi__rewind(s);
+   return r;
+}
+
+
+// returns 0..31 for the highest set bit
+static int stbi__high_bit(unsigned int z)
+{
+   int n=0;
+   if (z == 0) return -1;
+   if (z >= 0x10000) { n += 16; z >>= 16; }
+   if (z >= 0x00100) { n +=  8; z >>=  8; }
+   if (z >= 0x00010) { n +=  4; z >>=  4; }
+   if (z >= 0x00004) { n +=  2; z >>=  2; }
+   if (z >= 0x00002) { n +=  1;/* >>=  1;*/ }
+   return n;
+}
+
+static int stbi__bitcount(unsigned int a)
+{
+   a = (a & 0x55555555) + ((a >>  1) & 0x55555555); // max 2
+   a = (a & 0x33333333) + ((a >>  2) & 0x33333333); // max 4
+   a = (a + (a >> 4)) & 0x0f0f0f0f; // max 8 per 4, now 8 bits
+   a = (a + (a >> 8)); // max 16 per 8 bits
+   a = (a + (a >> 16)); // max 32 per 8 bits
+   return a & 0xff;
+}
+
+// extract an arbitrarily-aligned N-bit value (N=bits)
+// from v, and then make it 8-bits long and fractionally
+// extend it to full full range.
+static int stbi__shiftsigned(unsigned int v, int shift, int bits)
+{
+   static unsigned int mul_table[9] = {
+      0,
+      0xff/*0b11111111*/, 0x55/*0b01010101*/, 0x49/*0b01001001*/, 0x11/*0b00010001*/,
+      0x21/*0b00100001*/, 0x41/*0b01000001*/, 0x81/*0b10000001*/, 0x01/*0b00000001*/,
+   };
+   static unsigned int shift_table[9] = {
+      0, 0,0,1,0,2,4,6,0,
+   };
+   if (shift < 0)
+      v <<= -shift;
+   else
+      v >>= shift;
+   STBI_ASSERT(v >= 0 && v < 256);
+   v >>= (8-bits);
+   STBI_ASSERT(bits >= 0 && bits <= 8);
+   return (int) ((unsigned) v * mul_table[bits]) >> shift_table[bits];
+}
+
+typedef struct
+{
+   int bpp, offset, hsz;
+   unsigned int mr,mg,mb,ma, all_a;
+} stbi__bmp_data;
+
+static void *stbi__bmp_parse_header(stbi__context *s, stbi__bmp_data *info)
+{
+   int hsz;
+   if (stbi__get8(s) != 'B' || stbi__get8(s) != 'M') return stbi__errpuc("not BMP", "Corrupt BMP");
+   stbi__get32le(s); // discard filesize
+   stbi__get16le(s); // discard reserved
+   stbi__get16le(s); // discard reserved
+   info->offset = stbi__get32le(s);
+   info->hsz = hsz = stbi__get32le(s);
+   info->mr = info->mg = info->mb = info->ma = 0;
+
+   if (hsz != 12 && hsz != 40 && hsz != 56 && hsz != 108 && hsz != 124) return stbi__errpuc("unknown BMP", "BMP type not supported: unknown");
+   if (hsz == 12) {
+      s->img_x = stbi__get16le(s);
+      s->img_y = stbi__get16le(s);
+   } else {
+      s->img_x = stbi__get32le(s);
+      s->img_y = stbi__get32le(s);
+   }
+   if (stbi__get16le(s) != 1) return stbi__errpuc("bad BMP", "bad BMP");
+   info->bpp = stbi__get16le(s);
+   if (hsz != 12) {
+      int compress = stbi__get32le(s);
+      if (compress == 1 || compress == 2) return stbi__errpuc("BMP RLE", "BMP type not supported: RLE");
+      stbi__get32le(s); // discard sizeof
+      stbi__get32le(s); // discard hres
+      stbi__get32le(s); // discard vres
+      stbi__get32le(s); // discard colorsused
+      stbi__get32le(s); // discard max important
+      if (hsz == 40 || hsz == 56) {
+         if (hsz == 56) {
+            stbi__get32le(s);
+            stbi__get32le(s);
+            stbi__get32le(s);
+            stbi__get32le(s);
+         }
+         if (info->bpp == 16 || info->bpp == 32) {
+            if (compress == 0) {
+               if (info->bpp == 32) {
+                  info->mr = 0xffu << 16;
+                  info->mg = 0xffu <<  8;
+                  info->mb = 0xffu <<  0;
+                  info->ma = 0xffu << 24;
+                  info->all_a = 0; // if all_a is 0 at end, then we loaded alpha channel but it was all 0
+               } else {
+                  info->mr = 31u << 10;
+                  info->mg = 31u <<  5;
+                  info->mb = 31u <<  0;
+               }
+            } else if (compress == 3) {
+               info->mr = stbi__get32le(s);
+               info->mg = stbi__get32le(s);
+               info->mb = stbi__get32le(s);
+               // not documented, but generated by photoshop and handled by mspaint
+               if (info->mr == info->mg && info->mg == info->mb) {
+                  // ?!?!?
+                  return stbi__errpuc("bad BMP", "bad BMP");
+               }
+            } else
+               return stbi__errpuc("bad BMP", "bad BMP");
+         }
+      } else {
+         int i;
+         if (hsz != 108 && hsz != 124)
+            return stbi__errpuc("bad BMP", "bad BMP");
+         info->mr = stbi__get32le(s);
+         info->mg = stbi__get32le(s);
+         info->mb = stbi__get32le(s);
+         info->ma = stbi__get32le(s);
+         stbi__get32le(s); // discard color space
+         for (i=0; i < 12; ++i)
+            stbi__get32le(s); // discard color space parameters
+         if (hsz == 124) {
+            stbi__get32le(s); // discard rendering intent
+            stbi__get32le(s); // discard offset of profile data
+            stbi__get32le(s); // discard size of profile data
+            stbi__get32le(s); // discard reserved
+         }
+      }
+   }
+   return (void *) 1;
+}
+
+
+static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri)
+{
+   stbi_uc *out;
+   unsigned int mr=0,mg=0,mb=0,ma=0, all_a;
+   stbi_uc pal[256][4];
+   int psize=0,i,j,width;
+   int flip_vertically, pad, target;
+   stbi__bmp_data info;
+   STBI_NOTUSED(ri);
+
+   info.all_a = 255;
+   if (stbi__bmp_parse_header(s, &info) == NULL)
+      return NULL; // error code already set
+
+   flip_vertically = ((int) s->img_y) > 0;
+   s->img_y = abs((int) s->img_y);
+
+   mr = info.mr;
+   mg = info.mg;
+   mb = info.mb;
+   ma = info.ma;
+   all_a = info.all_a;
+
+   if (info.hsz == 12) {
+      if (info.bpp < 24)
+         psize = (info.offset - 14 - 24) / 3;
+   } else {
+      if (info.bpp < 16)
+         psize = (info.offset - 14 - info.hsz) >> 2;
+   }
+
+   if (info.bpp == 24 && ma == 0xff000000)
+      s->img_n = 3;
+   else
+      s->img_n = ma ? 4 : 3;
+   if (req_comp && req_comp >= 3) // we can directly decode 3 or 4
+      target = req_comp;
+   else
+      target = s->img_n; // if they want monochrome, we'll post-convert
+
+   // sanity-check size
+   if (!stbi__mad3sizes_valid(target, s->img_x, s->img_y, 0))
+      return stbi__errpuc("too large", "Corrupt BMP");
+
+   out = (stbi_uc *) stbi__malloc_mad3(target, s->img_x, s->img_y, 0);
+   if (!out) return stbi__errpuc("outofmem", "Out of memory");
+   if (info.bpp < 16) {
+      int z=0;
+      if (psize == 0 || psize > 256) { STBI_FREE(out); return stbi__errpuc("invalid", "Corrupt BMP"); }
+      for (i=0; i < psize; ++i) {
+         pal[i][2] = stbi__get8(s);
+         pal[i][1] = stbi__get8(s);
+         pal[i][0] = stbi__get8(s);
+         if (info.hsz != 12) stbi__get8(s);
+         pal[i][3] = 255;
+      }
+      stbi__skip(s, info.offset - 14 - info.hsz - psize * (info.hsz == 12 ? 3 : 4));
+      if (info.bpp == 1) width = (s->img_x + 7) >> 3;
+      else if (info.bpp == 4) width = (s->img_x + 1) >> 1;
+      else if (info.bpp == 8) width = s->img_x;
+      else { STBI_FREE(out); return stbi__errpuc("bad bpp", "Corrupt BMP"); }
+      pad = (-width)&3;
+      if (info.bpp == 1) {
+         for (j=0; j < (int) s->img_y; ++j) {
+            int bit_offset = 7, v = stbi__get8(s);
+            for (i=0; i < (int) s->img_x; ++i) {
+               int color = (v>>bit_offset)&0x1;
+               out[z++] = pal[color][0];
+               out[z++] = pal[color][1];
+               out[z++] = pal[color][2];
+               if (target == 4) out[z++] = 255;
+               if (i+1 == (int) s->img_x) break;
+               if((--bit_offset) < 0) {
+                  bit_offset = 7;
+                  v = stbi__get8(s);
+               }
+            }
+            stbi__skip(s, pad);
+         }
+      } else {
+         for (j=0; j < (int) s->img_y; ++j) {
+            for (i=0; i < (int) s->img_x; i += 2) {
+               int v=stbi__get8(s),v2=0;
+               if (info.bpp == 4) {
+                  v2 = v & 15;
+                  v >>= 4;
+               }
+               out[z++] = pal[v][0];
+               out[z++] = pal[v][1];
+               out[z++] = pal[v][2];
+               if (target == 4) out[z++] = 255;
+               if (i+1 == (int) s->img_x) break;
+               v = (info.bpp == 8) ? stbi__get8(s) : v2;
+               out[z++] = pal[v][0];
+               out[z++] = pal[v][1];
+               out[z++] = pal[v][2];
+               if (target == 4) out[z++] = 255;
+            }
+            stbi__skip(s, pad);
+         }
+      }
+   } else {
+      int rshift=0,gshift=0,bshift=0,ashift=0,rcount=0,gcount=0,bcount=0,acount=0;
+      int z = 0;
+      int easy=0;
+      stbi__skip(s, info.offset - 14 - info.hsz);
+      if (info.bpp == 24) width = 3 * s->img_x;
+      else if (info.bpp == 16) width = 2*s->img_x;
+      else /* bpp = 32 and pad = 0 */ width=0;
+      pad = (-width) & 3;
+      if (info.bpp == 24) {
+         easy = 1;
+      } else if (info.bpp == 32) {
+         if (mb == 0xff && mg == 0xff00 && mr == 0x00ff0000 && ma == 0xff000000)
+            easy = 2;
+      }
+      if (!easy) {
+         if (!mr || !mg || !mb) { STBI_FREE(out); return stbi__errpuc("bad masks", "Corrupt BMP"); }
+         // right shift amt to put high bit in position #7
+         rshift = stbi__high_bit(mr)-7; rcount = stbi__bitcount(mr);
+         gshift = stbi__high_bit(mg)-7; gcount = stbi__bitcount(mg);
+         bshift = stbi__high_bit(mb)-7; bcount = stbi__bitcount(mb);
+         ashift = stbi__high_bit(ma)-7; acount = stbi__bitcount(ma);
+      }
+      for (j=0; j < (int) s->img_y; ++j) {
+         if (easy) {
+            for (i=0; i < (int) s->img_x; ++i) {
+               unsigned char a;
+               out[z+2] = stbi__get8(s);
+               out[z+1] = stbi__get8(s);
+               out[z+0] = stbi__get8(s);
+               z += 3;
+               a = (easy == 2 ? stbi__get8(s) : 255);
+               all_a |= a;
+               if (target == 4) out[z++] = a;
+            }
+         } else {
+            int bpp = info.bpp;
+            for (i=0; i < (int) s->img_x; ++i) {
+               stbi__uint32 v = (bpp == 16 ? (stbi__uint32) stbi__get16le(s) : stbi__get32le(s));
+               unsigned int a;
+               out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mr, rshift, rcount));
+               out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mg, gshift, gcount));
+               out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mb, bshift, bcount));
+               a = (ma ? stbi__shiftsigned(v & ma, ashift, acount) : 255);
+               all_a |= a;
+               if (target == 4) out[z++] = STBI__BYTECAST(a);
+            }
+         }
+         stbi__skip(s, pad);
+      }
+   }
+
+   // if alpha channel is all 0s, replace with all 255s
+   if (target == 4 && all_a == 0)
+      for (i=4*s->img_x*s->img_y-1; i >= 0; i -= 4)
+         out[i] = 255;
+
+   if (flip_vertically) {
+      stbi_uc t;
+      for (j=0; j < (int) s->img_y>>1; ++j) {
+         stbi_uc *p1 = out +      j     *s->img_x*target;
+         stbi_uc *p2 = out + (s->img_y-1-j)*s->img_x*target;
+         for (i=0; i < (int) s->img_x*target; ++i) {
+            t = p1[i]; p1[i] = p2[i]; p2[i] = t;
+         }
+      }
+   }
+
+   if (req_comp && req_comp != target) {
+      out = stbi__convert_format(out, target, req_comp, s->img_x, s->img_y);
+      if (out == NULL) return out; // stbi__convert_format frees input on failure
+   }
+
+   *x = s->img_x;
+   *y = s->img_y;
+   if (comp) *comp = s->img_n;
+   return out;
+}
+#endif
+
+// Targa Truevision - TGA
+// by Jonathan Dummer
+#ifndef STBI_NO_TGA
+// returns STBI_rgb or whatever, 0 on error
+static int stbi__tga_get_comp(int bits_per_pixel, int is_grey, int* is_rgb16)
+{
+   // only RGB or RGBA (incl. 16bit) or grey allowed
+   if (is_rgb16) *is_rgb16 = 0;
+   switch(bits_per_pixel) {
+      case 8:  return STBI_grey;
+      case 16: if(is_grey) return STBI_grey_alpha;
+               // fallthrough
+      case 15: if(is_rgb16) *is_rgb16 = 1;
+               return STBI_rgb;
+      case 24: // fallthrough
+      case 32: return bits_per_pixel/8;
+      default: return 0;
+   }
+}
+
+static int stbi__tga_info(stbi__context *s, int *x, int *y, int *comp)
+{
+    int tga_w, tga_h, tga_comp, tga_image_type, tga_bits_per_pixel, tga_colormap_bpp;
+    int sz, tga_colormap_type;
+    stbi__get8(s);                   // discard Offset
+    tga_colormap_type = stbi__get8(s); // colormap type
+    if( tga_colormap_type > 1 ) {
+        stbi__rewind(s);
+        return 0;      // only RGB or indexed allowed
+    }
+    tga_image_type = stbi__get8(s); // image type
+    if ( tga_colormap_type == 1 ) { // colormapped (paletted) image
+        if (tga_image_type != 1 && tga_image_type != 9) {
+            stbi__rewind(s);
+            return 0;
+        }
+        stbi__skip(s,4);       // skip index of first colormap entry and number of entries
+        sz = stbi__get8(s);    //   check bits per palette color entry
+        if ( (sz != 8) && (sz != 15) && (sz != 16) && (sz != 24) && (sz != 32) ) {
+            stbi__rewind(s);
+            return 0;
+        }
+        stbi__skip(s,4);       // skip image x and y origin
+        tga_colormap_bpp = sz;
+    } else { // "normal" image w/o colormap - only RGB or grey allowed, +/- RLE
+        if ( (tga_image_type != 2) && (tga_image_type != 3) && (tga_image_type != 10) && (tga_image_type != 11) ) {
+            stbi__rewind(s);
+            return 0; // only RGB or grey allowed, +/- RLE
+        }
+        stbi__skip(s,9); // skip colormap specification and image x/y origin
+        tga_colormap_bpp = 0;
+    }
+    tga_w = stbi__get16le(s);
+    if( tga_w < 1 ) {
+        stbi__rewind(s);
+        return 0;   // test width
+    }
+    tga_h = stbi__get16le(s);
+    if( tga_h < 1 ) {
+        stbi__rewind(s);
+        return 0;   // test height
+    }
+    tga_bits_per_pixel = stbi__get8(s); // bits per pixel
+    stbi__get8(s); // ignore alpha bits
+    if (tga_colormap_bpp != 0) {
+        if((tga_bits_per_pixel != 8) && (tga_bits_per_pixel != 16)) {
+            // when using a colormap, tga_bits_per_pixel is the size of the indexes
+            // I don't think anything but 8 or 16bit indexes makes sense
+            stbi__rewind(s);
+            return 0;
+        }
+        tga_comp = stbi__tga_get_comp(tga_colormap_bpp, 0, NULL);
+    } else {
+        tga_comp = stbi__tga_get_comp(tga_bits_per_pixel, (tga_image_type == 3) || (tga_image_type == 11), NULL);
+    }
+    if(!tga_comp) {
+      stbi__rewind(s);
+      return 0;
+    }
+    if (x) *x = tga_w;
+    if (y) *y = tga_h;
+    if (comp) *comp = tga_comp;
+    return 1;                   // seems to have passed everything
+}
+
+static int stbi__tga_test(stbi__context *s)
+{
+   int res = 0;
+   int sz, tga_color_type;
+   stbi__get8(s);      //   discard Offset
+   tga_color_type = stbi__get8(s);   //   color type
+   if ( tga_color_type > 1 ) goto errorEnd;   //   only RGB or indexed allowed
+   sz = stbi__get8(s);   //   image type
+   if ( tga_color_type == 1 ) { // colormapped (paletted) image
+      if (sz != 1 && sz != 9) goto errorEnd; // colortype 1 demands image type 1 or 9
+      stbi__skip(s,4);       // skip index of first colormap entry and number of entries
+      sz = stbi__get8(s);    //   check bits per palette color entry
+      if ( (sz != 8) && (sz != 15) && (sz != 16) && (sz != 24) && (sz != 32) ) goto errorEnd;
+      stbi__skip(s,4);       // skip image x and y origin
+   } else { // "normal" image w/o colormap
+      if ( (sz != 2) && (sz != 3) && (sz != 10) && (sz != 11) ) goto errorEnd; // only RGB or grey allowed, +/- RLE
+      stbi__skip(s,9); // skip colormap specification and image x/y origin
+   }
+   if ( stbi__get16le(s) < 1 ) goto errorEnd;      //   test width
+   if ( stbi__get16le(s) < 1 ) goto errorEnd;      //   test height
+   sz = stbi__get8(s);   //   bits per pixel
+   if ( (tga_color_type == 1) && (sz != 8) && (sz != 16) ) goto errorEnd; // for colormapped images, bpp is size of an index
+   if ( (sz != 8) && (sz != 15) && (sz != 16) && (sz != 24) && (sz != 32) ) goto errorEnd;
+
+   res = 1; // if we got this far, everything's good and we can return 1 instead of 0
+
+errorEnd:
+   stbi__rewind(s);
+   return res;
+}
+
+// read 16bit value and convert to 24bit RGB
+static void stbi__tga_read_rgb16(stbi__context *s, stbi_uc* out)
+{
+   stbi__uint16 px = (stbi__uint16)stbi__get16le(s);
+   stbi__uint16 fiveBitMask = 31;
+   // we have 3 channels with 5bits each
+   int r = (px >> 10) & fiveBitMask;
+   int g = (px >> 5) & fiveBitMask;
+   int b = px & fiveBitMask;
+   // Note that this saves the data in RGB(A) order, so it doesn't need to be swapped later
+   out[0] = (stbi_uc)((r * 255)/31);
+   out[1] = (stbi_uc)((g * 255)/31);
+   out[2] = (stbi_uc)((b * 255)/31);
+
+   // some people claim that the most significant bit might be used for alpha
+   // (possibly if an alpha-bit is set in the "image descriptor byte")
+   // but that only made 16bit test images completely translucent..
+   // so let's treat all 15 and 16bit TGAs as RGB with no alpha.
+}
+
+static void *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri)
+{
+   //   read in the TGA header stuff
+   int tga_offset = stbi__get8(s);
+   int tga_indexed = stbi__get8(s);
+   int tga_image_type = stbi__get8(s);
+   int tga_is_RLE = 0;
+   int tga_palette_start = stbi__get16le(s);
+   int tga_palette_len = stbi__get16le(s);
+   int tga_palette_bits = stbi__get8(s);
+   int tga_x_origin = stbi__get16le(s);
+   int tga_y_origin = stbi__get16le(s);
+   int tga_width = stbi__get16le(s);
+   int tga_height = stbi__get16le(s);
+   int tga_bits_per_pixel = stbi__get8(s);
+   int tga_comp, tga_rgb16=0;
+   int tga_inverted = stbi__get8(s);
+   // int tga_alpha_bits = tga_inverted & 15; // the 4 lowest bits - unused (useless?)
+   //   image data
+   unsigned char *tga_data;
+   unsigned char *tga_palette = NULL;
+   int i, j;
+   unsigned char raw_data[4] = {0};
+   int RLE_count = 0;
+   int RLE_repeating = 0;
+   int read_next_pixel = 1;
+   STBI_NOTUSED(ri);
+   STBI_NOTUSED(tga_x_origin); // @TODO
+   STBI_NOTUSED(tga_y_origin); // @TODO
+
+   //   do a tiny bit of precessing
+   if ( tga_image_type >= 8 )
+   {
+      tga_image_type -= 8;
+      tga_is_RLE = 1;
+   }
+   tga_inverted = 1 - ((tga_inverted >> 5) & 1);
+
+   //   If I'm paletted, then I'll use the number of bits from the palette
+   if ( tga_indexed ) tga_comp = stbi__tga_get_comp(tga_palette_bits, 0, &tga_rgb16);
+   else tga_comp = stbi__tga_get_comp(tga_bits_per_pixel, (tga_image_type == 3), &tga_rgb16);
+
+   if(!tga_comp) // shouldn't really happen, stbi__tga_test() should have ensured basic consistency
+      return stbi__errpuc("bad format", "Can't find out TGA pixelformat");
+
+   //   tga info
+   *x = tga_width;
+   *y = tga_height;
+   if (comp) *comp = tga_comp;
+
+   if (!stbi__mad3sizes_valid(tga_width, tga_height, tga_comp, 0))
+      return stbi__errpuc("too large", "Corrupt TGA");
+
+   tga_data = (unsigned char*)stbi__malloc_mad3(tga_width, tga_height, tga_comp, 0);
+   if (!tga_data) return stbi__errpuc("outofmem", "Out of memory");
+
+   // skip to the data's starting position (offset usually = 0)
+   stbi__skip(s, tga_offset );
+
+   if ( !tga_indexed && !tga_is_RLE && !tga_rgb16 ) {
+      for (i=0; i < tga_height; ++i) {
+         int row = tga_inverted ? tga_height -i - 1 : i;
+         stbi_uc *tga_row = tga_data + row*tga_width*tga_comp;
+         stbi__getn(s, tga_row, tga_width * tga_comp);
+      }
+   } else  {
+      //   do I need to load a palette?
+      if ( tga_indexed)
+      {
+         //   any data to skip? (offset usually = 0)
+         stbi__skip(s, tga_palette_start );
+         //   load the palette
+         tga_palette = (unsigned char*)stbi__malloc_mad2(tga_palette_len, tga_comp, 0);
+         if (!tga_palette) {
+            STBI_FREE(tga_data);
+            return stbi__errpuc("outofmem", "Out of memory");
+         }
+         if (tga_rgb16) {
+            stbi_uc *pal_entry = tga_palette;
+            STBI_ASSERT(tga_comp == STBI_rgb);
+            for (i=0; i < tga_palette_len; ++i) {
+               stbi__tga_read_rgb16(s, pal_entry);
+               pal_entry += tga_comp;
+            }
+         } else if (!stbi__getn(s, tga_palette, tga_palette_len * tga_comp)) {
+               STBI_FREE(tga_data);
+               STBI_FREE(tga_palette);
+               return stbi__errpuc("bad palette", "Corrupt TGA");
+         }
+      }
+      //   load the data
+      for (i=0; i < tga_width * tga_height; ++i)
+      {
+         //   if I'm in RLE mode, do I need to get a RLE stbi__pngchunk?
+         if ( tga_is_RLE )
+         {
+            if ( RLE_count == 0 )
+            {
+               //   yep, get the next byte as a RLE command
+               int RLE_cmd = stbi__get8(s);
+               RLE_count = 1 + (RLE_cmd & 127);
+               RLE_repeating = RLE_cmd >> 7;
+               read_next_pixel = 1;
+            } else if ( !RLE_repeating )
+            {
+               read_next_pixel = 1;
+            }
+         } else
+         {
+            read_next_pixel = 1;
+         }
+         //   OK, if I need to read a pixel, do it now
+         if ( read_next_pixel )
+         {
+            //   load however much data we did have
+            if ( tga_indexed )
+            {
+               // read in index, then perform the lookup
+               int pal_idx = (tga_bits_per_pixel == 8) ? stbi__get8(s) : stbi__get16le(s);
+               if ( pal_idx >= tga_palette_len ) {
+                  // invalid index
+                  pal_idx = 0;
+               }
+               pal_idx *= tga_comp;
+               for (j = 0; j < tga_comp; ++j) {
+                  raw_data[j] = tga_palette[pal_idx+j];
+               }
+            } else if(tga_rgb16) {
+               STBI_ASSERT(tga_comp == STBI_rgb);
+               stbi__tga_read_rgb16(s, raw_data);
+            } else {
+               //   read in the data raw
+               for (j = 0; j < tga_comp; ++j) {
+                  raw_data[j] = stbi__get8(s);
+               }
+            }
+            //   clear the reading flag for the next pixel
+            read_next_pixel = 0;
+         } // end of reading a pixel
+
+         // copy data
+         for (j = 0; j < tga_comp; ++j)
+           tga_data[i*tga_comp+j] = raw_data[j];
+
+         //   in case we're in RLE mode, keep counting down
+         --RLE_count;
+      }
+      //   do I need to invert the image?
+      if ( tga_inverted )
+      {
+         for (j = 0; j*2 < tga_height; ++j)
+         {
+            int index1 = j * tga_width * tga_comp;
+            int index2 = (tga_height - 1 - j) * tga_width * tga_comp;
+            for (i = tga_width * tga_comp; i > 0; --i)
+            {
+               unsigned char temp = tga_data[index1];
+               tga_data[index1] = tga_data[index2];
+               tga_data[index2] = temp;
+               ++index1;
+               ++index2;
+            }
+         }
+      }
+      //   clear my palette, if I had one
+      if ( tga_palette != NULL )
+      {
+         STBI_FREE( tga_palette );
+      }
+   }
+
+   // swap RGB - if the source data was RGB16, it already is in the right order
+   if (tga_comp >= 3 && !tga_rgb16)
+   {
+      unsigned char* tga_pixel = tga_data;
+      for (i=0; i < tga_width * tga_height; ++i)
+      {
+         unsigned char temp = tga_pixel[0];
+         tga_pixel[0] = tga_pixel[2];
+         tga_pixel[2] = temp;
+         tga_pixel += tga_comp;
+      }
+   }
+
+   // convert to target component count
+   if (req_comp && req_comp != tga_comp)
+      tga_data = stbi__convert_format(tga_data, tga_comp, req_comp, tga_width, tga_height);
+
+   //   the things I do to get rid of an error message, and yet keep
+   //   Microsoft's C compilers happy... [8^(
+   tga_palette_start = tga_palette_len = tga_palette_bits =
+         tga_x_origin = tga_y_origin = 0;
+   STBI_NOTUSED(tga_palette_start);
+   //   OK, done
+   return tga_data;
+}
+#endif
+
+// *************************************************************************************************
+// Photoshop PSD loader -- PD by Thatcher Ulrich, integration by Nicolas Schulz, tweaked by STB
+
+#ifndef STBI_NO_PSD
+static int stbi__psd_test(stbi__context *s)
+{
+   int r = (stbi__get32be(s) == 0x38425053);
+   stbi__rewind(s);
+   return r;
+}
+
+static int stbi__psd_decode_rle(stbi__context *s, stbi_uc *p, int pixelCount)
+{
+   int count, nleft, len;
+
+   count = 0;
+   while ((nleft = pixelCount - count) > 0) {
+      len = stbi__get8(s);
+      if (len == 128) {
+         // No-op.
+      } else if (len < 128) {
+         // Copy next len+1 bytes literally.
+         len++;
+         if (len > nleft) return 0; // corrupt data
+         count += len;
+         while (len) {
+            *p = stbi__get8(s);
+            p += 4;
+            len--;
+         }
+      } else if (len > 128) {
+         stbi_uc   val;
+         // Next -len+1 bytes in the dest are replicated from next source byte.
+         // (Interpret len as a negative 8-bit int.)
+         len = 257 - len;
+         if (len > nleft) return 0; // corrupt data
+         val = stbi__get8(s);
+         count += len;
+         while (len) {
+            *p = val;
+            p += 4;
+            len--;
+         }
+      }
+   }
+
+   return 1;
+}
+
+static void *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri, int bpc)
+{
+   int pixelCount;
+   int channelCount, compression;
+   int channel, i;
+   int bitdepth;
+   int w,h;
+   stbi_uc *out;
+   STBI_NOTUSED(ri);
+
+   // Check identifier
+   if (stbi__get32be(s) != 0x38425053)   // "8BPS"
+      return stbi__errpuc("not PSD", "Corrupt PSD image");
+
+   // Check file type version.
+   if (stbi__get16be(s) != 1)
+      return stbi__errpuc("wrong version", "Unsupported version of PSD image");
+
+   // Skip 6 reserved bytes.
+   stbi__skip(s, 6 );
+
+   // Read the number of channels (R, G, B, A, etc).
+   channelCount = stbi__get16be(s);
+   if (channelCount < 0 || channelCount > 16)
+      return stbi__errpuc("wrong channel count", "Unsupported number of channels in PSD image");
+
+   // Read the rows and columns of the image.
+   h = stbi__get32be(s);
+   w = stbi__get32be(s);
+
+   // Make sure the depth is 8 bits.
+   bitdepth = stbi__get16be(s);
+   if (bitdepth != 8 && bitdepth != 16)
+      return stbi__errpuc("unsupported bit depth", "PSD bit depth is not 8 or 16 bit");
+
+   // Make sure the color mode is RGB.
+   // Valid options are:
+   //   0: Bitmap
+   //   1: Grayscale
+   //   2: Indexed color
+   //   3: RGB color
+   //   4: CMYK color
+   //   7: Multichannel
+   //   8: Duotone
+   //   9: Lab color
+   if (stbi__get16be(s) != 3)
+      return stbi__errpuc("wrong color format", "PSD is not in RGB color format");
+
+   // Skip the Mode Data.  (It's the palette for indexed color; other info for other modes.)
+   stbi__skip(s,stbi__get32be(s) );
+
+   // Skip the image resources.  (resolution, pen tool paths, etc)
+   stbi__skip(s, stbi__get32be(s) );
+
+   // Skip the reserved data.
+   stbi__skip(s, stbi__get32be(s) );
+
+   // Find out if the data is compressed.
+   // Known values:
+   //   0: no compression
+   //   1: RLE compressed
+   compression = stbi__get16be(s);
+   if (compression > 1)
+      return stbi__errpuc("bad compression", "PSD has an unknown compression format");
+
+   // Check size
+   if (!stbi__mad3sizes_valid(4, w, h, 0))
+      return stbi__errpuc("too large", "Corrupt PSD");
+
+   // Create the destination image.
+
+   if (!compression && bitdepth == 16 && bpc == 16) {
+      out = (stbi_uc *) stbi__malloc_mad3(8, w, h, 0);
+      ri->bits_per_channel = 16;
+   } else
+      out = (stbi_uc *) stbi__malloc(4 * w*h);
+
+   if (!out) return stbi__errpuc("outofmem", "Out of memory");
+   pixelCount = w*h;
+
+   // Initialize the data to zero.
+   //memset( out, 0, pixelCount * 4 );
+
+   // Finally, the image data.
+   if (compression) {
+      // RLE as used by .PSD and .TIFF
+      // Loop until you get the number of unpacked bytes you are expecting:
+      //     Read the next source byte into n.
+      //     If n is between 0 and 127 inclusive, copy the next n+1 bytes literally.
+      //     Else if n is between -127 and -1 inclusive, copy the next byte -n+1 times.
+      //     Else if n is 128, noop.
+      // Endloop
+
+      // The RLE-compressed data is preceded by a 2-byte data count for each row in the data,
+      // which we're going to just skip.
+      stbi__skip(s, h * channelCount * 2 );
+
+      // Read the RLE data by channel.
+      for (channel = 0; channel < 4; channel++) {
+         stbi_uc *p;
+
+         p = out+channel;
+         if (channel >= channelCount) {
+            // Fill this channel with default data.
+            for (i = 0; i < pixelCount; i++, p += 4)
+               *p = (channel == 3 ? 255 : 0);
+         } else {
+            // Read the RLE data.
+            if (!stbi__psd_decode_rle(s, p, pixelCount)) {
+               STBI_FREE(out);
+               return stbi__errpuc("corrupt", "bad RLE data");
+            }
+         }
+      }
+
+   } else {
+      // We're at the raw image data.  It's each channel in order (Red, Green, Blue, Alpha, ...)
+      // where each channel consists of an 8-bit (or 16-bit) value for each pixel in the image.
+
+      // Read the data by channel.
+      for (channel = 0; channel < 4; channel++) {
+         if (channel >= channelCount) {
+            // Fill this channel with default data.
+            if (bitdepth == 16 && bpc == 16) {
+               stbi__uint16 *q = ((stbi__uint16 *) out) + channel;
+               stbi__uint16 val = channel == 3 ? 65535 : 0;
+               for (i = 0; i < pixelCount; i++, q += 4)
+                  *q = val;
+            } else {
+               stbi_uc *p = out+channel;
+               stbi_uc val = channel == 3 ? 255 : 0;
+               for (i = 0; i < pixelCount; i++, p += 4)
+                  *p = val;
+            }
+         } else {
+            if (ri->bits_per_channel == 16) {    // output bpc
+               stbi__uint16 *q = ((stbi__uint16 *) out) + channel;
+               for (i = 0; i < pixelCount; i++, q += 4)
+                  *q = (stbi__uint16) stbi__get16be(s);
+            } else {
+               stbi_uc *p = out+channel;
+               if (bitdepth == 16) {  // input bpc
+                  for (i = 0; i < pixelCount; i++, p += 4)
+                     *p = (stbi_uc) (stbi__get16be(s) >> 8);
+               } else {
+                  for (i = 0; i < pixelCount; i++, p += 4)
+                     *p = stbi__get8(s);
+               }
+            }
+         }
+      }
+   }
+
+   // remove weird white matte from PSD
+   if (channelCount >= 4) {
+      if (ri->bits_per_channel == 16) {
+         for (i=0; i < w*h; ++i) {
+            stbi__uint16 *pixel = (stbi__uint16 *) out + 4*i;
+            if (pixel[3] != 0 && pixel[3] != 65535) {
+               float a = pixel[3] / 65535.0f;
+               float ra = 1.0f / a;
+               float inv_a = 65535.0f * (1 - ra);
+               pixel[0] = (stbi__uint16) (pixel[0]*ra + inv_a);
+               pixel[1] = (stbi__uint16) (pixel[1]*ra + inv_a);
+               pixel[2] = (stbi__uint16) (pixel[2]*ra + inv_a);
+            }
+         }
+      } else {
+         for (i=0; i < w*h; ++i) {
+            unsigned char *pixel = out + 4*i;
+            if (pixel[3] != 0 && pixel[3] != 255) {
+               float a = pixel[3] / 255.0f;
+               float ra = 1.0f / a;
+               float inv_a = 255.0f * (1 - ra);
+               pixel[0] = (unsigned char) (pixel[0]*ra + inv_a);
+               pixel[1] = (unsigned char) (pixel[1]*ra + inv_a);
+               pixel[2] = (unsigned char) (pixel[2]*ra + inv_a);
+            }
+         }
+      }
+   }
+
+   // convert to desired output format
+   if (req_comp && req_comp != 4) {
+      if (ri->bits_per_channel == 16)
+         out = (stbi_uc *) stbi__convert_format16((stbi__uint16 *) out, 4, req_comp, w, h);
+      else
+         out = stbi__convert_format(out, 4, req_comp, w, h);
+      if (out == NULL) return out; // stbi__convert_format frees input on failure
+   }
+
+   if (comp) *comp = 4;
+   *y = h;
+   *x = w;
+
+   return out;
+}
+#endif
+
+// *************************************************************************************************
+// Softimage PIC loader
+// by Tom Seddon
+//
+// See http://softimage.wiki.softimage.com/index.php/INFO:_PIC_file_format
+// See http://ozviz.wasp.uwa.edu.au/~pbourke/dataformats/softimagepic/
+
+#ifndef STBI_NO_PIC
+static int stbi__pic_is4(stbi__context *s,const char *str)
+{
+   int i;
+   for (i=0; i<4; ++i)
+      if (stbi__get8(s) != (stbi_uc)str[i])
+         return 0;
+
+   return 1;
+}
+
+static int stbi__pic_test_core(stbi__context *s)
+{
+   int i;
+
+   if (!stbi__pic_is4(s,"\x53\x80\xF6\x34"))
+      return 0;
+
+   for(i=0;i<84;++i)
+      stbi__get8(s);
+
+   if (!stbi__pic_is4(s,"PICT"))
+      return 0;
+
+   return 1;
+}
+
+typedef struct
+{
+   stbi_uc size,type,channel;
+} stbi__pic_packet;
+
+static stbi_uc *stbi__readval(stbi__context *s, int channel, stbi_uc *dest)
+{
+   int mask=0x80, i;
+
+   for (i=0; i<4; ++i, mask>>=1) {
+      if (channel & mask) {
+         if (stbi__at_eof(s)) return stbi__errpuc("bad file","PIC file too short");
+         dest[i]=stbi__get8(s);
+      }
+   }
+
+   return dest;
+}
+
+static void stbi__copyval(int channel,stbi_uc *dest,const stbi_uc *src)
+{
+   int mask=0x80,i;
+
+   for (i=0;i<4; ++i, mask>>=1)
+      if (channel&mask)
+         dest[i]=src[i];
+}
+
+static stbi_uc *stbi__pic_load_core(stbi__context *s,int width,int height,int *comp, stbi_uc *result)
+{
+   int act_comp=0,num_packets=0,y,chained;
+   stbi__pic_packet packets[10];
+
+   // this will (should...) cater for even some bizarre stuff like having data
+    // for the same channel in multiple packets.
+   do {
+      stbi__pic_packet *packet;
+
+      if (num_packets==sizeof(packets)/sizeof(packets[0]))
+         return stbi__errpuc("bad format","too many packets");
+
+      packet = &packets[num_packets++];
+
+      chained = stbi__get8(s);
+      packet->size    = stbi__get8(s);
+      packet->type    = stbi__get8(s);
+      packet->channel = stbi__get8(s);
+
+      act_comp |= packet->channel;
+
+      if (stbi__at_eof(s))          return stbi__errpuc("bad file","file too short (reading packets)");
+      if (packet->size != 8)  return stbi__errpuc("bad format","packet isn't 8bpp");
+   } while (chained);
+
+   *comp = (act_comp & 0x10 ? 4 : 3); // has alpha channel?
+
+   for(y=0; y<height; ++y) {
+      int packet_idx;
+
+      for(packet_idx=0; packet_idx < num_packets; ++packet_idx) {
+         stbi__pic_packet *packet = &packets[packet_idx];
+         stbi_uc *dest = result+y*width*4;
+
+         switch (packet->type) {
+            default:
+               return stbi__errpuc("bad format","packet has bad compression type");
+
+            case 0: {//uncompressed
+               int x;
+
+               for(x=0;x<width;++x, dest+=4)
+                  if (!stbi__readval(s,packet->channel,dest))
+                     return 0;
+               break;
+            }
+
+            case 1://Pure RLE
+               {
+                  int left=width, i;
+
+                  while (left>0) {
+                     stbi_uc count,value[4];
+
+                     count=stbi__get8(s);
+                     if (stbi__at_eof(s))   return stbi__errpuc("bad file","file too short (pure read count)");
+
+                     if (count > left)
+                        count = (stbi_uc) left;
+
+                     if (!stbi__readval(s,packet->channel,value))  return 0;
+
+                     for(i=0; i<count; ++i,dest+=4)
+                        stbi__copyval(packet->channel,dest,value);
+                     left -= count;
+                  }
+               }
+               break;
+
+            case 2: {//Mixed RLE
+               int left=width;
+               while (left>0) {
+                  int count = stbi__get8(s), i;
+                  if (stbi__at_eof(s))  return stbi__errpuc("bad file","file too short (mixed read count)");
+
+                  if (count >= 128) { // Repeated
+                     stbi_uc value[4];
+
+                     if (count==128)
+                        count = stbi__get16be(s);
+                     else
+                        count -= 127;
+                     if (count > left)
+                        return stbi__errpuc("bad file","scanline overrun");
+
+                     if (!stbi__readval(s,packet->channel,value))
+                        return 0;
+
+                     for(i=0;i<count;++i, dest += 4)
+                        stbi__copyval(packet->channel,dest,value);
+                  } else { // Raw
+                     ++count;
+                     if (count>left) return stbi__errpuc("bad file","scanline overrun");
+
+                     for(i=0;i<count;++i, dest+=4)
+                        if (!stbi__readval(s,packet->channel,dest))
+                           return 0;
+                  }
+                  left-=count;
+               }
+               break;
+            }
+         }
+      }
+   }
+
+   return result;
+}
+
+static void *stbi__pic_load(stbi__context *s,int *px,int *py,int *comp,int req_comp, stbi__result_info *ri)
+{
+   stbi_uc *result;
+   int i, x,y, internal_comp;
+   STBI_NOTUSED(ri);
+
+   if (!comp) comp = &internal_comp;
+
+   for (i=0; i<92; ++i)
+      stbi__get8(s);
+
+   x = stbi__get16be(s);
+   y = stbi__get16be(s);
+   if (stbi__at_eof(s))  return stbi__errpuc("bad file","file too short (pic header)");
+   if (!stbi__mad3sizes_valid(x, y, 4, 0)) return stbi__errpuc("too large", "PIC image too large to decode");
+
+   stbi__get32be(s); //skip `ratio'
+   stbi__get16be(s); //skip `fields'
+   stbi__get16be(s); //skip `pad'
+
+   // intermediate buffer is RGBA
+   result = (stbi_uc *) stbi__malloc_mad3(x, y, 4, 0);
+   memset(result, 0xff, x*y*4);
+
+   if (!stbi__pic_load_core(s,x,y,comp, result)) {
+      STBI_FREE(result);
+      result=0;
+   }
+   *px = x;
+   *py = y;
+   if (req_comp == 0) req_comp = *comp;
+   result=stbi__convert_format(result,4,req_comp,x,y);
+
+   return result;
+}
+
+static int stbi__pic_test(stbi__context *s)
+{
+   int r = stbi__pic_test_core(s);
+   stbi__rewind(s);
+   return r;
+}
+#endif
+
+// *************************************************************************************************
+// GIF loader -- public domain by Jean-Marc Lienher -- simplified/shrunk by stb
+
+#ifndef STBI_NO_GIF
+typedef struct
+{
+   stbi__int16 prefix;
+   stbi_uc first;
+   stbi_uc suffix;
+} stbi__gif_lzw;
+
+typedef struct
+{
+   int w,h;
+   stbi_uc *out;                 // output buffer (always 4 components)
+   stbi_uc *background;          // The current "background" as far as a gif is concerned
+   stbi_uc *history; 
+   int flags, bgindex, ratio, transparent, eflags;
+   stbi_uc  pal[256][4];
+   stbi_uc lpal[256][4];
+   stbi__gif_lzw codes[8192];
+   stbi_uc *color_table;
+   int parse, step;
+   int lflags;
+   int start_x, start_y;
+   int max_x, max_y;
+   int cur_x, cur_y;
+   int line_size;
+   int delay;
+} stbi__gif;
+
+static int stbi__gif_test_raw(stbi__context *s)
+{
+   int sz;
+   if (stbi__get8(s) != 'G' || stbi__get8(s) != 'I' || stbi__get8(s) != 'F' || stbi__get8(s) != '8') return 0;
+   sz = stbi__get8(s);
+   if (sz != '9' && sz != '7') return 0;
+   if (stbi__get8(s) != 'a') return 0;
+   return 1;
+}
+
+static int stbi__gif_test(stbi__context *s)
+{
+   int r = stbi__gif_test_raw(s);
+   stbi__rewind(s);
+   return r;
+}
+
+static void stbi__gif_parse_colortable(stbi__context *s, stbi_uc pal[256][4], int num_entries, int transp)
+{
+   int i;
+   for (i=0; i < num_entries; ++i) {
+      pal[i][2] = stbi__get8(s);
+      pal[i][1] = stbi__get8(s);
+      pal[i][0] = stbi__get8(s);
+      pal[i][3] = transp == i ? 0 : 255;
+   }
+}
+
+static int stbi__gif_header(stbi__context *s, stbi__gif *g, int *comp, int is_info)
+{
+   stbi_uc version;
+   if (stbi__get8(s) != 'G' || stbi__get8(s) != 'I' || stbi__get8(s) != 'F' || stbi__get8(s) != '8')
+      return stbi__err("not GIF", "Corrupt GIF");
+
+   version = stbi__get8(s);
+   if (version != '7' && version != '9')    return stbi__err("not GIF", "Corrupt GIF");
+   if (stbi__get8(s) != 'a')                return stbi__err("not GIF", "Corrupt GIF");
+
+   stbi__g_failure_reason = "";
+   g->w = stbi__get16le(s);
+   g->h = stbi__get16le(s);
+   g->flags = stbi__get8(s);
+   g->bgindex = stbi__get8(s);
+   g->ratio = stbi__get8(s);
+   g->transparent = -1;
+
+   if (comp != 0) *comp = 4;  // can't actually tell whether it's 3 or 4 until we parse the comments
+
+   if (is_info) return 1;
+
+   if (g->flags & 0x80)
+      stbi__gif_parse_colortable(s,g->pal, 2 << (g->flags & 7), -1);
+
+   return 1;
+}
+
+static int stbi__gif_info_raw(stbi__context *s, int *x, int *y, int *comp)
+{
+   stbi__gif* g = (stbi__gif*) stbi__malloc(sizeof(stbi__gif));
+   if (!stbi__gif_header(s, g, comp, 1)) {
+      STBI_FREE(g);
+      stbi__rewind( s );
+      return 0;
+   }
+   if (x) *x = g->w;
+   if (y) *y = g->h;
+   STBI_FREE(g);
+   return 1;
+}
+
+static void stbi__out_gif_code(stbi__gif *g, stbi__uint16 code)
+{
+   stbi_uc *p, *c;
+   int idx; 
+
+   // recurse to decode the prefixes, since the linked-list is backwards,
+   // and working backwards through an interleaved image would be nasty
+   if (g->codes[code].prefix >= 0)
+      stbi__out_gif_code(g, g->codes[code].prefix);
+
+   if (g->cur_y >= g->max_y) return;
+
+   idx = g->cur_x + g->cur_y; 
+   p = &g->out[idx];
+   g->history[idx / 4] = 1;  
+
+   c = &g->color_table[g->codes[code].suffix * 4];
+   if (c[3] > 128) { // don't render transparent pixels; 
+      p[0] = c[2];
+      p[1] = c[1];
+      p[2] = c[0];
+      p[3] = c[3];
+   }
+   g->cur_x += 4;
+
+   if (g->cur_x >= g->max_x) {
+      g->cur_x = g->start_x;
+      g->cur_y += g->step;
+
+      while (g->cur_y >= g->max_y && g->parse > 0) {
+         g->step = (1 << g->parse) * g->line_size;
+         g->cur_y = g->start_y + (g->step >> 1);
+         --g->parse;
+      }
+   }
+}
+
+static stbi_uc *stbi__process_gif_raster(stbi__context *s, stbi__gif *g)
+{
+   stbi_uc lzw_cs;
+   stbi__int32 len, init_code;
+   stbi__uint32 first;
+   stbi__int32 codesize, codemask, avail, oldcode, bits, valid_bits, clear;
+   stbi__gif_lzw *p;
+
+   lzw_cs = stbi__get8(s);
+   if (lzw_cs > 12) return NULL;
+   clear = 1 << lzw_cs;
+   first = 1;
+   codesize = lzw_cs + 1;
+   codemask = (1 << codesize) - 1;
+   bits = 0;
+   valid_bits = 0;
+   for (init_code = 0; init_code < clear; init_code++) {
+      g->codes[init_code].prefix = -1;
+      g->codes[init_code].first = (stbi_uc) init_code;
+      g->codes[init_code].suffix = (stbi_uc) init_code;
+   }
+
+   // support no starting clear code
+   avail = clear+2;
+   oldcode = -1;
+
+   len = 0;
+   for(;;) {
+      if (valid_bits < codesize) {
+         if (len == 0) {
+            len = stbi__get8(s); // start new block
+            if (len == 0)
+               return g->out;
+         }
+         --len;
+         bits |= (stbi__int32) stbi__get8(s) << valid_bits;
+         valid_bits += 8;
+      } else {
+         stbi__int32 code = bits & codemask;
+         bits >>= codesize;
+         valid_bits -= codesize;
+         // @OPTIMIZE: is there some way we can accelerate the non-clear path?
+         if (code == clear) {  // clear code
+            codesize = lzw_cs + 1;
+            codemask = (1 << codesize) - 1;
+            avail = clear + 2;
+            oldcode = -1;
+            first = 0;
+         } else if (code == clear + 1) { // end of stream code
+            stbi__skip(s, len);
+            while ((len = stbi__get8(s)) > 0)
+               stbi__skip(s,len);
+            return g->out;
+         } else if (code <= avail) {
+            if (first) {
+               return stbi__errpuc("no clear code", "Corrupt GIF");
+            }
+
+            if (oldcode >= 0) {
+               p = &g->codes[avail++];
+               if (avail > 8192) {
+                  return stbi__errpuc("too many codes", "Corrupt GIF");
+               }
+
+               p->prefix = (stbi__int16) oldcode;
+               p->first = g->codes[oldcode].first;
+               p->suffix = (code == avail) ? p->first : g->codes[code].first;
+            } else if (code == avail)
+               return stbi__errpuc("illegal code in raster", "Corrupt GIF");
+
+            stbi__out_gif_code(g, (stbi__uint16) code);
+
+            if ((avail & codemask) == 0 && avail <= 0x0FFF) {
+               codesize++;
+               codemask = (1 << codesize) - 1;
+            }
+
+            oldcode = code;
+         } else {
+            return stbi__errpuc("illegal code in raster", "Corrupt GIF");
+         }
+      }
+   }
+}
+
+// this function is designed to support animated gifs, although stb_image doesn't support it
+// two back is the image from two frames ago, used for a very specific disposal format
+static stbi_uc *stbi__gif_load_next(stbi__context *s, stbi__gif *g, int *comp, int req_comp, stbi_uc *two_back)
+{
+   int dispose; 
+   int first_frame; 
+   int pi; 
+   int pcount; 
+   STBI_NOTUSED(req_comp);
+
+   // on first frame, any non-written pixels get the background colour (non-transparent)
+   first_frame = 0; 
+   if (g->out == 0) {
+      if (!stbi__gif_header(s, g, comp,0)) return 0; // stbi__g_failure_reason set by stbi__gif_header
+      if (!stbi__mad3sizes_valid(4, g->w, g->h, 0))
+         return stbi__errpuc("too large", "GIF image is too large");
+      pcount = g->w * g->h;
+      g->out = (stbi_uc *) stbi__malloc(4 * pcount);
+      g->background = (stbi_uc *) stbi__malloc(4 * pcount);
+      g->history = (stbi_uc *) stbi__malloc(pcount);
+      if (!g->out || !g->background || !g->history)
+         return stbi__errpuc("outofmem", "Out of memory");
+
+      // image is treated as "transparent" at the start - ie, nothing overwrites the current background; 
+      // background colour is only used for pixels that are not rendered first frame, after that "background"
+      // color refers to the color that was there the previous frame. 
+      memset(g->out, 0x00, 4 * pcount);
+      memset(g->background, 0x00, 4 * pcount); // state of the background (starts transparent)
+      memset(g->history, 0x00, pcount);        // pixels that were affected previous frame
+      first_frame = 1; 
+   } else {
+      // second frame - how do we dispoase of the previous one?
+      dispose = (g->eflags & 0x1C) >> 2; 
+      pcount = g->w * g->h; 
+
+      if ((dispose == 3) && (two_back == 0)) {
+         dispose = 2; // if I don't have an image to revert back to, default to the old background
+      }
+
+      if (dispose == 3) { // use previous graphic
+         for (pi = 0; pi < pcount; ++pi) {
+            if (g->history[pi]) {
+               memcpy( &g->out[pi * 4], &two_back[pi * 4], 4 ); 
+            }
+         }
+      } else if (dispose == 2) { 
+         // restore what was changed last frame to background before that frame; 
+         for (pi = 0; pi < pcount; ++pi) {
+            if (g->history[pi]) {
+               memcpy( &g->out[pi * 4], &g->background[pi * 4], 4 ); 
+            }
+         }
+      } else {
+         // This is a non-disposal case eithe way, so just 
+         // leave the pixels as is, and they will become the new background
+         // 1: do not dispose
+         // 0:  not specified.
+      }
+
+      // background is what out is after the undoing of the previou frame; 
+      memcpy( g->background, g->out, 4 * g->w * g->h ); 
+   }
+
+   // clear my history; 
+   memset( g->history, 0x00, g->w * g->h );        // pixels that were affected previous frame
+
+   for (;;) {
+      int tag = stbi__get8(s); 
+      switch (tag) {
+         case 0x2C: /* Image Descriptor */
+         {
+            stbi__int32 x, y, w, h;
+            stbi_uc *o;
+
+            x = stbi__get16le(s);
+            y = stbi__get16le(s);
+            w = stbi__get16le(s);
+            h = stbi__get16le(s);
+            if (((x + w) > (g->w)) || ((y + h) > (g->h)))
+               return stbi__errpuc("bad Image Descriptor", "Corrupt GIF");
+
+            g->line_size = g->w * 4;
+            g->start_x = x * 4;
+            g->start_y = y * g->line_size;
+            g->max_x   = g->start_x + w * 4;
+            g->max_y   = g->start_y + h * g->line_size;
+            g->cur_x   = g->start_x;
+            g->cur_y   = g->start_y;
+
+            // if the width of the specified rectangle is 0, that means
+            // we may not see *any* pixels or the image is malformed;
+            // to make sure this is caught, move the current y down to
+            // max_y (which is what out_gif_code checks).
+            if (w == 0)
+               g->cur_y = g->max_y;
+
+            g->lflags = stbi__get8(s);
+
+            if (g->lflags & 0x40) {
+               g->step = 8 * g->line_size; // first interlaced spacing
+               g->parse = 3;
+            } else {
+               g->step = g->line_size;
+               g->parse = 0;
+            }
+
+            if (g->lflags & 0x80) {
+               stbi__gif_parse_colortable(s,g->lpal, 2 << (g->lflags & 7), g->eflags & 0x01 ? g->transparent : -1);
+               g->color_table = (stbi_uc *) g->lpal;
+            } else if (g->flags & 0x80) {
+               g->color_table = (stbi_uc *) g->pal;
+            } else
+               return stbi__errpuc("missing color table", "Corrupt GIF");            
+            
+            o = stbi__process_gif_raster(s, g);
+            if (!o) return NULL;
+
+            // if this was the first frame, 
+            pcount = g->w * g->h; 
+            if (first_frame && (g->bgindex > 0)) {
+               // if first frame, any pixel not drawn to gets the background color
+               for (pi = 0; pi < pcount; ++pi) {
+                  if (g->history[pi] == 0) {
+                     g->pal[g->bgindex][3] = 255; // just in case it was made transparent, undo that; It will be reset next frame if need be; 
+                     memcpy( &g->out[pi * 4], &g->pal[g->bgindex], 4 ); 
+                  }
+               }
+            }
+
+            return o;
+         }
+
+         case 0x21: // Comment Extension.
+         {
+            int len;
+            int ext = stbi__get8(s); 
+            if (ext == 0xF9) { // Graphic Control Extension.
+               len = stbi__get8(s);
+               if (len == 4) {
+                  g->eflags = stbi__get8(s);
+                  g->delay = 10 * stbi__get16le(s); // delay - 1/100th of a second, saving as 1/1000ths.
+
+                  // unset old transparent
+                  if (g->transparent >= 0) {
+                     g->pal[g->transparent][3] = 255; 
+                  } 
+                  if (g->eflags & 0x01) {
+                     g->transparent = stbi__get8(s);
+                     if (g->transparent >= 0) {
+                        g->pal[g->transparent][3] = 0; 
+                     }
+                  } else {
+                     // don't need transparent
+                     stbi__skip(s, 1); 
+                     g->transparent = -1; 
+                  }
+               } else {
+                  stbi__skip(s, len);
+                  break;
+               }
+            } 
+            while ((len = stbi__get8(s)) != 0) {
+               stbi__skip(s, len);
+            }
+            break;
+         }
+
+         case 0x3B: // gif stream termination code
+            return (stbi_uc *) s; // using '1' causes warning on some compilers
+
+         default:
+            return stbi__errpuc("unknown code", "Corrupt GIF");
+      }
+   }
+}
+
+static void *stbi__load_gif_main(stbi__context *s, int **delays, int *x, int *y, int *z, int *comp, int req_comp)
+{
+   if (stbi__gif_test(s)) {
+      int layers = 0; 
+      stbi_uc *u = 0;
+      stbi_uc *out = 0;
+      stbi_uc *two_back = 0; 
+      stbi__gif g;
+      int stride; 
+      memset(&g, 0, sizeof(g));
+      if (delays) {
+         *delays = 0; 
+      }
+
+      do {
+         u = stbi__gif_load_next(s, &g, comp, req_comp, two_back);
+         if (u == (stbi_uc *) s) u = 0;  // end of animated gif marker
+
+         if (u) {
+            *x = g.w;
+            *y = g.h;
+            ++layers; 
+            stride = g.w * g.h * 4; 
+         
+            if (out) {
+               out = (stbi_uc*) STBI_REALLOC( out, layers * stride ); 
+               if (delays) {
+                  *delays = (int*) STBI_REALLOC( *delays, sizeof(int) * layers ); 
+               }
+            } else {
+               out = (stbi_uc*)stbi__malloc( layers * stride ); 
+               if (delays) {
+                  *delays = (int*) stbi__malloc( layers * sizeof(int) ); 
+               }
+            }
+            memcpy( out + ((layers - 1) * stride), u, stride ); 
+            if (layers >= 2) {
+               two_back = out - 2 * stride; 
+            }
+
+            if (delays) {
+               (*delays)[layers - 1U] = g.delay; 
+            }
+         }
+      } while (u != 0); 
+
+      // free temp buffer; 
+      STBI_FREE(g.out); 
+      STBI_FREE(g.history); 
+      STBI_FREE(g.background); 
+
+      // do the final conversion after loading everything; 
+      if (req_comp && req_comp != 4)
+         out = stbi__convert_format(out, 4, req_comp, layers * g.w, g.h);
+
+      *z = layers; 
+      return out;
+   } else {
+      return stbi__errpuc("not GIF", "Image was not as a gif type."); 
+   }
+}
+
+static void *stbi__gif_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri)
+{
+   stbi_uc *u = 0;
+   stbi__gif g;
+   memset(&g, 0, sizeof(g));
+   STBI_NOTUSED(ri);
+
+   u = stbi__gif_load_next(s, &g, comp, req_comp, 0);
+   if (u == (stbi_uc *) s) u = 0;  // end of animated gif marker
+   if (u) {
+      *x = g.w;
+      *y = g.h;
+
+      // moved conversion to after successful load so that the same
+      // can be done for multiple frames. 
+      if (req_comp && req_comp != 4)
+         u = stbi__convert_format(u, 4, req_comp, g.w, g.h);
+   } else if (g.out) {
+      // if there was an error and we allocated an image buffer, free it!
+      STBI_FREE(g.out);
+   }
+
+   // free buffers needed for multiple frame loading; 
+   STBI_FREE(g.history);
+   STBI_FREE(g.background); 
+
+   return u;
+}
+
+static int stbi__gif_info(stbi__context *s, int *x, int *y, int *comp)
+{
+   return stbi__gif_info_raw(s,x,y,comp);
+}
+#endif
+
+// *************************************************************************************************
+// Radiance RGBE HDR loader
+// originally by Nicolas Schulz
+#ifndef STBI_NO_HDR
+static int stbi__hdr_test_core(stbi__context *s, const char *signature)
+{
+   int i;
+   for (i=0; signature[i]; ++i)
+      if (stbi__get8(s) != signature[i])
+          return 0;
+   stbi__rewind(s);
+   return 1;
+}
+
+static int stbi__hdr_test(stbi__context* s)
+{
+   int r = stbi__hdr_test_core(s, "#?RADIANCE\n");
+   stbi__rewind(s);
+   if(!r) {
+       r = stbi__hdr_test_core(s, "#?RGBE\n");
+       stbi__rewind(s);
+   }
+   return r;
+}
+
+#define STBI__HDR_BUFLEN  1024
+static char *stbi__hdr_gettoken(stbi__context *z, char *buffer)
+{
+   int len=0;
+   char c = '\0';
+
+   c = (char) stbi__get8(z);
+
+   while (!stbi__at_eof(z) && c != '\n') {
+      buffer[len++] = c;
+      if (len == STBI__HDR_BUFLEN-1) {
+         // flush to end of line
+         while (!stbi__at_eof(z) && stbi__get8(z) != '\n')
+            ;
+         break;
+      }
+      c = (char) stbi__get8(z);
+   }
+
+   buffer[len] = 0;
+   return buffer;
+}
+
+static void stbi__hdr_convert(float *output, stbi_uc *input, int req_comp)
+{
+   if ( input[3] != 0 ) {
+      float f1;
+      // Exponent
+      f1 = (float) ldexp(1.0f, input[3] - (int)(128 + 8));
+      if (req_comp <= 2)
+         output[0] = (input[0] + input[1] + input[2]) * f1 / 3;
+      else {
+         output[0] = input[0] * f1;
+         output[1] = input[1] * f1;
+         output[2] = input[2] * f1;
+      }
+      if (req_comp == 2) output[1] = 1;
+      if (req_comp == 4) output[3] = 1;
+   } else {
+      switch (req_comp) {
+         case 4: output[3] = 1; /* fallthrough */
+         case 3: output[0] = output[1] = output[2] = 0;
+                 break;
+         case 2: output[1] = 1; /* fallthrough */
+         case 1: output[0] = 0;
+                 break;
+      }
+   }
+}
+
+static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri)
+{
+   char buffer[STBI__HDR_BUFLEN];
+   char *token;
+   int valid = 0;
+   int width, height;
+   stbi_uc *scanline;
+   float *hdr_data;
+   int len;
+   unsigned char count, value;
+   int i, j, k, c1,c2, z;
+   const char *headerToken;
+   STBI_NOTUSED(ri);
+
+   // Check identifier
+   headerToken = stbi__hdr_gettoken(s,buffer);
+   if (strcmp(headerToken, "#?RADIANCE") != 0 && strcmp(headerToken, "#?RGBE") != 0)
+      return stbi__errpf("not HDR", "Corrupt HDR image");
+
+   // Parse header
+   for(;;) {
+      token = stbi__hdr_gettoken(s,buffer);
+      if (token[0] == 0) break;
+      if (strcmp(token, "FORMAT=32-bit_rle_rgbe") == 0) valid = 1;
+   }
+
+   if (!valid)    return stbi__errpf("unsupported format", "Unsupported HDR format");
+
+   // Parse width and height
+   // can't use sscanf() if we're not using stdio!
+   token = stbi__hdr_gettoken(s,buffer);
+   if (strncmp(token, "-Y ", 3))  return stbi__errpf("unsupported data layout", "Unsupported HDR format");
+   token += 3;
+   height = (int) strtol(token, &token, 10);
+   while (*token == ' ') ++token;
+   if (strncmp(token, "+X ", 3))  return stbi__errpf("unsupported data layout", "Unsupported HDR format");
+   token += 3;
+   width = (int) strtol(token, NULL, 10);
+
+   *x = width;
+   *y = height;
+
+   if (comp) *comp = 3;
+   if (req_comp == 0) req_comp = 3;
+
+   if (!stbi__mad4sizes_valid(width, height, req_comp, sizeof(float), 0))
+      return stbi__errpf("too large", "HDR image is too large");
+
+   // Read data
+   hdr_data = (float *) stbi__malloc_mad4(width, height, req_comp, sizeof(float), 0);
+   if (!hdr_data)
+      return stbi__errpf("outofmem", "Out of memory");
+
+   // Load image data
+   // image data is stored as some number of sca
+   if ( width < 8 || width >= 32768) {
+      // Read flat data
+      for (j=0; j < height; ++j) {
+         for (i=0; i < width; ++i) {
+            stbi_uc rgbe[4];
+           main_decode_loop:
+            stbi__getn(s, rgbe, 4);
+            stbi__hdr_convert(hdr_data + j * width * req_comp + i * req_comp, rgbe, req_comp);
+         }
+      }
+   } else {
+      // Read RLE-encoded data
+      scanline = NULL;
+
+      for (j = 0; j < height; ++j) {
+         c1 = stbi__get8(s);
+         c2 = stbi__get8(s);
+         len = stbi__get8(s);
+         if (c1 != 2 || c2 != 2 || (len & 0x80)) {
+            // not run-length encoded, so we have to actually use THIS data as a decoded
+            // pixel (note this can't be a valid pixel--one of RGB must be >= 128)
+            stbi_uc rgbe[4];
+            rgbe[0] = (stbi_uc) c1;
+            rgbe[1] = (stbi_uc) c2;
+            rgbe[2] = (stbi_uc) len;
+            rgbe[3] = (stbi_uc) stbi__get8(s);
+            stbi__hdr_convert(hdr_data, rgbe, req_comp);
+            i = 1;
+            j = 0;
+            STBI_FREE(scanline);
+            goto main_decode_loop; // yes, this makes no sense
+         }
+         len <<= 8;
+         len |= stbi__get8(s);
+         if (len != width) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("invalid decoded scanline length", "corrupt HDR"); }
+         if (scanline == NULL) {
+            scanline = (stbi_uc *) stbi__malloc_mad2(width, 4, 0);
+            if (!scanline) {
+               STBI_FREE(hdr_data);
+               return stbi__errpf("outofmem", "Out of memory");
+            }
+         }
+
+         for (k = 0; k < 4; ++k) {
+            int nleft;
+            i = 0;
+            while ((nleft = width - i) > 0) {
+               count = stbi__get8(s);
+               if (count > 128) {
+                  // Run
+                  value = stbi__get8(s);
+                  count -= 128;
+                  if (count > nleft) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("corrupt", "bad RLE data in HDR"); }
+                  for (z = 0; z < count; ++z)
+                     scanline[i++ * 4 + k] = value;
+               } else {
+                  // Dump
+                  if (count > nleft) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("corrupt", "bad RLE data in HDR"); }
+                  for (z = 0; z < count; ++z)
+                     scanline[i++ * 4 + k] = stbi__get8(s);
+               }
+            }
+         }
+         for (i=0; i < width; ++i)
+            stbi__hdr_convert(hdr_data+(j*width + i)*req_comp, scanline + i*4, req_comp);
+      }
+      if (scanline)
+         STBI_FREE(scanline);
+   }
+
+   return hdr_data;
+}
+
+static int stbi__hdr_info(stbi__context *s, int *x, int *y, int *comp)
+{
+   char buffer[STBI__HDR_BUFLEN];
+   char *token;
+   int valid = 0;
+   int dummy;
+
+   if (!x) x = &dummy;
+   if (!y) y = &dummy;
+   if (!comp) comp = &dummy;
+
+   if (stbi__hdr_test(s) == 0) {
+       stbi__rewind( s );
+       return 0;
+   }
+
+   for(;;) {
+      token = stbi__hdr_gettoken(s,buffer);
+      if (token[0] == 0) break;
+      if (strcmp(token, "FORMAT=32-bit_rle_rgbe") == 0) valid = 1;
+   }
+
+   if (!valid) {
+       stbi__rewind( s );
+       return 0;
+   }
+   token = stbi__hdr_gettoken(s,buffer);
+   if (strncmp(token, "-Y ", 3)) {
+       stbi__rewind( s );
+       return 0;
+   }
+   token += 3;
+   *y = (int) strtol(token, &token, 10);
+   while (*token == ' ') ++token;
+   if (strncmp(token, "+X ", 3)) {
+       stbi__rewind( s );
+       return 0;
+   }
+   token += 3;
+   *x = (int) strtol(token, NULL, 10);
+   *comp = 3;
+   return 1;
+}
+#endif // STBI_NO_HDR
+
+#ifndef STBI_NO_BMP
+static int stbi__bmp_info(stbi__context *s, int *x, int *y, int *comp)
+{
+   void *p;
+   stbi__bmp_data info;
+
+   info.all_a = 255;
+   p = stbi__bmp_parse_header(s, &info);
+   stbi__rewind( s );
+   if (p == NULL)
+      return 0;
+   if (x) *x = s->img_x;
+   if (y) *y = s->img_y;
+   if (comp) {
+      if (info.bpp == 24 && info.ma == 0xff000000)
+         *comp = 3;
+      else
+         *comp = info.ma ? 4 : 3;
+   }
+   return 1;
+}
+#endif
+
+#ifndef STBI_NO_PSD
+static int stbi__psd_info(stbi__context *s, int *x, int *y, int *comp)
+{
+   int channelCount, dummy, depth;
+   if (!x) x = &dummy;
+   if (!y) y = &dummy;
+   if (!comp) comp = &dummy;
+   if (stbi__get32be(s) != 0x38425053) {
+       stbi__rewind( s );
+       return 0;
+   }
+   if (stbi__get16be(s) != 1) {
+       stbi__rewind( s );
+       return 0;
+   }
+   stbi__skip(s, 6);
+   channelCount = stbi__get16be(s);
+   if (channelCount < 0 || channelCount > 16) {
+       stbi__rewind( s );
+       return 0;
+   }
+   *y = stbi__get32be(s);
+   *x = stbi__get32be(s);
+   depth = stbi__get16be(s);
+   if (depth != 8 && depth != 16) {
+       stbi__rewind( s );
+       return 0;
+   }
+   if (stbi__get16be(s) != 3) {
+       stbi__rewind( s );
+       return 0;
+   }
+   *comp = 4;
+   return 1;
+}
+
+static int stbi__psd_is16(stbi__context *s)
+{
+   int channelCount, depth;
+   if (stbi__get32be(s) != 0x38425053) {
+       stbi__rewind( s );
+       return 0;
+   }
+   if (stbi__get16be(s) != 1) {
+       stbi__rewind( s );
+       return 0;
+   }
+   stbi__skip(s, 6);
+   channelCount = stbi__get16be(s);
+   if (channelCount < 0 || channelCount > 16) {
+       stbi__rewind( s );
+       return 0;
+   }
+   (void) stbi__get32be(s);
+   (void) stbi__get32be(s);
+   depth = stbi__get16be(s);
+   if (depth != 16) {
+       stbi__rewind( s );
+       return 0;
+   }
+   return 1;
+}
+#endif
+
+#ifndef STBI_NO_PIC
+static int stbi__pic_info(stbi__context *s, int *x, int *y, int *comp)
+{
+   int act_comp=0,num_packets=0,chained,dummy;
+   stbi__pic_packet packets[10];
+
+   if (!x) x = &dummy;
+   if (!y) y = &dummy;
+   if (!comp) comp = &dummy;
+
+   if (!stbi__pic_is4(s,"\x53\x80\xF6\x34")) {
+      stbi__rewind(s);
+      return 0;
+   }
+
+   stbi__skip(s, 88);
+
+   *x = stbi__get16be(s);
+   *y = stbi__get16be(s);
+   if (stbi__at_eof(s)) {
+      stbi__rewind( s);
+      return 0;
+   }
+   if ( (*x) != 0 && (1 << 28) / (*x) < (*y)) {
+      stbi__rewind( s );
+      return 0;
+   }
+
+   stbi__skip(s, 8);
+
+   do {
+      stbi__pic_packet *packet;
+
+      if (num_packets==sizeof(packets)/sizeof(packets[0]))
+         return 0;
+
+      packet = &packets[num_packets++];
+      chained = stbi__get8(s);
+      packet->size    = stbi__get8(s);
+      packet->type    = stbi__get8(s);
+      packet->channel = stbi__get8(s);
+      act_comp |= packet->channel;
+
+      if (stbi__at_eof(s)) {
+          stbi__rewind( s );
+          return 0;
+      }
+      if (packet->size != 8) {
+          stbi__rewind( s );
+          return 0;
+      }
+   } while (chained);
+
+   *comp = (act_comp & 0x10 ? 4 : 3);
+
+   return 1;
+}
+#endif
+
+// *************************************************************************************************
+// Portable Gray Map and Portable Pixel Map loader
+// by Ken Miller
+//
+// PGM: http://netpbm.sourceforge.net/doc/pgm.html
+// PPM: http://netpbm.sourceforge.net/doc/ppm.html
+//
+// Known limitations:
+//    Does not support comments in the header section
+//    Does not support ASCII image data (formats P2 and P3)
+//    Does not support 16-bit-per-channel
+
+#ifndef STBI_NO_PNM
+
+static int      stbi__pnm_test(stbi__context *s)
+{
+   char p, t;
+   p = (char) stbi__get8(s);
+   t = (char) stbi__get8(s);
+   if (p != 'P' || (t != '5' && t != '6')) {
+       stbi__rewind( s );
+       return 0;
+   }
+   return 1;
+}
+
+static void *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri)
+{
+   stbi_uc *out;
+   STBI_NOTUSED(ri);
+
+   if (!stbi__pnm_info(s, (int *)&s->img_x, (int *)&s->img_y, (int *)&s->img_n))
+      return 0;
+
+   *x = s->img_x;
+   *y = s->img_y;
+   if (comp) *comp = s->img_n;
+
+   if (!stbi__mad3sizes_valid(s->img_n, s->img_x, s->img_y, 0))
+      return stbi__errpuc("too large", "PNM too large");
+
+   out = (stbi_uc *) stbi__malloc_mad3(s->img_n, s->img_x, s->img_y, 0);
+   if (!out) return stbi__errpuc("outofmem", "Out of memory");
+   stbi__getn(s, out, s->img_n * s->img_x * s->img_y);
+
+   if (req_comp && req_comp != s->img_n) {
+      out = stbi__convert_format(out, s->img_n, req_comp, s->img_x, s->img_y);
+      if (out == NULL) return out; // stbi__convert_format frees input on failure
+   }
+   return out;
+}
+
+static int      stbi__pnm_isspace(char c)
+{
+   return c == ' ' || c == '\t' || c == '\n' || c == '\v' || c == '\f' || c == '\r';
+}
+
+static void     stbi__pnm_skip_whitespace(stbi__context *s, char *c)
+{
+   for (;;) {
+      while (!stbi__at_eof(s) && stbi__pnm_isspace(*c))
+         *c = (char) stbi__get8(s);
+
+      if (stbi__at_eof(s) || *c != '#')
+         break;
+
+      while (!stbi__at_eof(s) && *c != '\n' && *c != '\r' )
+         *c = (char) stbi__get8(s);
+   }
+}
+
+static int      stbi__pnm_isdigit(char c)
+{
+   return c >= '0' && c <= '9';
+}
+
+static int      stbi__pnm_getinteger(stbi__context *s, char *c)
+{
+   int value = 0;
+
+   while (!stbi__at_eof(s) && stbi__pnm_isdigit(*c)) {
+      value = value*10 + (*c - '0');
+      *c = (char) stbi__get8(s);
+   }
+
+   return value;
+}
+
+static int      stbi__pnm_info(stbi__context *s, int *x, int *y, int *comp)
+{
+   int maxv, dummy;
+   char c, p, t;
+
+   if (!x) x = &dummy;
+   if (!y) y = &dummy;
+   if (!comp) comp = &dummy;
+
+   stbi__rewind(s);
+
+   // Get identifier
+   p = (char) stbi__get8(s);
+   t = (char) stbi__get8(s);
+   if (p != 'P' || (t != '5' && t != '6')) {
+       stbi__rewind(s);
+       return 0;
+   }
+
+   *comp = (t == '6') ? 3 : 1;  // '5' is 1-component .pgm; '6' is 3-component .ppm
+
+   c = (char) stbi__get8(s);
+   stbi__pnm_skip_whitespace(s, &c);
+
+   *x = stbi__pnm_getinteger(s, &c); // read width
+   stbi__pnm_skip_whitespace(s, &c);
+
+   *y = stbi__pnm_getinteger(s, &c); // read height
+   stbi__pnm_skip_whitespace(s, &c);
+
+   maxv = stbi__pnm_getinteger(s, &c);  // read max value
+
+   if (maxv > 255)
+      return stbi__err("max value > 255", "PPM image not 8-bit");
+   else
+      return 1;
+}
+#endif
+
+static int stbi__info_main(stbi__context *s, int *x, int *y, int *comp)
+{
+   #ifndef STBI_NO_JPEG
+   if (stbi__jpeg_info(s, x, y, comp)) return 1;
+   #endif
+
+   #ifndef STBI_NO_PNG
+   if (stbi__png_info(s, x, y, comp))  return 1;
+   #endif
+
+   #ifndef STBI_NO_GIF
+   if (stbi__gif_info(s, x, y, comp))  return 1;
+   #endif
+
+   #ifndef STBI_NO_BMP
+   if (stbi__bmp_info(s, x, y, comp))  return 1;
+   #endif
+
+   #ifndef STBI_NO_PSD
+   if (stbi__psd_info(s, x, y, comp))  return 1;
+   #endif
+
+   #ifndef STBI_NO_PIC
+   if (stbi__pic_info(s, x, y, comp))  return 1;
+   #endif
+
+   #ifndef STBI_NO_PNM
+   if (stbi__pnm_info(s, x, y, comp))  return 1;
+   #endif
+
+   #ifndef STBI_NO_HDR
+   if (stbi__hdr_info(s, x, y, comp))  return 1;
+   #endif
+
+   // test tga last because it's a crappy test!
+   #ifndef STBI_NO_TGA
+   if (stbi__tga_info(s, x, y, comp))
+       return 1;
+   #endif
+   return stbi__err("unknown image type", "Image not of any known type, or corrupt");
+}
+
+static int stbi__is_16_main(stbi__context *s)
+{
+   #ifndef STBI_NO_PNG
+   if (stbi__png_is16(s))  return 1;
+   #endif
+
+   #ifndef STBI_NO_PSD
+   if (stbi__psd_is16(s))  return 1;
+   #endif
+
+   return 0;
+}
+
+#ifndef STBI_NO_STDIO
+STBIDEF int stbi_info(char const *filename, int *x, int *y, int *comp)
+{
+    FILE *f = stbi__fopen(filename, "rb");
+    int result;
+    if (!f) return stbi__err("can't fopen", "Unable to open file");
+    result = stbi_info_from_file(f, x, y, comp);
+    fclose(f);
+    return result;
+}
+
+STBIDEF int stbi_info_from_file(FILE *f, int *x, int *y, int *comp)
+{
+   int r;
+   stbi__context s;
+   long pos = ftell(f);
+   stbi__start_file(&s, f);
+   r = stbi__info_main(&s,x,y,comp);
+   fseek(f,pos,SEEK_SET);
+   return r;
+}
+
+STBIDEF int stbi_is_16_bit(char const *filename)
+{
+    FILE *f = stbi__fopen(filename, "rb");
+    int result;
+    if (!f) return stbi__err("can't fopen", "Unable to open file");
+    result = stbi_is_16_bit_from_file(f);
+    fclose(f);
+    return result;
+}
+
+STBIDEF int stbi_is_16_bit_from_file(FILE *f)
+{
+   int r;
+   stbi__context s;
+   long pos = ftell(f);
+   stbi__start_file(&s, f);
+   r = stbi__is_16_main(&s);
+   fseek(f,pos,SEEK_SET);
+   return r;
+}
+#endif // !STBI_NO_STDIO
+
+STBIDEF int stbi_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp)
+{
+   stbi__context s;
+   stbi__start_mem(&s,buffer,len);
+   return stbi__info_main(&s,x,y,comp);
+}
+
+STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *c, void *user, int *x, int *y, int *comp)
+{
+   stbi__context s;
+   stbi__start_callbacks(&s, (stbi_io_callbacks *) c, user);
+   return stbi__info_main(&s,x,y,comp);
+}
+
+STBIDEF int stbi_is_16_bit_from_memory(stbi_uc const *buffer, int len)
+{
+   stbi__context s;
+   stbi__start_mem(&s,buffer,len);
+   return stbi__is_16_main(&s);
+}
+
+STBIDEF int stbi_is_16_bit_from_callbacks(stbi_io_callbacks const *c, void *user)
+{
+   stbi__context s;
+   stbi__start_callbacks(&s, (stbi_io_callbacks *) c, user);
+   return stbi__is_16_main(&s);
+}
+
+#endif // STB_IMAGE_IMPLEMENTATION
+
+/*
+   revision history:
+      2.20  (2019-02-07) support utf8 filenames in Windows; fix warnings and platform ifdefs 
+      2.19  (2018-02-11) fix warning
+      2.18  (2018-01-30) fix warnings
+      2.17  (2018-01-29) change sbti__shiftsigned to avoid clang -O2 bug
+                         1-bit BMP
+                         *_is_16_bit api
+                         avoid warnings
+      2.16  (2017-07-23) all functions have 16-bit variants;
+                         STBI_NO_STDIO works again;
+                         compilation fixes;
+                         fix rounding in unpremultiply;
+                         optimize vertical flip;
+                         disable raw_len validation;
+                         documentation fixes
+      2.15  (2017-03-18) fix png-1,2,4 bug; now all Imagenet JPGs decode;
+                         warning fixes; disable run-time SSE detection on gcc;
+                         uniform handling of optional "return" values;
+                         thread-safe initialization of zlib tables
+      2.14  (2017-03-03) remove deprecated STBI_JPEG_OLD; fixes for Imagenet JPGs
+      2.13  (2016-11-29) add 16-bit API, only supported for PNG right now
+      2.12  (2016-04-02) fix typo in 2.11 PSD fix that caused crashes
+      2.11  (2016-04-02) allocate large structures on the stack
+                         remove white matting for transparent PSD
+                         fix reported channel count for PNG & BMP
+                         re-enable SSE2 in non-gcc 64-bit
+                         support RGB-formatted JPEG
+                         read 16-bit PNGs (only as 8-bit)
+      2.10  (2016-01-22) avoid warning introduced in 2.09 by STBI_REALLOC_SIZED
+      2.09  (2016-01-16) allow comments in PNM files
+                         16-bit-per-pixel TGA (not bit-per-component)
+                         info() for TGA could break due to .hdr handling
+                         info() for BMP to shares code instead of sloppy parse
+                         can use STBI_REALLOC_SIZED if allocator doesn't support realloc
+                         code cleanup
+      2.08  (2015-09-13) fix to 2.07 cleanup, reading RGB PSD as RGBA
+      2.07  (2015-09-13) fix compiler warnings
+                         partial animated GIF support
+                         limited 16-bpc PSD support
+                         #ifdef unused functions
+                         bug with < 92 byte PIC,PNM,HDR,TGA
+      2.06  (2015-04-19) fix bug where PSD returns wrong '*comp' value
+      2.05  (2015-04-19) fix bug in progressive JPEG handling, fix warning
+      2.04  (2015-04-15) try to re-enable SIMD on MinGW 64-bit
+      2.03  (2015-04-12) extra corruption checking (mmozeiko)
+                         stbi_set_flip_vertically_on_load (nguillemot)
+                         fix NEON support; fix mingw support
+      2.02  (2015-01-19) fix incorrect assert, fix warning
+      2.01  (2015-01-17) fix various warnings; suppress SIMD on gcc 32-bit without -msse2
+      2.00b (2014-12-25) fix STBI_MALLOC in progressive JPEG
+      2.00  (2014-12-25) optimize JPG, including x86 SSE2 & NEON SIMD (ryg)
+                         progressive JPEG (stb)
+                         PGM/PPM support (Ken Miller)
+                         STBI_MALLOC,STBI_REALLOC,STBI_FREE
+                         GIF bugfix -- seemingly never worked
+                         STBI_NO_*, STBI_ONLY_*
+      1.48  (2014-12-14) fix incorrectly-named assert()
+      1.47  (2014-12-14) 1/2/4-bit PNG support, both direct and paletted (Omar Cornut & stb)
+                         optimize PNG (ryg)
+                         fix bug in interlaced PNG with user-specified channel count (stb)
+      1.46  (2014-08-26)
+              fix broken tRNS chunk (colorkey-style transparency) in non-paletted PNG
+      1.45  (2014-08-16)
+              fix MSVC-ARM internal compiler error by wrapping malloc
+      1.44  (2014-08-07)
+              various warning fixes from Ronny Chevalier
+      1.43  (2014-07-15)
+              fix MSVC-only compiler problem in code changed in 1.42
+      1.42  (2014-07-09)
+              don't define _CRT_SECURE_NO_WARNINGS (affects user code)
+              fixes to stbi__cleanup_jpeg path
+              added STBI_ASSERT to avoid requiring assert.h
+      1.41  (2014-06-25)
+              fix search&replace from 1.36 that messed up comments/error messages
+      1.40  (2014-06-22)
+              fix gcc struct-initialization warning
+      1.39  (2014-06-15)
+              fix to TGA optimization when req_comp != number of components in TGA;
+              fix to GIF loading because BMP wasn't rewinding (whoops, no GIFs in my test suite)
+              add support for BMP version 5 (more ignored fields)
+      1.38  (2014-06-06)
+              suppress MSVC warnings on integer casts truncating values
+              fix accidental rename of 'skip' field of I/O
+      1.37  (2014-06-04)
+              remove duplicate typedef
+      1.36  (2014-06-03)
+              convert to header file single-file library
+              if de-iphone isn't set, load iphone images color-swapped instead of returning NULL
+      1.35  (2014-05-27)
+              various warnings
+              fix broken STBI_SIMD path
+              fix bug where stbi_load_from_file no longer left file pointer in correct place
+              fix broken non-easy path for 32-bit BMP (possibly never used)
+              TGA optimization by Arseny Kapoulkine
+      1.34  (unknown)
+              use STBI_NOTUSED in stbi__resample_row_generic(), fix one more leak in tga failure case
+      1.33  (2011-07-14)
+              make stbi_is_hdr work in STBI_NO_HDR (as specified), minor compiler-friendly improvements
+      1.32  (2011-07-13)
+              support for "info" function for all supported filetypes (SpartanJ)
+      1.31  (2011-06-20)
+              a few more leak fixes, bug in PNG handling (SpartanJ)
+      1.30  (2011-06-11)
+              added ability to load files via callbacks to accomidate custom input streams (Ben Wenger)
+              removed deprecated format-specific test/load functions
+              removed support for installable file formats (stbi_loader) -- would have been broken for IO callbacks anyway
+              error cases in bmp and tga give messages and don't leak (Raymond Barbiero, grisha)
+              fix inefficiency in decoding 32-bit BMP (David Woo)
+      1.29  (2010-08-16)
+              various warning fixes from Aurelien Pocheville
+      1.28  (2010-08-01)
+              fix bug in GIF palette transparency (SpartanJ)
+      1.27  (2010-08-01)
+              cast-to-stbi_uc to fix warnings
+      1.26  (2010-07-24)
+              fix bug in file buffering for PNG reported by SpartanJ
+      1.25  (2010-07-17)
+              refix trans_data warning (Won Chun)
+      1.24  (2010-07-12)
+              perf improvements reading from files on platforms with lock-heavy fgetc()
+              minor perf improvements for jpeg
+              deprecated type-specific functions so we'll get feedback if they're needed
+              attempt to fix trans_data warning (Won Chun)
+      1.23    fixed bug in iPhone support
+      1.22  (2010-07-10)
+              removed image *writing* support
+              stbi_info support from Jetro Lauha
+              GIF support from Jean-Marc Lienher
+              iPhone PNG-extensions from James Brown
+              warning-fixes from Nicolas Schulz and Janez Zemva (i.stbi__err. Janez (U+017D)emva)
+      1.21    fix use of 'stbi_uc' in header (reported by jon blow)
+      1.20    added support for Softimage PIC, by Tom Seddon
+      1.19    bug in interlaced PNG corruption check (found by ryg)
+      1.18  (2008-08-02)
+              fix a threading bug (local mutable static)
+      1.17    support interlaced PNG
+      1.16    major bugfix - stbi__convert_format converted one too many pixels
+      1.15    initialize some fields for thread safety
+      1.14    fix threadsafe conversion bug
+              header-file-only version (#define STBI_HEADER_FILE_ONLY before including)
+      1.13    threadsafe
+      1.12    const qualifiers in the API
+      1.11    Support installable IDCT, colorspace conversion routines
+      1.10    Fixes for 64-bit (don't use "unsigned long")
+              optimized upsampling by Fabian "ryg" Giesen
+      1.09    Fix format-conversion for PSD code (bad global variables!)
+      1.08    Thatcher Ulrich's PSD code integrated by Nicolas Schulz
+      1.07    attempt to fix C++ warning/errors again
+      1.06    attempt to fix C++ warning/errors again
+      1.05    fix TGA loading to return correct *comp and use good luminance calc
+      1.04    default float alpha is 1, not 255; use 'void *' for stbi_image_free
+      1.03    bugfixes to STBI_NO_STDIO, STBI_NO_HDR
+      1.02    support for (subset of) HDR files, float interface for preferred access to them
+      1.01    fix bug: possible bug in handling right-side up bmps... not sure
+              fix bug: the stbi__bmp_load() and stbi__tga_load() functions didn't work at all
+      1.00    interface to zlib that skips zlib header
+      0.99    correct handling of alpha in palette
+      0.98    TGA loader by lonesock; dynamically add loaders (untested)
+      0.97    jpeg errors on too large a file; also catch another malloc failure
+      0.96    fix detection of invalid v value - particleman at mollyrocket forum
+      0.95    during header scan, seek to markers in case of padding
+      0.94    STBI_NO_STDIO to disable stdio usage; rename all #defines the same
+      0.93    handle jpegtran output; verbose errors
+      0.92    read 4,8,16,24,32-bit BMP files of several formats
+      0.91    output 24-bit Windows 3.0 BMP files
+      0.90    fix a few more warnings; bump version number to approach 1.0
+      0.61    bugfixes due to Marc LeBlanc, Christopher Lloyd
+      0.60    fix compiling as c++
+      0.59    fix warnings: merge Dave Moore's -Wall fixes
+      0.58    fix bug: zlib uncompressed mode len/nlen was wrong endian
+      0.57    fix bug: jpg last huffman symbol before marker was >9 bits but less than 16 available
+      0.56    fix bug: zlib uncompressed mode len vs. nlen
+      0.55    fix bug: restart_interval not initialized to 0
+      0.54    allow NULL for 'int *comp'
+      0.53    fix bug in png 3->4; speedup png decoding
+      0.52    png handles req_comp=3,4 directly; minor cleanup; jpeg comments
+      0.51    obey req_comp requests, 1-component jpegs return as 1-component,
+              on 'test' only check type, not whether we support this variant
+      0.50  (2006-11-19)
+              first released version
+*/
+
+
+/*
+------------------------------------------------------------------------------
+This software is available under 2 licenses -- choose whichever you prefer.
+------------------------------------------------------------------------------
+ALTERNATIVE A - MIT License
+Copyright (c) 2017 Sean Barrett
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+------------------------------------------------------------------------------
+ALTERNATIVE B - Public Domain (www.unlicense.org)
+This is free and unencumbered software released into the public domain.
+Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
+software, either in source code form or as a compiled binary, for any purpose,
+commercial or non-commercial, and by any means.
+In jurisdictions that recognize copyright laws, the author or authors of this
+software dedicate any and all copyright interest in the software to the public
+domain. We make this dedication for the benefit of the public at large and to
+the detriment of our heirs and successors. We intend this dedication to be an
+overt act of relinquishment in perpetuity of all present and future rights to
+this software under copyright law.
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+------------------------------------------------------------------------------
+*/

Added: trunk/Build/source/texk/web2c/hitexdir/hintview/src/tables.c
===================================================================
--- trunk/Build/source/texk/web2c/hitexdir/hintview/src/tables.c	                        (rev 0)
+++ trunk/Build/source/texk/web2c/hitexdir/hintview/src/tables.c	2022-01-19 13:28:43 UTC (rev 61658)
@@ -0,0 +1,78 @@
+#include "basetypes.h"
+#include "format.h"
+
+const char *content_name[32]={"text", "list", "param", "xdimen", "adjust", "glyph", "kern", "glue", "ligature", "disc", "language", "rule", "image", "leaders", "baseline", "hbox", "vbox", "par", "math", "table", "item", "hset", "vset", "hpack", "vpack", "stream", "page", "range", "link", "undefined2", "undefined3", "penalty"};
+
+const char *definition_name[32]={"text", "list", "param", "xdimen", "adjust", "font", "dimen", "glue", "ligature", "disc", "language", "rule", "image", "leaders", "baseline", "hbox", "vbox", "par", "math", "table", "item", "hset", "vset", "hpack", "vpack", "stream", "page", "range", "label", "undefined2", "undefined3", "int"};
+
+int max_outline=-1;
+
+int32_t int_defaults[MAX_INT_DEFAULT+1]={0, 100, 200, 10, 50, 50, 150, 150, 50, 100, 10000, 0, 0, 10000, 5000, 10000, 0, 720, 4, 7, 1776, 1, 20000};
+
+dimen_t dimen_defaults[MAX_DIMEN_DEFAULT+1]={0x0, 0x1d5c147, 0x28333f7, 0x0, 0x0, 0x38000, 0x0, 0x0, 0xa0000, 0xa0000};
+
+glue_t glue_defaults[MAX_GLUE_DEFAULT+1]={
+{{0x0, 0.000000, 0.000000},{0.000000, 0},{0.000000, 0}},
+{{0x0, 0.000000, 0.000000},{1.000000, 1},{0.000000, 0}},
+{{0x0, 0.000000, 0.000000},{1.000000, 2},{0.000000, 0}},
+{{0x10000, 0.000000, 0.000000},{0.000000, 0},{0.000000, 0}},
+{{0xc0000, 0.000000, 0.000000},{0.000000, 0},{0.000000, 0}},
+{{0xc0000, 0.000000, 0.000000},{3.000000, 0},{9.000000, 0}},
+{{0xc0000, 0.000000, 0.000000},{3.000000, 0},{9.000000, 0}},
+{{0x0, 0.000000, 0.000000},{3.000000, 0},{0.000000, 0}},
+{{0x70000, 0.000000, 0.000000},{3.000000, 0},{4.000000, 0}},
+{{0x0, 0.000000, 0.000000},{0.000000, 0},{0.000000, 0}},
+{{0x0, 0.000000, 0.000000},{0.000000, 0},{0.000000, 0}},
+{{0xa0000, 0.000000, 0.000000},{0.000000, 0},{0.000000, 0}},
+{{0x80000, 0.000000, 0.000000},{0.000000, 0},{0.000000, 0}},
+{{0x0, 0.000000, 0.000000},{0.000000, 0},{0.000000, 0}},
+{{0x0, 0.000000, 0.000000},{1.000000, 1},{0.000000, 0}},
+};
+
+xdimen_t xdimen_defaults[MAX_XDIMEN_DEFAULT+1]={{0x0, 0.0, 0.0}, {0x0, 1.0, 0.0}, {0x0, 0.0, 1.0}};
+
+baseline_t baseline_defaults[MAX_BASELINE_DEFAULT+1]={{{{0x0, 0.000000, 0.000000},{0.000000, 0},{0.000000, 0}}, {{0x0, 0.000000, 0.000000},{0.000000, 0},{0.000000, 0}}, 0x0}};
+
+label_t label_defaults[MAX_LABEL_DEFAULT+1]={{0,LABEL_TOP,true,0,0,0}};
+
+int max_fixed[32]= {65536, 65536, -1, 2, 65536, -1, 0, 2, -1, -1, -1, -1, -1, -1, 0, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 0, 0, 0, -1, 65536, 65536, 0};
+
+int max_default[32]= {-1, -1, -1, 2, -1, -1, 9, 14, -1, -1, -1, -1, -1, -1, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 0, 0, 0, -1, -1, 22};
+
+int max_ref[32]= {-1, -1, -1, 2, -1, -1, 9, 14, -1, -1, -1, -1, -1, -1, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 0, 0, 0, -1, -1, 22};
+
+signed char hnode_size[0x100]= {
+0,0,0,0,0,0,0,0, /* text */
+0,0,0,0,0,0,0,0, /* list */
+0,0,0,0,0,0,0,0, /* param */
+0,6,6,10,6,10,10,14, /* xdimen */
+0,-4*1+0,0,0,0,0,0,0, /* adjust */
+0,4,5,6,7,0,0,0, /* glyph */
+3,3,6,-4*1+0,3,3,6,-4*1+0, /* kern */
+3,6,6,10,6,10,10,-4*9+0, /* glue */
+3,4,5,6,7,8,9,-4*2+0, /* ligature */
+3,0,-4*1+0,-4*1+1,3,0,-4*2+0,-4*2+1, /* disc */
+3,2,2,2,2,2,2,2, /* language */
+3,6,6,10,6,10,10,14, /* rule */
+3,0,0,0,4,12,12,20, /* image */
+3,-4*1+0,-4*1+0,-4*1+0,0,-4*1+1,-4*1+1,-4*1+1, /* leaders */
+3,6,-4*1+0,-4*5+0,-4*1+0,-4*5+0,-4*1+1,-4*5+1, /* baseline */
+-4*9+0,-4*13+0,-4*13+0,-4*17+0,-4*14+0,-4*18+0,-4*18+0,-4*22+0, /* hbox */
+-4*9+0,-4*13+0,-4*13+0,-4*17+0,-4*14+0,-4*18+0,-4*18+0,-4*22+0, /* vbox */
+-4*3+0,0,-4*2+1,0,-4*2+1,0,-4*1+2,0, /* par */
+-4*2+0,-4*2+1,-4*2+1,2,-4*1+1,-4*1+2,-4*1+2,2, /* math */
+-4*2+1,-4*2+1,-4*2+1,-4*2+1,-4*1+2,-4*1+2,-4*1+2,-4*1+2, /* table */
+-4*1+0,-4*1+0,-4*1+0,-4*1+0,-4*1+0,-4*1+0,-4*2+0,0, /* item */
+-4*18+0,-4*22+0,-4*22+0,-4*26+0,-4*17+1,-4*21+1,-4*21+1,-4*25+1, /* hset */
+-4*18+0,-4*22+0,-4*22+0,-4*26+0,-4*17+1,-4*21+1,-4*21+1,-4*25+1, /* vset */
+-4*2+0,-4*2+0,-4*6+0,-4*6+0,-4*1+1,-4*1+1,-4*5+1,-4*5+1, /* hpack */
+-4*6+0,-4*6+0,-4*10+0,-4*10+0,-4*5+1,-4*5+1,-4*9+1,-4*9+1, /* vpack */
+-4*3+0,0,-4*2+1,0,0,0,0,0, /* stream */
+0,0,0,0,0,0,0,0, /* page */
+0,0,0,0,0,0,0,0, /* range */
+3,4,3,4,0,0,0,0, /* link */
+0,0,0,0,0,0,0,0, /* undefined2 */
+0,0,0,0,0,0,0,0, /* undefined3 */
+3,3,4,0,0,0,0,0}; /* penalty */
+
+



More information about the tex-live-commits mailing list.