summaryrefslogtreecommitdiff
path: root/Build
diff options
context:
space:
mode:
authorMartin Ruckert <martin.ruckert@hm.edu>2022-01-19 13:28:43 +0000
committerMartin Ruckert <martin.ruckert@hm.edu>2022-01-19 13:28:43 +0000
commit7f3c341a9f19795e423e8821c34bbe37fea20aed (patch)
tree5a1ea5d468e06ccb9ad37a8ea743e2677b1ff3d9 /Build
parent257dabf9b9d3e3ac387e7d16eb06b37c8096638b (diff)
adding files to build the Linux HINT viewer (independent of the TL build)
git-svn-id: svn://tug.org/texlive/trunk@61658 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build')
-rw-r--r--Build/source/texk/web2c/hitexdir/hintview/man/hintview.1228
-rw-r--r--Build/source/texk/web2c/hitexdir/hintview/src/Makefile77
-rw-r--r--Build/source/texk/web2c/hitexdir/hintview/src/basetypes.h45
-rw-r--r--Build/source/texk/web2c/hitexdir/hintview/src/error.h59
-rw-r--r--Build/source/texk/web2c/hitexdir/hintview/src/format.h357
-rw-r--r--Build/source/texk/web2c/hitexdir/hintview/src/get.c624
-rw-r--r--Build/source/texk/web2c/hitexdir/hintview/src/get.h190
-rw-r--r--Build/source/texk/web2c/hitexdir/hintview/src/hfonts.c596
-rw-r--r--Build/source/texk/web2c/hitexdir/hintview/src/hfonts.h101
-rw-r--r--Build/source/texk/web2c/hitexdir/hintview/src/hint.c3775
-rw-r--r--Build/source/texk/web2c/hitexdir/hintview/src/hint.h167
-rw-r--r--Build/source/texk/web2c/hitexdir/hintview/src/hrender.c1436
-rw-r--r--Build/source/texk/web2c/hitexdir/hintview/src/hrender.h45
-rw-r--r--Build/source/texk/web2c/hitexdir/hintview/src/htex.c3757
-rw-r--r--Build/source/texk/web2c/hitexdir/hintview/src/htex.h1958
-rw-r--r--Build/source/texk/web2c/hitexdir/hintview/src/main.c406
-rw-r--r--Build/source/texk/web2c/hitexdir/hintview/src/main.h22
-rw-r--r--Build/source/texk/web2c/hitexdir/hintview/src/renderOGL.c553
-rw-r--r--Build/source/texk/web2c/hitexdir/hintview/src/rendernative.h52
-rw-r--r--Build/source/texk/web2c/hitexdir/hintview/src/stb_image.h7559
-rw-r--r--Build/source/texk/web2c/hitexdir/hintview/src/tables.c78
21 files changed, 22085 insertions, 0 deletions
diff --git a/Build/source/texk/web2c/hitexdir/hintview/man/hintview.1 b/Build/source/texk/web2c/hitexdir/hintview/man/hintview.1
new file mode 100644
index 00000000000..dc6d7626e7b
--- /dev/null
+++ b/Build/source/texk/web2c/hitexdir/hintview/man/hintview.1
@@ -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
diff --git a/Build/source/texk/web2c/hitexdir/hintview/src/Makefile b/Build/source/texk/web2c/hitexdir/hintview/src/Makefile
new file mode 100644
index 00000000000..6fb3b15d5e9
--- /dev/null
+++ b/Build/source/texk/web2c/hitexdir/hintview/src/Makefile
@@ -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
+
diff --git a/Build/source/texk/web2c/hitexdir/hintview/src/basetypes.h b/Build/source/texk/web2c/hitexdir/hintview/src/basetypes.h
new file mode 100644
index 00000000000..1db75956522
--- /dev/null
+++ b/Build/source/texk/web2c/hitexdir/hintview/src/basetypes.h
@@ -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*/
diff --git a/Build/source/texk/web2c/hitexdir/hintview/src/error.h b/Build/source/texk/web2c/hitexdir/hintview/src/error.h
new file mode 100644
index 00000000000..d283a6cd52e
--- /dev/null
+++ b/Build/source/texk/web2c/hitexdir/hintview/src/error.h
@@ -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*/
diff --git a/Build/source/texk/web2c/hitexdir/hintview/src/format.h b/Build/source/texk/web2c/hitexdir/hintview/src/format.h
new file mode 100644
index 00000000000..fa3ac640948
--- /dev/null
+++ b/Build/source/texk/web2c/hitexdir/hintview/src/format.h
@@ -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*/
diff --git a/Build/source/texk/web2c/hitexdir/hintview/src/get.c b/Build/source/texk/web2c/hitexdir/hintview/src/get.c
new file mode 100644
index 00000000000..300c7db66f2
--- /dev/null
+++ b/Build/source/texk/web2c/hitexdir/hintview/src/get.c
@@ -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*/
diff --git a/Build/source/texk/web2c/hitexdir/hintview/src/get.h b/Build/source/texk/web2c/hitexdir/hintview/src/get.h
new file mode 100644
index 00000000000..31bebae04e7
--- /dev/null
+++ b/Build/source/texk/web2c/hitexdir/hintview/src/get.h
@@ -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*/
diff --git a/Build/source/texk/web2c/hitexdir/hintview/src/hfonts.c b/Build/source/texk/web2c/hitexdir/hintview/src/hfonts.c
new file mode 100644
index 00000000000..7de7f5a1da6
--- /dev/null
+++ b/Build/source/texk/web2c/hitexdir/hintview/src/hfonts.c
@@ -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*/
diff --git a/Build/source/texk/web2c/hitexdir/hintview/src/hfonts.h b/Build/source/texk/web2c/hitexdir/hintview/src/hfonts.h
new file mode 100644
index 00000000000..550c6a9a751
--- /dev/null
+++ b/Build/source/texk/web2c/hitexdir/hintview/src/hfonts.h
@@ -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*/
diff --git a/Build/source/texk/web2c/hitexdir/hintview/src/hint.c b/Build/source/texk/web2c/hitexdir/hintview/src/hint.c
new file mode 100644
index 00000000000..a021046481b
--- /dev/null
+++ b/Build/source/texk/web2c/hitexdir/hintview/src/hint.c
@@ -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*/
diff --git a/Build/source/texk/web2c/hitexdir/hintview/src/hint.h b/Build/source/texk/web2c/hitexdir/hintview/src/hint.h
new file mode 100644
index 00000000000..a9e8ec7ea27
--- /dev/null
+++ b/Build/source/texk/web2c/hitexdir/hintview/src/hint.h
@@ -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*/
diff --git a/Build/source/texk/web2c/hitexdir/hintview/src/hrender.c b/Build/source/texk/web2c/hitexdir/hintview/src/hrender.c
new file mode 100644
index 00000000000..bf0946e3e1e
--- /dev/null
+++ b/Build/source/texk/web2c/hitexdir/hintview/src/hrender.c
@@ -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*/
diff --git a/Build/source/texk/web2c/hitexdir/hintview/src/hrender.h b/Build/source/texk/web2c/hitexdir/hintview/src/hrender.h
new file mode 100644
index 00000000000..7d389335aea
--- /dev/null
+++ b/Build/source/texk/web2c/hitexdir/hintview/src/hrender.h
@@ -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*/
diff --git a/Build/source/texk/web2c/hitexdir/hintview/src/htex.c b/Build/source/texk/web2c/hitexdir/hintview/src/htex.c
new file mode 100644
index 00000000000..4c3d5d18066
--- /dev/null
+++ b/Build/source/texk/web2c/hitexdir/hintview/src/htex.c
@@ -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*/
diff --git a/Build/source/texk/web2c/hitexdir/hintview/src/htex.h b/Build/source/texk/web2c/hitexdir/hintview/src/htex.h
new file mode 100644
index 00000000000..1107e48533b
--- /dev/null
+++ b/Build/source/texk/web2c/hitexdir/hintview/src/htex.h
@@ -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*/
diff --git a/Build/source/texk/web2c/hitexdir/hintview/src/main.c b/Build/source/texk/web2c/hitexdir/hintview/src/main.c
new file mode 100644
index 00000000000..f8e4b9e16f5
--- /dev/null
+++ b/Build/source/texk/web2c/hitexdir/hintview/src/main.c
@@ -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;
+}
+
diff --git a/Build/source/texk/web2c/hitexdir/hintview/src/main.h b/Build/source/texk/web2c/hitexdir/hintview/src/main.h
new file mode 100644
index 00000000000..d42397916cb
--- /dev/null
+++ b/Build/source/texk/web2c/hitexdir/hintview/src/main.h
@@ -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*/
diff --git a/Build/source/texk/web2c/hitexdir/hintview/src/renderOGL.c b/Build/source/texk/web2c/hitexdir/hintview/src/renderOGL.c
new file mode 100644
index 00000000000..7a2488cf982
--- /dev/null
+++ b/Build/source/texk/web2c/hitexdir/hintview/src/renderOGL.c
@@ -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;
+ }
+}
diff --git a/Build/source/texk/web2c/hitexdir/hintview/src/rendernative.h b/Build/source/texk/web2c/hitexdir/hintview/src/rendernative.h
new file mode 100644
index 00000000000..1a375736e77
--- /dev/null
+++ b/Build/source/texk/web2c/hitexdir/hintview/src/rendernative.h
@@ -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*/
diff --git a/Build/source/texk/web2c/hitexdir/hintview/src/stb_image.h b/Build/source/texk/web2c/hitexdir/hintview/src/stb_image.h
new file mode 100644
index 00000000000..196dfd5cc6e
--- /dev/null
+++ b/Build/source/texk/web2c/hitexdir/hintview/src/stb_image.h
@@ -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@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.
+------------------------------------------------------------------------------
+*/
diff --git a/Build/source/texk/web2c/hitexdir/hintview/src/tables.c b/Build/source/texk/web2c/hitexdir/hintview/src/tables.c
new file mode 100644
index 00000000000..e8d8c4cd3ca
--- /dev/null
+++ b/Build/source/texk/web2c/hitexdir/hintview/src/tables.c
@@ -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 */
+
+