+++ /dev/null
-Notice
-
- This documentation is a little outdated. As with swftools-0.2.1 and
- above, you can simply do
- pdf2swf -bl -o document.swf document.pdf
- to link viewer and preloader.
- However, the Steps below are still valid for jpeg2swf.
-
-Step 1: Converting the documents
-
- Suppose you have an arbitrary pdf file, "document.pdf".
- Call:
- pdf2swf -o tmp.swf document.pdf
- Now, tmp.swf is a Flash Movie generated from document.pdf. Movie means
- that there are no navigation elements whatsoever. Just frames which
- get displayed one by one, at a rate of approx. 1/2 frames/second. How
- to make document browsable is explained below.
- (You can do the same things described below with jpeg files. Simply
- use
- jpeg2swf -o tmp.swf pic1.jpeg pic2.jpeg ...
- and read on)
-
-Step 2: Linking a viewer
-
- Just take a viewer of your choice (e.g. [1]SimpleViewer.swf ) and put
- it in the same directory where you entered the commands above.
- Now call:
- swfcombine -o flashfile.swf SimpleViewer.swf viewport=tmp.swf
- Now, 'flashfile.swf' is "browsable", i.e. there are some buttons in it
- for turning pages.
-
-Step 3: Linking a Preloader
-
- Depending on the size of your PDFs/SWFs, you may want to have some
- kind of loading animation displayed while the browser is busy getting
- the actual document. Assuming you have some file like flashfile.swf
- above, you furthermore need the file [2]PreLoader.swf and an arbirtary
- loading animation of your choice. (To get started, try [3]loading.swf,
- or just convert a "Loading" JPEG picture to swf (jpeg2swf -o
- loading.swf picture.jpg)) Now use
- swfcombine -o flashfile.swf PreLoader.swf loader=loading.swf
- movie=flashfile.swf
- (Most loaders are smaller than the document they load. They usually
- need some centering so they appear in the middle of the page to be
- displayed, not in the upper left corner. Replace the above command
- with e.g.
- swfcombine -o flashfile.swf PreLoader.swf -x 3000 -y 3000
- loader=loading.swf movie=flashfile.swf
- and try playing around with the values after -x and -y)
-
-Step 4: Correcting the size and framerate
-
- Sometimes, the bounding box of the generated flash file is not
- correct. This happens because when linking a viewer or preloader to
- the SWFs, the new dimensions are those of the PreLoader and Viewer
- templates, and not those of your pdf or jpeg files. To fix this, use
- swfcombine --dummy `swfdump -XY tmp.swf` flashfile.swf -o
- flashfile.swf
- (tmp.swf is your 'original' swf, generated like above)
- You may also want to adjust the framerate of the movie to that of the
- preloader. (As the preloader is usually the only animated part of e.g.
- pdf viewers)
- Use:
- swfcombine --dummy `swfdump -r loading.swf` flashfile.swf -o
- flashfile.swf
-
-Step 5: Embedding the SWF into a html page
-
- Usually, one wants to put the generated SWFs on his web page. To do
- so, you have to embed the SWF file into html. If you don't know how to
- embed SWFs into html pages, it's explained at
- [4]http://www.macromedia.com/support/flash/ts/documents/tn4150.html .
- Also, you can simply type
- swfdump --html flashfile.swf
- and insert the output into your html document
-
-Appendix A: Creating your own Viewers
-
- If you know about Flash, and you want to substitute SimpleViewer from
- above with something more sophisticated, follow these rules:
- 1. There has to be some rectangle (Movieclip, whatever... ) in your
- Viewer, named "viewport". (This name is used to reference the object
- when using swfcombine for merging it with the converted pdfs)
- 2. The First frame should contain an actionscript "Stop" instruction.
- (Otherwise, the browsing buttons turn pages, but pages get also
- automatically turned every few seconds)
- 3. Browsing buttons next to the rectangle (which turn pages in the
- shown pdf) should trigger some Actionsscript events, like
-
- SetTarget "viewport"
- NextFrame
- SetTarget ""
-
- to set the frame in the to-be-replaced rectangle. (It will be replaced
- with a MovieClip, therefore a SetTarget is neccessary)
- It's important that the Target Name ist "viewport", not "/viewport",
- as the Movie will get inserted into a Movieclip (Sprite).
- _________________________________________________________________
-
- [5]Back to the SWFTools Project page
-
-References
-
- Visible links
- 1. http://www.quiss.org/swftools/SimpleViewer.swf
- 2. http://www.quiss.org/swftools/PreLoader.swf
- 3. http://www.quiss.org/swftools/loading.swf
- 4. http://www.macromedia.com/support/flash/ts/documents/tn4150.html
- 5. http://www.quiss.org/swftools
-
-
-
+++ /dev/null
-.TH pdf2swf "1" "January 2003" "pdf2swf" "swftools"
-.SH NAME
-pdf2swf - convert PDF files into SWF
-.SH Synopsis
-.B pdf2swf
-[\fIoptions\fR] \fIfile.pdf\fR [-o \fIfile.swf\fR]
-.SH DESCRIPTION
-This tools converts Acrobat PDF files into Flash SWF Animation
-files.
-.SH OPTIONS
-.TP
-\fB\-h\fR, \fB\-\-help\fR
-Print short help message and exit
-.TP
-\fB\-V\fR, \fB\-\-version\fR
-Print version info and exit
-.TP
-\fB\-p\fR, \fB\-\-pages\fR \fIrange\fR
-Convert only pages in \fIrange\fR with \fIrange\fR e.g. 1-20 or 1,4,6,9-11 or
-3-5,10-12
-.TP
-\fB\-v\fR, \fB\-\-verbose\fR
-Be verbose. Use more than one -v for greater effect.
-.TP
-\fB\-z\fR, \fB\-\-zlib\fR
-Use Flash 6 (MX) zlib compression.
-\fBThe resulting SWF will not be playable in browsers with Flash Plugins 5 and below!\fR
-.TP
-\fB\-i\fR, \fB\-\-ignore\fR
-Allows pdf2swf to change the draw order of the pdf. This may make the generated
-SWF files a little bit smaller, but it may also cause the images in the pdf to look funny.
-.TP
-\fB\-j\fR, \fB\-\-jpegquality\fR \fIquality\fR
-Set quality of embedded jpeg pictures to \fIquality\fR. 0 is worst (small), 100 is best (big). (default:85)
-.TP
-\fB\-s\fR, \fB\-\-set\fR \fIparam=value\fR
-Set a SWF encoder specific parameter. See pdf2swf \-\-help for more information.
-.TP
-\fB\-w\fR, \fB\-\-samewindow\fR
-When converting pdf hyperlinks, don't make the links open a new window when clicked on,
-but open the page they point to in the window the SWF is displayed.
-.TP
-\fB\-t\fR, \fB\-\-stop\fR
-Insert a stop() command in each page. The resulting SWF file will not turn pages automatically.
-.TP
-\fB\-T\fR, \fB\-\-flashversion\fR \fInum\fR
-Set Flash Version in the SWF header to \fInum\fR.
-.TP
-\fB\-F\fR, \fB\-\-fontdir\fR \fIdirectory\fR
-Add \fIdirectory\fR to the font search path.
-.TP
-\fB\-b\fR, \fB\-\-defaultviewer\fR
-Link a standard viewer to the swf file. Therefore the swf file will be "browseable", i.e.
-display some buttons for turning pages.
-The viewer swf to be used is determined by a symlink named "default_viewer.swf" in
-the swftools data directory.
-.TP
-\fB\-l\fR, \fB\-\-defaultloader\fR
-Link a standard preloader to the swf file which will be displayed while the main swf is
-loading.
-The loader swf to be used is determined by a symlink named "default_loader.swf" in
-the swftools data directory.
-.TP
-\fB\-B\fR, \fB\-\-viewer\fR \fIfilename\fR
-Link viewer \fIfilename\fR to the swf file. See http://www.quiss.org/swftools/pdf2swf_usage.html
-for information on how to create your own viewers.
-.TP
-\fB\-L\fR, \fB\-\-loader\fR \fIfilename\fR
-Link preloader \fIfilename\fR to the swf file, where \fIfilename\fR
-is an arbitrary swf animation.
-.SH BUGS
-.PP
-dashed lines don't work.
-
-.SH AUTHOR
-
-Matthias Kramm <kramm@quiss.org>
+++ /dev/null
-The following copyright notice applies to all the files provided
-in this distribution unless explicitly noted otherwise
-(the most notable exception being t1asm.c).
-
- Copyright (c) 1997-2001 by the AUTHORS:
- Andrew Weeks <ccsaw@bath.ac.uk>
- Frank M. Siegert <fms@this.net>
- Mark Heath <mheath@netspace.net.au>
- Thomas Henlich <thenlich@rcs.urz.tu-dresden.de>
- Sergey Babkin <babkin@bellatlantic.net>, <sab123@hotmail.com>
- Turgut Uyar <uyar@cs.itu.edu.tr>
- Rihardas Hepas <rch@WriteMe.Com>
- Szalay Tamas <tomek@elender.hu>
- Johan Vromans <jvromans@squirrel.nl>
- Petr Titera <P.Titera@sh.cvut.cz>
- Lei Wang <lwang@amath8.amt.ac.cn>
- Chen Xiangyang <chenxy@sun.ihep.ac.cn>
- Zvezdan Petkovic <z.petkovic@computer.org>
- All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions
- are met:
- 1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
- 3. All advertising materials mentioning features or use of this software
- must display the following acknowledgement:
- This product includes software developed by the TTF2PT1 Project
- and its contributors.
-
- THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- SUCH DAMAGE.
-
-For the approximate list of the AUTHORS' responsibilities see the
-project history.
-
-Other contributions to the project are:
-
-Turgut Uyar <uyar@cs.itu.edu.tr>
- The Unicode translation table for the Turkish language.
-
-Rihardas Hepas <rch@WriteMe.Com>
- The Unicode translation table for the Baltic languages.
-
-Szalay Tamas <tomek@elender.hu>
- The Unicode translation table for the Central European languages.
-
-Johan Vromans <jvromans@squirrel.nl>
- The RPM file.
-
-Petr Titera <P.Titera@sh.cvut.cz>
- The Unicode map format with names, the forced Unicode option.
-
-Frank M. Siegert <frank@this.net>
- Port to Windows
-
-Lei Wang <lwang@amath8.amt.ac.cn>
-Chen Xiangyang <chenxy@sun.ihep.ac.cn>
- Translation maps for Chinese fonts.
-
-Zvezdan Petkovic <z.petkovic@computer.org>
- The Unicode translation tables for the Cyrillic alphabet.
-
-I. Lee Hetherington <ilh@lcs.mit.edu>
- The Type1 assembler (from the package 't1utils'), its full copyright
- notice:
- Copyright (c) 1992 by I. Lee Hetherington, all rights reserved.
- Permission is hereby granted to use, modify, and distribute this program
- for any purpose provided this copyright notice and the one below remain
- intact.
-
+++ /dev/null
-top_builddir = ../..
-srcdir = @srcdir@
-top_srcdir = @top_srcdir@
-include ../../Makefile.common
-
-all: libpdf.a
-
-ttf2pt1_objects = ft.o ttf.o pt1.o ttf2pt1.o t1asm.o bdf.o bitmap.o
-
-ft.o: ft.c
- $(C) -I./ -Wno-parentheses ft.c -o $@
-ttf.o: ttf.c
- $(C) -I./ -Wno-parentheses ttf.c -o $@
-pt1.o: pt1.c
- $(C) -I./ -Wno-parentheses pt1.c -o $@
-ttf2pt1.o: ttf2pt1.c
- $(C) -I./ -Wno-parentheses ttf2pt1.c -o $@
-t1asm.o: t1asm.c
- $(C) -I./ -Wno-parentheses t1asm.c -o $@
-bitmap.o: bitmap.c
- $(C) -I./ -Wno-parentheses bitmap.c -o $@
-bdf.o: bdf.c
- $(C) -I./ -Wno-parentheses bdf.c -o $@
-
-libpdf.a: $(ttf2pt1_objects)
- $(AR) r ttf2pt1.a $(ttf2pt1_objects)
- $(RANLIB) ttf2pt1.a
-
-install:
-uninstall:
-
-clean:
- rm -f *.o *.lo *.a *.la gmon.out
-
+++ /dev/null
-/*
- * The font parser for the BDF files
- *
- * Copyright (c) 2001 by the TTF2PT1 project
- * Copyright (c) 2001 by Sergey Babkin
- *
- * see COPYRIGHT for the full copyright notice
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <ctype.h>
-#include "pt1.h"
-#include "global.h"
-
-/* prototypes of call entries */
-static void openfont(char *fname, char *arg);
-static void closefont( void);
-static int getnglyphs ( void);
-static int glnames( GLYPH *glyph_list);
-static void readglyphs( GLYPH *glyph_list);
-static int glenc( GLYPH *glyph_list, int *encoding, int *unimap);
-static void fnmetrics( struct font_metrics *fm);
-static void glpath( int glyphno, GLYPH *glyph_list);
-static void kerning( GLYPH *glyph_list);
-
-/* globals */
-
-/* front-end descriptor */
-struct frontsw bdf_sw = {
- /*name*/ "bdf",
- /*descr*/ "BDF bitmapped fonts",
- /*suffix*/ { "bdf" },
- /*open*/ openfont,
- /*close*/ closefont,
- /*nglyphs*/ getnglyphs,
- /*glnames*/ glnames,
- /*glmetrics*/ readglyphs,
- /*glenc*/ glenc,
- /*fnmetrics*/ fnmetrics,
- /*glpath*/ glpath,
- /*kerning*/ kerning,
-};
-
-/* statics */
-
-#define MAXLINE 10240 /* maximal line length in the input file */
-
-static int lineno; /* line number */
-
-#define GETLEN(s) s, (sizeof(s)-1)
-#define LENCMP(str, txt) strncmp(str, txt, sizeof(txt)-1)
-
-static FILE *bdf_file;
-static int nglyphs;
-static struct font_metrics fmet;
-
-/* many BDF fonts are of small pixel size, so we better try
- * to scale them by an integer to keep the dimensions in
- * whole pixels. However if the size is too big and a non-
- * integer scaling is needed, we use the standard ttf2pt1's
- * scaling abilities.
- */
-static int pixel_size;
-static int scale;
-static int scale_external;
-
-static char *slant;
-static char xlfdname[201];
-static char *spacing;
-static char *charset_reg;
-static char *charset_enc;
-static char *fnwidth;
-static int is_unicode = 0;
-
-/* tempoary storage for returning data to ttf2pt1 later on request */
-static int maxenc = 0;
-static int *fontenc;
-static GENTRY **glpaths;
-
-static int got_glyphs = 0;
-static GLYPH *glyphs;
-static int curgl;
-
-static int readfile(FILE *f, int (*strfunc)(int len, char *str));
-
-/*
- * Read the file and parse each string with strfunc(),
- * until strfunc() returns !=0 or the end of file happens.
- * Returns -1 on EOF or strfunc() returning <0, else 0
- */
-
-static int
-readfile(
- FILE *f,
- int (*strfunc)(int len, char *str)
-)
-{
- static char str[MAXLINE]; /* input line, maybe should be dynamic ? */
- char *s;
- int len, c, res;
-
- len=0;
- while(( c=getc(f) )!=EOF) {
- if(c=='\n') {
- str[len]=0;
-
- res = strfunc(len, str);
- lineno++;
- if(res<0)
- return -1;
- else if(res!=0)
- return 0;
-
- len=0;
- } else if(len<MAXLINE-1) {
- if(c!='\r')
- str[len++]=c;
- } else {
- fprintf(stderr, "**** bdf: line %d is too long (>%d)\n", lineno, MAXLINE-1);
- exit(1);
- }
- }
- return -1; /* EOF */
-}
-
-/*
- * Parse the header of the font file.
- * Stop after the line CHARS is encountered. Ignore the unknown lines.
- */
-
-struct line {
- char *name; /* property name with trailing space */
- int namelen; /* length of the name string */
- enum {
- ALLOW_REPEAT = 0x01, /* this property may be repeated in multiple lines */
- IS_SEEN = 0x02, /* this property has been seen already */
- MUST_SEE = 0x04, /* this property must be seen */
- IS_LAST = 0x08 /* this is the last property to be read */
- } flags;
- char *fmt; /* format string for the arguments, NULL means a string arg */
- int nvals; /* number of values to be read by sscanf */
- void *vp[4]; /* pointers to values to be read */
-};
-
-static struct line header[] = {
- { GETLEN("FONT "), 0, " %200s", 1, {&xlfdname} },
- { GETLEN("SIZE "), MUST_SEE, " %d", 1, {&pixel_size} },
- { GETLEN("FONTBOUNDINGBOX "), MUST_SEE, " %hd %hd %hd %hd", 4,
- {&fmet.bbox[2], &fmet.bbox[3], &fmet.bbox[0], &fmet.bbox[1]} },
- { GETLEN("FAMILY_NAME "), MUST_SEE, NULL, 1, {&fmet.name_family} },
- { GETLEN("WEIGHT_NAME "), MUST_SEE, NULL, 1, {&fmet.name_style} },
- { GETLEN("COPYRIGHT "), 0, NULL, 1, {&fmet.name_copyright} },
- { GETLEN("SLANT "), MUST_SEE, NULL, 1, {&slant} },
- { GETLEN("SPACING "), 0, NULL, 1, {&spacing} },
- { GETLEN("SETWIDTH_NAME "), 0, NULL, 1, {&fnwidth} },
- { GETLEN("CHARSET_REGISTRY "), 0, NULL, 1, {&charset_reg} },
- { GETLEN("CHARSET_ENCODING "), 0, NULL, 1, {&charset_enc} },
- { GETLEN("FONT_ASCENT "), 0, " %hd", 1, {&fmet.ascender} },
- { GETLEN("FONT_DESCENT "), 0, " %hd", 1, {&fmet.descender} },
-
- /* these 2 must go in this order for post-processing */
- { GETLEN("UNDERLINE_THICKNESS "), 0, " %hd", 1, {&fmet.underline_thickness} },
- { GETLEN("UNDERLINE_POSITION "), 0, " %hd", 1, {&fmet.underline_position} },
-
- { GETLEN("CHARS "), MUST_SEE|IS_LAST, " %d", 1, {&nglyphs} },
- { NULL, 0, 0 } /* end mark: name==NULL */
-};
-
-static int
-handle_header(
- int len,
- char *str
-)
-{
- struct line *cl;
- char *s, *p;
- int c;
-
-#if 0
- fprintf(stderr, "line: %s\n", str);
-#endif
- for(cl = header; cl->name != 0; cl++) {
- if(strncmp(str, cl->name, cl->namelen))
- continue;
-#if 0
- fprintf(stderr, "match: %s\n", cl->name);
-#endif
- if(cl->flags & IS_SEEN) {
- if(cl->flags & ALLOW_REPEAT)
- continue;
-
- fprintf(stderr, "**** input line %d redefines the property %s\n", lineno, cl->name);
- exit(1);
- }
- cl->flags |= IS_SEEN;
- if(cl->fmt == 0) {
- s = malloc(len - cl->namelen + 1);
- if(s == 0) {
- fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__);
- exit(255);
- }
- *((char **)(cl->vp[0])) = s;
-
- /* skip until a quote */
- for(p = str+cl->namelen; (c = *p)!=0; p++) {
- if(c == '"') {
- p++;
- break;
- }
- }
- for(; (c = *p)!=0; p++) {
- if(c == '"') {
- c = *++p;
- if(c == '"')
- *s++ = c;
- else
- break;
- } else
- *s++ = c;
- }
- *s = 0; /* end of line */
- } else {
- c = sscanf(str+cl->namelen, cl->fmt, cl->vp[0], cl->vp[1], cl->vp[2], cl->vp[3]);
- if(c != cl->nvals) {
- fprintf(stderr, "**** property %s at input line %d must have %d arguments\n",
- cl->name, lineno, cl->nvals);
- exit(1);
- }
- }
- if(cl->flags & IS_LAST)
- return 1;
- else
- return 0;
- }
- return 0;
-}
-
-/*
- * Parse the description of the glyphs
- */
-
-static int
-handle_glyphs(
- int len,
- char *str
-)
-{
- static int inbmap=0;
- static char *bmap;
- static int xsz, ysz, xoff, yoff;
- static int curln;
- int i, c;
- char *p, *plim, *psz;
-
- if(!LENCMP(str, "ENDFONT")) {
- if(curgl < nglyphs) {
- fprintf(stderr, "**** unexpected end of font file after %d glyphs\n", curgl);
- exit(1);
- } else
- return 1;
- }
- if(curgl >= nglyphs) {
- fprintf(stderr, "**** file contains more glyphs than advertised (%d)\n", nglyphs);
- exit(1);
- }
- if(!LENCMP(str, "STARTCHAR")) {
- /* sizeof will count \0 instead of ' ' */
- for(i=sizeof("STARTCHAR"); str[i] == ' '; i++)
- {}
-
- glyphs[curgl].name = strdup(str + i);
- if(glyphs[curgl].name == 0) {
- fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__);
- exit(255);
- }
- } else if(!LENCMP(str, "ENCODING")) {
- if(sscanf(str, "ENCODING %d", &fontenc[curgl])!=1) {
- fprintf(stderr,"**** weird ENCODING statement at line %d\n", lineno);
- exit(1);
- }
- if(fontenc[curgl] == -1) /* compatibility format */
- sscanf(str, "ENCODING -1 %d", &fontenc[curgl]);
- if(fontenc[curgl] > maxenc)
- maxenc = fontenc[curgl];
- } else if(!LENCMP(str, "DWIDTH")) {
- if(sscanf(str, "DWIDTH %d %d", &xsz, &ysz)!=2) {
- fprintf(stderr,"**** weird DWIDTH statement at line %d\n", lineno);
- exit(1);
- }
- glyphs[curgl].width = xsz*scale;
- } else if(!LENCMP(str, "BBX")) {
- if(sscanf(str, "BBX %d %d %d %d", &xsz, &ysz, &xoff, &yoff)!=4) {
- fprintf(stderr,"**** weird BBX statement at line %d\n", lineno);
- exit(1);
- }
- bmap=malloc(xsz*ysz);
- if(bmap==0) {
- fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__);
- exit(255);
- }
- glyphs[curgl].lsb = -xoff*scale;
- glyphs[curgl].xMin = -xoff*scale;
- glyphs[curgl].xMax = (xsz-xoff)*scale;
- glyphs[curgl].yMin = -yoff*scale;
- glyphs[curgl].yMax = (ysz-xoff)*scale;
- } else if(!LENCMP(str, "BITMAP")) {
- inbmap=1;
- curln=ysz-1; /* the lowest line has index 0 */
- } else if(!LENCMP(str, "ENDCHAR")) {
- inbmap=0;
- if(bmap) {
- glyphs[curgl].lastentry = 0;
- glyphs[curgl].path = 0;
- glyphs[curgl].entries = 0;
- bmp_outline(&glyphs[curgl], scale, bmap, xsz, ysz, xoff, yoff);
- free(bmap);
- /* remember in a static table or it will be erased */
- glpaths[curgl] = glyphs[curgl].entries;
- glyphs[curgl].entries = 0;
-
- if(glpaths[curgl])
- glyphs[curgl].ttf_pathlen = 1;
- else
- glyphs[curgl].ttf_pathlen = 0;
- }
- curgl++;
- } else if(inbmap) {
- if(curln<0) {
- fprintf(stderr,"**** bitmap is longer than %d lines at line %d\n", ysz, lineno);
- exit(1);
- }
-
- i=0;
- p=&bmap[curln*xsz]; psz=p+xsz;
- while(i<len) {
- c=str[i++];
- if(!isxdigit(c)) {
- fprintf(stderr,"**** non-hex digit in bitmap at line %d\n", lineno);
- exit(1);
- }
- if(c<='9')
- c-='0';
- else
- c= tolower(c)-'a'+10;
-
- for(plim=p+4; p<psz && p<plim; c<<=1)
- *p++ = (( c & 0x08 )!=0);
- }
- if(p<psz) {
- fprintf(stderr,"**** bitmap line is too short at line %d\n", lineno);
- exit(1);
- }
- curln--;
- }
- return 0;
-}
-
-/*
- * Read all the possible information about the glyphs
- */
-
-static void
-readglyphs(
- GLYPH *glyph_list
-)
-{
- int i;
- GLYPH *g;
-
- if(got_glyphs)
- return;
-
- /* pass them to handle_glyphs() through statics */
- glyphs = glyph_list;
- curgl = 2; /* skip the empty glyph and .notdef */
-
- /* initialize the empty glyph and .notdef */
-
- for(i=0; i<2; i++) {
- g = &glyphs[i];
- g->lsb = 0;
- g->width = fmet.bbox[2];
- g->xMin = 0;
- g->yMin = 0;
- }
- g = &glyphs[0];
- g->name = ".notdef";
- g->xMax = fmet.bbox[2]*4/5;
- g->yMax = fmet.bbox[3]*4/5;
- g->entries = g->path = g->lastentry = 0;
- /* make it look as a black square */
- fg_rmoveto(g, 0.0, 0.0);
- fg_rlineto(g, 0.0, (double)g->yMax);
- fg_rlineto(g, (double)g->xMax, (double)g->yMax);
- fg_rlineto(g, (double)g->xMax, 0.0);
- fg_rlineto(g, 0.0, 0.0);
- g_closepath(g);
- glpaths[0] = g->entries;
- g->entries = 0;
- g->ttf_pathlen = 4;
-
- g = &glyphs[1];
- g->name = ".null";
- g->xMax = g->yMax = 0;
- g->ttf_pathlen = 0;
-
- if(readfile(bdf_file, handle_glyphs) < 0) {
- fprintf(stderr, "**** file does not contain the ENDFONT line\n");
- exit(1);
- }
- got_glyphs = 1;
-}
-
-/*
- * Open font and prepare to return information to the main driver.
- * May print error and warning messages.
- * Exit on error.
- */
-
-static void
-openfont(
- char *fname,
- char *arg /* unused now */
-)
-{
- struct line *cl;
- int i, l;
-
- if ((bdf_file = fopen(fname, "rb")) == NULL) {
- fprintf(stderr, "**** Cannot open file '%s'\n", fname);
- exit(1);
- } else {
- WARNING_2 fprintf(stderr, "Processing file %s\n", fname);
- }
-
- lineno = 1;
-
- for(cl = header; cl->name != 0; cl++)
- cl->flags &= ~IS_SEEN;
- if(readfile(bdf_file, handle_header) < 0) {
- fprintf(stderr, "**** file does not contain the CHARS definition\n");
- exit(1);
- }
- for(cl = header; cl->name != 0; cl++) {
- if( (cl->flags & MUST_SEE) && !(cl->flags & IS_SEEN) ) {
- fprintf(stderr, "**** mandatory property %sis not found in the input line\n",
- cl->name); /* cl->name has a space at the end */
- exit(1);
- }
-
- /* set a few defaults */
- if( !(cl->flags & IS_SEEN) ) {
- if(cl->vp[0] == &fmet.underline_thickness) {
- fmet.underline_thickness = 1;
- } else if(cl->vp[0] == &fmet.underline_position) {
- fmet.underline_position = fmet.bbox[1] + fmet.underline_thickness
- - (pixel_size - fmet.bbox[3]);
- } else if(cl->vp[0] == &fmet.ascender) {
- fmet.ascender = fmet.bbox[2] + fmet.bbox[0];
- } else if(cl->vp[0] == &fmet.descender) {
- fmet.descender = fmet.bbox[0];
- }
- }
- }
-
- nglyphs += 2; /* add empty glyph and .notdef */
-
- /* postprocessing to compensate for the differences in the metric formats */
- fmet.bbox[2] += fmet.bbox[0];
- fmet.bbox[3] += fmet.bbox[1];
-
- scale = 1000/pixel_size; /* XXX ? */
- if(scale*pixel_size < 950) {
- scale = 1;
- scale_external = 1;
- fmet.units_per_em = pixel_size;
- } else {
- scale_external = 0;
- fmet.units_per_em = scale*pixel_size;
-
- fmet.underline_position *= scale;
- fmet.underline_thickness *= scale;
- fmet.ascender *= scale;
- fmet.descender *= scale;
- for(i=0; i<4; i++)
- fmet.bbox[i] *= scale;
- }
-
- fmet.italic_angle = 0.0;
- if(spacing == 0 /* possibly an old font */
- || toupper(spacing[0]) != 'P') /* or anything non-proportional */
- fmet.is_fixed_pitch = 1;
- else
- fmet.is_fixed_pitch = 0;
-
- if(fmet.name_copyright==NULL)
- fmet.name_copyright = "";
-
- /* create the full name */
- l = strlen(fmet.name_family)
- + (fmet.name_style? strlen(fmet.name_style) : 0)
- + (fnwidth? strlen(fnwidth) : 0)
- + strlen("Oblique") + 1;
-
- if(( fmet.name_full = malloc(l) )==NULL) {
- fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__);
- exit(255);
- }
- strcpy(fmet.name_full, fmet.name_family);
- if(fnwidth && strcmp(fnwidth, "Normal")) {
- strcat(fmet.name_full, fnwidth);
- }
- if(fmet.name_style && strcmp(fmet.name_style, "Medium")) {
- strcat(fmet.name_full, fmet.name_style);
- }
- switch(toupper(slant[0])) {
- case 'O':
- strcat(fmet.name_full, "Oblique");
- break;
- case 'I':
- strcat(fmet.name_full, "Italic");
- break;
- }
-
- fmet.name_ps = fmet.name_full;
- fmet.name_version = "1.0";
-
- if(charset_reg && charset_enc
- && !strcmp(charset_reg, "iso10646") && !strcmp(charset_enc, "1"))
- is_unicode = 1;
-
- if(( fontenc = calloc(nglyphs, sizeof *fontenc) )==NULL) {
- fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__);
- exit(255);
- }
- for(i=0; i<nglyphs; i++)
- fontenc[i] = -1;
- if(( glpaths = calloc(nglyphs, sizeof *glpaths) )==NULL) {
- fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__);
- exit(255);
- }
-}
-
-/*
- * Close font.
- * Exit on error.
- */
-
-static void
-closefont(
- void
-)
-{
- if(fclose(bdf_file) < 0) {
- WARNING_1 fprintf(stderr, "Errors when closing the font file, ignored\n");
- }
-}
-
-/*
- * Get the number of glyphs in font.
- */
-
-static int
-getnglyphs (
- void
-)
-{
- return nglyphs;
-}
-
-/*
- * Get the names of the glyphs.
- * Returns 0 if the names were assigned, non-zero if the font
- * provides no glyph names.
- */
-
-static int
-glnames(
- GLYPH *glyph_list
-)
-{
- readglyphs(glyph_list);
- return 0;
-}
-
-/*
- * Get the original encoding of the font.
- * Returns 1 for if the original encoding is Unicode, 2 if the
- * original encoding is other 16-bit, 0 if 8-bit.
- */
-
-static int
-glenc(
- GLYPH *glyph_list,
- int *encoding,
- int *unimap
-)
-{
- int i, douni, e;
-
- if(is_unicode || forcemap)
- douni = 1;
- else
- douni = 0;
-
- for(i=0; i<nglyphs; i++) {
- e = fontenc[i];
- if(douni)
- e = unicode_rev_lookup(e);
- if(e>=0 && e<ENCTABSZ && encoding[e] == -1)
- encoding[e] = i;
- }
-
- if(is_unicode)
- return 1;
- else if(maxenc > 255)
- return 2;
- else
- return 0;
-}
-
-/*
- * Get the font metrics
- */
-static void
-fnmetrics(
- struct font_metrics *fm
-)
-{
- *fm = fmet;
-}
-
-/*
- * Get the path of contrours for a glyph.
- */
-
-static void
-glpath(
- int glyphno,
- GLYPH *glyf_list
-)
-{
- readglyphs(glyf_list);
- glyf_list[glyphno].entries = glpaths[glyphno];
- glpaths[glyphno] = 0;
-}
-
-/*
- * Get the kerning data.
- */
-
-static void
-kerning(
- GLYPH *glyph_list
-)
-{
- return; /* no kerning in BDF */
-}
+++ /dev/null
-/*
- * Handling of the bitmapped glyphs
- *
- * Copyright (c) 2001 by the TTF2PT1 project
- * Copyright (c) 2001 by Sergey Babkin
- *
- * see COPYRIGHT for the full copyright notice
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <math.h>
-#include "pt1.h"
-#include "global.h"
-
-/* possible values of limits */
-#define L_NONE 0 /* nothing here */
-#define L_ON 1 /* black is on up/right */
-#define L_OFF 2 /* black is on down/left */
-
-static int warnedhints = 0;
-
-
-#ifdef USE_AUTOTRACE
-#include <autotrace/autotrace.h>
-
-/*
- * Produce an autotraced outline from a bitmap.
- * scale - factor to scale the sizes
- * bmap - array of dots by lines, xsz * ysz
- * xoff, yoff - offset of the bitmap's lower left corner
- * from the logical position (0,0)
- */
-
-static void
-autotraced_bmp_outline(
- GLYPH *g,
- int scale,
- char *bmap,
- int xsz,
- int ysz,
- int xoff,
- int yoff
-)
-{
- at_bitmap_type atb;
- at_splines_type *atsp;
- at_fitting_opts_type *atoptsp;
- at_spline_list_type *slp;
- at_spline_type *sp;
- int i, j, k;
- double lastx, lasty;
- double fscale;
- char *xbmap;
-
- fscale = (double)scale;
-
- /* provide a white margin around the bitmap */
- xbmap = malloc((ysz+2)*(xsz+2));
- if(xbmap == 0) {
- fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__);
- exit(255);
- }
- memset(xbmap, 0, xsz+2); /* top margin */
- for(i=0, j=xsz+2; i<ysz; i++, j+=xsz+2) {
- xbmap[j] = 0; /* left margin */
- memcpy(&xbmap[j+1], &bmap[xsz*(ysz-1-i)], xsz); /* a line of bitmap */
- xbmap[j+xsz+1] = 0; /* right margin */
- }
- memset(xbmap+j, 0, xsz+2); /* bottom margin */
- xoff--; yoff-=2; /* compensate for the margins */
-
- atoptsp = at_fitting_opts_new();
-
- atb.width = xsz+2;
- atb.height = ysz+2;
- atb.np = 1;
- atb.bitmap = xbmap;
-
- atsp = at_splines_new(&atb, atoptsp);
-
- lastx = lasty = -1.;
- for(i=0; i<atsp->length; i++) {
- slp = &atsp->data[i];
-#if 0
- fprintf(stderr, "%s: contour %d: %d entries clockwise=%d color=%02X%02X%02X\n",
- g->name, i, slp->length, slp->clockwise, slp->color.r, slp->color.g, slp->color.b);
-#endif
- if(slp->length == 0)
- continue;
-#if 0
- if(slp->color.r + slp->color.g + slp->color.b == 0)
- continue;
-#endif
- fg_rmoveto(g, fscale*(slp->data[0].v[0].x+xoff), fscale*(slp->data[0].v[0].y+yoff));
- for(j=0; j<slp->length; j++) {
-#if 0
- fprintf(stderr, " ");
- for(k=0; k<4; k++)
- fprintf(stderr, "(%g %g) ",
- fscale*(slp->data[j].v[k].x+xoff),
- fscale*(ysz-slp->data[j].v[k].y+yoff)
- );
- fprintf(stderr, "\n");
-#endif
- fg_rrcurveto(g,
- fscale*(slp->data[j].v[1].x+xoff), fscale*(slp->data[j].v[1].y+yoff),
- fscale*(slp->data[j].v[2].x+xoff), fscale*(slp->data[j].v[2].y+yoff),
- fscale*(slp->data[j].v[3].x+xoff), fscale*(slp->data[j].v[3].y+yoff) );
- }
- g_closepath(g);
- }
-
- at_splines_free(atsp);
- at_fitting_opts_free(atoptsp);
- free(xbmap);
-}
-
-#endif /*USE_AUTOTRACE*/
-
-/* an extension of gentry for description of the fragments */
-typedef struct gex_frag GEX_FRAG;
-struct gex_frag {
- /* indexes to len, the exact values and order are important */
-#define GEXFI_NONE -1
-#define GEXFI_CONVEX 0
-#define GEXFI_CONCAVE 1
-#define GEXFI_LINE 2 /* a line with steps varying by +-1 pixel */
-#define GEXFI_EXACTLINE 3 /* a line with exactly the same steps */
-#define GEXFI_COUNT 4 /* maximal index + 1 */
- unsigned short len[GEXFI_COUNT]; /* length of various fragment types starting here */
- unsigned short lenback[GEXFI_COUNT]; /* length back to the start of curve */
-
- signed char ixstart; /* index of the frag type that starts here */
- signed char ixcont; /* index of the frag type that continues here */
-
- short flags;
-#define GEXFF_HLINE 0x0001 /* the exact line is longer in "horizontal" dimension */
-#define GEXFF_EXTR 0x0002 /* this gentry is an extremum in some direction */
-#define GEXFF_CIRC 0x0004 /* the joint at this gentry is for a circular curve */
-#define GEXFF_DRAWCURVE 0x0008 /* vect[] describes a curve to draw */
-#define GEXFF_DRAWLINE 0x0010 /* vect[] describes a line to draw */
-#define GEXFF_SPLIT 0x0020 /* is a result of splitting a line */
-#define GEXFF_SYMNEXT 0x0040 /* this subfrag is symmetric with next one */
-#define GEXFF_DONE 0x0080 /* this subfrag has been vectorized */
-#define GEXFF_LONG 0x0100 /* this gentry is longer than 1 pixel */
-
- unsigned short aidx; /* index of gentry in the array representing the contour */
-
- unsigned short vectlen; /* number of gentries represented by vect[] */
-
- /* coordinates for vectored replacement of this fragment */
- /* (already scaled because it's needed for curve approximation) */
- double vect[4 /*ref.points*/][2 /*X,Y*/];
-
- double bbox[2 /*X,Y*/]; /* absolute sizes of bounding box of a subfragment */
-
- /* used when splitting the curved frags into subfrags */
- GENTRY *prevsub; /* to gentries describing neighboring subfrags */
- GENTRY *nextsub;
- GENTRY *ordersub; /* single-linked list describing the order of calculation */
-
- int sublen; /* length of this subfrag */
- /* the symmetry across the subfrags */
- int symaxis; /* the symmetry axis, with next subfrag */
- int symxlen; /* min length of adjacent symmetric frags */
- /* the symmetry within this subfrag (the axis is always diagonal) */
- GENTRY *symge; /* symge->i{x,y}3 is the symmetry point of symge==0 if none */
-
-};
-#define X_FRAG(ge) ((GEX_FRAG *)((ge)->ext))
-
-/* various interesting tables related to GEX_FRAG */
-static char *gxf_name[GEXFI_COUNT] = {"Convex", "Concave", "Line", "ExLine"};
-static int gxf_cvk[2] = {-1, 1}; /* coefficients of concaveness */
-
-/*
- * Dump the contents of X_EXT()->len and ->lenback for a contour
- */
-static void
-gex_dump_contour(
- GENTRY *ge,
- int clen
-)
-{
- int i, j;
-
- for(j = 0; j < GEXFI_COUNT; j++) {
- fprintf(stderr, "%-8s", gxf_name[j]);
- for(i = 0; i < clen; i++, ge = ge->frwd)
- fprintf(stderr, " %2d", X_FRAG(ge)->len[j]);
- fprintf(stderr, " %p\n (back) ", ge);
- for(i = 0; i < clen; i++, ge = ge->frwd)
- fprintf(stderr, " %2d", X_FRAG(ge)->lenback[j]);
- fprintf(stderr, "\n");
- }
-}
-
-/*
- * Calculate values of X_EXT()->lenback[] for all entries in
- * a contour. The contour is identified by:
- * ge - any gentry of the contour
- * clen - contour length
- */
-
-static void
-gex_calc_lenback(
- GENTRY *ge,
- int clen
-)
-{
- int i, j;
- int end;
- GEX_FRAG *f;
- int len[GEXFI_COUNT]; /* length of the most recent fragment */
- int count[GEXFI_COUNT]; /* steps since beginning of the fragment */
-
- for(j = 0; j < GEXFI_COUNT; j++)
- len[j] = count[j] = 0;
-
- end = clen;
- for(i = 0; i < end; i++, ge = ge->frwd) {
- f = X_FRAG(ge);
- for(j = 0; j < GEXFI_COUNT; j++) {
- if(len[j] != count[j]) {
- f->lenback[j] = count[j]++;
- } else
- f->lenback[j] = 0;
- if(f->len[j] != 0) {
- len[j] = f->len[j];
- count[j] = 1; /* start with the next gentry */
- /* if the fragment will wrap over the start, process to its end */
- if(i < clen && i + len[j] > end)
- end = i + len[j];
- }
- }
- }
- gex_dump_contour(ge, clen);
-}
-
-/* Limit a curve to not exceed the given coordinates
- * at its given side
- */
-
-static void
-limcurve(
- double curve[4][2 /*X,Y*/],
- double lim[2 /*X,Y*/],
- int where /* 0 - start, 3 - end */
-)
-{
- int other = 3-where; /* the other end */
- int sgn[2 /*X,Y*/]; /* sign for comparison */
- double t, from, to, nt, t2, nt2, tt[4];
- double val[2 /*X,Y*/];
- int i;
-
- for(i=0; i<2; i++)
- sgn[i] = fsign(curve[other][i] - curve[where][i]);
-
-#if 0
- fprintf(stderr, " limit (%g,%g)-(%g,%g) at %d by (%g,%g), sgn(%d,%d)\n",
- curve[0][0], curve[0][1], curve[3][0], curve[3][1],
- where, lim[0], lim[1], sgn[0], sgn[1]);
-#endif
- /* a common special case */
- if( sgn[0]*(curve[where][0] - lim[0]) >= 0.
- && sgn[1]*(curve[where][1] - lim[1]) >= 0. )
- return; /* nothing to do */
-
- if(other==0) {
- from = 0.;
- to = 1.;
- } else {
- from = 1.;
- to = 0.;
- }
-#if 0
- fprintf(stderr, "t=");
-#endif
- while( fabs(from-to) > 0.00001 ) {
- t = 0.5 * (from+to);
- t2 = t*t;
- nt = 1.-t;
- nt2 = nt*nt;
- tt[0] = nt2*nt;
- tt[1] = 3*nt2*t;
- tt[2] = 3*nt*t2;
- tt[3] = t*t2;
- for(i=0; i<2; i++)
- val[i] = curve[0][i]*tt[0] + curve[1][i]*tt[1]
- + curve[2][i]*tt[2] + curve[3][i]*tt[3];
-#if 0
- fprintf(stderr, "%g(%g,%g) ", t, val[0], val[1]);
-#endif
- if(fabs(val[0] - lim[0]) < 0.1
- || fabs(val[1] - lim[1]) < 0.1)
- break;
-
- if(sgn[0] * (val[0] - lim[0]) < 0.
- || sgn[1] * (val[1] - lim[1]) < 0.)
- to = t;
- else
- from = t;
- }
- /* now t is the point of splitting */
-#define SPLIT(pt1, pt2) ( (pt1) + t*((pt2)-(pt1)) ) /* order is important! */
- for(i=0; i<2; i++) {
- double v11, v12, v13, v21, v22, v31; /* intermediate points */
-
- v11 = SPLIT(curve[0][i], curve[1][i]);
- v12 = SPLIT(curve[1][i], curve[2][i]);
- v13 = SPLIT(curve[2][i], curve[3][i]);
- v21 = SPLIT(v11, v12);
- v22 = SPLIT(v12, v13);
- v31 = SPLIT(v21, v22);
- if(other==0) {
- curve[1][i] = v11;
- curve[2][i] = v21;
- curve[3][i] = fabs(v31 - lim[i]) < 0.1 ? lim[i] : v31;
- } else {
- curve[0][i] = fabs(v31 - lim[i]) < 0.1 ? lim[i] : v31;
- curve[1][i] = v22;
- curve[2][i] = v13;
- }
- }
-#undef SPLIT
-#if 0
- fprintf(stderr, "\n");
-#endif
-}
-
-/*
- * Vectorize a subfragment of a curve fragment. All the data has been already
- * collected by this time
- */
-
-static void
-dosubfrag(
- GLYPH *g,
- int fti, /* fragment type index */
- GENTRY *firstge, /* first gentry of fragment */
- GENTRY *ge, /* first gentry of subfragment */
- double fscale
-)
-{
- GENTRY *gel, *gei; /* last gentry of this subfrag */
- GEX_FRAG *f, *ff, *lf, *pf, *xf;
- /* maximal amount of space that can be used at the beginning and the end */
- double fixfront[2], fixend[2]; /* fixed points - used to show direction */
- double mvfront[2], mvend[2]; /* movable points */
- double limfront[2], limend[2]; /* limit of movement for movabel points */
- double sympt;
- int outfront, outend; /* the beginning/end is going outwards */
- int symfront, symend; /* a ready symmetric fragment is present at front/end */
- int drnd[2 /*X,Y*/]; /* size of the round part */
- int i, j, a1, a2, ndots;
- double avg2, max2; /* squared distances */
- struct dot_dist *dots, *usedots;
-
- ff = X_FRAG(firstge);
- f = X_FRAG(ge);
- gel = f->nextsub;
- lf = X_FRAG(gel);
- if(f->prevsub != 0)
- pf = X_FRAG(f->prevsub);
- else
- pf = 0;
-
- for(i=0; i<2; i++)
- drnd[i] = gel->bkwd->ipoints[i][2] - ge->ipoints[i][2];
-
- if(f->prevsub==0 && f->ixcont == GEXFI_NONE) {
- /* nothing to join with : may use the whole length */
- for(i = 0; i < 2; i++)
- limfront[i] = ge->bkwd->ipoints[i][2];
- } else {
- /* limit to a half */
- for(i = 0; i < 2; i++)
- limfront[i] = 0.5 * (ge->ipoints[i][2] + ge->bkwd->ipoints[i][2]);
- }
- if( (ge->ix3 == ge->bkwd->ix3) /* vert */
- ^ (isign(ge->bkwd->ix3 - ge->frwd->ix3)==isign(ge->bkwd->iy3 - ge->frwd->iy3))
- ^ (fti == GEXFI_CONCAVE) /* counter-clockwise */ ) {
- /* the beginning is not a flat 90-degree end */
- outfront = 1;
- for(i = 0; i < 2; i++)
- fixfront[i] = ge->frwd->ipoints[i][2];
- } else {
- outfront = 0;
- for(i = 0; i < 2; i++)
- fixfront[i] = ge->ipoints[i][2];
- }
-
- if(lf->nextsub==0 && lf->ixstart == GEXFI_NONE) {
- /* nothing to join with : may use the whole length */
- for(i = 0; i < 2; i++)
- limend[i] = gel->ipoints[i][2];
- } else {
- /* limit to a half */
- for(i = 0; i < 2; i++)
- limend[i] = 0.5 * (gel->ipoints[i][2] + gel->bkwd->ipoints[i][2]);
- }
- gei = gel->bkwd->bkwd;
- if( (gel->ix3 == gel->bkwd->ix3) /* vert */
- ^ (isign(gel->ix3 - gei->ix3)==isign(gel->iy3 - gei->iy3))
- ^ (fti == GEXFI_CONVEX) /* clockwise */ ) {
- /* the end is not a flat 90-degree end */
- outend = 1;
- for(i = 0; i < 2; i++)
- fixend[i] = gel->bkwd->bkwd->ipoints[i][2];
- } else {
- outend = 0;
- for(i = 0; i < 2; i++)
- fixend[i] = gel->bkwd->ipoints[i][2];
- }
-
- for(i = 0; i < 2; i++) {
- fixfront[i] *= fscale;
- limfront[i] *= fscale;
- fixend[i] *= fscale;
- limend[i] *= fscale;
- }
-
- fprintf(stderr, " %d out(%d[%d %d %d],%d[%d %d %d]) drnd(%d, %d)\n",
- fti,
- outfront,
- (ge->ix3 == ge->bkwd->ix3),
- (isign(ge->bkwd->ix3 - ge->frwd->ix3)==isign(ge->bkwd->iy3 - ge->frwd->iy3)),
- (fti == GEXFI_CONCAVE),
- outend,
- (gel->ix3 == gel->bkwd->ix3),
- (isign(gel->ix3 - gei->ix3)==isign(gel->iy3 - gei->iy3)),
- (fti == GEXFI_CONVEX),
- drnd[0], drnd[1]);
-
- /* prepare to calculate the distances */
- ndots = f->sublen - 1;
- dots = malloc(sizeof(*dots) * ndots);
- if(dots == 0) {
- fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__);
- exit(255);
- }
- for(i = 0, gei = ge; i < ndots; i++, gei = gei->frwd) {
- for(a1 = 0; a1 < 2; a1++)
- dots[i].p[a1] = fscale * gei->ipoints[a1][2];
- }
-
- /* see if we can mirror a ready symmetric curve */
-
- /* check symmetry with the fragment before this */
- symfront = (pf != 0 && (pf->flags & GEXFF_SYMNEXT) && (pf->flags & GEXFF_DONE)
- && ( outend && f->sublen <= pf->sublen
- || ( pf->sublen == f->sublen
- && (lf->sublen == 0
- || ( abs(limfront[0]-limend[0]) >= abs(pf->vect[0][0]-pf->vect[3][0])
- && abs(limfront[1]-limend[1]) >= abs(pf->vect[0][1]-pf->vect[3][1]) ))
- )
- )
- );
- /* check symmetry with the fragment after this */
- symend = ( (f->flags & GEXFF_SYMNEXT) && (lf->flags & GEXFF_DONE)
- && ( outfront && f->sublen <= lf->sublen
- || ( lf->sublen == f->sublen
- && (pf == 0
- || ( abs(limfront[0]-limend[0]) >= abs(lf->vect[0][0]-lf->vect[3][0])
- && abs(limfront[1]-limend[1]) >= abs(lf->vect[0][1]-lf->vect[3][1]) ))
- )
- )
- );
- if(symfront || symend) {
- /* mirror the symmetric neighbour subfrag */
- if(symfront) {
- a1 = (ge->ix3 != ge->bkwd->ix3); /* the symmetry axis */
- a2 = !a1; /* the other axis (goes along the extremum gentry) */
-
- /* the symmetry point on a2 */
- sympt = fscale * 0.5 * (ge->ipoints[a2][2] + ge->bkwd->ipoints[a2][2]);
- xf = pf; /* the symmetric fragment */
- } else {
- a1 = (gel->ix3 != gel->bkwd->ix3); /* the symmetry axis */
- a2 = !a1; /* the other axis (goes along the extremum gentry) */
-
- /* the symmetry point on a2 */
- sympt = fscale * 0.5 * (gel->ipoints[a2][2] + gel->bkwd->ipoints[a2][2]);
- xf = lf; /* the symmetric fragment */
- }
- fprintf(stderr, " sym with %p f=%d(%p) e=%d(%p) a1=%c a2=%c sympt=%g\n",
- xf, symfront, pf, symend, lf,
- a1 ? 'Y': 'X', a2 ? 'Y': 'X', sympt
- );
- for(i=0; i<4; i++) {
- f->vect[3-i][a1] = xf->vect[i][a1];
- f->vect[3-i][a2] = sympt - (xf->vect[i][a2]-sympt);
- }
- if(symfront) {
- if(outend || lf->sublen==0)
- limcurve(f->vect, limend, 3);
- } else {
- if(outfront || pf == 0)
- limcurve(f->vect, limfront, 0);
- }
- avg2 = fdotcurvdist2(f->vect, dots, ndots, &max2);
- fprintf(stderr, " avg=%g max=%g fscale=%g\n", sqrt(avg2), sqrt(max2), fscale);
- if(max2 <= fscale*fscale) {
- f->flags |= (GEXFF_DONE | GEXFF_DRAWCURVE);
- f->vectlen = f->sublen;
- free(dots);
- return;
- }
- }
-
- if( !outfront && !outend && f->symge != 0) {
- /* a special case: try a circle segment as an approximation */
- double lenfront, lenend, len, maxlen;
-
- /* coefficient for a Bezier approximation of a circle */
-#define CIRCLE_FRAC 0.55
-
- a1 = (ge->ix3 == ge->bkwd->ix3); /* get the axis along the front */
- a2 = !a1; /* axis along the end */
-
- lenfront = fixfront[a1] - limfront[a1];
- lenend = fixend[a2] - limend[a2];
- if(fabs(lenfront) < fabs(lenend))
- len = fabs(lenfront);
- else
- len = fabs(lenend);
-
- /* make it go close to the round shape */
- switch(f->sublen) {
- case 2:
- maxlen = fscale;
- break;
- case 4:
- case 6:
- maxlen = fscale * 2.;
- break;
- default:
- maxlen = fscale * abs(ge->frwd->frwd->ipoints[a1][2]
- - ge->ipoints[a1][2]);
- break;
- }
- if(len > maxlen)
- len = maxlen;
-
- mvfront[a1] = fixfront[a1] - fsign(lenfront) * len;
- mvfront[a2] = limfront[a2];
- mvend[a2] = fixend[a2] - fsign(lenend) * len;
- mvend[a1] = limend[a1];
-
- for(i=0; i<2; i++) {
- f->vect[0][i] = mvfront[i];
- f->vect[3][i] = mvend[i];
- }
- f->vect[1][a1] = mvfront[a1] + CIRCLE_FRAC*(mvend[a1]-mvfront[a1]);
- f->vect[1][a2] = mvfront[a2];
- f->vect[2][a1] = mvend[a1];
- f->vect[2][a2] = mvend[a2] + CIRCLE_FRAC*(mvfront[a2]-mvend[a2]);
-
- avg2 = fdotcurvdist2(f->vect, dots, ndots, &max2);
- fprintf(stderr, " avg=%g max=%g fscale=%g\n", sqrt(avg2), sqrt(max2), fscale);
- if(max2 <= fscale*fscale) {
- f->flags |= (GEXFF_DONE | GEXFF_DRAWCURVE);
- f->vectlen = f->sublen;
- free(dots);
- return;
- }
-#undef CIRCLE_FRAC
- }
- for(i=0; i<2; i++) {
- f->vect[0][i] = limfront[i];
- f->vect[1][i] = fixfront[i];
- f->vect[2][i] = fixend[i];
- f->vect[3][i] = limend[i];
- }
- usedots = dots;
- if(outfront) {
- usedots++; ndots--;
- }
- if(outend)
- ndots--;
- if( fcrossrayscv(f->vect, NULL, NULL) == 0) {
- fprintf(stderr, "**** Internal error: rays must cross but don't at %p-%p\n",
- ge, gel);
- fprintf(stderr, " (%g, %g) (%g, %g) (%g, %g) (%g, %g)\n",
- limfront[0], limfront[1],
- fixfront[0], fixfront[1],
- fixend[0], fixend[1],
- limend[0], limend[1]
- );
- dumppaths(g, NULL, NULL);
- exit(1);
- } else {
- if(ndots != 0)
- fapproxcurve(f->vect, usedots, ndots);
- f->flags |= (GEXFF_DONE | GEXFF_DRAWCURVE);
- f->vectlen = f->sublen;
- }
- free(dots);
-}
-
-/*
- * Produce an outline from a bitmap.
- * scale - factor to scale the sizes
- * bmap - array of dots by lines, xsz * ysz
- * xoff, yoff - offset of the bitmap's lower left corner
- * from the logical position (0,0)
- */
-
-void
-bmp_outline(
- GLYPH *g,
- int scale,
- char *bmap,
- int xsz,
- int ysz,
- int xoff,
- int yoff
-)
-{
- char *hlm, *vlm; /* arrays of the limits of outlines */
- char *amp; /* map of ambiguous points */
- int x, y;
- char *ip, *op;
- double fscale;
-
- if(xsz==0 || ysz==0)
- return;
-
-#ifdef USE_AUTOTRACE
- if(use_autotrace) {
- autotraced_bmp_outline(g, scale, bmap, xsz, ysz, xoff, yoff);
- return;
- }
-#endif /*USE_AUTOTRACE*/
-
- fscale = (double)scale;
- g->flags &= ~GF_FLOAT; /* build it as int first */
-
- if(!warnedhints) {
- warnedhints = 1;
- if(hints && subhints) {
- WARNING_2 fprintf(stderr,
- "Use of hint substitution on bitmap fonts is not recommended\n");
- }
- }
-
-#if 0
- printbmap(bmap, xsz, ysz, xoff, yoff);
-#endif
-
- /* now find the outlines */
- hlm=calloc( xsz, ysz+1 ); /* horizontal limits */
- vlm=calloc( xsz+1, ysz ); /* vertical limits */
- amp=calloc( xsz, ysz ); /* ambiguous points */
-
- if(hlm==0 || vlm==0 || amp==0) {
- fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__);
- exit(255);
- }
-
- /*
- * hlm and vlm represent a grid of horisontal and
- * vertical lines. Each pixel is surrounded by the grid
- * from all the sides. The values of [hv]lm mark the
- * parts of grid where the pixel value switches from white
- * to black and back.
- */
-
- /* find the horizontal limits */
- ip=bmap; op=hlm;
- /* 1st row */
- for(x=0; x<xsz; x++) {
- if(ip[x])
- op[x]=L_ON;
- }
- ip+=xsz; op+=xsz;
- /* internal rows */
- for(y=1; y<ysz; y++) {
- for(x=0; x<xsz; x++) {
- if(ip[x]) {
- if(!ip[x-xsz])
- op[x]=L_ON;
- } else {
- if(ip[x-xsz])
- op[x]=L_OFF;
- }
- }
- ip+=xsz; op+=xsz;
- }
-
- /* last row */
- ip-=xsz;
- for(x=0; x<xsz; x++) {
- if(ip[x])
- op[x]=L_OFF;
- }
-
- /* find the vertical limits */
- ip=bmap; op=vlm;
- for(y=0; y<ysz; y++) {
- if(ip[0])
- op[0]=L_ON;
- for(x=1; x<xsz; x++) {
- if(ip[x]) {
- if(!ip[x-1])
- op[x]=L_ON;
- } else {
- if(ip[x-1])
- op[x]=L_OFF;
- }
- }
- if(ip[xsz-1])
- op[xsz]=L_OFF;
- ip+=xsz; op+=xsz+1;
- }
-
- /*
- * Ambiguous points are the nodes of the grids
- * that are between two white and two black pixels
- * located in a checkerboard style. Actually
- * there are only two patterns that may be
- * around an ambiguous point:
- *
- * X|. .|X
- * -*- -*-
- * .|X X|.
- *
- * where "|" and "-" represent the grid (respectively members
- * of vlm and hlm), "*" represents an ambiguous point
- * and "X" and "." represent black and white pixels.
- *
- * If these sample pattern occur in the lower left corner
- * of the bitmap then this ambiguous point will be
- * located at amp[1][1] or in other words amp[1*xsz+1].
- *
- * These points are named "ambiguous" because it's
- * not easy to guess what did the font creator mean
- * at these points. So we are going to treat them
- * specially, doing no aggressive smoothing.
- */
-
- /* find the ambiguous points */
- for(y=ysz-1; y>0; y--)
- for(x=xsz-1; x>0; x--) {
- if(bmap[y*xsz+x]) {
- if( !bmap[y*xsz+x-1] && !bmap[y*xsz-xsz+x] && bmap[y*xsz-xsz+x-1] )
- amp[y*xsz+x]=1;
- } else {
- if( bmap[y*xsz+x-1] && bmap[y*xsz-xsz+x] && !bmap[y*xsz-xsz+x-1] )
- amp[y*xsz+x]=1;
- }
- }
-
-#if 0
- printlimits(hlm, vlm, amp, xsz, ysz);
-#endif
-
- /* generate the vectored (stepping) outline */
-
- while(1) {
- int found = 0;
- int outer; /* flag: this is an outer contour */
- int hor, newhor; /* flag: the current contour direction is horizontal */
- int dir; /* previous direction of the coordinate, 1 - L_ON, 0 - L_OFF */
- int startx, starty; /* start of a contour */
- int firstx, firsty; /* start of the current line */
- int newx, newy; /* new coordinates to try */
- char *lm, val;
- int maxx, maxy, xor;
-
- for(y=ysz; !found && y>0; y--)
- for(x=0; x<xsz; x++)
- if(hlm[y*xsz+x] > L_NONE)
- goto foundcontour;
- break; /* have no contours left */
-
- foundcontour:
- ig_rmoveto(g, x+xoff, y+yoff); /* intermediate as int */
-
- startx = firstx = x;
- starty = firsty = y;
-
- if(hlm[y*xsz+x] == L_OFF) {
- outer = 1; dir = 0;
- hlm[y*xsz+x] = -hlm[y*xsz+x]; /* mark as seen */
- hor = 1; x++;
- } else {
- outer = 0; dir = 0;
- hor = 0; y--;
- vlm[y*(xsz+1)+x] = -vlm[y*(xsz+1)+x]; /* mark as seen */
- }
-
- while(x!=startx || y!=starty) {
-#if 0
- printf("trace (%d, %d) outer=%d hor=%d dir=%d\n", x, y, outer, hor, dir);
-#endif
-
- /* initialization common for try1 and try2 */
- if(hor) {
- lm = vlm; maxx = xsz+1; maxy = ysz; newhor = 0;
- } else {
- lm = hlm; maxx = xsz; maxy = ysz+1; newhor = 1;
- }
- xor = (outer ^ hor ^ dir);
-
- try1:
- /* first we try to change axis, to keep the
- * contour as long as possible
- */
-
- newx = x; newy = y;
- if(!hor && (!outer ^ dir))
- newx--;
- if(hor && (!outer ^ dir))
- newy--;
-
- if(newx < 0 || newx >= maxx || newy < 0 || newy >= maxy)
- goto try2;
-
- if(!xor)
- val = L_ON;
- else
- val = L_OFF;
-#if 0
- printf("try 1, want %d have %d at %c(%d, %d)\n", val, lm[newy*maxx + newx],
- (newhor ? 'h':'v'), newx, newy);
-#endif
- if( lm[newy*maxx + newx] == val )
- goto gotit;
-
- try2:
- /* try to change the axis anyway */
-
- newx = x; newy = y;
- if(!hor && (outer ^ dir))
- newx--;
- if(hor && (outer ^ dir))
- newy--;
-
- if(newx < 0 || newx >= maxx || newy < 0 || newy >= maxy)
- goto try3;
-
- if(xor)
- val = L_ON;
- else
- val = L_OFF;
-#if 0
- printf("try 2, want %d have %d at %c(%d, %d)\n", val, lm[newy*maxx + newx],
- (newhor ? 'h':'v'), newx, newy);
-#endif
- if( lm[newy*maxx + newx] == val )
- goto gotit;
-
- try3:
- /* try to continue in the old direction */
-
- if(hor) {
- lm = hlm; maxx = xsz; maxy = ysz+1;
- } else {
- lm = vlm; maxx = xsz+1; maxy = ysz;
- }
- newhor = hor;
- newx = x; newy = y;
- if(hor && dir)
- newx--;
- if(!hor && !dir)
- newy--;
-
- if(newx < 0 || newx >= maxx || newy < 0 || newy >= maxy)
- goto badtry;
-
- if(dir)
- val = L_ON;
- else
- val = L_OFF;
-#if 0
- printf("try 3, want %d have %d at %c(%d, %d)\n", val, lm[newy*maxx + newx],
- (newhor ? 'h':'v'), newx, newy);
-#endif
- if( lm[newy*maxx + newx] == val )
- goto gotit;
-
- badtry:
- fprintf(stderr, "**** Internal error in the contour detection code at (%d, %d)\n", x, y);
- fprintf(stderr, "glyph='%s' outer=%d hor=%d dir=%d\n", g->name, outer, hor, dir);
- fflush(stdout);
- exit(1);
-
- gotit:
- if(hor != newhor) { /* changed direction, end the previous line */
- ig_rlineto(g, x+xoff, y+yoff); /* intermediate as int */
- firstx = x; firsty = y;
- }
- lm[newy*maxx + newx] = -lm[newy*maxx + newx];
- hor = newhor;
- dir = (val == L_ON);
- if(newhor)
- x -= (dir<<1)-1;
- else
- y += (dir<<1)-1;
- }
-#if 0
- printf("trace (%d, %d) outer=%d hor=%d dir=%d\n", x, y, outer, hor, dir);
-#endif
- ig_rlineto(g, x+xoff, y+yoff); /* intermediate as int */
- g_closepath(g);
- }
-
-
- /* try to vectorize the curves and sloped lines in the bitmap */
- if(vectorize) {
- GENTRY *ge, *pge, *cge, *loopge;
- int i;
- int skip;
-
- dumppaths(g, NULL, NULL);
-
- /* allocate the extensions */
- for(cge=g->entries; cge!=0; cge=cge->next) {
- cge->ext = calloc(1, sizeof(GEX_FRAG) );
- if(cge->ext == 0) {
- fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__);
- exit(255);
- }
- }
-
- for(cge=g->entries; cge!=0; cge=cge->next) {
- if(cge->type != GE_MOVE)
- continue;
-
- /* we've found the beginning of a contour */
- {
- int d, vert, count, stepmore, delaystop;
- int vdir, hdir, fullvdir, fullhdir, len;
- int dx, dy, lastdx, lastdy;
- int k1, k2, reversal, smooth, good;
- int line[2 /*H,V*/], maxlen[2 /*H,V*/], minlen[2 /*H,V*/];
- GENTRY **age; /* array of gentries in a contour */
- int clen; /* contour length, size of ths array */
- int i, j;
- GEX_FRAG *f;
-
- /* we know that all the contours start at the top-left corner,
- * so at most it might be before/after the last element of
- * the last/first fragment
- */
-
- ge = cge->next;
- pge = ge->bkwd;
- if(ge->ix3 == pge->ix3) { /* a vertical line */
- /* we want to start always from a horizontal line because
- * then we always start from top and that is quaranteed to be a
- * fragment boundary, so move the start point of the contour
- */
- pge->prev->next = pge->next;
- pge->next->prev = pge->prev;
- cge->next = pge;
- pge->prev = cge;
- pge->next = ge;
- ge->prev = pge;
- ge = pge; pge = ge->bkwd;
- cge->ix3 = pge->ix3; cge->iy3 = pge->iy3;
- }
-
- /* fill the array of gentries */
- clen = 1;
- for(ge = cge->next->frwd; ge != cge->next; ge = ge->frwd)
- clen++;
- age = (GENTRY **)malloc(sizeof(*age) * clen);
- ge = cge->next;
- count = 0;
- do {
- age[count] = ge;
- X_FRAG(ge)->aidx = count++;
-
- /* and by the way find the extremums */
- for(i=0; i<2; i++) {
- if( isign(ge->frwd->ipoints[i][2] - ge->ipoints[i][2])
- * isign(ge->bkwd->bkwd->ipoints[i][2] - ge->bkwd->ipoints[i][2]) == 1) {
- X_FRAG(ge)->flags |= GEXFF_EXTR;
- fprintf(stderr, " %s extremum at %p\n", (i?"vert":"hor"), ge);
- }
- if(abs(ge->ipoints[i][2] - ge->bkwd->ipoints[i][2]) > 1)
- X_FRAG(ge)->flags |= GEXFF_LONG;
- }
-
- ge = ge->frwd;
- } while(ge != cge->next);
-
- /* Find the convex and concave fragments, defined as:
- * convex (clockwise): dy/dx <= dy0/dx0,
- * or a reversal: dy/dx == - dy0/dx0 && abs(dxthis) == 1 && dy/dx > 0
- * concave (counter-clockwise): dy/dx >= dy0/dx0,
- * or a reversal: dy/dx == - dy0/dx0 && abs(dxthis) == 1 && dy/dx < 0
- *
- * Where dx and dy are measured between the end of this gentry
- * and the start of the previous one (dx0 and dy0 are the same
- * thing calculated for the previous gentry and its previous one),
- * dxthis is between the end and begginning of this gentry.
- *
- * A reversal is a situation when the curve changes its direction
- * along the x axis, so it passes through a momentary vertical
- * direction.
- */
- for(d = GEXFI_CONVEX; d<= GEXFI_CONCAVE; d++) {
- ge = cge->next;
- pge = ge->bkwd; /* the beginning of the fragment */
- count = 1;
- lastdx = pge->ix3 - pge->bkwd->bkwd->ix3;
- lastdy = pge->iy3 - pge->bkwd->bkwd->iy3;
-
-#define CHKCURVCONN(ge, msg) do { \
- dx = (ge)->ix3 - (ge)->bkwd->bkwd->ix3; \
- dy = (ge)->iy3 - (ge)->bkwd->bkwd->iy3; \
- if(0 && msg) { \
- fprintf(stderr, " %p: dx=%d dy=%d dx0=%d dy0=%d ", \
- (ge), dx, dy, lastdx, lastdy); \
- } \
- k1 = X_FRAG(ge)->flags; \
- k2 = X_FRAG((ge)->bkwd)->flags; \
- if(0 && msg) { \
- fprintf(stderr, "fl=%c%c%c%c ", \
- (k1 & GEXFF_EXTR) ? 'X' : '-', \
- (k1 & GEXFF_LONG) ? 'L' : '-', \
- (k2 & GEXFF_EXTR) ? 'X' : '-', \
- (k2 & GEXFF_LONG) ? 'L' : '-' \
- ); \
- } \
- if( (k1 & GEXFF_EXTR) && (k2 & GEXFF_LONG) \
- || (k2 & GEXFF_EXTR) && (k1 & GEXFF_LONG) ) { \
- smooth = 0; \
- good = reversal = -1; /* for debugging */ \
- } else { \
- k1 = dy * lastdx; \
- k2 = lastdy * dx; \
- smooth = (abs(dx)==1 || abs(dy)==1); \
- good = (k1 - k2)*gxf_cvk[d] >= 0; \
- if(smooth && !good) { \
- reversal = (k1 == -k2 && abs((ge)->ix3 - (ge)->bkwd->ix3)==1 \
- && dy*dx*gxf_cvk[d] < 0); \
- } else \
- reversal = 0; \
- } \
- if(0 && msg) { \
- fprintf(stderr, "k1=%d k2=%d pge=%p count=%d %s good=%d rev=%d\n", \
- k1, k2, pge, count, gxf_name[d], good, reversal); \
- } \
- } while(0)
-
- do {
- CHKCURVCONN(ge, 1);
-
- if(smooth && (good || reversal) )
- count++;
- else {
- /* can't continue */
-#if 0
- if(count >= 4) { /* worth remembering */
- fprintf(stderr, " %s frag %p-%p count=%d\n", gxf_name[d], pge, ge->bkwd, count);
- }
-#endif
- X_FRAG(pge)->len[d] = count;
- if(smooth) {
- pge = ge->bkwd;
- count = 2;
- } else {
- pge = ge;
- count = 1;
- }
- }
- lastdx = dx; lastdy = dy;
- ge = ge->frwd;
- } while(ge != cge->next);
-
- /* see if we can connect the last fragment to the first */
- CHKCURVCONN(ge, 1);
-
- if(smooth && (good || reversal) ) {
- /* -1 to avoid ge->bkwd being counted twice */
- if( X_FRAG(ge->bkwd)->len[d] >= 2 )
- count += X_FRAG(ge->bkwd)->len[d] - 1;
- else if(count == clen+1) {
- /* we are joining a circular (closed) curve, check whether it
- * can be joined at any point or whether it has a discontinuity
- * at the point where we join it now
- */
- lastdx = dx; lastdy = dy;
- CHKCURVCONN(ge->frwd, 0);
-
- if(smooth && (good || reversal) ) {
- /* yes, the curve is truly a circular one and can be
- * joined at any point
- */
-
-#if 0
- fprintf(stderr, " found a circular joint point at %p\n", pge);
-#endif
- /* make sure that in a circular fragment we start from an extremum */
- while( ! (X_FRAG(pge)->flags & GEXFF_EXTR) )
- pge = pge->frwd;
- X_FRAG(pge)->flags |= GEXFF_CIRC;
- }
- }
-#if 0
- fprintf(stderr, " %s joined %p to %p count=%d bk_count=%d\n", gxf_name[d], pge, ge->bkwd,
- count, X_FRAG(ge->bkwd)->len[d] );
-#endif
- X_FRAG(ge->bkwd)->len[d] = 0;
- }
- X_FRAG(pge)->len[d] = count;
-#if 0
- if(count >= 4) { /* worth remembering */
- fprintf(stderr, " %s last frag %p-%p count=%d\n", gxf_name[d], pge, ge->bkwd, count);
- }
-#endif
-#undef CHKCURVCONN
-
- /* do postprocessing */
- ge = cge->next;
- do {
- f = X_FRAG(ge);
- len = f->len[d];
-#if 0
- fprintf(stderr, " %p %s len=%d clen=%d\n", ge, gxf_name[d], len, clen);
-#endif
- if(len < 3) /* get rid of the fragments that are too short */
- f->len[d] = 0;
- else if(len == 3) {
- /* _
- * drop the |_| - shaped fragments, leave alone the _| - shaped
- * (and even those only if not too short in pixels),
- * those left alone are further filtered later
- */
- k1 = (ge->ix3 == ge->bkwd->ix3); /* axis of the start */
- if(isign(ge->ipoints[k1][2] - ge->bkwd->ipoints[k1][2])
- != isign(ge->frwd->ipoints[k1][2] - ge->frwd->frwd->ipoints[k1][2])
- && abs(ge->frwd->frwd->ipoints[k1][2] - ge->bkwd->ipoints[k1][2]) > 2) {
-#if 0
- fprintf(stderr, " %s frag %p count=%d good shape\n",
- gxf_name[d], ge, count);
-#endif
- } else
- f->len[d] = 0;
- } else if(len == clen+1)
- break; /* a closed fragment, nothing else interesting */
- else { /* only for open fragments */
- GENTRY *gem, *gex, *gei, *ges;
-
- ges = ge; /* the start entry */
- gem = age[(f->aidx + f->len[d])%clen]; /* entry past the end of the fragment */
-
- gei = ge->frwd;
- if( (ge->ix3 == ge->bkwd->ix3) /* vert */
- ^ (isign(ge->bkwd->ix3 - gei->ix3)==isign(ge->bkwd->iy3 - gei->iy3))
- ^ !(d == GEXFI_CONVEX) /* counter-clockwise */ ) {
-
-#if 0
- fprintf(stderr, " %p: %s potential spurious start\n", ge, gxf_name[d]);
-#endif
- /* the beginning may be a spurious entry */
-
- gex = 0; /* the extremum closest to the beginning - to be found */
- for(gei = ge->frwd; gei != gem; gei = gei->frwd) {
- if(X_FRAG(gei)->flags & GEXFF_EXTR) {
- gex = gei;
- break;
- }
- }
- if(gex == 0)
- gex = gem->bkwd;
-
- /* A special case: ignore the spurious ends on small curves that
- * either enclose an 1-pixel-wide extremum or are 1-pixel deep.
- * Any 5-or-less-pixel-long curve with extremum 2 steps away
- * qualifies for that.
- */
-
- if(len <= 5 && gex == ge->frwd->frwd) {
- good = 0;
-#if 0
- fprintf(stderr, " E");
-#endif
- } else {
- good = 1; /* assume that ge is not spurious */
-
- /* gei goes backwards, gex goes forwards from the extremum */
- gei = gex;
- /* i is the symmetry axis, j is the other axis (X=0 Y=1) */
- i = (gex->ix3 != gex->bkwd->ix3);
- j = !i;
- for( ; gei!=ge && gex!=gem; gei=gei->bkwd, gex=gex->frwd) {
- if( gei->bkwd->ipoints[i][2] != gex->ipoints[i][2]
- || gei->bkwd->ipoints[j][2] - gei->ipoints[j][2]
- != gex->bkwd->ipoints[j][2] - gex->ipoints[j][2]
- ) {
- good = 0; /* no symmetry - must be spurious */
-#if 0
- fprintf(stderr, " M(%p,%p)(%d %d,%d)(%d %d,%d)",
- gei, gex,
- i, gei->bkwd->ipoints[i][2], gex->ipoints[i][2],
- j, gei->bkwd->ipoints[j][2] - gei->ipoints[j][2],
- gex->bkwd->ipoints[j][2] - gex->ipoints[j][2] );
-#endif
- break;
- }
- }
- if(gex == gem) { /* oops, the other side is too short */
- good = 0;
-#if 0
- fprintf(stderr, " X");
-#endif
- }
- if(good && gei == ge) {
- if( isign(gei->bkwd->ipoints[j][2] - gei->ipoints[j][2])
- != isign(gex->bkwd->ipoints[j][2] - gex->ipoints[j][2]) ) {
- good = 0; /* oops, goes into another direction */
-#if 0
- fprintf(stderr, " D");
-#endif
- }
- }
- }
- if(!good) { /* it is spurious, drop it */
-#if 0
- fprintf(stderr, " %p: %s spurious start\n", ge, gxf_name[d]);
-#endif
- f->len[d] = 0;
- ges = ge->frwd;
- len--;
- X_FRAG(ges)->len[d] = len;
- }
- }
-
- gei = gem->bkwd->bkwd->bkwd;
- if( (gem->ix3 != gem->bkwd->ix3) /* gem->bkwd is vert */
- ^ (isign(gem->bkwd->ix3 - gei->ix3)==isign(gem->bkwd->iy3 - gei->iy3))
- ^ (d == GEXFI_CONVEX) /* clockwise */ ) {
-
-#if 0
- fprintf(stderr, " %p: %s potential spurious end\n", gem->bkwd, gxf_name[d]);
-#endif
- /* the end may be a spurious entry */
-
- gex = 0; /* the extremum closest to the end - to be found */
- for(gei = gem->bkwd->bkwd; gei != ges->bkwd; gei = gei->bkwd) {
- if(X_FRAG(gei)->flags & GEXFF_EXTR) {
- gex = gei;
- break;
- }
- }
- if(gex == 0)
- gex = ges;
-
- good = 1; /* assume that gem->bkwd is not spurious */
- /* gei goes backwards, gex goes forwards from the extremum */
- gei = gex;
- /* i is the symmetry axis, j is the other axis (X=0 Y=1) */
- i = (gex->ix3 != gex->bkwd->ix3);
- j = !i;
- for( ; gei!=ges->bkwd && gex!=gem->bkwd; gei=gei->bkwd, gex=gex->frwd) {
- if( gei->bkwd->ipoints[i][2] != gex->ipoints[i][2]
- || gei->bkwd->ipoints[j][2] - gei->ipoints[j][2]
- != gex->bkwd->ipoints[j][2] - gex->ipoints[j][2]
- ) {
- good = 0; /* no symmetry - must be spurious */
-#if 0
- fprintf(stderr, " M(%p,%p)(%d %d,%d)(%d %d,%d)",
- gei, gex,
- i, gei->bkwd->ipoints[i][2], gex->ipoints[i][2],
- j, gei->bkwd->ipoints[j][2] - gei->ipoints[j][2],
- gex->bkwd->ipoints[j][2] - gex->ipoints[j][2] );
-#endif
- break;
- }
- }
- if(gei == ges->bkwd) { /* oops, the other side is too short */
- good = 0;
-#if 0
- fprintf(stderr, " X");
-#endif
- }
- if(good && gex == gem->bkwd) {
- if( isign(gei->bkwd->ipoints[j][2] - gei->ipoints[j][2])
- != isign(gex->bkwd->ipoints[j][2] - gex->ipoints[j][2]) ) {
- good = 0; /* oops, goes into another direction */
-#if 0
- fprintf(stderr, " D");
-#endif
- }
- }
- if(!good) { /* it is spurious, drop it */
-#if 0
- fprintf(stderr, " %p: %s spurious end\n", gem->bkwd, gxf_name[d]);
-#endif
- X_FRAG(ges)->len[d] = --len;
- }
- }
- if(len < 4) {
- X_FRAG(ges)->len[d] = 0;
-#if 0
- fprintf(stderr, " %p: %s frag discarded, too small now\n", ge, gxf_name[d]);
-#endif
- }
- if(ges != ge) {
- if(ges == cge->next)
- break; /* went around the loop */
- else {
- ge = ges->frwd; /* don't look at this fragment twice */
- continue;
- }
- }
- }
-
- ge = ge->frwd;
- } while(ge != cge->next);
- }
-
- /* Find the straight line fragments.
- * Even though the lines are sloped, they are called
- * "vertical" or "horizontal" according to their longer
- * dimension. All the steps in the shother dimension must
- * be 1 pixel long, all the steps in the longer dimension
- * must be within the difference of 1 pixel.
- */
- for(d = GEXFI_LINE; d<= GEXFI_EXACTLINE; d++) {
- ge = cge->next;
- pge = ge->bkwd; /* the beginning of the fragment */
- count = 1;
- delaystop = 0;
- do {
- int h;
-
- stepmore = 0;
- hdir = isign(ge->ix3 - ge->bkwd->ix3);
- vdir = isign(ge->iy3 - ge->bkwd->iy3);
- vert = (hdir == 0);
- if(count==1) {
- /* at this point pge==ge->bkwd */
- /* account for the previous gentry, which was !vert */
- if(!vert) { /* prev was vertical */
- maxlen[0] = minlen[0] = 0;
- maxlen[1] = minlen[1] = abs(pge->iy3 - pge->bkwd->iy3);
- line[0] = (maxlen[1] == 1);
- line[1] = 1;
- fullhdir = hdir;
- fullvdir = isign(pge->iy3 - pge->bkwd->iy3);
- } else {
- maxlen[0] = minlen[0] = abs(pge->ix3 - pge->bkwd->ix3);
- maxlen[1] = minlen[1] = 0;
- line[0] = 1;
- line[1] = (maxlen[0] == 1);
- fullhdir = isign(pge->ix3 - pge->bkwd->ix3);
- fullvdir = vdir;
- }
- }
- h = line[0]; /* remember the prevalent direction */
-#if 0
- fprintf(stderr, " %p: v=%d(%d) h=%d(%d) vl(%d,%d,%d) hl=(%d,%d,%d) %s count=%d ",
- ge, vdir, fullvdir, hdir, fullhdir,
- line[1], minlen[1], maxlen[1],
- line[0], minlen[0], maxlen[0],
- gxf_name[d], count);
-#endif
- if(vert) {
- if(vdir != fullvdir)
- line[0] = line[1] = 0;
- len = abs(ge->iy3 - ge->bkwd->iy3);
- } else {
- if(hdir != fullhdir)
- line[0] = line[1] = 0;
- len = abs(ge->ix3 - ge->bkwd->ix3);
- }
-#if 0
- fprintf(stderr, "len=%d\n", len);
-#endif
- if(len != 1) /* this is not a continuation in the short dimension */
- line[!vert] = 0;
-
- /* can it be a continuation in the long dimension ? */
- if( line[vert] ) {
- if(maxlen[vert]==0)
- maxlen[vert] = minlen[vert] = len;
- else if(maxlen[vert]==minlen[vert]) {
- if(d == GEXFI_EXACTLINE) {
- if(len != maxlen[vert])
- line[vert] = 0; /* it can't */
- } else if(len < maxlen[vert]) {
- if(len < minlen[vert]-1)
- line[vert] = 0; /* it can't */
- else
- minlen[vert] = len;
- } else {
- if(len > maxlen[vert]+1)
- line[vert] = 0; /* it can't */
- else
- maxlen[vert] = len;
- }
- } else if(len < minlen[vert] || len > maxlen[vert])
- line[vert] = 0; /* it can't */
- }
-
- if(line[0] == 0 && line[1] == 0) {
-#if 0
- if(count >= 3)
- fprintf(stderr, " %s frag %p-%p count=%d\n", gxf_name[d], pge, ge->bkwd, count);
-#endif
- X_FRAG(pge)->len[d] = count;
- if(d == GEXFI_EXACTLINE && h) {
- X_FRAG(pge)->flags |= GEXFF_HLINE;
- }
- if(count == 1)
- pge = ge;
- else {
- stepmore = 1; /* may reconsider the 1st gentry */
- pge = ge = ge->bkwd;
- count = 1;
- }
- } else
- count++;
-
- ge = ge->frwd;
- if(ge == cge->next && !stepmore)
- delaystop = 1; /* consider the first gentry again */
- } while(stepmore || ge != cge->next ^ delaystop);
- /* see if there is an unfinished line left */
- if(count != 1) {
-#if 0
- if(count >= 3)
- fprintf(stderr, " %s frag %p-%p count=%d\n", gxf_name[d], pge, ge->bkwd, count);
-#endif
- X_FRAG(ge->bkwd->bkwd)->len[d] = 0;
- X_FRAG(pge)->len[d] = count;
- }
- }
-
- /* do postprocessing of the lines */
-#if 0
- fprintf(stderr, "Line postprocessing\n");
- gex_dump_contour(cge->next, clen);
-#endif
-
- /* the non-exact line frags are related to exact line frags sort
- * of like to individual gentries: two kinds of exact frags
- * must be interleaved, with one kind having the size of 3
- * and the other kind having the size varying within +-2.
- */
-
- ge = cge->next;
- do {
- GEX_FRAG *pf, *lastf1, *lastf2;
- int len1, len2, fraglen;
-
- f = X_FRAG(ge);
-
- fraglen = f->len[GEXFI_LINE];
- if(fraglen >= 4) {
-
- vert = 0; /* vert is a pseudo-directon */
- line[0] = line[1] = 1;
- maxlen[0] = minlen[0] = maxlen[1] = minlen[1] = 0;
- lastf2 = lastf1 = f;
- len2 = len1 = 0;
- for(pge = ge, i = 1; i < fraglen; i++, pge=pge->frwd) {
- pf = X_FRAG(pge);
- len = pf->len[GEXFI_EXACTLINE];
-#if 0
- fprintf(stderr, " pge=%p i=%d of %d ge=%p exLen=%d\n", pge, i,
- f->len[GEXFI_LINE], ge, len);
-#endif
- len1++; len2++;
- if(len==0) {
- continue;
- }
- vert = !vert; /* alternate the pseudo-direction */
- if(len > 3)
- line[!vert] = 0;
- if(maxlen[vert] == 0)
- maxlen[vert] = minlen[vert] = len;
- else if(maxlen[vert]-2 >= len && minlen[vert]+2 <= len) {
- if(len > maxlen[vert])
- maxlen[vert] = len;
- else if(len < minlen[vert])
- minlen[vert] = len;
- } else
- line[vert] = 0;
- if(line[0] == 0 && line[1] == 0) {
-#if 0
- fprintf(stderr, " Line breaks at %p %c(%d, %d) %c(%d, %d) len=%d fl=%d l2=%d l1=%d\n",
- pge, (!vert)?'*':' ', minlen[0], maxlen[0],
- vert?'*':' ', minlen[1], maxlen[1], len, fraglen, len2, len1);
-#endif
- if(lastf2 != lastf1) {
- lastf2->len[GEXFI_LINE] = len2-len1;
- }
- lastf1->len[GEXFI_LINE] = len1+1;
- pf->len[GEXFI_LINE] = fraglen+1 - i;
- gex_dump_contour(pge, clen);
-
- /* continue with the line */
- vert = 0; /* vert is a pseudo-directon */
- line[0] = line[1] = 1;
- maxlen[0] = minlen[0] = maxlen[1] = minlen[1] = 0;
- lastf2 = lastf1 = f;
- len2 = len1 = 0;
- } else {
- lastf1 = pf;
- len1 = 0;
- }
- }
- }
-
- ge = ge->frwd;
- } while(ge != cge->next);
-#if 0
- gex_dump_contour(cge->next, clen);
-#endif
-
- ge = cge->next;
- do {
- f = X_FRAG(ge);
-
- if(f->len[GEXFI_LINE] >= 4) {
- len = f->len[GEXFI_EXACTLINE];
- /* if a non-exact line covers precisely two exact lines,
- * split it
- */
- if(len > 0 && f->len[GEXFI_LINE] > len+1) {
- GEX_FRAG *pf;
- pge = age[(f->aidx + len - 1)%clen]; /* last gentry of exact line */
- pf = X_FRAG(pge);
- if(f->len[GEXFI_LINE] + 1 == len + pf->len[GEXFI_EXACTLINE]) {
- f->len[GEXFI_LINE] = len;
- f->flags |= GEXFF_SPLIT;
- pf->len[GEXFI_LINE] = pf->len[GEXFI_EXACTLINE];
- pf->flags |= GEXFF_SPLIT;
- }
- }
- }
-
- ge = ge->frwd;
- } while(ge != cge->next);
- ge = cge->next;
- do {
- f = X_FRAG(ge);
-
- /* too small lines are of no interest */
- if( (f->flags & GEXFF_SPLIT)==0 && f->len[GEXFI_LINE] < 4)
- f->len[GEXFI_LINE] = 0;
-
- len = f->len[GEXFI_EXACTLINE];
- /* too small exact lines are of no interest */
- if(len < 3) /* exact lines may be shorter */
- f->len[GEXFI_EXACTLINE] = 0;
- /* get rid of inexact additions to the end of the exact lines */
- else if(f->len[GEXFI_LINE] == len+1)
- f->len[GEXFI_LINE] = len;
- /* same at the beginning */
- else {
- int diff = X_FRAG(ge->bkwd)->len[GEXFI_LINE] - len;
-
- if(diff == 1 || diff == 2) {
- X_FRAG(ge->bkwd)->len[GEXFI_LINE] = 0;
- f->len[GEXFI_LINE] = len;
- }
- }
-
- ge = ge->frwd;
- } while(ge != cge->next);
-#if 0
- gex_dump_contour(cge->next, clen);
-#endif
-
- gex_calc_lenback(cge->next, clen); /* prepare data */
-
- /* resolve conflicts between lines and curves */
-
- /*
- * the short (3-gentry) curve frags must have one of the ends
- * coinciding with another curve frag of the same type
- */
-
- for(d = GEXFI_CONVEX; d<= GEXFI_CONCAVE; d++) {
- ge = cge->next;
- do {
- f = X_FRAG(ge);
-
- if(f->len[d] == 3) {
- pge = age[(f->aidx + 2)%clen]; /* last gentry of this frag */
- if(f->lenback[d] == 0 && X_FRAG(pge)->len[d] == 0) {
- fprintf(stderr, " discarded small %s at %p-%p\n", gxf_name[d], ge, pge);
- f->len[d] = 0;
- X_FRAG(ge->frwd)->lenback[d] = 0;
- X_FRAG(ge->frwd->frwd)->lenback[d] = 0;
- }
- }
- ge = ge->frwd;
- } while(ge != cge->next);
- }
-
- /*
- * longer exact lines take priority over curves, shorter lines
- * and inexact lines are resolved with convex/concave conflicts
- */
- ge = cge->next;
- do {
- f = X_FRAG(ge);
-
- len = f->len[GEXFI_EXACTLINE];
-
- if(len < 6) { /* line is short */
- ge = ge->frwd;
- continue;
- }
-
- fprintf(stderr, " line at %p len=%d\n", ge, f->len[GEXFI_EXACTLINE]);
- for(d = GEXFI_CONVEX; d<= GEXFI_CONCAVE; d++) {
- GEX_FRAG *pf;
-
- /* check if we overlap the end of some fragment */
- if(f->lenback[d]) {
- /* chop off the end of conflicting fragment */
- len = f->lenback[d];
- pge = age[(f->aidx + clen - len)%clen];
- pf = X_FRAG(pge);
- if(pf->len[d] == clen+1 && pf->flags & GEXFF_CIRC) {
- /* the conflicting fragment is self-connected */
-
- pf->len[d] = 0;
- /* calculate the new value for lenback */
- len = clen+1 - f->len[GEXFI_EXACTLINE];
- for(pge = ge; len > 0; pge = pge->bkwd, len--)
- X_FRAG(pge)->lenback[d] = len;
- /* now pge points to the last entry of the line,
- * which is also the new first entry of the curve
- */
- X_FRAG(pge)->len[d] = clen+2 - f->len[GEXFI_EXACTLINE];
- /* clean lenback of gentries covered by the line */
- for(pge = ge->frwd, j = f->len[GEXFI_EXACTLINE]-1; j > 0; pge = pge->frwd, j--)
- X_FRAG(pge)->lenback[d] = 0;
- fprintf(stderr, " cut %s circular frag to %p-%p\n",
- gxf_name[d], pge, ge);
- gex_dump_contour(ge, clen);
- } else {
- /* when we chop off a piece of fragment, we leave the remaining
- * piece(s) overlapping with the beginning and possibly the end
- * of the line fragment under consideration
- */
- fprintf(stderr, " cut %s frag at %p from len=%d to len=%d (end %p)\n",
- gxf_name[d], pge, pf->len[d], len+1, ge);
- j = pf->len[d] - len - 1; /* how many gentries are chopped off */
- pf->len[d] = len + 1;
- i = f->len[GEXFI_EXACTLINE] - 1;
- for(pge = ge->frwd; j > 0 && i > 0; j--, i--, pge = pge->frwd)
- X_FRAG(pge)->lenback[d] = 0;
- gex_dump_contour(ge, clen);
-
- if(j != 0) {
- /* the conflicting fragment is split in two by this line
- * fragment, fix up its tail
- */
-
- fprintf(stderr, " end of %s frag len=%d %p-",
- gxf_name[d], j+1, pge->bkwd);
- X_FRAG(pge->bkwd)->len[d] = j+1; /* the overlapping */
- for(i = 1; j > 0; j--, i++, pge = pge->frwd)
- X_FRAG(pge)->lenback[d] = i;
- fprintf(stderr, "%p\n", pge->bkwd);
- gex_dump_contour(ge, clen);
- }
- }
- }
- /* check if we overlap the beginning of some fragments */
- i = f->len[GEXFI_EXACTLINE]-1; /* getntries remaining to consider */
- j = 0; /* gentries remaining in the overlapping fragment */
- for(pge = ge; i > 0; i--, pge = pge->frwd) {
- if(j > 0) {
- X_FRAG(pge)->lenback[d] = 0;
- j--;
- }
- /* the beginning of one fragment may be the end of another
- * fragment, in this case if j-- above results in 0, that will
- * cause it to check the same gentry for the beginning
- */
- if(j == 0) {
- pf = X_FRAG(pge);
- j = pf->len[d];
- if(j != 0) {
- fprintf(stderr, " removed %s frag at %p len=%d\n",
- gxf_name[d], pge, j);
- gex_dump_contour(ge, clen);
- pf->len[d] = 0;
- j--;
- }
- }
- }
- /* pge points at the last gentry of the line fragment */
- if(j > 1) { /* we have the tail of a fragment left */
- fprintf(stderr, " end of %s frag len=%d %p-",
- gxf_name[d], j, pge);
- X_FRAG(pge)->len[d] = j; /* the overlapping */
- for(i = 0; j > 0; j--, i++, pge = pge->frwd)
- X_FRAG(pge)->lenback[d] = i;
- fprintf(stderr, "%p\n", pge->bkwd);
- gex_dump_contour(ge, clen);
- } else if(j == 1) {
- X_FRAG(pge)->lenback[d] = 0;
- }
- }
-
- ge = ge->frwd;
- } while(ge != cge->next);
-
- /*
- * The exact lines take priority over curves that coincide
- * with them or extend by only one gentry on either side
- * (but not both sides). By this time it applies only to the
- * small exact lines.
- */
-
- /* Maybe we should remove only exact coincidences ? */
-
- ge = cge->next;
- do {
- f = X_FRAG(ge);
-
- len = f->len[GEXFI_EXACTLINE];
- if(len >= 4) {
- for(d = GEXFI_CONVEX; d<= GEXFI_CONCAVE; d++) {
- if(f->len[d] == len || f->len[d] == len+1) {
-
- fprintf(stderr, " removed %s frag at %p len=%d linelen=%d\n",
- gxf_name[d], ge, f->len[d], len);
- pge = ge->frwd;
- for(i = f->len[d]; i > 1; i--, pge = pge->frwd)
- X_FRAG(pge)->lenback[d] = 0;
- f->len[d] = 0;
- gex_dump_contour(ge, clen);
- } else if(X_FRAG(ge->bkwd)->len[d] == len+1) {
- fprintf(stderr, " removed %s frag at %p len=%d next linelen=%d\n",
- gxf_name[d], ge->bkwd, X_FRAG(ge->bkwd)->len[d], len);
- pge = ge;
- for(i = len; i > 0; i--, pge = pge->frwd)
- X_FRAG(pge)->lenback[d] = 0;
- X_FRAG(ge->bkwd)->len[d] = 0;
- gex_dump_contour(ge, clen);
- }
- }
- }
-
- ge = ge->frwd;
- } while(ge != cge->next);
-
- /*
- * The lines may cover only whole curves (or otherwise empty space),
- * so cut them where they overlap parts of the curves. If 2 or less
- * gentries are left in the line, remove the line.
- * If a line and a curve fully coincide, remove the line. Otherwise
- * remove the curves that are completely covered by the lines.
- */
-
- ge = cge->next;
- do {
- f = X_FRAG(ge);
-
- reconsider_line:
- len = f->len[GEXFI_LINE];
-
- if(len == 0) {
- ge = ge->frwd;
- continue;
- }
-
- if(f->len[GEXFI_CONVEX] >= len
- || f->len[GEXFI_CONCAVE] >= len) {
- line_completely_covered:
- fprintf(stderr, " removed covered Line frag at %p len=%d\n",
- ge, len);
- f->len[GEXFI_LINE] = 0;
- for(pge = ge->frwd; len > 1; len--, pge = pge->frwd)
- X_FRAG(pge)->lenback[GEXFI_LINE] = 0;
- gex_dump_contour(ge, clen);
- ge = ge->frwd;
- continue;
- }
-
- k1 = 0; /* how much to cut at the front */
- for(d = GEXFI_CONVEX; d<= GEXFI_CONCAVE; d++) {
- if(f->lenback[d]) {
- pge = age[(f->aidx + clen - f->lenback[d])%clen];
- i = X_FRAG(pge)->len[d] - f->lenback[d] - 1;
- if(i > k1)
- k1 = i;
- }
- }
-
- k2 = 0; /* how much to cut at the end */
- pge = age[(f->aidx + len)%clen]; /* gentry after the end */
- for(d = GEXFI_CONVEX; d<= GEXFI_CONCAVE; d++) {
- i = X_FRAG(pge)->lenback[d] - 1;
- if(i > k2)
- k2 = i;
- }
-
- if(k1+k2 > 0 && k1+k2 >= len-3)
- goto line_completely_covered;
-
- if(k2 != 0) { /* cut the end */
- len -= k2;
- f->len[GEXFI_LINE] = len;
- /* pge still points after the end */
- for(i = k2, pge = pge->bkwd; i > 0; i--, pge = pge->bkwd)
- X_FRAG(pge)->lenback[GEXFI_LINE] = 0;
- }
- if(k1 != 0) { /* cut the beginning */
- len -= k1;
- f->len[GEXFI_LINE] = 0;
- for(i = 1, pge = ge->frwd; i < k1; i++, pge = pge->frwd)
- X_FRAG(pge)->lenback[GEXFI_LINE] = 0;
- X_FRAG(pge)->len[GEXFI_LINE] = len;
- for(i = 0; i < len; i++, pge = pge->frwd)
- X_FRAG(pge)->lenback[GEXFI_LINE] = i;
- }
- if(k1 != 0 || k2 != 0) {
- fprintf(stderr, " cut Line frag at %p by (%d,%d) to len=%d\n",
- ge, k1, k2, len);
- gex_dump_contour(ge, clen);
-
- goto reconsider_line; /* the line may have to be cut again */
- }
- pge = age[(f->aidx + k1)%clen]; /* new beginning */
- good = 1; /* flag: no need do do a debugging dump */
- for(i=1; i<len; i++, pge = pge->frwd)
- for(d = GEXFI_CONVEX; d<= GEXFI_CONCAVE; d++) {
- if(X_FRAG(pge)->len[d]) {
- fprintf(stderr, " removed %s frag at %p len=%d covered by line\n",
- gxf_name[d], pge, X_FRAG(pge)->len[d], len);
- good = 0;
- }
- X_FRAG(pge)->len[d] = 0;
- }
- pge = age[(f->aidx + k1 + 1)%clen]; /* next after new beginning */
- for(i=1; i<len; i++, pge = pge->frwd)
- for(d = GEXFI_CONVEX; d<= GEXFI_CONCAVE; d++)
- X_FRAG(pge)->lenback[d] = 0;
- if(!good)
- gex_dump_contour(ge, clen);
-
- ge = ge->frwd;
- } while(ge != cge->next);
-
- /* Resolve conflicts between curves */
- for(d = GEXFI_CONVEX; d<= GEXFI_CONCAVE; d++) {
- dx = (GEXFI_CONVEX + GEXFI_CONCAVE) - d; /* the other type */
- ge = cge->next;
- do {
- GENTRY *sge;
-
- f = X_FRAG(ge);
- len = f->len[d];
- if(len < 2) {
- ge = ge->frwd;
- continue;
- }
- sge = ge; /* the start of fragment */
-
- i = f->len[dx];
- if(i != 0) { /* two curved frags starting here */
- /* should be i!=len because otherwise they would be
- * covered by an exact line
- */
- if(i > len) {
- curve_completely_covered:
- /* remove the convex frag */
- fprintf(stderr, " removed %s frag at %p len=%d covered by %s\n",
- gxf_name[d], ge, len, gxf_name[dx]);
- f->len[d] = 0;
- for(pge = ge->frwd, j = 1; j < len; j++, pge = pge->frwd)
- X_FRAG(pge)->lenback[d] = 0;
- gex_dump_contour(ge, clen);
-
- ge = ge->frwd; /* the frag is gone, nothing more to do */
- continue;
- } else {
- /* remove the concave frag */
- fprintf(stderr, " removed %s frag at %p len=%d covered by %s\n",
- gxf_name[dx], ge, i, gxf_name[d]);
- f->len[dx] = 0;
- for(pge = ge->frwd, j = 1; j < i; j++, pge = pge->frwd)
- X_FRAG(pge)->lenback[dx] = 0;
- gex_dump_contour(ge, clen);
- }
- }
-
-
- k1 = X_FRAG(ge->frwd)->lenback[dx];
- if(k1 != 0) { /* conflict at the front */
- GENTRY *gels, *gele, *gei;
-
- pge = age[(f->aidx + clen - (k1-1))%clen]; /* first gentry of concave frag */
- k2 = X_FRAG(pge)->len[dx]; /* its length */
-
- i = k2 - (k1-1); /* amount of overlap */
- if(i > len)
- i = len;
- /* i >= 2 by definition */
- if(i >= k2-1) { /* covers the other frag - maybe with 1 gentry showing */
- fprintf(stderr, " removed %s frag at %p len=%d covered by %s\n",
- gxf_name[dx], pge, k2, gxf_name[d]);
- X_FRAG(pge)->len[dx] = 0;
- for(pge = pge->frwd, j = 1; j < k2; j++, pge = pge->frwd)
- X_FRAG(pge)->lenback[dx] = 0;
- if(i >= len-1) { /* covers our frag too - maybe with 1 gentry showing */
- /* our frag will be removed as well, prepare a line to replace it */
- gels = ge;
- gele = age[(f->aidx + i - 1)%clen];
- fprintf(stderr, " new Line frag at %p-%p len=%d\n", gels, gele, i);
- X_FRAG(gels)->len[GEXFI_LINE] = i;
- for(gei = gels->frwd, j = 1; j < i; gei = gei->frwd, j++)
- X_FRAG(gei)->lenback[GEXFI_LINE] = j;
- } else {
- gex_dump_contour(ge, clen);
- ge = ge->frwd;
- continue;
- }
- }
- if(i >= len-1) /* covers our frag - maybe with 1 gentry showing */
- goto curve_completely_covered;
-
- /* XXX need to do something better for the case when a curve frag
- * is actually nothing but an artifact of two other curves of
- * the opposite type touching each other, like on the back of "3"
- */
-
- /* change the overlapping part to a line */
- gels = ge;
- gele = age[(f->aidx + i - 1)%clen];
- /* give preference to local extremums */
- if(X_FRAG(gels)->flags & GEXFF_EXTR) {
- gels = gels->frwd;
- i--;
- }
- if(X_FRAG(gele)->flags & GEXFF_EXTR) {
- gele = gele->bkwd;
- i--;
- }
- if(gels->bkwd == gele) {
- /* Oops the line became negative. Probably should
- * never happen but I can't think of any formal reasoning
- * leading to that, so check just in case. Restore
- * the previous state.
- */
- gels = gele; gele = gels->frwd; i = 2;
- }
-
- j = X_FRAG(gels)->lenback[dx] + 1; /* new length */
- if(j != k2) {
- X_FRAG(pge)->len[dx] = j;
- fprintf(stderr, " cut %s frag at %p len=%d to %p len=%d end overlap with %s\n",
- gxf_name[dx], pge, k2, gels, j, gxf_name[d]);
- for(gei = gels->frwd; j < k2; gei = gei->frwd, j++)
- X_FRAG(gei)->lenback[dx] = 0;
- }
-
- if(gele != ge) {
- sge = gele;
- f->len[d] = 0;
- fprintf(stderr, " cut %s frag at %p len=%d ", gxf_name[d], ge, len);
- len--;
- for(gei = ge->frwd; gei != gele; gei = gei->frwd, len--)
- X_FRAG(gei)->lenback[d] = 0;
- X_FRAG(gele)->len[d] = len;
- X_FRAG(gele)->lenback[d] = 0;
- fprintf(stderr, "to %p len=%d start overlap with %s\n",
- sge, len, gxf_name[dx]);
- for(gei = gei->frwd, j = 1; j < len; gei = gei->frwd, j++)
- X_FRAG(gei)->lenback[d] = j;
-
- }
- if(i > 1) {
- fprintf(stderr, " new Line frag at %p-%p len=%d\n", gels, gele, i);
- X_FRAG(gels)->len[GEXFI_LINE] = i;
- for(gei = gels->frwd, j = 1; j < i; gei = gei->frwd, j++)
- X_FRAG(gei)->lenback[GEXFI_LINE] = j;
- }
- gex_dump_contour(ge, clen);
- }
-
- ge = ge->frwd;
- } while(ge != cge->next);
- }
-
- /*
- * Assert that there are no conflicts any more and
- * for each gentry find the fragment types that start
- * and continue here.
- */
- ge = cge->next;
- do {
- f = X_FRAG(ge);
- dx = GEXFI_NONE; /* type that starts here */
- dy = GEXFI_NONE; /* type that goes through here */
- for(d = GEXFI_CONVEX; d<= GEXFI_LINE; d++) {
- if(f->len[d]) {
- if(dx >= 0) {
- fprintf(stderr, "**** Internal error in vectorization\n");
- fprintf(stderr, "CONFLICT in %s at %p between %s and %s\n",
- g->name, ge, gxf_name[dx], gxf_name[d]);
- dumppaths(g, cge->next, cge->next->bkwd);
- gex_dump_contour(ge, clen);
- exit(1);
- }
- dx = d;
- }
- if(f->lenback[d]) {
- if(dy >= 0) {
- fprintf(stderr, "**** Internal error in vectorization\n");
- fprintf(stderr, "CONFLICT in %s at %p between %s and %s\n",
- g->name, ge, gxf_name[dy], gxf_name[d]);
- dumppaths(g, cge->next, cge->next->bkwd);
- gex_dump_contour(ge, clen);
- exit(1);
- }
- dy = d;
- }
- }
- f->ixstart = dx;
- f->ixcont = dy;
- ge = ge->frwd;
- } while(ge != cge->next);
-
- /*
- * make sure that the contour does not start in the
- * middle of a fragment
- */
- ge = cge->next; /* old start of the contour */
- f = X_FRAG(ge);
- if(f->ixstart == GEXFI_NONE && f->ixcont != GEXFI_NONE) {
- /* oops, it's mid-fragment, move the start */
- GENTRY *xge;
-
- xge = ge->bkwd->next; /* entry following the contour */
-
- /* find the first gentry of this frag */
- pge = age[(f->aidx + clen - f->lenback[f->ixcont])%clen];
-
- ge->prev = ge->bkwd;
- ge->bkwd->next = ge;
-
- cge->next = pge;
- pge->prev = cge;
-
- pge->bkwd->next = xge;
- if(xge)
- xge->prev = pge->bkwd;
-
- cge->ix3 = pge->bkwd->ix3; cge->iy3 = pge->bkwd->iy3;
- }
-
- /* vectorize each fragment separately */
- ge = cge->next;
- do {
- /* data for curves */
- GENTRY *firstge, *lastge, *gef, *gel, *gei, *gex;
- GENTRY *ordhd; /* head of the order list */
- GENTRY **ordlast;
- int nsub; /* number of subfrags */
- GEX_FRAG *ff, *lf, *xf;
-
- f = X_FRAG(ge);
- switch(f->ixstart) {
- case GEXFI_LINE:
- len = f->len[GEXFI_LINE];
- pge = age[(f->aidx + len - 1)%clen]; /* last gentry */
-
- if(ge->iy3 == ge->bkwd->iy3) { /* frag starts and ends horizontally */
- k1 = 1/*Y*/ ; /* across the direction of start */
- k2 = 0/*X*/ ; /* along the direction of start */
- } else { /* frag starts and ends vertically */
- k1 = 0/*X*/ ; /* across the direction of start */
- k2 = 1/*Y*/ ; /* along the direction of start */
- }
-
- if(len % 2) {
- /* odd number of entries in the frag */
- double halfstep, halfend;
-
- f->vect[0][k1] = fscale * ge->ipoints[k1][2];
- f->vect[3][k1] = fscale * pge->ipoints[k1][2];
-
- halfstep = (pge->ipoints[k2][2] - ge->bkwd->ipoints[k2][2])
- * 0.5 / ((len+1)/2);
- if(f->ixcont != GEXFI_NONE) {
- halfend = (ge->ipoints[k2][2] - ge->bkwd->ipoints[k2][2]) * 0.5;
- if(fabs(halfstep) < fabs(halfend)) /* must be at least half gentry away */
- halfstep = halfend;
- }
- if(X_FRAG(pge)->ixstart != GEXFI_NONE) {
- halfend = (pge->ipoints[k2][2] - pge->bkwd->ipoints[k2][2]) * 0.5;
- if(fabs(halfstep) < fabs(halfend)) /* must be at least half gentry away */
- halfstep = halfend;
- }
- f->vect[0][k2] = fscale * (ge->bkwd->ipoints[k2][2] + halfstep);
- f->vect[3][k2] = fscale * (pge->ipoints[k2][2] - halfstep);
- } else {
- /* even number of entries */
- double halfstep, halfend;
-
- f->vect[0][k1] = fscale * ge->ipoints[k1][2];
- halfstep = (pge->ipoints[k2][2] - ge->bkwd->ipoints[k2][2])
- * 0.5 / (len/2);
- if(f->ixcont != GEXFI_NONE) {
- halfend = (ge->ipoints[k2][2] - ge->bkwd->ipoints[k2][2]) * 0.5;
- if(fabs(halfstep) < fabs(halfend)) /* must be at least half gentry away */
- halfstep = halfend;
- }
- f->vect[0][k2] = fscale * (ge->bkwd->ipoints[k2][2] + halfstep);
-
- halfstep = (pge->ipoints[k1][2] - ge->bkwd->ipoints[k1][2])
- * 0.5 / (len/2);
- if(X_FRAG(pge)->ixstart != GEXFI_NONE) {
- halfend = (pge->ipoints[k1][2] - pge->bkwd->ipoints[k1][2]) * 0.5;
- if(fabs(halfstep) < fabs(halfend)) /* must be at least half gentry away */
- halfstep = halfend;
- }
- f->vect[3][k1] = fscale * (pge->ipoints[k1][2] - halfstep);
- f->vect[3][k2] = fscale * pge->ipoints[k2][2];
- }
- f->vectlen = len;
- f->flags |= GEXFF_DRAWLINE;
- break;
- case GEXFI_CONVEX:
- case GEXFI_CONCAVE:
- len = f->len[f->ixstart];
- firstge = ge;
- lastge = age[(f->aidx + len - 1)%clen]; /* last gentry */
-
- nsub = 0;
- gex = firstge;
- xf = X_FRAG(gex);
- xf->prevsub = 0;
- xf->sublen = 1;
- xf->flags &= ~GEXFF_DONE;
- for(gei = firstge->frwd; gei != lastge; gei = gei->frwd) {
- xf->sublen++;
- if(X_FRAG(gei)->flags & GEXFF_EXTR) {
- xf->nextsub = gei;
- for(i=0; i<2; i++)
- xf->bbox[i] = abs(gei->ipoints[i][2] - gex->bkwd->ipoints[i][2]);
- nsub++;
- xf = X_FRAG(gei);
- xf->prevsub = gex;
- xf->sublen = 1;
- xf->flags &= ~GEXFF_DONE;
- gex = gei;
- }
- }
- xf->sublen++;
- xf->nextsub = gei;
- for(i=0; i<2; i++)
- xf->bbox[i] = abs(gei->ipoints[i][2] - gex->bkwd->ipoints[i][2]);
- nsub++;
- ff = xf; /* remember the beginning of the last subfrag */
- xf = X_FRAG(gei);
- xf->prevsub = gex;
- if(firstge != lastge) {
- xf->nextsub = 0;
- xf->sublen = 0;
-
- /* correct the bounding box of the last and first subfrags for
- * intersections with other fragments
- */
- if(xf->ixstart != GEXFI_NONE) {
- /* ff points to the beginning of the last subfrag */
- for(i=0; i<2; i++)
- ff->bbox[i] -= 0.5 * abs(lastge->ipoints[i][2] - lastge->bkwd->ipoints[i][2]);
- }
- ff = X_FRAG(firstge);
- if(ff->ixcont != GEXFI_NONE) {
- for(i=0; i<2; i++)
- ff->bbox[i] -= 0.5 * abs(firstge->ipoints[i][2] - firstge->bkwd->ipoints[i][2]);
- }
- }
-
- fprintf(stderr, " %s frag %p%s nsub=%d\n", gxf_name[f->ixstart],
- ge, (f->flags&GEXFF_CIRC)?" circular":"", nsub);
-
- /* find the symmetry between the subfragments */
- for(gef = firstge, count=0; count < nsub; gef = ff->nextsub, count++) {
- ff = X_FRAG(gef);
- gex = ff->nextsub;
- xf = X_FRAG(gex);
- gel = xf->nextsub;
- if(gel == 0) {
- ff->flags &= ~GEXFF_SYMNEXT;
- break; /* not a circular frag */
- }
- good = 1; /* assume that we have symmetry */
- /* gei goes backwards, gex goes forwards from the extremum */
- gei = gex;
- /* i is the symmetry axis, j is the other axis (X=0 Y=1) */
- ff->symaxis = i = (gex->ix3 != gex->bkwd->ix3);
- j = !i;
- for( ; gei!=gef && gex!=gel; gei=gei->bkwd, gex=gex->frwd) {
- if( gei->bkwd->ipoints[i][2] != gex->ipoints[i][2]
- || gei->bkwd->ipoints[j][2] - gei->ipoints[j][2]
- != gex->bkwd->ipoints[j][2] - gex->ipoints[j][2]
- ) {
- good = 0; /* no symmetry */
- break;
- }
- }
- if(good) {
- if( isign(gei->bkwd->ipoints[j][2] - gei->ipoints[j][2])
- != isign(gex->bkwd->ipoints[j][2] - gex->ipoints[j][2]) ) {
- good = 0; /* oops, goes into another direction */
- }
- }
- if(good)
- ff->flags |= GEXFF_SYMNEXT;
- else
- ff->flags &= ~GEXFF_SYMNEXT;
- }
-
- for(gef = firstge, count=0; count < nsub; gef = ff->nextsub, count++) {
- ff = X_FRAG(gef);
- if((ff->flags & GEXFF_SYMNEXT)==0) {
- ff->symxlen = 0;
- continue;
- }
- gex = ff->prevsub;
- if(gex == 0 || (X_FRAG(gex)->flags & GEXFF_SYMNEXT)==0) {
- ff->symxlen = 0;
- continue;
- }
- ff->symxlen = X_FRAG(gex)->sublen;
- xf = X_FRAG(ff->nextsub);
- if(xf->sublen < ff->symxlen)
- ff->symxlen = xf->sublen;
- }
-
- /* find the symmetry inside the subfragments */
- for(gef = firstge, count=0; count < nsub; gef = ff->nextsub, count++) {
- ff = X_FRAG(gef);
-
- if(ff->sublen % 2) {
- /* we must have an even number of gentries for diagonal symmetry */
- ff->symge = 0;
- continue;
- }
-
- /* gei goes forwards from the front */
- gei = gef->frwd;
- /* gex goes backwards from the back */
- gex = ff->nextsub->bkwd;
-
- /* i is the direction of gei, j is the direction of gex */
- i = (gei->iy3 != gei->bkwd->iy3);
- j = !i;
- for( ; gei->bkwd != gex; gei=gei->frwd, gex=gex->bkwd) {
- if( abs(gei->bkwd->ipoints[i][2] - gei->ipoints[i][2])
- != abs(gex->bkwd->ipoints[j][2] - gex->ipoints[j][2]) )
- break; /* no symmetry */
- i = j;
- j = !j;
- }
- if(gei->bkwd == gex)
- ff->symge = gex;
- else
- ff->symge = 0; /* no symmetry */
- }
-
- /* find the order of calculation:
- * prefer to start from long fragments that have the longest
- * neighbours symmetric with them, with all being equal prefer
- * the fragments that have smaller physical size
- */
- ordhd = 0;
- for(gef = firstge, count=0; count < nsub; gef = ff->nextsub, count++) {
- ff = X_FRAG(gef);
-
- for(ordlast = &ordhd; *ordlast != 0; ordlast = &xf->ordersub) {
- xf = X_FRAG(*ordlast);
- if(ff->sublen > xf->sublen)
- break;
- if(ff->sublen < xf->sublen)
- continue;
- if(ff->symxlen > xf->symxlen)
- break;
- if(ff->symxlen < xf->symxlen)
- continue;
- if(ff->bbox[0] < xf->bbox[0] || ff->bbox[1] < xf->bbox[1])
- break;
- }
-
- ff->ordersub = *ordlast;
- *ordlast = gef;
- }
-
- /* vectorize the subfragments */
- for(gef = ordhd; gef != 0; gef = ff->ordersub) {
-
- /* debugging stuff */
- ff = X_FRAG(gef);
- fprintf(stderr, " %p-%p bbox[%g,%g] sym=%p %s len=%d xlen=%d\n",
- gef, ff->nextsub, ff->bbox[0], ff->bbox[1], ff->symge,
- (ff->flags & GEXFF_SYMNEXT) ? "symnext" : "",
- ff->sublen, ff->symxlen);
-
- dosubfrag(g, f->ixstart, firstge, gef, fscale);
- }
-
- break;
- }
- ge = ge->frwd;
- } while(ge != cge->next);
-
- free(age);
-
- }
-
- }
-
- /* all the fragments are found, extract the vectorization */
- pge = g->entries;
- g->entries = g->lastentry = 0;
- g->flags |= GF_FLOAT;
- loopge = 0;
- skip = 0;
-
- for(ge = pge; ge != 0; ge = ge->next) {
- GEX_FRAG *f, *pf;
-
- switch(ge->type) {
- case GE_LINE:
- f = X_FRAG(ge);
- if(skip == 0) {
- if(f->flags & (GEXFF_DRAWLINE|GEXFF_DRAWCURVE)) {
- /* draw a line to the start point */
- fg_rlineto(g, f->vect[0][0], f->vect[0][1]);
- /* draw the fragment */
- if(f->flags & GEXFF_DRAWCURVE)
- fg_rrcurveto(g,
- f->vect[1][0], f->vect[1][1],
- f->vect[2][0], f->vect[2][1],
- f->vect[3][0], f->vect[3][1]);
- else
- fg_rlineto(g, f->vect[3][0], f->vect[3][1]);
- skip = f->vectlen - 2;
- } else {
- fg_rlineto(g, fscale * ge->ix3, fscale * ge->iy3);
- }
- } else
- skip--;
- break;
- case GE_MOVE:
- fg_rmoveto(g, -1e6, -1e6); /* will be fixed by GE_PATH */
- skip = 0;
- /* remember the reference to update it later */
- loopge = g->lastentry;
- break;
- case GE_PATH:
- /* update the first MOVE of this contour */
- if(loopge) {
- loopge->fx3 = g->lastentry->fx3;
- loopge->fy3 = g->lastentry->fy3;
- loopge = 0;
- }
- g_closepath(g);
- break;
- }
- }
- for(ge = pge; ge != 0; ge = cge) {
- cge = ge->next;
- free(ge->ext);
- free(ge);
- }
- dumppaths(g, NULL, NULL);
-
- /* end of vectorization logic */
- } else {
- /* convert the data to float */
- GENTRY *ge;
- double x, y;
-
- for(ge = g->entries; ge != 0; ge = ge->next) {
- ge->flags |= GEF_FLOAT;
- if(ge->type != GE_MOVE && ge->type != GE_LINE)
- continue;
-
- x = fscale * ge->ix3;
- y = fscale * ge->iy3;
-
- ge->fx3 = x;
- ge->fy3 = y;
- }
- g->flags |= GF_FLOAT;
- }
-
- free(hlm); free(vlm); free(amp);
-}
-
-#if 0
-/* print out the bitmap */
-printbmap(bmap, xsz, ysz, xoff, yoff)
- char *bmap;
- int xsz, ysz, xoff, yoff;
-{
- int x, y;
-
- for(y=ysz-1; y>=0; y--) {
- putchar( (y%10==0) ? y/10+'0' : ' ' );
- putchar( y%10+'0' );
- for(x=0; x<xsz; x++)
- putchar( bmap[y*xsz+x] ? 'X' : '.' );
- if(-yoff==y)
- putchar('_'); /* mark the baseline */
- putchar('\n');
- }
- putchar(' '); putchar(' ');
- for(x=0; x<xsz; x++)
- putchar( x%10+'0' );
- putchar('\n'); putchar(' '); putchar(' ');
- for(x=0; x<xsz; x++)
- putchar( (x%10==0) ? x/10+'0' : ' ' );
- putchar('\n');
-}
-
-/* print out the limits of outlines */
-printlimits(hlm, vlm, amp, xsz, ysz)
- char *hlm, *vlm, *amp;
- int xsz, ysz;
-{
- int x, y;
- static char h_char[]={ ' ', '~', '^' };
- static char v_char[]={ ' ', '(', ')' };
-
- for(y=ysz-1; y>=0; y--) {
- for(x=0; x<xsz; x++) {
- if(amp[y*xsz+x])
- putchar('!'); /* ambigouos point is always on a limit */
- else
- putchar(v_char[ vlm[y*(xsz+1)+x] & (L_ON|L_OFF) ]);
- putchar(h_char[ hlm[(y+1)*xsz+x] & (L_ON|L_OFF) ]);
- }
- putchar(v_char[ vlm[y*(xsz+1)+x] & (L_ON|L_OFF) ]);
- putchar('\n');
- }
- /* last line */
- for(x=0; x<xsz; x++) {
- putchar(' ');
- putchar(h_char[ hlm[x] & (L_ON|L_OFF) ]);
- }
- putchar(' ');
- putchar('\n');
-}
-#endif /* 0 */
+++ /dev/null
-/*
- * see COPYRIGHT
- */
-
-/* This defines the macroes ntohs and ntohl, which convert short and long
- ints from network order (used on 68000 chips, and in TrueType font
- files) to whatever order your computer uses. #define _BIG_ENDIAN or not
- to control which set of definitions apply. If you don't know, try both. If
- you have a peculiar machine you're on your own.
-*/
-
-#if defined(_BIG_ENDIAN)
-#define ntohl(x) (x)
-#define ntohs(x) (x)
-#else
-#define ntohs(x) \
- ((USHORT)((((USHORT)(x) & 0x00ff) << 8) | \
- (((USHORT)(x) & 0xff00) >> 8)))
-#define ntohl(x) \
- ((ULONG)((((ULONG)(x) & 0x000000ffU) << 24) | \
- (((ULONG)(x) & 0x0000ff00U) << 8) | \
- (((ULONG)(x) & 0x00ff0000U) >> 8) | \
- (((ULONG)(x) & 0xff000000U) >> 24)))
-#endif
+++ /dev/null
-/*
- * The font parser using the FreeType library version 2.
- *
- * see COPYRIGHT
- *
- */
-
-#include "../../config.h"
-#ifdef USE_FREETYPE
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <ctype.h>
-#include <sys/types.h>
-#include <freetype/freetype.h>
-#include <freetype/ftglyph.h>
-#include <freetype/ftsnames.h>
-#include <freetype/ttnameid.h>
-#include <freetype/ftoutln.h>
-#include "pt1.h"
-#include "global.h"
-
-/* prototypes of call entries */
-static void openfont(char *fname, char *arg);
-static void closefont( void);
-static int getnglyphs ( void);
-static int glnames( GLYPH *glyph_list);
-static void glmetrics( GLYPH *glyph_list);
-static int glenc( GLYPH *glyph_list, int *encoding, int *unimap);
-static void fnmetrics( struct font_metrics *fm);
-static void glpath( int glyphno, GLYPH *glyph_list);
-static void kerning( GLYPH *glyph_list);
-
-/* globals */
-
-/* front-end descriptor */
-struct frontsw freetype_sw = {
- /*name*/ "ft",
- /*descr*/ "based on the FreeType library",
- /*suffix*/ { "ttf", "otf", "pfa", "pfb" },
- /*open*/ openfont,
- /*close*/ closefont,
- /*nglyphs*/ getnglyphs,
- /*glnames*/ glnames,
- /*glmetrics*/ glmetrics,
- /*glenc*/ glenc,
- /*fnmetrics*/ fnmetrics,
- /*glpath*/ glpath,
- /*kerning*/ kerning,
-};
-
-/* statics */
-
-static char * dupcnstring( unsigned char *s, int len);
-
-static FT_Library library;
-static FT_Face face;
-
-static int enc_type, enc_found;
-
-/* SFNT functions do not seem to be included by default in FT2beta8 */
-#define ENABLE_SFNT
-
-/*
- * Open font and prepare to return information to the main driver.
- * May print error and warning messages.
- * Exit on error.
- */
-
-static void
-openfont(
- char *fname,
- char *arg /* unused now */
-)
-{
- FT_Error error;
-
- if( FT_Init_FreeType( &library ) ) {
- fprintf(stderr, "** FreeType initialization failed\n");
- exit(1);
- }
-
- if( error = FT_New_Face( library, fname, 0, &face ) ) {
- if ( error == FT_Err_Unknown_File_Format )
- fprintf(stderr, "**** %s has format unknown to FreeType\n", fname);
- else
- fprintf(stderr, "**** Cannot access %s ****\n", fname);
- exit(1);
- }
-
- if(FT_HAS_FIXED_SIZES(face)) {
- WARNING_1 fprintf(stderr, "Font contains bitmaps\n");
- }
- if(FT_HAS_MULTIPLE_MASTERS(face)) {
- WARNING_1 fprintf(stderr, "Font contains multiple masters, using default\n");
- }
-
- if(ISDBG(FT)) fprintf(stderr," %d units per EM\n", face->units_per_EM);
-
- enc_found = 0;
-}
-
-/*
- * Close font.
- * Exit on error.
- */
-
-static void
-closefont(
- void
-)
-{
- if( FT_Done_Face(face) ) {
- WARNING_1 fprintf(stderr, "Errors when closing the font file, ignored\n");
- }
- if( FT_Done_FreeType(library) ) {
- WARNING_1 fprintf(stderr, "Errors when stopping FreeType, ignored\n");
- }
-}
-
-/*
- * Get the number of glyphs in font.
- */
-
-static int
-getnglyphs (
- void
-)
-{
- if(ISDBG(FT)) fprintf(stderr, "%d glyphs in font\n", face->num_glyphs);
- return (int)face->num_glyphs;
-}
-
-/*
- * Get the names of the glyphs.
- * Returns 0 if the names were assigned, non-zero if the font
- * provides no glyph names.
- */
-
-static int
-glnames(
- GLYPH *glyph_list
-)
-{
-#define MAX_NAMELEN 1024
- unsigned char bf[1024];
- int i;
-
- if( ! FT_HAS_GLYPH_NAMES(face) ) {
- WARNING_1 fprintf(stderr, "Font has no glyph names\n");
- return 1;
- }
-
- for(i=0; i < face->num_glyphs; i++) {
- if( FT_Get_Glyph_Name(face, i, bf, MAX_NAMELEN) || bf[0]==0 ) {
- sprintf(bf, "_g_%d", i);
- WARNING_2 fprintf(stderr,
- "Glyph No. %d has no postscript name, becomes %s\n", i, bf);
- }
- glyph_list[i].name = strdup(bf);
- if(ISDBG(FT)) fprintf(stderr, "%d has name %s\n", i, bf);
- if (glyph_list[i].name == NULL) {
- fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__);
- exit(255);
- }
- }
- return 0;
-}
-
-/*
- * Get the metrics of the glyphs.
- */
-
-static void
-glmetrics(
- GLYPH *glyph_list
-)
-{
- GLYPH *g;
- int i;
- FT_Glyph_Metrics *met;
- FT_BBox bbox;
- FT_Glyph gly;
-
- for(i=0; i < face->num_glyphs; i++) {
- g = &(glyph_list[i]);
-
- if( FT_Load_Glyph(face, i, FT_LOAD_NO_BITMAP|FT_LOAD_NO_SCALE) ) {
- fprintf(stderr, "Can't load glyph %s, skipped\n", g->name);
- continue;
- }
-
- met = &face->glyph->metrics;
-
- if(FT_HAS_HORIZONTAL(face)) {
- g->width = met->horiAdvance;
- g->lsb = met->horiBearingX;
- } else {
- WARNING_2 fprintf(stderr, "Glyph %s has no horizontal metrics, guessed them\n", g->name);
- g->width = met->width;
- g->lsb = 0;
- }
-
- if( FT_Get_Glyph(face->glyph, &gly) ) {
- fprintf(stderr, "Can't access glyph %s bbox, skipped\n", g->name);
- continue;
- }
-
- FT_Glyph_Get_CBox(gly, ft_glyph_bbox_unscaled, &bbox);
- g->xMin = bbox.xMin;
- g->yMin = bbox.yMin;
- g->xMax = bbox.xMax;
- g->yMax = bbox.yMax;
-
- g->ttf_pathlen = face->glyph->outline.n_points;
- }
-}
-
-/*
- * Get the original encoding of the font.
- * Returns 1 for if the original encoding is Unicode, 2 if the
- * original encoding is other 16-bit, 0 if 8-bit.
- */
-
-static int
-glenc(
- GLYPH *glyph_list,
- int *encoding,
- int *unimap
-)
-{
- int i, e;
- unsigned code;
-
- if(ISDBG(FT))
- for(e=0; e < face->num_charmaps; e++) {
- fprintf(stderr, "found encoding pid=%d eid=%d\n",
- face->charmaps[e]->platform_id,
- face->charmaps[e]->encoding_id);
- }
-
- if(enc_found)
- goto populate_map;
-
- enc_type = 0;
-
- /* first check for an explicit PID/EID */
-
- if(force_pid != -1) {
- for(e=0; e < face->num_charmaps; e++) {
- if(face->charmaps[e]->platform_id == force_pid
- && face->charmaps[e]->encoding_id == force_eid) {
- WARNING_1 fprintf(stderr, "Found Encoding PID=%d/EID=%d\n",
- force_pid, force_eid);
- if( FT_Set_Charmap(face, face->charmaps[e]) ) {
- fprintf(stderr, "**** Cannot set charmap in FreeType ****\n");
- exit(1);
- }
- enc_type = 1;
- goto populate_map;
- }
- }
- fprintf(stderr, "*** TTF encoding table PID=%d/EID=%d not found\n",
- force_pid, force_eid);
- exit(1);
- }
-
- /* next check for a direct Adobe mapping */
-
- if(!forcemap) {
- for(e=0; e < face->num_charmaps; e++) {
- if(face->charmaps[e]->encoding == ft_encoding_adobe_custom) {
- WARNING_1 fputs("Found Adobe Custom Encoding\n", stderr);
- if( FT_Set_Charmap(face, face->charmaps[e]) ) {
- fprintf(stderr, "**** Cannot set charmap in FreeType ****\n");
- exit(1);
- }
- goto populate_map;
- }
- }
- }
-
- for(e=0; e < face->num_charmaps; e++) {
- if(face->charmaps[e]->platform_id == 3) {
- switch(face->charmaps[e]->encoding_id) {
- case 0:
- WARNING_1 fputs("Found Symbol Encoding\n", stderr);
- break;
- case 1:
- WARNING_1 fputs("Found Unicode Encoding\n", stderr);
- enc_type = 1;
- break;
- default:
- WARNING_1 {
- fprintf(stderr,
- "****MS Encoding ID %d not supported****\n",
- face->charmaps[e]->encoding_id);
- fputs("Treating it like Symbol encoding\n", stderr);
- }
- break;
- }
- break;
- }
- }
- if(e >= face->num_charmaps) {
- WARNING_1 fputs("No Microsoft encoding, using first encoding available\n", stderr);
- e = 0;
- }
-
- if( !face->charmaps || FT_Set_Charmap(face, face->charmaps[e]) ) {
- fprintf(stderr, "**** Cannot set charmap in FreeType ****\n");
- }
-
-populate_map:
- enc_found = 1;
- for(i=0; i<ENCTABSZ; i++) {
- if(encoding[i] != -1)
- continue;
- if(enc_type == 1 || forcemap) {
- code = unimap[i];
- if(code == (unsigned) -1)
- continue;
- } else
- code = i;
-
- code = FT_Get_Char_Index(face, code);
- if(0 && ISDBG(FT)) fprintf(stderr, "code of %3d is %3d\n", i, code);
- if(code == 0)
- continue; /* .notdef */
- encoding[i] = code;
- }
-
- return enc_type;
-}
-
-/* duplicate a string with counter to a 0-terminated string */
-static char *
-dupcnstring(
- unsigned char *s,
- int len
-)
-{
- char *res, *out;
- int i, c;
- static int warned=0;
-
- if(( res = malloc(len+1) )==NULL) {
- fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__);
- exit(255);
- }
-
- out = res;
- for(i=0; i<len; i++) {
- if(( c=s[i] )>=' ' && c!=127)
- *out++ = c;
- else if(!warned) {
- warned=1;
- WARNING_1 fprintf(stderr, "Some font name strings are in Unicode, may not show properly\n");
- }
- }
- *out = 0;
- return res;
-}
-
-/*
- * Get the font metrics
- */
-static void
-fnmetrics(
- struct font_metrics *fm
-)
-{
- char *str;
- static char *fieldstocheck[3];
-#ifdef ENABLE_SFNT
- FT_SfntName sn;
-#endif /* ENABLE_SFNT */
- int i;
-
- fm->italic_angle = 0.0; /* FreeType hides the angle */
- fm->underline_position = face->underline_position;
- fm->underline_thickness = face->underline_thickness;
- fm->is_fixed_pitch = FT_IS_FIXED_WIDTH(face);
-
- fm->ascender = face->ascender;
- fm->descender = face->descender;
-
- fm->units_per_em = face->units_per_EM;
-
- fm->bbox[0] = face->bbox.xMin;
- fm->bbox[1] = face->bbox.yMin;
- fm->bbox[2] = face->bbox.xMax;
- fm->bbox[3] = face->bbox.yMax;
-
-#ifdef ENABLE_SFNT
- if( FT_Get_Sfnt_Name(face, TT_NAME_ID_COPYRIGHT, &sn) )
-#endif /* ENABLE_SFNT */
- fm->name_copyright = "";
-#ifdef ENABLE_SFNT
- else
- fm->name_copyright = dupcnstring(sn.string, sn.string_len);
-#endif /* ENABLE_SFNT */
-
- fm->name_family = face->family_name;
-
- fm->name_style = face->style_name;
- if(fm->name_style == NULL)
- fm->name_style = "";
-
-#ifdef ENABLE_SFNT
- if( FT_Get_Sfnt_Name(face, TT_NAME_ID_FULL_NAME, &sn) )
-#endif /* ENABLE_SFNT */
- {
- int len;
-
- if(!fm->name_family)
- fm->name_family = "";
- if(!fm->name_style)
- fm->name_style= "";
- len = strlen(fm->name_family) + strlen(fm->name_style) + 2;
- if(( fm->name_full = malloc(len) )==NULL) {
- fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__);
- exit(255);
- }
- strcpy(fm->name_full, fm->name_family);
- if(strlen(fm->name_style) != 0) {
- strcat(fm->name_full, " ");
- strcat(fm->name_full, fm->name_style);
- }
- }
-#ifdef ENABLE_SFNT
- else
- fm->name_full = dupcnstring(sn.string, sn.string_len);
-#endif /* ENABLE_SFNT */
-
-#ifdef ENABLE_SFNT
- if( FT_Get_Sfnt_Name(face, TT_NAME_ID_VERSION_STRING, &sn) )
-#endif /* ENABLE_SFNT */
- fm->name_version = "1.0";
-#ifdef ENABLE_SFNT
- else
- fm->name_version = dupcnstring(sn.string, sn.string_len);
-#endif /* ENABLE_SFNT */
-
-#ifdef ENABLE_SFNT
- if( FT_Get_Sfnt_Name(face, TT_NAME_ID_PS_NAME , &sn) ) {
-#endif /* ENABLE_SFNT */
- if(( fm->name_ps = strdup(fm->name_full) )==NULL) {
- fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__);
- exit(255);
- }
-#ifdef ENABLE_SFNT
- } else
- fm->name_ps = dupcnstring(sn.string, sn.string_len);
-#endif /* ENABLE_SFNT */
- for(i=0; fm->name_ps[i]!=0; i++)
- if(fm->name_ps[i] == ' ')
- fm->name_ps[i] = '_'; /* no spaces in the Postscript name */
-
- /* guess the boldness from the font names */
- fm->force_bold=0;
-
- fieldstocheck[0] = fm->name_style;
- fieldstocheck[1] = fm->name_full;
- fieldstocheck[2] = fm->name_ps;
-
- for(i=0; !fm->force_bold && i<sizeof fieldstocheck /sizeof(fieldstocheck[0]); i++) {
- int j;
- str=fieldstocheck[i];
- for(j=0; str[j]!=0; j++) {
- if( (str[j]=='B'
- || str[j]=='b'
- && ( j==0 || !isalpha(str[j-1]) )
- )
- && !strncmp("old",&str[j+1],3)
- && !islower(str[j+4])
- ) {
- fm->force_bold=1;
- break;
- }
- }
- }
-}
-
-/*
- * Functions to decompose the outlines
- */
-
-static GLYPH *curg;
-static double lastx, lasty;
-
-static int
-outl_moveto(
- FT_Vector *to,
- void *unused
-)
-{
- double tox, toy;
-
- tox = fscale((double)to->x); toy = fscale((double)to->y);
-
- /* FreeType does not do explicit closepath() */
- if(curg->lastentry) {
- g_closepath(curg);
- }
- fg_rmoveto(curg, tox, toy);
- lastx = tox; lasty = toy;
-
- return 0;
-}
-
-static int
-outl_lineto(
- FT_Vector *to,
- void *unused
-)
-{
- double tox, toy;
-
- tox = fscale((double)to->x); toy = fscale((double)to->y);
-
- fg_rlineto(curg, tox, toy);
- lastx = tox; lasty = toy;
-
- return 0;
-}
-
-static int
-outl_conicto(
- FT_Vector *control1,
- FT_Vector *to,
- void *unused
-)
-{
- double c1x, c1y, tox, toy;
-
- c1x = fscale((double)control1->x); c1y = fscale((double)control1->y);
- tox = fscale((double)to->x); toy = fscale((double)to->y);
-
- fg_rrcurveto(curg,
- (lastx + 2.0 * c1x) / 3.0, (lasty + 2.0 * c1y) / 3.0,
- (2.0 * c1x + tox) / 3.0, (2.0 * c1y + toy) / 3.0,
- tox, toy );
- lastx = tox; lasty = toy;
-
- return 0;
-}
-
-static int
-outl_cubicto(
- FT_Vector *control1,
- FT_Vector *control2,
- FT_Vector *to,
- void *unused
-)
-{
- double c1x, c1y, c2x, c2y, tox, toy;
-
- c1x = fscale((double)control1->x); c1y = fscale((double)control1->y);
- c2x = fscale((double)control2->x); c2y = fscale((double)control2->y);
- tox = fscale((double)to->x); toy = fscale((double)to->y);
-
- fg_rrcurveto(curg, c1x, c1y, c2x, c2y, tox, toy);
- lastx = tox; lasty = toy;
-
- return 0;
-}
-
-static FT_Outline_Funcs ft_outl_funcs = {
- outl_moveto,
- outl_lineto,
- outl_conicto,
- outl_cubicto,
- 0,
- 0
-};
-
-/*
- * Get the path of contrours for a glyph.
- */
-
-static void
-glpath(
- int glyphno,
- GLYPH *glyf_list
-)
-{
- FT_Outline *ol;
-
- curg = &glyf_list[glyphno];
-
- if( FT_Load_Glyph(face, glyphno, FT_LOAD_NO_BITMAP|FT_LOAD_NO_SCALE|FT_LOAD_NO_HINTING)
- || face->glyph->format != ft_glyph_format_outline ) {
- fprintf(stderr, "Can't load glyph %s, skipped\n", curg->name);
- return;
- }
-
- ol = &face->glyph->outline;
- lastx = 0.0; lasty = 0.0;
-
- if( FT_Outline_Decompose(ol, &ft_outl_funcs, NULL) ) {
- fprintf(stderr, "Can't decompose outline of glyph %s, skipped\n", curg->name);
- return;
- }
-
- /* FreeType does not do explicit closepath() */
- if(curg->lastentry) {
- g_closepath(curg);
- }
-
- if(ol->flags & ft_outline_reverse_fill) {
- assertpath(curg->entries, __FILE__, __LINE__, curg->name);
- reversepaths(curg);
- }
-}
-
-/*
- * Get the kerning data.
- */
-
-static void
-kerning(
- GLYPH *glyph_list
-)
-{
- int i, j, n;
- int nglyphs = face->num_glyphs;
- FT_Vector k;
- GLYPH *gl;
-
- if( nglyphs == 0 || !FT_HAS_KERNING(face) ) {
- WARNING_1 fputs("No Kerning data\n", stderr);
- return;
- }
-
- for(i=0; i<nglyphs; i++) {
- if( (glyph_list[i].flags & GF_USED) ==0)
- continue;
- for(j=0; j<nglyphs; j++) {
- if( (glyph_list[j].flags & GF_USED) ==0)
- continue;
- if( FT_Get_Kerning(face, i, j, ft_kerning_unscaled, &k) )
- continue;
- if( k.x == 0 )
- continue;
-
- addkernpair(i, j, k.x);
- }
- }
-}
-
-#endif
+++ /dev/null
-/*
- * see COPYRIGHT
- */
-
-
-/* options */
-
-extern int encode; /* encode the resulting file */
-extern int pfbflag; /* produce compressed file */
-extern int wantafm; /* want to see .afm instead of .t1a on stdout */
-extern int correctvsize; /* try to correct the vertical size of characters */
-extern int wantuid; /* user wants UniqueID entry in the font */
-extern int allglyphs; /* convert all glyphs, not only 256 of them */
-extern int warnlevel; /* the level of permitted warnings */
-extern int forcemap; /* do mapping even on non-Unicode fonts */
-/* options - maximal limits */
-extern int max_stemdepth; /* maximal depth of stem stack in interpreter */
-/* options - debugging */
-extern int absolute; /* print out in absolute values */
-extern int reverse; /* reverse font to Type1 path directions */
-/* options - suboptions of Outline Processing */
-extern int optimize; /* enables space optimization */
-extern int smooth; /* enable smoothing of outlines */
-extern int transform; /* enables transformation to 1000x1000 matrix */
-extern int hints; /* enables autogeneration of hints */
-extern int subhints; /* enables autogeneration of substituted hints */
-extern int trybold; /* try to guess whether the font is bold */
-extern int correctwidth; /* try to correct the character width */
-extern int vectorize; /* vectorize the bitmaps */
-extern int use_autotrace; /* use the autotrace library on bitmap */
-/* options - suboptions of File Generation */
-extern int gen_pfa; /* generate the font file */
-extern int gen_afm; /* generate the metrics file */
-extern int gen_dvienc; /* generate the dvips encoding file */
-
-/* not quite options to select a particular source encoding */
-extern int force_pid; /* specific platform id */
-extern int force_eid; /* specific encoding id */
-
-/* other globals */
-extern FILE *null_file, *pfa_file, *afm_file, *dvienc_file;
-extern int numglyphs;
-
-/* warnings */
-
-#define WARNING_1 if(warnlevel >= 1)
-#define WARNING_2 if(warnlevel >= 2)
-#define WARNING_3 if(warnlevel >= 3)
-#define WARNING_4 if(warnlevel >= 4)
-
-/*
- * Bitmap control macros
- */
-
-#define BITMAP_BYTES(size) (((size)+7)>>3)
-#define DEF_BITMAP(name, size) unsigned char name[BITMAP_BYTES(size)]
-#define SET_BITMAP(name, bit) ( name[(bit)>>3] |= (1<<((bit)&7)) )
-#define CLR_BITMAP(name, bit) ( name[(bit)>>3] &= ~(1<<((bit)&7)) )
-#define IS_BITMAP(name, bit) ( name[(bit)>>3] & (1<<((bit)&7)) )
-
-/* debugging */
-
-/* debug flags */
-#define DEBUG_UNICODE 0x00000001 /* unicode to 8-bit code conversion */
-#define DEBUG_MAINSTEMS 0x00000002 /* glyph-wide main stem generation */
-#define DEBUG_SUBSTEMS 0x00000004 /* substituted stem generation */
-#define DEBUG_STEMS (DEBUG_MAINSTEMS|DEBUG_SUBSTEMS)
-#define DEBUG_REVERSAL 0x00000008 /* reversal of the paths */
-#define DEBUG_FIXCVDIR 0x00000010 /* fixcvdir() */
-#define DEBUG_STEMOVERLAP 0x00000020 /* stemoverlap() */
-#define DEBUG_BLUESTEMS 0x00000040 /* markbluestems() */
-#define DEBUG_STRAIGHTEN 0x00000080 /* markbluestems() */
-#define DEBUG_EXTMAP 0x00000100 /* parsing of external map */
-#define DEBUG_TOINT 0x00000200 /* conversion of path to integer */
-#define DEBUG_BUILDG 0x00000400 /* building of glyph path */
-#define DEBUG_QUAD 0x00000800 /* splitting curves by quadrants */
-#define DEBUG_SQEQ 0x00001000 /* square equation solver */
-#define DEBUG_COMPOSITE 0x00002000 /* handling of composite glyphs */
-#define DEBUG_FCONCISE 0x00004000 /* normalization of curves */
-#define DEBUG_FT 0x00008000 /* FreeType front-end */
-#define DEBUG_DISABLED 0x80000000 /* special flag: temporary disable debugging */
-
-/* at what we want to look now */
-#ifndef DEBUG
-# define DEBUG (0)
-#endif
-
-/* uncomment the next line if debugging data is wanted for one glyph only */
-/* #define DBG_GLYPH "_517" /* */
-
-#if DEBUG==0
-# define ISDBG(name) (0)
-# define ENABLEDBG(condition) (0)
-# define DISABLEDBG(condition) (0)
-#else
- extern int debug; /* collection of the flags */
-/* this ISDBG will only work on ANSI C, not K&R */
-# define ISDBG(name) ( (debug & DEBUG_DISABLED) ? 0 : (debug & (DEBUG_##name)) )
-# define ENABLEDBG(condition) ( (condition) ? (debug&=~DEBUG_DISABLED) : 0 )
-# define DISABLEDBG(condition) ( (condition) ? (debug|=DEBUG_DISABLED) : 0 )
-#endif
-
-#ifdef DBG_GLYPH
-# define DBG_TO_GLYPH(g) DISABLEDBG( strcmp( (g)->name, DBG_GLYPH ) )
-# define DBG_FROM_GLYPH(g) ENABLEDBG(1)
-#else
-# define DBG_TO_GLYPH(g) (0)
-# define DBG_FROM_GLYPH(g) (0)
-#endif
-
-/* prototypes */
-int iscale( int val);
-double fscale( double val);
-int unicode_rev_lookup( int unival);
-void bmp_outline( GLYPH *g, int scale, char *bmap,
- int xsz, int ysz, int xoff, int yoff);
-int isign( int x);
-int fsign( double x);
-
-/* global metrics for a font */
-
-struct font_metrics {
- /* post */
- double italic_angle;
- short underline_position;
- short underline_thickness;
- short is_fixed_pitch;
-
- /* hhea */
- short ascender;
- short descender;
-
- /* head */
- unsigned short units_per_em;
- short bbox[4];
-
- /* name */
- char *name_copyright;
- char *name_family;
- char *name_style;
- char *name_full;
- char *name_version;
- char *name_ps;
-
- /* other */
- int force_bold;
-};
-
-/* size of the encoding table - glyphs beyond 255 are actually unnumbered */
-
-#define ENCTABSZ 1024
-
-/* switch table structure for front-ends */
-
-#define MAXSUFFIX 10
-
-struct frontsw {
- char *name; /* name of the front end */
- char *descr; /* description of the front end */
- char *suffix[MAXSUFFIX]; /* possible file name suffixes */
-
- void (*open)(char *fname, char *arg); /* open font file */
- void (*close)(void); /* close font file */
- int (*nglyphs)(void); /* get the number of glyphs */
- int (*glnames)(GLYPH *glyphs); /* get the names of glyphs */
- void (*glmetrics)(GLYPH *glyphs); /* get the metrics of glyphs */
- int (*glenc)(GLYPH *glyphs, int *enc, int *unimap); /* get the encoding */
- void (*fnmetrics)(struct font_metrics *fm); /* get the font metrics */
- void (*glpath)(int glyphno, GLYPH *glyphs); /* get the glyph path */
- void (*kerning)(GLYPH *glyph_list); /* extract the kerning data */
-};
+++ /dev/null
-/*
- * see COPYRIGHT
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <time.h>
-#include <ctype.h>
-#include <math.h>
-
-#ifndef WIN32
-# include <netinet/in.h>
-# include <unistd.h>
-#else
-# include "win_missing.h"
-#endif
-
-#include "ttf.h"
-#include "pt1.h"
-#include "global.h"
-
-/* big and small values for comparisons */
-#define FBIGVAL (1e20)
-#define FEPS (100000./FBIGVAL)
-
-/* names of the axes */
-#define X 0
-#define Y 1
-
-/* the GENTRY extension structure used in fforceconcise() */
-
-struct gex_con {
- double d[2 /*X, Y*/]; /* sizes of curve */
- double sin2; /* squared sinus of the angle to the next gentry */
- double len2; /* squared distance between the endpoints */
-
-/* number of reference dots taken from each curve */
-#define NREFDOTS 3
-
- double dots[NREFDOTS][2]; /* reference dots */
-
- int flags; /* flags for gentry and tits joint to the next gentry */
-/* a vertical or horizontal line may be in 2 quadrants at once */
-#define GEXF_QUL 0x00000001 /* in up-left quadrant */
-#define GEXF_QUR 0x00000002 /* in up-right quadrant */
-#define GEXF_QDR 0x00000004 /* in down-right quadrant */
-#define GEXF_QDL 0x00000008 /* in down-left quadrant */
-#define GEXF_QMASK 0x0000000F /* quadrant mask */
-
-/* if a line is nearly vertical or horizontal, we remember that idealized quartant too */
-#define GEXF_QTO_IDEAL(f) (((f)&0xF)<<4)
-#define GEXF_QFROM_IDEAL(f) (((f)&0xF0)>>4)
-#define GEXF_IDQ_L 0x00000090 /* left */
-#define GEXF_IDQ_R 0x00000060 /* right */
-#define GEXF_IDQ_U 0x00000030 /* up */
-#define GEXF_IDQ_D 0x000000C0 /* down */
-
-/* possibly can be joined with conditions:
- * (in order of increasing preference, the numeric order is important)
- */
-#define GEXF_JLINE 0x00000100 /* into one line */
-#define GEXF_JIGN 0x00000200 /* if one entry's tangent angle is ignored */
-#define GEXF_JID 0x00000400 /* if one entry is idealized to hor/vert */
-#define GEXF_JFLAT 0x00000800 /* if one entry is flattened */
-#define GEXF_JGOOD 0x00001000 /* perfectly, no additional maodifications */
-
-#define GEXF_JMASK 0x00001F00 /* the mask of all above */
-#define GEXF_JCVMASK 0x00001E00 /* the mask of all above except JLINE */
-
-/* which entry needs to be modified for conditional joining */
-#define GEXF_JIGN1 0x00002000
-#define GEXF_JIGN2 0x00004000
-#define GEXF_JIGNDIR(dir) (GEXF_JIGN1<<(dir))
-#define GEXF_JID1 0x00008000
-#define GEXF_JID2 0x00010000
-#define GEXF_JIDDIR(dir) (GEXF_JID1<<(dir))
-#define GEXF_JFLAT1 0x00020000
-#define GEXF_JFLAT2 0x00040000
-#define GEXF_JFLATDIR(dir) (GEXF_JFLAT1<<(dir))
-
-#define GEXF_VERT 0x00100000 /* is nearly vertical */
-#define GEXF_HOR 0x00200000 /* is nearly horizontal */
-#define GEXF_FLAT 0x00400000 /* is nearly flat */
-
-#define GEXF_VDOTS 0x01000000 /* the dots are valid */
-
- signed char isd[2 /*X,Y*/]; /* signs of the sizes */
-};
-typedef struct gex_con GEX_CON;
-
-/* convenience macros */
-#define X_CON(ge) ((GEX_CON *)((ge)->ext))
-#define X_CON_D(ge) (X_CON(ge)->d)
-#define X_CON_DX(ge) (X_CON(ge)->d[0])
-#define X_CON_DY(ge) (X_CON(ge)->d[1])
-#define X_CON_ISD(ge) (X_CON(ge)->isd)
-#define X_CON_ISDX(ge) (X_CON(ge)->isd[0])
-#define X_CON_ISDY(ge) (X_CON(ge)->isd[1])
-#define X_CON_SIN2(ge) (X_CON(ge)->sin2)
-#define X_CON_LEN2(ge) (X_CON(ge)->len2)
-#define X_CON_F(ge) (X_CON(ge)->flags)
-
-/* performance statistics about guessing the concise curves */
-static int ggoodcv=0, ggoodcvdots=0, gbadcv=0, gbadcvdots=0;
-
-int stdhw, stdvw; /* dominant stems widths */
-int stemsnaph[12], stemsnapv[12]; /* most typical stem width */
-
-int bluevalues[14];
-int nblues;
-int otherblues[10];
-int notherb;
-int bbox[4]; /* the FontBBox array */
-double italic_angle;
-
-GLYPH *glyph_list;
-int encoding[ENCTABSZ]; /* inverse of glyph[].char_no */
-int kerning_pairs = 0;
-
-/* prototypes */
-static void fixcvdir( GENTRY * ge, int dir);
-static void fixcvends( GENTRY * ge);
-static int fgetcvdir( GENTRY * ge);
-static int igetcvdir( GENTRY * ge);
-static int fiszigzag( GENTRY *ge);
-static int iiszigzag( GENTRY *ge);
-static GENTRY * freethisge( GENTRY *ge);
-static void addgeafter( GENTRY *oge, GENTRY *nge );
-static GENTRY * newgentry( int flags);
-static void debugstems( char *name, STEM * hstems, int nhs, STEM * vstems, int nvs);
-static int addbluestems( STEM *s, int n);
-static void sortstems( STEM * s, int n);
-static int stemoverlap( STEM * s1, STEM * s2);
-static int steminblue( STEM *s);
-static void markbluestems( STEM *s, int nold);
-static int joinmainstems( STEM * s, int nold, int useblues);
-static void joinsubstems( STEM * s, short *pairs, int nold, int useblues);
-static void fixendpath( GENTRY *ge);
-static void fdelsmall( GLYPH *g, double minlen);
-static void alloc_gex_con( GENTRY *ge);
-static double fjointsin2( GENTRY *ge1, GENTRY *ge2);
-static double fcvarea( GENTRY *ge);
-static double fcvval( GENTRY *ge, int axis, double t);
-static void fsampledots( GENTRY *ge, double dots[][2], int ndots);
-static void fnormalizege( GENTRY *ge);
-static void fanalyzege( GENTRY *ge);
-static void fanalyzejoint( GENTRY *ge);
-static void fconcisecontour( GLYPH *g, GENTRY *ge);
-static double fclosegap( GENTRY *from, GENTRY *to, int axis,
- double gap, double *ret);
-
-int
-isign(
- int x
-)
-{
- if (x > 0)
- return 1;
- else if (x < 0)
- return -1;
- else
- return 0;
-}
-
-int
-fsign(
- double x
-)
-{
- if (x > 0.0)
- return 1;
- else if (x < 0.0)
- return -1;
- else
- return 0;
-}
-
-static GENTRY *
-newgentry(
- int flags
-)
-{
- GENTRY *ge;
-
- ge = calloc(1, sizeof(GENTRY));
-
- if (ge == 0) {
- fprintf(stderr, "***** Memory allocation error *****\n");
- exit(255);
- }
- ge->stemid = -1;
- ge->flags = flags;
- /* the rest is set to 0 by calloc() */
- return ge;
-}
-
-/*
- * Routines to print out Postscript functions with optimization
- */
-
-void
-rmoveto(
- int dx,
- int dy
-)
-{
- if (optimize && dx == 0)
- fprintf(pfa_file, "%d vmoveto\n", dy);
- else if (optimize && dy == 0)
- fprintf(pfa_file, "%d hmoveto\n", dx);
- else
- fprintf(pfa_file, "%d %d rmoveto\n", dx, dy);
-}
-
-void
-rlineto(
- int dx,
- int dy
-)
-{
- if (optimize && dx == 0 && dy == 0) /* for special pathologic
- * case */
- return;
- else if (optimize && dx == 0)
- fprintf(pfa_file, "%d vlineto\n", dy);
- else if (optimize && dy == 0)
- fprintf(pfa_file, "%d hlineto\n", dx);
- else
- fprintf(pfa_file, "%d %d rlineto\n", dx, dy);
-}
-
-void
-rrcurveto(
- int dx1,
- int dy1,
- int dx2,
- int dy2,
- int dx3,
- int dy3
-)
-{
- /* first two ifs are for crazy cases that occur surprisingly often */
- if (optimize && dx1 == 0 && dx2 == 0 && dx3 == 0)
- rlineto(0, dy1 + dy2 + dy3);
- else if (optimize && dy1 == 0 && dy2 == 0 && dy3 == 0)
- rlineto(dx1 + dx2 + dx3, 0);
- else if (optimize && dy1 == 0 && dx3 == 0)
- fprintf(pfa_file, "%d %d %d %d hvcurveto\n",
- dx1, dx2, dy2, dy3);
- else if (optimize && dx1 == 0 && dy3 == 0)
- fprintf(pfa_file, "%d %d %d %d vhcurveto\n",
- dy1, dx2, dy2, dx3);
- else
- fprintf(pfa_file, "%d %d %d %d %d %d rrcurveto\n",
- dx1, dy1, dx2, dy2, dx3, dy3);
-}
-
-void
-closepath(void)
-{
- fprintf(pfa_file, "closepath\n");
-}
-
-/*
- * Many of the path processing routines exist (or will exist) in
- * both floating-point and integer version. Fimally most of the
- * processing will go in floating point and the integer processing
- * will become legacy.
- * The names of floating routines start with f, names of integer
- * routines start with i, and those old routines existing in one
- * version only have no such prefix at all.
- */
-
-/*
-** Routine that checks integrity of the path, for debugging
-*/
-
-void
-assertpath(
- GENTRY * from,
- char *file,
- int line,
- char *name
-)
-{
- GENTRY *first, *pe, *ge;
- int isfloat;
-
- if(from==0)
- return;
- isfloat = (from->flags & GEF_FLOAT);
- pe = from->prev;
- for (ge = from; ge != 0; pe = ge, ge = ge->next) {
- if( (ge->flags & GEF_FLOAT) ^ isfloat ) {
- fprintf(stderr, "**! assertpath: called from %s line %d (%s) ****\n", file, line, name);
- fprintf(stderr, "float flag changes from %s to %s at 0x%p (type %c, prev type %c)\n",
- (isfloat ? "TRUE" : "FALSE"), (isfloat ? "FALSE" : "TRUE"), ge, ge->type, pe->type);
- abort();
- }
- if (pe != ge->prev) {
- fprintf(stderr, "**! assertpath: called from %s line %d (%s) ****\n", file, line, name);
- fprintf(stderr, "unidirectional chain 0x%x -next-> 0x%x -prev-> 0x%x \n",
- pe, ge, ge->prev);
- abort();
- }
-
- switch(ge->type) {
- case GE_MOVE:
- break;
- case GE_PATH:
- if (ge->prev == 0) {
- fprintf(stderr, "**! assertpath: called from %s line %d (%s) ****\n", file, line, name);
- fprintf(stderr, "empty path at 0x%x \n", ge);
- abort();
- }
- break;
- case GE_LINE:
- case GE_CURVE:
- if(ge->frwd->bkwd != ge) {
- fprintf(stderr, "**! assertpath: called from %s line %d (%s) ****\n", file, line, name);
- fprintf(stderr, "unidirectional chain 0x%x -frwd-> 0x%x -bkwd-> 0x%x \n",
- ge, ge->frwd, ge->frwd->bkwd);
- abort();
- }
- if(ge->prev->type == GE_MOVE) {
- first = ge;
- if(ge->bkwd->next->type != GE_PATH) {
- fprintf(stderr, "**! assertpath: called from %s line %d (%s) ****\n", file, line, name);
- fprintf(stderr, "broken first backlink 0x%x -bkwd-> 0x%x -next-> 0x%x \n",
- ge, ge->bkwd, ge->bkwd->next);
- abort();
- }
- }
- if(ge->next->type == GE_PATH) {
- if(ge->frwd != first) {
- fprintf(stderr, "**! assertpath: called from %s line %d (%s) ****\n", file, line, name);
- fprintf(stderr, "broken loop 0x%x -...-> 0x%x -frwd-> 0x%x \n",
- first, ge, ge->frwd);
- abort();
- }
- }
- break;
- }
-
- }
-}
-
-void
-assertisfloat(
- GLYPH *g,
- char *msg
-)
-{
- if( !(g->flags & GF_FLOAT) ) {
- fprintf(stderr, "**! Glyph %s is not float: %s\n", g->name, msg);
- abort();
- }
- if(g->lastentry) {
- if( !(g->lastentry->flags & GEF_FLOAT) ) {
- fprintf(stderr, "**! Glyphs %s last entry is int: %s\n", g->name, msg);
- abort();
- }
- }
-}
-
-void
-assertisint(
- GLYPH *g,
- char *msg
-)
-{
- if( (g->flags & GF_FLOAT) ) {
- fprintf(stderr, "**! Glyph %s is not int: %s\n", g->name, msg);
- abort();
- }
- if(g->lastentry) {
- if( (g->lastentry->flags & GEF_FLOAT) ) {
- fprintf(stderr, "**! Glyphs %s last entry is float: %s\n", g->name, msg);
- abort();
- }
- }
-}
-
-
-/*
- * Routines to save the generated data about glyph
- */
-
-void
-fg_rmoveto(
- GLYPH * g,
- double x,
- double y)
-{
- GENTRY *oge;
-
- if (ISDBG(BUILDG))
- fprintf(stderr, "%s: f rmoveto(%g, %g)\n", g->name, x, y);
-
- assertisfloat(g, "adding float MOVE");
-
- if ((oge = g->lastentry) != 0) {
- if (oge->type == GE_MOVE) { /* just eat up the first move */
- oge->fx3 = x;
- oge->fy3 = y;
- } else if (oge->type == GE_LINE || oge->type == GE_CURVE) {
- fprintf(stderr, "Glyph %s: MOVE in middle of path\n", g->name);
- } else {
- GENTRY *nge;
-
- nge = newgentry(GEF_FLOAT);
- nge->type = GE_MOVE;
- nge->fx3 = x;
- nge->fy3 = y;
-
- oge->next = nge;
- nge->prev = oge;
- g->lastentry = nge;
- }
- } else {
- GENTRY *nge;
-
- nge = newgentry(GEF_FLOAT);
- nge->type = GE_MOVE;
- nge->fx3 = x;
- nge->fy3 = y;
- nge->bkwd = (GENTRY*)&g->entries;
- g->entries = g->lastentry = nge;
- }
-
- if (0 && ISDBG(BUILDG))
- dumppaths(g, NULL, NULL);
-}
-
-void
-ig_rmoveto(
- GLYPH * g,
- int x,
- int y)
-{
- GENTRY *oge;
-
- if (ISDBG(BUILDG))
- fprintf(stderr, "%s: i rmoveto(%d, %d)\n", g->name, x, y);
-
- assertisint(g, "adding int MOVE");
-
- if ((oge = g->lastentry) != 0) {
- if (oge->type == GE_MOVE) { /* just eat up the first move */
- oge->ix3 = x;
- oge->iy3 = y;
- } else if (oge->type == GE_LINE || oge->type == GE_CURVE) {
- fprintf(stderr, "Glyph %s: MOVE in middle of path, ignored\n", g->name);
- } else {
- GENTRY *nge;
-
- nge = newgentry(0);
- nge->type = GE_MOVE;
- nge->ix3 = x;
- nge->iy3 = y;
-
- oge->next = nge;
- nge->prev = oge;
- g->lastentry = nge;
- }
- } else {
- GENTRY *nge;
-
- nge = newgentry(0);
- nge->type = GE_MOVE;
- nge->ix3 = x;
- nge->iy3 = y;
- nge->bkwd = (GENTRY*)&g->entries;
- g->entries = g->lastentry = nge;
- }
-
-}
-
-void
-fg_rlineto(
- GLYPH * g,
- double x,
- double y)
-{
- GENTRY *oge, *nge;
-
- if (ISDBG(BUILDG))
- fprintf(stderr, "%s: f rlineto(%g, %g)\n", g->name, x, y);
-
- assertisfloat(g, "adding float LINE");
-
- nge = newgentry(GEF_FLOAT);
- nge->type = GE_LINE;
- nge->fx3 = x;
- nge->fy3 = y;
-
- if ((oge = g->lastentry) != 0) {
- if (x == oge->fx3 && y == oge->fy3) { /* empty line */
- /* ignore it or we will get in troubles later */
- free(nge);
- return;
- }
- if (g->path == 0) {
- g->path = nge;
- nge->bkwd = nge->frwd = nge;
- } else {
- oge->frwd = nge;
- nge->bkwd = oge;
- g->path->bkwd = nge;
- nge->frwd = g->path;
- }
-
- oge->next = nge;
- nge->prev = oge;
- g->lastentry = nge;
- } else {
- WARNING_1 fprintf(stderr, "Glyph %s: LINE outside of path\n", g->name);
- free(nge);
- }
-
- if (0 && ISDBG(BUILDG))
- dumppaths(g, NULL, NULL);
-}
-
-void
-ig_rlineto(
- GLYPH * g,
- int x,
- int y)
-{
- GENTRY *oge, *nge;
-
- if (ISDBG(BUILDG))
- fprintf(stderr, "%s: i rlineto(%d, %d)\n", g->name, x, y);
-
- assertisint(g, "adding int LINE");
-
- nge = newgentry(0);
- nge->type = GE_LINE;
- nge->ix3 = x;
- nge->iy3 = y;
-
- if ((oge = g->lastentry) != 0) {
- if (x == oge->ix3 && y == oge->iy3) { /* empty line */
- /* ignore it or we will get in troubles later */
- free(nge);
- return;
- }
- if (g->path == 0) {
- g->path = nge;
- nge->bkwd = nge->frwd = nge;
- } else {
- oge->frwd = nge;
- nge->bkwd = oge;
- g->path->bkwd = nge;
- nge->frwd = g->path;
- }
-
- oge->next = nge;
- nge->prev = oge;
- g->lastentry = nge;
- } else {
- WARNING_1 fprintf(stderr, "Glyph %s: LINE outside of path\n", g->name);
- free(nge);
- }
-
-}
-
-void
-fg_rrcurveto(
- GLYPH * g,
- double x1,
- double y1,
- double x2,
- double y2,
- double x3,
- double y3)
-{
- GENTRY *oge, *nge;
-
- oge = g->lastentry;
-
- if (ISDBG(BUILDG))
- fprintf(stderr, "%s: f rrcurveto(%g, %g, %g, %g, %g, %g)\n"
- ,g->name, x1, y1, x2, y2, x3, y3);
-
- assertisfloat(g, "adding float CURVE");
-
- if (oge && oge->fx3 == x1 && x1 == x2 && x2 == x3) /* check if it's
- * actually a line */
- fg_rlineto(g, x1, y3);
- else if (oge && oge->fy3 == y1 && y1 == y2 && y2 == y3)
- fg_rlineto(g, x3, y1);
- else {
- nge = newgentry(GEF_FLOAT);
- nge->type = GE_CURVE;
- nge->fx1 = x1;
- nge->fy1 = y1;
- nge->fx2 = x2;
- nge->fy2 = y2;
- nge->fx3 = x3;
- nge->fy3 = y3;
-
- if (oge != 0) {
- if (x3 == oge->fx3 && y3 == oge->fy3) {
- free(nge); /* consider this curve empty */
- /* ignore it or we will get in troubles later */
- return;
- }
- if (g->path == 0) {
- g->path = nge;
- nge->bkwd = nge->frwd = nge;
- } else {
- oge->frwd = nge;
- nge->bkwd = oge;
- g->path->bkwd = nge;
- nge->frwd = g->path;
- }
-
- oge->next = nge;
- nge->prev = oge;
- g->lastentry = nge;
- } else {
- WARNING_1 fprintf(stderr, "Glyph %s: CURVE outside of path\n", g->name);
- free(nge);
- }
- }
-
- if (0 && ISDBG(BUILDG))
- dumppaths(g, NULL, NULL);
-}
-
-void
-ig_rrcurveto(
- GLYPH * g,
- int x1,
- int y1,
- int x2,
- int y2,
- int x3,
- int y3)
-{
- GENTRY *oge, *nge;
-
- oge = g->lastentry;
-
- if (ISDBG(BUILDG))
- fprintf(stderr, "%s: i rrcurveto(%d, %d, %d, %d, %d, %d)\n"
- ,g->name, x1, y1, x2, y2, x3, y3);
-
- assertisint(g, "adding int CURVE");
-
- if (oge && oge->ix3 == x1 && x1 == x2 && x2 == x3) /* check if it's
- * actually a line */
- ig_rlineto(g, x1, y3);
- else if (oge && oge->iy3 == y1 && y1 == y2 && y2 == y3)
- ig_rlineto(g, x3, y1);
- else {
- nge = newgentry(0);
- nge->type = GE_CURVE;
- nge->ix1 = x1;
- nge->iy1 = y1;
- nge->ix2 = x2;
- nge->iy2 = y2;
- nge->ix3 = x3;
- nge->iy3 = y3;
-
- if (oge != 0) {
- if (x3 == oge->ix3 && y3 == oge->iy3) {
- free(nge); /* consider this curve empty */
- /* ignore it or we will get in troubles later */
- return;
- }
- if (g->path == 0) {
- g->path = nge;
- nge->bkwd = nge->frwd = nge;
- } else {
- oge->frwd = nge;
- nge->bkwd = oge;
- g->path->bkwd = nge;
- nge->frwd = g->path;
- }
-
- oge->next = nge;
- nge->prev = oge;
- g->lastentry = nge;
- } else {
- WARNING_1 fprintf(stderr, "Glyph %s: CURVE outside of path\n", g->name);
- free(nge);
- }
- }
-}
-
-void
-g_closepath(
- GLYPH * g
-)
-{
- GENTRY *oge, *nge;
-
- if (ISDBG(BUILDG))
- fprintf(stderr, "%s: closepath\n", g->name);
-
- oge = g->lastentry;
-
- if (g->path == 0) {
- WARNING_1 fprintf(stderr, "Warning: **** closepath on empty path in glyph \"%s\" ****\n",
- g->name);
- if (oge == 0) {
- WARNING_1 fprintf(stderr, "No previois entry\n");
- } else {
- WARNING_1 fprintf(stderr, "Previous entry type: %c\n", oge->type);
- if (oge->type == GE_MOVE) {
- g->lastentry = oge->prev;
- if (oge->prev == 0)
- g->entries = 0;
- else
- g->lastentry->next = 0;
- free(oge);
- }
- }
- return;
- }
-
- nge = newgentry(oge->flags & GEF_FLOAT); /* keep the same type */
- nge->type = GE_PATH;
-
- g->path = 0;
-
- oge->next = nge;
- nge->prev = oge;
- g->lastentry = nge;
-
- if (0 && ISDBG(BUILDG))
- dumppaths(g, NULL, NULL);
-}
-
-/*
- * * SB * Routines to smooth and fix the glyphs
- */
-
-/*
-** we don't want to see the curves with coinciding middle and
-** outer points
-*/
-
-static void
-fixcvends(
- GENTRY * ge
-)
-{
- int dx, dy;
- int x0, y0, x1, y1, x2, y2, x3, y3;
-
- if (ge->type != GE_CURVE)
- return;
-
- if(ge->flags & GEF_FLOAT) {
- fprintf(stderr, "**! fixcvends(0x%x) on floating entry, ABORT\n", ge);
- abort(); /* dump core */
- }
-
- x0 = ge->prev->ix3;
- y0 = ge->prev->iy3;
- x1 = ge->ix1;
- y1 = ge->iy1;
- x2 = ge->ix2;
- y2 = ge->iy2;
- x3 = ge->ix3;
- y3 = ge->iy3;
-
-
- /* look at the start of the curve */
- if (x1 == x0 && y1 == y0) {
- dx = x2 - x1;
- dy = y2 - y1;
-
- if (dx == 0 && dy == 0
- || x2 == x3 && y2 == y3) {
- /* Oops, we actually have a straight line */
- /*
- * if it's small, we hope that it will get optimized
- * later
- */
- if (abs(x3 - x0) <= 2 || abs(y3 - y0) <= 2) {
- ge->ix1 = x3;
- ge->iy1 = y3;
- ge->ix2 = x0;
- ge->iy2 = y0;
- } else {/* just make it a line */
- ge->type = GE_LINE;
- }
- } else {
- if (abs(dx) < 4 && abs(dy) < 4) { /* consider it very
- * small */
- ge->ix1 = x2;
- ge->iy1 = y2;
- } else if (abs(dx) < 8 && abs(dy) < 8) { /* consider it small */
- ge->ix1 += dx / 2;
- ge->iy1 += dy / 2;
- } else {
- ge->ix1 += dx / 4;
- ge->iy1 += dy / 4;
- }
- /* make sure that it's still on the same side */
- if (abs(x3 - x0) * abs(dy) < abs(y3 - y0) * abs(dx)) {
- if (abs(x3 - x0) * abs(ge->iy1 - y0) > abs(y3 - y0) * abs(ge->ix1 - x0))
- ge->ix1 += isign(dx);
- } else {
- if (abs(x3 - x0) * abs(ge->iy1 - y0) < abs(y3 - y0) * abs(ge->ix1 - x0))
- ge->iy1 += isign(dy);
- }
-
- ge->ix2 += (x3 - x2) / 8;
- ge->iy2 += (y3 - y2) / 8;
- /* make sure that it's still on the same side */
- if (abs(x3 - x0) * abs(y3 - y2) < abs(y3 - y0) * abs(x3 - x2)) {
- if (abs(x3 - x0) * abs(y3 - ge->iy2) > abs(y3 - y0) * abs(x3 - ge->ix2))
- ge->iy1 -= isign(y3 - y2);
- } else {
- if (abs(x3 - x0) * abs(y3 - ge->iy2) < abs(y3 - y0) * abs(x3 - ge->ix2))
- ge->ix1 -= isign(x3 - x2);
- }
-
- }
- } else if (x2 == x3 && y2 == y3) {
- dx = x1 - x2;
- dy = y1 - y2;
-
- if (dx == 0 && dy == 0) {
- /* Oops, we actually have a straight line */
- /*
- * if it's small, we hope that it will get optimized
- * later
- */
- if (abs(x3 - x0) <= 2 || abs(y3 - y0) <= 2) {
- ge->ix1 = x3;
- ge->iy1 = y3;
- ge->ix2 = x0;
- ge->iy2 = y0;
- } else {/* just make it a line */
- ge->type = GE_LINE;
- }
- } else {
- if (abs(dx) < 4 && abs(dy) < 4) { /* consider it very
- * small */
- ge->ix2 = x1;
- ge->iy2 = y1;
- } else if (abs(dx) < 8 && abs(dy) < 8) { /* consider it small */
- ge->ix2 += dx / 2;
- ge->iy2 += dy / 2;
- } else {
- ge->ix2 += dx / 4;
- ge->iy2 += dy / 4;
- }
- /* make sure that it's still on the same side */
- if (abs(x3 - x0) * abs(dy) < abs(y3 - y0) * abs(dx)) {
- if (abs(x3 - x0) * abs(ge->iy2 - y3) > abs(y3 - y0) * abs(ge->ix2 - x3))
- ge->ix2 += isign(dx);
- } else {
- if (abs(x3 - x0) * abs(ge->iy2 - y3) < abs(y3 - y0) * abs(ge->ix2 - x3))
- ge->iy2 += isign(dy);
- }
-
- ge->ix1 += (x0 - x1) / 8;
- ge->iy1 += (y0 - y1) / 8;
- /* make sure that it's still on the same side */
- if (abs(x3 - x0) * abs(y0 - y1) < abs(y3 - y0) * abs(x0 - x1)) {
- if (abs(x3 - x0) * abs(y0 - ge->iy1) > abs(y3 - y0) * abs(x0 - ge->ix1))
- ge->iy1 -= isign(y0 - y1);
- } else {
- if (abs(x3 - x0) * abs(y0 - ge->iy1) < abs(y3 - y0) * abs(x0 - ge->ix1))
- ge->ix1 -= isign(x0 - x1);
- }
-
- }
- }
-}
-
-/*
-** After transformations we want to make sure that the resulting
-** curve is going in the same quadrant as the original one,
-** because rounding errors introduced during transformations
-** may make the result completeley wrong.
-**
-** `dir' argument describes the direction of the original curve,
-** it is the superposition of two values for the front and
-** rear ends of curve:
-**
-** >EQUAL - goes over the line connecting the ends
-** =EQUAL - coincides with the line connecting the ends
-** <EQUAL - goes under the line connecting the ends
-**
-** See CVDIR_* for exact definitions.
-*/
-
-static void
-fixcvdir(
- GENTRY * ge,
- int dir
-)
-{
- int a, b, c, d;
- double kk, kk1, kk2;
- int changed;
- int fdir, rdir;
-
- if(ge->flags & GEF_FLOAT) {
- fprintf(stderr, "**! fixcvdir(0x%x) on floating entry, ABORT\n", ge);
- abort(); /* dump core */
- }
-
- fdir = (dir & CVDIR_FRONT) - CVDIR_FEQUAL;
- if ((dir & CVDIR_REAR) == CVDIR_RSAME)
- rdir = fdir; /* we need only isign, exact value doesn't matter */
- else
- rdir = (dir & CVDIR_REAR) - CVDIR_REQUAL;
-
- fixcvends(ge);
-
- c = isign(ge->ix3 - ge->prev->ix3); /* note the direction of
- * curve */
- d = isign(ge->iy3 - ge->prev->iy3);
-
- a = ge->iy3 - ge->prev->iy3;
- b = ge->ix3 - ge->prev->ix3;
- kk = fabs(a == 0 ? (b == 0 ? 1. : 100000.) : ((double) b / (double) a));
- a = ge->iy1 - ge->prev->iy3;
- b = ge->ix1 - ge->prev->ix3;
- kk1 = fabs(a == 0 ? (b == 0 ? 1. : 100000.) : ((double) b / (double) a));
- a = ge->iy3 - ge->iy2;
- b = ge->ix3 - ge->ix2;
- kk2 = fabs(a == 0 ? (b == 0 ? 1. : 100000.) : ((double) b / (double) a));
-
- changed = 1;
- while (changed) {
- if (ISDBG(FIXCVDIR)) {
- /* for debugging */
- fprintf(stderr, "fixcvdir %d %d (%d %d %d %d %d %d) %f %f %f\n",
- fdir, rdir,
- ge->ix1 - ge->prev->ix3,
- ge->iy1 - ge->prev->iy3,
- ge->ix2 - ge->ix1,
- ge->iy2 - ge->iy1,
- ge->ix3 - ge->ix2,
- ge->iy3 - ge->iy2,
- kk1, kk, kk2);
- }
- changed = 0;
-
- if (fdir > 0) {
- if (kk1 > kk) { /* the front end has problems */
- if (c * (ge->ix1 - ge->prev->ix3) > 0) {
- ge->ix1 -= c;
- changed = 1;
- } if (d * (ge->iy2 - ge->iy1) > 0) {
- ge->iy1 += d;
- changed = 1;
- }
- /* recalculate the coefficients */
- a = ge->iy3 - ge->prev->iy3;
- b = ge->ix3 - ge->prev->ix3;
- kk = fabs(a == 0 ? (b == 0 ? 1. : 100000.) : ((double) b / (double) a));
- a = ge->iy1 - ge->prev->iy3;
- b = ge->ix1 - ge->prev->ix3;
- kk1 = fabs(a == 0 ? (b == 0 ? 1. : 100000.) : ((double) b / (double) a));
- }
- } else if (fdir < 0) {
- if (kk1 < kk) { /* the front end has problems */
- if (c * (ge->ix2 - ge->ix1) > 0) {
- ge->ix1 += c;
- changed = 1;
- } if (d * (ge->iy1 - ge->prev->iy3) > 0) {
- ge->iy1 -= d;
- changed = 1;
- }
- /* recalculate the coefficients */
- a = ge->iy1 - ge->prev->iy3;
- b = ge->ix1 - ge->prev->ix3;
- kk1 = fabs(a == 0 ? (b == 0 ? 1. : 100000.) : ((double) b / (double) a));
- a = ge->iy3 - ge->prev->iy3;
- b = ge->ix3 - ge->prev->ix3;
- kk = fabs(a == 0 ? (b == 0 ? 1. : 100000.) : ((double) b / (double) a));
- }
- }
- if (rdir > 0) {
- if (kk2 < kk) { /* the rear end has problems */
- if (c * (ge->ix2 - ge->ix1) > 0) {
- ge->ix2 -= c;
- changed = 1;
- } if (d * (ge->iy3 - ge->iy2) > 0) {
- ge->iy2 += d;
- changed = 1;
- }
- /* recalculate the coefficients */
- a = ge->iy3 - ge->prev->iy3;
- b = ge->ix3 - ge->prev->ix3;
- kk = fabs(a == 0 ? (b == 0 ? 1. : 100000.) : ((double) b / (double) a));
- a = ge->iy3 - ge->iy2;
- b = ge->ix3 - ge->ix2;
- kk2 = fabs(a == 0 ? (b == 0 ? 1. : 100000.) : ((double) b / (double) a));
- }
- } else if (rdir < 0) {
- if (kk2 > kk) { /* the rear end has problems */
- if (c * (ge->ix3 - ge->ix2) > 0) {
- ge->ix2 += c;
- changed = 1;
- } if (d * (ge->iy2 - ge->iy1) > 0) {
- ge->iy2 -= d;
- changed = 1;
- }
- /* recalculate the coefficients */
- a = ge->iy3 - ge->prev->iy3;
- b = ge->ix3 - ge->prev->ix3;
- kk = fabs(a == 0 ? (b == 0 ? 1. : 100000.) : ((double) b / (double) a));
- a = ge->iy3 - ge->iy2;
- b = ge->ix3 - ge->ix2;
- kk2 = fabs(a == 0 ? (b == 0 ? 1. : 100000.) : ((double) b / (double) a));
- }
- }
- }
- fixcvends(ge);
-}
-
-/* Get the directions of ends of curve for further usage */
-
-/* expects that the previous element is also float */
-
-static int
-fgetcvdir(
- GENTRY * ge
-)
-{
- double a, b;
- double k, k1, k2;
- int dir = 0;
-
- if( !(ge->flags & GEF_FLOAT) ) {
- fprintf(stderr, "**! fgetcvdir(0x%x) on int entry, ABORT\n", ge);
- abort(); /* dump core */
- }
-
- a = fabs(ge->fy3 - ge->prev->fy3);
- b = fabs(ge->fx3 - ge->prev->fx3);
- k = a < FEPS ? (b < FEPS ? 1. : 100000.) : ( b / a);
-
- a = fabs(ge->fy1 - ge->prev->fy3);
- b = fabs(ge->fx1 - ge->prev->fx3);
- if(a < FEPS) {
- if(b < FEPS) {
- a = fabs(ge->fy2 - ge->prev->fy3);
- b = fabs(ge->fx2 - ge->prev->fx3);
- k1 = a < FEPS ? (b < FEPS ? k : 100000.) : ( b / a);
- } else
- k1 = FBIGVAL;
- } else
- k1 = b / a;
-
- a = fabs(ge->fy3 - ge->fy2);
- b = fabs(ge->fx3 - ge->fx2);
- if(a < FEPS) {
- if(b < FEPS) {
- a = fabs(ge->fy3 - ge->fy1);
- b = fabs(ge->fx3 - ge->fx1);
- k2 = a < FEPS ? (b < FEPS ? k : 100000.) : ( b / a);
- } else
- k2 = FBIGVAL;
- } else
- k2 = b / a;
-
- if(fabs(k1-k) < 0.0001)
- dir |= CVDIR_FEQUAL;
- else if (k1 < k)
- dir |= CVDIR_FUP;
- else
- dir |= CVDIR_FDOWN;
-
- if(fabs(k2-k) < 0.0001)
- dir |= CVDIR_REQUAL;
- else if (k2 > k)
- dir |= CVDIR_RUP;
- else
- dir |= CVDIR_RDOWN;
-
- return dir;
-}
-
-
-/* expects that the previous element is also int */
-
-static int
-igetcvdir(
- GENTRY * ge
-)
-{
- int a, b;
- double k, k1, k2;
- int dir = 0;
-
- if(ge->flags & GEF_FLOAT) {
- fprintf(stderr, "**! igetcvdir(0x%x) on floating entry, ABORT\n", ge);
- abort(); /* dump core */
- }
-
- a = ge->iy3 - ge->prev->iy3;
- b = ge->ix3 - ge->prev->ix3;
- k = (a == 0) ? (b == 0 ? 1. : 100000.) : fabs((double) b / (double) a);
-
- a = ge->iy1 - ge->prev->iy3;
- b = ge->ix1 - ge->prev->ix3;
- if(a == 0) {
- if(b == 0) {
- a = ge->iy2 - ge->prev->iy3;
- b = ge->ix2 - ge->prev->ix3;
- k1 = (a == 0) ? (b == 0 ? k : 100000.) : fabs((double) b / (double) a);
- } else
- k1 = FBIGVAL;
- } else
- k1 = fabs((double) b / (double) a);
-
- a = ge->iy3 - ge->iy2;
- b = ge->ix3 - ge->ix2;
- if(a == 0) {
- if(b == 0) {
- a = ge->iy3 - ge->iy1;
- b = ge->ix3 - ge->ix1;
- k2 = (a == 0) ? (b == 0 ? k : 100000.) : fabs((double) b / (double) a);
- } else
- k2 = FBIGVAL;
- } else
- k2 = fabs((double) b / (double) a);
-
- if(fabs(k1-k) < 0.0001)
- dir |= CVDIR_FEQUAL;
- else if (k1 < k)
- dir |= CVDIR_FUP;
- else
- dir |= CVDIR_FDOWN;
-
- if(fabs(k2-k) < 0.0001)
- dir |= CVDIR_REQUAL;
- else if (k2 > k)
- dir |= CVDIR_RUP;
- else
- dir |= CVDIR_RDOWN;
-
- return dir;
-}
-
-#if 0
-/* a function just to test the work of fixcvdir() */
-static void
-testfixcvdir(
- GLYPH * g
-)
-{
- GENTRY *ge;
- int dir;
-
- for (ge = g->entries; ge != 0; ge = ge->next) {
- if (ge->type == GE_CURVE) {
- dir = igetcvdir(ge);
- fixcvdir(ge, dir);
- }
- }
-}
-#endif
-
-static int
-iround(
- double val
-)
-{
- return (int) (val > 0 ? val + 0.5 : val - 0.5);
-}
-
-/* for debugging - dump the glyph
- * mark with a star the entries from start to end inclusive
- * (start == NULL means don't mark any, end == NULL means to the last)
- */
-
-void
-dumppaths(
- GLYPH *g,
- GENTRY *start,
- GENTRY *end
-)
-{
- GENTRY *ge;
- int i;
- char mark=' ';
-
- fprintf(stderr, "Glyph %s:\n", g->name);
-
- /* now do the conversion */
- for(ge = g->entries; ge != 0; ge = ge->next) {
- if(ge == start)
- mark = '*';
- fprintf(stderr, " %c %8x", mark, ge);
- switch(ge->type) {
- case GE_MOVE:
- case GE_LINE:
- if(ge->flags & GEF_FLOAT)
- fprintf(stderr," %c float (%g, %g)\n", ge->type, ge->fx3, ge->fy3);
- else
- fprintf(stderr," %c int (%d, %d)\n", ge->type, ge->ix3, ge->iy3);
- break;
- case GE_CURVE:
- if(ge->flags & GEF_FLOAT) {
- fprintf(stderr," C float ");
- for(i=0; i<3; i++)
- fprintf(stderr,"(%g, %g) ", ge->fxn[i], ge->fyn[i]);
- fprintf(stderr,"\n");
- } else {
- fprintf(stderr," C int ");
- for(i=0; i<3; i++)
- fprintf(stderr,"(%d, %d) ", ge->ixn[i], ge->iyn[i]);
- fprintf(stderr,"\n");
- }
- break;
- default:
- fprintf(stderr, " %c\n", ge->type);
- break;
- }
- if(ge == end)
- mark = ' ';
- }
-}
-
-/*
- * Routine that converts all entries in the path from float to int
- */
-
-void
-pathtoint(
- GLYPH *g
-)
-{
- GENTRY *ge;
- int x[3], y[3];
- int i;
-
-
- if(ISDBG(TOINT))
- fprintf(stderr, "TOINT: glyph %s\n", g->name);
- assertisfloat(g, "converting path to int\n");
-
- fdelsmall(g, 1.0); /* get rid of sub-pixel contours */
- assertpath(g->entries, __FILE__, __LINE__, g->name);
-
- /* 1st pass, collect the directions of the curves: have
- * to do that in advance, while everyting is float
- */
- for(ge = g->entries; ge != 0; ge = ge->next) {
- if( !(ge->flags & GEF_FLOAT) ) {
- fprintf(stderr, "**! glyphs %s has int entry, found in conversion to int\n",
- g->name);
- exit(1);
- }
- if(ge->type == GE_CURVE) {
- ge->dir = fgetcvdir(ge);
- }
- }
-
- /* now do the conversion */
- for(ge = g->entries; ge != 0; ge = ge->next) {
- switch(ge->type) {
- case GE_MOVE:
- case GE_LINE:
- if(ISDBG(TOINT))
- fprintf(stderr," %c float x=%g y=%g\n", ge->type, ge->fx3, ge->fy3);
- x[0] = iround(ge->fx3);
- y[0] = iround(ge->fy3);
- for(i=0; i<3; i++) { /* put some valid values everywhere, for convenience */
- ge->ixn[i] = x[0];
- ge->iyn[i] = y[0];
- }
- if(ISDBG(TOINT))
- fprintf(stderr," int x=%d y=%d\n", ge->ix3, ge->iy3);
- break;
- case GE_CURVE:
- if(ISDBG(TOINT))
- fprintf(stderr," %c float ", ge->type);
-
- for(i=0; i<3; i++) {
- if(ISDBG(TOINT))
- fprintf(stderr,"(%g, %g) ", ge->fxn[i], ge->fyn[i]);
- x[i] = iround(ge->fxn[i]);
- y[i] = iround(ge->fyn[i]);
- }
-
- if(ISDBG(TOINT))
- fprintf(stderr,"\n int ");
-
- for(i=0; i<3; i++) {
- ge->ixn[i] = x[i];
- ge->iyn[i] = y[i];
- if(ISDBG(TOINT))
- fprintf(stderr,"(%d, %d) ", ge->ixn[i], ge->iyn[i]);
- }
- ge->flags &= ~GEF_FLOAT; /* for fixcvdir */
- fixcvdir(ge, ge->dir);
-
- if(ISDBG(TOINT)) {
- fprintf(stderr,"\n fixed ");
- for(i=0; i<3; i++)
- fprintf(stderr,"(%d, %d) ", ge->ixn[i], ge->iyn[i]);
- fprintf(stderr,"\n");
- }
-
- break;
- }
- ge->flags &= ~GEF_FLOAT;
- }
- g->flags &= ~GF_FLOAT;
-}
-
-
-/* check whether we can fix up the curve to change its size by (dx,dy) */
-/* 0 means NO, 1 means YES */
-
-/* for float: if scaling would be under 10% */
-
-int
-fcheckcv(
- GENTRY * ge,
- double dx,
- double dy
-)
-{
- if( !(ge->flags & GEF_FLOAT) ) {
- fprintf(stderr, "**! fcheckcv(0x%x) on int entry, ABORT\n", ge);
- abort(); /* dump core */
- }
-
- if (ge->type != GE_CURVE)
- return 0;
-
- if( fabs(ge->fx3 - ge->prev->fx3) < fabs(dx) * 10 )
- return 0;
-
- if( fabs(ge->fy3 - ge->prev->fy3) < fabs(dy) * 10 )
- return 0;
-
- return 1;
-}
-
-/* for int: if won't create new zigzags at the ends */
-
-int
-icheckcv(
- GENTRY * ge,
- int dx,
- int dy
-)
-{
- int xdep, ydep;
-
- if(ge->flags & GEF_FLOAT) {
- fprintf(stderr, "**! icheckcv(0x%x) on floating entry, ABORT\n", ge);
- abort(); /* dump core */
- }
-
- if (ge->type != GE_CURVE)
- return 0;
-
- xdep = ge->ix3 - ge->prev->ix3;
- ydep = ge->iy3 - ge->prev->iy3;
-
- if (ge->type == GE_CURVE
- && (xdep * (xdep + dx)) > 0
- && (ydep * (ydep + dy)) > 0) {
- return 1;
- } else
- return 0;
-}
-
-/* float connect the ends of open contours */
-
-void
-fclosepaths(
- GLYPH * g
-)
-{
- GENTRY *ge, *fge, *xge, *nge;
- int i;
-
- assertisfloat(g, "fclosepaths float\n");
-
- for (xge = g->entries; xge != 0; xge = xge->next) {
- if( xge->type != GE_PATH )
- continue;
-
- ge = xge->prev;
- if(ge == 0 || ge->type != GE_LINE && ge->type!= GE_CURVE) {
- fprintf(stderr, "**! Glyph %s got empty path\n",
- g->name);
- exit(1);
- }
-
- fge = ge->frwd;
- if (fge->prev == 0 || fge->prev->type != GE_MOVE) {
- fprintf(stderr, "**! Glyph %s got strange beginning of path\n",
- g->name);
- exit(1);
- }
- fge = fge->prev;
- if (fge->fx3 != ge->fx3 || fge->fy3 != ge->fy3) {
- /* we have to fix this open path */
-
- WARNING_4 fprintf(stderr, "Glyph %s got path open by dx=%g dy=%g\n",
- g->name, fge->fx3 - ge->fx3, fge->fy3 - ge->fy3);
-
-
- /* add a new line */
- nge = newgentry(GEF_FLOAT);
- (*nge) = (*ge);
- nge->fx3 = fge->fx3;
- nge->fy3 = fge->fy3;
- nge->type = GE_LINE;
-
- addgeafter(ge, nge);
-
- if (fabs(ge->fx3 - fge->fx3) <= 2 && fabs(ge->fy3 - fge->fy3) <= 2) {
- /*
- * small change, try to get rid of the new entry
- */
-
- double df[2];
-
- for(i=0; i<2; i++) {
- df[i] = ge->fpoints[i][2] - fge->fpoints[i][2];
- df[i] = fclosegap(nge, nge, i, df[i], NULL);
- }
-
- if(df[0] == 0. && df[1] == 0.) {
- /* closed gap successfully, remove the added entry */
- freethisge(nge);
- }
- }
- }
- }
-}
-
-void
-smoothjoints(
- GLYPH * g
-)
-{
- GENTRY *ge, *ne;
- int dx1, dy1, dx2, dy2, k;
- int dir;
-
- return; /* this stuff seems to create problems */
-
- assertisint(g, "smoothjoints int");
-
- if (g->entries == 0) /* nothing to do */
- return;
-
- for (ge = g->entries->next; ge != 0; ge = ge->next) {
- ne = ge->frwd;
-
- /*
- * although there should be no one-line path * and any path
- * must end with CLOSEPATH, * nobody can say for sure
- */
-
- if (ge == ne || ne == 0)
- continue;
-
- /* now handle various joints */
-
- if (ge->type == GE_LINE && ne->type == GE_LINE) {
- dx1 = ge->ix3 - ge->prev->ix3;
- dy1 = ge->iy3 - ge->prev->iy3;
- dx2 = ne->ix3 - ge->ix3;
- dy2 = ne->iy3 - ge->iy3;
-
- /* check whether they have the same direction */
- /* and the same slope */
- /* then we can join them into one line */
-
- if (dx1 * dx2 >= 0 && dy1 * dy2 >= 0 && dx1 * dy2 == dy1 * dx2) {
- /* extend the previous line */
- ge->ix3 = ne->ix3;
- ge->iy3 = ne->iy3;
-
- /* and get rid of the next line */
- freethisge(ne);
- }
- } else if (ge->type == GE_LINE && ne->type == GE_CURVE) {
- fixcvends(ne);
-
- dx1 = ge->ix3 - ge->prev->ix3;
- dy1 = ge->iy3 - ge->prev->iy3;
- dx2 = ne->ix1 - ge->ix3;
- dy2 = ne->iy1 - ge->iy3;
-
- /* if the line is nearly horizontal and we can fix it */
- if (dx1 != 0 && 5 * abs(dy1) / abs(dx1) == 0
- && icheckcv(ne, 0, -dy1)
- && abs(dy1) <= 4) {
- dir = igetcvdir(ne);
- ge->iy3 -= dy1;
- ne->iy1 -= dy1;
- fixcvdir(ne, dir);
- if (ge->next != ne)
- ne->prev->iy3 -= dy1;
- dy1 = 0;
- } else if (dy1 != 0 && 5 * abs(dx1) / abs(dy1) == 0
- && icheckcv(ne, -dx1, 0)
- && abs(dx1) <= 4) {
- /* the same but vertical */
- dir = igetcvdir(ne);
- ge->ix3 -= dx1;
- ne->ix1 -= dx1;
- fixcvdir(ne, dir);
- if (ge->next != ne)
- ne->prev->ix3 -= dx1;
- dx1 = 0;
- }
- /*
- * if line is horizontal and curve begins nearly
- * horizontally
- */
- if (dy1 == 0 && dx2 != 0 && 5 * abs(dy2) / abs(dx2) == 0) {
- dir = igetcvdir(ne);
- ne->iy1 -= dy2;
- fixcvdir(ne, dir);
- dy2 = 0;
- } else if (dx1 == 0 && dy2 != 0 && 5 * abs(dx2) / abs(dy2) == 0) {
- /* the same but vertical */
- dir = igetcvdir(ne);
- ne->ix1 -= dx2;
- fixcvdir(ne, dir);
- dx2 = 0;
- }
- } else if (ge->type == GE_CURVE && ne->type == GE_LINE) {
- fixcvends(ge);
-
- dx1 = ge->ix3 - ge->ix2;
- dy1 = ge->iy3 - ge->iy2;
- dx2 = ne->ix3 - ge->ix3;
- dy2 = ne->iy3 - ge->iy3;
-
- /* if the line is nearly horizontal and we can fix it */
- if (dx2 != 0 && 5 * abs(dy2) / abs(dx2) == 0
- && icheckcv(ge, 0, dy2)
- && abs(dy2) <= 4) {
- dir = igetcvdir(ge);
- ge->iy3 += dy2;
- ge->iy2 += dy2;
- fixcvdir(ge, dir);
- if (ge->next != ne)
- ne->prev->iy3 += dy2;
- dy2 = 0;
- } else if (dy2 != 0 && 5 * abs(dx2) / abs(dy2) == 0
- && icheckcv(ge, dx2, 0)
- && abs(dx2) <= 4) {
- /* the same but vertical */
- dir = igetcvdir(ge);
- ge->ix3 += dx2;
- ge->ix2 += dx2;
- fixcvdir(ge, dir);
- if (ge->next != ne)
- ne->prev->ix3 += dx2;
- dx2 = 0;
- }
- /*
- * if line is horizontal and curve ends nearly
- * horizontally
- */
- if (dy2 == 0 && dx1 != 0 && 5 * abs(dy1) / abs(dx1) == 0) {
- dir = igetcvdir(ge);
- ge->iy2 += dy1;
- fixcvdir(ge, dir);
- dy1 = 0;
- } else if (dx2 == 0 && dy1 != 0 && 5 * abs(dx1) / abs(dy1) == 0) {
- /* the same but vertical */
- dir = igetcvdir(ge);
- ge->ix2 += dx1;
- fixcvdir(ge, dir);
- dx1 = 0;
- }
- } else if (ge->type == GE_CURVE && ne->type == GE_CURVE) {
- fixcvends(ge);
- fixcvends(ne);
-
- dx1 = ge->ix3 - ge->ix2;
- dy1 = ge->iy3 - ge->iy2;
- dx2 = ne->ix1 - ge->ix3;
- dy2 = ne->iy1 - ge->iy3;
-
- /*
- * check if we have a rather smooth joint at extremal
- * point
- */
- /* left or right extremal point */
- if (abs(dx1) <= 4 && abs(dx2) <= 4
- && dy1 != 0 && 5 * abs(dx1) / abs(dy1) == 0
- && dy2 != 0 && 5 * abs(dx2) / abs(dy2) == 0
- && (ge->iy3 < ge->prev->iy3 && ne->iy3 < ge->iy3
- || ge->iy3 > ge->prev->iy3 && ne->iy3 > ge->iy3)
- && (ge->ix3 - ge->prev->ix3) * (ne->ix3 - ge->ix3) < 0
- ) {
- dir = igetcvdir(ge);
- ge->ix2 += dx1;
- dx1 = 0;
- fixcvdir(ge, dir);
- dir = igetcvdir(ne);
- ne->ix1 -= dx2;
- dx2 = 0;
- fixcvdir(ne, dir);
- }
- /* top or down extremal point */
- else if (abs(dy1) <= 4 && abs(dy2) <= 4
- && dx1 != 0 && 5 * abs(dy1) / abs(dx1) == 0
- && dx2 != 0 && 5 * abs(dy2) / abs(dx2) == 0
- && (ge->ix3 < ge->prev->ix3 && ne->ix3 < ge->ix3
- || ge->ix3 > ge->prev->ix3 && ne->ix3 > ge->ix3)
- && (ge->iy3 - ge->prev->iy3) * (ne->iy3 - ge->iy3) < 0
- ) {
- dir = igetcvdir(ge);
- ge->iy2 += dy1;
- dy1 = 0;
- fixcvdir(ge, dir);
- dir = igetcvdir(ne);
- ne->iy1 -= dy2;
- dy2 = 0;
- fixcvdir(ne, dir);
- }
- /* or may be we just have a smooth junction */
- else if (dx1 * dx2 >= 0 && dy1 * dy2 >= 0
- && 10 * abs(k = abs(dx1 * dy2) - abs(dy1 * dx2)) < (abs(dx1 * dy2) + abs(dy1 * dx2))) {
- int tries[6][4];
- int results[6];
- int i, b;
-
- /* build array of changes we are going to try */
- /* uninitalized entries are 0 */
- if (k > 0) {
- static int t1[6][4] = {
- {0, 0, 0, 0},
- {-1, 0, 1, 0},
- {-1, 0, 0, 1},
- {0, -1, 1, 0},
- {0, -1, 0, 1},
- {-1, -1, 1, 1}};
- memcpy(tries, t1, sizeof tries);
- } else {
- static int t1[6][4] = {
- {0, 0, 0, 0},
- {1, 0, -1, 0},
- {1, 0, 0, -1},
- {0, 1, -1, 0},
- {0, 1, 0, -1},
- {1, 1, -1, -1}};
- memcpy(tries, t1, sizeof tries);
- }
-
- /* now try the changes */
- results[0] = abs(k);
- for (i = 1; i < 6; i++) {
- results[i] = abs((abs(dx1) + tries[i][0]) * (abs(dy2) + tries[i][1]) -
- (abs(dy1) + tries[i][2]) * (abs(dx2) + tries[i][3]));
- }
-
- /* and find the best try */
- k = abs(k);
- b = 0;
- for (i = 1; i < 6; i++)
- if (results[i] < k) {
- k = results[i];
- b = i;
- }
- /* and finally apply it */
- if (dx1 < 0)
- tries[b][0] = -tries[b][0];
- if (dy2 < 0)
- tries[b][1] = -tries[b][1];
- if (dy1 < 0)
- tries[b][2] = -tries[b][2];
- if (dx2 < 0)
- tries[b][3] = -tries[b][3];
-
- dir = igetcvdir(ge);
- ge->ix2 -= tries[b][0];
- ge->iy2 -= tries[b][2];
- fixcvdir(ge, dir);
- dir = igetcvdir(ne);
- ne->ix1 += tries[b][3];
- ne->iy1 += tries[b][1];
- fixcvdir(ne, dir);
- }
- }
- }
-}
-
-/* debugging: print out stems of a glyph */
-static void
-debugstems(
- char *name,
- STEM * hstems,
- int nhs,
- STEM * vstems,
- int nvs
-)
-{
- int i;
-
- fprintf(pfa_file, "%% %s\n", name);
- fprintf(pfa_file, "%% %d horizontal stems:\n", nhs);
- for (i = 0; i < nhs; i++)
- fprintf(pfa_file, "%% %3d %d (%d...%d) %c %c%c%c%c\n", i, hstems[i].value,
- hstems[i].from, hstems[i].to,
- ((hstems[i].flags & ST_UP) ? 'U' : 'D'),
- ((hstems[i].flags & ST_END) ? 'E' : '-'),
- ((hstems[i].flags & ST_FLAT) ? 'F' : '-'),
- ((hstems[i].flags & ST_ZONE) ? 'Z' : ' '),
- ((hstems[i].flags & ST_TOPZONE) ? 'T' : ' '));
- fprintf(pfa_file, "%% %d vertical stems:\n", nvs);
- for (i = 0; i < nvs; i++)
- fprintf(pfa_file, "%% %3d %d (%d...%d) %c %c%c\n", i, vstems[i].value,
- vstems[i].from, vstems[i].to,
- ((vstems[i].flags & ST_UP) ? 'U' : 'D'),
- ((vstems[i].flags & ST_END) ? 'E' : '-'),
- ((vstems[i].flags & ST_FLAT) ? 'F' : '-'));
-}
-
-/* add pseudo-stems for the limits of the Blue zones to the stem array */
-static int
-addbluestems(
- STEM *s,
- int n
-)
-{
- int i;
-
- for(i=0; i<nblues && i<2; i+=2) { /* baseline */
- s[n].value=bluevalues[i];
- s[n].flags=ST_UP|ST_ZONE;
- /* don't overlap with anything */
- s[n].origin=s[n].from=s[n].to= -10000+i;
- n++;
- s[n].value=bluevalues[i+1];
- s[n].flags=ST_ZONE;
- /* don't overlap with anything */
- s[n].origin=s[n].from=s[n].to= -10000+i+1;
- n++;
- }
- for(i=2; i<nblues; i+=2) { /* top zones */
- s[n].value=bluevalues[i];
- s[n].flags=ST_UP|ST_ZONE|ST_TOPZONE;
- /* don't overlap with anything */
- s[n].origin=s[n].from=s[n].to= -10000+i;
- n++;
- s[n].value=bluevalues[i+1];
- s[n].flags=ST_ZONE|ST_TOPZONE;
- /* don't overlap with anything */
- s[n].origin=s[n].from=s[n].to= -10000+i+1;
- n++;
- }
- for(i=0; i<notherb; i+=2) { /* bottom zones */
- s[n].value=otherblues[i];
- s[n].flags=ST_UP|ST_ZONE;
- /* don't overlap with anything */
- s[n].origin=s[n].from=s[n].to= -10000+i+nblues;
- n++;
- s[n].value=otherblues[i+1];
- s[n].flags=ST_ZONE;
- /* don't overlap with anything */
- s[n].origin=s[n].from=s[n].to= -10000+i+1+nblues;
- n++;
- }
- return n;
-}
-
-/* sort stems in array */
-static void
-sortstems(
- STEM * s,
- int n
-)
-{
- int i, j;
- STEM x;
-
-
- /* a simple sorting */
- /* hm, the ordering criteria are not quite simple :-)
- * if the values are tied
- * ST_UP always goes under not ST_UP
- * ST_ZONE goes on the most outer side
- * ST_END goes towards inner side after ST_ZONE
- * ST_FLAT goes on the inner side
- */
-
- for (i = 0; i < n; i++)
- for (j = i + 1; j < n; j++) {
- if(s[i].value < s[j].value)
- continue;
- if(s[i].value == s[j].value) {
- if( (s[i].flags & ST_UP) < (s[j].flags & ST_UP) )
- continue;
- if( (s[i].flags & ST_UP) == (s[j].flags & ST_UP) ) {
- if( s[i].flags & ST_UP ) {
- if(
- (s[i].flags & (ST_ZONE|ST_FLAT|ST_END) ^ ST_FLAT)
- >
- (s[j].flags & (ST_ZONE|ST_FLAT|ST_END) ^ ST_FLAT)
- )
- continue;
- } else {
- if(
- (s[i].flags & (ST_ZONE|ST_FLAT|ST_END) ^ ST_FLAT)
- <
- (s[j].flags & (ST_ZONE|ST_FLAT|ST_END) ^ ST_FLAT)
- )
- continue;
- }
- }
- }
- x = s[j];
- s[j] = s[i];
- s[i] = x;
- }
-}
-
-/* check whether two stem borders overlap */
-
-static int
-stemoverlap(
- STEM * s1,
- STEM * s2
-)
-{
- int result;
-
- if (s1->from <= s2->from && s1->to >= s2->from
- || s2->from <= s1->from && s2->to >= s1->from)
- result = 1;
- else
- result = 0;
-
- if (ISDBG(STEMOVERLAP))
- fprintf(pfa_file, "%% overlap %d(%d..%d)x%d(%d..%d)=%d\n",
- s1->value, s1->from, s1->to, s2->value, s2->from, s2->to, result);
- return result;
-}
-
-/*
- * check if the stem [border] is in an appropriate blue zone
- * (currently not used)
- */
-
-static int
-steminblue(
- STEM *s
-)
-{
- int i, val;
-
- val=s->value;
- if(s->flags & ST_UP) {
- /* painted size up, look at lower zones */
- if(nblues>=2 && val>=bluevalues[0] && val<=bluevalues[1] )
- return 1;
- for(i=0; i<notherb; i++) {
- if( val>=otherblues[i] && val<=otherblues[i+1] )
- return 1;
- }
- } else {
- /* painted side down, look at upper zones */
- for(i=2; i<nblues; i++) {
- if( val>=bluevalues[i] && val<=bluevalues[i+1] )
- return 1;
- }
- }
-
- return 0;
-}
-
-/* mark the outermost stem [borders] in the blue zones */
-
-static void
-markbluestems(
- STEM *s,
- int nold
-)
-{
- int i, j, a, b, c;
- /*
- * traverse the list of Blue Values, mark the lowest upper
- * stem in each bottom zone and the topmost lower stem in
- * each top zone with ST_BLUE
- */
-
- /* top zones */
- for(i=2; i<nblues; i+=2) {
- a=bluevalues[i]; b=bluevalues[i+1];
- if(ISDBG(BLUESTEMS))
- fprintf(pfa_file, "%% looking at blue zone %d...%d\n", a, b);
- for(j=nold-1; j>=0; j--) {
- if( s[j].flags & (ST_ZONE|ST_UP|ST_END) )
- continue;
- c=s[j].value;
- if(c<a) /* too low */
- break;
- if(c<=b) { /* found the topmost stem border */
- /* mark all the stems with the same value */
- if(ISDBG(BLUESTEMS))
- fprintf(pfa_file, "%% found D BLUE at %d\n", s[j].value);
- /* include ST_END values */
- while( s[j+1].value==c && (s[j+1].flags & ST_ZONE)==0 )
- j++;
- s[j].flags |= ST_BLUE;
- for(j--; j>=0 && s[j].value==c
- && (s[j].flags & (ST_UP|ST_ZONE))==0 ; j--)
- s[j].flags |= ST_BLUE;
- break;
- }
- }
- }
- /* baseline */
- if(nblues>=2) {
- a=bluevalues[0]; b=bluevalues[1];
- for(j=0; j<nold; j++) {
- if( (s[j].flags & (ST_ZONE|ST_UP|ST_END))!=ST_UP )
- continue;
- c=s[j].value;
- if(c>b) /* too high */
- break;
- if(c>=a) { /* found the lowest stem border */
- /* mark all the stems with the same value */
- if(ISDBG(BLUESTEMS))
- fprintf(pfa_file, "%% found U BLUE at %d\n", s[j].value);
- /* include ST_END values */
- while( s[j-1].value==c && (s[j-1].flags & ST_ZONE)==0 )
- j--;
- s[j].flags |= ST_BLUE;
- for(j++; j<nold && s[j].value==c
- && (s[j].flags & (ST_UP|ST_ZONE))==ST_UP ; j++)
- s[j].flags |= ST_BLUE;
- break;
- }
- }
- }
- /* bottom zones: the logic is the same as for baseline */
- for(i=0; i<notherb; i+=2) {
- a=otherblues[i]; b=otherblues[i+1];
- for(j=0; j<nold; j++) {
- if( (s[j].flags & (ST_UP|ST_ZONE|ST_END))!=ST_UP )
- continue;
- c=s[j].value;
- if(c>b) /* too high */
- break;
- if(c>=a) { /* found the lowest stem border */
- /* mark all the stems with the same value */
- if(ISDBG(BLUESTEMS))
- fprintf(pfa_file, "%% found U BLUE at %d\n", s[j].value);
- /* include ST_END values */
- while( s[j-1].value==c && (s[j-1].flags & ST_ZONE)==0 )
- j--;
- s[j].flags |= ST_BLUE;
- for(j++; j<nold && s[j].value==c
- && (s[j].flags & (ST_UP|ST_ZONE))==ST_UP ; j++)
- s[j].flags |= ST_BLUE;
- break;
- }
- }
- }
-}
-
-/* Eliminate invalid stems, join equivalent lines and remove nested stems
- * to build the main (non-substituted) set of stems.
- * XXX add consideration of the italic angle
- */
-static int
-joinmainstems(
- STEM * s,
- int nold,
- int useblues /* do we use the blue values ? */
-)
-{
-#define MAX_STACK 1000
- STEM stack[MAX_STACK];
- int nstack = 0;
- int sbottom = 0;
- int nnew;
- int i, j, k;
- int a, b, c, w1, w2, w3;
- int fw, fd;
- /*
- * priority of the last found stem:
- * 0 - nothing found yet
- * 1 - has ST_END in it (one or more)
- * 2 - has no ST_END and no ST_FLAT, can override only one stem
- * with priority 1
- * 3 - has no ST_END and at least one ST_FLAT, can override one
- * stem with priority 2 or any number of stems with priority 1
- * 4 (handled separately) - has ST_BLUE, can override anything
- */
- int readystem = 0;
- int pri;
- int nlps = 0; /* number of non-committed
- * lowest-priority stems */
-
-
- for (i = 0, nnew = 0; i < nold; i++) {
- if (s[i].flags & (ST_UP|ST_ZONE)) {
- if(s[i].flags & ST_BLUE) {
- /* we just HAVE to use this value */
- if (readystem)
- nnew += 2;
- readystem=0;
-
- /* remember the list of Blue zone stems with the same value */
- for(a=i, i++; i<nold && s[a].value==s[i].value
- && (s[i].flags & ST_BLUE); i++)
- {}
- b=i; /* our range is a <= i < b */
- c= -1; /* index of our best guess up to now */
- pri=0;
- /* try to find a match, don't cross blue zones */
- for(; i<nold && (s[i].flags & ST_BLUE)==0; i++) {
- if(s[i].flags & ST_UP) {
- if(s[i].flags & ST_TOPZONE)
- break;
- else
- continue;
- }
- for(j=a; j<b; j++) {
- if(!stemoverlap(&s[j], &s[i]) )
- continue;
- /* consider priorities */
- if( ( (s[j].flags|s[i].flags) & (ST_FLAT|ST_END) )==ST_FLAT ) {
- c=i;
- goto bluematch;
- }
- if( ((s[j].flags|s[i].flags) & ST_END)==0 ) {
- if(pri < 2) {
- c=i; pri=2;
- }
- } else {
- if(pri == 0) {
- c=i; pri=1;
- }
- }
- }
- }
- bluematch:
- /* clean up the stack */
- nstack=sbottom=0;
- readystem=0;
- /* add this stem */
- s[nnew++]=s[a];
- if(c<0) { /* make one-dot-wide stem */
- if(nnew>=b) { /* have no free space */
- for(j=nold; j>=b; j--) /* make free space */
- s[j]=s[j-1];
- b++;
- nold++;
- }
- s[nnew]=s[a];
- s[nnew].flags &= ~(ST_UP|ST_BLUE);
- nnew++;
- i=b-1;
- } else {
- s[nnew++]=s[c];
- i=c; /* skip up to this point */
- }
- if (ISDBG(MAINSTEMS))
- fprintf(pfa_file, "%% +stem %d...%d U BLUE\n",
- s[nnew-2].value, s[nnew-1].value);
- } else {
- if (nstack >= MAX_STACK) {
- WARNING_1 fprintf(stderr, "Warning: **** converter's stem stack overflow ****\n");
- nstack = 0;
- }
- stack[nstack++] = s[i];
- }
- } else if(s[i].flags & ST_BLUE) {
- /* again, we just HAVE to use this value */
- if (readystem)
- nnew += 2;
- readystem=0;
-
- /* remember the list of Blue zone stems with the same value */
- for(a=i, i++; i<nold && s[a].value==s[i].value
- && (s[i].flags & ST_BLUE); i++)
- {}
- b=i; /* our range is a <= i < b */
- c= -1; /* index of our best guess up to now */
- pri=0;
- /* try to find a match */
- for (i = nstack - 1; i >= 0; i--) {
- if( (stack[i].flags & ST_UP)==0 ) {
- if( (stack[i].flags & (ST_ZONE|ST_TOPZONE))==ST_ZONE )
- break;
- else
- continue;
- }
- for(j=a; j<b; j++) {
- if(!stemoverlap(&s[j], &stack[i]) )
- continue;
- /* consider priorities */
- if( ( (s[j].flags|stack[i].flags) & (ST_FLAT|ST_END) )==ST_FLAT ) {
- c=i;
- goto bluedownmatch;
- }
- if( ((s[j].flags|stack[i].flags) & ST_END)==0 ) {
- if(pri < 2) {
- c=i; pri=2;
- }
- } else {
- if(pri == 0) {
- c=i; pri=1;
- }
- }
- }
- }
- bluedownmatch:
- /* if found no match make a one-dot-wide stem */
- if(c<0) {
- c=0;
- stack[0]=s[b-1];
- stack[0].flags |= ST_UP;
- stack[0].flags &= ~ST_BLUE;
- }
- /* remove all the stems conflicting with this one */
- readystem=0;
- for(j=nnew-2; j>=0; j-=2) {
- if (ISDBG(MAINSTEMS))
- fprintf(pfa_file, "%% ?stem %d...%d -- %d\n",
- s[j].value, s[j+1].value, stack[c].value);
- if(s[j+1].value < stack[c].value) /* no conflict */
- break;
- if(s[j].flags & ST_BLUE) {
- /* oops, we don't want to spoil other blue zones */
- stack[c].value=s[j+1].value+1;
- break;
- }
- if( (s[j].flags|s[j+1].flags) & ST_END ) {
- if (ISDBG(MAINSTEMS))
- fprintf(pfa_file, "%% -stem %d...%d p=1\n",
- s[j].value, s[j+1].value);
- continue; /* pri==1, silently discard it */
- }
- /* we want to discard no nore than 2 stems of pri>=2 */
- if( ++readystem > 2 ) {
- /* change our stem to not conflict */
- stack[c].value=s[j+1].value+1;
- break;
- } else {
- if (ISDBG(MAINSTEMS))
- fprintf(pfa_file, "%% -stem %d...%d p>=2\n",
- s[j].value, s[j+1].value);
- continue;
- }
- }
- nnew=j+2;
- /* add this stem */
- if(nnew>=b-1) { /* have no free space */
- for(j=nold; j>=b-1; j--) /* make free space */
- s[j]=s[j-1];
- b++;
- nold++;
- }
- s[nnew++]=stack[c];
- s[nnew++]=s[b-1];
- /* clean up the stack */
- nstack=sbottom=0;
- readystem=0;
- /* set the next position to search */
- i=b-1;
- if (ISDBG(MAINSTEMS))
- fprintf(pfa_file, "%% +stem %d...%d D BLUE\n",
- s[nnew-2].value, s[nnew-1].value);
- } else if (nstack > 0) {
-
- /*
- * check whether our stem overlaps with anything in
- * stack
- */
- for (j = nstack - 1; j >= sbottom; j--) {
- if (s[i].value <= stack[j].value)
- break;
- if (stack[j].flags & ST_ZONE)
- continue;
-
- if ((s[i].flags & ST_END)
- || (stack[j].flags & ST_END))
- pri = 1;
- else if ((s[i].flags & ST_FLAT)
- || (stack[j].flags & ST_FLAT))
- pri = 3;
- else
- pri = 2;
-
- if (pri < readystem && s[nnew + 1].value >= stack[j].value
- || !stemoverlap(&stack[j], &s[i]))
- continue;
-
- if (readystem > 1 && s[nnew + 1].value < stack[j].value) {
- nnew += 2;
- readystem = 0;
- nlps = 0;
- }
- /*
- * width of the previous stem (if it's
- * present)
- */
- w1 = s[nnew + 1].value - s[nnew].value;
-
- /* width of this stem */
- w2 = s[i].value - stack[j].value;
-
- if (readystem == 0) {
- /* nothing yet, just add a new stem */
- s[nnew] = stack[j];
- s[nnew + 1] = s[i];
- readystem = pri;
- if (pri == 1)
- nlps = 1;
- else if (pri == 2)
- sbottom = j;
- else {
- sbottom = j + 1;
- while (sbottom < nstack
- && stack[sbottom].value <= stack[j].value)
- sbottom++;
- }
- if (ISDBG(MAINSTEMS))
- fprintf(pfa_file, "%% +stem %d...%d p=%d n=%d\n",
- stack[j].value, s[i].value, pri, nlps);
- } else if (pri == 1) {
- if (stack[j].value > s[nnew + 1].value) {
- /*
- * doesn't overlap with the
- * previous one
- */
- nnew += 2;
- nlps++;
- s[nnew] = stack[j];
- s[nnew + 1] = s[i];
- if (ISDBG(MAINSTEMS))
- fprintf(pfa_file, "%% +stem %d...%d p=%d n=%d\n",
- stack[j].value, s[i].value, pri, nlps);
- } else if (w2 < w1) {
- /* is narrower */
- s[nnew] = stack[j];
- s[nnew + 1] = s[i];
- if (ISDBG(MAINSTEMS))
- fprintf(pfa_file, "%% /stem %d...%d p=%d n=%d %d->%d\n",
- stack[j].value, s[i].value, pri, nlps, w1, w2);
- }
- } else if (pri == 2) {
- if (readystem == 2) {
- /* choose the narrower stem */
- if (w1 > w2) {
- s[nnew] = stack[j];
- s[nnew + 1] = s[i];
- sbottom = j;
- if (ISDBG(MAINSTEMS))
- fprintf(pfa_file, "%% /stem %d...%d p=%d n=%d\n",
- stack[j].value, s[i].value, pri, nlps);
- }
- /* else readystem==1 */
- } else if (stack[j].value > s[nnew + 1].value) {
- /*
- * value doesn't overlap with
- * the previous one
- */
- nnew += 2;
- nlps = 0;
- s[nnew] = stack[j];
- s[nnew + 1] = s[i];
- sbottom = j;
- readystem = pri;
- if (ISDBG(MAINSTEMS))
- fprintf(pfa_file, "%% +stem %d...%d p=%d n=%d\n",
- stack[j].value, s[i].value, pri, nlps);
- } else if (nlps == 1
- || stack[j].value > s[nnew - 1].value) {
- /*
- * we can replace the top
- * stem
- */
- nlps = 0;
- s[nnew] = stack[j];
- s[nnew + 1] = s[i];
- readystem = pri;
- sbottom = j;
- if (ISDBG(MAINSTEMS))
- fprintf(pfa_file, "%% /stem %d...%d p=%d n=%d\n",
- stack[j].value, s[i].value, pri, nlps);
- }
- } else if (readystem == 3) { /* that means also
- * pri==3 */
- /* choose the narrower stem */
- if (w1 > w2) {
- s[nnew] = stack[j];
- s[nnew + 1] = s[i];
- sbottom = j + 1;
- while (sbottom < nstack
- && stack[sbottom].value <= stack[j].value)
- sbottom++;
- if (ISDBG(MAINSTEMS))
- fprintf(pfa_file, "%% /stem %d...%d p=%d n=%d\n",
- stack[j].value, s[i].value, pri, nlps);
- }
- } else if (pri == 3) {
- /*
- * we can replace as many stems as
- * neccessary
- */
- nnew += 2;
- while (nnew > 0 && s[nnew - 1].value >= stack[j].value) {
- nnew -= 2;
- if (ISDBG(MAINSTEMS))
- fprintf(pfa_file, "%% -stem %d..%d\n",
- s[nnew].value, s[nnew + 1].value);
- }
- nlps = 0;
- s[nnew] = stack[j];
- s[nnew + 1] = s[i];
- readystem = pri;
- sbottom = j + 1;
- while (sbottom < nstack
- && stack[sbottom].value <= stack[j].value)
- sbottom++;
- if (ISDBG(MAINSTEMS))
- fprintf(pfa_file, "%% +stem %d...%d p=%d n=%d\n",
- stack[j].value, s[i].value, pri, nlps);
- }
- }
- }
- }
- if (readystem)
- nnew += 2;
-
- /* change the 1-pixel-wide stems to 20-pixel-wide stems if possible
- * the constant 20 is recommended in the Type1 manual
- */
- if(useblues) {
- for(i=0; i<nnew; i+=2) {
- if(s[i].value != s[i+1].value)
- continue;
- if( ((s[i].flags ^ s[i+1].flags) & ST_BLUE)==0 )
- continue;
- if( s[i].flags & ST_BLUE ) {
- if(nnew>i+2 && s[i+2].value<s[i].value+22)
- s[i+1].value=s[i+2].value-2; /* compensate for fuzziness */
- else
- s[i+1].value+=20;
- } else {
- if(i>0 && s[i-1].value>s[i].value-22)
- s[i].value=s[i-1].value+2; /* compensate for fuzziness */
- else
- s[i].value-=20;
- }
- }
- }
- /* make sure that no stem it stretched between
- * a top zone and a bottom zone
- */
- if(useblues) {
- for(i=0; i<nnew; i+=2) {
- a=10000; /* lowest border of top zone crosing the stem */
- b= -10000; /* highest border of bottom zone crossing the stem */
-
- for(j=2; j<nblues; j++) {
- c=bluevalues[j];
- if( c>=s[i].value && c<=s[i+1].value && c<a )
- a=c;
- }
- if(nblues>=2) {
- c=bluevalues[1];
- if( c>=s[i].value && c<=s[i+1].value && c>b )
- b=c;
- }
- for(j=1; j<notherb; j++) {
- c=otherblues[j];
- if( c>=s[i].value && c<=s[i+1].value && c>b )
- b=c;
- }
- if( a!=10000 && b!= -10000 ) { /* it is stretched */
- /* split the stem into 2 ghost stems */
- for(j=nnew+1; j>i+1; j--) /* make free space */
- s[j]=s[j-2];
- nnew+=2;
-
- if(s[i].value+22 >= a)
- s[i+1].value=a-2; /* leave space for fuzziness */
- else
- s[i+1].value=s[i].value+20;
-
- if(s[i+3].value-22 <= b)
- s[i+2].value=b+2; /* leave space for fuzziness */
- else
- s[i+2].value=s[i+3].value-20;
-
- i+=2;
- }
- }
- }
- /* look for triple stems */
- for (i = 0; i < nnew; i += 2) {
- if (nnew - i >= 6) {
- a = s[i].value + s[i + 1].value;
- b = s[i + 2].value + s[i + 3].value;
- c = s[i + 4].value + s[i + 5].value;
-
- w1 = s[i + 1].value - s[i].value;
- w2 = s[i + 3].value - s[i + 2].value;
- w3 = s[i + 5].value - s[i + 4].value;
-
- fw = w3 - w1; /* fuzz in width */
- fd = ((c - b) - (b - a)); /* fuzz in distance
- * (doubled) */
-
- /* we are able to handle some fuzz */
- /*
- * it doesn't hurt if the declared stem is a bit
- * narrower than actual unless it's an edge in
- * a blue zone
- */
- if (abs(abs(fd) - abs(fw)) * 5 < w2
- && abs(fw) * 20 < (w1 + w3)) { /* width dirrerence <10% */
-
- if(useblues) { /* check that we don't disturb any blue stems */
- j=c; k=a;
- if (fw > 0) {
- if (fd > 0) {
- if( s[i+5].flags & ST_BLUE )
- continue;
- j -= fw;
- } else {
- if( s[i+4].flags & ST_BLUE )
- continue;
- j += fw;
- }
- } else if(fw < 0) {
- if (fd > 0) {
- if( s[i+1].flags & ST_BLUE )
- continue;
- k -= fw;
- } else {
- if( s[i].flags & ST_BLUE )
- continue;
- k += fw;
- }
- }
- pri = ((j - b) - (b - k));
-
- if (pri > 0) {
- if( s[i+2].flags & ST_BLUE )
- continue;
- } else if(pri < 0) {
- if( s[i+3].flags & ST_BLUE )
- continue;
- }
- }
-
- /*
- * first fix up the width of 1st and 3rd
- * stems
- */
- if (fw > 0) {
- if (fd > 0) {
- s[i + 5].value -= fw;
- c -= fw;
- } else {
- s[i + 4].value += fw;
- c += fw;
- }
- } else {
- if (fd > 0) {
- s[i + 1].value -= fw;
- a -= fw;
- } else {
- s[i].value += fw;
- a += fw;
- }
- }
- fd = ((c - b) - (b - a));
-
- if (fd > 0) {
- s[i + 2].value += abs(fd) / 2;
- } else {
- s[i + 3].value -= abs(fd) / 2;
- }
-
- s[i].flags |= ST_3;
- i += 4;
- }
- }
- }
-
- return (nnew & ~1); /* number of lines must be always even */
-}
-
-/*
- * these macros and function allow to set the base stem,
- * check that it's not empty and subtract another stem
- * from the base stem (possibly dividing it into multiple parts)
- */
-
-/* pairs for pieces of the base stem */
-static short xbstem[MAX_STEMS*2];
-/* index of the last point */
-static int xblast= -1;
-
-#define setbasestem(from, to) \
- (xbstem[0]=from, xbstem[1]=to, xblast=1)
-#define isbaseempty() (xblast<=0)
-
-/* returns 1 if was overlapping, 0 otherwise */
-static int
-subfrombase(
- int from,
- int to
-)
-{
- int a, b;
- int i, j;
-
- if(isbaseempty())
- return 0;
-
- /* handle the simple case simply */
- if(from > xbstem[xblast] || to < xbstem[0])
- return 0;
-
- /* the binary search may be more efficient */
- /* but for now the linear search is OK */
- for(b=1; from > xbstem[b]; b+=2) {} /* result: from <= xbstem[b] */
- for(a=xblast-1; to < xbstem[a]; a-=2) {} /* result: to >= xbstem[a] */
-
- /* now the interesting examples are:
- * (it was hard for me to understand, so I looked at the examples)
- * 1
- * a|-----| |-----|b |-----| |-----|
- * f|-----|t
- * 2
- * a|-----|b |-----| |-----| |-----|
- * f|--|t
- * 3
- * a|-----|b |-----| |-----| |-----|
- * f|-----|t
- * 4
- * |-----|b a|-----| |-----| |-----|
- * f|------------|t
- * 5
- * |-----| |-----|b |-----| a|-----|
- * f|-----------------------------|t
- * 6
- * |-----|b |-----| |-----| a|-----|
- * f|--------------------------------------------------|t
- * 7
- * |-----|b |-----| a|-----| |-----|
- * f|--------------------------|t
- */
-
- if(a < b-1) /* hits a gap - example 1 */
- return 0;
-
- /* now the subtraction itself */
-
- if(a==b-1 && from > xbstem[a] && to < xbstem[b]) {
- /* overlaps with only one subrange and splits it - example 2 */
- j=xblast; i=(xblast+=2);
- while(j>=b)
- xbstem[i--]=xbstem[j--];
- xbstem[b]=from-1;
- xbstem[b+1]=to+1;
- return 1;
- /* becomes
- * 2a
- * a|b || |-----| |-----| |-----|
- * f|--|t
- */
- }
-
- if(xbstem[b-1] < from) {
- /* cuts the back of this subrange - examples 3, 4, 7 */
- xbstem[b] = from-1;
- b+=2;
- /* becomes
- * 3a
- * a|----| |-----|b |-----| |-----|
- * f|-----|t
- * 4a
- * |---| a|-----|b |-----| |-----|
- * f|------------|t
- * 7a
- * |---| |-----|b a|-----| |-----|
- * f|--------------------------|t
- */
- }
-
- if(xbstem[a+1] > to) {
- /* cuts the front of this subrange - examples 4a, 5, 7a */
- xbstem[a] = to+1;
- a-=2;
- /* becomes
- * 4b
- * a|---| |---|b |-----| |-----|
- * f|------------|t
- * 5b
- * |-----| |-----|b a|-----| ||
- * f|-----------------------------|t
- * 7b
- * |---| a|-----|b || |-----|
- * f|--------------------------|t
- */
- }
-
- if(a < b-1) /* now after modification it hits a gap - examples 3a, 4b */
- return 1; /* because we have removed something */
-
- /* now remove the subranges completely covered by the new stem */
- /* examples 5b, 6, 7b */
- i=b-1; j=a+2;
- /* positioned as:
- * 5b i j
- * |-----| |-----|b a|-----| ||
- * f|-----------------------------|t
- * 6 i xblast j
- * |-----|b |-----| |-----| a|-----|
- * f|--------------------------------------------------|t
- * 7b i j
- * |---| a|-----|b || |-----|
- * f|--------------------------|t
- */
- while(j <= xblast)
- xbstem[i++]=xbstem[j++];
- xblast=i-1;
- return 1;
-}
-
-/* for debugging */
-static void
-printbasestem(void)
-{
- int i;
-
- printf("( ");
- for(i=0; i<xblast; i+=2)
- printf("%d-%d ", xbstem[i], xbstem[i+1]);
- printf(") %d\n", xblast);
-}
-
-/*
- * Join the stem borders to build the sets of substituted stems
- * XXX add consideration of the italic angle
- */
-static void
-joinsubstems(
- STEM * s,
- short *pairs,
- int nold,
- int useblues /* do we use the blue values ? */
-)
-{
- int i, j, x;
- static unsigned char mx[MAX_STEMS][MAX_STEMS];
-
- /* we do the substituted groups of stems first
- * and it looks like it's going to be REALLY SLOW
- * AND PAINFUL but let's bother about it later
- */
-
- /* for the substituted stems we don't bother about [hv]stem3 -
- * anyway the X11R6 rasterizer does not bother about hstem3
- * at all and is able to handle only one global vstem3
- * per glyph
- */
-
- /* clean the used part of matrix */
- for(i=0; i<nold; i++)
- for(j=0; j<nold; j++)
- mx[i][j]=0;
-
- /* build the matrix of stem pairs */
- for(i=0; i<nold; i++) {
- if( s[i].flags & ST_ZONE )
- continue;
- if(s[i].flags & ST_BLUE)
- mx[i][i]=1; /* allow to pair with itself if no better pair */
- if(s[i].flags & ST_UP) { /* the down-stems are already matched */
- setbasestem(s[i].from, s[i].to);
- for(j=i+1; j<nold; j++) {
- if(s[i].value==s[j].value
- || s[j].flags & ST_ZONE ) {
- continue;
- }
- x=subfrombase(s[j].from, s[j].to);
-
- if(s[j].flags & ST_UP) /* match only up+down pairs */
- continue;
-
- mx[i][j]=mx[j][i]=x;
-
- if(isbaseempty()) /* nothing else to do */
- break;
- }
- }
- }
-
- if(ISDBG(SUBSTEMS)) {
- fprintf(pfa_file, "%% ");
- for(j=0; j<nold; j++)
- putc( j%10==0 ? '0'+(j/10)%10 : ' ', pfa_file);
- fprintf(pfa_file, "\n%% ");
- for(j=0; j<nold; j++)
- putc('0'+j%10, pfa_file);
- putc('\n', pfa_file);
- for(i=0; i<nold; i++) {
- fprintf(pfa_file, "%% %3d ",i);
- for(j=0; j<nold; j++)
- putc( mx[i][j] ? 'X' : '.', pfa_file);
- putc('\n', pfa_file);
- }
- }
-
- /* now use the matrix to find the best pair for each stem */
- for(i=0; i<nold; i++) {
- int pri, lastpri, v, f;
-
- x= -1; /* best pair: none */
- lastpri=0;
-
- v=s[i].value;
- f=s[i].flags;
-
- if(f & ST_ZONE) {
- pairs[i]= -1;
- continue;
- }
-
- if(f & ST_UP) {
- for(j=i+1; j<nold; j++) {
- if(mx[i][j]==0)
- continue;
-
- if( (f | s[j].flags) & ST_END )
- pri=1;
- else if( (f | s[j].flags) & ST_FLAT )
- pri=3;
- else
- pri=2;
-
- if(lastpri==0
- || pri > lastpri
- && ( lastpri==1 || s[j].value-v<20 || (s[x].value-v)*2 >= s[j].value-v ) ) {
- lastpri=pri;
- x=j;
- }
- }
- } else {
- for(j=i-1; j>=0; j--) {
- if(mx[i][j]==0)
- continue;
-
- if( (f | s[j].flags) & ST_END )
- pri=1;
- else if( (f | s[j].flags) & ST_FLAT )
- pri=3;
- else
- pri=2;
-
- if(lastpri==0
- || pri > lastpri
- && ( lastpri==1 || v-s[j].value<20 || (v-s[x].value)*2 >= v-s[j].value ) ) {
- lastpri=pri;
- x=j;
- }
- }
- }
- if(x== -1 && mx[i][i])
- pairs[i]=i; /* a special case */
- else
- pairs[i]=x;
- }
-
- if(ISDBG(SUBSTEMS)) {
- for(i=0; i<nold; i++) {
- j=pairs[i];
- if(j>0)
- fprintf(pfa_file, "%% %d...%d (%d x %d)\n", s[i].value, s[j].value, i, j);
- }
- }
-}
-
-/*
- * Make all the stems originating at the same value get the
- * same width. Without this the rasterizer may move the dots
- * randomly up or down by one pixel, and that looks bad.
- * The prioritisation is the same as in findstemat().
- */
-static void
-uniformstems(
- STEM * s,
- short *pairs,
- int ns
-)
-{
- int i, j, from, to, val, dir;
- int pri, prevpri[2], wd, prevwd[2], prevbest[2];
-
- for(from=0; from<ns; from=to) {
- prevpri[0] = prevpri[1] = 0;
- prevwd[0] = prevwd[1] = 0;
- prevbest[0] = prevbest[1] = -1;
- val = s[from].value;
-
- for(to = from; to<ns && s[to].value == val; to++) {
- dir = ((s[to].flags & ST_UP)!=0);
-
- i=pairs[to]; /* the other side of this stem */
- if(i<0 || i==to)
- continue; /* oops, no other side */
- wd=abs(s[i].value-val);
- if(wd == 0)
- continue;
- pri=1;
- if( (s[to].flags | s[i].flags) & ST_END )
- pri=0;
- if( prevbest[dir] == -1 || pri > prevpri[dir] || wd<prevwd[dir] ) {
- prevbest[dir]=i;
- prevpri[dir]=pri;
- prevwd[dir]=wd;
- }
- }
-
- for(i=from; i<to; i++) {
- dir = ((s[i].flags & ST_UP)!=0);
- if(prevbest[dir] >= 0) {
- if(ISDBG(SUBSTEMS)) {
- fprintf(stderr, "at %d (%s %d) pair %d->%d(%d)\n", i,
- (dir ? "UP":"DOWN"), s[i].value, pairs[i], prevbest[dir],
- s[prevbest[dir]].value);
- }
- pairs[i] = prevbest[dir];
- }
- }
- }
-}
-
-/*
- * Find the best stem in the array at the specified (value, origin),
- * related to the entry ge.
- * Returns its index in the array sp, -1 means "none".
- * prevbest is the result for the other end of the line, we must
- * find something better than it or leave it as it is.
- */
-static int
-findstemat(
- int value,
- int origin,
- GENTRY *ge,
- STEM *sp,
- short *pairs,
- int ns,
- int prevbest /* -1 means "none" */
-)
-{
- int i, min, max;
- int v, si;
- int pri, prevpri; /* priority, 0 = has ST_END, 1 = no ST_END */
- int wd, prevwd; /* stem width */
-
- si= -1; /* nothing yet */
-
- /* stems are ordered by value, binary search */
- min=0; max=ns; /* min <= i < max */
- while( min < max ) {
- i=(min+max)/2;
- v=sp[i].value;
- if(v<value)
- min=i+1;
- else if(v>value)
- max=i;
- else {
- si=i; /* temporary value */
- break;
- }
- }
-
- if( si < 0 ) /* found nothing this time */
- return prevbest;
-
- /* find the priority of the prevbest */
- /* we expect that prevbest has a pair */
- if(prevbest>=0) {
- i=pairs[prevbest];
- prevpri=1;
- if( (sp[prevbest].flags | sp[i].flags) & ST_END )
- prevpri=0;
- prevwd=abs(sp[i].value-value);
- }
-
- /* stems are not ordered by origin, so now do the linear search */
-
- while( si>0 && sp[si-1].value==value ) /* find the first one */
- si--;
-
- for(; si<ns && sp[si].value==value; si++) {
- if(sp[si].origin != origin)
- continue;
- if(sp[si].ge != ge) {
- if(ISDBG(SUBSTEMS)) {
- fprintf(stderr,
- "dbg: possible self-intersection at v=%d o=%d exp_ge=0x%x ge=0x%x\n",
- value, origin, ge, sp[si].ge);
- }
- continue;
- }
- i=pairs[si]; /* the other side of this stem */
- if(i<0)
- continue; /* oops, no other side */
- pri=1;
- if( (sp[si].flags | sp[i].flags) & ST_END )
- pri=0;
- wd=abs(sp[i].value-value);
- if( prevbest == -1 || pri >prevpri
- || pri==prevpri && prevwd==0 || wd!=0 && wd<prevwd ) {
- prevbest=si;
- prevpri=pri;
- prevwd=wd;
- continue;
- }
- }
-
- return prevbest;
-}
-
-/* add the substems for one glyph entry
- * (called from groupsubstems())
- * returns 0 if all OK, 1 if too many groups
- */
-
-static int gssentry_lastgrp=0; /* reset to 0 for each new glyph */
-
-static int
-gssentry( /* crazy number of parameters */
- GENTRY *ge,
- STEM *hs, /* horizontal stems, sorted by value */
- short *hpairs,
- int nhs,
- STEM *vs, /* vertical stems, sorted by value */
- short *vpairs,
- int nvs,
- STEMBOUNDS *s,
- short *egp,
- int *nextvsi,
- int *nexthsi /* -2 means "check by yourself" */
-) {
- enum {
- SI_VP, /* vertical primary */
- SI_HP, /* horizontal primary */
- SI_SIZE /* size of the array */
- };
- int si[SI_SIZE]; /* indexes of relevant stems */
-
- /* the bounds of the existing relevant stems */
- STEMBOUNDS r[ sizeof(si) / sizeof(si[0]) * 2 ];
- char rexpand; /* by how much we need to expand the group */
- int nr; /* and the number of them */
-
- /* yet more temporary storage */
- short lb, hb, isvert;
- int conflict, grp;
- int i, j, x, y;
-
-
- /* for each line or curve we try to find a horizontal and
- * a vertical stem corresponding to its first point
- * (corresponding to the last point of the previous
- * glyph entry), because the directions of the lines
- * will be eventually reversed and it will then become the last
- * point. And the T1 rasterizer applies the hints to
- * the last point.
- *
- */
-
- /* start with the common part, the first point */
- x=ge->prev->ix3;
- y=ge->prev->iy3;
-
- if(*nextvsi == -2)
- si[SI_VP]=findstemat(x, y, ge, vs, vpairs, nvs, -1);
- else {
- si[SI_VP]= *nextvsi; *nextvsi= -2;
- }
- if(*nexthsi == -2)
- si[SI_HP]=findstemat(y, x, ge, hs, hpairs, nhs, -1);
- else {
- si[SI_HP]= *nexthsi; *nexthsi= -2;
- }
-
- /*
- * For the horizontal lines we make sure that both
- * ends of the line have the same horizontal stem,
- * and the same thing for vertical lines and stems.
- * In both cases we enforce the stem for the next entry.
- * Otherwise unpleasant effects may arise.
- */
-
- if(ge->type==GE_LINE) {
- if(ge->ix3==x) { /* vertical line */
- *nextvsi=si[SI_VP]=findstemat(x, ge->iy3, ge->frwd, vs, vpairs, nvs, si[SI_VP]);
- } else if(ge->iy3==y) { /* horizontal line */
- *nexthsi=si[SI_HP]=findstemat(y, ge->ix3, ge->frwd, hs, hpairs, nhs, si[SI_HP]);
- }
- }
-
- if(si[SI_VP]+si[SI_HP] == -2) /* no stems, leave it alone */
- return 0;
-
- /* build the array of relevant bounds */
- nr=0;
- for(i=0; i< sizeof(si) / sizeof(si[0]); i++) {
- STEM *sp;
- short *pairs;
- int step;
- int f;
- int nzones, firstzone, binzone, einzone;
- int btype, etype;
-
- if(si[i] < 0)
- continue;
-
- if(i<SI_HP) {
- r[nr].isvert=1; sp=vs; pairs=vpairs;
- } else {
- r[nr].isvert=0; sp=hs; pairs=hpairs;
- }
-
- r[nr].low=sp[ si[i] ].value;
- r[nr].high=sp[ pairs[ si[i] ] ].value;
-
- if(r[nr].low > r[nr].high) {
- j=r[nr].low; r[nr].low=r[nr].high; r[nr].high=j;
- step= -1;
- } else {
- step=1;
- }
-
- /* handle the interaction with Blue Zones */
-
- if(i>=SI_HP) { /* only for horizontal stems */
- if(si[i]==pairs[si[i]]) {
- /* special case, the outermost stem in the
- * Blue Zone without a pair, simulate it to 20-pixel
- */
- if(sp[ si[i] ].flags & ST_UP) {
- r[nr].high+=20;
- for(j=si[i]+1; j<nhs; j++)
- if( (sp[j].flags & (ST_ZONE|ST_TOPZONE))
- == (ST_ZONE|ST_TOPZONE) ) {
- if(r[nr].high > sp[j].value-2)
- r[nr].high=sp[j].value-2;
- break;
- }
- } else {
- r[nr].low-=20;
- for(j=si[i]-1; j>=0; j--)
- if( (sp[j].flags & (ST_ZONE|ST_TOPZONE))
- == (ST_ZONE) ) {
- if(r[nr].low < sp[j].value+2)
- r[nr].low=sp[j].value+2;
- break;
- }
- }
- }
-
- /* check that the stem borders don't end up in
- * different Blue Zones */
- f=sp[ si[i] ].flags;
- nzones=0; einzone=binzone=0;
- for(j=si[i]; j!=pairs[ si[i] ]; j+=step) {
- if( (sp[j].flags & ST_ZONE)==0 )
- continue;
- /* if see a zone border going in the same direction */
- if( ((f ^ sp[j].flags) & ST_UP)==0 ) {
- if( ++nzones == 1 ) {
- firstzone=sp[j].value; /* remember the first one */
- etype=sp[j].flags & ST_TOPZONE;
- }
- einzone=1;
-
- } else { /* the opposite direction */
- if(nzones==0) { /* beginning is in a blue zone */
- binzone=1;
- btype=sp[j].flags & ST_TOPZONE;
- }
- einzone=0;
- }
- }
-
- /* beginning and end are in Blue Zones of different types */
- if( binzone && einzone && (btype ^ etype)!=0 ) {
- if( sp[si[i]].flags & ST_UP ) {
- if(firstzone > r[nr].low+22)
- r[nr].high=r[nr].low+20;
- else
- r[nr].high=firstzone-2;
- } else {
- if(firstzone < r[nr].high-22)
- r[nr].low=r[nr].high-20;
- else
- r[nr].low=firstzone+2;
- }
- }
- }
-
- if(ISDBG(SUBSTEMS))
- fprintf(pfa_file, "%% at(%d,%d)[%d,%d] %d..%d %c (%d x %d)\n", x, y, i, nr,
- r[nr].low, r[nr].high, r[nr].isvert ? 'v' : 'h',
- si[i], pairs[si[i]]);
-
- nr++;
- }
-
- /* now try to find a group */
- conflict=0; /* no conflicts found yet */
- for(j=0; j<nr; j++)
- r[j].already=0;
-
- /* check if it fits into the last group */
- grp = gssentry_lastgrp;
- i = (grp==0)? 0 : egp[grp-1];
- for(; i<egp[grp]; i++) {
- lb=s[i].low; hb=s[i].high; isvert=s[i].isvert;
- for(j=0; j<nr; j++)
- if( r[j].isvert==isvert /* intersects */
- && r[j].low <= hb && r[j].high >= lb ) {
- if( r[j].low == lb && r[j].high == hb ) /* coincides */
- r[j].already=1;
- else
- conflict=1;
- }
-
- if(conflict)
- break;
- }
-
- if(conflict) { /* nope, check all the groups */
- for(j=0; j<nr; j++)
- r[j].already=0;
-
- for(i=0, grp=0; i<egp[NSTEMGRP-1]; i++) {
- if(i == egp[grp]) { /* checked all stems in a group */
- if(conflict) {
- grp++; conflict=0; /* check the next group */
- for(j=0; j<nr; j++)
- r[j].already=0;
- } else
- break; /* insert into this group */
- }
-
- lb=s[i].low; hb=s[i].high; isvert=s[i].isvert;
- for(j=0; j<nr; j++)
- if( r[j].isvert==isvert /* intersects */
- && r[j].low <= hb && r[j].high >= lb ) {
- if( r[j].low == lb && r[j].high == hb ) /* coincides */
- r[j].already=1;
- else
- conflict=1;
- }
-
- if(conflict)
- i=egp[grp]-1; /* fast forward to the next group */
- }
- }
-
- /* do we have any empty group ? */
- if(conflict && grp < NSTEMGRP-1) {
- grp++; conflict=0;
- for(j=0; j<nr; j++)
- r[j].already=0;
- }
-
- if(conflict) { /* oops, can't find any group to fit */
- return 1;
- }
-
- /* OK, add stems to this group */
-
- rexpand = nr;
- for(j=0; j<nr; j++)
- rexpand -= r[j].already;
-
- if(rexpand > 0) {
- for(i=egp[NSTEMGRP-1]-1; i>=egp[grp]; i--)
- s[i+rexpand]=s[i];
- for(i=0; i<nr; i++)
- if(!r[i].already)
- s[egp[grp]++]=r[i];
- for(i=grp+1; i<NSTEMGRP; i++)
- egp[i]+=rexpand;
- }
-
- ge->stemid = gssentry_lastgrp = grp;
- return 0;
-}
-
-/*
- * Create the groups of substituted stems from the list.
- * Each group will be represented by a subroutine in the Subs
- * array.
- */
-
-static void
-groupsubstems(
- GLYPH *g,
- STEM *hs, /* horizontal stems, sorted by value */
- short *hpairs,
- int nhs,
- STEM *vs, /* vertical stems, sorted by value */
- short *vpairs,
- int nvs
-)
-{
- GENTRY *ge;
- int i, j;
-
- /* temporary storage */
- STEMBOUNDS s[MAX_STEMS*2];
- /* indexes in there, pointing past the end each stem group */
- short egp[NSTEMGRP];
-
- int nextvsi, nexthsi; /* -2 means "check by yourself" */
-
- for(i=0; i<NSTEMGRP; i++)
- egp[i]=0;
-
- nextvsi=nexthsi= -2; /* processed no horiz/vert line */
-
- gssentry_lastgrp = 0; /* reset the last group for new glyph */
-
- for (ge = g->entries; ge != 0; ge = ge->next) {
- if(ge->type!=GE_LINE && ge->type!=GE_CURVE) {
- nextvsi=nexthsi= -2; /* next path is independent */
- continue;
- }
-
- if( gssentry(ge, hs, hpairs, nhs, vs, vpairs, nvs, s, egp, &nextvsi, &nexthsi) ) {
- WARNING_2 fprintf(stderr, "*** glyph %s requires over %d hint subroutines, ignored them\n",
- g->name, NSTEMGRP);
- /* it's better to have no substituted hints at all than have only part */
- for (ge = g->entries; ge != 0; ge = ge->next)
- ge->stemid= -1;
- g->nsg=0; /* just to be safe, already is 0 by initialization */
- return;
- }
-
- /*
- * handle the last vert/horiz line of the path specially,
- * correct the hint for the first entry of the path
- */
- if(ge->frwd != ge->next && (nextvsi != -2 || nexthsi != -2) ) {
- if( gssentry(ge->frwd, hs, hpairs, nhs, vs, vpairs, nvs, s, egp, &nextvsi, &nexthsi) ) {
- WARNING_2 fprintf(stderr, "*** glyph %s requires over %d hint subroutines, ignored them\n",
- g->name, NSTEMGRP);
- /* it's better to have no substituted hints at all than have only part */
- for (ge = g->entries; ge != 0; ge = ge->next)
- ge->stemid= -1;
- g->nsg=0; /* just to be safe, already is 0 by initialization */
- return;
- }
- }
-
- }
-
- /* find the index of the first empty group - same as the number of groups */
- if(egp[0]>0) {
- for(i=1; i<NSTEMGRP && egp[i]!=egp[i-1]; i++)
- {}
- g->nsg=i;
- } else
- g->nsg=0;
-
- if(ISDBG(SUBSTEMS)) {
- fprintf(pfa_file, "%% %d substem groups (%d %d %d)\n", g->nsg,
- g->nsg>1 ? egp[g->nsg-2] : -1,
- g->nsg>0 ? egp[g->nsg-1] : -1,
- g->nsg<NSTEMGRP ? egp[g->nsg] : -1 );
- j=0;
- for(i=0; i<g->nsg; i++) {
- fprintf(pfa_file, "%% grp %3d: ", i);
- for(; j<egp[i]; j++) {
- fprintf(pfa_file, " %4d...%-4d %c ", s[j].low, s[j].high,
- s[j].isvert ? 'v' : 'h');
- }
- fprintf(pfa_file, "\n");
- }
- }
-
- if(g->nsg==1) { /* it would be the same as the main stems */
- /* so erase it */
- for (ge = g->entries; ge != 0; ge = ge->next)
- ge->stemid= -1;
- g->nsg=0;
- }
-
- if(g->nsg>0) {
- if( (g->nsbs=malloc(g->nsg * sizeof (egp[0]))) == 0 ) {
- fprintf(stderr, "**** not enough memory for substituted hints ****\n");
- exit(255);
- }
- memmove(g->nsbs, egp, g->nsg * sizeof(short));
- if( (g->sbstems=malloc(egp[g->nsg-1] * sizeof (s[0]))) == 0 ) {
- fprintf(stderr, "**** not enough memory for substituted hints ****\n");
- exit(255);
- }
- memmove(g->sbstems, s, egp[g->nsg-1] * sizeof(s[0]));
- }
-}
-
-void
-buildstems(
- GLYPH * g
-)
-{
- STEM hs[MAX_STEMS], vs[MAX_STEMS]; /* temporary working
- * storage */
- short hs_pairs[MAX_STEMS], vs_pairs[MAX_STEMS]; /* best pairs for these stems */
- STEM *sp;
- GENTRY *ge, *nge, *pge;
- int nx, ny;
- int ovalue;
- int totals, grp, lastgrp;
-
- assertisint(g, "buildstems int");
-
- g->nhs = g->nvs = 0;
- memset(hs, 0, sizeof hs);
- memset(vs, 0, sizeof vs);
-
- /* first search the whole character for possible stem points */
-
- for (ge = g->entries; ge != 0; ge = ge->next) {
- if (ge->type == GE_CURVE) {
-
- /*
- * SURPRISE!
- * We consider the stems bound by the
- * H/V ends of the curves as flat ones.
- *
- * But we don't include the point on the
- * other end into the range.
- */
-
- /* first check the beginning of curve */
- /* if it is horizontal, add a hstem */
- if (ge->iy1 == ge->prev->iy3) {
- hs[g->nhs].value = ge->iy1;
-
- if (ge->ix1 < ge->prev->ix3)
- hs[g->nhs].flags = ST_FLAT | ST_UP;
- else
- hs[g->nhs].flags = ST_FLAT;
-
- hs[g->nhs].origin = ge->prev->ix3;
- hs[g->nhs].ge = ge;
-
- if (ge->ix1 < ge->prev->ix3) {
- hs[g->nhs].from = ge->ix1+1;
- hs[g->nhs].to = ge->prev->ix3;
- if(hs[g->nhs].from > hs[g->nhs].to)
- hs[g->nhs].from--;
- } else {
- hs[g->nhs].from = ge->prev->ix3;
- hs[g->nhs].to = ge->ix1-1;
- if(hs[g->nhs].from > hs[g->nhs].to)
- hs[g->nhs].to++;
- }
- if (ge->ix1 != ge->prev->ix3)
- g->nhs++;
- }
- /* if it is vertical, add a vstem */
- else if (ge->ix1 == ge->prev->ix3) {
- vs[g->nvs].value = ge->ix1;
-
- if (ge->iy1 > ge->prev->iy3)
- vs[g->nvs].flags = ST_FLAT | ST_UP;
- else
- vs[g->nvs].flags = ST_FLAT;
-
- vs[g->nvs].origin = ge->prev->iy3;
- vs[g->nvs].ge = ge;
-
- if (ge->iy1 < ge->prev->iy3) {
- vs[g->nvs].from = ge->iy1+1;
- vs[g->nvs].to = ge->prev->iy3;
- if(vs[g->nvs].from > vs[g->nvs].to)
- vs[g->nvs].from--;
- } else {
- vs[g->nvs].from = ge->prev->iy3;
- vs[g->nvs].to = ge->iy1-1;
- if(vs[g->nvs].from > vs[g->nvs].to)
- vs[g->nvs].to++;
- }
-
- if (ge->iy1 != ge->prev->iy3)
- g->nvs++;
- }
- /* then check the end of curve */
- /* if it is horizontal, add a hstem */
- if (ge->iy3 == ge->iy2) {
- hs[g->nhs].value = ge->iy3;
-
- if (ge->ix3 < ge->ix2)
- hs[g->nhs].flags = ST_FLAT | ST_UP;
- else
- hs[g->nhs].flags = ST_FLAT;
-
- hs[g->nhs].origin = ge->ix3;
- hs[g->nhs].ge = ge->frwd;
-
- if (ge->ix3 < ge->ix2) {
- hs[g->nhs].from = ge->ix3;
- hs[g->nhs].to = ge->ix2-1;
- if( hs[g->nhs].from > hs[g->nhs].to )
- hs[g->nhs].to++;
- } else {
- hs[g->nhs].from = ge->ix2+1;
- hs[g->nhs].to = ge->ix3;
- if( hs[g->nhs].from > hs[g->nhs].to )
- hs[g->nhs].from--;
- }
-
- if (ge->ix3 != ge->ix2)
- g->nhs++;
- }
- /* if it is vertical, add a vstem */
- else if (ge->ix3 == ge->ix2) {
- vs[g->nvs].value = ge->ix3;
-
- if (ge->iy3 > ge->iy2)
- vs[g->nvs].flags = ST_FLAT | ST_UP;
- else
- vs[g->nvs].flags = ST_FLAT;
-
- vs[g->nvs].origin = ge->iy3;
- vs[g->nvs].ge = ge->frwd;
-
- if (ge->iy3 < ge->iy2) {
- vs[g->nvs].from = ge->iy3;
- vs[g->nvs].to = ge->iy2-1;
- if( vs[g->nvs].from > vs[g->nvs].to )
- vs[g->nvs].to++;
- } else {
- vs[g->nvs].from = ge->iy2+1;
- vs[g->nvs].to = ge->iy3;
- if( vs[g->nvs].from > vs[g->nvs].to )
- vs[g->nvs].from--;
- }
-
- if (ge->iy3 != ge->iy2)
- g->nvs++;
- } else {
-
- /*
- * check the end of curve for a not smooth
- * local extremum
- */
- nge = ge->frwd;
-
- if (nge == 0)
- continue;
- else if (nge->type == GE_LINE) {
- nx = nge->ix3;
- ny = nge->iy3;
- } else if (nge->type == GE_CURVE) {
- nx = nge->ix1;
- ny = nge->iy1;
- } else
- continue;
-
- /* check for vertical extremums */
- if (ge->iy3 > ge->iy2 && ge->iy3 > ny
- || ge->iy3 < ge->iy2 && ge->iy3 < ny) {
- hs[g->nhs].value = ge->iy3;
- hs[g->nhs].from
- = hs[g->nhs].to
- = hs[g->nhs].origin = ge->ix3;
- hs[g->nhs].ge = ge->frwd;
-
- if (ge->ix3 < ge->ix2
- || nx < ge->ix3)
- hs[g->nhs].flags = ST_UP;
- else
- hs[g->nhs].flags = 0;
-
- if (ge->ix3 != ge->ix2 || nx != ge->ix3)
- g->nhs++;
- }
- /*
- * the same point may be both horizontal and
- * vertical extremum
- */
- /* check for horizontal extremums */
- if (ge->ix3 > ge->ix2 && ge->ix3 > nx
- || ge->ix3 < ge->ix2 && ge->ix3 < nx) {
- vs[g->nvs].value = ge->ix3;
- vs[g->nvs].from
- = vs[g->nvs].to
- = vs[g->nvs].origin = ge->iy3;
- vs[g->nvs].ge = ge->frwd;
-
- if (ge->iy3 > ge->iy2
- || ny > ge->iy3)
- vs[g->nvs].flags = ST_UP;
- else
- vs[g->nvs].flags = 0;
-
- if (ge->iy3 != ge->iy2 || ny != ge->iy3)
- g->nvs++;
- }
- }
-
- } else if (ge->type == GE_LINE) {
- nge = ge->frwd;
-
- /* if it is horizontal, add a hstem */
- /* and the ends as vstems if they brace the line */
- if (ge->iy3 == ge->prev->iy3
- && ge->ix3 != ge->prev->ix3) {
- hs[g->nhs].value = ge->iy3;
- if (ge->ix3 < ge->prev->ix3) {
- hs[g->nhs].flags = ST_FLAT | ST_UP;
- hs[g->nhs].from = ge->ix3;
- hs[g->nhs].to = ge->prev->ix3;
- } else {
- hs[g->nhs].flags = ST_FLAT;
- hs[g->nhs].from = ge->prev->ix3;
- hs[g->nhs].to = ge->ix3;
- }
- hs[g->nhs].origin = ge->ix3;
- hs[g->nhs].ge = ge->frwd;
-
- pge = ge->bkwd;
-
- /* add beginning as vstem */
- vs[g->nvs].value = pge->ix3;
- vs[g->nvs].origin
- = vs[g->nvs].from
- = vs[g->nvs].to = pge->iy3;
- vs[g->nvs].ge = ge;
-
- if(pge->type==GE_CURVE)
- ovalue=pge->iy2;
- else
- ovalue=pge->prev->iy3;
-
- if (pge->iy3 > ovalue)
- vs[g->nvs].flags = ST_UP | ST_END;
- else if (pge->iy3 < ovalue)
- vs[g->nvs].flags = ST_END;
- else
- vs[g->nvs].flags = 0;
-
- if( vs[g->nvs].flags != 0 )
- g->nvs++;
-
- /* add end as vstem */
- vs[g->nvs].value = ge->ix3;
- vs[g->nvs].origin
- = vs[g->nvs].from
- = vs[g->nvs].to = ge->iy3;
- vs[g->nvs].ge = ge->frwd;
-
- if(nge->type==GE_CURVE)
- ovalue=nge->iy1;
- else
- ovalue=nge->iy3;
-
- if (ovalue > ge->iy3)
- vs[g->nvs].flags = ST_UP | ST_END;
- else if (ovalue < ge->iy3)
- vs[g->nvs].flags = ST_END;
- else
- vs[g->nvs].flags = 0;
-
- if( vs[g->nvs].flags != 0 )
- g->nvs++;
-
- g->nhs++;
- }
- /* if it is vertical, add a vstem */
- /* and the ends as hstems if they brace the line */
- else if (ge->ix3 == ge->prev->ix3
- && ge->iy3 != ge->prev->iy3) {
- vs[g->nvs].value = ge->ix3;
- if (ge->iy3 > ge->prev->iy3) {
- vs[g->nvs].flags = ST_FLAT | ST_UP;
- vs[g->nvs].from = ge->prev->iy3;
- vs[g->nvs].to = ge->iy3;
- } else {
- vs[g->nvs].flags = ST_FLAT;
- vs[g->nvs].from = ge->iy3;
- vs[g->nvs].to = ge->prev->iy3;
- }
- vs[g->nvs].origin = ge->iy3;
- vs[g->nvs].ge = ge->frwd;
-
- pge = ge->bkwd;
-
- /* add beginning as hstem */
- hs[g->nhs].value = pge->iy3;
- hs[g->nhs].origin
- = hs[g->nhs].from
- = hs[g->nhs].to = pge->ix3;
- hs[g->nhs].ge = ge;
-
- if(pge->type==GE_CURVE)
- ovalue=pge->ix2;
- else
- ovalue=pge->prev->ix3;
-
- if (pge->ix3 < ovalue)
- hs[g->nhs].flags = ST_UP | ST_END;
- else if (pge->ix3 > ovalue)
- hs[g->nhs].flags = ST_END;
- else
- hs[g->nhs].flags = 0;
-
- if( hs[g->nhs].flags != 0 )
- g->nhs++;
-
- /* add end as hstem */
- hs[g->nhs].value = ge->iy3;
- hs[g->nhs].origin
- = hs[g->nhs].from
- = hs[g->nhs].to = ge->ix3;
- hs[g->nhs].ge = ge->frwd;
-
- if(nge->type==GE_CURVE)
- ovalue=nge->ix1;
- else
- ovalue=nge->ix3;
-
- if (ovalue < ge->ix3)
- hs[g->nhs].flags = ST_UP | ST_END;
- else if (ovalue > ge->ix3)
- hs[g->nhs].flags = ST_END;
- else
- hs[g->nhs].flags = 0;
-
- if( hs[g->nhs].flags != 0 )
- g->nhs++;
-
- g->nvs++;
- }
- /*
- * check the end of line for a not smooth local
- * extremum
- */
- nge = ge->frwd;
-
- if (nge == 0)
- continue;
- else if (nge->type == GE_LINE) {
- nx = nge->ix3;
- ny = nge->iy3;
- } else if (nge->type == GE_CURVE) {
- nx = nge->ix1;
- ny = nge->iy1;
- } else
- continue;
-
- /* check for vertical extremums */
- if (ge->iy3 > ge->prev->iy3 && ge->iy3 > ny
- || ge->iy3 < ge->prev->iy3 && ge->iy3 < ny) {
- hs[g->nhs].value = ge->iy3;
- hs[g->nhs].from
- = hs[g->nhs].to
- = hs[g->nhs].origin = ge->ix3;
- hs[g->nhs].ge = ge->frwd;
-
- if (ge->ix3 < ge->prev->ix3
- || nx < ge->ix3)
- hs[g->nhs].flags = ST_UP;
- else
- hs[g->nhs].flags = 0;
-
- if (ge->ix3 != ge->prev->ix3 || nx != ge->ix3)
- g->nhs++;
- }
- /*
- * the same point may be both horizontal and vertical
- * extremum
- */
- /* check for horizontal extremums */
- if (ge->ix3 > ge->prev->ix3 && ge->ix3 > nx
- || ge->ix3 < ge->prev->ix3 && ge->ix3 < nx) {
- vs[g->nvs].value = ge->ix3;
- vs[g->nvs].from
- = vs[g->nvs].to
- = vs[g->nvs].origin = ge->iy3;
- vs[g->nvs].ge = ge->frwd;
-
- if (ge->iy3 > ge->prev->iy3
- || ny > ge->iy3)
- vs[g->nvs].flags = ST_UP;
- else
- vs[g->nvs].flags = 0;
-
- if (ge->iy3 != ge->prev->iy3 || ny != ge->iy3)
- g->nvs++;
- }
- }
- }
-
- g->nhs=addbluestems(hs, g->nhs);
- sortstems(hs, g->nhs);
- sortstems(vs, g->nvs);
-
- if (ISDBG(STEMS))
- debugstems(g->name, hs, g->nhs, vs, g->nvs);
-
- /* find the stems interacting with the Blue Zones */
- markbluestems(hs, g->nhs);
-
- if(subhints) {
- if (ISDBG(SUBSTEMS))
- fprintf(pfa_file, "%% %s: joining subst horizontal stems\n", g->name);
- joinsubstems(hs, hs_pairs, g->nhs, 1);
- uniformstems(hs, hs_pairs, g->nhs);
-
- if (ISDBG(SUBSTEMS))
- fprintf(pfa_file, "%% %s: joining subst vertical stems\n", g->name);
- joinsubstems(vs, vs_pairs, g->nvs, 0);
-
- groupsubstems(g, hs, hs_pairs, g->nhs, vs, vs_pairs, g->nvs);
- }
-
- if (ISDBG(MAINSTEMS))
- fprintf(pfa_file, "%% %s: joining main horizontal stems\n", g->name);
- g->nhs = joinmainstems(hs, g->nhs, 1);
- if (ISDBG(MAINSTEMS))
- fprintf(pfa_file, "%% %s: joining main vertical stems\n", g->name);
- g->nvs = joinmainstems(vs, g->nvs, 0);
-
- if (ISDBG(MAINSTEMS))
- debugstems(g->name, hs, g->nhs, vs, g->nvs);
-
- if(g->nhs > 0) {
- if ((sp = malloc(sizeof(STEM) * g->nhs)) == 0) {
- fprintf(stderr, "**** not enough memory for hints ****\n");
- exit(255);
- }
- g->hstems = sp;
- memcpy(sp, hs, sizeof(STEM) * g->nhs);
- } else
- g->hstems = 0;
-
- if(g->nvs > 0) {
- if ((sp = malloc(sizeof(STEM) * g->nvs)) == 0) {
- fprintf(stderr, "**** not enough memory for hints ****\n");
- exit(255);
- }
- g->vstems = sp;
- memcpy(sp, vs, sizeof(STEM) * g->nvs);
- } else
- g->vstems = 0;
-
- /* now check that the stems won't overflow the interpreter's stem stack:
- * some interpreters (like X11) push the stems on each change into
- * stack and pop them only after the whole glyphs is completed.
- */
-
- totals = (g->nhs+g->nvs) / 2; /* we count whole stems, not halves */
- lastgrp = -1;
-
- for (ge = g->entries; ge != 0; ge = ge->next) {
- grp=ge->stemid;
- if(grp >= 0 && grp != lastgrp) {
- if(grp==0)
- totals += g->nsbs[0];
- else
- totals += g->nsbs[grp] - g->nsbs[grp-1];
-
- lastgrp = grp;
- }
- }
-
- /* be on the safe side, check for >= , not > */
- if(totals >= max_stemdepth) { /* oops, too deep */
- WARNING_2 {
- fprintf(stderr, "Warning: glyph %s needs hint stack depth %d\n", g->name, totals);
- fprintf(stderr, " (limit %d): removed the substituted hints from it\n", max_stemdepth);
- }
- if(g->nsg > 0) {
- for (ge = g->entries; ge != 0; ge = ge->next)
- ge->stemid = -1;
- free(g->sbstems); g->sbstems = 0;
- free(g->nsbs); g->nsbs = 0;
- g->nsg = 0;
- }
- }
-
- /* now check if there are too many main stems */
- totals = (g->nhs+g->nvs) / 2; /* we count whole stems, not halves */
- if(totals >= max_stemdepth) {
- /* even worse, too much of non-substituted stems */
- WARNING_2 {
- fprintf(stderr, "Warning: glyph %s has %d main hints\n", g->name, totals);
- fprintf(stderr, " (limit %d): removed the hints from it\n", max_stemdepth);
- }
- if(g->vstems) {
- free(g->vstems); g->vstems = 0; g->nvs = 0;
- }
- if(g->hstems) {
- free(g->hstems); g->hstems = 0; g->nhs = 0;
- }
- }
-}
-
-/* convert weird curves that are close to lines into lines.
-*/
-
-void
-fstraighten(
- GLYPH * g
-)
-{
- GENTRY *ge, *pge, *nge, *ige;
- double df;
- int dir;
- double iln, oln;
- int svdir, i, o;
-
- for (ige = g->entries; ige != 0; ige = ige->next) {
- if (ige->type != GE_CURVE)
- continue;
-
- ge = ige;
- pge = ge->bkwd;
- nge = ge->frwd;
-
- df = 0.;
-
- /* look for vertical then horizontal */
- for(i=0; i<2; i++) {
- o = !i; /* other axis */
-
- iln = fabs(ge->fpoints[i][2] - pge->fpoints[i][2]);
- oln = fabs(ge->fpoints[o][2] - pge->fpoints[o][2]);
- /*
- * if current curve is almost a vertical line, and it
- * doesn't begin or end horizontally (and the prev/next
- * line doesn't join smoothly ?)
- */
- if( oln < 1.
- || ge->fpoints[o][2] == ge->fpoints[o][1]
- || ge->fpoints[o][0] == pge->fpoints[o][2]
- || iln > 2.
- || iln > 1. && iln/oln > 0.1 )
- continue;
-
-
- if(ISDBG(STRAIGHTEN))
- fprintf(stderr,"** straighten almost %s\n", (i? "horizontal":"vertical"));
-
- df = ge->fpoints[i][2] - pge->fpoints[i][2];
- dir = fsign(ge->fpoints[o][2] - pge->fpoints[o][2]);
- ge->type = GE_LINE;
-
- /*
- * suck in all the sequence of such almost lines
- * going in the same direction but not deviating
- * too far from vertical
- */
- iln = fabs(nge->fpoints[i][2] - ge->fpoints[i][2]);
- oln = nge->fpoints[o][2] - ge->fpoints[o][2];
-
- while (fabs(df) <= 5 && nge->type == GE_CURVE
- && dir == fsign(oln) /* that also gives oln != 0 */
- && iln <= 2.
- && ( iln <= 1. || iln/fabs(oln) <= 0.1 ) ) {
- ge->fx3 = nge->fx3;
- ge->fy3 = nge->fy3;
-
- if(ISDBG(STRAIGHTEN))
- fprintf(stderr,"** straighten collapsing %s\n", (i? "horizontal":"vertical"));
- freethisge(nge);
- fixendpath(ge);
- pge = ge->bkwd;
- nge = ge->frwd;
-
- df = ge->fpoints[i][2] - pge->fpoints[i][2];
-
- iln = fabs(nge->fpoints[i][2] - ge->fpoints[i][2]);
- oln = nge->fpoints[o][2] - ge->fpoints[o][2];
- }
-
- /* now check what do we have as previous/next line */
-
- if(ge != pge) {
- if( pge->type == GE_LINE && pge->fpoints[i][2] == pge->prev->fpoints[i][2]
- && fabs(pge->fpoints[o][2] != pge->prev->fpoints[o][2]) ) {
- if(ISDBG(STRAIGHTEN)) fprintf(stderr,"** straighten join with previous 0x%x 0x%x\n", pge, ge);
- /* join the previous line with current */
- pge->fx3 = ge->fx3;
- pge->fy3 = ge->fy3;
-
- ige = freethisge(ge)->prev; /* keep the iterator valid */
- ge = pge;
- fixendpath(ge);
- pge = ge->bkwd;
- }
- }
-
- if(ge != nge) {
- if (nge->type == GE_LINE && nge->fpoints[i][2] == ge->fpoints[i][2]
- && fabs(nge->fpoints[o][2] != ge->fpoints[o][2]) ) {
- if(ISDBG(STRAIGHTEN)) fprintf(stderr,"** straighten join with next 0x%x 0x%x\n", ge, nge);
- /* join the next line with current */
- ge->fx3 = nge->fx3;
- ge->fy3 = nge->fy3;
-
- freethisge(nge);
- fixendpath(ge);
- pge = ge->bkwd;
- nge = ge->frwd;
-
- }
- }
-
- if(ge != pge) {
- /* try to align the lines if neccessary */
- if(df != 0.)
- fclosegap(ge, ge, i, df, NULL);
- } else {
- /* contour consists of only one line, get rid of it */
- ige = freethisge(ge); /* keep the iterator valid */
- if(ige == 0) /* this was the last contour */
- return;
- ige = ige->prev;
- }
-
- break; /* don't bother looking at the other axis */
- }
- }
-}
-
-/* solve a square equation,
- * returns the number of solutions found, the solutions
- * are stored in res which should point to array of two doubles.
- * min and max limit the area for solutions
- */
-
-static int
-fsqequation(
- double a,
- double b,
- double c,
- double *res,
- double min,
- double max
-)
-{
- double D;
- int n;
-
- if(ISDBG(SQEQ)) fprintf(stderr, "sqeq(%g,%g,%g) [%g;%g]\n", a, b, c, min, max);
-
- if(fabs(a) < 0.000001) { /* if a linear equation */
- n=0;
- if(fabs(b) < 0.000001) /* not an equation at all */
- return 0;
- res[0] = -c/b;
- if(ISDBG(SQEQ)) fprintf(stderr, "sqeq: linear t=%g\n", res[0]);
- if(res[0] >= min && res[0] <= max)
- n++;
- return n;
- }
-
- D = b*b - 4.0*a*c;
- if(ISDBG(SQEQ)) fprintf(stderr, "sqeq: D=%g\n", D);
- if(D<0)
- return 0;
-
- D = sqrt(D);
-
- n=0;
- res[0] = (-b+D) / (2*a);
- if(ISDBG(SQEQ)) fprintf(stderr, "sqeq: t1=%g\n", res[0]);
- if(res[0] >= min && res[0] <= max)
- n++;
-
- res[n] = (-b-D) / (2*a);
- if(ISDBG(SQEQ)) fprintf(stderr, "sqeq: t2=%g\n", res[n]);
- if(res[n] >= min && res[n] <= max)
- n++;
-
- /* return 2nd solution only if it's different enough */
- if(n==2 && fabs(res[0]-res[1])<0.000001)
- n=1;
-
- return n;
-}
-
-/* check that the curves don't cross quadrant boundary */
-/* (float) */
-
-/*
- Here we make sure that the curve does not continue past
- horizontal or vertical extremums. The horizontal points are
- explained, vertical points are by analogy.
-
- The horizontal points are where the derivative
- dy/dx is equal to 0. But the Bezier curves are defined by
- parametric formulas
- x=fx(t)
- y=fy(t)
- so finding this derivative is complicated.
- Also even if we find some point (x,y) splitting at this point
- is far not obvious. Fortunately we can use dy/dt = 0 instead,
- this gets to a rather simple square equation and splitting
- at a known value of t is simple.
-
- The formulas are:
-
- y = A*(1-t)^3 + 3*B*(1-t)^2*t + 3*C*(1-t)*t^2 + D*t^3
- y = (-A+3*B-3*C+D)*t^3 + (3*A-6*B+3*C)*t^2 + (-3*A+3*B)*t + A
- dy/dt = 3*(-A+3*B-3*C+D)*t^2 + 2*(3*A-6*B+3*C)*t + (-3*A+3*B)
- */
-
-void
-ffixquadrants(
- GLYPH *g
-)
-{
- GENTRY *ge, *nge;
- int i, j, np, oldnp;
- double sp[5]; /* split points, last one empty */
- char dir[5]; /* for debugging, direction by which split happened */
- double a, b, *pts; /* points of a curve */
-
- for (ge = g->entries; ge != 0; ge = ge->next) {
- if (ge->type != GE_CURVE)
- continue;
-
- doagain:
- np = 0; /* no split points yet */
- if(ISDBG(QUAD)) {
- fprintf(stderr, "%s: trying 0x%x (%g %g) (%g %g) (%g %g) (%g %g)\n ", g->name,
- ge, ge->prev->fx3, ge->prev->fy3, ge->fx1, ge->fy1, ge->fx2, ge->fy2,
- ge->fx3, ge->fy3);
- }
- for(i=0; i<2; i++) { /* first for x then for y */
- /* find the cooridnates of control points */
- a = ge->prev->fpoints[i][2];
- pts = &ge->fpoints[i][0];
-
- oldnp = np;
- np += fsqequation(
- 3.0*(-a + 3.0*pts[0] - 3.0*pts[1] + pts[2]),
- 6.0*(a - 2.0*pts[0] + pts[1]),
- 3.0*(-a + pts[0]),
- &sp[np],
- 0.0, 1.0); /* XXX range is [0;1] */
-
- if(np == oldnp)
- continue;
-
- if(ISDBG(QUAD))
- fprintf(stderr, "%s: 0x%x: %d pts(%c): ",
- g->name, ge, np-oldnp, i? 'y':'x');
-
- /* remove points that are too close to the ends
- * because hor/vert ends are permitted, also
- * if the split point is VERY close to the ends
- * but not exactly then just flatten it and check again.
- */
- for(j = oldnp; j<np; j++) {
- dir[j] = i;
- if(ISDBG(QUAD))
- fprintf(stderr, "%g ", sp[j]);
- if(sp[j] < 0.03) { /* front end of curve */
- if(ge->fpoints[i][0] != ge->prev->fpoints[i][2]) {
- ge->fpoints[i][0] = ge->prev->fpoints[i][2];
- if(ISDBG(QUAD)) fprintf(stderr, "flattened at front\n");
- goto doagain;
- }
- if( ge->fpoints[i][1] != ge->fpoints[i][0]
- && fsign(ge->fpoints[i][2] - ge->fpoints[i][1])
- != fsign(ge->fpoints[i][1] - ge->fpoints[i][0]) ) {
- ge->fpoints[i][1] = ge->fpoints[i][0];
- if(ISDBG(QUAD)) fprintf(stderr, "flattened zigzag at front\n");
- goto doagain;
- }
- sp[j] = sp[j+1]; np--; j--;
- if(ISDBG(QUAD)) fprintf(stderr, "(front flat) ");
- } else if(sp[j] > 0.97) { /* rear end of curve */
- if(ge->fpoints[i][1] != ge->fpoints[i][2]) {
- ge->fpoints[i][1] = ge->fpoints[i][2];
- if(ISDBG(QUAD)) fprintf(stderr, "flattened at rear\n");
- goto doagain;
- }
- if( ge->fpoints[i][0] != ge->fpoints[i][1]
- && fsign(ge->prev->fpoints[i][2] - ge->fpoints[i][0])
- != fsign(ge->fpoints[i][0] - ge->fpoints[i][1]) ) {
- ge->fpoints[i][0] = ge->fpoints[i][1];
- if(ISDBG(QUAD)) fprintf(stderr, "flattened zigzag at rear\n");
- goto doagain;
- }
- sp[j] = sp[j+1]; np--; j--;
- if(ISDBG(QUAD)) fprintf(stderr, "(rear flat) ");
- }
- }
- if(ISDBG(QUAD)) fprintf(stderr, "\n");
- }
-
- if(np==0) /* no split points, leave it alone */
- continue;
-
- if(ISDBG(QUAD)) {
- fprintf(stderr, "%s: splitting 0x%x (%g %g) (%g %g) (%g %g) (%g %g) at %d points\n ", g->name,
- ge, ge->prev->fx3, ge->prev->fy3, ge->fx1, ge->fy1, ge->fx2, ge->fy2,
- ge->fx3, ge->fy3, np);
- for(i=0; i<np; i++)
- fprintf(stderr, "%g(%c) ", sp[i], dir[i] ? 'y':'x');
- fprintf(stderr, "\n");
- }
-
- /* sort the points ascending */
- for(i=0; i<np; i++)
- for(j=i+1; j<np; j++)
- if(sp[i] > sp[j]) {
- a = sp[i]; sp[i] = sp[j]; sp[j] = a;
- }
-
- /* now finally do the split on each point */
- for(j=0; j<np; j++) {
- double k1, k2, c;
-
- k1 = sp[j];
- k2 = 1 - k1;
-
- if(ISDBG(QUAD)) fprintf(stderr, " 0x%x %g/%g\n", ge, k1, k2);
-
- nge = newgentry(GEF_FLOAT);
- (*nge) = (*ge);
-
-#define SPLIT(pt1, pt2) ( (pt1) + k1*((pt2)-(pt1)) ) /* order is important! */
- for(i=0; i<2; i++) { /* for x and y */
- a = ge->fpoints[i][0]; /* get the middle points */
- b = ge->fpoints[i][1];
-
- /* calculate new internal points */
- c = SPLIT(a, b);
-
- ge->fpoints[i][0] = SPLIT(ge->prev->fpoints[i][2], a);
- ge->fpoints[i][1] = SPLIT(ge->fpoints[i][0], c);
-
- nge->fpoints[i][1] = SPLIT(b, nge->fpoints[i][2]);
- nge->fpoints[i][0] = SPLIT(c, nge->fpoints[i][1]);
-
- ge->fpoints[i][2] = SPLIT(ge->fpoints[i][1],
- + nge->fpoints[i][0]);
- }
-#undef SPLIT
-
- addgeafter(ge, nge);
-
- /* go to the next part, adjust remaining points */
- ge = nge;
- for(i=j+1; i<np; i++)
- sp[i] = (sp[i]-k1) / k2;
- }
- }
-
-}
-
-/* check if a curve is a zigzag */
-
-static int
-iiszigzag(
- GENTRY *ge
-)
-{
- double k, k1, k2;
- int a, b;
-
- if (ge->type != GE_CURVE)
- return 0;
-
- a = ge->iy2 - ge->iy1;
- b = ge->ix2 - ge->ix1;
- if(a == 0) {
- if(b == 0) {
- return 0;
- } else
- k = FBIGVAL;
- } else
- k = fabs((double) b / (double) a);
-
- a = ge->iy1 - ge->prev->iy3;
- b = ge->ix1 - ge->prev->ix3;
- if(a == 0) {
- if(b == 0) {
- return 0;
- } else
- k1 = FBIGVAL;
- } else
- k1 = fabs((double) b / (double) a);
-
- a = ge->iy3 - ge->iy2;
- b = ge->ix3 - ge->ix2;
- if(a == 0) {
- if(b == 0) {
- return 0;
- } else
- k2 = FBIGVAL;
- } else
- k2 = fabs((double) b / (double) a);
-
- /* if the curve is not a zigzag */
- if (k1+0.0001 >= k && k2 <= k+0.0001 || k1 <= k+0.0001 && k2+0.0001 >= k)
- return 0;
- else
- return 1;
-}
-
-/* check if a curve is a zigzag - floating */
-
-static int
-fiszigzag(
- GENTRY *ge
-)
-{
- double k, k1, k2;
- double a, b;
-
- if (ge->type != GE_CURVE)
- return 0;
-
- a = fabs(ge->fy2 - ge->fy1);
- b = fabs(ge->fx2 - ge->fx1);
- if(a < FEPS) {
- if(b < FEPS) {
- return 0;
- } else
- k = FBIGVAL;
- } else
- k = b / a;
-
- a = fabs(ge->fy1 - ge->prev->fy3);
- b = fabs(ge->fx1 - ge->prev->fx3);
- if(a < FEPS) {
- if(b < FEPS) {
- return 0;
- } else
- k1 = FBIGVAL;
- } else
- k1 = b / a;
-
- a = fabs(ge->fy3 - ge->fy2);
- b = fabs(ge->fx3 - ge->fx2);
- if(a < FEPS) {
- if(b < FEPS) {
- return 0;
- } else
- k2 = FBIGVAL;
- } else
- k2 = b / a;
-
- /* if the curve is not a zigzag */
- if (k1+0.0001 >= k && k2 <= k+0.0001 || k1 <= k+0.0001 && k2+0.0001 >= k)
- return 0;
- else
- return 1;
-}
-
-/* split the zigzag-like curves into two parts */
-
-void
-fsplitzigzags(
- GLYPH * g
-)
-{
- GENTRY *ge, *nge;
- double a, b, c, d;
-
- assertisfloat(g, "splitting zigzags");
- for (ge = g->entries; ge != 0; ge = ge->next) {
- if (ge->type != GE_CURVE)
- continue;
-
- /* if the curve is not a zigzag */
- if ( !fiszigzag(ge) ) {
- continue;
- }
-
- if(ISDBG(FCONCISE)) {
- double maxsc1, maxsc2;
- fprintf(stderr, "split a zigzag ");
- fnormalizege(ge);
- if( fcrossraysge(ge, ge, &maxsc1, &maxsc2, NULL) ) {
- fprintf(stderr, "sc1=%g sc2=%g\n", maxsc1, maxsc2);
- } else {
- fprintf(stderr, "(rays don't cross)\n");
- }
- }
- /* split the curve by t=0.5 */
- nge = newgentry(GEF_FLOAT);
- (*nge) = (*ge);
- nge->type = GE_CURVE;
-
- a = ge->prev->fx3;
- b = ge->fx1;
- c = ge->fx2;
- d = ge->fx3;
- nge->fx3 = d;
- nge->fx2 = (c + d) / 2.;
- nge->fx1 = (b + 2. * c + d) / 4.;
- ge->fx3 = (a + b * 3. + c * 3. + d) / 8.;
- ge->fx2 = (a + 2. * b + c) / 4.;
- ge->fx1 = (a + b) / 2.;
-
- a = ge->prev->fy3;
- b = ge->fy1;
- c = ge->fy2;
- d = ge->fy3;
- nge->fy3 = d;
- nge->fy2 = (c + d) / 2.;
- nge->fy1 = (b + 2. * c + d) / 4.;
- ge->fy3 = (a + b * 3. + c * 3. + d) / 8.;
- ge->fy2 = (a + 2. * b + c) / 4.;
- ge->fy1 = (a + b) / 2.;
-
- addgeafter(ge, nge);
-
- if(ISDBG(FCONCISE)) {
- dumppaths(g, ge, nge);
- }
- }
-}
-
-/* free this GENTRY, returns what was ge->next
- * (ge must be of type GE_LINE or GE_CURVE)
- * works on both float and int entries
- */
-
-static GENTRY *
-freethisge(
- GENTRY *ge
-)
-{
- GENTRY *xge;
-
- if (ge->bkwd != ge->prev) {
- /* at beginning of the contour */
-
- xge = ge->bkwd;
- if(xge == ge) { /* was the only line in contour */
- /* remove the contour completely */
- /* prev is GE_MOVE, next is GE_PATH, remove them all */
-
- /* may be the first contour, then ->bkwd points to ge->entries */
- if(ge->prev->prev == 0)
- *(GENTRY **)(ge->prev->bkwd) = ge->next->next;
- else
- ge->prev->prev->next = ge->next->next;
-
- if(ge->next->next) {
- ge->next->next->prev = ge->prev->prev;
- ge->next->next->bkwd = ge->prev->bkwd;
- }
-
- xge = ge->next->next;
- free(ge->prev); free(ge->next); free(ge);
- return xge;
- }
-
- /* move the start point of the contour */
- if(ge->flags & GEF_FLOAT) {
- ge->prev->fx3 = xge->fx3;
- ge->prev->fy3 = xge->fy3;
- } else {
- ge->prev->ix3 = xge->ix3;
- ge->prev->iy3 = xge->iy3;
- }
- } else if(ge->frwd != ge->next) {
- /* at end of the contour */
-
- xge = ge->frwd->prev;
- /* move the start point of the contour */
- if(ge->flags & GEF_FLOAT) {
- xge->fx3 = ge->bkwd->fx3;
- xge->fy3 = ge->bkwd->fy3;
- } else {
- xge->ix3 = ge->bkwd->ix3;
- xge->iy3 = ge->bkwd->iy3;
- }
- }
-
- ge->prev->next = ge->next;
- ge->next->prev = ge->prev;
- ge->bkwd->frwd = ge->frwd;
- ge->frwd->bkwd = ge->bkwd;
-
- xge = ge->next;
- free(ge);
- return xge;
-}
-
-/* inserts a new gentry (LINE or CURVE) after another (MOVE
- * or LINE or CURVE)
- * corrects the first GE_MOVE if neccessary
- */
-
-static void
-addgeafter(
- GENTRY *oge, /* after this */
- GENTRY *nge /* insert this */
-)
-{
- if(oge->type == GE_MOVE) {
- /* insert before next */
- if(oge->next->type == GE_PATH) {
- /* first and only GENTRY in path */
- nge->frwd = nge->bkwd = nge;
- } else {
- nge->frwd = oge->next;
- nge->bkwd = oge->next->bkwd;
- oge->next->bkwd->frwd = nge;
- oge->next->bkwd = nge;
- }
- } else {
- nge->frwd = oge->frwd;
- nge->bkwd = oge;
- oge->frwd->bkwd = nge;
- oge->frwd = nge;
- }
-
- nge->next = oge->next;
- nge->prev = oge;
- oge->next->prev = nge;
- oge->next = nge;
-
- if(nge->frwd->prev->type == GE_MOVE) {
- /* fix up the GE_MOVE entry */
- if(nge->flags & GEF_FLOAT) {
- nge->frwd->prev->fx3 = nge->fx3;
- nge->frwd->prev->fy3 = nge->fy3;
- } else {
- nge->frwd->prev->ix3 = nge->ix3;
- nge->frwd->prev->iy3 = nge->iy3;
- }
- }
-}
-
-/*
- * Check if this GENTRY happens to be at the end of path
- * and fix the first MOVETO accordingly
- * handles both int and float
- */
-
-static void
-fixendpath(
- GENTRY *ge
-)
-{
- GENTRY *mge;
-
- mge = ge->frwd->prev;
- if(mge->type == GE_MOVE) {
- if(ge->flags & GEF_FLOAT) {
- mge->fx3 = ge->fx3;
- mge->fy3 = ge->fy3;
- } else {
- mge->ix3 = ge->ix3;
- mge->iy3 = ge->iy3;
- }
- }
-}
-
-/*
- * This function adjusts the rest of path (the part from...to is NOT changed)
- * to cover the specified gap by the specified axis (0 - X, 1 - Y).
- * Gap is counted in direction (end_of_to - beginning_of_from).
- * Returns by how much the gap was not closed (0.0 if it was fully closed).
- * Ret contains by how much the first and last points of [from...to]
- * were moved to bring them in consistence to the rest of the path.
- * If ret==NULL then this info is not returned.
- */
-
-static double
-fclosegap(
- GENTRY *from,
- GENTRY *to,
- int axis,
- double gap,
- double *ret
-)
-{
-#define TIMESLARGER 10. /* how many times larger must be a curve to not change too much */
- double rm[2];
- double oldpos[2];
- double times, limit, df, dx;
- int j, k;
- GENTRY *xge, *pge, *nge, *bge[2];
-
- /* remember the old points to calculate ret */
- oldpos[0] = from->prev->fpoints[axis][2];
- oldpos[1] = to->fpoints[axis][2];
-
- rm[0] = rm[1] = gap / 2. ;
-
- bge[0] = from; /* this is convenient for iterations */
- bge[1] = to;
-
- /* first try to modify large curves but if have none then settle for small */
- for(times = (TIMESLARGER-1); times > 0.1; times /= 2. ) {
-
- if(rm[0]+rm[1] == 0.)
- break;
-
- /* iterate in both directions, backwards then forwards */
- for(j = 0; j<2; j++) {
-
- if(rm[j] == 0.) /* if this direction is exhausted */
- continue;
-
- limit = fabs(rm[j]) * (1.+times);
-
- for(xge = bge[j]->cntr[j]; xge != bge[!j]; xge = xge->cntr[j]) {
- dx = xge->fpoints[axis][2] - xge->prev->fpoints[axis][2];
- df = fabs(dx) - limit;
- if( df <= FEPS ) /* curve is too small to change */
- continue;
-
- if( df >= fabs(rm[j]) )
- df = rm[j];
- else
- df *= fsign(rm[j]); /* we may cover this part of rm */
-
- rm[j] -= df;
- limit = fabs(rm[j]) * (1.+times);
-
- if(xge->type == GE_CURVE) { /* correct internal points */
- double scale = ((dx+df) / dx) - 1.;
- double base;
-
- if(j)
- base = xge->fpoints[axis][2];
- else
- base = xge->prev->fpoints[axis][2];
-
- for(k = 0; k<2; k++)
- xge->fpoints[axis][k] += scale *
- (xge->fpoints[axis][k] - base);
- }
-
- /* move all the intermediate lines */
- if(j) {
- df = -df; /* absolute direction */
- pge = bge[1]->bkwd;
- nge = xge->bkwd;
- } else {
- xge->fpoints[axis][2] += df;
- pge = bge[0];
- nge = xge->frwd;
- }
- while(nge != pge) {
- if(nge->type == GE_CURVE) {
- nge->fpoints[axis][0] +=df;
- nge->fpoints[axis][1] +=df;
- }
- nge->fpoints[axis][2] += df;
- if(nge->next != nge->frwd) { /* last entry of contour */
- nge->frwd->prev->fpoints[axis][2] += df;
- }
- nge = nge->cntr[!j];
- }
-
- if(rm[j] == 0.)
- break;
- }
- }
- }
-
- /* find the difference */
- oldpos[0] -= from->prev->fpoints[axis][2];
- oldpos[1] -= to->fpoints[axis][2];
-
- if(ret) {
- ret[0] = oldpos[0] - from->prev->fpoints[axis][2];
- ret[1] = oldpos[1] - to->fpoints[axis][2];
- }
-
-#if 0
- if( rm[0]+rm[1] != gap - oldpos[1] + oldpos[0]) {
- fprintf(stderr, "** gap=%g rm[0]=%g rm[1]=%g o[0]=%g o[1]=%g rg=%g og=%g\n",
- gap, rm[0], rm[1], oldpos[0], oldpos[1], rm[0]+rm[1],
- gap - oldpos[1] + oldpos[0]);
- }
-#endif
-
- return rm[0]+rm[1];
-#undef TIMESLARGER
-}
-
-/* remove the lines or curves smaller or equal to the size limit */
-
-static void
-fdelsmall(
- GLYPH *g,
- double minlen
-)
-{
- GENTRY *ge, *nge, *pge, *xge, *next;
- int i, k;
- double dx, dy, d2, d2m;
- double minlen2;
-#define TIMESLARGER 10. /* how much larger must be a curve to not change too much */
-
- minlen2 = minlen*minlen;
-
- for (ge = g->entries; ge != 0; ge = next) {
- next = ge->next;
-
- if (ge->type != GE_CURVE && ge->type != GE_LINE)
- continue;
-
- d2m = 0;
- for(i= (ge->type==GE_CURVE? 0: 2); i<3; i++) {
- dx = ge->fxn[i] - ge->prev->fx3;
- dy = ge->fyn[i] - ge->prev->fy3;
- d2 = dx*dx + dy*dy;
- if(d2m < d2)
- d2m = d2;
- }
-
- if( d2m > minlen2 ) { /* line is not too small */
- /* XXX add more normalization here */
- continue;
- }
-
- /* if the line is too small */
-
- /* check forwards if we have a whole sequence of them */
- nge = ge;
- for(xge = ge->frwd; xge != ge; xge = xge->frwd) {
- d2m = 0;
- for(i= (xge->type==GE_CURVE? 0: 2); i<3; i++) {
- dx = xge->fxn[i] - xge->prev->fx3;
- dy = xge->fyn[i] - xge->prev->fy3;
- d2 = dx*dx + dy*dy;
- if(d2m < d2)
- d2m = d2;
- }
- if( d2m > minlen2 ) /* line is not too small */
- break;
- nge = xge;
- if(next == nge) /* move the next step past this sequence */
- next = next->next;
- }
-
- /* check backwards if we have a whole sequence of them */
- pge = ge;
- for(xge = ge->bkwd; xge != ge; xge = xge->bkwd) {
- d2m = 0;
- for(i= (xge->type==GE_CURVE? 0: 2); i<3; i++) {
- dx = xge->fxn[i] - xge->prev->fx3;
- dy = xge->fyn[i] - xge->prev->fy3;
- d2 = dx*dx + dy*dy;
- if(d2m < d2)
- d2m = d2;
- }
- if( d2m > minlen2 ) /* line is not too small */
- break;
- pge = xge;
- }
-
- /* now we have a sequence of small fragments in pge...nge (inclusive) */
-
- if(ISDBG(FCONCISE)) {
- fprintf(stderr, "glyph %s has very small fragments(%x..%x..%x)\n",
- g->name, pge, ge, nge);
- dumppaths(g, pge, nge);
- }
-
- /* reduce whole sequence to one part and remember the middle point */
- if(pge != nge) {
- while(1) {
- xge = pge->frwd;
- if(xge == nge) {
- pge->fx1 = pge->fx2 = pge->fx3;
- pge->fx3 = nge->fx3;
- pge->fy1 = pge->fy2 = pge->fy3;
- pge->fy3 = nge->fy3;
- pge->type = GE_CURVE;
- freethisge(nge);
- break;
- }
- if(xge == nge->bkwd) {
- pge->fx1 = pge->fx2 = (pge->fx3+xge->fx3)/2.;
- pge->fx3 = nge->fx3;
- pge->fy1 = pge->fy2 = (pge->fy3+xge->fy3)/2.;
- pge->fy3 = nge->fy3;
- pge->type = GE_CURVE;
- freethisge(nge);
- freethisge(xge);
- break;
- }
- freethisge(pge); pge = xge;
- xge = nge->bkwd; freethisge(nge); nge = xge;
- }
- }
- ge = pge;
-
- /* check if the whole sequence is small */
- dx = ge->fx3 - ge->prev->fx3;
- dy = ge->fy3 - ge->prev->fy3;
- d2 = dx*dx + dy*dy;
-
- if( d2 > minlen2 ) { /* no, it is not */
- double b, d;
-
- WARNING_3 fprintf(stderr, "glyph %s had a sequence of fragments < %g points each, reduced to one curve\n",
- g->name, minlen);
-
- /* check that we did not create a monstrosity spanning quadrants */
- if(fsign(ge->fx1 - ge->prev->fx1) * fsign(ge->fx3 - ge->fx1) < 0
- || fsign(ge->fy1 - ge->prev->fy1) * fsign(ge->fy3 - ge->fy1) < 0 ) {
- /* yes, we did; are both parts of this thing big enough ? */
- dx = ge->fx1 - ge->prev->fx3;
- dy = ge->fy1 - ge->prev->fy3;
- d2 = dx*dx + dy*dy;
-
- dx = ge->fx3 - ge->fx1;
- dy = ge->fy3 - ge->fy1;
- d2m = dx*dx + dy*dy;
-
- if(d2 > minlen2 && d2m > minlen2) { /* make two straights */
- nge = newgentry(GEF_FLOAT);
- *nge = *ge;
-
- for(i=0; i<2; i++) {
- ge->fpoints[i][2] = ge->fpoints[i][0];
- b = nge->fpoints[i][0];
- d = nge->fpoints[i][2] - b;
- nge->fpoints[i][0] = b + 0.1*d;
- nge->fpoints[i][1] = b + 0.9*d;
- }
- }
- for(i=0; i<2; i++) { /* make one straight or first of two straights */
- b = ge->prev->fpoints[i][2];
- d = ge->fpoints[i][2] - b;
- ge->fpoints[i][0] = b + 0.1*d;
- ge->fpoints[i][1] = b + 0.9*d;
- }
- }
- continue;
- }
-
- if(ge->frwd == ge) { /* points to itself, just remove the path completely */
- WARNING_3 fprintf(stderr, "glyph %s had a path made of fragments < %g points each, removed\n",
- g->name, minlen);
-
- next = freethisge(ge);
- continue;
- }
-
- /* now close the gap by x and y */
- for(i=0; i<2; i++) {
- double gap;
-
- gap = ge->fpoints[i][2] - ge->prev->fpoints[i][2];
- if( fclosegap(ge, ge, i, gap, NULL) != 0.0 ) {
- double scale, base;
-
- /* not good, as the last resort just scale the next line */
- gap = ge->fpoints[i][2] - ge->prev->fpoints[i][2];
-
- if(ISDBG(FCONCISE))
- fprintf(stderr, " last resort on %c: closing next by %g\n",
- (i==0 ? 'x' : 'y'), gap);
-
- nge = ge->frwd;
- base = nge->fpoints[i][2];
- dx = ge->fpoints[i][2] - base;
- if(fabs(dx) < FEPS)
- continue;
-
- scale = ((dx-gap) / dx);
-
- if(nge->type == GE_CURVE)
- for(k = 0; k<2; k++)
- nge->fpoints[i][k] = base +
- scale * (nge->fpoints[i][k] - base);
-
- ge->fpoints[i][2] -= gap;
- }
- }
-
- /* OK, the gap is closed - remove this useless GENTRY */
- freethisge(ge);
- }
-#undef TIMESLARGER
-}
-
-/* find the point where two rays continuing vectors cross
- * returns 1 if they cross, 0 if they don't
- * If they cross optionally (if the pointers are not NULL) returns
- * the maximal scales for both vectors and also optionally the point
- * where the rays cross (twice).
- * Expects that the curves are normalized.
- *
- * For convenience there are 2 front-end functions taking
- * arguments in different formats
- */
-
-struct ray {
- double x1, y1, x2, y2;
- int isvert;
- double k, b; /* lines are represented as y = k*x + b */
- double *maxp;
-};
-static struct ray ray[3];
-
-/* the back-end doing the actual work
- * the rays are defined in the static array ray[]
- */
-
-static int
-fcrossraysxx(
- double crossdot[2][2]
-)
-{
- double x, y, max;
- int i;
-
- for(i=0; i<2; i++) {
- if(ray[i].x1 == ray[i].x2)
- ray[i].isvert = 1;
- else {
- ray[i].isvert = 0;
- ray[i].k = (ray[i].y2 - ray[i].y1) / (ray[i].x2 - ray[i].x1);
- ray[i].b = ray[i].y2 - ray[i].k * ray[i].x2;
- }
- }
-
- if(ray[0].isvert && ray[1].isvert) {
- if(ISDBG(FCONCISE)) fprintf(stderr, "crossrays: both vertical\n");
- return 0; /* both vertical, don't cross */
- }
-
- if(ray[1].isvert) {
- ray[2] = ray[0]; /* exchange them */
- ray[0] = ray[1];
- ray[1] = ray[2];
- }
-
- if(ray[0].isvert) {
- x = ray[0].x1;
- } else {
- if( fabs(ray[0].k - ray[1].k) < FEPS) {
- if(ISDBG(FCONCISE)) fprintf(stderr, "crossrays: parallel lines, k = %g, %g\n",
- ray[0].k, ray[1].k);
- return 0; /* parallel lines */
- }
- x = (ray[1].b - ray[0].b) / (ray[0].k - ray[1].k) ;
- }
- y = ray[1].k * x + ray[1].b;
-
- for(i=0; i<2; i++) {
- if(ray[i].isvert)
- max = (y - ray[i].y1) / (ray[i].y2 - ray[i].y1);
- else
- max = (x - ray[i].x1) / (ray[i].x2 - ray[i].x1);
- /* check if wrong sides of rays cross */
- if( max < 0 ) {
- if(ISDBG(FCONCISE)) fprintf(stderr, "crossrays: %c scale=%g @(%g,%g) (%g,%g)<-(%g,%g)\n",
- (i?'Y':'X'), max, x, y, ray[i].x2, ray[i].y2, ray[i].x1, ray[i].y1);
- return 0;
- }
- if(ray[i].maxp)
- *ray[i].maxp = max;
- }
- if(crossdot != 0) {
- crossdot[0][0] = crossdot[1][0] = x;
- crossdot[0][1] = crossdot[1][1] = y;
- }
- return 1;
-}
-
-/* the front-end getting the arguments from 4 dots defining
- * a curve in the same format as for fapproxcurve():
- * rays are defined as beginning and end of the curve,
- * the crossdot is inserted as the two middle dots of the curve
- */
-
-int
-fcrossrayscv(
- double curve[4][2 /*X,Y*/],
- double *max1,
- double *max2
-)
-{
- ray[0].x1 = curve[0][X];
- ray[0].y1 = curve[0][Y];
- ray[0].x2 = curve[1][X];
- ray[0].y2 = curve[1][Y];
- ray[0].maxp = max1;
-
- ray[1].x1 = curve[2][X];
- ray[1].y1 = curve[2][Y];
- ray[1].x2 = curve[3][X];
- ray[1].y2 = curve[3][Y];
- ray[1].maxp = max2;
-
- return fcrossraysxx(&curve[1]);
-}
-
-/* the front-end getting the arguments from gentries:
- * rays are defined as beginning of curve1 and end of curve 2
- */
-
-int
-fcrossraysge(
- GENTRY *ge1,
- GENTRY *ge2,
- double *max1,
- double *max2,
- double crossdot[2][2]
-)
-{
- ray[0].x1 = ge1->prev->fx3;
- ray[0].y1 = ge1->prev->fy3;
- ray[0].x2 = ge1->fpoints[X][ge1->ftg];
- ray[0].y2 = ge1->fpoints[Y][ge1->ftg];
- ray[0].maxp = max1;
-
- ray[1].x1 = ge2->fx3;
- ray[1].y1 = ge2->fy3;
- if(ge2->rtg < 0) {
- ray[1].x2 = ge2->prev->fx3;
- ray[1].y2 = ge2->prev->fy3;
- } else {
- ray[1].x2 = ge2->fpoints[X][ge2->rtg];
- ray[1].y2 = ge2->fpoints[Y][ge2->rtg];
- }
- ray[1].maxp = max2;
-
- return fcrossraysxx(crossdot);
-}
-
-/* debugging printout functions */
-
-#if defined(DEBUG_DOTSEG) || defined(DEBUG_DOTCURVE) || defined(DEBUG_APPROXCV)
-
-/* for debugging */
-static
-printdot(
- double dot[2]
-)
-{
- fprintf(stderr, "(%g,%g)", dot[0], dot[1]);
-}
-
-static
-printseg(
- double seg[2][2]
-)
-{
- putc('[', stderr);
- printdot(seg[0]);
- putc(' ', stderr);
- printdot(seg[1]);
- putc(']', stderr);
-}
-
-#endif /* DEBUG_* */
-
-/*
- * Find squared distance from a dot to a line segment
- */
-
-double
-fdotsegdist2(
- double seg[2][2 /*X,Y*/],
- double dot[2 /*X,Y*/]
-)
-{
-#define x1 seg[0][X]
-#define y1 seg[0][Y]
-#define x2 seg[1][X]
-#define y2 seg[1][Y]
-#define xdot dot[X]
-#define ydot dot[Y]
-
- double dx, dy; /* segment dimensions */
- double kline, bline; /* segment line formula is y=k*x+b */
- double kperp, bperp; /* perpendicular from the dot to the line */
- double xcross, ycross; /* where the perpendicular crosses the segment */
-
-/* handle the situation where the nearest point of the segment is its end */
-#define HANDLE_LIMITS(less12, lesscr1, lesscr2) \
- if( less12 ) { \
- if( lesscr1 ) { \
- xcross = x1; \
- ycross = y1; \
- } else if( !(lesscr2) ) { \
- xcross = x2; \
- ycross = y2; \
- } \
- } else { \
- if( !(lesscr1) ) { \
- xcross = x1; \
- ycross = y1; \
- } else if( lesscr2 ) { \
- xcross = x2; \
- ycross = y2; \
- } \
- } \
- /* end of macro */
-
-
- dx = x2 - x1;
- dy = y2 - y1;
-
- if(fabs(dx) < FEPS) {
- /* special case - vertical line */
-#ifdef DEBUG_DOTSEG
- printf("vertical line!\n");
-#endif
- xcross = x1;
- ycross = ydot;
- HANDLE_LIMITS( y1 < y2, ycross < y1, ycross < y2);
- } else if(fabs(dy) < FEPS) {
- /* special case - horizontal line */
-#ifdef DEBUG_DOTSEG
- printf("horizontal line!\n");
-#endif
- xcross = xdot;
- ycross = y1;
- HANDLE_LIMITS( x1 < x2, xcross < x1, xcross < x2)
- } else {
- kline = dy/dx;
- bline = y1 - x1*kline;
- kperp = -1./kline;
- bperp = ydot - xdot*kperp;
-
- xcross = (bline-bperp) / (kperp-kline);
- ycross = kline*xcross + bline;
-
- HANDLE_LIMITS( x1 < x2, xcross < x1, xcross < x2)
- }
-#ifdef DEBUG_DOTSEG
- printf("crossover at (%g,%g)\n", xcross, ycross);
-#endif
-
- dx = xdot-xcross;
- dy = ydot-ycross;
- return dx*dx+dy*dy;
-#undef x1
-#undef y1
-#undef x2
-#undef y2
-#undef xdot
-#undef ydot
-#undef HANDLE_LIMITS
-}
-
-/* find the weighted quadratic average for the distance of a set
- * of dots from the curve; also fills out the individual distances
- * for each dot; if maxp!=NULL then returns the maximal squared
- * distance in there
- */
-
-double
-fdotcurvdist2(
- double curve[4][2 /*X,Y*/ ],
- struct dot_dist *dots,
- int ndots, /* number of entries in dots */
- double *maxp
-)
-{
- /* a curve is approximated by this many straight segments */
-#define NAPSECT 16
- /* a curve is divided into this many sections with equal weight each */
-#define NWSECT 4
- /* table of coefficients for finding the dots on the curve */
- /* tt[0] is left unused */
- static double tt[NAPSECT][4];
- static int havett = 0; /* flag: tt is initialized */
- /* dots on the curve */
- double cvd[NAPSECT+1][2 /*X,Y*/];
- /* sums by sections */
- double sum[NWSECT];
- /* counts by sections */
- double count[NWSECT];
- int d, i, j;
- int id1, id2;
- double dist1, dist2, dist3, dx, dy, x, y;
- double max = 0.;
-
- if(!havett) {
- double t, nt, t2, nt2, step;
-
- havett++;
- step = 1. / NAPSECT;
- t = 0;
- for(i=1; i<NAPSECT; i++) {
- t += step;
- nt = 1 - t;
- t2 = t*t;
- nt2 = nt*nt;
- tt[i][0] = nt2*nt; /* (1-t)^3 */
- tt[i][1] = 3*nt2*t; /* 3*(1-t)^2*t */
- tt[i][2] = 3*nt*t2; /* 3*(1-t)*t^2 */
- tt[i][3] = t2*t; /* t^3 */
- }
- }
-
- for(i=0; i<NWSECT; i++) {
- sum[i] = 0.;
- count[i] = 0;
- }
-
- /* split the curve into segments */
- for(d=0; d<2; d++) { /* X and Y */
- cvd[0][d] = curve[0][d]; /* endpoints */
- cvd[NAPSECT][d] = curve[3][d];
- for(i=1; i<NAPSECT; i++) {
- cvd[i][d] = curve[0][d] * tt[i][0]
- + curve[1][d] * tt[i][1]
- + curve[2][d] * tt[i][2]
- + curve[3][d] * tt[i][3];
- }
- }
-
- for(d=0; d<ndots; d++) {
-#ifdef DEBUG_DOTCURVE
- printf("dot %d ", d); printdot(dots[d].p); printf(":\n");
-
- /* for debugging */
- for(i=0; i< NAPSECT; i++) {
- dist1 = fdotsegdist2(&cvd[i], dots[d].p);
- printf(" seg %d ",i); printseg(&cvd[i]); printf(" dist=%g\n", sqrt(dist1));
- }
-#endif
-
- x = dots[d].p[X];
- y = dots[d].p[Y];
-
- /* find the nearest dot on the curve
- * there may be up to 2 local minimums - so we start from the
- * ends of curve and go to the center
- */
-
- id1 = 0;
- dx = x - cvd[0][X];
- dy = y - cvd[0][Y];
- dist1 = dx*dx + dy*dy;
-#ifdef DEBUG_DOTCURVE
- printf(" dot 0 "); printdot(cvd[id1]); printf(" dist=%g\n", sqrt(dist1));
-#endif
- for(i = 1; i<=NAPSECT; i++) {
- dx = x - cvd[i][X];
- dy = y - cvd[i][Y];
- dist3 = dx*dx + dy*dy;
-#ifdef DEBUG_DOTCURVE
- printf(" dot %d ",i); printdot(cvd[i]); printf(" dist=%g\n", sqrt(dist3));
-#endif
- if(dist3 < dist1) {
- dist1 = dist3;
- id1 = i;
- } else
- break;
- }
-
- if(id1 < NAPSECT-1) {
- id2 = NAPSECT;
- dx = x - cvd[NAPSECT][X];
- dy = y - cvd[NAPSECT][Y];
- dist2 = dx*dx + dy*dy;
-#ifdef DEBUG_DOTCURVE
- printf(" +dot %d ", id2); printdot(cvd[id2]); printf(" dist=%g\n", sqrt(dist2));
-#endif
- for(i = NAPSECT-1; i>id1+1; i--) {
- dx = x - cvd[i][X];
- dy = y - cvd[i][Y];
- dist3 = dx*dx + dy*dy;
-#ifdef DEBUG_DOTCURVE
- printf(" dot %d ",i); printdot(cvd[i]); printf(" dist=%g\n", sqrt(dist3));
-#endif
- if(dist3 < dist2) {
- dist2 = dist3;
- id2 = i;
- } else
- break;
- }
-
- /* now find which of the local minimums is smaller */
- if(dist2 < dist1) {
- id1 = id2;
- }
- }
-
- /* the nearest segment must include the nearest dot */
- if(id1==0) {
- dots[d].seg = 0;
- dots[d].dist2 = fdotsegdist2(&cvd[0], dots[d].p);
- } else if(id1==NAPSECT) {
- dots[d].seg = NAPSECT-1;
- dots[d].dist2 = fdotsegdist2(&cvd[NAPSECT-1], dots[d].p);
- } else {
- dist1 = fdotsegdist2(&cvd[id1], dots[d].p);
- dist2 = fdotsegdist2(&cvd[id1-1], dots[d].p);
- if(dist2 < dist1) {
- dots[d].seg = id1-1;
- dots[d].dist2 = dist2;
- } else {
- dots[d].seg = id1;
- dots[d].dist2 = dist1;
- }
- }
-
- i = dots[d].seg % NWSECT;
- sum[i] += dots[d].dist2;
- if(dots[d].dist2 > max)
- max = dots[d].dist2;
- count[i]++;
-#ifdef DEBUG_DOTCURVE
- printf(" best seg %d sect %d dist=%g\n", dots[d].seg, i, sqrt(dots[d].dist2));
-#endif
- }
-
- /* calculate the weighted average */
- id1=0;
- dist1=0.;
- for(i=0; i<NWSECT; i++) {
- if(count[i]==0)
- continue;
- id1++;
- dist1 += sum[i]/count[i];
- }
- if(maxp)
- *maxp = max;
- if(id1==0) /* no dots, strange */
- return 0.;
- else
- return dist1/id1; /* to get the average distance apply sqrt() */
-}
-
-/*
- * Approximate a curve matching the giving set of points and with
- * middle reference points going along the given segments (and no farther
- * than these segments).
- */
-
-void
-fapproxcurve(
- double cv[4][2 /*X,Y*/ ], /* points 0-3 are passed in, points 1,2 - out */
- struct dot_dist *dots, /* the dots to approximate - distances returned
- * there may be invalid */
- int ndots
-)
-{
- /* b and c are the middle control points */
-#define B 0
-#define C 1
- /* maximal number of sections on each axis - used for the first step */
-#define MAXSECT 2
- /* number of sections used for the other steps */
-#define NORMSECT 2
- /* when the steps become less than this many points, it's time to stop */
-#define STEPEPS 1.
- double from[2 /*B,C*/], to[2 /*B,C*/];
- double middf[2 /*B,C*/][2 /*X,Y*/], df;
- double coef[2 /*B,C*/][MAXSECT];
- double res[MAXSECT][MAXSECT], thisres, bestres, goodres;
- int ncoef[2 /*B,C*/], best[2 /*B,C*/], good[2 /*B,C*/];
- int i, j, k, keepsym;
- char bc[]="BC";
- char xy[]="XY";
-
-#ifdef DEBUG_APPROXCV
- fprintf(stderr, "Curve points:");
- for(i=0; i<4; i++) {
- fprintf(stderr, " ");
- printdot(cv[i]);
- }
- fprintf(stderr, "\nDots:");
- for(i=0; i<ndots; i++) {
- fprintf(stderr, " ");
- printdot(dots[i].p);
- }
- fprintf(stderr, "\n");
-#endif
-
- /* load the endpoints and calculate differences */
- for(i=0; i<2; i++) {
- /* i is X, Y */
- middf[B][i] = cv[1][i]-cv[0][i];
- middf[C][i] = cv[2][i]-cv[3][i];
-
- /* i is B, C */
- from[i] = 0.;
- to[i] = 1.;
- ncoef[i] = MAXSECT;
- }
-
- while(ncoef[B] != 1 || ncoef[C] != 1) {
- /* prepare the values of coefficients */
- for(i=0; i<2; i++) { /*B,C*/
-#ifdef DEBUG_APPROXCV
- fprintf(stderr, "Coefficients by %c(%g,%g):", bc[i], from[i], to[i]);
-#endif
- df = (to[i]-from[i]) / (ncoef[i]*2);
- for(j=0; j<ncoef[i]; j++) {
- coef[i][j] = from[i] + df*(2*j+1);
-#ifdef DEBUG_APPROXCV
- fprintf(stderr, " %g", coef[i][j]);
-#endif
- }
-#ifdef DEBUG_APPROXCV
- fprintf(stderr, "\n");
-#endif
- }
- bestres = FBIGVAL;
- /* i iterates by ncoef[B], j iterates by ncoef[C] */
- for(i=0; i<ncoef[B]; i++) {
- for(j=0; j<ncoef[C]; j++) {
- for(k=0; k<2; k++) { /*X, Y*/
- cv[1][k] = cv[0][k] + middf[B][k]*coef[B][i];
- cv[2][k] = cv[3][k] + middf[C][k]*coef[C][j];
- }
- res[i][j] = thisres = fdotcurvdist2(cv, dots, ndots, NULL);
- if(thisres < bestres) {
- goodres = bestres;
- good[B] = best[B];
- good[C] = best[C];
- bestres = thisres;
- best[B] = i;
- best[C] = j;
- } else if(thisres < goodres) {
- goodres = thisres;
- good[B] = i;
- good[C] = j;
- }
-#ifdef DEBUG_APPROXCV
- fprintf(stderr, " at (%g,%g) dist=%g %s\n", coef[B][i], coef[C][j], sqrt(thisres),
- (best[B]==i && best[C]==j)? "(BEST)":"");
-#endif
- }
- }
-#ifdef DEBUG_APPROXCV
- fprintf(stderr, " best: at (%g, %g) dist=%g\n",
- coef[B][best[B]], coef[C][best[C]], sqrt(bestres));
- fprintf(stderr, " B:%d,%d C:%d,%d -- 2nd best: at (%g, %g) dist=%g\n",
- best[B], good[B], best[C], good[C], coef[B][good[B]], coef[C][good[C]], sqrt(goodres));
-#endif
-
- if(bestres < (0.1*0.1)) { /* consider it close enough */
- /* calculate the coordinates to return */
- for(k=0; k<2; k++) { /*X, Y*/
- cv[1][k] = cv[0][k] + middf[B][k]*coef[B][best[B]];
- cv[2][k] = cv[3][k] + middf[C][k]*coef[C][best[C]];
- }
-#ifdef DEBUG_APPROXCV
- fprintf(stderr, "quick approximated middle points "); printdot(cv[1]);
- fprintf(stderr, " "); printdot(cv[2]); fprintf(stderr, "\n");
-#endif
- return;
- }
- keepsym = 0;
- if(best[B] != best[C] && best[B]-best[C] == good[C]-good[B]) {
- keepsym = 1;
-#ifdef DEBUG_APPROXCV
- fprintf(stderr, "keeping symmetry!\n");
-#endif
- }
- for(i=0; i<2; i++) { /*B,C*/
- if(ncoef[i]==1)
- continue;
- if(keepsym) {
- /* try to keep the symmetry */
- if(best[i] < good[i]) {
- from[i] = coef[i][best[i]];
- to[i] = coef[i][good[i]];
- } else {
- from[i] = coef[i][good[i]];
- to[i] = coef[i][best[i]];
- }
- } else {
- df = (to[i]-from[i]) / ncoef[i];
- from[i] += df*best[i];
- to[i] = from[i] + df;
- }
- if( fabs(df*middf[i][0]) < STEPEPS && fabs(df*middf[i][1]) < STEPEPS) {
- /* this side has converged */
- from[i] = to[i] = (from[i]+to[i]) / 2.;
- ncoef[i] = 1;
- } else
- ncoef[i] = NORMSECT;
- }
-
- }
- /* calculate the coordinates to return */
- for(k=0; k<2; k++) { /*X, Y*/
- cv[1][k] = cv[0][k] + middf[B][k]*from[B];
- cv[2][k] = cv[3][k] + middf[C][k]*from[C];
- }
-#ifdef DEBUG_APPROXCV
- fprintf(stderr, "approximated middle points "); printdot(cv[1]);
- fprintf(stderr, " "); printdot(cv[2]); fprintf(stderr, "\n");
-#endif
-#undef B
-#undef C
-#undef MAXSECT
-#undef NORMSECT
-#undef STEPEPS
-}
-
-/*
- * Find the squared value of the sinus of the angle between the
- * end of ge1 and the beginning of ge2
- * The curve must be normalized.
- */
-
-static double
-fjointsin2(
- GENTRY *ge1,
- GENTRY *ge2
-)
-{
- double d[3][2 /*X,Y*/];
- double scale1, scale2, len1, len2;
- int axis;
-
- if(ge1->rtg < 0) {
- d[1][X] = ge1->fx3 - ge1->prev->fx3;
- d[1][Y] = ge1->fy3 - ge1->prev->fy3;
- } else {
- d[1][X] = ge1->fx3 - ge1->fpoints[X][ge1->rtg];
- d[1][Y] = ge1->fy3 - ge1->fpoints[Y][ge1->rtg];
- }
- d[2][X] = ge2->fpoints[X][ge2->ftg] - ge2->prev->fx3;
- d[2][Y] = ge2->fpoints[Y][ge2->ftg] - ge2->prev->fy3;
-
- len1 = sqrt( d[1][X]*d[1][X] + d[1][Y]*d[1][Y] );
- len2 = sqrt( d[2][X]*d[2][X] + d[2][Y]*d[2][Y] );
- /* scale the 2nd segment to the length of 1
- * and to make sure that the 1st segment is longer scale it to
- * the length of 2 and extend to the same distance backwards
- */
- scale1 = 2./len1;
- scale2 = 1./len2;
-
- for(axis=0; axis <2; axis++) {
- d[0][axis] = -( d[1][axis] *= scale1 );
- d[2][axis] *= scale2;
- }
- return fdotsegdist2(d, d[2]);
-}
-
-#if 0
-/* find the area covered by the curve
- * (limited by the projections to the X axis)
- */
-
-static double
-fcvarea(
- GENTRY *ge
-)
-{
- double Ly, My, Ny, Py, Qx, Rx, Sx;
- double area;
-
- /* y = Ly*t^3 + My*t^2 + Ny*t + Py */
- Ly = -ge->prev->fy3 + 3*(ge->fy1 - ge->fy2) + ge->fy3;
- My = 3*ge->prev->fy3 - 6*ge->fy1 + 3*ge->fy2;
- Ny = 3*(-ge->prev->fy3 + ge->fy1);
- Py = ge->prev->fy3;
-
- /* dx/dt = Qx*t^2 + Rx*t + Sx */
- Qx = 3*(-ge->prev->fx3 + 3*(ge->fx1 - ge->fx2) + ge->fx3);
- Rx = 6*(ge->prev->fx3 - 2*ge->fx1 + ge->fx2);
- Sx = 3*(-ge->prev->fx3 + ge->fx1);
-
- /* area is integral[from 0 to 1]( y(t) * dx(t)/dt *dt) */
- area = 1./6.*(Ly*Qx) + 1./5.*(Ly*Rx + My*Qx)
- + 1./4.*(Ly*Sx + My*Rx + Ny*Qx) + 1./3.*(My*Sx + Ny*Rx + Py*Qx)
- + 1./2.*(Ny*Sx + Py*Rx) + Py*Sx;
-
- return area;
-}
-#endif
-
-/* find the value of point on the curve at the given parameter t,
- * along the given axis (0 - X, 1 - Y).
- */
-
-static double
-fcvval(
- GENTRY *ge,
- int axis,
- double t
-)
-{
- double t2, mt, mt2;
-
- /* val = A*(1-t)^3 + 3*B*(1-t)^2*t + 3*C*(1-t)*t^2 + D*t^3 */
- t2 = t*t;
- mt = 1-t;
- mt2 = mt*mt;
-
- return ge->prev->fpoints[axis][2]*mt2*mt
- + 3*(ge->fpoints[axis][0]*mt2*t + ge->fpoints[axis][1]*mt*t2)
- + ge->fpoints[axis][2]*t*t2;
-}
-
-/*
- * Find ndots equally spaced dots on a curve or line and fill
- * their coordinates into the dots array
- */
-
-static void
-fsampledots(
- GENTRY *ge,
- double dots[][2], /* the dots to fill */
- int ndots
-)
-{
- int i, axis;
- double t, nf, dx, d[2];
-
- nf = ndots+1;
- if(ge->type == GE_CURVE) {
- for(i=0; i<ndots; i++) {
- t = (i+1)/nf;
- for(axis=0; axis<2; axis++)
- dots[i][axis] = fcvval(ge, axis, t);
- }
- } else { /* line */
- d[0] = ge->fx3 - ge->prev->fx3;
- d[1] = ge->fy3 - ge->prev->fy3;
- for(i=0; i<ndots; i++) {
- t = (i+1)/nf;
- for(axis=0; axis<2; axis++)
- dots[i][axis] = ge->prev->fpoints[axis][2]
- + t*d[axis];
- }
- }
-}
-
-/*
- * Allocate a structure gex_con
- */
-
-static void
-alloc_gex_con(
- GENTRY *ge
-)
-{
- ge->ext = (void*)calloc(1, sizeof(GEX_CON));
- if(ge->ext == 0) {
- fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__);
- exit(255);
- }
-}
-
-/*
- * Normalize a gentry for fforceconcise() : find the points that
- * can be used to calculate the tangents.
- */
-
-static void
-fnormalizege(
- GENTRY *ge
-)
-{
- int midsame, frontsame, rearsame;
-
- if(ge->type == GE_LINE) {
- ge->ftg = 2;
- ge->rtg = -1;
- } else { /* assume it's a curve */
- midsame = (fabs(ge->fx1-ge->fx2)<FEPS && fabs(ge->fy1-ge->fy2)<FEPS);
- frontsame = (fabs(ge->fx1-ge->prev->fx3)<FEPS && fabs(ge->fy1-ge->prev->fy3)<FEPS);
- rearsame = (fabs(ge->fx3-ge->fx2)<FEPS && fabs(ge->fy3-ge->fy2)<FEPS);
-
- if(midsame && (frontsame || rearsame) ) {
- /* essentially a line */
- ge->ftg = 2;
- ge->rtg = -1;
- } else {
- if(frontsame) {
- ge->ftg = 1;
- } else {
- ge->ftg = 0;
- }
- if(rearsame) {
- ge->rtg = 0;
- } else {
- ge->rtg = 1;
- }
- }
- }
-}
-
-/* various definition for the processing of outlines */
-
-/* maximal average quadratic distance from the original curve
- * (in dots) to consider the joined curve good
- */
-#define CVEPS 1.5
-#define CVEPS2 (CVEPS*CVEPS)
-/* squared sinus of the maximal angle that we consider a smooth joint */
-#define SMOOTHSIN2 0.25 /* 0.25==sin(30 degrees)^2 */
-/* squared line length that we consider small */
-#define SMALL_LINE2 (15.*15.)
-/* how many times a curve must be bigger than a line to join, squared */
-#define TIMES_LINE2 (3.*3.)
-
-/*
- * Normalize and analyse a gentry for fforceconcise() and fill out the gex_con
- * structure
- */
-
-static void
-fanalyzege(
- GENTRY *ge
-)
-{
- int i, ix, iy;
- double avsd2, dots[3][2 /*X,Y*/];
- GEX_CON *gex;
-
- gex = X_CON(ge);
- memset(gex, 0, sizeof *gex);
-
- gex->len2 = 0;
- for(i=0; i<2; i++) {
- avsd2 = gex->d[i] = ge->fpoints[i][2] - ge->prev->fpoints[i][2];
- gex->len2 += avsd2*avsd2;
- }
- gex->sin2 = fjointsin2(ge, ge->frwd);
- if(ge->type == GE_CURVE) {
- ge->dir = fgetcvdir(ge);
- for(i=0; i<2; i++) {
- dots[0][i] = ge->prev->fpoints[i][2];
- dots[1][i] = ge->fpoints[i][2];
- dots[2][i] = fcvval(ge, i, 0.5);
- }
- avsd2 = fdotsegdist2(dots, dots[2]);
- if(avsd2 <= CVEPS2) {
- gex->flags |= GEXF_FLAT;
- }
- } else {
- ge->dir = CVDIR_FEQUAL|CVDIR_REQUAL;
- gex->flags |= GEXF_FLAT;
- }
- if(gex->flags & GEXF_FLAT) {
- if( fabs(gex->d[X]) > FEPS && fabs(gex->d[Y]) < 5.
- && fabs(gex->d[Y] / gex->d[X]) < 0.2)
- gex->flags |= GEXF_HOR;
- else if( fabs(gex->d[Y]) > FEPS && fabs(gex->d[X]) < 5.
- && fabs(gex->d[X] / gex->d[Y]) < 0.2)
- gex->flags |= GEXF_VERT;
- }
- ix = gex->isd[X] = fsign(gex->d[X]);
- iy = gex->isd[Y] = fsign(gex->d[Y]);
- if(ix <= 0) {
- if(iy <= 0)
- gex->flags |= GEXF_QDL;
- if(iy >= 0)
- gex->flags |= GEXF_QUL;
- if(gex->flags & GEXF_HOR)
- gex->flags |= GEXF_IDQ_L;
- }
- if(ix >= 0) {
- if(iy <= 0)
- gex->flags |= GEXF_QDR;
- if(iy >= 0)
- gex->flags |= GEXF_QUR;
- if(gex->flags & GEXF_HOR)
- gex->flags |= GEXF_IDQ_R;
- }
- if(gex->flags & GEXF_VERT) {
- if(iy <= 0) {
- gex->flags |= GEXF_IDQ_U;
- } else { /* supposedly there is no 0-sized entry */
- gex->flags |= GEXF_IDQ_D;
- }
- }
-}
-
-/*
- * Analyse a joint between this and following gentry for fforceconcise()
- * and fill out the corresponding parts of the gex_con structure
- * Bothe entries must be analyzed first.
- */
-
-static void
-fanalyzejoint(
- GENTRY *ge
-)
-{
- GENTRY *nge = ge->frwd;
- GENTRY tge;
- GEX_CON *gex, *ngex;
- double avsd2, dots[3][2 /*X,Y*/];
- int i;
-
- gex = X_CON(ge); ngex = X_CON(nge);
-
- /* look if they can be joined honestly */
-
- /* if any is flat, they should join smoothly */
- if( (gex->flags & GEXF_FLAT || ngex->flags & GEXF_FLAT)
- && gex->sin2 > SMOOTHSIN2)
- goto try_flatboth;
-
- if(ge->type == GE_LINE) {
- if(nge->type == GE_LINE) {
- if(gex->len2 > SMALL_LINE2 || ngex->len2 > SMALL_LINE2)
- goto try_flatboth;
- } else {
- if(gex->len2*TIMES_LINE2 > ngex->len2)
- goto try_flatboth;
- }
- } else if(nge->type == GE_LINE) {
- if(ngex->len2*TIMES_LINE2 > gex->len2)
- goto try_flatboth;
- }
-
- /* if curve changes direction */
- if( gex->isd[X]*ngex->isd[X]<0 || gex->isd[Y]*ngex->isd[Y]<0)
- goto try_idealone;
-
- /* if would create a zigzag */
- if( ((ge->dir&CVDIR_FRONT)-CVDIR_FEQUAL) * ((nge->dir&CVDIR_REAR)-CVDIR_REQUAL) < 0 )
- goto try_flatone;
-
- if( fcrossraysge(ge, nge, NULL, NULL, NULL) )
- gex->flags |= GEXF_JGOOD;
-
-try_flatone:
- /* look if they can be joined by flatting out one of the entries */
-
- /* at this point we know that the general direction of the
- * gentries is OK
- */
-
- if( gex->flags & GEXF_FLAT ) {
- tge = *ge;
- tge.fx1 = tge.fx3;
- tge.fy1 = tge.fy3;
- fnormalizege(&tge);
- if( fcrossraysge(&tge, nge, NULL, NULL, NULL) )
- gex->flags |= GEXF_JFLAT|GEXF_JFLAT1;
- }
- if( ngex->flags & GEXF_FLAT ) {
- tge = *nge;
- tge.fx2 = ge->fx3;
- tge.fy2 = ge->fy3;
- fnormalizege(&tge);
- if( fcrossraysge(ge, &tge, NULL, NULL, NULL) )
- gex->flags |= GEXF_JFLAT|GEXF_JFLAT2;
- }
-
-try_idealone:
- /* look if one of the entries can be brought to an idealized
- * horizontal or vertical position and then joined
- */
- if( gex->flags & GEXF_HOR && gex->isd[X]*ngex->isd[X]>=0 ) {
- tge = *ge;
- tge.fx1 = tge.fx3;
- tge.fy1 = ge->prev->fy3; /* force horizontal */
- fnormalizege(&tge);
- if( fcrossraysge(&tge, nge, NULL, NULL, NULL) )
- gex->flags |= GEXF_JID|GEXF_JID1;
- } else if( gex->flags & GEXF_VERT && gex->isd[Y]*ngex->isd[Y]>=0 ) {
- tge = *ge;
- tge.fx1 = ge->prev->fx3; /* force vertical */
- tge.fy1 = tge.fy3;
- fnormalizege(&tge);
- if( fcrossraysge(&tge, nge, NULL, NULL, NULL) )
- gex->flags |= GEXF_JID|GEXF_JID1;
- }
- if( ngex->flags & GEXF_HOR && gex->isd[X]*ngex->isd[X]>=0 ) {
- tge = *nge;
- tge.fx2 = ge->fx3;
- tge.fy2 = nge->fy3; /* force horizontal */
- fnormalizege(&tge);
- if( fcrossraysge(ge, &tge, NULL, NULL, NULL) )
- gex->flags |= GEXF_JID|GEXF_JID2;
- } else if( ngex->flags & GEXF_VERT && gex->isd[Y]*ngex->isd[Y]>=0 ) {
- tge = *nge;
- tge.fx2 = nge->fx3; /* force vertical */
- tge.fy2 = ge->fy3;
- fnormalizege(&tge);
- if( fcrossraysge(ge, &tge, NULL, NULL, NULL) )
- gex->flags |= GEXF_JID|GEXF_JID2;
- }
-
-try_flatboth:
- /* look if we can change them to one line */
- if(gex->flags & GEXF_FLAT && ngex->flags & GEXF_FLAT) {
- for(i=0; i<2; i++) {
- dots[0][i] = ge->prev->fpoints[i][2];
- dots[1][i] = nge->fpoints[i][2];
- dots[2][i] = ge->fpoints[i][2];
- }
- if( fdotsegdist2(dots, dots[2]) <= CVEPS2)
- gex->flags |= GEXF_JLINE;
- }
-}
-
-/*
- * Force conciseness of one contour in the glyph,
- * the contour is indicated by one entry from it.
- */
-
-static void
-fconcisecontour(
- GLYPH *g,
- GENTRY *startge
-)
-{
-/* initial maximal number of dots to be used as reference */
-#define MAXDOTS ((NREFDOTS+1)*12)
-
- GENTRY *ge, *pge, *nge, *ige;
- GEX_CON *gex, *pgex, *ngex, *nngex;
- GENTRY tpge, tnge;
- int quad, qq, i, j, ndots, maxdots;
- int found[2];
- int joinmask, pflag, nflag;
- struct dot_dist *dots;
- double avsd2, maxd2, eps2;
- double apcv[4][2];
-
- if(startge == 0) {
- fprintf(stderr, "WARNING: assertion in %s line %d, please report it to the ttf2pt1 project\n",
- __FILE__, __LINE__);
- fprintf(stderr, "Strange contour in glyph %s\n", g->name);
- dumppaths(g, NULL, NULL);
- return;
- }
-
- if(startge->type != GE_CURVE && startge->type != GE_LINE)
- return; /* probably a degenerate contour */
-
- if(ISDBG(FCONCISE))
- fprintf(stderr, "processing contour 0x%p of glyph %s\n", startge, g->name);
-
- maxdots = MAXDOTS;
- dots = (struct dot_dist *)malloc(sizeof(*dots)*maxdots);
- if(dots == NULL) {
- fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__);
- exit(255);
- }
-
- ge = startge;
- joinmask = GEXF_JGOOD;
- while(1) {
- restart:
- gex = X_CON(ge);
- if((gex->flags & GEXF_JMASK) > ((joinmask<<1)-1)) {
- if(ISDBG(FCONCISE))
- fprintf(stderr, "found higher flag (%x>%x) at 0x%p\n",
- gex->flags & GEXF_JMASK, ((joinmask<<1)-1), ge);
- joinmask <<= 1;
- startge = ge; /* have to redo the pass */
- continue;
- }
- if(( gex->flags & joinmask )==0)
- goto next;
-
- /* if we happen to be in the middle of a string of
- * joinable entries, find its beginning
- */
- if( gex->flags & (GEXF_JCVMASK^GEXF_JID) )
- quad = gex->flags & X_CON_F(ge->frwd) & GEXF_QMASK;
- else if( gex->flags & GEXF_JID2 )
- quad = gex->flags & GEXF_QFROM_IDEAL(X_CON_F(ge->frwd)) & GEXF_QMASK;
- else /* must be GEXF_JID1 */
- quad = GEXF_QFROM_IDEAL(gex->flags) & X_CON_F(ge->frwd) & GEXF_QMASK;
-
- pge = ge;
- pgex = X_CON(pge->bkwd);
-
- if(ISDBG(FCONCISE))
- fprintf(stderr, "ge %p prev -> 0x%p ", ge, pge);
-
- while(pgex->flags & GEXF_JCVMASK) {
- if( !(pgex->flags & ((GEXF_JCVMASK^GEXF_JID)|GEXF_JID2)) )
- qq = GEXF_QFROM_IDEAL(pgex->flags);
- else
- qq = pgex->flags & GEXF_QMASK;
-
- if(ISDBG(FCONCISE))
- fprintf(stderr, "(%x?%x)", quad, qq);
-
- if( !(quad & qq) ) {
- if( !(X_CON_F(pge) & (GEXF_JCVMASK^GEXF_JID))
- && pgex->flags & (GEXF_JCVMASK^GEXF_JID) ) {
- /* the previos entry is definitely a better match */
- if(pge == ge) {
- if(ISDBG(FCONCISE))
- fprintf(stderr, "\nprev is a better match at %p\n", pge);
- startge = ge;
- goto next;
- } else
- pge = pge->frwd;
- }
- break;
- }
-
- quad &= qq;
- pge = pge->bkwd;
- pgex = X_CON(pge->bkwd);
- if(ISDBG(FCONCISE))
- fprintf(stderr, "0x%p ", pge);
- }
-
- /* collect as many entries for joining as possible */
- nge = ge->frwd;
- ngex = X_CON(nge);
- nngex = X_CON(nge->frwd);
-
- if(ISDBG(FCONCISE))
- fprintf(stderr, ": 0x%x\nnext -> 0x%p ", pge, nge);
-
- while(ngex->flags & GEXF_JCVMASK) {
- if( !(ngex->flags & ((GEXF_JCVMASK^GEXF_JID)|GEXF_JID1)) )
- qq = GEXF_QFROM_IDEAL(nngex->flags);
- else
- qq = nngex->flags & GEXF_QMASK;
-
- if(ISDBG(FCONCISE))
- fprintf(stderr, "(%x?%x)", quad, qq);
- if( !(quad & qq) ) {
- if( !(X_CON_F(nge->bkwd) & (GEXF_JCVMASK^GEXF_JID))
- && ngex->flags & (GEXF_JCVMASK^GEXF_JID) ) {
- /* the next-next entry is definitely a better match */
- if(nge == ge->frwd) {
- if(ISDBG(FCONCISE))
- fprintf(stderr, "\nnext %x is a better match than %x at %p (jmask %x)\n",
- ngex->flags & GEXF_JCVMASK, gex->flags & GEXF_JCVMASK, nge, joinmask);
- goto next;
- } else
- nge = nge->bkwd;
- }
- break;
- }
-
- quad &= qq;
- nge = nge->frwd;
- ngex = nngex;
- nngex = X_CON(nge->frwd);
- if(ISDBG(FCONCISE))
- fprintf(stderr, "0x%p ", nge);
- }
-
- if(ISDBG(FCONCISE))
- fprintf(stderr, ": 0x%x\n", nge);
-
- /* XXX add splitting of last entries if neccessary */
-
- /* make sure that all the reference dots are valid */
- for(ige = pge; ige != nge->frwd; ige = ige->frwd) {
- nngex = X_CON(ige);
- if( !(nngex->flags & GEXF_VDOTS) ) {
- fsampledots(ige, nngex->dots, NREFDOTS);
- nngex->flags |= GEXF_VDOTS;
- }
- }
-
- /* do the actual joining */
- while(1) {
- pgex = X_CON(pge);
- ngex = X_CON(nge->bkwd);
- /* now the segments to be joined are pge...nge */
-
- ndots = 0;
- for(ige = pge; ige != nge->frwd; ige = ige->frwd) {
- if(maxdots < ndots+(NREFDOTS+1)) {
- maxdots += MAXDOTS;
- dots = (struct dot_dist *)realloc((void *)dots, sizeof(*dots)*maxdots);
- if(dots == NULL) {
- fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__);
- exit(255);
- }
- }
- nngex = X_CON(ige);
- for(i=0; i<NREFDOTS; i++) {
- for(j=0; j<2; j++)
- dots[ndots].p[j] = nngex->dots[i][j];
- ndots++;
- }
- for(j=0; j<2; j++)
- dots[ndots].p[j] = ige->fpoints[j][2];
- ndots++;
- }
- ndots--; /* the last point is not interesting */
-
- tpge = *pge;
- pflag = pgex->flags;
- if(pflag & (GEXF_JGOOD|GEXF_JFLAT2|GEXF_JID2)) {
- /* nothing */
- } else if(pflag & GEXF_JFLAT) {
- tpge.fx1 = tpge.fx3;
- tpge.fy1 = tpge.fy3;
- } else if(pflag & GEXF_JID) {
- if(pflag & GEXF_HOR)
- tpge.fy1 = tpge.bkwd->fy3;
- else
- tpge.fx1 = tpge.bkwd->fx3;
- }
-
- tnge = *nge;
- nflag = ngex->flags;
- if(nflag & (GEXF_JGOOD|GEXF_JFLAT1|GEXF_JID)
- && !(nflag & GEXF_JID2)) {
- /* nothing */
- } else if(nflag & GEXF_JFLAT) {
- tnge.fx2 = tnge.bkwd->fx3;
- tnge.fy2 = tnge.bkwd->fy3;
- } else if(nflag & GEXF_JID) {
- if(X_CON_F(nge) & GEXF_HOR)
- tnge.fy2 = tnge.fy3;
- else
- tnge.fx2 = tnge.fx3;
- }
-
- fnormalizege(&tpge);
- fnormalizege(&tnge);
- if( fcrossraysge(&tpge, &tnge, NULL, NULL, &apcv[1]) ) {
- apcv[0][X] = tpge.bkwd->fx3;
- apcv[0][Y] = tpge.bkwd->fy3;
- /* apcv[1] and apcv[2] were filled by fcrossraysge() */
- apcv[3][X] = tnge.fx3;
- apcv[3][Y] = tnge.fy3;
-
- /* calculate the precision depending on the smaller dimension of the curve */
- maxd2 = apcv[3][X]-apcv[0][X];
- maxd2 *= maxd2;
- eps2 = apcv[3][Y]-apcv[0][Y];
- eps2 *= eps2;
- if(maxd2 < eps2)
- eps2 = maxd2;
- eps2 *= (CVEPS2*4.) / (400.*400.);
- if(eps2 < CVEPS2)
- eps2 = CVEPS2;
- else if(eps2 > CVEPS2*4.)
- eps2 = CVEPS2*4.;
-
- fapproxcurve(apcv, dots, ndots);
-
- avsd2 = fdotcurvdist2(apcv, dots, ndots, &maxd2);
- if(ISDBG(FCONCISE))
- fprintf(stderr, "avsd = %g, maxd = %g, ", sqrt(avsd2), sqrt(maxd2));
- if(avsd2 <= eps2 && maxd2 <= eps2*2.) {
- /* we've guessed a curve that is close enough */
- ggoodcv++; ggoodcvdots += ndots;
-
- if(ISDBG(FCONCISE)) {
- fprintf(stderr, "in %s joined %p-%p to ", g->name, pge, nge);
- for(i=0; i<4; i++) {
- fprintf(stderr, " (%g, %g)", apcv[i][X], apcv[i][Y]);
- }
- fprintf(stderr, " from\n");
- dumppaths(g, pge, nge);
- }
- for(i=0; i<3; i++) {
- pge->fxn[i] = apcv[i+1][X];
- pge->fyn[i] = apcv[i+1][Y];
- }
- pge->type = GE_CURVE;
- ge = pge;
- for(ige = pge->frwd; ; ige = pge->frwd) {
- if(ige == pge) {
- fprintf(stderr, "WARNING: assertion in %s line %d, please report it to the ttf2pt1 project\n",
- __FILE__, __LINE__);
- free(dots);
- return;
- }
- if(startge == ige)
- startge = pge;
- free(ige->ext);
- freethisge(ige);
- if(ige == nge)
- break;
- }
- fnormalizege(ge);
- if(ISDBG(FCONCISE)) {
- fprintf(stderr, "normalized ");
- for(i=0; i<3; i++) {
- fprintf(stderr, " (%g, %g)", ge->fpoints[X][i], ge->fpoints[Y][i]);
- }
- fprintf(stderr, "\n");
- }
- fanalyzege(ge);
- fanalyzejoint(ge);
- fanalyzege(ge->bkwd);
- fanalyzejoint(ge->bkwd);
-
- /* the results of this join will have to be reconsidered */
- startge = ge = ge->frwd;
- goto restart;
- } else {
- gbadcv++; gbadcvdots += ndots;
- }
- }
-
- /* if we're down to 2 entries then the join has failed */
- if(pge->frwd == nge) {
- pgex->flags &= ~joinmask;
- if(ISDBG(FCONCISE))
- fprintf(stderr, "no match\n");
- goto next;
- }
-
- /* reduce the number of entries by dropping one at some end,
- * should never drop the original ge from the range
- */
-
- if(nge->bkwd == ge
- || pge != ge && (pgex->flags & GEXF_JCVMASK) <= (ngex->flags & GEXF_JCVMASK) ) {
- pge = pge->frwd;
- } else {
- nge = nge->bkwd;
- }
- if(ISDBG(FCONCISE))
- fprintf(stderr, "next try: %p to %p\n", pge, nge);
- }
-
-next:
- ge = ge->frwd;
- if(ge == startge) {
- joinmask = (joinmask >> 1) & GEXF_JCVMASK;
- if(joinmask == 0)
- break;
- }
- }
-
- /* join flat segments into lines */
- /* here ge==startge */
- while(1) {
- gex = X_CON(ge);
- if( !(gex->flags & GEXF_JLINE) )
- goto next2;
-
- ndots = 0;
- dots[ndots].p[X] = ge->fx3;
- dots[ndots].p[Y] = ge->fy3;
- ndots++;
-
- pge = ge->bkwd;
- nge = ge->frwd;
-
- if(ISDBG(FCONCISE))
- fprintf(stderr, "joining LINE from %p-%p\n", ge, nge);
-
- while(pge!=nge) {
- pgex = X_CON(pge);
- ngex = X_CON(nge);
- if(ISDBG(FCONCISE))
- fprintf(stderr, "(p=%p/%x n=0x%x/%x) ", pge, pgex->flags & GEXF_JLINE,
- nge, ngex->flags & GEXF_JLINE);
- if( !((pgex->flags | ngex->flags) & GEXF_JLINE) ) {
- if(ISDBG(FCONCISE))
- fprintf(stderr, "(end p=%p n=%p) ", pge, nge);
- break;
- }
-
- if(maxdots < ndots+2) {
- maxdots += MAXDOTS;
- dots = (struct dot_dist *)realloc((void *)dots, sizeof(*dots)*maxdots);
- if(dots == NULL) {
- fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__);
- exit(255);
- }
- }
- if( pgex->flags & GEXF_JLINE ) {
- for(i=0; i<2; i++) {
- apcv[0][i] = pge->bkwd->fpoints[i][2];
- apcv[1][i] = nge->fpoints[i][2];
- dots[ndots].p[i] = pge->fpoints[i][2];
- }
- ndots++;
- for(i=0; i<ndots; i++) {
- avsd2 = fdotsegdist2(apcv, dots[i].p);
- if(avsd2 > CVEPS2)
- break;
- }
- if(i<ndots) { /* failed to join */
- if(ISDBG(FCONCISE))
- fprintf(stderr, "failed to join prev %p ", pge);
- ndots--;
- pgex->flags &= ~GEXF_JLINE;
- } else {
- pge = pge->bkwd;
- if(pge == nge) {
- if(ISDBG(FCONCISE))
- fprintf(stderr, "intersected at prev %p ", pge);
- break; /* oops, tried to self-intersect */
- }
- }
- } else if(ISDBG(FCONCISE))
- fprintf(stderr, "(p=%p) ", pge);
-
- if( ngex->flags & GEXF_JLINE ) {
- for(i=0; i<2; i++) {
- apcv[0][i] = pge->fpoints[i][2]; /* pge points before the 1st segment */
- apcv[1][i] = nge->frwd->fpoints[i][2];
- dots[ndots].p[i] = nge->fpoints[i][2];
- }
- ndots++;
- for(i=0; i<ndots; i++) {
- avsd2 = fdotsegdist2(apcv, dots[i].p);
- if(avsd2 > CVEPS2)
- break;
- }
- if(i<ndots) { /* failed to join */
- if(ISDBG(FCONCISE))
- fprintf(stderr, "failed to join next %p ", nge->frwd);
- ndots--;
- ngex->flags &= ~GEXF_JLINE;
- } else {
- nge = nge->frwd;
- }
- } else if(ISDBG(FCONCISE))
- fprintf(stderr, "(n=%p) ", nge);
- }
-
- pge = pge->frwd; /* now the limits are pge...nge inclusive */
- if(pge == nge) /* a deeply perversive contour */
- break;
-
- if(ISDBG(FCONCISE)) {
- fprintf(stderr, "\nin %s joined LINE %p-%p from\n", g->name, pge, nge);
- dumppaths(g, pge, nge);
- }
- pge->type = GE_LINE;
- for(i=0; i<2; i++) {
- pge->fpoints[i][2] = nge->fpoints[i][2];
- }
- fnormalizege(pge);
- X_CON_F(pge) &= ~GEXF_JLINE;
-
- ge = pge;
- for(ige = pge->frwd; ; ige = pge->frwd) {
- if(ige == pge) {
- fprintf(stderr, "WARNING: assertion in %s line %d, please report it to the ttf2pt1 project\n",
- __FILE__, __LINE__);
- free(dots);
- return;
- }
- if(startge == ige)
- startge = pge;
- free(ige->ext);
- freethisge(ige);
- if(ige == nge)
- break;
- }
-next2:
- ge = ge->frwd;
- if(ge == startge)
- break;
- }
-
- free(dots);
-}
-
-/* force conciseness: substitute 2 or more curves going in the
-** same quadrant with one curve
-** in floating point
-*/
-
-void
-fforceconcise(
- GLYPH * g
-)
-{
-
- GENTRY *ge, *nge, *endge, *xge;
-
- assertisfloat(g, "enforcing conciseness");
-
- fdelsmall(g, 0.05);
- assertpath(g->entries, __FILE__, __LINE__, g->name);
-
- if(ISDBG(FCONCISE))
- dumppaths(g, NULL, NULL);
-
- /* collect more information about each gentry and their joints */
- for (ge = g->entries; ge != 0; ge = ge->next)
- if (ge->type == GE_CURVE || ge->type == GE_LINE)
- fnormalizege(ge);
-
- for (ge = g->entries; ge != 0; ge = ge->next)
- if (ge->type == GE_CURVE || ge->type == GE_LINE) {
- alloc_gex_con(ge);
- fanalyzege(ge);
- }
-
- /* see what we can do about joining */
- for (ge = g->entries; ge != 0; ge = ge->next)
- if (ge->type == GE_CURVE || ge->type == GE_LINE)
- fanalyzejoint(ge);
-
- /* now do the joining */
- for (ge = g->entries; ge != 0; ge = ge->next)
- if(ge->type == GE_MOVE)
- fconcisecontour(g, ge->next);
-
- for (ge = g->entries; ge != 0; ge = ge->next)
- if (ge->type == GE_CURVE || ge->type == GE_LINE)
- free(ge->ext);
-}
-
-void
-print_glyph(
- int glyphno
-)
-{
- GLYPH *g;
- GENTRY *ge;
- int x = 0, y = 0;
- int i;
- int grp, lastgrp= -1;
-
- if(ISDBG(FCONCISE) && glyphno == 0) {
- fprintf(stderr, "Guessed curves: bad %d/%d good %d/%d\n",
- gbadcv, gbadcvdots, ggoodcv, ggoodcvdots);
- }
-
- g = &glyph_list[glyphno];
-
- fprintf(pfa_file, "/%s { \n", g->name);
-
- /* consider widths >MAXLEGALWIDTH as bugs */
- if( g->scaledwidth <= MAXLEGALWIDTH ) {
- fprintf(pfa_file, "0 %d hsbw\n", g->scaledwidth);
- } else {
- fprintf(pfa_file, "0 1000 hsbw\n");
- WARNING_2 fprintf(stderr, "glyph %s: width %d seems to be buggy, set to 1000\n",
- g->name, g->scaledwidth);
- }
-
-#if 0
- fprintf(pfa_file, "%% contours: ");
- for (i = 0; i < g->ncontours; i++)
- fprintf(pfa_file, "%s(%d,%d) ", (g->contours[i].direction == DIR_OUTER ? "out" : "in"),
- g->contours[i].xofmin, g->contours[i].ymin);
- fprintf(pfa_file, "\n");
-
- if (g->rymin < 5000)
- fprintf(pfa_file, "%d lower%s\n", g->rymin, (g->flatymin ? "flat" : "curve"));
- if (g->rymax > -5000)
- fprintf(pfa_file, "%d upper%s\n", g->rymax, (g->flatymax ? "flat" : "curve"));
-#endif
-
- if (g->hstems)
- for (i = 0; i < g->nhs; i += 2) {
- if (g->hstems[i].flags & ST_3) {
- fprintf(pfa_file, "%d %d %d %d %d %d hstem3\n",
- g->hstems[i].value,
- g->hstems[i + 1].value - g->hstems[i].value,
- g->hstems[i + 2].value,
- g->hstems[i + 3].value - g->hstems[i + 2].value,
- g->hstems[i + 4].value,
- g->hstems[i + 5].value - g->hstems[i + 4].value
- );
- i += 4;
- } else {
- fprintf(pfa_file, "%d %d hstem\n", g->hstems[i].value,
- g->hstems[i + 1].value - g->hstems[i].value);
- }
- }
-
- if (g->vstems)
- for (i = 0; i < g->nvs; i += 2) {
- if (g->vstems[i].flags & ST_3) {
- fprintf(pfa_file, "%d %d %d %d %d %d vstem3\n",
- g->vstems[i].value,
- g->vstems[i + 1].value - g->vstems[i].value,
- g->vstems[i + 2].value,
- g->vstems[i + 3].value - g->vstems[i + 2].value,
- g->vstems[i + 4].value,
- g->vstems[i + 5].value - g->vstems[i + 4].value
- );
- i += 4;
- } else {
- fprintf(pfa_file, "%d %d vstem\n", g->vstems[i].value,
- g->vstems[i + 1].value - g->vstems[i].value);
- }
- }
-
- for (ge = g->entries; ge != 0; ge = ge->next) {
- if(g->nsg>0) {
- grp=ge->stemid;
- if(grp >= 0 && grp != lastgrp) {
- fprintf(pfa_file, "%d 4 callsubr\n", grp+g->firstsubr);
- lastgrp=grp;
- }
- }
-
- switch (ge->type) {
- case GE_MOVE:
- if (absolute)
- fprintf(pfa_file, "%d %d amoveto\n", ge->ix3, ge->iy3);
- else
- rmoveto(ge->ix3 - x, ge->iy3 - y);
- if (0)
- fprintf(stderr, "Glyph %s: print moveto(%d, %d)\n",
- g->name, ge->ix3, ge->iy3);
- x = ge->ix3;
- y = ge->iy3;
- break;
- case GE_LINE:
- if (absolute)
- fprintf(pfa_file, "%d %d alineto\n", ge->ix3, ge->iy3);
- else
- rlineto(ge->ix3 - x, ge->iy3 - y);
- x = ge->ix3;
- y = ge->iy3;
- break;
- case GE_CURVE:
- if (absolute)
- fprintf(pfa_file, "%d %d %d %d %d %d arcurveto\n",
- ge->ix1, ge->iy1, ge->ix2, ge->iy2, ge->ix3, ge->iy3);
- else
- rrcurveto(ge->ix1 - x, ge->iy1 - y,
- ge->ix2 - ge->ix1, ge->iy2 - ge->iy1,
- ge->ix3 - ge->ix2, ge->iy3 - ge->iy2);
- x = ge->ix3;
- y = ge->iy3;
- break;
- case GE_PATH:
- closepath();
- break;
- default:
- WARNING_1 fprintf(stderr, "**** Glyph %s: unknown entry type '%c'\n",
- g->name, ge->type);
- break;
- }
- }
-
- fprintf(pfa_file, "endchar } ND\n");
-}
-
-/* print the subroutines for this glyph, returns the number of them */
-int
-print_glyph_subs(
- int glyphno,
- int startid /* start numbering subroutines from this id */
-)
-{
- GLYPH *g;
- int i, grp;
-
- g = &glyph_list[glyphno];
-
- if(!hints || !subhints || g->nsg<1)
- return 0;
-
- g->firstsubr=startid;
-
-#if 0
- fprintf(pfa_file, "%% %s %d\n", g->name, g->nsg);
-#endif
- for(grp=0; grp<g->nsg; grp++) {
- fprintf(pfa_file, "dup %d {\n", startid++);
- for(i= (grp==0)? 0 : g->nsbs[grp-1]; i<g->nsbs[grp]; i++)
- fprintf(pfa_file, "\t%d %d %cstem\n", g->sbstems[i].low,
- g->sbstems[i].high-g->sbstems[i].low,
- g->sbstems[i].isvert ? 'v' : 'h');
- fprintf(pfa_file, "\treturn\n\t} NP\n");
- }
-
- return g->nsg;
-}
-
-void
-print_glyph_metrics(
- int code,
- int glyphno
-)
-{
- GLYPH *g;
-
- g = &glyph_list[glyphno];
-
- if(transform)
- fprintf(afm_file, "C %d ; WX %d ; N %s ; B %d %d %d %d ;\n",
- code, g->scaledwidth, g->name,
- iscale(g->xMin), iscale(g->yMin), iscale(g->xMax), iscale(g->yMax));
- else
- fprintf(afm_file, "C %d ; WX %d ; N %s ; B %d %d %d %d ;\n",
- code, g->scaledwidth, g->name,
- g->xMin, g->yMin, g->xMax, g->yMax);
-}
-
-/*
- SB:
- An important note about the BlueValues.
-
- The Adobe documentation says that the maximal width of a Blue zone
- is connected to the value of BlueScale, which is by default 0.039625.
- The BlueScale value defines, at which point size the overshoot
- suppression be disabled.
-
- The formula for it that is given in the manual is:
-
- BlueScale=point_size/240, for a 300dpi device
-
- that makes us wonder what is this 240 standing for. Incidentally
- 240=72*1000/300, where 72 is the relation between inches and points,
- 1000 is the size of the glyph matrix, and 300dpi is the resolution of
- the output device. Knowing that we can recalculate the formula for
- the font size in pixels rather than points:
-
- BlueScale=pixel_size/1000
-
- That looks a lot simpler than the original formula, does not it ?
- And the limitation about the maximal width of zone also looks
- a lot simpler after the transformation:
-
- max_width < 1000/pixel_size
-
- that ensures that even at the maximal pixel size when the overshoot
- suppression is disabled the zone width will be less than one pixel.
- This is important, failure to comply to this limit will result in
- really ugly fonts (been there, done that). But knowing the formula
- for the pixel width, we see that in fact we can use the maximal width
- of 24, not 23 as specified in the manual.
-
-*/
-
-#define MAXBLUEWIDTH (24)
-
-/*
- * Find the indexes of the most frequent values
- * in the hystogram, sort them in ascending order, and save which one
- * was the best one (if asked).
- * Returns the number of values found (may be less than maximal because
- * we ignore the zero values)
- */
-
-#define MAXHYST (2000) /* size of the hystogram */
-#define HYSTBASE 500
-
-static int
-besthyst(
- int *hyst, /* the hystogram */
- int base, /* the base point of the hystogram */
- int *best, /* the array for indexes of best values */
- int nbest, /* its allocated size */
- int width, /* minimal difference between indexes */
- int *bestindp /* returned top point */
-)
-{
- unsigned char hused[MAXHYST / 8 + 1];
- int i, max, j, w, last = 0;
- int nf = 0;
-
- width--;
-
- memset(hused, 0 , sizeof hused);
-
- max = 1;
- for (i = 0; i < nbest && max != 0; i++) {
- best[i] = 0;
- max = 0;
- for (j = 1; j < MAXHYST - 1; j++) {
- w = hyst[j];
-
- if (w > max && (hused[j>>3] & (1 << (j & 0x07))) == 0) {
- best[i] = j;
- max = w;
- }
- }
- if (max != 0) {
- if (max < last/2) {
- /* do not pick the too low values */
- break;
- }
- for (j = best[i] - width; j <= best[i] + width; j++) {
- if (j >= 0 && j < MAXHYST)
- hused[j >> 3] |= (1 << (j & 0x07));
- }
- last = max;
- best[i] -= base;
- nf = i + 1;
- }
- }
-
- if (bestindp)
- *bestindp = best[0];
-
- /* sort the indexes in ascending order */
- for (i = 0; i < nf; i++) {
- for (j = i + 1; j < nf; j++)
- if (best[j] < best[i]) {
- w = best[i];
- best[i] = best[j];
- best[j] = w;
- }
- }
-
- return nf;
-}
-
-/*
- * Find the next best Blue zone in the hystogram.
- * Return the weight of the found zone.
- */
-
-static int
-bestblue(
- short *zhyst, /* the zones hystogram */
- short *physt, /* the points hystogram */
- short *ozhyst, /* the other zones hystogram */
- int *bluetab /* where to put the found zone */
-)
-{
- int i, j, w, max, ind, first, last;
-
- /* find the highest point in the zones hystogram */
- /* if we have a plateau, take its center */
- /* if we have multiple peaks, take the first one */
-
- max = -1;
- first = last = -10;
- for (i = 0; i <= MAXHYST - MAXBLUEWIDTH; i++) {
- w = zhyst[i];
- if (w > max) {
- first = last = i;
- max = w;
- } else if (w == max) {
- if (last == i - 1)
- last = i;
- }
- }
- ind = (first + last) / 2;
-
- if (max == 0) /* no zones left */
- return 0;
-
- /* now we reuse `first' and `last' as inclusive borders of the zone */
- first = ind;
- last = ind + (MAXBLUEWIDTH - 1);
-
- /* our maximal width is far too big, so we try to make it narrower */
- w = max;
- j = (w & 1); /* a pseudo-random bit */
- while (1) {
- while (physt[first] == 0)
- first++;
- while (physt[last] == 0)
- last--;
- if (last - first < (MAXBLUEWIDTH * 2 / 3) || (max - w) * 10 > max)
- break;
-
- if (physt[first] < physt[last]
- || physt[first] == physt[last] && j) {
- if (physt[first] * 20 > w) /* if weight is >5%,
- * stop */
- break;
- w -= physt[first];
- first++;
- j = 0;
- } else {
- if (physt[last] * 20 > w) /* if weight is >5%,
- * stop */
- break;
- w -= physt[last];
- last--;
- j = 1;
- }
- }
-
- /* save our zone */
- bluetab[0] = first - HYSTBASE;
- bluetab[1] = last - HYSTBASE;
-
- /* invalidate all the zones overlapping with this one */
- /* the constant of 2 is determined by the default value of BlueFuzz */
- for (i = first - (MAXBLUEWIDTH - 1) - 2; i <= last + 2; i++)
- if (i >= 0 && i < MAXHYST) {
- zhyst[i] = 0;
- ozhyst[i] = 0;
- }
- return w;
-}
-
-/*
- * Try to find the Blue Values, bounding box and italic angle
- */
-
-void
-findblues(void)
-{
- /* hystograms for upper and lower zones */
- short hystl[MAXHYST];
- short hystu[MAXHYST];
- short zuhyst[MAXHYST];
- short zlhyst[MAXHYST];
- int nchars;
- int i, j, k, w, max;
- GENTRY *ge;
- GLYPH *g;
- double ang;
-
- /* find the lowest and highest points of glyphs */
- /* and by the way build the values for FontBBox */
- /* and build the hystogram for the ItalicAngle */
-
- /* re-use hystl for the hystogram of italic angle */
-
- bbox[0] = bbox[1] = 5000;
- bbox[2] = bbox[3] = -5000;
-
- for (i = 0; i < MAXHYST; i++)
- hystl[i] = 0;
-
- nchars = 0;
-
- for (i = 0, g = glyph_list; i < numglyphs; i++, g++) {
- if (g->flags & GF_USED) {
- nchars++;
-
- g->rymin = 5000;
- g->rymax = -5000;
- for (ge = g->entries; ge != 0; ge = ge->next) {
- if (ge->type == GE_LINE) {
-
- j = ge->iy3 - ge->prev->iy3;
- k = ge->ix3 - ge->prev->ix3;
- if (j > 0)
- ang = atan2(-k, j) * 180.0 / M_PI;
- else
- ang = atan2(k, -j) * 180.0 / M_PI;
-
- k /= 100;
- j /= 100;
- if (ang > -45.0 && ang < 45.0) {
- /*
- * be careful to not overflow
- * the counter
- */
- hystl[HYSTBASE + (int) (ang * 10.0)] += (k * k + j * j) / 4;
- }
- if (ge->iy3 == ge->prev->iy3) {
- if (ge->iy3 <= g->rymin) {
- g->rymin = ge->iy3;
- g->flatymin = 1;
- }
- if (ge->iy3 >= g->rymax) {
- g->rymax = ge->iy3;
- g->flatymax = 1;
- }
- } else {
- if (ge->iy3 < g->rymin) {
- g->rymin = ge->iy3;
- g->flatymin = 0;
- }
- if (ge->iy3 > g->rymax) {
- g->rymax = ge->iy3;
- g->flatymax = 0;
- }
- }
- } else if (ge->type == GE_CURVE) {
- if (ge->iy3 < g->rymin) {
- g->rymin = ge->iy3;
- g->flatymin = 0;
- }
- if (ge->iy3 > g->rymax) {
- g->rymax = ge->iy3;
- g->flatymax = 0;
- }
- }
- if (ge->type == GE_LINE || ge->type == GE_CURVE) {
- if (ge->ix3 < bbox[0])
- bbox[0] = ge->ix3;
- if (ge->ix3 > bbox[2])
- bbox[2] = ge->ix3;
- if (ge->iy3 < bbox[1])
- bbox[1] = ge->iy3;
- if (ge->iy3 > bbox[3])
- bbox[3] = ge->iy3;
- }
- }
- }
- }
-
- /* get the most popular angle */
- max = 0;
- w = 0;
- for (i = 0; i < MAXHYST; i++) {
- if (hystl[i] > w) {
- w = hystl[i];
- max = i;
- }
- }
- ang = (double) (max - HYSTBASE) / 10.0;
- WARNING_2 fprintf(stderr, "Guessed italic angle: %f\n", ang);
- if (italic_angle == 0.0)
- italic_angle = ang;
-
- /* build the hystogram of the lower points */
- for (i = 0; i < MAXHYST; i++)
- hystl[i] = 0;
-
- for (i = 0, g = glyph_list; i < numglyphs; i++, g++) {
- if ((g->flags & GF_USED)
- && g->rymin + HYSTBASE >= 0 && g->rymin < MAXHYST - HYSTBASE) {
- hystl[g->rymin + HYSTBASE]++;
- }
- }
-
- /* build the hystogram of the upper points */
- for (i = 0; i < MAXHYST; i++)
- hystu[i] = 0;
-
- for (i = 0, g = glyph_list; i < numglyphs; i++, g++) {
- if ((g->flags & GF_USED)
- && g->rymax + HYSTBASE >= 0 && g->rymax < MAXHYST - HYSTBASE) {
- hystu[g->rymax + HYSTBASE]++;
- }
- }
-
- /* build the hystogram of all the possible lower zones with max width */
- for (i = 0; i < MAXHYST; i++)
- zlhyst[i] = 0;
-
- for (i = 0; i <= MAXHYST - MAXBLUEWIDTH; i++) {
- for (j = 0; j < MAXBLUEWIDTH; j++)
- zlhyst[i] += hystl[i + j];
- }
-
- /* build the hystogram of all the possible upper zones with max width */
- for (i = 0; i < MAXHYST; i++)
- zuhyst[i] = 0;
-
- for (i = 0; i <= MAXHYST - MAXBLUEWIDTH; i++) {
- for (j = 0; j < MAXBLUEWIDTH; j++)
- zuhyst[i] += hystu[i + j];
- }
-
- /* find the baseline */
- w = bestblue(zlhyst, hystl, zuhyst, &bluevalues[0]);
- if (0)
- fprintf(stderr, "BaselineBlue zone %d%% %d...%d\n", w * 100 / nchars,
- bluevalues[0], bluevalues[1]);
-
- if (w == 0) /* no baseline, something weird */
- return;
-
- /* find the upper zones */
- for (nblues = 2; nblues < 14; nblues += 2) {
- w = bestblue(zuhyst, hystu, zlhyst, &bluevalues[nblues]);
-
- if (0)
- fprintf(stderr, "Blue zone %d%% %d...%d\n", w * 100 / nchars,
- bluevalues[nblues], bluevalues[nblues+1]);
-
- if (w * 20 < nchars)
- break; /* don't save this zone */
- }
-
- /* find the lower zones */
- for (notherb = 0; notherb < 10; notherb += 2) {
- w = bestblue(zlhyst, hystl, zuhyst, &otherblues[notherb]);
-
- if (0)
- fprintf(stderr, "OtherBlue zone %d%% %d...%d\n", w * 100 / nchars,
- otherblues[notherb], otherblues[notherb+1]);
-
-
- if (w * 20 < nchars)
- break; /* don't save this zone */
- }
-
-}
-
-/*
- * Find the actual width of the glyph and modify the
- * description to reflect it. Not guaranteed to do
- * any good, may make character spacing too wide.
- */
-
-void
-docorrectwidth(void)
-{
- int i;
- GENTRY *ge;
- GLYPH *g;
- int xmin, xmax;
- int maxwidth, minsp;
-
- /* enforce this minimal spacing,
- * we limit the amount of the enforced spacing to avoid
- * spacing the bold wonts too widely
- */
- minsp = (stdhw>60 || stdhw<10)? 60 : stdhw;
-
- for (i = 0, g = glyph_list; i < numglyphs; i++, g++) {
- g->oldwidth=g->scaledwidth; /* save the old width, will need for AFM */
-
- if (correctwidth && g->flags & GF_USED) {
- xmin = 5000;
- xmax = -5000;
- for (ge = g->entries; ge != 0; ge = ge->next) {
- if (ge->type != GE_LINE && ge->type != GE_CURVE)
- continue;
-
- if (ge->ix3 <= xmin) {
- xmin = ge->ix3;
- }
- if (ge->ix3 >= xmax) {
- xmax = ge->ix3;
- }
- }
-
- maxwidth=xmax+minsp;
- if( g->scaledwidth < maxwidth ) {
- g->scaledwidth = maxwidth;
- WARNING_3 fprintf(stderr, "glyph %s: extended from %d to %d\n",
- g->name, g->oldwidth, g->scaledwidth );
- }
- }
- }
-
-}
-
-/*
- * Try to find the typical stem widths
- */
-
-void
-stemstatistics(void)
-{
-#define MINDIST 10 /* minimal distance between the widths */
- int hyst[MAXHYST+MINDIST*2];
- int best[12];
- int i, j, k, w;
- int nchars;
- int ns;
- STEM *s;
- GLYPH *g;
-
- /* start with typical stem width */
-
- nchars=0;
-
- /* build the hystogram of horizontal stem widths */
- memset(hyst, 0, sizeof hyst);
-
- for (i = 0, g = glyph_list; i < numglyphs; i++, g++) {
- if (g->flags & GF_USED) {
- nchars++;
- s = g->hstems;
- for (j = 0; j < g->nhs; j += 2) {
- if ((s[j].flags | s[j + 1].flags) & ST_END)
- continue;
- w = s[j + 1].value - s[j].value+1;
- if(w==20) /* split stems should not be counted */
- continue;
- if (w > 0 && w < MAXHYST - 1) {
- /*
- * handle some fuzz present in
- * converted fonts
- */
- hyst[w+MINDIST] += MINDIST-1;
- for(k=1; k<MINDIST-1; k++) {
- hyst[w+MINDIST + k] += MINDIST-1-k;
- hyst[w+MINDIST - k] += MINDIST-1-k;
- }
- }
- }
- }
- }
-
- /* find 12 most frequent values */
- ns = besthyst(hyst+MINDIST, 0, best, 12, MINDIST, &stdhw);
-
- /* store data in stemsnaph */
- for (i = 0; i < ns; i++)
- stemsnaph[i] = best[i];
- if (ns < 12)
- stemsnaph[ns] = 0;
-
- /* build the hystogram of vertical stem widths */
- memset(hyst, 0, sizeof hyst);
-
- for (i = 0, g = glyph_list; i < numglyphs; i++, g++) {
- if (g->flags & GF_USED) {
- s = g->vstems;
- for (j = 0; j < g->nvs; j += 2) {
- if ((s[j].flags | s[j + 1].flags) & ST_END)
- continue;
- w = s[j + 1].value - s[j].value+1;
- if (w > 0 && w < MAXHYST - 1) {
- /*
- * handle some fuzz present in
- * converted fonts
- */
- hyst[w+MINDIST] += MINDIST-1;
- for(k=1; k<MINDIST-1; k++) {
- hyst[w+MINDIST + k] += MINDIST-1-k;
- hyst[w+MINDIST - k] += MINDIST-1-k;
- }
- }
- }
- }
- }
-
- /* find 12 most frequent values */
- ns = besthyst(hyst+MINDIST, 0, best, 12, MINDIST, &stdvw);
-
- /* store data in stemsnaph */
- for (i = 0; i < ns; i++)
- stemsnapv[i] = best[i];
- if (ns < 12)
- stemsnapv[ns] = 0;
-
-#undef MINDIST
-}
-
-/*
- * SB
- * A funny thing: TTF paths are going in reverse direction compared
- * to Type1. So after all (because the rest of logic uses TTF
- * path directions) we have to reverse the paths.
- *
- * It was a big headache to discover that.
- */
-
-/* works on both int and float paths */
-
-void
-reversepathsfromto(
- GENTRY * from,
- GENTRY * to
-)
-{
- GENTRY *ge, *nge, *pge;
- GENTRY *cur, *next;
- int i, n, ilast[2];
- double flast[2], f;
-
- for (ge = from; ge != 0 && ge != to; ge = ge->next) {
- if(ge->type == GE_LINE || ge->type == GE_CURVE) {
- if (ISDBG(REVERSAL))
- fprintf(stderr, "reverse path 0x%x <- 0x%x, 0x%x\n", ge, ge->prev, ge->bkwd);
-
- /* cut out the path itself */
- pge = ge->prev; /* GE_MOVE */
- if (pge == 0) {
- fprintf(stderr, "**! No MOVE before line !!! Fatal. ****\n");
- exit(1);
- }
- nge = ge->bkwd->next; /* GE_PATH */
- pge->next = nge;
- nge->prev = pge;
- ge->bkwd->next = 0; /* mark end of chain */
-
- /* remember the starting point */
- if(ge->flags & GEF_FLOAT) {
- flast[0] = pge->fx3;
- flast[1] = pge->fy3;
- } else {
- ilast[0] = pge->ix3;
- ilast[1] = pge->iy3;
- }
-
- /* then reinsert them in backwards order */
- for(cur = ge; cur != 0; cur = next ) {
- next = cur->next; /* or addgeafter() will screw it up */
- if(cur->flags & GEF_FLOAT) {
- for(i=0; i<2; i++) {
- /* reverse the direction of path element */
- f = cur->fpoints[i][0];
- cur->fpoints[i][0] = cur->fpoints[i][1];
- cur->fpoints[i][1] = f;
- f = flast[i];
- flast[i] = cur->fpoints[i][2];
- cur->fpoints[i][2] = f;
- }
- } else {
- for(i=0; i<2; i++) {
- /* reverse the direction of path element */
- n = cur->ipoints[i][0];
- cur->ipoints[i][0] = cur->ipoints[i][1];
- cur->ipoints[i][1] = n;
- n = ilast[i];
- ilast[i] = cur->ipoints[i][2];
- cur->ipoints[i][2] = n;
- }
- }
- addgeafter(pge, cur);
- }
-
- /* restore the starting point */
- if(ge->flags & GEF_FLOAT) {
- pge->fx3 = flast[0];
- pge->fy3 = flast[1];
- } else {
- pge->ix3 = ilast[0];
- pge->iy3 = ilast[1];
- }
-
- ge = nge;
- }
-
- }
-}
-
-void
-reversepaths(
- GLYPH * g
-)
-{
- reversepathsfromto(g->entries, NULL);
-}
-
-/* add a kerning pair information, scales the value */
-
-void
-addkernpair(
- unsigned id1,
- unsigned id2,
- int unscval
-)
-{
- static unsigned char *bits = 0;
- static int lastid;
- GLYPH *g = &glyph_list[id1];
- int i, n;
- struct kern *p;
-
- if(unscval == 0 || id1 >= numglyphs || id2 >= numglyphs)
- return;
-
- if( (glyph_list[id1].flags & GF_USED)==0
- || (glyph_list[id2].flags & GF_USED)==0 )
- return;
-
- if(bits == 0) {
- bits = calloc( BITMAP_BYTES(numglyphs), 1);
- if (bits == NULL) {
- fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__);
- exit(255);
- }
- lastid = id1;
- }
-
- if(lastid != id1) {
- /* refill the bitmap cache */
- memset(bits, 0,BITMAP_BYTES(numglyphs));
- p = g->kern;
- for(i=g->kerncount; i>0; i--) {
- n = (p++)->id;
- SET_BITMAP(bits, n);
- }
- lastid = id1;
- }
-
- if(IS_BITMAP(bits, id2))
- return; /* duplicate */
-
- if(g->kerncount <= g->kernalloc) {
- g->kernalloc += 8;
- p = realloc(g->kern, sizeof(struct kern) * g->kernalloc);
- if(p == 0) {
- fprintf (stderr, "** realloc failed, kerning data will be incomplete\n");
- }
- g->kern = p;
- }
-
- SET_BITMAP(bits, id2);
- p = &g->kern[g->kerncount];
- p->id = id2;
- p->val = iscale(unscval) - (g->scaledwidth - g->oldwidth);
- g->kerncount++;
- kerning_pairs++;
-}
-
-/* print out the kerning information */
-
-void
-print_kerning(
- FILE *afm_file
-)
-{
- int i, j, n;
- GLYPH *g;
- struct kern *p;
-
- if( kerning_pairs == 0 )
- return;
-
- fprintf(afm_file, "StartKernData\n");
- fprintf(afm_file, "StartKernPairs %hd\n", kerning_pairs);
-
- for(i=0; i<numglyphs; i++) {
- g = &glyph_list[i];
- if( (g->flags & GF_USED) ==0)
- continue;
- p = g->kern;
- for(j=g->kerncount; j>0; j--, p++) {
- fprintf(afm_file, "KPX %s %s %d\n", g->name,
- glyph_list[ p->id ].name, p->val );
- }
- }
-
- fprintf(afm_file, "EndKernPairs\n");
- fprintf(afm_file, "EndKernData\n");
-}
-
-
-#if 0
-
-/*
-** This function is commented out because the information
-** collected by it is not used anywhere else yet. Now
-** it only collects the directions of contours. And the
-** direction of contours gets fixed already in draw_glyf().
-**
-***********************************************
-**
-** Here we expect that the paths are already closed.
-** We also expect that the contours do not intersect
-** and that curves doesn't cross any border of quadrant.
-**
-** Find which contours go inside which and what is
-** their proper direction. Then fix the direction
-** to make it right.
-**
-*/
-
-#define MAXCONT 1000
-
-void
-fixcontours(
- GLYPH * g
-)
-{
- CONTOUR cont[MAXCONT];
- short ymax[MAXCONT]; /* the highest point */
- short xofmax[MAXCONT]; /* X-coordinate of any point
- * at ymax */
- short ymin[MAXCONT]; /* the lowest point */
- short xofmin[MAXCONT]; /* X-coordinate of any point
- * at ymin */
- short count[MAXCONT]; /* count of lines */
- char dir[MAXCONT]; /* in which direction they must go */
- GENTRY *start[MAXCONT], *minptr[MAXCONT], *maxptr[MAXCONT];
- int ncont;
- int i;
- int dx1, dy1, dx2, dy2;
- GENTRY *ge, *nge;
-
- /* find the contours and their most upper/lower points */
- ncont = 0;
- ymax[0] = -5000;
- ymin[0] = 5000;
- for (ge = g->entries; ge != 0; ge = ge->next) {
- if (ge->type == GE_LINE || ge->type == GE_CURVE) {
- if (ge->iy3 > ymax[ncont]) {
- ymax[ncont] = ge->iy3;
- xofmax[ncont] = ge->ix3;
- maxptr[ncont] = ge;
- }
- if (ge->iy3 < ymin[ncont]) {
- ymin[ncont] = ge->iy3;
- xofmin[ncont] = ge->ix3;
- minptr[ncont] = ge;
- }
- }
- if (ge->frwd != ge->next) {
- start[ncont++] = ge->frwd;
- ymax[ncont] = -5000;
- ymin[ncont] = 5000;
- }
- }
-
- /* determine the directions of contours */
- for (i = 0; i < ncont; i++) {
- ge = minptr[i];
- nge = ge->frwd;
-
- if (ge->type == GE_CURVE) {
- dx1 = ge->ix3 - ge->ix2;
- dy1 = ge->iy3 - ge->iy2;
-
- if (dx1 == 0 && dy1 == 0) { /* a pathological case */
- dx1 = ge->ix3 - ge->ix1;
- dy1 = ge->iy3 - ge->iy1;
- }
- if (dx1 == 0 && dy1 == 0) { /* a more pathological
- * case */
- dx1 = ge->ix3 - ge->prev->ix3;
- dy1 = ge->iy3 - ge->prev->iy3;
- }
- } else {
- dx1 = ge->ix3 - ge->prev->ix3;
- dy1 = ge->iy3 - ge->prev->iy3;
- }
- if (nge->type == GE_CURVE) {
- dx2 = ge->ix3 - nge->ix1;
- dy2 = ge->iy3 - nge->iy1;
- if (dx1 == 0 && dy1 == 0) { /* a pathological case */
- dx2 = ge->ix3 - nge->ix2;
- dy2 = ge->iy3 - nge->iy2;
- }
- if (dx1 == 0 && dy1 == 0) { /* a more pathological
- * case */
- dx2 = ge->ix3 - nge->ix3;
- dy2 = ge->iy3 - nge->iy3;
- }
- } else {
- dx2 = ge->ix3 - nge->ix3;
- dy2 = ge->iy3 - nge->iy3;
- }
-
- /* compare angles */
- cont[i].direction = DIR_INNER;
- if (dy1 == 0) {
- if (dx1 < 0)
- cont[i].direction = DIR_OUTER;
- } else if (dy2 == 0) {
- if (dx2 > 0)
- cont[i].direction = DIR_OUTER;
- } else if (dx2 * dy1 < dx1 * dy2)
- cont[i].direction = DIR_OUTER;
-
- cont[i].ymin = ymin[i];
- cont[i].xofmin = xofmin[i];
- }
-
- /* save the information that may be needed further */
- g->ncontours = ncont;
- if (ncont > 0) {
- g->contours = malloc(sizeof(CONTOUR) * ncont);
- if (g->contours == 0) {
- fprintf(stderr, "***** Memory allocation error *****\n");
- exit(255);
- }
- memcpy(g->contours, cont, sizeof(CONTOUR) * ncont);
- }
-}
-
-#endif
-
-/*
- *
- */
-
+++ /dev/null
-/*
- * see COPYRIGHT
- */
-
-
-/* glyph entry, one drawing command */
-typedef struct gentry {
- /* this list links all GENTRYs of a GLYPH sequentially */
- struct gentry *next; /* double linked list */
- struct gentry *prev;
-
- /* this list links all GENTRYs of one contour -
- * of types GE_LINE and GE_CURVE only
- * bkwd is also reused: in the very first entry (normally
- * of type GE_MOVE) it points to g->entries
- */
- struct gentry *cntr[2]; /* double-linked circular list */
-/* convenience handles */
-#define bkwd cntr[0]
-#define frwd cntr[1]
-
- /* various extended structures used at some stage of transformation */
- void *ext;
-
- union {
- struct {
- int val[2][3]; /* integer values */
- } i;
- struct {
- double val[2][3]; /* floating values */
- } f;
- } points; /* absolute values, NOT deltas */
-/* convenience handles */
-#define ipoints points.i.val
-#define fpoints points.f.val
-#define ixn ipoints[0]
-#define iyn ipoints[1]
-#define fxn fpoints[0]
-#define fyn fpoints[1]
-#define ix1 ixn[0]
-#define ix2 ixn[1]
-#define ix3 ixn[2]
-#define iy1 iyn[0]
-#define iy2 iyn[1]
-#define iy3 iyn[2]
-#define fx1 fxn[0]
-#define fx2 fxn[1]
-#define fx3 fxn[2]
-#define fy1 fyn[0]
-#define fy2 fyn[1]
-#define fy3 fyn[2]
-
- char flags;
-#define GEF_FLOAT 0x02 /* entry contains floating point data */
-#define GEF_LINE 0x04 /* entry looks like a line even if it's a curve */
-
- unsigned char dir; /* used to temporarily store the values for
- * the directions of the ends of curves */
-/* front end */
-#define CVDIR_FUP 0x02 /* goes over the line connecting the ends */
-#define CVDIR_FEQUAL 0x01 /* coincides with the line connecting the
- * ends */
-#define CVDIR_FDOWN 0x00 /* goes under the line connecting the ends */
-#define CVDIR_FRONT 0x0F /* mask of all front directions */
-/* rear end */
-#define CVDIR_RSAME 0x30 /* is the same as for the front end */
-#define CVDIR_RUP 0x20 /* goes over the line connecting the ends */
-#define CVDIR_REQUAL 0x10 /* coincides with the line connecting the
- * ends */
-#define CVDIR_RDOWN 0x00 /* goes under the line connecting the ends */
-#define CVDIR_REAR 0xF0 /* mask of all rear directions */
-
- signed char stemid; /* connection to the substituted stem group */
- char type;
-#define GE_HSBW 'B'
-#define GE_MOVE 'M'
-#define GE_LINE 'L'
-#define GE_CURVE 'C'
-#define GE_PATH 'P'
-
- /* indexes of the points to be used for calculation of the tangents */
- signed char ftg; /* front tangent */
- signed char rtg; /* rear tangent, -1 means "idx 2 of the previous entry" */
-} GENTRY;
-
-/* stem structure, describes one [hv]stem */
-/* acually, it describes one border of a stem */
-/* the whole stem is a pair of these structures */
-
-typedef struct stem {
- short value; /* value of X or Y coordinate */
- short origin; /* point of origin for curve stems */
- GENTRY *ge; /* entry that has (value, origin) as its first dot */
- /* also for all the stems the couple (value, origin)
- * is used to determine whether a stem is relevant for a
- * line, it's considered revelant if this tuple is
- * equal to any of the ends of the line.
- * ge is also used to resolve ambiguity if there is more than
- * one line going through certain pointi, it is used to
- * distinguish these lines.
- */
-
- short from, to; /* values of other coordinate between
- * which this stem is valid */
-
- short flags;
- /* ordering of ST_END, ST_FLAT, ST_ZONE is IMPORTANT for sorting */
-#define ST_END 0x01 /* end of line, lowest priority */
-#define ST_FLAT 0x02 /* stem is defined by a flat line, not a
- * curve */
-#define ST_ZONE 0x04 /* pseudo-stem, the limit of a blue zone */
-#define ST_UP 0x08 /* the black area is to up or right from
- * value */
-#define ST_3 0x20 /* first stem of [hv]stem3 */
-#define ST_BLUE 0x40 /* stem is in blue zone */
-#define ST_TOPZONE 0x80 /* 1 - top zone, 0 - bottom zone */
-#define ST_VERT 0x100 /* vertical stem (used in substitutions) */
-} STEM;
-
-#define MAX_STEMS 2000 /* we can't have more stems than path
- * elements (or hope so) */
-#define NSTEMGRP 50 /* maximal number of the substituted stem groups */
-
-/* structure for economical representation of the
- * substituted stems
- */
-
-typedef struct stembounds {
- short low; /* low bound */
- short high; /* high bound */
- char isvert; /* 1 - vertical, 0 - horizontal */
- char already; /* temp. flag: is aleready included */
-} STEMBOUNDS;
-
-struct kern {
- unsigned id; /* ID of the second glyph */
- int val; /* kerning value */
-};
-
-typedef struct contour {
- short ymin, xofmin;
- short inside; /* inside which contour */
- char direction;
-#define DIR_OUTER 1
-#define DIR_INNER 0
-} CONTOUR;
-
-typedef struct glyph {
- int char_no;/* Encoding of glyph */
- int orig_code;/* code of glyph in the font's original encoding */
- char *name; /* Postscript name of glyph */
- int xMin, yMin, xMax, yMax; /* values from TTF dictionary */
- int lsb; /* left sidebearing */
- int ttf_pathlen; /* total length of TTF paths */
- short width;
- short flags;
-#define GF_USED 0x0001 /* whether is this glyph used in T1 font */
-#define GF_FLOAT 0x0002 /* thys glyph contains floating point entries */
-
- GENTRY *entries;/* doube linked list of entries */
- GENTRY *lastentry; /* the last inserted entry */
- GENTRY *path; /* beggining of the last path */
- int oldwidth; /* actually also scaled */
- int scaledwidth;
-#define MAXLEGALWIDTH 10000
-
- struct kern *kern; /* kerning data */
- int kerncount; /* number of kerning pairs */
- int kernalloc; /* for how many pairs we have space */
-
- STEM *hstems; /* global horiz. and vert. stems */
- STEM *vstems;
- int nhs, nvs; /* numbers of stems */
-
- STEMBOUNDS *sbstems; /* substituted stems for all the groups */
- short *nsbs; /* indexes of the group ends in the common array */
- int nsg; /* actual number of the stem groups */
- int firstsubr; /* first substistuted stems subroutine number */
-
- CONTOUR *contours; /* it is not used now */
- int ncontours;
-
- int rymin, rymax; /* real values */
- /* do we have flat surfaces on top/bottom */
- char flatymin, flatymax;
-
-} GLYPH;
-
-/* description of a dot for calculation of its distance to a curve */
-
-struct dot_dist {
- double p[2 /*X,Y*/]; /* coordinates of a dot */
- double dist2; /* squared distance from the dot to the curve */
- short seg; /* the closest segment of the curve */
-};
-
-extern int stdhw, stdvw; /* dominant stems widths */
-extern int stemsnaph[12], stemsnapv[12]; /* most typical stem width */
-
-extern int bluevalues[14];
-extern int nblues;
-extern int otherblues[10];
-extern int notherb;
-extern int bbox[4]; /* the FontBBox array */
-extern double italic_angle;
-
-extern GLYPH *glyph_list;
-extern int encoding[]; /* inverse of glyph[].char_no */
-
-/* prototypes of functions */
-void rmoveto( int dx, int dy);
-void rlineto( int dx, int dy);
-void rrcurveto( int dx1, int dy1, int dx2, int dy2, int dx3, int dy3);
-void assertpath( GENTRY * from, char *file, int line, char *name);
-
-void fg_rmoveto( GLYPH * g, double x, double y);
-void ig_rmoveto( GLYPH * g, int x, int y);
-void fg_rlineto( GLYPH * g, double x, double y);
-void ig_rlineto( GLYPH * g, int x, int y);
-void fg_rrcurveto( GLYPH * g, double x1, double y1,
- double x2, double y2, double x3, double y3);
-void ig_rrcurveto( GLYPH * g, int x1, int y1,
- int x2, int y2, int x3, int y3);
-void g_closepath( GLYPH * g);
-
-void pathtoint( GLYPH *g);
-void ffixquadrants( GLYPH *g);
-void flattencurves( GLYPH * g);
-int checkcv( GENTRY * ge, int dx, int dy);
-void iclosepaths( GLYPH * g);
-void fclosepaths( GLYPH * g);
-void smoothjoints( GLYPH * g);
-void buildstems( GLYPH * g);
-void fstraighten( GLYPH * g);
-void istraighten( GLYPH * g, int zigonly);
-void isplitzigzags( GLYPH * g);
-void fsplitzigzags( GLYPH * g);
-void fforceconcise( GLYPH * g);
-void iforceconcise( GLYPH * g);
-void reversepathsfromto( GENTRY * from, GENTRY * to);
-void reversepaths( GLYPH * g);
-void dumppaths( GLYPH * g, GENTRY *start, GENTRY *end);
-void print_glyph( int glyphno);
-int print_glyph_subs( int glyphno, int startid);
-void print_glyph_metrics( int code, int glyphno);
-void findblues(void);
-void stemstatistics(void);
-void docorrectwidth(void);
-void addkernpair( unsigned id1, unsigned id2, int unscval);
-void print_kerning( FILE *afm_file);
-
-int fcrossrayscv( double curve[4][2], double *max1, double *max2);
-int fcrossraysge( GENTRY *ge1, GENTRY *ge2, double *max1, double *max2,
- double crossdot[2][2]);
-double fdotsegdist2( double seg[2][2], double dot[2]);
-double fdotcurvdist2( double curve[4][2], struct dot_dist *dots, int ndots, double *maxp);
-void fapproxcurve( double cv[4][2], struct dot_dist *dots, int ndots);
+++ /dev/null
-/*
- * Wrap-around code to either compile in t1asm or call it externally
- *
- * Copyright (C) 2000 by Sergey Babkin
- * Copyright (C) 2000 by The TTF2PT1 Project
- *
- * See COPYRIGHT for full license
- */
-
-#ifdef EXTERNAL_T1ASM
-
-#include <stdio.h>
-#include <errno.h>
-
-FILE *ifp;
-FILE *ofp;
-
-int
-runt1asm(
- int pfbflag
-)
-{
- char *cmd;
- int id, od;
- int error;
-
- /* first make a copy in case some of then is already stdin/stdout */
- if(( id = dup(fileno(ifp)) )<0) {
- perror("** Re-opening input file for t1asm");
- exit(1);
- }
- if(( od = dup(fileno(ofp)) )<0) {
- perror("** Re-opening output file for t1asm");
- exit(1);
- }
- fclose(ifp); fclose(ofp);
- close(0);
- if(( dup(id) )!=0) {
- perror("** Re-directing input file for t1asm");
- exit(1);
- }
- close(1);
- if(( dup(od) )!=1) {
- perror("** Re-directing output file for t1asm");
- exit(1);
- }
- close(id); close(od);
-
- if(pfbflag)
- error = execlp("t1asm", "t1asm", "-b", NULL);
- else
- error = execlp("t1asm", "t1asm", NULL);
-
- perror("** Calling t1asm");
-
- exit(1);
-}
-
-#else
-# include "t1asm.c"
-#endif
+++ /dev/null
-/* t1asm
- *
- * This program `assembles' Adobe Type-1 font programs in pseudo-PostScript
- * form into either PFB or PFA format. The human readable/editable input is
- * charstring- and eexec-encrypted as specified in the `Adobe Type 1 Font
- * Format' version 1.1 (the `black book'). There is a companion program,
- * t1disasm, which `disassembles' PFB and PFA files into a pseudo-PostScript
- * file.
- *
- * Copyright (c) 1992 by I. Lee Hetherington, all rights reserved.
- *
- * Permission is hereby granted to use, modify, and distribute this program
- * for any purpose provided this copyright notice and the one below remain
- * intact.
- *
- * I. Lee Hetherington (ilh@lcs.mit.edu)
- *
- * Revision 1.2 92/05/22 11:54:45 ilh
- * Fixed bug where integers larger than 32000 could not be encoded in
- * charstrings. Now integer range is correct for four-byte
- * twos-complement integers: -(1<<31) <= i <= (1<<31)-1. Bug detected by
- * Piet Tutelaers (rcpt@urc.tue.nl).
- *
- * Revision 1.1 92/05/22 11:48:46 ilh
- * initial version
- *
- * Ported to Microsoft C/C++ Compiler and MS-DOS operating system by
- * Kai-Uwe Herbing (herbing@netmbx.netmbx.de) on June 12, 1992. Code
- * specific to the MS-DOS version is encapsulated with #ifdef _MSDOS
- * ... #endif, where _MSDOS is an identifier, which is automatically
- * defined, if you compile with the Microsoft C/C++ Compiler.
- *
- */
-
-#ifndef lint
-static char copyright[] =
- "@(#) Copyright (c) 1992 by I. Lee Hetherington, all rights reserved.";
-#ifdef _MSDOS
-static char portnotice[] =
- "@(#) Ported to MS-DOS by Kai-Uwe Herbing (herbing@netmbx.netmbx.de).";
-#endif
-#endif
-
-/* Note: this is ANSI C. */
-
-#ifdef _MSDOS
- #include <fcntl.h>
- #include <getopt.h>
- #include <io.h>
-#endif
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <limits.h>
-
-#ifdef WIN32
-# ifdef STANDALONE
-# define WINDOWS_FUNCTIONS
-# include "win_missing.h"
-# endif
-#endif
-
-/* int32 must be at least 32-bit and uint16 must be at least 16-bit */
-#if INT_MAX >= 0x7FFFFFFFUL
-typedef int int32;
-#else
-typedef long int32;
-#endif
-#if USHRT_MAX >= 0xFFFFUL
-typedef unsigned short uint16;
-#else
-typedef unsigned int uint16;
-#endif
-
-#define LINESIZE 256
-
-#define MAXBLOCKLEN ((1L<<17)-6)
-#define MINBLOCKLEN ((1L<<8)-6)
-
-#define MARKER 128
-#define ASCII 1
-#define BINARY 2
-#define DONE 3
-
-typedef unsigned char byte;
-
-/* must be visible from outside */
-FILE *ifp;
-FILE *ofp;
-
-/* flags */
-static int pfb = 0;
-static int active = 0;
-static int start_charstring = 0;
-static int in_eexec = 0;
-
-static char line[LINESIZE];
-
-/* lenIV and charstring start command */
-static int lenIV = 4;
-static char cs_start[10];
-
-/* for charstring buffering */
-static byte charstring_buf[65535];
-static byte *charstring_bp;
-
-/* for PFB block buffering */
-static byte blockbuf[MAXBLOCKLEN];
-static int32 blocklen = MAXBLOCKLEN;
-static int32 blockpos = -1;
-static int blocktyp = ASCII;
-
-/* decryption stuff */
-static uint16 er, cr;
-static uint16 c1 = 52845, c2 = 22719;
-
-/* table of charstring commands */
-static struct command {
- char *name;
- int one, two;
-} command_table[] = {
- { "callothersubr", 12, 16 },
- { "callsubr", 10, -1 },
- { "closepath", 9, -1 },
- { "div", 12, 12 },
- { "dotsection", 12, 0 },
- { "endchar", 14, -1 },
- { "hlineto", 6, -1 },
- { "hmoveto", 22, -1 },
- { "hsbw", 13, -1 },
- { "hstem", 1, -1 },
- { "hstem3", 12, 2 },
- { "hvcurveto", 31, -1 },
- { "pop", 12, 17 },
- { "return", 11, -1 },
- { "rlineto", 5, -1 },
- { "rmoveto", 21, -1 },
- { "rrcurveto", 8, -1 },
- { "sbw", 12, 7 },
- { "seac", 12, 6 },
- { "setcurrentpoint", 12, 33 },
- { "vhcurveto", 30, -1 },
- { "vlineto", 7, -1 },
- { "vmoveto", 4, -1 },
- { "vstem", 3, -1 },
- { "vstem3", 12, 1 },
-}; /* alphabetical */
-
-/* Two separate encryption functions because eexec and charstring encryption
- must proceed in parallel. */
-
-static byte eencrypt(byte plain)
-{
- byte cipher;
-
- cipher = (byte) (plain ^ (er >> 8));
- er = (uint16) ((cipher + er) * c1 + c2);
- return cipher;
-}
-
-static byte cencrypt(byte plain)
-{
- byte cipher;
-
- cipher = (byte) (plain ^ (cr >> 8));
- cr = (uint16) ((cipher + cr) * c1 + c2);
- return cipher;
-}
-
-/* This function flushes a buffered PFB block. */
-
-static void output_block()
-{
- int32 i;
-
- /* output four-byte block length */
- fputc((int) (blockpos & 0xff), ofp);
- fputc((int) ((blockpos >> 8) & 0xff), ofp);
- fputc((int) ((blockpos >> 16) & 0xff), ofp);
- fputc((int) ((blockpos >> 24) & 0xff), ofp);
-
- /* output block data */
- for (i = 0; i < blockpos; i++)
- fputc(blockbuf[i], ofp);
-
- /* mark block buffer empty and uninitialized */
- blockpos = -1;
-}
-
-/* This function outputs a single byte. If output is in PFB format then output
- is buffered through blockbuf[]. If output is in PFA format, then output
- will be hexadecimal if in_eexec is set, ASCII otherwise. */
-
-static void output_byte(byte b)
-{
- static char *hexchar = "0123456789ABCDEF";
- static int hexcol = 0;
-
- if (pfb) {
- /* PFB */
- if (blockpos < 0) {
- fputc(MARKER, ofp);
- fputc(blocktyp, ofp);
- blockpos = 0;
- }
- blockbuf[blockpos++] = b;
- if (blockpos == blocklen)
- output_block();
- } else {
- /* PFA */
- if (in_eexec) {
- /* trim hexadecimal lines to 64 columns */
- if (hexcol >= 64) {
- fputc('\n', ofp);
- hexcol = 0;
- }
- fputc(hexchar[(b >> 4) & 0xf], ofp);
- fputc(hexchar[b & 0xf], ofp);
- hexcol += 2;
- } else {
- fputc(b, ofp);
- }
- }
-}
-
-/* This function outputs a byte through possible eexec encryption. */
-
-static void eexec_byte(byte b)
-{
- if (in_eexec)
- output_byte(eencrypt(b));
- else
- output_byte(b);
-}
-
-/* This function outputs a null-terminated string through possible eexec
- encryption. */
-
-static void eexec_string(char *string)
-{
- while (*string)
- eexec_byte((byte) *string++);
-}
-
-/* This function gets ready for the eexec-encrypted data. If output is in
- PFB format then flush current ASCII block and get ready for binary block.
- We start encryption with four random (zero) bytes. */
-
-static void eexec_start()
-{
- eexec_string(line);
- if (pfb) {
- output_block();
- blocktyp = BINARY;
- }
-
- in_eexec = 1;
- er = 55665;
- eexec_byte(0);
- eexec_byte(0);
- eexec_byte(0);
- eexec_byte(0);
-}
-
-/* This function wraps-up the eexec-encrypted data.
- If output is in PFB format then this entails flushing binary block and
- starting an ASCII block. */
-
-static void eexec_end()
-{
- int i, j;
-
- if (pfb) {
- output_block();
- blocktyp = ASCII;
- } else {
- fputc('\n', ofp);
- }
- in_eexec = 0;
- for (i = 0; i < 8; i++) {
- for (j = 0; j < 64; j++)
- eexec_byte('0');
- eexec_byte('\n');
- }
-#if 0
- eexec_string("cleartomark\n");
-#endif
-}
-
-/* This function writes ASCII trailer.
- If output is in PFB format then this entails flushing binary block and
- starting an ASCII block. */
-
-static void file_end()
-{
- if (pfb) {
- output_block();
- fputc(MARKER, ofp);
- fputc(DONE, ofp);
- }
-}
-/* This function returns an input line of characters. A line is terminated by
- length (including terminating null) greater than LINESIZE, a newline \n, or
- when active (looking for charstrings) by '{'. When terminated by a newline
- the newline is put into line[]. When terminated by '{', the '{' is not put
- into line[], and the flag start_charstring is set to 1. */
-
-static void t1asm_getline()
-{
- int c;
- char *p = line;
- int comment = 0;
-
- start_charstring = 0;
- while (p < line + LINESIZE) {
- c = fgetc(ifp);
- if (c == EOF)
- break;
- if (c == '%')
- comment = 1;
- if (active && !comment && c == '{') {
- start_charstring = 1;
- break;
- }
- *p++ = (char) c;
- if (c == '\n')
- break;
- }
- *p = '\0';
-}
-
-/* This function is used by the binary search, bsearch(), for command names in
- the command table. */
-
-static int command_compare(const void *key, const void *item)
-{
- return strcmp((char *) key, ((struct command *) item)->name);
-}
-
-/* This function returns 1 if the string is an integer and 0 otherwise. */
-
-static int is_integer(char *string)
-{
- if (isdigit(string[0]) || string[0] == '-' || string[0] == '+') {
- while (*++string && isdigit(*string))
- ; /* deliberately empty */
- if (!*string)
- return 1;
- }
- return 0;
-}
-
-/* This function initializes charstring encryption. Note that this is called
- at the beginning of every charstring. */
-
-static void charstring_start()
-{
- int i;
-
- charstring_bp = charstring_buf;
- cr = 4330;
- for (i = 0; i < lenIV; i++)
- *charstring_bp++ = cencrypt((byte) 0);
-}
-
-/* This function encrypts and buffers a single byte of charstring data. */
-
-static void charstring_byte(int v)
-{
- byte b = (byte) (v & 0xff);
-
- if (charstring_bp - charstring_buf > sizeof(charstring_buf)) {
- fprintf(stderr, "error: charstring_buf full (%d bytes)\n",
- sizeof(charstring_buf));
- exit(1);
- }
- *charstring_bp++ = cencrypt(b);
-}
-
-/* This function outputs buffered, encrypted charstring data through possible
- eexec encryption. */
-
-static void charstring_end()
-{
- byte *bp;
-
- sprintf(line, "%d ", charstring_bp - charstring_buf);
- eexec_string(line);
- sprintf(line, "%s ", cs_start);
- eexec_string(line);
- for (bp = charstring_buf; bp < charstring_bp; bp++)
- eexec_byte(*bp);
-}
-
-/* This function generates the charstring representation of an integer. */
-
-static void charstring_int(int num)
-{
- int x;
-
- if (num >= -107 && num <= 107) {
- charstring_byte(num + 139);
- } else if (num >= 108 && num <= 1131) {
- x = num - 108;
- charstring_byte(x / 256 + 247);
- charstring_byte(x % 256);
- } else if (num >= -1131 && num <= -108) {
- x = abs(num) - 108;
- charstring_byte(x / 256 + 251);
- charstring_byte(x % 256);
- } else if (num >= (-2147483647-1) && num <= 2147483647) {
- charstring_byte(255);
- charstring_byte(num >> 24);
- charstring_byte(num >> 16);
- charstring_byte(num >> 8);
- charstring_byte(num);
- } else {
- fprintf(stderr,
- "error: cannot format the integer %d, too large\n", num);
- exit(1);
- }
-}
-
-/* This function parses an entire charstring into integers and commands,
- outputting bytes through the charstring buffer. */
-
-static void parse_charstring()
-{
- struct command *cp;
-
- charstring_start();
- while (fscanf(ifp, "%s", line) == 1) {
- //char*bracket;
- if (line[0] == '%') {
- /* eat comment to end of line */
- while (fgetc(ifp) != '\n' && !feof(ifp))
- ; /* deliberately empty */
- continue;
- }
- if (line[0] == '}')
- break;
- //if(bracket=strchr(line, '}')) {
- // *bracket = 0;
- //}
- if (is_integer(line)) {
- charstring_int(atoi(line));
- } else {
- cp = (struct command *)
- bsearch((void *) line, (void *) command_table,
- sizeof(command_table) / sizeof(struct command),
- sizeof(struct command),
- command_compare);
- if (cp) {
- charstring_byte(cp->one);
- if (cp->two >= 0)
- charstring_byte(cp->two);
- } else {
- fprintf(stderr, "error: cannot use `%s' in charstring\n",line);
- exit(1);
- }
- }
- //if(bracket) {
- // //line ended with }
- // break;
- //}
- }
- charstring_end();
-}
-
-static void usage()
-{
- fprintf(stderr,
- "usage: t1asm [-b] [-l block-length] [input [output]]\n");
- fprintf(stderr,
- "\n-b means output in PFB format, otherwise PFA format.\n");
- fprintf(stderr,
- "The block length applies to the length of blocks in the\n");
- fprintf(stderr,
- "PFB output file; the default is to use the largest possible.\n");
- exit(1);
-}
-
-static void print_banner()
-{
- static char rcs_revision[] = ""; /* removed RCS */
- static char revision[20];
-
- if (sscanf(rcs_revision, "$Revision: %19s", revision) != 1)
- revision[0] = '\0';
- fprintf(stderr, "This is t1asm %s.\n", revision);
-}
-
-#ifdef STANDALONE
-int main(int argc, char **argv)
-{
- char *p, *q, *r;
- int c;
-
- extern char *optarg;
- extern int optind;
-
- ifp = stdin;
- ofp = stdout;
-
- print_banner();
-
- /* interpret command line arguments using getopt */
- while ((c = getopt(argc, argv, "bl:")) != -1)
- switch (c) {
- case 'b':
- pfb = 1;
- break;
- case 'l':
- blocklen = atoi(optarg);
- if (blocklen < MINBLOCKLEN) {
- blocklen = MINBLOCKLEN;
- fprintf(stderr,
- "warning: using minimum block length of %d\n",
- blocklen);
- } else if (blocklen > MAXBLOCKLEN) {
- blocklen = MAXBLOCKLEN;
- fprintf(stderr,
- "warning: using maximum block length of %d\n",
- blocklen);
- }
- break;
- default:
- usage();
- break;
- }
- if (argc - optind > 2)
- usage();
-
- /* possibly open input & output files */
- if (argc - optind >= 1) {
- ifp = fopen(argv[optind], "rb");
- if (!ifp) {
- fprintf(stderr, "error: cannot open %s for reading\n", argv[1]);
- exit(1);
- }
- }
- if (argc - optind >= 2) {
- ofp = fopen(argv[optind + 1], "wb");
- if (!ofp) {
- fprintf(stderr, "error: cannot open %s for writing\n", argv[2]);
- exit(1);
- }
- }
-
-#else
-int runt1asm(int pfbflag)
-{
- char *p, *q, *r;
-
- /* need to reset this. (For some reason, if ttf2pt1.c fork()s, it doesn't
- matter whether we reset this or not, triggering a bug which only appears
- on Win32 */
- active = 0;
-
- pfb = pfbflag;
-#endif
-
- #ifdef _MSDOS
- /* If we are processing a PFB (binary) output */
- /* file, we must set its file mode to binary. */
- if (pfb)
- _setmode(_fileno(ofp), _O_BINARY);
- #endif
-
- /* Finally, we loop until no more input. Some special things to look for
- are the `currentfile eexec' line, the beginning of the `/Subrs'
- definition, the definition of `/lenIV', and the definition of the
- charstring start command which has `...string currentfile...' in it. */
-
- while (!feof(ifp) && !ferror(ifp)) {
- t1asm_getline();
- if (strcmp(line, "currentfile eexec\n") == 0) {
- eexec_start();
- continue;
- } else if (strstr(line, "/Subrs") && isspace(line[6])) {
- active = 1;
- } else if ((p = strstr(line, "/lenIV"))) {
- sscanf(p, "%*s %d", &lenIV);
- } else if ((p = strstr(line, "string currentfile"))) {
- /* locate the name of the charstring start command */
- *p = '\0'; /* damage line[] */
- q = strrchr(line, '/');
- if (q) {
- r = cs_start;
- ++q;
- while (!isspace(*q) && *q != '{')
- *r++ = *q++;
- *r = '\0';
- }
- *p = 's'; /* repair line[] */
- }
- /* output line data */
- eexec_string(line);
- if ((p = strstr(line, "currentfile closefile"))) {
- eexec_end();
- }
- if (start_charstring) {
- if (!cs_start[0]) {
- fprintf(stderr, "error: couldn't find charstring start command\n");
- exit(1);
- }
- parse_charstring();
- }
- }
- file_end();
-
- fclose(ifp);
- fclose(ofp);
-
- return 0;
-}
+++ /dev/null
-/*
- * True Type Font to Adobe Type 1 font converter
- * By Mark Heath <mheath@netspace.net.au>
- * Based on ttf2pfa by Andrew Weeks <ccsaw@bath.ac.uk>
- * With help from Frank M. Siegert <fms@this.net>
- *
- * see COPYRIGHT
- *
- */
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <time.h>
-#include <ctype.h>
-#include <math.h>
-
-#ifndef WIN32
-# include <unistd.h>
-# include <netinet/in.h>
-#else
-# include "windows.h"
-#endif
-
-#include "ttf.h"
-#include "pt1.h"
-#include "global.h"
-
-/* prototypes of call entries */
-static void openfont(char *fname, char *arg);
-static void closefont( void);
-static int getnglyphs ( void);
-static int glnames( GLYPH *glyph_list);
-static void glmetrics( GLYPH *glyph_list);
-static int glenc( GLYPH *glyph_list, int *encoding, int *unimap);
-static void fnmetrics( struct font_metrics *fm);
-static void glpath( int glyphno, GLYPH *glyph_list);
-static void kerning( GLYPH *glyph_list);
-
-/* globals */
-
-/* front-end descriptor */
-struct frontsw ttf_sw = {
- /*name*/ "ttf",
- /*descr*/ "built-in TTF support",
- /*suffix*/ { "ttf" },
- /*open*/ openfont,
- /*close*/ closefont,
- /*nglyphs*/ getnglyphs,
- /*glnames*/ glnames,
- /*glmetrics*/ glmetrics,
- /*glenc*/ glenc,
- /*fnmetrics*/ fnmetrics,
- /*glpath*/ glpath,
- /*kerning*/ kerning,
-};
-
-/* statics */
-
-static FILE *ttf_file;
-static int ttf_nglyphs, long_offsets;
-
-static TTF_DIRECTORY *directory;
-static TTF_DIR_ENTRY *dir_entry;
-static char *filebuffer;
-static char *filebuffer_end;
-static TTF_NAME *name_table = NULL;
-static TTF_NAME_REC *name_record;
-static TTF_HEAD *head_table = NULL;
-static TTF_HHEA *hhea_table = NULL;
-static TTF_KERN *kern_table = NULL;
-static TTF_CMAP *cmap_table = NULL;
-static LONGHORMETRIC *hmtx_table = NULL;
-static TTF_GLYF *glyf_table;
-static BYTE *glyf_start = NULL;
-static TTF_MAXP *maxp_table = NULL;
-static TTF_POST_HEAD *post_table = NULL;
-static union {
- USHORT *sp;
- ULONG *lp;
-} loca_table;
-#define short_loca_table loca_table.sp
-#define long_loca_table loca_table.lp
-
-static short cmap_n_segs;
-static USHORT *cmap_seg_start, *cmap_seg_end;
-static short *cmap_idDelta, *cmap_idRangeOffset;
-static TTF_CMAP_FMT0 *encoding0;
-static int enc_type;
-
-static char name_buffer[2000];
-static char *name_fields[8];
-
-static int enc_found_ms, enc_found_mac;
-
-static char *mac_glyph_names[258] = {
- ".notdef", ".null", "CR",
- "space", "exclam", "quotedbl", "numbersign",
- "dollar", "percent", "ampersand", "quotesingle",
- "parenleft", "parenright", "asterisk", "plus",
- "comma", "hyphen", "period", "slash",
- "zero", "one", "two", "three",
- "four", "five", "six", "seven",
- "eight", "nine", "colon", "semicolon",
- "less", "equal", "greater", "question",
- "at", "A", "B", "C",
- "D", "E", "F", "G",
- "H", "I", "J", "K",
- "L", "M", "N", "O",
- "P", "Q", "R", "S",
- "T", "U", "V", "W",
- "X", "Y", "Z", "bracketleft",
- "backslash", "bracketright", "asciicircum", "underscore",
- "grave", "a", "b", "c",
- "d", "e", "f", "g",
- "h", "i", "j", "k",
- "l", "m", "n", "o",
- "p", "q", "r", "s",
- "t", "u", "v", "w",
- "x", "y", "z", "braceleft",
- "bar", "braceright", "asciitilde", "Adieresis",
- "Aring", "Ccedilla", "Eacute", "Ntilde",
- "Odieresis", "Udieresis", "aacute", "agrave",
- "acircumflex", "adieresis", "atilde", "aring",
- "ccedilla", "eacute", "egrave", "ecircumflex",
- "edieresis", "iacute", "igrave", "icircumflex",
- "idieresis", "ntilde", "oacute", "ograve",
- "ocircumflex", "odieresis", "otilde", "uacute",
- "ugrave", "ucircumflex", "udieresis", "dagger",
- "degree", "cent", "sterling", "section",
- "bullet", "paragraph", "germandbls", "registered",
- "copyright", "trademark", "acute", "dieresis",
- "notequal", "AE", "Oslash", "infinity",
- "plusminus", "lessequal", "greaterequal", "yen",
- "mu", "partialdiff", "summation", "product",
- "pi", "integral", "ordfeminine", "ordmasculine",
- "Omega", "ae", "oslash", "questiondown",
- "exclamdown", "logicalnot", "radical", "florin",
- "approxequal", "increment", "guillemotleft", "guillemotright",
- "ellipsis", "nbspace", "Agrave", "Atilde",
- "Otilde", "OE", "oe", "endash",
- "emdash", "quotedblleft", "quotedblright", "quoteleft",
- "quoteright", "divide", "lozenge", "ydieresis",
- "Ydieresis", "fraction", "currency", "guilsinglleft",
- "guilsinglright", "fi", "fl", "daggerdbl",
- "periodcentered", "quotesinglbase", "quotedblbase", "perthousand",
- "Acircumflex", "Ecircumflex", "Aacute", "Edieresis",
- "Egrave", "Iacute", "Icircumflex", "Idieresis",
- "Igrave", "Oacute", "Ocircumflex", "applelogo",
- "Ograve", "Uacute", "Ucircumflex", "Ugrave",
- "dotlessi", "circumflex", "tilde", "macron",
- "breve", "dotaccent", "ring", "cedilla",
- "hungarumlaut", "ogonek", "caron", "Lslash",
- "lslash", "Scaron", "scaron", "Zcaron",
- "zcaron", "brokenbar", "Eth", "eth",
- "Yacute", "yacute", "Thorn", "thorn",
- "minus", "multiply", "onesuperior", "twosuperior",
- "threesuperior", "onehalf", "onequarter", "threequarters",
- "franc", "Gbreve", "gbreve", "Idot",
- "Scedilla", "scedilla", "Cacute", "cacute",
- "Ccaron", "ccaron", "dmacron"
-};
-
-/* other prototypes */
-static void draw_composite_glyf( GLYPH *g, GLYPH *glyph_list, int glyphno,
- double *matrix, int level);
-static void draw_simple_glyf( GLYPH *g, GLYPH *glyph_list, int glyphno,
- double *matrix);
-static double f2dot14( short x);
-
-/* get the TTF description table address and length for this index */
-
-static void
-get_glyf_table(
- int glyphno,
- TTF_GLYF **tab,
- int *len
-)
-{
- if(tab!=NULL) {
- if (long_offsets) {
- *tab = (TTF_GLYF *) (glyf_start + ntohl(long_loca_table[glyphno]));
- } else {
- *tab = (TTF_GLYF *) (glyf_start + (ntohs(short_loca_table[glyphno]) << 1));
- }
- }
- if(len!=NULL) {
- if (long_offsets) {
- *len = ntohl(long_loca_table[glyphno + 1]) - ntohl(long_loca_table[glyphno]);
- } else {
- *len = (ntohs(short_loca_table[glyphno + 1]) - ntohs(short_loca_table[glyphno])) << 1;
- }
- }
-}
-
-static void
-handle_name(void)
-{
- int j, k, lang, len, platform;
- char *p, *string_area;
- char *nbp = name_buffer;
- int found3 = 0;
-
- string_area = (char *) name_table + ntohs(name_table->offset);
- name_record = &(name_table->nameRecords);
-
- for (j = 0; j < 8; j++) {
- name_fields[j] = "";
- }
-
- for (j = 0; j < ntohs(name_table->numberOfNameRecords); j++) {
-
- platform = ntohs(name_record->platformID);
-
- if (platform == 3) {
-
- found3 = 1;
- lang = ntohs(name_record->languageID) & 0xff;
- len = ntohs(name_record->stringLength);
- if (lang == 0 || lang == 9) {
- k = ntohs(name_record->nameID);
- if (k < 8) {
- name_fields[k] = nbp;
-
- p = string_area + ntohs(name_record->stringOffset);
- for (k = 0; k < len; k++) {
- if (p[k] != '\0') {
- if (p[k] == '(') {
- *nbp = '[';
- } else if (p[k] == ')') {
- *nbp = ']';
- } else {
- *nbp = p[k];
- }
- nbp++;
- }
- }
- *nbp = '\0';
- nbp++;
- }
- }
- }
- name_record++;
- }
-
- string_area = (char *) name_table + ntohs(name_table->offset);
- name_record = &(name_table->nameRecords);
-
- if (!found3) {
- for (j = 0; j < ntohs(name_table->numberOfNameRecords); j++) {
-
- platform = ntohs(name_record->platformID);
-
- if (platform == 1) {
-
- found3 = 1;
- lang = ntohs(name_record->languageID) & 0xff;
- len = ntohs(name_record->stringLength);
- if (lang == 0 || lang == 9) {
- k = ntohs(name_record->nameID);
- if (k < 8) {
- name_fields[k] = nbp;
-
- p = string_area + ntohs(name_record->stringOffset);
- for (k = 0; k < len; k++) {
- if (p[k] != '\0') {
- if (p[k] == '(') {
- *nbp = '[';
- } else if (p[k] == ')') {
- *nbp = ']';
- } else {
- *nbp = p[k];
- }
- nbp++;
- }
- }
- *nbp = '\0';
- nbp++;
- }
- }
- }
- name_record++;
- }
- }
- if (!found3) {
- fprintf(stderr, "**** Cannot decode font name fields ****\n");
- exit(1);
- }
- if (name_fields[4][0] == 0) { /* Full Name empty, use Family Name */
- name_fields[4] = name_fields[1];
- }
- if (name_fields[6][0] == 0) { /* Font Name empty, use Full Name */
- name_fields[6] = name_fields[4];
- if (name_fields[6][0] == 0) { /* oops, empty again */
- WARNING_1 fprintf(stderr, "Font name is unknown, setting to \"Unknown\"\n");
- name_fields[6] = "Unknown";
- }
- }
- p = name_fields[6];
- /* must not start with a digit */
- if(isdigit(*p))
- *p+= 'A'-'0'; /* change to a letter */
- while (*p != '\0') {
- if (!isalnum(*p) || *p=='_') {
- *p = '-';
- }
- p++;
- }
-}
-
-static void
-handle_head(void)
-{
- long_offsets = ntohs(head_table->indexToLocFormat);
- if (long_offsets != 0 && long_offsets != 1) {
- fprintf(stderr, "**** indexToLocFormat wrong ****\n");
- exit(1);
- }
-}
-
-/* limit the recursion level to avoid cycles */
-#define MAX_COMPOSITE_LEVEL 20
-
-static void
-draw_composite_glyf(
- GLYPH *g,
- GLYPH *glyph_list,
- int glyphno,
- double *orgmatrix,
- int level
-)
-{
- int len;
- short ncontours;
- USHORT flagbyte, glyphindex;
- double arg1, arg2;
- BYTE *ptr;
- char *bptr;
- SHORT *sptr;
- double matrix[6], newmatrix[6];
-
- get_glyf_table(glyphno, &glyf_table, &len);
-
- if(len<=0) /* nothing to do */
- return;
-
- ncontours = ntohs(glyf_table->numberOfContours);
- if (ncontours >= 0) { /* simple case */
- draw_simple_glyf(g, glyph_list, glyphno, orgmatrix);
- return;
- }
-
- if(ISDBG(COMPOSITE) && level ==0)
- fprintf(stderr, "* %s [ %.2f %.2f %.2f %.2f %.2f %.2f ]\n", g->name,
- orgmatrix[0], orgmatrix[1], orgmatrix[2], orgmatrix[3],
- orgmatrix[4], orgmatrix[5]);
-
- /* complex case */
- if(level >= MAX_COMPOSITE_LEVEL) {
- WARNING_1 fprintf(stderr,
- "*** Glyph %s: stopped (possibly infinite) recursion at depth %d\n",
- g->name, level);
- return;
- }
-
- ptr = ((BYTE *) glyf_table + sizeof(TTF_GLYF));
- sptr = (SHORT *) ptr;
- do {
- flagbyte = ntohs(*sptr);
- sptr++;
- glyphindex = ntohs(*sptr);
- sptr++;
-
- if (flagbyte & ARG_1_AND_2_ARE_WORDS) {
- arg1 = (short)ntohs(*sptr);
- sptr++;
- arg2 = (short)ntohs(*sptr);
- sptr++;
- } else {
- bptr = (char *) sptr;
- arg1 = (signed char) bptr[0];
- arg2 = (signed char) bptr[1];
- sptr++;
- }
- matrix[1] = matrix[2] = 0.0;
-
- if (flagbyte & WE_HAVE_A_SCALE) {
- matrix[0] = matrix[3] = f2dot14(*sptr);
- sptr++;
- } else if (flagbyte & WE_HAVE_AN_X_AND_Y_SCALE) {
- matrix[0] = f2dot14(*sptr);
- sptr++;
- matrix[3] = f2dot14(*sptr);
- sptr++;
- } else if (flagbyte & WE_HAVE_A_TWO_BY_TWO) {
- matrix[0] = f2dot14(*sptr);
- sptr++;
- matrix[2] = f2dot14(*sptr);
- sptr++;
- matrix[1] = f2dot14(*sptr);
- sptr++;
- matrix[3] = f2dot14(*sptr);
- sptr++;
- } else {
- matrix[0] = matrix[3] = 1.0;
- }
-
- /*
- * See *
- * http://fonts.apple.com/TTRefMan/RM06/Chap6g
- * lyf.html * matrix[0,1,2,3,4,5]=a,b,c,d,m,n
- */
-
- if (fabs(matrix[0]) > fabs(matrix[1]))
- matrix[4] = fabs(matrix[0]);
- else
- matrix[4] = fabs(matrix[1]);
- if (fabs(fabs(matrix[0]) - fabs(matrix[2])) <= 33. / 65536.)
- matrix[4] *= 2.0;
-
- if (fabs(matrix[2]) > fabs(matrix[3]))
- matrix[5] = fabs(matrix[2]);
- else
- matrix[5] = fabs(matrix[3]);
- if (fabs(fabs(matrix[2]) - fabs(matrix[3])) <= 33. / 65536.)
- matrix[5] *= 2.0;
-
- /*
- * fprintf (stderr,"Matrix Opp %hd
- * %hd\n",arg1,arg2);
- */
-#if 0
- fprintf(stderr, "Matrix: %f %f %f %f %f %f\n",
- matrix[0], matrix[1], matrix[2], matrix[3],
- matrix[4], matrix[5]);
- fprintf(stderr, "Offset: %f %f (%s)\n",
- arg1, arg2,
- ((flagbyte & ARGS_ARE_XY_VALUES) ? "XY" : "index"));
-#endif
-
- if (flagbyte & ARGS_ARE_XY_VALUES) {
- matrix[4] *= arg1;
- matrix[5] *= arg2;
- } else {
- WARNING_1 fprintf(stderr,
- "*** Glyph %s: reusing scale from another glyph is unsupported\n",
- g->name);
- /*
- * must extract values from a glyph
- * but it seems to be too much pain
- * and it's not clear now that it
- * would be really used in any
- * interesting font
- */
- }
-
- /* at this point arg1,arg2 contain what logically should be matrix[4,5] */
-
- /* combine matrices */
-
- newmatrix[0] = orgmatrix[0]*matrix[0] + orgmatrix[2]*matrix[1];
- newmatrix[1] = orgmatrix[0]*matrix[2] + orgmatrix[2]*matrix[3];
-
- newmatrix[2] = orgmatrix[1]*matrix[0] + orgmatrix[3]*matrix[1];
- newmatrix[3] = orgmatrix[1]*matrix[2] + orgmatrix[3]*matrix[3];
-
- newmatrix[4] = orgmatrix[0]*matrix[4] + orgmatrix[2]*matrix[5] + orgmatrix[4];
- newmatrix[5] = orgmatrix[1]*matrix[4] + orgmatrix[3]*matrix[5] + orgmatrix[5];
-
- if(ISDBG(COMPOSITE)) {
- fprintf(stderr, "%*c+-> %2d %s [ %.2f %.2f %.2f %.2f %.2f %.2f ]\n",
- level+1, ' ', level, glyph_list[glyphindex].name,
- matrix[0], matrix[1], matrix[2], matrix[3],
- matrix[4], matrix[5]);
- fprintf(stderr, "%*c = [ %.2f %.2f %.2f %.2f %.2f %.2f ]\n",
- level+1, ' ',
- newmatrix[0], newmatrix[1], newmatrix[2], newmatrix[3],
- newmatrix[4], newmatrix[5]);
- }
- draw_composite_glyf(g, glyph_list, glyphindex, newmatrix, level+1);
-
- } while (flagbyte & MORE_COMPONENTS);
-}
-
-static void
-draw_simple_glyf(
- GLYPH *g,
- GLYPH *glyph_list,
- int glyphno,
- double *matrix
-)
-{
- int i, j, k, k1, len, first, cs, ce;
- /* We assume that hsbw always sets to(0, 0) */
- double xlast = 0, ylast = 0;
- int finished, nguide, contour_start, contour_end;
- short ncontours, n_inst, last_point;
- USHORT *contour_end_pt;
- BYTE *ptr;
-#define GLYFSZ 2000
- short xabs[GLYFSZ], yabs[GLYFSZ], xrel[GLYFSZ], yrel[GLYFSZ];
- double xcoord[GLYFSZ], ycoord[GLYFSZ];
- BYTE flags[GLYFSZ];
- double tx, ty;
- int needreverse = 0; /* transformation may require
- * that */
- GENTRY *lge;
-
- lge = g->lastentry;
-
- get_glyf_table(glyphno, &glyf_table, &len);
-
- if (len <= 0) {
- WARNING_1 fprintf(stderr,
- "**** Composite glyph %s refers to non-existent glyph %s, ignored\n",
- g->name,
- glyph_list[glyphno].name);
- return;
- }
- ncontours = ntohs(glyf_table->numberOfContours);
- if (ncontours < 0) {
- WARNING_1 fprintf(stderr,
- "**** Composite glyph %s refers to composite glyph %s, ignored\n",
- g->name,
- glyph_list[glyphno].name);
- return;
- }
- contour_end_pt = (USHORT *) ((char *) glyf_table + sizeof(TTF_GLYF));
-
- last_point = ntohs(contour_end_pt[ncontours - 1]);
- n_inst = ntohs(contour_end_pt[ncontours]);
-
- ptr = ((BYTE *) contour_end_pt) + (ncontours << 1) + n_inst + 2;
- j = k = 0;
- while (k <= last_point) {
- flags[k] = ptr[j];
-
- if (ptr[j] & REPEAT) {
- for (k1 = 0; k1 < ptr[j + 1]; k1++) {
- k++;
- flags[k] = ptr[j];
- }
- j++;
- }
- j++;
- k++;
- }
-
- for (k = 0; k <= last_point; k++) {
- if (flags[k] & XSHORT) {
- if (flags[k] & XSAME) {
- xrel[k] = ptr[j];
- } else {
- xrel[k] = -ptr[j];
- }
- j++;
- } else if (flags[k] & XSAME) {
- xrel[k] = 0.0;
- } else {
- xrel[k] = (short)( ptr[j] * 256 + ptr[j + 1] );
- j += 2;
- }
- if (k == 0) {
- xabs[k] = xrel[k];
- } else {
- xabs[k] = xrel[k] + xabs[k - 1];
- }
-
- }
-
- for (k = 0; k <= last_point; k++) {
- if (flags[k] & YSHORT) {
- if (flags[k] & YSAME) {
- yrel[k] = ptr[j];
- } else {
- yrel[k] = -ptr[j];
- }
- j++;
- } else if (flags[k] & YSAME) {
- yrel[k] = 0;
- } else {
- yrel[k] = ptr[j] * 256 + ptr[j + 1];
- j += 2;
- }
- if (k == 0) {
- yabs[k] = yrel[k];
- } else {
- yabs[k] = yrel[k] + yabs[k - 1];
- }
- }
-
- if (matrix) {
- for (i = 0; i <= last_point; i++) {
- tx = xabs[i];
- ty = yabs[i];
- xcoord[i] = fscale(matrix[0] * tx + matrix[2] * ty + matrix[4]);
- ycoord[i] = fscale(matrix[1] * tx + matrix[3] * ty + matrix[5]);
- }
- } else {
- for (i = 0; i <= last_point; i++) {
- xcoord[i] = fscale(xabs[i]);
- ycoord[i] = fscale(yabs[i]);
- }
- }
-
- i = j = 0;
- first = 1;
-
- while (i <= ntohs(contour_end_pt[ncontours - 1])) {
- contour_end = ntohs(contour_end_pt[j]);
-
- if (first) {
- fg_rmoveto(g, xcoord[i], ycoord[i]);
- xlast = xcoord[i];
- ylast = ycoord[i];
- contour_start = i;
- first = 0;
- } else if (flags[i] & ONOROFF) {
- fg_rlineto(g, xcoord[i], ycoord[i]);
- xlast = xcoord[i];
- ylast = ycoord[i];
- } else {
- cs = i - 1;
- finished = nguide = 0;
- while (!finished) {
- if (i == contour_end + 1) {
- ce = contour_start;
- finished = 1;
- } else if (flags[i] & ONOROFF) {
- ce = i;
- finished = 1;
- } else {
- i++;
- nguide++;
- }
- }
-
- switch (nguide) {
- case 0:
- fg_rlineto(g, xcoord[ce], ycoord[ce]);
- xlast = xcoord[ce];
- ylast = ycoord[ce];
- break;
-
- case 1:
- fg_rrcurveto(g,
- (xcoord[cs] + 2.0 * xcoord[cs + 1]) / 3.0,
- (ycoord[cs] + 2.0 * ycoord[cs + 1]) / 3.0,
- (2.0 * xcoord[cs + 1] + xcoord[ce]) / 3.0,
- (2.0 * ycoord[cs + 1] + ycoord[ce]) / 3.0,
- xcoord[ce],
- ycoord[ce]
- );
- xlast = xcoord[ce];
- ylast = ycoord[ce];
-
- break;
-
- case 2:
- fg_rrcurveto(g,
- (-xcoord[cs] + 4.0 * xcoord[cs + 1]) / 3.0,
- (-ycoord[cs] + 4.0 * ycoord[cs + 1]) / 3.0,
- (4.0 * xcoord[cs + 2] - xcoord[ce]) / 3.0,
- (4.0 * ycoord[cs + 2] - ycoord[ce]) / 3.0,
- xcoord[ce],
- ycoord[ce]
- );
- xlast = xcoord[ce];
- ylast = ycoord[ce];
- break;
-
- case 3:
- fg_rrcurveto(g,
- (xcoord[cs] + 2.0 * xcoord[cs + 1]) / 3.0,
- (ycoord[cs] + 2.0 * ycoord[cs + 1]) / 3.0,
- (5.0 * xcoord[cs + 1] + xcoord[cs + 2]) / 6.0,
- (5.0 * ycoord[cs + 1] + ycoord[cs + 2]) / 6.0,
- (xcoord[cs + 1] + xcoord[cs + 2]) / 2.0,
- (ycoord[cs + 1] + ycoord[cs + 2]) / 2.0
- );
-
- fg_rrcurveto(g,
- (xcoord[cs + 1] + 5.0 * xcoord[cs + 2]) / 6.0,
- (ycoord[cs + 1] + 5.0 * ycoord[cs + 2]) / 6.0,
- (5.0 * xcoord[cs + 2] + xcoord[cs + 3]) / 6.0,
- (5.0 * ycoord[cs + 2] + ycoord[cs + 3]) / 6.0,
- (xcoord[cs + 3] + xcoord[cs + 2]) / 2.0,
- (ycoord[cs + 3] + ycoord[cs + 2]) / 2.0
- );
-
- fg_rrcurveto(g,
- (xcoord[cs + 2] + 5.0 * xcoord[cs + 3]) / 6.0,
- (ycoord[cs + 2] + 5.0 * ycoord[cs + 3]) / 6.0,
- (2.0 * xcoord[cs + 3] + xcoord[ce]) / 3.0,
- (2.0 * ycoord[cs + 3] + ycoord[ce]) / 3.0,
- xcoord[ce],
- ycoord[ce]
- );
- ylast = ycoord[ce];
- xlast = xcoord[ce];
-
- break;
-
- default:
- k1 = cs + nguide;
- fg_rrcurveto(g,
- (xcoord[cs] + 2.0 * xcoord[cs + 1]) / 3.0,
- (ycoord[cs] + 2.0 * ycoord[cs + 1]) / 3.0,
- (5.0 * xcoord[cs + 1] + xcoord[cs + 2]) / 6.0,
- (5.0 * ycoord[cs + 1] + ycoord[cs + 2]) / 6.0,
- (xcoord[cs + 1] + xcoord[cs + 2]) / 2.0,
- (ycoord[cs + 1] + ycoord[cs + 2]) / 2.0
- );
-
- for (k = cs + 2; k <= k1 - 1; k++) {
- fg_rrcurveto(g,
- (xcoord[k - 1] + 5.0 * xcoord[k]) / 6.0,
- (ycoord[k - 1] + 5.0 * ycoord[k]) / 6.0,
- (5.0 * xcoord[k] + xcoord[k + 1]) / 6.0,
- (5.0 * ycoord[k] + ycoord[k + 1]) / 6.0,
- (xcoord[k] + xcoord[k + 1]) / 2.0,
- (ycoord[k] + ycoord[k + 1]) / 2.0
- );
-
- }
-
- fg_rrcurveto(g,
- (xcoord[k1 - 1] + 5.0 * xcoord[k1]) / 6.0,
- (ycoord[k1 - 1] + 5.0 * ycoord[k1]) / 6.0,
- (2.0 * xcoord[k1] + xcoord[ce]) / 3.0,
- (2.0 * ycoord[k1] + ycoord[ce]) / 3.0,
- xcoord[ce],
- ycoord[ce]
- );
- xlast = xcoord[ce];
- ylast = ycoord[ce];
-
- break;
- }
- }
- if (i >= contour_end) {
- g_closepath(g);
- first = 1;
- i = contour_end + 1;
- j++;
- } else {
- i++;
- }
- }
-
- if (matrix) {
- /* guess whether do we need to reverse the results */
-
- double x[3], y[3];
- int max = 0, from, to;
-
- /* transform a triangle going in proper direction */
- /*
- * the origin of triangle is in (0,0) so we know it in
- * advance
- */
-
- x[0] = y[0] = 0;
- x[1] = matrix[0] * 0 + matrix[2] * 300;
- y[1] = matrix[1] * 0 + matrix[3] * 300;
- x[2] = matrix[0] * 300 + matrix[2] * 0;
- y[2] = matrix[1] * 300 + matrix[3] * 0;
-
- /* then find the topmost point */
- for (i = 0; i < 3; i++)
- if (y[i] > y[max])
- max = i;
- from = (max + 3 - 1) % 3;
- to = (max + 1) % 3;
-
- needreverse = 0;
-
- /* special cases for horizontal lines */
- if (y[max] == y[from]) {
- if (x[max] < y[from])
- needreverse = 1;
- } else if (y[to] == y[from]) {
- if (x[to] < x[max])
- needreverse = 1;
- } else { /* generic case */
- if ((x[to] - x[max]) * (y[max] - y[from])
- > (x[max] - x[from]) * (y[to] - y[max]))
- needreverse = 1;
- }
-
- if (needreverse) {
- if (lge) {
- assertpath(lge->next, __FILE__, __LINE__, g->name);
- reversepathsfromto(lge->next, NULL);
- } else {
- assertpath(g->entries, __FILE__, __LINE__, g->name);
- reversepaths(g);
- }
- }
- }
-}
-
-static double
-f2dot14(
- short x
-)
-{
- short y = ntohs(x);
- return (y >> 14) + ((y & 0x3fff) / 16384.0);
-}
-
-
-/* check that the pointer points within the file */
-/* returns 0 if pointer is good, 1 if bad */
-static int
-badpointer(
- void *ptr
-)
-{
- return (ptr < (void *)filebuffer || ptr >= (void *)filebuffer_end);
-}
-
-/*
- * Externally accessible methods
- */
-
-/*
- * Open font and prepare to return information to the main driver.
- * May print error and warning messages.
- * Exit on error.
- */
-
-static void
-openfont(
- char *fname,
- char *arg /* unused now */
-)
-{
- int i, j;
- struct stat statbuf;
- static struct {
- void **tbpp; /* pointer to pointer to the table */
- char name[5]; /* table name */
- char optional; /* flag: table may be missing */
- } tables[] = {
- { (void **)&name_table, "name", 0 },
- { (void **)&head_table, "head", 0 },
- { (void **)&hhea_table, "hhea", 0 },
- { (void **)&post_table, "post", 0 },
- { (void **)&glyf_start, "glyf", 0 },
- { (void **)&cmap_table, "cmap", 0 },
- { (void **)&kern_table, "kern", 1 },
- { (void **)&maxp_table, "maxp", 0 },
- { (void **)&hmtx_table, "hmtx", 0 },
- { (void **)&long_loca_table, "loca", 0 },
- { NULL, "", 0 } /* end of table */
- };
-
- if (stat(fname, &statbuf) == -1) {
- fprintf(stderr, "**** Cannot access %s ****\n", fname);
- exit(1);
- }
- if ((filebuffer = malloc(statbuf.st_size)) == NULL) {
- fprintf(stderr, "**** Cannot malloc space for file ****\n");
- exit(1);
- }
-
- filebuffer_end = filebuffer + statbuf.st_size;
-
- if ((ttf_file = fopen(fname, "rb")) == NULL) {
- fprintf(stderr, "**** Cannot open file '%s'\n", fname);
- exit(1);
- } else {
- WARNING_2 fprintf(stderr, "Processing file %s\n", fname);
- }
-
- if (fread(filebuffer, 1, statbuf.st_size, ttf_file) != statbuf.st_size) {
- fprintf(stderr, "**** Could not read whole file \n");
- exit(1);
- }
- fclose(ttf_file);
-
- directory = (TTF_DIRECTORY *) filebuffer;
-
- if (ntohl(directory->sfntVersion) != 0x00010000) {
- fprintf(stderr,
- "**** Unknown File Version number [%x], or not a TrueType file\n",
- directory->sfntVersion);
- exit(1);
- }
-
- /* clear the tables */
- for(j=0; tables[j].tbpp != NULL; j++)
- *(tables[j].tbpp) = NULL;
-
- dir_entry = &(directory->list);
-
- for (i = 0; i < ntohs(directory->numTables); i++) {
-
- for(j=0; tables[j].tbpp != NULL; j++)
- if (memcmp(dir_entry->tag, tables[j].name, 4) == 0) {
- *(tables[j].tbpp) = (void *) (filebuffer + ntohl(dir_entry->offset));
- break;
- }
-
- if (memcmp(dir_entry->tag, "EBDT", 4) == 0 ||
- memcmp(dir_entry->tag, "EBLC", 4) == 0 ||
- memcmp(dir_entry->tag, "EBSC", 4) == 0) {
- WARNING_1 fprintf(stderr, "Font contains bitmaps\n");
- }
- dir_entry++;
- }
-
- for(j=0; tables[j].tbpp != NULL; j++)
- if(!tables[j].optional && badpointer( *(tables[j].tbpp) )) {
- fprintf(stderr, "**** File contains no required table '%s'\n", tables[j].name);
- exit(1);
- }
-
- handle_name();
-
- handle_head();
-
- ttf_nglyphs = ntohs(maxp_table->numGlyphs);
-
- enc_found_ms = enc_found_mac = 0;
-}
-
-/*
- * Close font.
- * Exit on error.
- */
-
-static void
-closefont(
- void
-)
-{
- return; /* empty operation */
-}
-
-/*
- * Get the number of glyphs in font.
- */
-
-static int
-getnglyphs (
- void
-)
-{
- return ttf_nglyphs;
-}
-
-/*
- * Get the names of the glyphs.
- * Returns 0 if the names were assigned, non-zero if the font
- * provides no glyph names.
- */
-
-static int
-glnames(
- GLYPH *glyph_list
-)
-{
- int i, len, n, npost;
- unsigned int format;
- USHORT *name_index;
- char *ptr, *p;
- char **ps_name_ptr = (char **) malloc(ttf_nglyphs * sizeof(char *));
- int n_ps_names;
- int ps_fmt_3 = 0;
-
- format = ntohl(post_table->formatType);
-
- if (format == 0x00010000) {
- for (i = 0; i < 258 && i < ttf_nglyphs; i++) {
- glyph_list[i].name = mac_glyph_names[i];
- }
- } else if (format == 0x00020000) {
- npost = ntohs(post_table->numGlyphs);
- if (ttf_nglyphs != npost) {
- /* This is an error in the font, but we can now cope */
- WARNING_1 fprintf(stderr, "**** Postscript table size mismatch %d/%d ****\n",
- npost, ttf_nglyphs);
- }
- n_ps_names = 0;
- name_index = &(post_table->glyphNameIndex);
-
- /* This checks the integrity of the post table */
- for (i=0; i<npost; i++) {
- n = ntohs(name_index[i]);
- if (n > n_ps_names + 257) {
- n_ps_names = n - 257;
- }
- }
-
- ptr = (char *) post_table + 34 + (ttf_nglyphs << 1);
- i = 0;
- while (*ptr > 0 && i < n_ps_names) {
- len = *ptr;
- /* previously the program wrote nulls into the table. If the table
- was corrupt, this could put zeroes anywhere, leading to obscure bugs,
- so now I malloc space for the names. Yes it is much less efficient */
-
- if ((p = malloc(len+1)) == NULL) {
- fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__);
- exit(255);
- }
-
- ps_name_ptr[i] = p;
- strncpy(p, ptr+1, len);
- p[len] = '\0';
- i ++;
- ptr += len + 1;
- }
-
- if (i != n_ps_names)
- {
- WARNING_2 fprintf (stderr, "** Postscript Name mismatch %d != %d **\n",
- i, n_ps_names);
- n_ps_names = i;
- }
-
- /*
- * for (i=0; i<n_ps_names; i++) { fprintf(stderr, "i=%d,
- * len=%d, name=%s\n", i, ps_name_len[i], ps_name_ptr[i]); }
- */
-
- for (i = 0; i < npost; i++) {
- n = ntohs(name_index[i]);
- if (n < 258) {
- glyph_list[i].name = mac_glyph_names[n];
- } else if (n < 258 + n_ps_names) {
- glyph_list[i].name = ps_name_ptr[n - 258];
- } else {
- glyph_list[i].name = malloc(16);
- sprintf(glyph_list[i].name, "_g_%d", i);
- WARNING_2 fprintf(stderr,
- "Glyph No. %d has no postscript name, becomes %s\n",
- i, glyph_list[i].name);
- }
- }
- /* Now fake postscript names for all those beyond the end of the table */
- if (npost < ttf_nglyphs) {
- for (i=npost; i<ttf_nglyphs; i++) {
- if ((glyph_list[i].name = malloc(16)) == NULL)
- {
- fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__);
- exit(255);
- }
- sprintf(glyph_list[i].name, "_g_%d", i);
- WARNING_2 fprintf(stderr,
- "Glyph No. %d has no postscript name, becomes %s\n",
- i, glyph_list[i].name);
- }
- }
- } else if (format == 0x00030000) {
- WARNING_3 fputs("No postscript table, using default\n", stderr);
- ps_fmt_3 = 1;
- } else if (format == 0x00028000) {
- ptr = (char *) &(post_table->numGlyphs);
- for (i = 0; i < ttf_nglyphs; i++) {
- glyph_list[i].name = mac_glyph_names[i + ptr[i]];
- }
- } else {
- fprintf(stderr,
- "**** Postscript table in wrong format %x ****\n",
- format);
- exit(1);
- }
-
- return ps_fmt_3;
-}
-
-/*
- * Get the metrics of the glyphs.
- */
-
-static void
-glmetrics(
- GLYPH *glyph_list
-)
-{
- int i;
- int n_hmetrics = ntohs(hhea_table->numberOfHMetrics);
- GLYPH *g;
- LONGHORMETRIC *hmtx_entry = hmtx_table;
- FWORD *lsblist;
-
- for (i = 0; i < n_hmetrics; i++) {
- g = &(glyph_list[i]);
- g->width = ntohs(hmtx_entry->advanceWidth);
- g->lsb = ntohs(hmtx_entry->lsb);
- hmtx_entry++;
- }
-
- lsblist = (FWORD *) hmtx_entry;
- hmtx_entry--;
-
- for (i = n_hmetrics; i < ttf_nglyphs; i++) {
- g = &(glyph_list[i]);
- g->width = ntohs(hmtx_entry->advanceWidth);
- g->lsb = ntohs(lsblist[i - n_hmetrics]);
- }
-
- for (i = 0; i < ttf_nglyphs; i++) {
- g = &(glyph_list[i]);
- get_glyf_table(i, &glyf_table, &g->ttf_pathlen);
-
- g->xMin = (short)ntohs(glyf_table->xMin);
- g->xMax = (short)ntohs(glyf_table->xMax);
- g->yMin = (short)ntohs(glyf_table->yMin);
- g->yMax = (short)ntohs(glyf_table->yMax);
- }
-
-}
-
-
-static void
-handle_ms_encoding(
- GLYPH *glyph_list,
- int *encoding,
- int *unimap
-)
-{
- int j, k, kk, set_ok;
- USHORT start, end, ro;
- short delta, n;
-
- for (j = 0; j < cmap_n_segs - 1; j++) {
- start = ntohs(cmap_seg_start[j]);
- end = ntohs(cmap_seg_end[j]);
- delta = ntohs(cmap_idDelta[j]);
- ro = ntohs(cmap_idRangeOffset[j]);
-
- for (k = start; k <= end; k++) {
- if (ro == 0) {
- n = k + delta;
- } else {
- n = ntohs(*((ro >> 1) + (k - start) +
- &(cmap_idRangeOffset[j])));
- if (delta != 0)
- {
- /* Not exactly sure how to deal with this circumstance,
- I suspect it never occurs */
- n += delta;
- fprintf (stderr,
- "rangeoffset and delta both non-zero - %d/%d",
- ro, delta);
- }
- }
- if(n<0 || n>=ttf_nglyphs) {
- WARNING_1 fprintf(stderr, "Font contains a broken glyph code mapping, ignored\n");
- continue;
- }
- if (glyph_list[n].orig_code != -1) {
-#if 0
- if (strcmp(glyph_list[n].name, ".notdef") != 0) {
- WARNING_2 fprintf(stderr,
- "Glyph %s has >= two encodings (A), %4.4x & %4.4x\n",
- glyph_list[n].name,
- glyph_list[n].orig_code,
- k);
- }
-#endif
- set_ok = 0;
- } else {
- set_ok = 1;
- }
- if (enc_type==1 || forcemap) {
- kk = unicode_rev_lookup(k);
- if(ISDBG(UNICODE))
- fprintf(stderr, "Unicode %s - 0x%04x\n",glyph_list[n].name,k);
- if (set_ok) {
- glyph_list[n].orig_code = k;
- /* glyph_list[n].char_no = kk; */
- }
- if (kk >= 0 && kk < ENCTABSZ && encoding[kk] == -1)
- encoding[kk] = n;
- } else {
- if ((k & 0xff00) == 0xf000) {
- if( encoding[k & 0x00ff] == -1 ) {
- encoding[k & 0x00ff] = n;
- if (set_ok) {
- /* glyph_list[n].char_no = k & 0x00ff; */
- glyph_list[n].orig_code = k;
- }
- }
- } else {
- if (set_ok) {
- /* glyph_list[n].char_no = k; */
- glyph_list[n].orig_code = k;
- }
- WARNING_2 fprintf(stderr,
- "Glyph %s has non-symbol encoding %4.4x\n",
- glyph_list[n].name,
- k & 0xffff);
- /*
- * just use the code
- * as it is
- */
- if ((k & ~0xff) == 0 && encoding[k] == -1 )
- encoding[k] = n;
- }
- }
- }
- }
-}
-
-static void
-handle_mac_encoding(
- GLYPH *glyph_list,
- int *encoding,
- int *unimap
-)
-{
- short n;
- int j, size;
-
- size = ntohs(encoding0->length) - 6;
- for (j = 0; j < size; j++) {
- n = encoding0->glyphIdArray[j];
- if (glyph_list[n].char_no != -1) {
- WARNING_2 fprintf(stderr,
- "Glyph %s has >= two encodings (B), %4.4x & %4.4x\n",
- glyph_list[n].name,
- glyph_list[n].char_no,
- j);
- } else {
- if (j < ENCTABSZ) {
- if(encoding[j] == -1) {
- glyph_list[n].char_no = j;
- encoding[j] = n;
- }
- }
- }
- }
-}
-
-/*
- * Get the original encoding of the font.
- * Returns 1 for if the original encoding is Unicode, 2 if the
- * original encoding is other 16-bit, 0 if 8-bit.
- */
-
-static int
-glenc(
- GLYPH *glyph_list,
- int *encoding,
- int *unimap
-)
-{
- int num_tables = ntohs(cmap_table->numberOfEncodingTables);
- BYTE *ptr;
- int i, format, offset, seg_c2, found;
- int platform, encoding_id;
- TTF_CMAP_ENTRY *table_entry;
- TTF_CMAP_FMT4 *encoding4;
-
- if(enc_found_ms) {
- handle_ms_encoding(glyph_list, encoding, unimap);
- return enc_type;
- } else if(enc_found_mac) {
- handle_mac_encoding(glyph_list, encoding, unimap);
- return 0;
- }
-
- if(force_pid != -1 && force_pid != 3) {
- fputs("*** Only platform ID == 3 is supported\n", stderr);
- exit(1);
- }
-
- enc_type = 0;
- found = 0;
-
- for (i = 0; i < num_tables && !found; i++) {
- table_entry = &(cmap_table->encodingTable[i]);
- offset = ntohl(table_entry->offset);
- encoding4 = (TTF_CMAP_FMT4 *) ((BYTE *) cmap_table + offset);
- format = ntohs(encoding4->format);
- platform = ntohs(table_entry->platformID);
- encoding_id = ntohs(table_entry->encodingID);
-
- if (platform == 3 && format == 4) {
- if(force_pid == 3) {
- if(encoding_id != force_eid)
- continue;
- WARNING_1 fprintf(stderr, "Found Encoding PID=%d/EID=%d\n",
- force_pid, force_eid);
- enc_type = 1;
- } else {
- switch (encoding_id) {
- case 0:
- WARNING_1 fputs("Found Symbol Encoding\n", stderr);
- break;
- case 1:
- WARNING_1 fputs("Found Unicode Encoding\n", stderr);
- enc_type = 1;
- break;
- default:
- WARNING_1 {
- fprintf(stderr,
- "****MS Encoding ID %d not supported****\n",
- encoding_id);
- fputs("Treating it like Symbol encoding\n", stderr);
- }
- break;
- }
- }
-
- found = 1;
- seg_c2 = ntohs(encoding4->segCountX2);
- cmap_n_segs = seg_c2 >> 1;
- ptr = (BYTE *) encoding4 + 14;
- cmap_seg_end = (USHORT *) ptr;
- cmap_seg_start = (USHORT *) (ptr + seg_c2 + 2);
- cmap_idDelta = (short *) (ptr + (seg_c2 * 2) + 2);
- cmap_idRangeOffset = (short *) (ptr + (seg_c2 * 3) + 2);
- enc_found_ms = 1;
-
- handle_ms_encoding(glyph_list, encoding, unimap);
- }
- }
-
- if (!found) {
- if(force_pid != -1) {
- fprintf(stderr, "*** TTF encoding table PID=%d/EID=%d not found\n",
- force_pid, force_eid);
- exit(1);
- }
-
- WARNING_1 fputs("No Microsoft encoding, looking for MAC encoding\n", stderr);
- for (i = 0; i < num_tables && !found; i++) {
- table_entry = &(cmap_table->encodingTable[i]);
- offset = ntohl(table_entry->offset);
- encoding0 = (TTF_CMAP_FMT0 *) ((BYTE *) cmap_table + offset);
- format = ntohs(encoding0->format);
- platform = ntohs(table_entry->platformID);
- encoding_id = ntohs(table_entry->encodingID);
-
- if (format == 0) {
- found = 1;
- enc_found_mac = 1;
-
- handle_mac_encoding(glyph_list, encoding, unimap);
- }
- }
- }
- if (!found) {
- fprintf(stderr, "**** No Recognised Encoding Table ****\n");
- exit(1);
- }
-
- return enc_type;
-}
-
-/*
- * Get the font metrics
- */
-static void
-fnmetrics(
- struct font_metrics *fm
-)
-{
- char *str;
- static int fieldstocheck[]= {2,4,6};
- int i, j, len;
-
- fm->italic_angle = (short) (ntohs(post_table->italicAngle.upper)) +
- ((short) ntohs(post_table->italicAngle.lower) / 65536.0);
- fm->underline_position = (short) ntohs(post_table->underlinePosition);
- fm->underline_thickness = (short) ntohs(post_table->underlineThickness);
- fm->is_fixed_pitch = ntohl(post_table->isFixedPitch);
-
- fm->ascender = (short)ntohs(hhea_table->ascender);
- fm->descender = (short)ntohs(hhea_table->descender);
-
- fm->units_per_em = ntohs(head_table->unitsPerEm);
-
- fm->bbox[0] = (short) ntohs(head_table->xMin);
- fm->bbox[1] = (short) ntohs(head_table->yMin);
- fm->bbox[2] = (short) ntohs(head_table->xMax);
- fm->bbox[3] = (short) ntohs(head_table->yMax);
-
- fm->name_copyright = name_fields[0];
- fm->name_family = name_fields[1];
- fm->name_style = name_fields[2];
- fm->name_full = name_fields[4];
- fm->name_version = name_fields[5];
- fm->name_ps = name_fields[6];
-
- /* guess the boldness from the font names */
- fm->force_bold=0;
-
- for(i=0; !fm->force_bold && i<sizeof fieldstocheck /sizeof(int); i++) {
- str = name_fields[fieldstocheck[i]];
- len = strlen(str);
- for(j=0; j<len; j++) {
- if( (str[j]=='B'
- || str[j]=='b'
- && ( j==0 || !isalpha(str[j-1]) )
- )
- && !strncmp("old",&str[j+1],3)
- && (j+4 >= len || !islower(str[j+4]))
- ) {
- fm->force_bold=1;
- break;
- }
- }
- }
-}
-
-/*
- * Get the path of contrours for a glyph.
- */
-
-static void
-glpath(
- int glyphno,
- GLYPH *glyf_list
-)
-{
- double matrix[6];
- GLYPH *g;
-
- g = &glyph_list[glyphno];
-
- matrix[0] = matrix[3] = 1.0;
- matrix[1] = matrix[2] = matrix[4] = matrix[5] = 0.0;
- draw_composite_glyf(g, glyf_list, glyphno, matrix, 0 /*level*/);
-}
-
-/*
- * Get the kerning data.
- */
-
-static void
-kerning(
- GLYPH *glyph_list
-)
-{
- TTF_KERN_SUB *subtable;
- TTF_KERN_ENTRY *kern_entry;
- int i, j;
- int ntables;
- int npairs;
- char *ptr;
-
- if(kern_table == NULL) {
- WARNING_1 fputs("No Kerning data\n", stderr);
- return;
- }
- if(badpointer(kern_table)) {
- fputs("**** Defective Kerning table, ignored\n", stderr);
- return;
- }
-
- ntables = ntohs(kern_table->nTables);
- ptr = (char *) kern_table + 4;
-
- for (i = 0; i < ntables; i++) {
- subtable = (TTF_KERN_SUB *) ptr;
- if ((ntohs(subtable->coverage) & 0xff00) == 0) {
- npairs = (short) ntohs(subtable->nPairs);
- kern_entry = (TTF_KERN_ENTRY *) (ptr + sizeof(TTF_KERN_SUB));
-
- kern_entry = (TTF_KERN_ENTRY *) (ptr + sizeof(TTF_KERN_SUB));
- for (j = 0; j < npairs; j++) {
- if( kern_entry->value != 0)
- addkernpair(ntohs(kern_entry->left),
- ntohs(kern_entry->right), (short)ntohs(kern_entry->value));
- kern_entry++;
- }
- }
- ptr += subtable->length;
- }
-}
-
+++ /dev/null
-/*
- * see COPYRIGHT
- */
-
-/* these definitions are mostly taken from Microsoft's True Type
- documentation.
-*/
-
-#define BYTE unsigned char
-#define CHAR signed char
-#define USHORT unsigned short
-#define SHORT signed short
-#define ULONG unsigned int
-#define LONG signed int
-#define FWORD SHORT
-#define UFWORD USHORT
-
-#define ONOROFF 0x01
-#define XSHORT 0x02
-#define YSHORT 0x04
-#define REPEAT 0x08
-#define XSAME 0x10
-#define YSAME 0x20
-
-#define ARG_1_AND_2_ARE_WORDS 0x0001
-#define ARGS_ARE_XY_VALUES 0x0002
-#define XY_BOUND_TO_GRID 0x0004
-#define WE_HAVE_A_SCALE 0x0008
-#define MORE_COMPONENTS 0x0020
-#define WE_HAVE_AN_X_AND_Y_SCALE 0x0040
-#define WE_HAVE_A_TWO_BY_TWO 0x0080
-#define WE_HAVE_INSTRUCTIONS 0x0100
-#define USE_MY_METRICS 0x0200
-
-typedef struct short_2 {
- SHORT upper;
- USHORT lower;
-} TTF2PT1_FIXED ;
-
-typedef struct longhormetric {
- UFWORD advanceWidth;
- FWORD lsb;
-} LONGHORMETRIC;
-
-typedef struct ttf_hhea {
- BYTE version[4];
- SHORT ascender, descender, lineGap;
- USHORT advnaceWidthMax;
- SHORT minLSB, minRSB, xMaxExtent;
- SHORT caretSlopeRise, caretSlopeRun;
- SHORT reserved[5];
- SHORT metricDataFormat;
- USHORT numberOfHMetrics;
-} TTF_HHEA;
-
-typedef struct ttf_dir_entry {
- char tag[4];
- ULONG checksum;
- ULONG offset;
- ULONG length;
-} TTF_DIR_ENTRY ;
-
-typedef struct ttf_directory {
- ULONG sfntVersion;
- USHORT numTables;
- USHORT searchRange;
- USHORT entrySelector;
- USHORT rangeShift;
- TTF_DIR_ENTRY list;
-} TTF_DIRECTORY ;
-
-typedef struct ttf_name_rec {
- USHORT platformID;
- USHORT encodingID;
- USHORT languageID;
- USHORT nameID;
- USHORT stringLength;
- USHORT stringOffset;
-} TTF_NAME_REC;
-
-typedef struct ttf_name {
- USHORT format;
- USHORT numberOfNameRecords;
- USHORT offset;
- TTF_NAME_REC nameRecords;
-} TTF_NAME ;
-
-typedef struct ttf_head {
- ULONG version;
- ULONG fontRevision;
- ULONG checksumAdjust;
- ULONG magicNo;
- USHORT flags;
- USHORT unitsPerEm;
- BYTE created[8];
- BYTE modified[8];
- FWORD xMin, yMin, xMax, yMax;
- USHORT macStyle, lowestRecPPEM;
- SHORT fontDirection, indexToLocFormat, glyphDataFormat;
-} TTF_HEAD ;
-
-typedef struct ttf_kern {
- USHORT version, nTables;
-} TTF_KERN ;
-
-typedef struct ttf_kern_sub {
- USHORT version, length, coverage;
- USHORT nPairs, searchRange, entrySelector, rangeShift;
-} TTF_KERN_SUB;
-
-typedef struct ttf_kern_entry {
- USHORT left, right;
- FWORD value;
-} TTF_KERN_ENTRY;
-
-typedef struct ttf_cmap_fmt0 {
- USHORT format;
- USHORT length;
- USHORT version;
- BYTE glyphIdArray[256];
-} TTF_CMAP_FMT0;
-
-typedef struct ttf_cmap_fmt4 {
- USHORT format;
- USHORT length;
- USHORT version;
- USHORT segCountX2;
- USHORT searchRange;
- USHORT entrySelector;
- USHORT rangeShift;
-} TTF_CMAP_FMT4;
-
-typedef struct ttf_cmap_entry {
- USHORT platformID;
- USHORT encodingID;
- ULONG offset;
-} TTF_CMAP_ENTRY;
-
-typedef struct ttf_cmap {
- USHORT version;
- USHORT numberOfEncodingTables;
- TTF_CMAP_ENTRY encodingTable[1];
-} TTF_CMAP ;
-
-typedef struct ttf_glyf {
- SHORT numberOfContours;
- FWORD xMin, yMin, xMax, yMax;
-} TTF_GLYF ;
-
-typedef struct ttf_maxp {
- ULONG version;
- USHORT numGlyphs, maxPoints, maxContours;
- USHORT maxCompositePoints, maxCompositeContours;
- USHORT maxZones, maxTwilightPoints, maxStorage;
- USHORT maxFunctionDefs, maxInstructionsDefs;
- USHORT maxSizeOfInstructions, maxComponentElements;
- USHORT maxComponentDepth;
-} TTF_MAXP ;
-
-typedef struct ttf_post_head {
- ULONG formatType;
- TTF2PT1_FIXED italicAngle;
- FWORD underlinePosition;
- FWORD underlineThickness;
- ULONG isFixedPitch;
- ULONG minMemType42;
- ULONG maxMemType42;
- ULONG minMemType1;
- ULONG maxMemType1;
- USHORT numGlyphs;
- USHORT glyphNameIndex;
-} TTF_POST_HEAD ;
+++ /dev/null
-/*
- * True Type Font to Adobe Type 1 font converter
- * By Mark Heath <mheath@netspace.net.au>
- * Based on ttf2pfa by Andrew Weeks <ccsaw@bath.ac.uk>
- * With help from Frank M. Siegert <fms@this.net>
- *
- * see COPYRIGHT for full copyright notice
- *
-***********************************************************************
- *
- * Sergey Babkin <babkin@users.sourceforge.net>, <sab123@hotmail.com>
- *
- * Added post-processing of resulting outline to correct the errors
- * both introduced during conversion and present in the original font,
- * autogeneration of hints (has yet to be improved though) and BlueValues,
- * scaling to 1000x1000 matrix, option to print the result on STDOUT,
- * support of Unicode to CP1251 conversion, optimization of the
- * resulting font code by space (that improves the speed too). Excluded
- * the glyphs that are unaccessible through the encoding table from
- * the output file. Added the built-in Type1 assembler (taken from
- * the `t1utils' package).
- *
-***********************************************************************
- *
- * Thomas Henlich <thenlich@rcs.urz.tu-dresden.de>
- *
- * Added generation of .afm file (font metrics)
- * Read encoding information from encoding description file
- * Fixed bug in error message about unknown language ('-l' option)
- * Added `:' after %%!PS-AdobeFont-1.0
- * changed unused entries in ISOLatin1Encoding[] from .notdef to c127,c128...
- *
-***********************************************************************
- *
- * Thomas Henlich <thenlich@rcs.urz.tu-dresden.de>
- *
- * Added generation of .afm file (font metrics)
- *
-***********************************************************************
- *
- * Bug Fixes:
-************************************************************************
- *
- * Sun, 21 Jun 1998 Thomas Henlich <thenlich@Rcs1.urz.tu-dresden.de>
- * 1. "width" should be "short int" because otherwise:
- * characters with negative widths (e.g. -4) become *very* wide (65532)
- * 2. the number of /CharStrings is numglyphs and not numglyphs+1
- *
-***********************************************************************
- *
- *
- *
- * The resultant font file produced by this program still needs to be ran
- * through t1asm (from the t1utils archive) to produce a completely valid
- * font.
- *
- */
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <time.h>
-#include <ctype.h>
-#include <math.h>
-
-#include "../../config.h"
-
-#ifdef _GNU_SOURCE
-#include <getopt.h>
-#endif
-
-#ifndef WIN32
-# include <unistd.h>
-# include <netinet/in.h>
-# define BITBUCKET "/dev/null"
-# include <sys/wait.h>
-#else
-# define WINDOWS_FUNCTIONS /* ask to define functions - in one file only */
-# include "win_missing.h"
-# define BITBUCKET "NUL"
-#endif
-
-#include "pt1.h"
-#include "global.h"
-#include "version.h"
-
-/* globals */
-
-/* table of front-ends */
-
-extern struct frontsw ttf_sw;
-extern struct frontsw bdf_sw;
-#if defined(USE_FREETYPE)
- extern struct frontsw freetype_sw;
-#endif
-
-struct frontsw *frontswtab[] = {
- &bdf_sw,
-#if defined(USE_FREETYPE) && defined(PREFER_FREETYPE)
- &freetype_sw,
-#endif
- &ttf_sw,
-#if defined(USE_FREETYPE) && !defined(PREFER_FREETYPE)
- &freetype_sw,
-#endif
- NULL /* end of table */
-};
-
-#ifdef WIN32
-#define NOPIPES
-#else
-#undef NOPIPES
-#endif
-
-struct frontsw *cursw=0; /* the active front end */
-char *front_arg=""; /* optional argument */
-
-/* options */
-int encode = 0; /* encode the resulting file */
-int pfbflag = 0; /* produce compressed file */
-int wantafm=0; /* want to see .afm instead of .t1a on stdout */
-int correctvsize=0; /* try to correct the vertical size of characters */
-int wantuid = 0; /* user wants UniqueID entry in the font */
-int allglyphs = 0; /* convert all glyphs, not only 256 of them */
-int warnlevel = 3; /* the level of permitted warnings */
-int forcemap = 0; /* do mapping even on non-Unicode fonts */
-/* options - maximal limits */
-int max_stemdepth = 128; /* maximal depth of stem stack in interpreter (128 - limit from X11) */
-/* options - debugging */
-int absolute = 0; /* print out in absolute values */
-int reverse = 1; /* reverse font to Type1 path directions */
-/* options - suboptions of Outline Processing, defaults are set in table */
-int optimize; /* enables space optimization */
-int smooth; /* enable smoothing of outlines */
-int transform; /* enables transformation to 1000x1000 matrix */
-int hints; /* enables autogeneration of hints */
-int subhints; /* enables autogeneration of substituted hints */
-int trybold; /* try to guess whether the font is bold */
-int correctwidth; /* try to correct the character width */
-int vectorize; /* vectorize the bitmaps */
-int use_autotrace; /* use the autotrace library on bitmap */
-/* options - suboptions of File Generation, defaults are set in table */
-int gen_pfa; /* generate the font file */
-int gen_afm; /* generate the metrics file */
-int gen_dvienc; /* generate the dvips encoding file */
-
-/* not quite options to select a particular source encoding */
-int force_pid = -1; /* specific platform id */
-int force_eid = -1; /* specific encoding id */
-
-/* structure to define the sub-option lists controlled by the
- * case: uppercase enables them, lowercase disables
- */
-struct subo_case {
- char disbl; /* character to disable - enforced lowercase */
- char enbl; /* character to enable - auto-set as toupper(disbl) */
- int *valp; /* pointer to the actual variable containing value */
- int dflt; /* default value */
- char *descr; /* description */
-};
-
-int debug = DEBUG; /* debugging flag */
-
-FILE *null_file, *pfa_file, *afm_file, *dvienc_file;
-int numglyphs;
-struct font_metrics fontm;
-
-/* non-globals */
-static char *strUID = 0; /* user-supplied UniqueID */
-static unsigned long numUID; /* auto-generated UniqueID */
-
-static int ps_fmt_3 = 0;
-static double scale_factor, original_scale_factor;
-
-static char *glyph_rename[ENCTABSZ];
-
-/* the names assigned if the original font
- * does not specify any
- */
-
-static char *Fmt3Encoding[256] = {
- "c0", "c1", "c2", "c3",
- "c4", "c5", "c6", "c7",
- "c8", "c9", "c10", "c11",
- "c12", "CR", "c14", "c15",
- "c16", "c17", "c18", "c19",
- "c20", "c21", "c22", "c23",
- "c24", "c25", "c26", "c27",
- "c28", "c29", "c30", "c31",
- "space", "exclam", "quotedbl", "numbersign",
- "dollar", "percent", "ampersand", "quotesingle",
- "parenleft", "parenright", "asterisk", "plus",
- "comma", "hyphen", "period", "slash",
- "zero", "one", "two", "three",
- "four", "five", "six", "seven",
- "eight", "nine", "colon", "semicolon",
- "less", "equal", "greater", "question",
- "at", "A", "B", "C",
- "D", "E", "F", "G",
- "H", "I", "J", "K",
- "L", "M", "N", "O",
- "P", "Q", "R", "S",
- "T", "U", "V", "W",
- "X", "Y", "Z", "bracketleft",
- "backslash", "bracketright", "asciicircum", "underscore",
- "grave", "a", "b", "c",
- "d", "e", "f", "g",
- "h", "i", "j", "k",
- "l", "m", "n", "o",
- "p", "q", "r", "s",
- "t", "u", "v", "w",
- "x", "y", "z", "braceleft",
- "bar", "braceright", "asciitilde", "c127",
- "c128", "c129", "quotesinglbase", "florin",
- "quotedblbase", "ellipsis", "dagger", "daggerdbl",
- "circumflex", "perthousand", "Scaron", "guilsinglleft",
- "OE", "c141", "c142", "c143",
- "c144", "quoteleft", "quoteright", "quotedblleft",
- "quotedblright", "bullet", "endash", "emdash",
- "tilde", "trademark", "scaron", "guilsinglright",
- "oe", "c157", "c158", "Ydieresis",
- "nbspace", "exclamdown", "cent", "sterling",
- "currency", "yen", "brokenbar", "section",
- "dieresis", "copyright", "ordfeminine", "guillemotleft",
- "logicalnot", "sfthyphen", "registered", "macron",
- "degree", "plusminus", "twosuperior", "threesuperior",
- "acute", "mu", "paragraph", "periodcentered",
- "cedilla", "onesuperior", "ordmasculine", "guillemotright",
- "onequarter", "onehalf", "threequarters", "questiondown",
- "Agrave", "Aacute", "Acircumflex", "Atilde",
- "Adieresis", "Aring", "AE", "Ccedilla",
- "Egrave", "Eacute", "Ecircumflex", "Edieresis",
- "Igrave", "Iacute", "Icircumflex", "Idieresis",
- "Eth", "Ntilde", "Ograve", "Oacute",
- "Ocircumflex", "Otilde", "Odieresis", "multiply",
- "Oslash", "Ugrave", "Uacute", "Ucircumflex",
- "Udieresis", "Yacute", "Thorn", "germandbls",
- "agrave", "aacute", "acircumflex", "atilde",
- "adieresis", "aring", "ae", "ccedilla",
- "egrave", "eacute", "ecircumflex", "edieresis",
- "igrave", "iacute", "icircumflex", "idieresis",
- "eth", "ntilde", "ograve", "oacute",
- "ocircumflex", "otilde", "odieresis", "divide",
- "oslash", "ugrave", "uacute", "ucircumflex",
- "udieresis", "yacute", "thorn", "ydieresis"
-};
-
-#ifdef notdef /* { */
-/* This table is not used anywhere in the code
- * so it's ifdef-ed out by default but left in
- * the source code for reference purposes (and
- * possibly for future use)
- */
-
-static char *ISOLatin1Encoding[256] = {
- ".null", ".notdef", ".notdef", ".notdef",
- ".notdef", ".notdef", ".notdef", ".notdef",
- ".notdef", ".notdef", ".notdef", ".notdef",
- ".notdef", "CR", ".notdef", ".notdef",
- ".notdef", ".notdef", ".notdef", ".notdef",
- ".notdef", ".notdef", ".notdef", ".notdef",
- ".notdef", ".notdef", ".notdef", ".notdef",
- ".notdef", ".notdef", ".notdef", ".notdef",
- "space", "exclam", "quotedbl", "numbersign",
- "dollar", "percent", "ampersand", "quoteright",
- "parenleft", "parenright", "asterisk", "plus",
- "comma", "hyphen", "period", "slash",
- "zero", "one", "two", "three",
- "four", "five", "six", "seven",
- "eight", "nine", "colon", "semicolon",
- "less", "equal", "greater", "question",
- "at", "A", "B", "C",
- "D", "E", "F", "G",
- "H", "I", "J", "K",
- "L", "M", "N", "O",
- "P", "Q", "R", "S",
- "T", "U", "V", "W",
- "X", "Y", "Z", "bracketleft",
- "backslash", "bracketright", "asciicircum", "underscore",
- "grave", "a", "b", "c",
- "d", "e", "f", "g",
- "h", "i", "j", "k",
- "l", "m", "n", "o",
- "p", "q", "r", "s",
- "t", "u", "v", "w",
- "x", "y", "z", "braceleft",
- "bar", "braceright", "asciitilde", "c127",
- "c128", "c129", "quotesinglbase", "florin",
- "quotedblbase", "ellipsis", "dagger", "daggerdbl",
- "circumflex", "perthousand", "Scaron", "guilsinglleft",
- "OE", "c141", "c142", "c143",
- "c144", "quoteleft", "quoteright", "quotedblleft",
- "quotedblright", "bullet", "endash", "emdash",
- "tilde", "trademark", "scaron", "guilsinglright",
- "oe", "c157", "c158", "Ydieresis",
- "nbspace", "exclamdown", "cent", "sterling",
- "currency", "yen", "brokenbar", "section",
- "dieresis", "copyright", "ordfeminine", "guillemotleft",
- "logicalnot", "sfthyphen", "registered", "macron",
- "degree", "plusminus", "twosuperior", "threesuperior",
- "acute", "mu", "paragraph", "periodcentered",
- "cedilla", "onesuperior", "ordmasculine", "guillemotright",
- "onequarter", "onehalf", "threequarters", "questiondown",
- "Agrave", "Aacute", "Acircumflex", "Atilde",
- "Adieresis", "Aring", "AE", "Ccedilla",
- "Egrave", "Eacute", "Ecircumflex", "Edieresis",
- "Igrave", "Iacute", "Icircumflex", "Idieresis",
- "Eth", "Ntilde", "Ograve", "Oacute",
- "Ocircumflex", "Otilde", "Odieresis", "multiply",
- "Oslash", "Ugrave", "Uacute", "Ucircumflex",
- "Udieresis", "Yacute", "Thorn", "germandbls",
- "agrave", "aacute", "acircumflex", "atilde",
- "adieresis", "aring", "ae", "ccedilla",
- "egrave", "eacute", "ecircumflex", "edieresis",
- "igrave", "iacute", "icircumflex", "idieresis",
- "eth", "ntilde", "ograve", "oacute",
- "ocircumflex", "otilde", "odieresis", "divide",
- "oslash", "ugrave", "uacute", "ucircumflex",
- "udieresis", "yacute", "thorn", "ydieresis"
-};
-
-#endif /* } notdef */
-
-static char *adobe_StandardEncoding[256] = {
- ".notdef", ".notdef", ".notdef", ".notdef",
- ".notdef", ".notdef", ".notdef", ".notdef",
- ".notdef", ".notdef", ".notdef", ".notdef",
- ".notdef", ".notdef", ".notdef", ".notdef",
- ".notdef", ".notdef", ".notdef", ".notdef",
- ".notdef", ".notdef", ".notdef", ".notdef",
- ".notdef", ".notdef", ".notdef", ".notdef",
- ".notdef", ".notdef", ".notdef", ".notdef",
- "space", "exclam", "quotedbl", "numbersign",
- "dollar", "percent", "ampersand", "quoteright",
- "parenleft", "parenright", "asterisk", "plus",
- "comma", "hyphen", "period", "slash",
- "zero", "one", "two", "three",
- "four", "five", "six", "seven",
- "eight", "nine", "colon", "semicolon",
- "less", "equal", "greater", "question",
- "at", "A", "B", "C", "D", "E", "F", "G",
- "H", "I", "J", "K", "L", "M", "N", "O",
- "P", "Q", "R", "S", "T", "U", "V", "W",
- "X", "Y", "Z", "bracketleft",
- "backslash", "bracketright", "asciicircum", "underscore",
- "quoteleft", "a", "b", "c", "d", "e", "f", "g",
- "h", "i", "j", "k", "l", "m", "n", "o",
- "p", "q", "r", "s", "t", "u", "v", "w",
- "x", "y", "z", "braceleft",
- "bar", "braceright", "asciitilde", ".notdef",
- ".notdef", ".notdef", ".notdef", ".notdef",
- ".notdef", ".notdef", ".notdef", ".notdef",
- ".notdef", ".notdef", ".notdef", ".notdef",
- ".notdef", ".notdef", ".notdef", ".notdef",
- ".notdef", ".notdef", ".notdef", ".notdef",
- ".notdef", ".notdef", ".notdef", ".notdef",
- ".notdef", ".notdef", ".notdef", ".notdef",
- ".notdef", ".notdef", ".notdef", ".notdef",
- ".notdef", "exclamdown", "cent", "sterling",
- "fraction", "yen", "florin", "section",
- "currency", "quotesingle", "quotedblleft", "guillemotleft",
- "guilsinglleft", "guilsinglright", "fi", "fl",
- ".notdef", "endash", "dagger", "daggerdbl",
- "periodcentered", ".notdef", "paragraph", "bullet",
- "quotesinglbase", "quotedblbase", "quotedblright", "guillemotright",
- "ellipsis", "perthousand", ".notdef", "questiondown",
- ".notdef", "grave", "acute", "circumflex",
- "tilde", "macron", "breve", "dotaccent",
- "dieresis", ".notdef", "ring", "cedilla",
- ".notdef", "hungarumlaut", "ogonek", "caron",
- "emdash", ".notdef", ".notdef", ".notdef",
- ".notdef", ".notdef", ".notdef", ".notdef",
- ".notdef", ".notdef", ".notdef", ".notdef",
- ".notdef", ".notdef", ".notdef", ".notdef",
- ".notdef", "AE", ".notdef", "ordfeminine",
- ".notdef", ".notdef", ".notdef", ".notdef",
- "Lslash", "Oslash", "OE", "ordmasculine",
- ".notdef", ".notdef", ".notdef", ".notdef",
- ".notdef", "ae", ".notdef", ".notdef",
- ".notdef", "dotlessi", ".notdef", ".notdef",
- "lslash", "oslash", "oe", "germandbls",
- ".notdef", ".notdef", ".notdef", ".notdef"
-};
-
-/*
- * Decription of the supported conversions from Unicode
- *
- * SB
- * Yes, I know that the compiled-in conversion is stupid but
- * it is simple to implement and allows not to worry about the
- * filesystem context. After all, the source is always available
- * and adding another language to it is easy.
- *
- * The language name is expected to be the same as the subdirectory name
- * in the `encodings' directory (for possible future extensions).
- * The primary use of the aliases is for guessing based on the current
- * locale.
- */
-
-#define MAXUNIALIAS 10
-#define MAXUNITABLES 3
-
-/* the character used as the language argument separator */
-#define LANG_ARG_SEP '+'
-
-
-/*
- * Types of language-related routines. Arguments are:
- * name is the glyph name
- * arg is the user-specified language-dependent argument
- * which can for example select the subfont plane for Eastern fonts.
- * If none is supplied by user then an empty string ("") is passed.
- * If no language is specified by user and auto-guessing happens
- * then NULL is passed.
- * when shows if the conversion by name was called before conversion by
- * map or after (it's called twice)
- */
-
-/* type of the Unicode map initialization routine */
-typedef void uni_init_t(char *arg);
-
-/* type of Unicode converter-by-name function
- * it's called for each glyph twice: one time for each glyph
- * before doing conversion by map and one time after
- */
-typedef int uni_conv_t(char *name, char *arg, int when);
-#define UNICONV_BYNAME_BEFORE 0
-#define UNICONV_BYNAME_AFTER 1
-
-struct uni_language {
- uni_init_t *init[MAXUNITABLES]; /* map initialization routines */
- uni_conv_t *convbyname; /* the name-based conversion function */
- char *name; /* the language name */
- char *descr; /* description */
- char *alias[MAXUNIALIAS]; /* aliases of the language name */
- int sample_upper; /* code of some uppercase character for correctvsize() */
-};
-
-/* the converter routines have an option of adding this suffix to the font name */
-static char *uni_font_name_suffix = ""; /* empty by default */
-/* this buffer may be used to store the suffix */
-#define UNI_MAX_SUFFIX_LEN 100
-static char uni_suffix_buf[UNI_MAX_SUFFIX_LEN+1];
-
-/*
- * Prototypes of the conversion routines
- */
-
-static uni_init_t unicode_latin1;
-static uni_init_t unicode_latin2;
-static uni_init_t unicode_latin4;
-static uni_init_t unicode_latin5;
-static uni_init_t unicode_cyrillic;
-static uni_init_t unicode_adobestd;
-static uni_init_t unicode_plane;
-static uni_conv_t unicode_adobestd_byname;
-
-static uni_init_t unicode_init_user;
-
-/*
- * The order of descriptions is important: if we can't guess the
- * language we just call all the conversion routines in order until
- * we find one that understands this glyph.
- */
-static struct uni_language uni_lang[]= {
- /* pseudo-language for all the languages using Latin1 */
- {
- { unicode_latin1 },
- 0, /* no name-based mapping */
- "latin1",
- "works for most of the Western languages",
- { "en_", "de_", "fr_", "nl_", "no_", "da_", "it_" },
- 'A'
- },
- { /* by Szalay Tamas <tomek@elender.hu> */
- { unicode_latin2 },
- 0, /* no name-based mapping */
- "latin2",
- "works for Central European languages",
- { "hu_","pl_","cz_","si_","sk_" },
- 'A'
- },
- { /* by Rièardas Èepas <rch@WriteMe.Com> */
- { unicode_latin4 },
- 0, /* no name-based mapping */
- "latin4",
- "works for Baltic languages",
- { "lt_", "lv_" }, /* doubt about ee_ */
- 'A'
- },
- { /* by Turgut Uyar <uyar@cs.itu.edu.tr> */
- { unicode_latin5 },
- 0, /* no name-based mapping */
- "latin5",
- "for Turkish",
- { "tr_" },
- 'A'
- },
- { /* by Zvezdan Petkovic <z.petkovic@computer.org> */
- { unicode_cyrillic, unicode_latin1 },
- 0, /* no name-based mapping */
- "cyrillic",
- "in Windows encoding",
- { "bg_", "be_", "mk_", "ru_", "sr_", "su_", "uk_" },
- 'A'
- },
- {
- { unicode_cyrillic, unicode_latin1 },
- 0, /* no name-based mapping */
- "russian",
- "obsolete, use cyrillic instead",
- { 0 },
- 'A'
- },
- {
- { unicode_cyrillic, unicode_latin1 },
- 0, /* no name-based mapping */
- "bulgarian",
- "obsolete, use cyrillic instead",
- { 0 },
- 'A'
- },
- {
- { unicode_adobestd },
- unicode_adobestd_byname,
- "adobestd",
- "Adobe Standard, expected by TeX",
- { NULL },
- 'A'
- },
- {
- { unicode_plane },
- 0, /* no name-based mapping */
- "plane",
- "one plane of Unicode or other multi-byte encoding as is",
- { NULL },
- 0 /* no easy way to predict the capital letters */
- },
-};
-
-static struct uni_language uni_lang_user = {
- { unicode_init_user },
- 0, /* no name-based mapping */
- 0, /* no name */
- 0, /* no description */
- { 0 },
- 0 /* no sample */
-};
-
-static struct uni_language *uni_lang_selected=0; /* 0 means "unknown, try all" */
-static int uni_sample='A'; /* sample of an uppercase character */
-static char *uni_lang_arg=""; /* user-supplied language-dependent argument */
-
-extern int runt1asm(int);
-
-/*
- * user-defined loadable maps
- */
-
-
-/* The idea begind buckets is to avoid comparing every code with all ENCTABSZ codes in table.
- * All the 16-bit unicode space is divided between a number of equal-sized buckets.
- * Initially all the buckets are marked with 0. Then if any code in the bucket is
- * used it's marked with 1. Later during translation we check the code's bucket first
- * and it it's 0 then return failure right away. This may be useful for
- * Chinese fonts with many thousands of glyphs.
- */
-
-#define BUCKET_ID_BITS 11
-#define MARK_UNI_BUCKET(unicode) SET_BITMAP(uni_user_buckets, (unicode)>>(16-BUCKET_ID_BITS))
-#define IS_UNI_BUCKET(unicode) IS_BITMAP(uni_user_buckets, (unicode)>>(16-BUCKET_ID_BITS))
-
-static DEF_BITMAP(uni_user_buckets, 1<<BUCKET_ID_BITS);
-
-static unsigned int unicode_map[ENCTABSZ]; /* font-encoding to unicode map */
-static int enctabsz = 256; /* actual number of codes used */
-
-static void
-unicode_init_user(
- char *path
-)
-{
- FILE *unicode_map_file;
-#define UNIBFSZ 256
- char buffer[UNIBFSZ];
- unsigned code, unicode, curpos, unicode2;
- char *arg, *p;
- int enabled, found, sawplane;
- int lineno, cnt, n, nchars;
- char next;
- int pid, eid, overid=0;
-
- /* check if we have an argument (plane name) */
- arg = strrchr(path, LANG_ARG_SEP);
- if(arg != 0) {
- *arg++ = 0;
- if( sscanf(arg, "pid=%d,eid=%d%n", &pid, &eid, &nchars) == 2 ) {
- force_pid = pid; force_eid = eid; overid = 1;
- WARNING_1 fprintf(stderr, "User override of the source encoding: pid=%d eid=%d\n", pid, eid);
- forcemap = 1;
- arg += nchars;
- if(*arg == ',')
- arg++;
- }
- if( *arg == 0 || strlen(arg) > UNI_MAX_SUFFIX_LEN-1)
- arg = NULL;
- else {
- sprintf(uni_suffix_buf, "-%s", arg);
- uni_font_name_suffix = uni_suffix_buf;
- }
- }
-
- /* now read in the encoding description file, if requested */
- if ((unicode_map_file = fopen(path, "rb")) == NULL) {
- fprintf(stderr, "**** Cannot access map file '%s' ****\n", path);
- exit(1);
- }
-
- sawplane = 0;
- if(arg==NULL)
- enabled = found = 1;
- else
- enabled = found = 0;
-
- lineno=0; curpos=0;
- while (fgets (buffer, UNIBFSZ, unicode_map_file) != NULL) {
- char name[UNIBFSZ];
-
- lineno++;
-
- if(sscanf(buffer, "plane %s", name)==1) {
- sawplane = 1;
- if(arg == 0) {
- fprintf(stderr, "**** map file '%s' requires plane name\n", path);
- fprintf(stderr, "for example:\n");
- fprintf(stderr, " ttf2pt1 -L %s%c[pid=N,eid=N,]%s ...\n",
- path, LANG_ARG_SEP, name);
- fprintf(stderr, "to select plane '%s'\n", name);
- exit(1);
- }
- if( !strcmp(arg, name) ) {
- enabled = found = 1;
- curpos = 0;
- } else {
- enabled = 0;
- if(found) /* no need to read further */
- break;
- }
- continue;
- }
-
- if(sscanf(buffer, "id %d %d", pid, eid)==2) {
- if( !overid /* only if the user has not overriden */
- && (enabled || !sawplane) ) {
- force_pid = pid; force_eid = eid;
- forcemap = 1;
- }
- continue;
- }
-
- if( !enabled )
- continue; /* skip to the next plane */
-
- if( sscanf(buffer, "at %i", &curpos) == 1 ) {
- if(curpos > 255) {
- fprintf(stderr, "**** map file '%s' line %d: code over 255\n", path, lineno);
- exit(1);
- }
- if(ISDBG(EXTMAP)) fprintf(stderr, "=== at 0x%x\n", curpos);
- continue;
- }
-
- /* try the format of Roman Czyborra's files */
- if ( sscanf (buffer, " =%x U+%4x", &code, &unicode) == 2
- /* try the format of Linux locale charmap file */
- || sscanf (buffer, " <%*s /x%x <U%4x>", &code, &unicode) == 2 ) {
- if (code < ENCTABSZ) {
- if(code >= enctabsz) enctabsz=code+1;
- unicode_map[code] = unicode;
- glyph_rename[code] = NULL;
- }
- }
- /* try the format with glyph renaming */
- else if (sscanf (buffer, " !%x U+%4x %128s", &code,
- &unicode, name) == 3) {
- if (code < ENCTABSZ) {
- if(code >= enctabsz) enctabsz=code+1;
- unicode_map[code] = unicode;
- glyph_rename[code] = strdup(name);
- }
- }
- /* try the compact sequence format */
- else if( (n=sscanf(buffer, " %i%n", &unicode, &cnt)) == 1 ) {
- p = buffer;
- do {
- if(curpos > 255) {
- fprintf(stderr, "**** map file '%s' line %d: code over 255 for unicode 0x%x\n",
- path, lineno, unicode);
- exit(1);
- }
- if(ISDBG(EXTMAP)) fprintf(stderr, "=== 0x%d -> 0x%x\n", curpos, unicode);
- unicode_map[curpos++] = unicode;
- p += cnt;
- if( sscanf(p, " %[,-]%n", &next,&cnt) == 1 ) {
- if(ISDBG(EXTMAP)) fprintf(stderr, "=== next: '%c'\n", next);
- p += cnt;
- if( next == '-' ) { /* range */
- if ( sscanf(p, " %i%n", &unicode2, &cnt) != 1 ) {
- fprintf(stderr, "**** map file '%s' line %d: missing end of range\n", path, lineno);
- exit(1);
- }
- p += cnt;
- if(ISDBG(EXTMAP)) fprintf(stderr, "=== range 0x%x to 0x%x\n", unicode, unicode2);
- for(unicode++; unicode <= unicode2; unicode++) {
- if(curpos > 255) {
- fprintf(stderr, "**** map file '%s' line %d: code over 255 in unicode range ...-0x%x\n",
- path, lineno, unicode2);
- exit(1);
- }
- if(ISDBG(EXTMAP)) fprintf(stderr, "=== 0x%x -> 0x%x\n", curpos, unicode);
- unicode_map[curpos++] = unicode;
- }
- }
- }
- } while ( sscanf(p, " %i%n", &unicode, &cnt) == 1 );
- }
-
- }
-
- fclose (unicode_map_file);
-
- if( !found ) {
- fprintf(stderr, "**** map file '%s' has no plane '%s'\n", path, arg);
- exit(1);
- }
-
- if(unicode_map['A'] == 'A')
- uni_sample = 'A'; /* seems to be compatible with Latin */
- else
- uni_sample = 0; /* don't make any assumptions */
-}
-
-/*
- * by Zvezdan Petkovic <z.petkovic@computer.org>
- */
-static void
-unicode_cyrillic(
- char *arg
-)
-{
- int i;
- static unsigned int cyrillic_unicode_map[] = {
- 0x0402, 0x0403, 0x201a, 0x0453, 0x201e, 0x2026, 0x2020, 0x2021, /* 80 */
- 0x20ac, 0x2030, 0x0409, 0x2039, 0x040a, 0x040c, 0x040b, 0x040f, /* 88 */
- 0x0452, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, /* 90 */
- 0x02dc, 0x2122, 0x0459, 0x203a, 0x045a, 0x045c, 0x045b, 0x045f, /* 98 */
- 0x00a0, 0x040e, 0x045e, 0x0408, 0x00a4, 0x0490, 0x00a6, 0x00a7, /* A0 */
- 0x0401, 0x00a9, 0x0404, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x0407, /* A8 */
- 0x00b0, 0x00b1, 0x0406, 0x0456, 0x0491, 0x00b5, 0x00b6, 0x00b7, /* B0 */
- 0x0451, 0x2116, 0x0454, 0x00bb, 0x0458, 0x0405, 0x0455, 0x0457, /* B8 */
- };
-
- for(i=0; i<=0x7F; i++)
- unicode_map[i] = i;
-
- for(i=0x80; i<=0xBF; i++)
- unicode_map[i] = cyrillic_unicode_map[i-0x80];
-
- for(i=0xC0; i<=0xFF; i++)
- unicode_map[i] = i+0x350;
-
-}
-
-static void
-unicode_latin1(
- char *arg
-)
-{
- int i;
- static unsigned int latin1_unicode_map[] = {
- 0x20ac, -1, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021, /* 80 */
- 0x02c6, 0x2030, 0x0160, 0x2039, 0x0152, 0x008d, 0x017d, 0x008f, /* 88 */
- 0x0090, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, /* 90 */
- 0x02dc, 0x2122, 0x0161, 0x203a, 0x0153, 0x009d, 0x017e, 0x0178, /* 98 */
- };
-
- for(i=0; i<=0x7F; i++)
- unicode_map[i] = i;
-
- for(i=0x80; i<=0x9F; i++)
- unicode_map[i] = latin1_unicode_map[i-0x80];
-
- for(i=0xA0; i<=0xFF; i++)
- unicode_map[i] = i;
-}
-
-static void
-unicode_adobestd(
- char *arg
-)
-{
- int i;
- static unsigned int adobestd_unicode_map[] = {
- -1, 0x00a1, 0x00a2, 0x00a3, 0x2215, 0x00a5, 0x0192, 0x00a7, /* A0 */
- 0x00a4, 0x0027, 0x201c, 0x00ab, 0x2039, 0x203a, 0xfb01, 0xfb02, /* A8 */
- -1, 0x2013, 0x2020, 0x2021, 0x2219, -1, 0x00b6, 0x2022, /* B0 */
- 0x201a, 0x201e, 0x201d, 0x00bb, 0x2026, 0x2030, -1, 0x00bf, /* B8 */
- -1, 0x0060, 0x00b4, 0x02c6, 0x02dc, 0x02c9, 0x02d8, 0x02d9, /* C0 */
- 0x00a8, -1, 0x02da, 0x00b8, -1, 0x02dd, 0x02db, 0x02c7, /* C8 */
- 0x2014, -1, -1, -1, -1, -1, -1, -1, /* D0 */
- -1, -1, -1, -1, -1, -1, -1, -1, /* D8 */
- -1, 0x00c6, -1, 0x00aa, -1, -1, -1, -1, /* E0 */
- 0x0141, 0x00d8, 0x0152, 0x00ba, -1, -1, -1, -1, /* E8 */
- -1, 0x00e6, -1, -1, -1, 0x0131, -1, -1, /* F0 */
- 0x0142, 0x00f8, 0x0153, 0x00df, -1, -1, -1, -1, /* F8 */
- };
-
- for(i=0; i<=0x7F; i++)
- unicode_map[i] = i;
-
- unicode_map[0x27] = 0x2019;
- unicode_map[0x60] = -1;
-
- /* 0x80 to 0x9F is a hole */
-
- for(i=0xA0; i<=0xFF; i++)
- unicode_map[i] = adobestd_unicode_map[i-0xA0];
-}
-
-/*
- * Not all of the Adobe glyphs are in the Unicode
- * standard maps, so the font creators have
- * different ideas about their codes. Because
- * of this we try to map based on the glyph
- * names instead of Unicode codes. If there are
- * no glyph names (ps_fmt_3!=0) we fall back
- * to the code-based scheme.
- */
-
-static int
-unicode_adobestd_byname(
- char *name,
- char *arg,
- int where
-)
-{
- int i;
-
- /* names always take precedence over codes */
- if(where == UNICONV_BYNAME_AFTER)
- return -1;
-
- for(i=32; i<256; i++) {
- if(!strcmp(name, adobe_StandardEncoding[i]))
- return i;
- }
- return -1;
-
-}
-
-static void
-unicode_latin2(
- char *arg
-)
-{
- int i;
- static unsigned int latin2_unicode_map[] = {
- 0x00a0, 0x0104, 0x02d8, 0x0141, 0x00a4, 0x013d, 0x015a, 0x00a7, /* A0 */
- 0x00a8, 0x0160, 0x015e, 0x0164, 0x0179, 0x00ad, 0x017d, 0x017b, /* A8 */
- 0x00b0, 0x0105, 0x02db, 0x0142, 0x00b4, 0x013e, 0x015b, 0x02c7, /* B0 */
- 0x00b8, 0x0161, 0x015f, 0x0165, 0x017a, 0x02dd, 0x017e, 0x017c, /* B8 */
- 0x0154, 0x00c1, 0x00c2, 0x0102, 0x00c4, 0x0139, 0x0106, 0x00c7, /* C0 */
- 0x010c, 0x00c9, 0x0118, 0x00cb, 0x011a, 0x00cd, 0x00ce, 0x010e, /* C8 */
- 0x0110, 0x0143, 0x0147, 0x00d3, 0x00d4, 0x0150, 0x00d6, 0x00d7, /* D0 */
- 0x0158, 0x016e, 0x00da, 0x0170, 0x00dc, 0x00dd, 0x0162, 0x00df, /* D8 */
- 0x0155, 0x00e1, 0x00e2, 0x0103, 0x00e4, 0x013a, 0x0107, 0x00e7, /* E0 */
- 0x010d, 0x00e9, 0x0119, 0x00eb, 0x011b, 0x00ed, 0x00ee, 0x010f, /* E8 */
- 0x0111, 0x0144, 0x0148, 0x00f3, 0x00f4, 0x0151, 0x00f6, 0x00f7, /* F0 */
- 0x0159, 0x016f, 0x00fa, 0x0171, 0x00fc, 0x00fd, 0x0163, 0x02d9, /* F8 */
- };
-
- for(i=0; i<=0x7E; i++)
- unicode_map[i] = i;
-
- /* 7F-9F are unused */
-
- for(i=0xA0; i<=0xFF; i++)
- unicode_map[i] = latin2_unicode_map[i-0xA0];
-}
-
-static void
-unicode_latin4(
- char *arg
-)
-{
- int i;
- static unsigned int latin4_unicode_map[] = {
- 0x0080, 0x0081, 0x201a, 0x0192, -1, 0x2026, 0x2020, 0x2021, /* 80 */
- 0x02c6, 0x2030, -1, 0x2039, 0x0152, 0x008d, 0x008e, 0x008f, /* 88 */
- 0x201e, 0x201c, 0x2019, -1, 0x201d, 0x2022, 0x2013, 0x2014, /* 90 */
- 0x02dc, 0x2122, -1, 0x203a, 0x0153, 0x009d, 0x009e, 0x0178, /* 98 */
- 0x00a0, 0x0104, 0x0138, 0x0156, 0x00a4, 0x0128, 0x013b, 0x00a7, /* A0 */
- 0x00a8, 0x0160, 0x0112, 0x0122, 0x0166, 0x00ad, 0x017d, 0x00af, /* A8 */
- 0x00b0, 0x0105, 0x02db, 0x0157, 0x00b4, 0x0129, 0x013c, 0x02c7, /* B0 */
- 0x00b8, 0x0161, 0x0113, 0x0123, 0x0167, 0x014a, 0x017e, 0x014b, /* B8 */
- 0x0100, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x012e, /* C0 */
- 0x010c, 0x00c9, 0x0118, 0x00cb, 0x0116, 0x00cd, 0x00ce, 0x012a, /* C8 */
- 0x0110, 0x0145, 0x014c, 0x0136, 0x00d4, 0x00d5, 0x00d6, 0x00d7, /* D0 */
- 0x00d8, 0x0172, 0x00da, 0x00db, 0x00dc, 0x0168, 0x016a, 0x00df, /* D8 */
- 0x0101, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x012f, /* E0 */
- 0x010d, 0x00e9, 0x0119, 0x00eb, 0x0117, 0x00ed, 0x00ee, 0x012b, /* E8 */
- 0x0111, 0x0146, 0x014d, 0x0137, 0x00f4, 0x00f5, 0x00f6, 0x00f7, /* F0 */
- 0x00f8, 0x0173, 0x00fa, 0x00fb, 0x00fc, 0x0169, 0x016b, 0x02d9, /* F8 */
- };
-
- for(i=0; i<=0x7F; i++)
- unicode_map[i] = i;
-
- for(i=0x80; i<=0xFF; i++)
- unicode_map[i] = latin4_unicode_map[i-0x80];
-
-#if 0 /* for documentation purposes only */
- case 0x201e: return 0x90; /* these two quotes are a hack only */
- case 0x201c: return 0x91; /* these two quotes are a hack only */
- case 0x00A0: return 0xA0; /* NO-BREAK SPACE */
- case 0x0104: return 0xA1; /* LATIN CAPITAL LETTER A WITH OGONEK */
- case 0x0138: return 0xA2; /* LATIN SMALL LETTER KRA */
- case 0x0156: return 0xA3; /* LATIN CAPITAL LETTER R WITH CEDILLA */
- case 0x00A4: return 0xA4; /* CURRENCY SIGN */
- case 0x0128: return 0xA5; /* LATIN CAPITAL LETTER I WITH TILDE */
- case 0x013B: return 0xA6; /* LATIN CAPITAL LETTER L WITH CEDILLA */
- case 0x00A7: return 0xA7; /* SECTION SIGN */
- case 0x00A8: return 0xA8; /* DIAERESIS */
- case 0x0160: return 0xA9; /* LATIN CAPITAL LETTER S WITH CARON */
- case 0x0112: return 0xAA; /* LATIN CAPITAL LETTER E WITH MACRON */
- case 0x0122: return 0xAB; /* LATIN CAPITAL LETTER G WITH CEDILLA */
- case 0x0166: return 0xAC; /* LATIN CAPITAL LETTER T WITH STROKE */
- case 0x00AD: return 0xAD; /* SOFT HYPHEN */
- case 0x017D: return 0xAE; /* LATIN CAPITAL LETTER Z WITH CARON */
- case 0x00AF: return 0xAF; /* MACRON */
- case 0x00B0: return 0xB0; /* DEGREE SIGN */
- case 0x0105: return 0xB1; /* LATIN SMALL LETTER A WITH OGONEK */
- case 0x02DB: return 0xB2; /* OGONEK */
- case 0x0157: return 0xB3; /* LATIN SMALL LETTER R WITH CEDILLA */
- case 0x00B4: return 0xB4; /* ACUTE ACCENT */
- case 0x0129: return 0xB5; /* LATIN SMALL LETTER I WITH TILDE */
- case 0x013C: return 0xB6; /* LATIN SMALL LETTER L WITH CEDILLA */
- case 0x02C7: return 0xB7; /* CARON */
- case 0x00B8: return 0xB8; /* CEDILLA */
- case 0x0161: return 0xB9; /* LATIN SMALL LETTER S WITH CARON */
- case 0x0113: return 0xBA; /* LATIN SMALL LETTER E WITH MACRON */
- case 0x0123: return 0xBB; /* LATIN SMALL LETTER G WITH CEDILLA */
- case 0x0167: return 0xBC; /* LATIN SMALL LETTER T WITH STROKE */
- case 0x014A: return 0xBD; /* LATIN CAPITAL LETTER ENG */
- case 0x017E: return 0xBE; /* LATIN SMALL LETTER Z WITH CARON */
- case 0x014B: return 0xBF; /* LATIN SMALL LETTER ENG */
- case 0x0100: return 0xC0; /* LATIN CAPITAL LETTER A WITH MACRON */
- case 0x00C1: return 0xC1; /* LATIN CAPITAL LETTER A WITH ACUTE */
- case 0x00C2: return 0xC2; /* LATIN CAPITAL LETTER A WITH CIRCUMFLEX */
- case 0x00C3: return 0xC3; /* LATIN CAPITAL LETTER A WITH TILDE */
- case 0x00C4: return 0xC4; /* LATIN CAPITAL LETTER A WITH DIAERESIS */
- case 0x00C5: return 0xC5; /* LATIN CAPITAL LETTER A WITH RING ABOVE */
- case 0x00C6: return 0xC6; /* LATIN CAPITAL LIGATURE AE */
- case 0x012E: return 0xC7; /* LATIN CAPITAL LETTER I WITH OGONEK */
- case 0x010C: return 0xC8; /* LATIN CAPITAL LETTER C WITH CARON */
- case 0x00C9: return 0xC9; /* LATIN CAPITAL LETTER E WITH ACUTE */
- case 0x0118: return 0xCA; /* LATIN CAPITAL LETTER E WITH OGONEK */
- case 0x00CB: return 0xCB; /* LATIN CAPITAL LETTER E WITH DIAERESIS */
- case 0x0116: return 0xCC; /* LATIN CAPITAL LETTER E WITH DOT ABOVE */
- case 0x00CD: return 0xCD; /* LATIN CAPITAL LETTER I WITH ACUTE */
- case 0x00CE: return 0xCE; /* LATIN CAPITAL LETTER I WITH CIRCUMFLEX */
- case 0x012A: return 0xCF; /* LATIN CAPITAL LETTER I WITH MACRON */
- case 0x0110: return 0xD0; /* LATIN CAPITAL LETTER D WITH STROKE */
- case 0x0145: return 0xD1; /* LATIN CAPITAL LETTER N WITH CEDILLA */
- case 0x014C: return 0xD2; /* LATIN CAPITAL LETTER O WITH MACRON */
- case 0x0136: return 0xD3; /* LATIN CAPITAL LETTER K WITH CEDILLA */
- case 0x00D4: return 0xD4; /* LATIN CAPITAL LETTER O WITH CIRCUMFLEX */
- case 0x00D5: return 0xD5; /* LATIN CAPITAL LETTER O WITH TILDE */
- case 0x00D6: return 0xD6; /* LATIN CAPITAL LETTER O WITH DIAERESIS */
- case 0x00D7: return 0xD7; /* MULTIPLICATION SIGN */
- case 0x00D8: return 0xD8; /* LATIN CAPITAL LETTER O WITH STROKE */
- case 0x0172: return 0xD9; /* LATIN CAPITAL LETTER U WITH OGONEK */
- case 0x00DA: return 0xDA; /* LATIN CAPITAL LETTER U WITH ACUTE */
- case 0x00DB: return 0xDB; /* LATIN CAPITAL LETTER U WITH CIRCUMFLEX */
- case 0x00DC: return 0xDC; /* LATIN CAPITAL LETTER U WITH DIAERESIS */
- case 0x0168: return 0xDD; /* LATIN CAPITAL LETTER U WITH TILDE */
- case 0x016A: return 0xDE; /* LATIN CAPITAL LETTER U WITH MACRON */
- case 0x00DF: return 0xDF; /* LATIN SMALL LETTER SHARP S */
- case 0x0101: return 0xE0; /* LATIN SMALL LETTER A WITH MACRON */
- case 0x00E1: return 0xE1; /* LATIN SMALL LETTER A WITH ACUTE */
- case 0x00E2: return 0xE2; /* LATIN SMALL LETTER A WITH CIRCUMFLEX */
- case 0x00E3: return 0xE3; /* LATIN SMALL LETTER A WITH TILDE */
- case 0x00E4: return 0xE4; /* LATIN SMALL LETTER A WITH DIAERESIS */
- case 0x00E5: return 0xE5; /* LATIN SMALL LETTER A WITH RING ABOVE */
- case 0x00E6: return 0xE6; /* LATIN SMALL LIGATURE AE */
- case 0x012F: return 0xE7; /* LATIN SMALL LETTER I WITH OGONEK */
- case 0x010D: return 0xE8; /* LATIN SMALL LETTER C WITH CARON */
- case 0x00E9: return 0xE9; /* LATIN SMALL LETTER E WITH ACUTE */
- case 0x0119: return 0xEA; /* LATIN SMALL LETTER E WITH OGONEK */
- case 0x00EB: return 0xEB; /* LATIN SMALL LETTER E WITH DIAERESIS */
- case 0x0117: return 0xEC; /* LATIN SMALL LETTER E WITH DOT ABOVE */
- case 0x00ED: return 0xED; /* LATIN SMALL LETTER I WITH ACUTE */
- case 0x00EE: return 0xEE; /* LATIN SMALL LETTER I WITH CIRCUMFLEX */
- case 0x012B: return 0xEF; /* LATIN SMALL LETTER I WITH MACRON */
- case 0x0111: return 0xF0; /* LATIN SMALL LETTER D WITH STROKE */
- case 0x0146: return 0xF1; /* LATIN SMALL LETTER N WITH CEDILLA */
- case 0x014D: return 0xF2; /* LATIN SMALL LETTER O WITH MACRON */
- case 0x0137: return 0xF3; /* LATIN SMALL LETTER K WITH CEDILLA */
- case 0x00F4: return 0xF4; /* LATIN SMALL LETTER O WITH CIRCUMFLEX */
- case 0x00F5: return 0xF5; /* LATIN SMALL LETTER O WITH TILDE */
- case 0x00F6: return 0xF6; /* LATIN SMALL LETTER O WITH DIAERESIS */
- case 0x00F7: return 0xF7; /* DIVISION SIGN */
- case 0x00F8: return 0xF8; /* LATIN SMALL LETTER O WITH STROKE */
- case 0x0173: return 0xF9; /* LATIN SMALL LETTER U WITH OGONEK */
- case 0x00FA: return 0xFA; /* LATIN SMALL LETTER U WITH ACUTE */
- case 0x00FB: return 0xFB; /* LATIN SMALL LETTER U WITH CIRCUMFLEX */
- case 0x00FC: return 0xFC; /* LATIN SMALL LETTER U WITH DIAERESIS */
- case 0x0169: return 0xFD; /* LATIN SMALL LETTER U WITH TILDE */
- case 0x016B: return 0xFE; /* LATIN SMALL LETTER U WITH MACRON */
- case 0x02D9: return 0xFF; /* DOT ABOVE */
-#endif
-}
-
-static void
-unicode_latin5(
- char *arg
-)
-{
- int i;
- static unsigned int latin5_unicode_map1[] = {
- 0x0080, 0x0081, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021, /* 80 */
- 0x02c6, 0x2030, 0x0160, 0x2039, 0x0152, 0x008d, 0x008e, 0x008f, /* 88 */
- 0x0090, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, /* 90 */
- 0x02dc, 0x2122, 0x0161, 0x203a, 0x0153, 0x009d, 0x009e, 0x0178, /* 98 */
- };
- static unsigned int latin5_unicode_map2[] = {
- 0x011e, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7, /* D0 */
- 0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x0130, 0x015e, 0x00df, /* D8 */
- 0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7, /* E0 direct */
- 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef, /* E8 direct */
- 0x011f, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7, /* F0 */
- 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x0131, 0x015f, 0x00ff, /* F8 */
- };
-
- for(i=0; i<=0x7F; i++)
- unicode_map[i] = i;
-
- for(i=0x80; i<=0x9F; i++)
- unicode_map[i] = latin5_unicode_map1[i-0x80];
-
- for(i=0xA0; i<=0xCF; i++)
- unicode_map[i] = i;
-
- for(i=0xD0; i<=0xFF; i++)
- unicode_map[i] = latin5_unicode_map2[i-0xD0];
-}
-
-/* a way to select one 256-character plane from Unicode
- * or other multi-byte encoding
- */
-
-static void
-unicode_plane(
- char *arg
-)
-{
- static unsigned plane;
- int nchars;
- int c1, c2, i;
-
- if(uni_lang_selected == 0)
- return; /* don't participate in auto-guessing */
-
- plane = 0; force_pid = force_eid = -1;
-
- c1 = sscanf(arg, "pid=%d,eid=%d%n", &force_pid, &force_eid, &nchars);
- if(c1 == 2) {
- arg += nchars;
- if(*arg == ',')
- arg++;
- }
- if(arg[0] == '0' && (arg[1]=='x' || arg[1]=='X') ) {
- arg += 2;
- c2 = sscanf(arg, "%x", &plane);
- } else {
- c2 = sscanf(arg, "%d", &plane);
- }
-
- if( (c1!=2 && c1!=0) || (c1==0 && c2==0) ) {
- fprintf(stderr, "**** option -l plane expects one of the following formats:\n");
- fprintf(stderr, " -l plane+0xNN - select hexadecimal number of plane of Unicode\n");
- fprintf(stderr, " -l plane+NN - select decimal number of plane of Unicode\n");
- fprintf(stderr, " -l plane+pid=N,eid=N - select plane 0 of specified encoding\n");
- fprintf(stderr, " -l plane+pid=N,eid=N,0xNN - select hex plane of TTF encoding with this PID/EID\n");
- fprintf(stderr, " -l plane+pid=N,eid=N,NN - select decimal plane of TTF encoding with this PID/EID\n");
- exit(1);
- }
-
- if(c2!=0) {
- if(strlen(arg) > sizeof(uni_suffix_buf)-2) {
- fprintf(stderr, "**** plane number is too large\n");
- }
-
- sprintf(uni_suffix_buf, "-%s", arg);
- uni_font_name_suffix = uni_suffix_buf;
- } else {
- uni_font_name_suffix = "";
- }
-
- plane <<= 8;
- for(i=0; i<=0xFF; i++)
- unicode_map[i] = plane | i;
-}
-
-/* look up the 8-bit code by unicode */
-
-int
-unicode_rev_lookup(
- int unival
-)
-{
- int res;
-
- if( ! IS_UNI_BUCKET(unival) )
- return -1;
-
- for (res = 0; res < enctabsz; res++)
- if (unicode_map[res] == unival)
- return res;
- return -1;
-}
-
-/* mark the buckets for quick lookup */
-
-static void
-unicode_prepare_buckets(
- void
-)
-{
- int i;
-
- memset(uni_user_buckets, 0, sizeof uni_user_buckets);
- for(i=0; i<enctabsz; i++) {
- if(unicode_map[i] != (unsigned) -1)
- MARK_UNI_BUCKET(unicode_map[i]);
- }
-}
-
-/*
- * When we print errors about bad names we want to print these names in
- * some decent-looking form
- */
-
-static char *
-nametoprint(
- unsigned char *s
-)
-{
- static char res[50];
- int c, i;
-
- for(i=0; ( c =* s )!=0 && i<sizeof(res)-8; s++) {
- if(c < ' ' || c > 126) {
- sprintf(res+i, "\\x%02X", c);
- i+=4;
- } else {
- res[i++] = c;
- }
- }
- if(*s != 0) {
- res[i++] = '.';
- res[i++] = '.';
- res[i++] = '.';
- }
- res[i++] = 0;
- return res;
-}
-
-/*
- * Scale the values according to the scale_factor
- */
-
-double
-fscale(
- double val
-)
-{
- return scale_factor * val;
-}
-
-int
-iscale(
- int val
-)
-{
- return (int) (val > 0 ? scale_factor * val + 0.5
- : scale_factor * val - 0.5);
-}
-
-/*
- * Try to force fixed width of characters
- */
-
-static void
-alignwidths(void)
-{
- int i;
- int n = 0, avg, max = 0, min = 3000, sum = 0, x;
-
- for (i = 0; i < numglyphs; i++) {
- if (glyph_list[i].flags & GF_USED) {
- x = glyph_list[i].width;
-
- if (x != 0) {
- if (x < min)
- min = x;
- if (x > max)
- max = x;
-
- sum += x;
- n++;
- }
- }
- }
-
- if (n == 0)
- return;
-
- avg = sum / n;
-
- WARNING_3 fprintf(stderr, "widths: max=%d avg=%d min=%d\n", max, avg, min);
-
- /* if less than 5% variation from average */
- /* force fixed width */
- if (20 * (avg - min) < avg && 20 * (max - avg) < avg) {
- for (i = 0; i < numglyphs; i++) {
- if (glyph_list[i].flags & GF_USED)
- glyph_list[i].width = avg;
- }
- fontm.is_fixed_pitch = 1;
- }
-}
-
-static void
-convert_glyf(
- int glyphno
-)
-{
- GLYPH *g;
- int ncurves;
-
- g = &glyph_list[glyphno];
-
-
- g->scaledwidth = iscale(g->width);
-
- g->entries = 0;
- g->lastentry = 0;
- g->path = 0;
- if (g->ttf_pathlen != 0) {
- cursw->glpath(glyphno, glyph_list);
- g->lastentry = 0;
-
- if(ISDBG(BUILDG))
- dumppaths(g, NULL, NULL);
-
- assertpath(g->entries, __FILE__, __LINE__, g->name);
-
- fclosepaths(g);
- assertpath(g->entries, __FILE__, __LINE__, g->name);
-
- /* float processing */
- if(smooth) {
- ffixquadrants(g);
- assertpath(g->entries, __FILE__, __LINE__, g->name);
-
- fsplitzigzags(g);
- assertpath(g->entries, __FILE__, __LINE__, g->name);
-
- fforceconcise(g);
- assertpath(g->entries, __FILE__, __LINE__, g->name);
-
- fstraighten(g);
- assertpath(g->entries, __FILE__, __LINE__, g->name);
- }
-
- pathtoint(g);
- /* all processing past this point expects integer path */
- assertpath(g->entries, __FILE__, __LINE__, g->name);
-
-#if 0
- fixcontours(g);
- testfixcvdir(g);
-#endif
-
- /* int processing */
- if (smooth) {
- smoothjoints(g);
- assertpath(g->entries, __FILE__, __LINE__, g->name);
- }
-
- ncurves = 0;
- {
- GENTRY *ge;
- for(ge = g->entries; ge; ge = ge->next)
- ncurves++;
- }
- if (ncurves > 200) {
- WARNING_3 fprintf(stderr,
- "** Glyph %s is too long, may display incorrectly\n",
- g->name);
- }
- } else {
- /* for buildstems */
- g->flags &= ~GF_FLOAT;
- }
-}
-
-static void
-handle_gnames(void)
-{
- int i, n, found, c, type;
-
- /* get the names from the font file */
- ps_fmt_3 = cursw->glnames(glyph_list);
-
- /* check for names with wrong characters */
- for (n = 0; n < numglyphs; n++) {
- int c;
- for (i = 0; (c = glyph_list[n].name[i]) != 0; i++) {
- if (!(isalnum(c) || c == '.' || c == '_' || c == '-')
- || i==0 && isdigit(c)) { /* must not start with a digit */
- WARNING_3 fprintf(stderr, "Glyph %d %s (%s), ",
- n, isdigit(c) ? "name starts with a digit" :
- "has bad characters in name",
- nametoprint(glyph_list[n].name));
- glyph_list[n].name = malloc(16);
- sprintf(glyph_list[n].name, "_b_%d", n);
- WARNING_3 fprintf(stderr, "changing to %s\n", glyph_list[n].name);
- break;
- }
- }
- }
-
- if( !ps_fmt_3 ) {
- /* check for duplicate names */
- for (n = 0; n < numglyphs; n++) {
- found = 0;
- for (i = 0; i < n && !found; i++) {
- if (strcmp(glyph_list[i].name, glyph_list[n].name) == 0) {
- if (( glyph_list[n].name = malloc(16) )==0) {
- fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__);
- exit(255);
- }
- sprintf(glyph_list[n].name, "_d_%d", n);
-
- /* if the font has no names in it (what the native parser
- * recognises as ps_fmt_3), FreeType returns all the
- * names as .notdef, so don't complain in this case
- */
- if(strcmp(glyph_list[i].name, ".notdef")) {
- WARNING_3 fprintf(stderr,
- "Glyph %d has the same name as %d: (%s), changing to %s\n",
- n, i,
- glyph_list[i].name,
- glyph_list[n].name);
- }
- found = 1;
- }
- }
- }
-
- }
-
- /* start the encoding stuff */
- for (i = 0; i < ENCTABSZ; i++) {
- encoding[i] = -1;
- }
-
- /* do the 1st round of encoding by name */
- if(!ps_fmt_3 && uni_lang_selected && uni_lang_selected->convbyname) {
- for (n = 0; n < numglyphs; n++) {
- c = uni_lang_selected->convbyname(glyph_list[n].name,
- uni_lang_arg, UNICONV_BYNAME_BEFORE);
- if(c>=0 && c<ENCTABSZ && encoding[c] == -1)
- encoding[c] = n;
- }
- }
-
- /* now do the encoding by table */
- if(uni_lang_selected) {
- for(i=0; i < MAXUNITABLES && uni_lang_selected->init[i]; i++) {
- for (n = 0; n < ENCTABSZ; n++)
- unicode_map[n] = -1;
- uni_lang_selected->init[i](uni_lang_arg);
- unicode_prepare_buckets();
- type = cursw->glenc(glyph_list, encoding, unicode_map);
- if( type == 0 )
- /* if we have an 8-bit encoding we don't need more tries */
- break;
- }
- } else {
- /* language is unknown, try the first table of each */
- for(i=0; i < sizeof uni_lang/(sizeof uni_lang[0]); i++) {
- if(uni_lang[i].init[0] == NULL)
- continue;
- for (n = 0; n < ENCTABSZ; n++)
- unicode_map[n] = -1;
- uni_lang[i].init[0](uni_lang_arg);
- unicode_prepare_buckets();
- type = cursw->glenc(glyph_list, encoding, unicode_map);
- if( type == 0 )
- /* if we have an 8-bit encoding we don't need more tries */
- break;
- }
- }
-
- if (ps_fmt_3) {
- /* get rid of the old names, they are all "UNKNOWN" anyawy */
- for (i = 0; i < numglyphs; i++) {
- glyph_list[i].name = 0;
- }
- if(type == 0) {
- /* 8-bit - give 8859/1 names to the first 256 glyphs */
- for (i = 0; i < 256; i++) { /* here 256, not ENCTABSZ */
- if (encoding[i] > 0) {
- glyph_list[encoding[i]].name = Fmt3Encoding[i];
- }
- }
- } else if(type == 1) {
- /* Unicode - give 8859/1 names to the first 256 glyphs of Unicode */
- for (n = 0; n < 256; n++) { /* here 256, not ENCTABSZ */
- i = unicode_rev_lookup(n);
- if (i>=0 && encoding[i] > 0) {
- glyph_list[encoding[i]].name = Fmt3Encoding[i];
- }
- }
- } /* for other types of encodings just give generated names */
- /* assign unique names to the rest of the glyphs */
- for (i = 0; i < numglyphs; i++) {
- if (glyph_list[i].name == 0) {
- if (( glyph_list[i].name = malloc(16) )==0) {
- fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__);
- exit(255);
- }
- sprintf(glyph_list[i].name, "_d_%d", i);
- }
- }
- }
-
- /* do the 2nd round of encoding by name */
- if(uni_lang_selected && uni_lang_selected->convbyname) {
- for (n = 0; n < numglyphs; n++) {
- c = uni_lang_selected->convbyname(glyph_list[n].name,
- uni_lang_arg, UNICONV_BYNAME_AFTER);
- if(c>=0 && c<ENCTABSZ && encoding[c] == -1)
- encoding[c] = n;
- }
- }
- /* all the encoding things are done */
-
- for (i = 0; i < ENCTABSZ; i++)
- if(encoding[i] == -1) {
- /* check whether this character might be a duplicate
- * (in which case it would be missed by unicode_rev_lookup())
- */
- c = unicode_map[i];
- if((type != 0 || forcemap) && c != -1) {
- for(n = 0; n < i; n++) {
- if(unicode_map[n] == c) {
- encoding[i] = encoding[n];
- }
- }
- }
- if(encoding[i] == -1) /* still not found, defaults to .notdef */
- encoding[i] = 0;
- }
-
- for (i = 0; i < 256; i++) /* here 256, not ENCTABSZ */
- glyph_list[encoding[i]].char_no = i;
-
- /* enforce two special cases defined in TTF manual */
- if(numglyphs > 0)
- glyph_list[0].name = ".notdef";
- if(numglyphs > 1)
- glyph_list[1].name = ".null";
-
- for (i = 0; i < ENCTABSZ; i++) {
- if ((encoding[i] != 0) && glyph_rename[i]) {
- glyph_list[encoding[i]].name = glyph_rename[i];
- }
- }
-
-}
-
-static void
-usage(void)
-{
-
-#ifdef _GNU_SOURCE
-# define fplop(txt) fputs(txt, stderr);
-#else
-# define fplop(txt)
-#endif
-
- fputs("Use:\n", stderr);
- fputs("ttf2pt1 [-<opts>] [-l language | -L file] <ttf-file> [<fontname>]\n", stderr);
- fputs(" or\n", stderr);
- fputs("ttf2pt1 [-<opts>] [-l language | -L file] <ttf-file> -\n", stderr);
- fputs(" or\n", stderr);
- fputs("ttf2pt1 [-<opts>] [-l language | -L file] <ttf-file> - | t1asm > <pfa-file>\n", stderr);
-
- fplop("\n");
- fplop("This build supports both short and long option names,\n");
- fplop("the long options are listed before corresponding short ones\n");
-
- fplop(" --all-glyphs\n");
- fputs(" -a - include all glyphs, even those not in the encoding table\n", stderr);
- fplop(" --pfb\n");
- fputs(" -b - produce a compressed .pfb file\n", stderr);
- fplop(" --debug dbg_suboptions\n");
- fputs(" -d dbg_suboptions - debugging options, run ttf2pt1 -d? for help\n", stderr);
- fplop(" --encode\n");
- fputs(" -e - produce a fully encoded .pfa file\n", stderr);
- fplop(" --force-unicode\n");
- fputs(" -F - force use of Unicode encoding even if other MS encoding detected\n", stderr);
- fplop(" --generate suboptions\n");
- fputs(" -G suboptions - control the file generation, run ttf2pt1 -G? for help\n", stderr);
- fplop(" --language language\n");
- fputs(" -l language - convert Unicode to specified language, run ttf2pt1 -l? for list\n", stderr);
- fplop(" --language-map file\n");
- fputs(" -L file - convert Unicode according to encoding description file\n", stderr);
- fplop(" --limit <type>=<value>\n");
- fputs(" -m <type>=<value> - set maximal limit of given type to value, types:\n", stderr);
- fputs(" h - maximal hint stack depth in the PostScript interpreter\n", stderr);
- fplop(" --processing suboptions\n");
- fputs(" -O suboptions - control outline processing, run ttf2pt1 -O? for help\n", stderr);
- fplop(" --parser name\n");
- fputs(" -p name - use specific front-end parser, run ttf2pt1 -p? for list\n", stderr);
- fplop(" --uid id\n");
- fputs(" -u id - use this UniqueID, -u A means autogeneration\n", stderr);
- fplop(" --vertical-autoscale size\n");
- fputs(" -v size - scale the font to make uppercase letters >size/1000 high\n", stderr);
- fplop(" --version\n");
- fputs(" -V - print ttf2pt1 version number\n", stderr);
- fplop(" --warning number\n");
- fputs(" -W number - set the level of permitted warnings (0 - disable)\n", stderr);
- fputs("Obsolete options (will be removed in future releases):\n", stderr);
- fplop(" --afm\n");
- fputs(" -A - write the .afm file to STDOUT instead of the font, now -GA\n", stderr);
- fputs(" -f - don't try to guess the value of the ForceBold hint, now -Ob\n", stderr);
- fputs(" -h - disable autogeneration of hints, now -Oh\n", stderr);
- fputs(" -H - disable hint substitution, now -Ou\n", stderr);
- fputs(" -o - disable outline optimization, now -Oo\n", stderr);
- fputs(" -s - disable outline smoothing, now -Os\n", stderr);
- fputs(" -t - disable auto-scaling to 1000x1000 standard matrix, now -Ot\n", stderr);
- fputs(" -w - correct the glyph widths (use only for buggy fonts), now -OW\n", stderr);
- fputs("With no <fontname>, write to <ttf-file> with suffix replaced.\n", stderr);
- fputs("The last '-' means 'use STDOUT'.\n", stderr);
-
-#undef fplop
-
-}
-
-static void
-printversion(void)
-{
- fprintf(stderr, "ttf2pt1 %s\n", TTF2PT1_VERSION);
-}
-
-/* initialize a table of suboptions */
-static void
-init_subo_tbl(
- struct subo_case *tbl
-)
-{
- int i;
-
- for(i=0; tbl[i].disbl != 0; i++) {
- tbl[i].disbl = tolower(tbl[i].disbl);
- tbl[i].enbl = toupper(tbl[i].disbl);
- *(tbl[i].valp) = tbl[i].dflt;
- }
-}
-
-/* print the default value of the suboptions */
-static void
-print_subo_dflt(
- FILE *f,
- struct subo_case *tbl
-)
-{
- int i;
-
- for(i=0; tbl[i].disbl != 0; i++) {
- if(tbl[i].dflt)
- putc(tbl[i].enbl, f);
- else
- putc(tbl[i].disbl, f);
- }
-}
-
-/* print the usage message for the suboptions */
-static void
-print_subo_usage(
- FILE *f,
- struct subo_case *tbl
-)
-{
- int i;
-
- fprintf(f,"The lowercase suboptions disable features, corresponding\n");
- fprintf(f,"uppercase suboptions enable them. The supported suboptions,\n");
- fprintf(f,"their default states and the features they control are:\n");
- for(i=0; tbl[i].disbl != 0; i++) {
- fprintf(f," %c/%c - [%s] %s\n", tbl[i].disbl, tbl[i].enbl,
- tbl[i].dflt ? "enabled" : "disabled", tbl[i].descr);
- }
-}
-
-/* find and set the entry according to suboption,
- * return the found entry (or if not found return NULL)
- */
-struct subo_case *
-set_subo(
- struct subo_case *tbl,
- int subopt
-)
-{
- int i;
-
- for(i=0; tbl[i].disbl != 0; i++) {
- if(subopt == tbl[i].disbl) {
- *(tbl[i].valp) = 0;
- return &tbl[i];
- } else if(subopt == tbl[i].enbl) {
- *(tbl[i].valp) = 1;
- return &tbl[i];
- }
- }
- return NULL;
-}
-
-
-int
-ttf2pt1_main(
- int argc,
- char **argv
-)
-{
- int i, j;
- time_t now;
- char filename[4096];
- int c,nchars,nmetrics;
- int ws;
- int forcebold= -1; /* -1 means "don't know" */
- char *lang;
- int oc;
- int subid;
- char *cmdline;
-#ifdef _GNU_SOURCE
-# define ttf2pt1_getopt(a, b, c, d, e) getopt_long(a, b, c, d, e)
- static struct option longopts[] = {
- { "afm", 0, NULL, 'A' },
- { "all-glyphs", 0, NULL, 'a' },
- { "pfb", 0, NULL, 'b' },
- { "debug", 1, NULL, 'd' },
- { "encode", 0, NULL, 'e' },
- { "force-unicode", 0, NULL, 'F' },
- { "generate", 1, NULL, 'G' },
- { "language", 1, NULL, 'l' },
- { "language-map", 1, NULL, 'L' },
- { "limit", 1, NULL, 'm' },
- { "processing", 1, NULL, 'O' },
- { "parser", 1, NULL, 'p' },
- { "uid", 1, NULL, 'u' },
- { "vertical-autoscale", 1, NULL, 'v' },
- { "version", 0, NULL, 'V' },
- { "warning", 1, NULL, 'W' },
- { NULL, 0, NULL, 0 }
- };
-#else
-# define ttf2pt1_getopt(a, b, c, d, e) getopt(a, b, c)
-#endif
- /* table of Outline Processing (may think also as Optimization) options */
- static struct subo_case opotbl[] = {
- { 'b', 0/*auto-set*/, &trybold, 1, "guessing of the ForceBold hint" },
- { 'h', 0/*auto-set*/, &hints, 1, "autogeneration of hints" },
- { 'u', 0/*auto-set*/, &subhints, 1, "hint substitution technique" },
- { 'o', 0/*auto-set*/, &optimize, 1, "space optimization of font files" },
- { 's', 0/*auto-set*/, &smooth, 1, "smoothing and repair of outlines" },
- { 't', 0/*auto-set*/, &transform, 1, "auto-scaling to the standard matrix 1000x1000" },
- { 'w', 0/*auto-set*/, &correctwidth, 0, "correct the glyph widths (use only for buggy fonts)" },
- { 'v', 0/*auto-set*/, &vectorize, 0, "vectorize (trace) the bitmaps" },
-#ifdef USE_AUTOTRACE
- { 'z', 0/*auto-set*/, &use_autotrace, 0, "use the autotrace library on bitmaps (works badly)" },
-#endif /*USE_AUTOTRACE*/
- { 0, 0, 0, 0, 0} /* terminator */
- };
- /* table of the File Generation options */
- static struct subo_case fgotbl[] = {
- { 'f', 0/*auto-set*/, &gen_pfa, 1, "generate the font file (.t1a, .pfa or .pfb)" },
- { 'a', 0/*auto-set*/, &gen_afm, 1, "generate the Adobe metrics file (.afm)" },
- { 'e', 0/*auto-set*/, &gen_dvienc, 0, "generate the dvips encoding file (.enc)" },
- { 0, 0, 0, 0, 0} /* terminator */
- };
- int *genlast = NULL;
-
-
- init_subo_tbl(opotbl); /* initialize sub-options of -O */
- init_subo_tbl(fgotbl); /* initialize sub-options of -G */
-
- /* save the command line for the record
- * (we don't bother about escaping the shell special characters)
- */
-
- j = 0;
- for(i=1; i<argc; i++) {
- j += strlen(argv[i])+1;
- }
- if ((cmdline = malloc(j+1)) == NULL) {
- fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__);
- exit(255);
- }
- cmdline[0] = 0;
- for(i=1; i<argc; i++) {
- strcat(cmdline, argv[i]);
- strcat(cmdline, " ");
- }
- for(i=0; (j=cmdline[i])!=0; i++)
- if(j == '\n')
- cmdline[i] = ' ';
-
-
- while(( oc=ttf2pt1_getopt(argc, argv, "FaoebAsthHfwVv:p:l:d:u:L:m:W:O:G:",
- longopts, NULL) )!= -1) {
- switch(oc) {
- case 'W':
- if(sscanf(optarg, "%d", &warnlevel) < 1 || warnlevel < 0) {
- fprintf(stderr, "**** warning level must be a positive number: %s (%d)\n", optarg, warnlevel);
- exit(1);
- }
- break;
- case 'F':
- forcemap = 1;
- break;
- case 'o':
- fputs("Warning: option -o is obsolete, use -Oo instead\n", stderr);
- optimize = 0;
- break;
- case 'e':
- encode = 1;
- break;
- case 'b':
- encode = pfbflag = 1;
- break;
- case 'A':
- fputs("Warning: option -A is obsolete, use -GA instead\n", stderr);
- wantafm = 1;
- break;
- case 'a':
- allglyphs = 1;
- break;
- case 's':
- fputs("Warning: option -s is obsolete, use -Os instead\n", stderr);
- smooth = 0;
- break;
- case 't':
- fputs("Warning: option -t is obsolete, use -Ot instead\n", stderr);
- transform = 0;
- break;
- case 'd':
- for(i=0; optarg[i]!=0; i++)
- switch(optarg[i]) {
- case 'a':
- absolute = 1;
- break;
- case 'r':
- reverse = 0;
- break;
- default:
- if (optarg[i] != '?')
- fprintf(stderr, "**** Unknown debugging option '%c' ****\n", optarg[i]);
- fputs("The recognized debugging options are:\n", stderr);
- fputs(" a - enable absolute coordinates\n", stderr);
- fputs(" r - do not reverse font outlines directions\n", stderr);
- exit(1);
- break;
- };
- break;
- case 'm':
- {
- char subopt;
- int val;
-
- if(sscanf(optarg, "%c=%d", &subopt, &val) !=2) {
- fprintf(stderr, "**** Misformatted maximal limit ****\n");
- fprintf(stderr, "spaces around the equal sign are not allowed\n");
- fprintf(stderr, "good examples: -mh=100 -m h=100\n");
- fprintf(stderr, "bad examples: -mh = 100 -mh= 100\n");
- exit(1);
- break;
- }
- switch(subopt) {
- case 'h':
- max_stemdepth = val;
- break;
- default:
- if (subopt != '?')
- fprintf(stderr, "**** Unknown limit type '%c' ****\n", subopt);
- fputs("The recognized limit types are:\n", stderr);
- fputs(" h - maximal hint stack depth in the PostScript interpreter\n", stderr);
- exit(1);
- break;
- }
- break;
- }
- case 'O':
- {
- char *p;
- for(p=optarg; *p != 0; p++) {
- if(set_subo(opotbl, *p) == NULL) { /* found no match */
- if (*p != '?')
- fprintf(stderr, "**** Unknown outline processing suboption '%c' ****\n", *p);
- fprintf(stderr,"The general form of the outline processing option is:\n");
- fprintf(stderr," -O suboptions\n");
- fprintf(stderr,"(To remember easily -O may be also thought of as \"optimization\").\n");
- print_subo_usage(stderr, opotbl);
- fprintf(stderr, "The default state corresponds to the option -O ");
- print_subo_dflt(stderr, opotbl);
- fprintf(stderr, "\n");
- exit(1);
- }
- }
- break;
- }
- case 'G':
- {
- char *p;
- struct subo_case *s;
-
- for(p=optarg; *p != 0; p++) {
- if(( s = set_subo(fgotbl, *p) )==NULL) { /* found no match */
- if (*p != '?')
- fprintf(stderr, "**** Unknown outline processing suboption '%c' ****\n", *p);
- fprintf(stderr,"The general form of the file generation option is:\n");
- fprintf(stderr," -G suboptions\n");
- print_subo_usage(stderr, fgotbl);
- fprintf(stderr, "The default state corresponds to the option -G ");
- print_subo_dflt(stderr, fgotbl);
- fprintf(stderr, "\n");
- fprintf(stderr, "If the result is written to STDOUT, the last specified enabling suboption of -G\n");
- fprintf(stderr, "selects the file to be written to STDOUT (the font file by default).\n");
- exit(1);
- }
- if( *(s->valp) )
- genlast = s->valp;
- }
- break;
- }
- case 'h':
- fputs("Warning: option -h is obsolete, use -Oh instead\n", stderr);
- hints = 0;
- break;
- case 'H':
- fputs("Warning: meaning of option -H has been changed to its opposite\n", stderr);
- fputs("Warning: option -H is obsolete, use -Ou instead\n", stderr);
- subhints = 0;
- break;
- case 'f':
- fputs("Warning: option -f is obsolete, use -Ob instead\n", stderr);
- trybold = 0;
- break;
- case 'w':
- fputs("Warning: option -w is obsolete, use -OW instead\n", stderr);
- correctwidth = 1;
- break;
- case 'u':
- if(wantuid) {
- fprintf(stderr, "**** UniqueID may be specified only once ****\n");
- exit(1);
- }
- wantuid = 1;
- if(optarg[0]=='A' && optarg[1]==0)
- strUID=0; /* will be generated automatically */
- else {
- strUID=optarg;
- for(i=0; optarg[i]!=0; i++)
- if( !isdigit(optarg[i]) ) {
- fprintf(stderr, "**** UniqueID must be numeric or A for automatic ****\n");
- exit(1);
- }
- }
- break;
- case 'v':
- correctvsize = atoi(optarg);
- if(correctvsize <= 0 && correctvsize > 1000) {
- fprintf(stderr, "**** wrong vsize '%d', ignored ****\n", correctvsize);
- correctvsize=0;
- }
- break;
- case 'p':
- if(cursw!=0) {
- fprintf(stderr, "**** only one front-end parser be used ****\n");
- exit(1);
- }
-
- { /* separate parser from parser-specific argument */
- char *p = strchr(optarg, LANG_ARG_SEP);
- if(p != 0) {
- *p = 0;
- front_arg = p+1;
- } else
- front_arg = "";
- }
- for(i=0; frontswtab[i] != NULL; i++)
- if( !strcmp(frontswtab[i]->name, optarg) ) {
- cursw = frontswtab[i];
- break;
- }
-
- if(cursw==0) {
- if (strcmp(optarg, "?"))
- fprintf(stderr, "**** unknown front-end parser '%s' ****\n", optarg);
- fputs("the following front-ends are supported now:\n", stderr);
- for(i=0; frontswtab[i] != NULL; i++) {
- fprintf(stderr," %s (%s)\n file suffixes: ",
- frontswtab[i]->name,
- frontswtab[i]->descr ? frontswtab[i]->descr : "no description"
- );
- for(j=0; j<MAXSUFFIX; j++)
- if(frontswtab[i]->suffix[j])
- fprintf(stderr, "%s ", frontswtab[i]->suffix[j]);
- fprintf(stderr, "\n");
- }
- exit(1);
- }
- break;
- case 'l':
- if(uni_lang_selected!=0) {
- fprintf(stderr, "**** only one language option may be used ****\n");
- exit(1);
- }
-
- { /* separate language from language-specific argument */
- char *p = strchr(optarg, LANG_ARG_SEP);
- if(p != 0) {
- *p = 0;
- uni_lang_arg = p+1;
- } else
- uni_lang_arg = "";
- }
- for(i=0; i < sizeof uni_lang/(sizeof uni_lang[0]); i++)
- if( !strcmp(uni_lang[i].name, optarg) ) {
- uni_lang_selected = &uni_lang[i];
- uni_sample = uni_lang[i].sample_upper;
- break;
- }
-
- if(uni_lang_selected==0) {
- if (strcmp(optarg, "?"))
- fprintf(stderr, "**** unknown language '%s' ****\n", optarg);
- fputs(" the following languages are supported now:\n", stderr);
- for(i=0; i < sizeof uni_lang/(sizeof uni_lang[0]); i++)
- fprintf(stderr," %s (%s)\n",
- uni_lang[i].name,
- uni_lang[i].descr ? uni_lang[i].descr : "no description"
- );
- exit(1);
- }
- break;
- case 'L':
- if(uni_lang_selected!=0) {
- fprintf(stderr, "**** only one language option may be used ****\n");
- exit(1);
- }
- uni_lang_selected = &uni_lang_user;
- uni_lang_arg = optarg;
- break;
- case 'V':
- printversion();
- exit(0);
- break;
- default:
- usage();
- exit(1);
- break;
- }
- }
-
- argc-=optind-1; /* the rest of code counts from argv[0] */
- argv+=optind-1;
-
- if (absolute && encode) {
- fprintf(stderr, "**** options -a and -e are incompatible ****\n");
- exit(1);
- }
- if ((argc != 2) && (argc != 3)) {
- usage();
- exit(1);
- }
- /* try to guess the language by the locale used */
- if(uni_lang_selected==0 && (lang=getenv("LANG"))!=0 ) {
- for(i=0; i < sizeof uni_lang/sizeof(struct uni_language); i++) {
- if( !strncmp(uni_lang[i].name, lang, strlen(uni_lang[i].name)) ) {
- uni_lang_selected = &uni_lang[i];
- goto got_a_language;
- }
- }
- /* no full name ? try aliases */
- for(i=0; i < sizeof uni_lang/sizeof(struct uni_language); i++) {
- for(c=0; c<MAXUNIALIAS; c++)
- if( uni_lang[i].alias[c]!=0
- && !strncmp(uni_lang[i].alias[c], lang, strlen(uni_lang[i].alias[c])) ) {
- uni_lang_selected = &uni_lang[i];
- goto got_a_language;
- }
- }
- got_a_language:
- if(uni_lang_selected!=0) {
- WARNING_1 fprintf(stderr, "Using language '%s' for Unicode fonts\n", uni_lang[i].name);
- uni_sample = uni_lang[i].sample_upper;
- }
- }
-
- /* try to guess the front-end parser by the file name suffix */
- if(cursw==0) {
- char *p = strrchr(argv[1], '.');
- char *s;
-
- if(p!=0 && (s = strdup(p+1))!=0) {
- for(p=s; *p; p++)
- *p = tolower(*p);
- p = s;
-
- for(i=0; frontswtab[i] != 0 && cursw == 0; i++) {
- for(j=0; j<MAXSUFFIX; j++)
- if(frontswtab[i]->suffix[j]
- && !strcmp(p, frontswtab[i]->suffix[j]) ) {
- cursw = frontswtab[i];
- WARNING_1 fprintf(stderr, "Auto-detected front-end parser '%s'\n",
- cursw->name);
- WARNING_1 fprintf(stderr, " (use ttf2pt1 -p? to get the full list of available front-ends)\n");
- break;
- }
- }
- free(s);
- }
-
- if(cursw==0) {
- cursw = frontswtab[0];
- WARNING_1 fprintf(stderr, "Can't detect front-end parser, using '%s' by default\n",
- cursw->name);
- WARNING_1 fprintf(stderr, " (use ttf2pt1 -p? to get the full list of available front-ends)\n");
- }
- }
-
- /* open the input file */
- cursw->open(argv[1], front_arg);
-
- /* Get base name of output file (if not specified)
- * by removing (known) suffixes
- */
- if (argc == 2) {
- char *p;
- argv[2] = strdup (argv[1]);
- p = strrchr(argv[2], '.');
- if (p != NULL)
- for (j = 0; (j < MAXSUFFIX) && (cursw->suffix[j]); j++)
- if (!strcmp(p+1, cursw->suffix[j])) {
- *p = '\0';
- break;
- }
- }
-
- if ((null_file = fopen(BITBUCKET, "wb")) == NULL) {
- fprintf(stderr, "**** Cannot open %s ****\n",
- BITBUCKET);
- exit(1);
- }
- if (argv[2][0] == '-' && argv[2][1] == 0) {
-#ifdef NOPIPES
- if(encode) {
- fprintf(stderr, "**** can't write encoded file to stdout ***\n");
- exit(1);
- }
-#endif /* NOPIPES */
- pfa_file = afm_file = dvienc_file = null_file;
-
- if(wantafm || genlast == &gen_afm) { /* print .afm instead of .pfa */
- afm_file=stdout;
- } else if(genlast == &gen_dvienc) { /* print .enc instead of .pfa */
- dvienc_file=stdout;
- } else {
- pfa_file=stdout;
- }
- } else {
-#ifndef NOPIPES
- snprintf(filename, sizeof filename, "%s.%s", argv[2], encode ? (pfbflag ? "pfb" : "pfa") : "t1a" );
-#else /* NOPIPES */
- snprintf(filename, sizeof filename, "%s.t1a", argv[2]);
-#endif /* NOPIPES */
- if(gen_pfa) {
- if ((pfa_file = fopen(filename, "wb+")) == NULL) {
- fprintf(stderr, "**** Cannot create %s ****\n", filename);
- exit(1);
- } else {
- WARNING_2 fprintf(stderr, "Creating file %s\n", filename);
- }
- } else
- pfa_file = null_file;
-
- if(gen_afm) {
- snprintf(filename, sizeof filename, "%s.afm", argv[2]) ;
- if ((afm_file = fopen(filename, "w+")) == NULL) {
- fprintf(stderr, "**** Cannot create %s ****\n", filename);
- exit(1);
- }
- } else
- afm_file = null_file;
-
- if(gen_dvienc) {
- snprintf(filename, sizeof filename, "%s.enc", argv[2]) ;
- if ((dvienc_file = fopen(filename, "w+")) == NULL) {
- fprintf(stderr, "**** Cannot create %s ****\n", filename);
- exit(1);
- }
- } else
- dvienc_file = null_file;
- }
-
- /*
- * Now check whether we want a fully encoded .pfa file
- */
-#ifndef NOPIPES
- if (encode && pfa_file != null_file) {
- int p[2];
- extern FILE *ifp, *ofp; /* from t1asm.c */
-
- ifp=stdin; //?
- ofp=stdout; //?
-
- if (pipe(p) < 0) {
- perror("**** Cannot create pipe ****\n");
- exit(1);
- }
- ofp = pfa_file;
- ifp = fdopen(p[0], "rb");
- if (ifp == NULL) {
- perror("**** Cannot use pipe for reading ****\n");
- exit(1);
- }
- pfa_file = fdopen(p[1], "wb");
- if (pfa_file == NULL) {
- perror("**** Cannot use pipe for writing ****\n");
- exit(1);
- }
- switch (fork()) {
- case -1:
- perror("**** Cannot fork the assembler process ****\n");
- exit(1);
- case 0: /* child */
- fclose(pfa_file);
- exit(runt1asm(pfbflag));
- default: /* parent */
- fclose(ifp); fclose(ofp);
- }
- }
-#endif /* NOPIPES */
-
- numglyphs = cursw->nglyphs();
-
- WARNING_3 fprintf(stderr, "numglyphs = %d\n", numglyphs);
-
- glyph_list = (GLYPH *) calloc(numglyphs, sizeof(GLYPH));
-
- /* initialize non-0 fields */
- for (i = 0; i < numglyphs; i++) {
- GLYPH *g;
-
- g = &glyph_list[i];
- g->char_no = -1;
- g->orig_code = -1;
- g->name = "UNKNOWN";
- g->flags = GF_FLOAT; /* we start with float representation */
- }
-
- handle_gnames();
-
- cursw->glmetrics(glyph_list);
- cursw->fnmetrics(&fontm);
-
- original_scale_factor = 1000.0 / (double) fontm.units_per_em;
-
- if(transform == 0)
- scale_factor = 1.0; /* don't transform */
- else
- scale_factor = original_scale_factor;
-
- if(correctvsize && uni_sample!=0) { /* only for known languages */
- /* try to adjust the scale factor to make a typical
- * uppercase character of hight at least (correctvsize), this
- * may improve the appearance of the font but also
- * make it weird, use with caution
- */
- int ysz;
-
- ysz = iscale(glyph_list[encoding[uni_sample]].yMax);
- if( ysz<correctvsize ) {
- scale_factor *= (double)correctvsize / ysz;
- }
- }
-
- if(allglyphs) {
- for (i = 0; i < numglyphs; i++) {
- glyph_list[i].flags |= GF_USED;
- }
- } else {
- for (i = 0; i < ENCTABSZ; i++) {
- glyph_list[encoding[i]].flags |= GF_USED;
- }
-
- /* also always include .notdef */
- for (i = 0; i < numglyphs; i++)
- if(!strcmp(glyph_list[i].name, ".notdef")) {
- glyph_list[i].flags |= GF_USED;
- break;
- }
- }
-
- for (i = 0; i < numglyphs; i++) {
- if (glyph_list[i].flags & GF_USED) {
- DBG_TO_GLYPH(&glyph_list[i]);
- convert_glyf(i);
- DBG_FROM_GLYPH(&glyph_list[i]);
- }
- }
-
- italic_angle = fontm.italic_angle;
-
- if (italic_angle > 45.0 || italic_angle < -45.0)
- italic_angle = 0.0; /* consider buggy */
-
- if (hints) {
- findblues();
- for (i = 0; i < numglyphs; i++) {
- if (glyph_list[i].flags & GF_USED) {
- DBG_TO_GLYPH(&glyph_list[i]);
- buildstems(&glyph_list[i]);
- assertpath(glyph_list[i].entries, __FILE__, __LINE__, glyph_list[i].name);
- DBG_FROM_GLYPH(&glyph_list[i]);
- }
- }
- stemstatistics();
- } else {
- for(i=0; i<4; i++)
- bbox[i] = iscale(fontm.bbox[i]);
- }
- /* don't touch the width of fixed width fonts */
- if( fontm.is_fixed_pitch )
- correctwidth=0;
- docorrectwidth(); /* checks correctwidth inside */
- if (reverse)
- for (i = 0; i < numglyphs; i++) {
- if (glyph_list[i].flags & GF_USED) {
- DBG_TO_GLYPH(&glyph_list[i]);
- reversepaths(&glyph_list[i]);
- assertpath(glyph_list[i].entries, __FILE__, __LINE__, glyph_list[i].name);
- DBG_FROM_GLYPH(&glyph_list[i]);
- }
- }
-
-
-#if 0
- /*
- ** It seems to bring troubles. The problem is that some
- ** styles of the font may be recognized as fixed-width
- ** while other styles of the same font as proportional.
- ** So it's better to be commented out yet.
- */
- if (tryfixed)
- alignwidths();
-#endif
-
- if(trybold) {
- forcebold = fontm.force_bold;
- }
-
- fprintf(pfa_file, "%%!PS-AdobeFont-1.0: %s %s\n", fontm.name_ps, fontm.name_copyright);
- time(&now);
- fprintf(pfa_file, "%%%%CreationDate: %s", ctime(&now));
- fprintf(pfa_file, "%% Converted by ttf2pt1 %s/%s\n", TTF2PT1_VERSION, cursw->name);
- fprintf(pfa_file, "%% Args: %s\n", cmdline);
- fprintf(pfa_file, "%%%%EndComments\n");
- fprintf(pfa_file, "12 dict begin\n/FontInfo 9 dict dup begin\n");
-
- WARNING_3 fprintf(stderr, "FontName %s%s\n", fontm.name_ps, uni_font_name_suffix);
-
-
- fprintf(pfa_file, "/version (%s) readonly def\n", fontm.name_version);
-
- fprintf(pfa_file, "/Notice (%s) readonly def\n", fontm.name_copyright);
-
- fprintf(pfa_file, "/FullName (%s) readonly def\n", fontm.name_full);
- fprintf(pfa_file, "/FamilyName (%s) readonly def\n", fontm.name_family);
-
- if(wantuid) {
- if(strUID)
- fprintf(pfa_file, "/UniqueID %s def\n", strUID);
- else {
- numUID=0;
- for(i=0; fontm.name_full[i]!=0; i++) {
- numUID *= 37; /* magic number, good for hash */
- numUID += fontm.name_full[i]-' ';
- /* if the name is long the first chars
- * may be lost forever, so re-insert
- * them thus making kind of CRC
- */
- numUID += (numUID>>24) & 0xFF;
- }
- /* the range for private UIDs is 4 000 000 - 4 999 999 */
- fprintf(pfa_file, "/UniqueID %lu def\n", numUID%1000000+4000000);
- }
- }
-
- fprintf(pfa_file, "/Weight (%s) readonly def\n", fontm.name_style);
-
- fprintf(pfa_file, "/ItalicAngle %f def\n", italic_angle);
- fprintf(pfa_file, "/isFixedPitch %s def\n",
- fontm.is_fixed_pitch ? "true" : "false");
-
- /* we don't print out the unused glyphs */
- nchars = 0;
- for (i = 0; i < numglyphs; i++) {
- if (glyph_list[i].flags & GF_USED) {
- nchars++;
- }
- }
-
- fprintf(afm_file, "StartFontMetrics 4.1\n");
- fprintf(afm_file, "FontName %s%s\n", fontm.name_ps, uni_font_name_suffix);
- fprintf(afm_file, "FullName %s\n", fontm.name_full);
- fprintf(afm_file, "Notice %s\n", fontm.name_copyright);
- fprintf(afm_file, "EncodingScheme FontSpecific\n");
- fprintf(afm_file, "FamilyName %s\n", fontm.name_family);
- fprintf(afm_file, "Weight %s\n", fontm.name_style);
- fprintf(afm_file, "Version %s\n", fontm.name_version);
- fprintf(afm_file, "Characters %d\n", nchars);
- fprintf(afm_file, "ItalicAngle %.1f\n", italic_angle);
-
- fprintf(afm_file, "Ascender %d\n", iscale(fontm.ascender));
- fprintf(afm_file, "Descender %d\n", iscale(fontm.descender));
-
- fprintf(pfa_file, "/UnderlinePosition %d def\n",
- iscale(fontm.underline_position));
-
- fprintf(pfa_file, "/UnderlineThickness %hd def\nend readonly def\n",
- iscale(fontm.underline_thickness));
-
- fprintf(afm_file, "UnderlineThickness %d\n",
- iscale(fontm.underline_thickness));
-
- fprintf(afm_file, "UnderlinePosition %d\n",
- iscale(fontm.underline_position));
-
- fprintf(afm_file, "IsFixedPitch %s\n",
- fontm.is_fixed_pitch ? "true" : "false");
- fprintf(afm_file, "FontBBox %d %d %d %d\n",
- bbox[0], bbox[1], bbox[2], bbox[3]);
-
- fprintf(pfa_file, "/FontName /%s%s def\n", fontm.name_ps, uni_font_name_suffix);
- fprintf(pfa_file, "/PaintType 0 def\n/StrokeWidth 0 def\n");
- /* I'm not sure if these are fixed */
- fprintf(pfa_file, "/FontType 1 def\n");
-
- if (transform) {
- fprintf(pfa_file, "/FontMatrix [0.001 0 0 0.001 0 0] def\n");
- } else {
- fprintf(pfa_file, "/FontMatrix [%9.7f 0 0 %9.7f 0 0] def\n",
- original_scale_factor / 1000.0, original_scale_factor / 1000.0);
- }
-
- fprintf(pfa_file, "/FontBBox {%d %d %d %d} readonly def\n",
- bbox[0], bbox[1], bbox[2], bbox[3]);
-
- fprintf(pfa_file, "/Encoding 256 array\n");
- /* determine number of elements for metrics table */
- nmetrics = 256;
- for (i = 0; i < numglyphs; i++) {
- if( glyph_list[i].flags & GF_USED
- && glyph_list[i].char_no == -1 ) {
- nmetrics++;
- }
- }
- fprintf(afm_file, "StartCharMetrics %d\n", nmetrics);
-
- fprintf(dvienc_file, "/%s%sEncoding [\n",
- fontm.name_ps, uni_font_name_suffix);
-
- for (i = 0; i < 256; i++) { /* here 256, not ENCTABSZ */
- fprintf(pfa_file,
- "dup %d /%s put\n", i, glyph_list[encoding[i]].name);
- if( glyph_list[encoding[i]].flags & GF_USED ) {
- print_glyph_metrics(i, encoding[i]);
- }
- if (encoding[i])
- fprintf (dvienc_file, "/index0x%04X\n", encoding[i]);
- else
- fprintf (dvienc_file, "/.notdef\n");
- }
-
- /* print the metrics for glyphs not in encoding table */
- for(i=0; i<numglyphs; i++) {
- if( (glyph_list[i].flags & GF_USED)
- && glyph_list[i].char_no == -1 ) {
- print_glyph_metrics(-1, i);
- }
- }
-
- fprintf(pfa_file, "readonly def\ncurrentdict end\ncurrentfile eexec\n");
- fprintf(pfa_file, "dup /Private 16 dict dup begin\n");
-
- fprintf(pfa_file, "/RD{string currentfile exch readstring pop}executeonly def\n");
- fprintf(pfa_file, "/ND{noaccess def}executeonly def\n");
- fprintf(pfa_file, "/NP{noaccess put}executeonly def\n");
-
- /* UniqueID must be shown twice, in both font and Private dictionary */
- if(wantuid) {
- if(strUID)
- fprintf(pfa_file, "/UniqueID %s def\n", strUID);
- else
- /* the range for private UIDs is 4 000 000 - 4 999 999 */
- fprintf(pfa_file, "/UniqueID %lu def\n", numUID%1000000+4000000);
- }
-
- if(forcebold==0)
- fprintf(pfa_file, "/ForceBold false def\n");
- else if(forcebold==1)
- fprintf(pfa_file, "/ForceBold true def\n");
-
- fprintf(pfa_file, "/BlueValues [ ");
- for (i = 0; i < nblues; i++)
- fprintf(pfa_file, "%d ", bluevalues[i]);
- fprintf(pfa_file, "] def\n");
-
- fprintf(pfa_file, "/OtherBlues [ ");
- for (i = 0; i < notherb; i++)
- fprintf(pfa_file, "%d ", otherblues[i]);
- fprintf(pfa_file, "] def\n");
-
- if (stdhw != 0)
- fprintf(pfa_file, "/StdHW [ %d ] def\n", stdhw);
- if (stdvw != 0)
- fprintf(pfa_file, "/StdVW [ %d ] def\n", stdvw);
- fprintf(pfa_file, "/StemSnapH [ ");
- for (i = 0; i < 12 && stemsnaph[i] != 0; i++)
- fprintf(pfa_file, "%d ", stemsnaph[i]);
- fprintf(pfa_file, "] def\n");
- fprintf(pfa_file, "/StemSnapV [ ");
- for (i = 0; i < 12 && stemsnapv[i] != 0; i++)
- fprintf(pfa_file, "%d ", stemsnapv[i]);
- fprintf(pfa_file, "] def\n");
-
- fprintf(pfa_file, "/MinFeature {16 16} def\n");
- /* Are these fixed also ? */
- fprintf(pfa_file, "/password 5839 def\n");
-
- /* calculate the number of subroutines */
-
- subid=5;
- for (i = 0; i < numglyphs; i++) {
- if (glyph_list[i].flags & GF_USED) {
- subid+=glyph_list[i].nsg;
- }
- }
-
- fprintf(pfa_file, "/Subrs %d array\n", subid);
- /* standard subroutines */
- fprintf(pfa_file, "dup 0 {\n\t3 0 callothersubr pop pop setcurrentpoint return\n\t} NP\n");
- fprintf(pfa_file, "dup 1 {\n\t0 1 callothersubr return\n\t} NP\n");
- fprintf(pfa_file, "dup 2 {\n\t0 2 callothersubr return\n\t} NP\n");
- fprintf(pfa_file, "dup 3 {\n\treturn\n\t} NP\n");
- /* our sub to make the hint substitution code shorter */
- fprintf(pfa_file, "dup 4 {\n\t1 3 callothersubr pop callsubr return\n\t} NP\n");
-
- if(pfa_file != null_file) { /* save time if the output would be wasted */
- /* print the hinting subroutines */
- subid=5;
- for (i = 0; i < numglyphs; i++) {
- if (glyph_list[i].flags & GF_USED) {
- subid+=print_glyph_subs(i, subid);
- }
- }
-
- fprintf(pfa_file, "ND\n");
-
- fprintf(pfa_file, "2 index /CharStrings %d dict dup begin\n", nchars);
-
- for (i = 0; i < numglyphs; i++) {
- if (glyph_list[i].flags & GF_USED) {
- print_glyph(i);
- }
- }
- }
-
-
- fprintf(pfa_file, "end\nend\nreadonly put\n");
- fprintf(pfa_file, "noaccess put\n");
- fprintf(pfa_file, "dup/FontName get exch definefont pop\n");
- fprintf(pfa_file, "mark currentfile closefile\n");
- fprintf(pfa_file, "cleartomark\n");
- if(pfa_file != null_file)
- fclose(pfa_file);
-
- fprintf(afm_file, "EndCharMetrics\n");
-
- if(afm_file != null_file) { /* save time if the output would be wasted */
- /* print the kerning data if present */
- cursw->kerning(glyph_list);
- print_kerning(afm_file);
- }
-
- fprintf(afm_file, "EndFontMetrics\n");
- if(afm_file != null_file)
- fclose(afm_file);
-
- fprintf(dvienc_file, "] def\n");
- if(dvienc_file != null_file)
- fclose(dvienc_file);
-
- WARNING_1 fprintf(stderr, "Finished - font files created\n");
-
- cursw->close();
-
-#ifndef NOPIPES
- while (wait(&ws) > 0) {
- }
-#else
- if (encode && pfa_file != null_file) {
- extern FILE *ifp, *ofp; /* from t1asm.c */
-
- snprintf(filename, sizeof filename, "%s.%s", argv[2], pfbflag ? "pfb" : "pfa" );
-
- if ((ofp = fopen(filename, "wb+")) == NULL) {
- exit(1);
- } else {
- WARNING_2 fprintf(stderr, "Creating file %s\n", filename);
- }
-
- snprintf(filename, sizeof filename, "%s.t1a", argv[2]);
-
- if ((ifp = fopen(filename, "rb")) == NULL) {
- exit(1);
- } else {
- WARNING_2 fprintf(stderr, "Converting file %s\n", filename);
- }
-
- runt1asm(pfbflag);
-
- WARNING_2 fprintf(stderr, "Removing file %s\n", filename);
- if(unlink(filename) < 0)
- WARNING_1 fprintf(stderr, "Unable to remove file %s\n", filename);
- }
-#endif /* NOPIPES */
-
- fclose(null_file);
- return 0;
-}
+++ /dev/null
-#ifndef __ttf2pt1_included__
-#define __ttf2pt1_included__
-#ifdef __cplusplus
-extern "C" {
-#endif
-int
-ttf2pt1_main(
- int argc,
- char **argv
-);
-#ifdef __cplusplus
-}
-#endif
-#endif
-
+++ /dev/null
-/*
- * see COPYRIGHT
- */
-
-
-/* version number */
-#define TTF2PT1_VERSION "3.4.3"
+++ /dev/null
-/*
- * Implementation of things missing in Windows
- */
-
-#ifndef M_PI
-#define M_PI 3.14159265358979323846
-#endif
-
-#undef ntohs
-#undef ntohl
-#undef htonl
-
-#ifdef WINDOWS_FUNCTIONS
-/* byte order */
-
-char *optarg;
-int optind=1;
-
-char getopt(int argc, char **argv, char *args) {
- int n,nlen=strlen(args),nLen=0;
- char nCmd;
-
- if (argv[optind] && *argv[optind]=='-') {
- nCmd=*((argv[optind]+1));
-
- for (n=0;n<nlen;n++) {
- if (args[n] == ':') continue;
- if (args[n] == nCmd) {
- if (args[n+1]==':') {
- char retVal;
- retVal=*(argv[optind]+1);
- optarg=argv[optind+1];
- if (!optarg) optarg="";
- optind+=2;
- return retVal;
- } else {
- char retVal;
- retVal=*(argv[optind]+1);
- optarg=NULL;
- optind+=1;
- return retVal;
- }
- }
- }
- }
- return -1;
-}
-
-#else
-
-unsigned short ntohs(unsigned short inv);
-unsigned long ntohl(unsigned long inv);
-unsigned long htonl(unsigned long inv);
-
-extern char *optarg;
-extern int optind;
-
-char getopt(int argc, char **argv, char *args);
-#endif
+++ /dev/null
-//========================================================================
-//
-// Annot.cc
-//
-// Copyright 2000-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma implementation
-#endif
-
-#include <stdlib.h>
-#include "gmem.h"
-#include "Object.h"
-#include "Catalog.h"
-#include "Gfx.h"
-#include "Lexer.h"
-#include "Annot.h"
-
-//------------------------------------------------------------------------
-// Annot
-//------------------------------------------------------------------------
-
-Annot::Annot(XRef *xrefA, Dict *acroForm, Dict *dict) {
- Object apObj, asObj, obj1, obj2;
- GBool regen, isTextField;
- double t;
-
- ok = gFalse;
- xref = xrefA;
- appearBuf = NULL;
-
- if (dict->lookup("Rect", &obj1)->isArray() &&
- obj1.arrayGetLength() == 4) {
- //~ should check object types here
- obj1.arrayGet(0, &obj2);
- xMin = obj2.getNum();
- obj2.free();
- obj1.arrayGet(1, &obj2);
- yMin = obj2.getNum();
- obj2.free();
- obj1.arrayGet(2, &obj2);
- xMax = obj2.getNum();
- obj2.free();
- obj1.arrayGet(3, &obj2);
- yMax = obj2.getNum();
- obj2.free();
- if (xMin > xMax) {
- t = xMin; xMin = xMax; xMax = t;
- }
- if (yMin > yMax) {
- t = yMin; yMin = yMax; yMax = t;
- }
- } else {
- //~ this should return an error
- xMin = yMin = 0;
- xMax = yMax = 1;
- }
- obj1.free();
-
- // check if field apperances need to be regenerated
- regen = gFalse;
- if (acroForm) {
- acroForm->lookup("NeedAppearances", &obj1);
- if (obj1.isBool() && obj1.getBool()) {
- regen = gTrue;
- }
- obj1.free();
- }
-
- // check for a text-type field
- isTextField = dict->lookup("FT", &obj1)->isName("Tx");
- obj1.free();
-
-#if 0 //~ appearance stream generation is not finished yet
- if (regen && isTextField) {
- generateAppearance(acroForm, dict);
- } else {
-#endif
- if (dict->lookup("AP", &apObj)->isDict()) {
- if (dict->lookup("AS", &asObj)->isName()) {
- if (apObj.dictLookup("N", &obj1)->isDict()) {
- if (obj1.dictLookupNF(asObj.getName(), &obj2)->isRef()) {
- obj2.copy(&appearance);
- ok = gTrue;
- } else {
- obj2.free();
- if (obj1.dictLookupNF("Off", &obj2)->isRef()) {
- obj2.copy(&appearance);
- ok = gTrue;
- }
- }
- obj2.free();
- }
- obj1.free();
- } else {
- if (apObj.dictLookupNF("N", &obj1)->isRef()) {
- obj1.copy(&appearance);
- ok = gTrue;
- }
- obj1.free();
- }
- asObj.free();
- }
- apObj.free();
-#if 0 //~ appearance stream generation is not finished yet
- }
-#endif
-}
-
-Annot::~Annot() {
- appearance.free();
- if (appearBuf) {
- delete appearBuf;
- }
-}
-
-void Annot::generateAppearance(Dict *acroForm, Dict *dict) {
- MemStream *appearStream;
- Object daObj, vObj, drObj, appearDict, obj1, obj2;
- GString *daStr, *daStr1, *vStr, *s;
- char buf[256];
- double fontSize;
- int c;
- int i0, i1;
-
- //~ DA can be inherited
- if (dict->lookup("DA", &daObj)->isString()) {
- daStr = daObj.getString();
-
- // look for a font size
- //~ may want to parse the DS entry in place of this (if it exists)
- daStr1 = NULL;
- fontSize = 10;
- for (i1 = daStr->getLength() - 2; i1 >= 0; --i1) {
- if (daStr->getChar(i1) == 'T' && daStr->getChar(i1+1) == 'f') {
- for (--i1; i1 >= 0 && Lexer::isSpace(daStr->getChar(i1)); --i1) ;
- for (i0 = i1; i0 >= 0 && !Lexer::isSpace(daStr->getChar(i0)); --i0) ;
- if (i0 >= 0) {
- ++i0;
- ++i1;
- s = new GString(daStr, i0, i1 - i0);
- fontSize = atof(s->getCString());
- delete s;
-
- // autosize the font
- if (fontSize == 0) {
- fontSize = 0.67 * (yMax - yMin);
- daStr1 = new GString(daStr, 0, i0);
- sprintf(buf, "%.2f", fontSize);
- daStr1->append(buf);
- daStr1->append(daStr->getCString() + i1,
- daStr->getLength() - i1);
- }
- }
- break;
- }
- }
-
- // build the appearance stream contents
- appearBuf = new GString();
- appearBuf->append("/Tx BMC\n");
- appearBuf->append("q BT\n");
- appearBuf->append(daStr1 ? daStr1 : daStr)->append("\n");
- if (dict->lookup("V", &vObj)->isString()) {
- //~ handle quadding -- this requires finding the font and using
- //~ the encoding and char widths
- sprintf(buf, "1 0 0 1 %.2f %.2f Tm\n", 2.0, yMax - yMin - fontSize);
- appearBuf->append(buf);
- sprintf(buf, "%g TL\n", fontSize);
- appearBuf->append(buf);
- vStr = vObj.getString();
- i0 = 0;
- while (i0 < vStr->getLength()) {
- for (i1 = i0;
- i1 < vStr->getLength() &&
- vStr->getChar(i1) != '\n' && vStr->getChar(i1) != '\r';
- ++i1) ;
- if (i0 > 0) {
- appearBuf->append("T*\n");
- }
- appearBuf->append('(');
- for (; i0 < i1; ++i0) {
- c = vStr->getChar(i0);
- if (c == '(' || c == ')' || c == '\\') {
- appearBuf->append('\\');
- appearBuf->append(c);
- } else if (c < 0x20 || c >= 0x80) {
- sprintf(buf, "\\%03o", c);
- appearBuf->append(buf);
- } else {
- appearBuf->append(c);
- }
- }
- appearBuf->append(") Tj\n");
- if (i1 + 1 < vStr->getLength() &&
- vStr->getChar(i1) == '\r' && vStr->getChar(i1 + 1) == '\n') {
- i0 = i1 + 2;
- } else {
- i0 = i1 + 1;
- }
- }
- }
- vObj.free();
- appearBuf->append("ET Q\n");
- appearBuf->append("EMC\n");
-
- // build the appearance stream dictionary
- appearDict.initDict(xref);
- appearDict.dictAdd(copyString("Length"),
- obj1.initInt(appearBuf->getLength()));
- appearDict.dictAdd(copyString("Subtype"), obj1.initName("Form"));
- obj1.initArray(xref);
- obj1.arrayAdd(obj2.initReal(0));
- obj1.arrayAdd(obj2.initReal(0));
- obj1.arrayAdd(obj2.initReal(xMax - xMin));
- obj1.arrayAdd(obj2.initReal(yMax - yMin));
- appearDict.dictAdd(copyString("BBox"), &obj1);
-
- // find the resource dictionary
- dict->lookup("DR", &drObj);
- if (!drObj.isDict()) {
- dict->lookup("Parent", &obj1);
- while (obj1.isDict()) {
- drObj.free();
- obj1.dictLookup("DR", &drObj);
- if (drObj.isDict()) {
- break;
- }
- obj1.dictLookup("Parent", &obj2);
- obj1.free();
- obj1 = obj2;
- }
- obj1.free();
- if (!drObj.isDict()) {
- if (acroForm) {
- drObj.free();
- acroForm->lookup("DR", &drObj);
- }
- }
- }
- if (drObj.isDict()) {
- appearDict.dictAdd(copyString("Resources"), drObj.copy(&obj1));
- }
- drObj.free();
-
- // build the appearance stream
- appearStream = new MemStream(appearBuf->getCString(), 0,
- appearBuf->getLength(), &appearDict);
- appearance.initStream(appearStream);
- ok = gTrue;
-
- if (daStr1) {
- delete daStr1;
- }
- }
- daObj.free();
-}
-
-void Annot::draw(Gfx *gfx) {
- Object obj;
-
- if (appearance.fetch(xref, &obj)->isStream()) {
- gfx->doAnnot(&obj, xMin, yMin, xMax, yMax);
- }
- obj.free();
-}
-
-//------------------------------------------------------------------------
-// Annots
-//------------------------------------------------------------------------
-
-Annots::Annots(XRef *xref, Catalog *catalog, Object *annotsObj) {
- Dict *acroForm;
- Annot *annot;
- Object obj1;
- int size;
- int i;
-
- annots = NULL;
- size = 0;
- nAnnots = 0;
-
- acroForm = catalog->getAcroForm()->isDict() ?
- catalog->getAcroForm()->getDict() : NULL;
- if (annotsObj->isArray()) {
- for (i = 0; i < annotsObj->arrayGetLength(); ++i) {
- if (annotsObj->arrayGet(i, &obj1)->isDict()) {
- annot = new Annot(xref, acroForm, obj1.getDict());
- if (annot->isOk()) {
- if (nAnnots >= size) {
- size += 16;
- annots = (Annot **)greallocn(annots, size, sizeof(Annot *));
- }
- annots[nAnnots++] = annot;
- } else {
- delete annot;
- }
- }
- obj1.free();
- }
- }
-}
-
-Annots::~Annots() {
- int i;
-
- for (i = 0; i < nAnnots; ++i) {
- delete annots[i];
- }
- gfree(annots);
-}
+++ /dev/null
-//========================================================================
-//
-// Annot.h
-//
-// Copyright 2000-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#ifndef ANNOT_H
-#define ANNOT_H
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma interface
-#endif
-
-class XRef;
-class Catalog;
-class Gfx;
-
-//------------------------------------------------------------------------
-// Annot
-//------------------------------------------------------------------------
-
-class Annot {
-public:
-
- Annot(XRef *xrefA, Dict *acroForm, Dict *dict);
- ~Annot();
- GBool isOk() { return ok; }
-
- void draw(Gfx *gfx);
-
- // Get appearance object.
- Object *getAppearance(Object *obj) { return appearance.fetch(xref, obj); }
-
-private:
-
- void generateAppearance(Dict *acroForm, Dict *dict);
-
- XRef *xref; // the xref table for this PDF file
- Object appearance; // a reference to the Form XObject stream
- // for the normal appearance
- GString *appearBuf;
- double xMin, yMin, // annotation rectangle
- xMax, yMax;
- GBool ok;
-};
-
-//------------------------------------------------------------------------
-// Annots
-//------------------------------------------------------------------------
-
-class Annots {
-public:
-
- // Extract non-link annotations from array of annotations.
- Annots(XRef *xref, Catalog *catalog, Object *annotsObj);
-
- ~Annots();
-
- // Iterate through list of annotations.
- int getNumAnnots() { return nAnnots; }
- Annot *getAnnot(int i) { return annots[i]; }
-
-private:
-
- Annot **annots;
- int nAnnots;
-};
-
-#endif
+++ /dev/null
-//========================================================================
-//
-// Array.cc
-//
-// Copyright 1996-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma implementation
-#endif
-
-#include <stdlib.h>
-#include <stddef.h>
-#include "gmem.h"
-#include "Object.h"
-#include "Array.h"
-
-//------------------------------------------------------------------------
-// Array
-//------------------------------------------------------------------------
-
-Array::Array(XRef *xrefA) {
- xref = xrefA;
- elems = NULL;
- size = length = 0;
- ref = 1;
-}
-
-Array::~Array() {
- int i;
-
- for (i = 0; i < length; ++i)
- elems[i].free();
- gfree(elems);
-}
-
-void Array::add(Object *elem) {
- if (length == size) {
- if (length == 0) {
- size = 8;
- } else {
- size *= 2;
- }
- elems = (Object *)greallocn(elems, size, sizeof(Object));
- }
- elems[length] = *elem;
- ++length;
-}
-
-Object *Array::get(int i, Object *obj) {
- if (i < 0 || i >= length) {
-#ifdef DEBUG_MEM
- abort();
-#else
- return obj->initNull();
-#endif
- }
- return elems[i].fetch(xref, obj);
-}
-
-Object *Array::getNF(int i, Object *obj) {
- if (i < 0 || i >= length) {
-#ifdef DEBUG_MEM
- abort();
-#else
- return obj->initNull();
-#endif
- }
- return elems[i].copy(obj);
-}
+++ /dev/null
-//========================================================================
-//
-// Array.h
-//
-// Copyright 1996-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#ifndef ARRAY_H
-#define ARRAY_H
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma interface
-#endif
-
-#include "Object.h"
-
-class XRef;
-
-//------------------------------------------------------------------------
-// Array
-//------------------------------------------------------------------------
-
-class Array {
-public:
-
- // Constructor.
- Array(XRef *xrefA);
-
- // Destructor.
- ~Array();
-
- // Reference counting.
- int incRef() { return ++ref; }
- int decRef() { return --ref; }
-
- // Get number of elements.
- int getLength() { return length; }
-
- // Add an element.
- void add(Object *elem);
-
- // Accessors.
- Object *get(int i, Object *obj);
- Object *getNF(int i, Object *obj);
-
-private:
-
- XRef *xref; // the xref table for this PDF file
- Object *elems; // array of elements
- int size; // size of <elems> array
- int length; // number of elements in array
- int ref; // reference count
-};
-
-#endif
+++ /dev/null
-//========================================================================
-//
-// BuiltinFont.cc
-//
-// Copyright 2001-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma implementation
-#endif
-
-#include <stdlib.h>
-#include <string.h>
-#include "gmem.h"
-#include "FontEncodingTables.h"
-#include "BuiltinFont.h"
-
-//------------------------------------------------------------------------
-
-BuiltinFontWidths::BuiltinFontWidths(BuiltinFontWidth *widths, int sizeA) {
- int i, h;
-
- size = sizeA;
- tab = (BuiltinFontWidth **)gmallocn(size, sizeof(BuiltinFontWidth *));
- for (i = 0; i < size; ++i) {
- tab[i] = NULL;
- }
- for (i = 0; i < sizeA; ++i) {
- h = hash(widths[i].name);
- widths[i].next = tab[h];
- tab[h] = &widths[i];
- }
-}
-
-BuiltinFontWidths::~BuiltinFontWidths() {
- gfree(tab);
-}
-
-GBool BuiltinFontWidths::getWidth(char *name, Gushort *width) {
- int h;
- BuiltinFontWidth *p;
-
- h = hash(name);
- for (p = tab[h]; p; p = p->next) {
- if (!strcmp(p->name, name)) {
- *width = p->width;
- return gTrue;
- }
- }
- return gFalse;
-}
-
-int BuiltinFontWidths::hash(char *name) {
- char *p;
- unsigned int h;
-
- h = 0;
- for (p = name; *p; ++p) {
- h = 17 * h + (int)(*p & 0xff);
- }
- return (int)(h % size);
-}
+++ /dev/null
-//========================================================================
-//
-// BuiltinFont.h
-//
-// Copyright 2001-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#ifndef BUILTINFONT_H
-#define BUILTINFONT_H
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma interface
-#endif
-
-#include "gtypes.h"
-
-struct BuiltinFont;
-class BuiltinFontWidths;
-
-//------------------------------------------------------------------------
-
-struct BuiltinFont {
- char *name;
- char **defaultBaseEnc;
- short ascent;
- short descent;
- short bbox[4];
- BuiltinFontWidths *widths;
-};
-
-//------------------------------------------------------------------------
-
-struct BuiltinFontWidth {
- char *name;
- Gushort width;
- BuiltinFontWidth *next;
-};
-
-class BuiltinFontWidths {
-public:
-
- BuiltinFontWidths(BuiltinFontWidth *widths, int sizeA);
- ~BuiltinFontWidths();
- GBool getWidth(char *name, Gushort *width);
-
-private:
-
- int hash(char *name);
-
- BuiltinFontWidth **tab;
- int size;
-};
-
-#endif
+++ /dev/null
-//========================================================================
-//
-// BuiltinFontTables.cc
-//
-// Copyright 2001-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#include <aconf.h>
-#include <stdlib.h>
-#include "FontEncodingTables.h"
-#include "BuiltinFontTables.h"
-
-static BuiltinFontWidth courierWidthsTab[] = {
- { "Ntilde", 600, NULL },
- { "rcaron", 600, NULL },
- { "kcommaaccent", 600, NULL },
- { "Ncommaaccent", 600, NULL },
- { "Zacute", 600, NULL },
- { "comma", 600, NULL },
- { "cedilla", 600, NULL },
- { "plusminus", 600, NULL },
- { "circumflex", 600, NULL },
- { "dotaccent", 600, NULL },
- { "edotaccent", 600, NULL },
- { "asciitilde", 600, NULL },
- { "colon", 600, NULL },
- { "onehalf", 600, NULL },
- { "dollar", 600, NULL },
- { "Lcaron", 600, NULL },
- { "ntilde", 600, NULL },
- { "Aogonek", 600, NULL },
- { "ncommaaccent", 600, NULL },
- { "minus", 600, NULL },
- { "Iogonek", 600, NULL },
- { "zacute", 600, NULL },
- { "yen", 600, NULL },
- { "space", 600, NULL },
- { "Omacron", 600, NULL },
- { "questiondown", 600, NULL },
- { "emdash", 600, NULL },
- { "Agrave", 600, NULL },
- { "three", 600, NULL },
- { "numbersign", 600, NULL },
- { "lcaron", 600, NULL },
- { "A", 600, NULL },
- { "B", 600, NULL },
- { "C", 600, NULL },
- { "aogonek", 600, NULL },
- { "D", 600, NULL },
- { "E", 600, NULL },
- { "onequarter", 600, NULL },
- { "F", 600, NULL },
- { "G", 600, NULL },
- { "H", 600, NULL },
- { "I", 600, NULL },
- { "J", 600, NULL },
- { "K", 600, NULL },
- { "iogonek", 600, NULL },
- { "L", 600, NULL },
- { "backslash", 600, NULL },
- { "periodcentered", 600, NULL },
- { "M", 600, NULL },
- { "N", 600, NULL },
- { "omacron", 600, NULL },
- { "Tcommaaccent", 600, NULL },
- { "O", 600, NULL },
- { "P", 600, NULL },
- { "Q", 600, NULL },
- { "Uhungarumlaut", 600, NULL },
- { "R", 600, NULL },
- { "Aacute", 600, NULL },
- { "caron", 600, NULL },
- { "S", 600, NULL },
- { "T", 600, NULL },
- { "U", 600, NULL },
- { "agrave", 600, NULL },
- { "V", 600, NULL },
- { "W", 600, NULL },
- { "equal", 600, NULL },
- { "question", 600, NULL },
- { "X", 600, NULL },
- { "Y", 600, NULL },
- { "Z", 600, NULL },
- { "four", 600, NULL },
- { "a", 600, NULL },
- { "Gcommaaccent", 600, NULL },
- { "b", 600, NULL },
- { "c", 600, NULL },
- { "d", 600, NULL },
- { "e", 600, NULL },
- { "f", 600, NULL },
- { "g", 600, NULL },
- { "bullet", 600, NULL },
- { "h", 600, NULL },
- { "i", 600, NULL },
- { "Oslash", 600, NULL },
- { "dagger", 600, NULL },
- { "j", 600, NULL },
- { "k", 600, NULL },
- { "l", 600, NULL },
- { "m", 600, NULL },
- { "n", 600, NULL },
- { "tcommaaccent", 600, NULL },
- { "o", 600, NULL },
- { "ordfeminine", 600, NULL },
- { "ring", 600, NULL },
- { "p", 600, NULL },
- { "q", 600, NULL },
- { "uhungarumlaut", 600, NULL },
- { "r", 600, NULL },
- { "twosuperior", 600, NULL },
- { "aacute", 600, NULL },
- { "s", 600, NULL },
- { "OE", 600, NULL },
- { "t", 600, NULL },
- { "divide", 600, NULL },
- { "u", 600, NULL },
- { "Ccaron", 600, NULL },
- { "v", 600, NULL },
- { "w", 600, NULL },
- { "x", 600, NULL },
- { "y", 600, NULL },
- { "z", 600, NULL },
- { "Gbreve", 600, NULL },
- { "commaaccent", 600, NULL },
- { "hungarumlaut", 600, NULL },
- { "Idotaccent", 600, NULL },
- { "Nacute", 600, NULL },
- { "quotedbl", 600, NULL },
- { "gcommaaccent", 600, NULL },
- { "mu", 600, NULL },
- { "greaterequal", 600, NULL },
- { "Scaron", 600, NULL },
- { "Lslash", 600, NULL },
- { "semicolon", 600, NULL },
- { "oslash", 600, NULL },
- { "lessequal", 600, NULL },
- { "lozenge", 600, NULL },
- { "parenright", 600, NULL },
- { "ccaron", 600, NULL },
- { "Ecircumflex", 600, NULL },
- { "gbreve", 600, NULL },
- { "trademark", 600, NULL },
- { "daggerdbl", 600, NULL },
- { "nacute", 600, NULL },
- { "macron", 600, NULL },
- { "Otilde", 600, NULL },
- { "Emacron", 600, NULL },
- { "ellipsis", 600, NULL },
- { "scaron", 600, NULL },
- { "AE", 600, NULL },
- { "Ucircumflex", 600, NULL },
- { "lslash", 600, NULL },
- { "quotedblleft", 600, NULL },
- { "hyphen", 600, NULL },
- { "guilsinglright", 600, NULL },
- { "quotesingle", 600, NULL },
- { "eight", 600, NULL },
- { "exclamdown", 600, NULL },
- { "endash", 600, NULL },
- { "oe", 600, NULL },
- { "Abreve", 600, NULL },
- { "Umacron", 600, NULL },
- { "ecircumflex", 600, NULL },
- { "Adieresis", 600, NULL },
- { "copyright", 600, NULL },
- { "Egrave", 600, NULL },
- { "slash", 600, NULL },
- { "Edieresis", 600, NULL },
- { "otilde", 600, NULL },
- { "Idieresis", 600, NULL },
- { "parenleft", 600, NULL },
- { "one", 600, NULL },
- { "emacron", 600, NULL },
- { "Odieresis", 600, NULL },
- { "ucircumflex", 600, NULL },
- { "bracketleft", 600, NULL },
- { "Ugrave", 600, NULL },
- { "quoteright", 600, NULL },
- { "Udieresis", 600, NULL },
- { "perthousand", 600, NULL },
- { "Ydieresis", 600, NULL },
- { "umacron", 600, NULL },
- { "abreve", 600, NULL },
- { "Eacute", 600, NULL },
- { "adieresis", 600, NULL },
- { "egrave", 600, NULL },
- { "edieresis", 600, NULL },
- { "idieresis", 600, NULL },
- { "Eth", 600, NULL },
- { "ae", 600, NULL },
- { "asterisk", 600, NULL },
- { "odieresis", 600, NULL },
- { "Uacute", 600, NULL },
- { "ugrave", 600, NULL },
- { "five", 600, NULL },
- { "nine", 600, NULL },
- { "udieresis", 600, NULL },
- { "Zcaron", 600, NULL },
- { "Scommaaccent", 600, NULL },
- { "threequarters", 600, NULL },
- { "guillemotright", 600, NULL },
- { "Ccedilla", 600, NULL },
- { "ydieresis", 600, NULL },
- { "tilde", 600, NULL },
- { "at", 600, NULL },
- { "eacute", 600, NULL },
- { "underscore", 600, NULL },
- { "Euro", 600, NULL },
- { "Dcroat", 600, NULL },
- { "zero", 600, NULL },
- { "multiply", 600, NULL },
- { "eth", 600, NULL },
- { "Scedilla", 600, NULL },
- { "Racute", 600, NULL },
- { "Ograve", 600, NULL },
- { "partialdiff", 600, NULL },
- { "uacute", 600, NULL },
- { "braceleft", 600, NULL },
- { "Thorn", 600, NULL },
- { "zcaron", 600, NULL },
- { "scommaaccent", 600, NULL },
- { "ccedilla", 600, NULL },
- { "Dcaron", 600, NULL },
- { "dcroat", 600, NULL },
- { "scedilla", 600, NULL },
- { "Oacute", 600, NULL },
- { "Ocircumflex", 600, NULL },
- { "ogonek", 600, NULL },
- { "ograve", 600, NULL },
- { "racute", 600, NULL },
- { "Tcaron", 600, NULL },
- { "Eogonek", 600, NULL },
- { "thorn", 600, NULL },
- { "degree", 600, NULL },
- { "registered", 600, NULL },
- { "radical", 600, NULL },
- { "Aring", 600, NULL },
- { "percent", 600, NULL },
- { "six", 600, NULL },
- { "paragraph", 600, NULL },
- { "dcaron", 600, NULL },
- { "Uogonek", 600, NULL },
- { "two", 600, NULL },
- { "summation", 600, NULL },
- { "Igrave", 600, NULL },
- { "Lacute", 600, NULL },
- { "ocircumflex", 600, NULL },
- { "oacute", 600, NULL },
- { "Uring", 600, NULL },
- { "Lcommaaccent", 600, NULL },
- { "tcaron", 600, NULL },
- { "eogonek", 600, NULL },
- { "Delta", 600, NULL },
- { "Ohungarumlaut", 600, NULL },
- { "asciicircum", 600, NULL },
- { "aring", 600, NULL },
- { "grave", 600, NULL },
- { "uogonek", 600, NULL },
- { "bracketright", 600, NULL },
- { "ampersand", 600, NULL },
- { "Iacute", 600, NULL },
- { "lacute", 600, NULL },
- { "igrave", 600, NULL },
- { "Ncaron", 600, NULL },
- { "plus", 600, NULL },
- { "uring", 600, NULL },
- { "quotesinglbase", 600, NULL },
- { "lcommaaccent", 600, NULL },
- { "Yacute", 600, NULL },
- { "ohungarumlaut", 600, NULL },
- { "threesuperior", 600, NULL },
- { "acute", 600, NULL },
- { "section", 600, NULL },
- { "dieresis", 600, NULL },
- { "quotedblbase", 600, NULL },
- { "iacute", 600, NULL },
- { "ncaron", 600, NULL },
- { "florin", 600, NULL },
- { "yacute", 600, NULL },
- { "Rcommaaccent", 600, NULL },
- { "fi", 600, NULL },
- { "fl", 600, NULL },
- { "Acircumflex", 600, NULL },
- { "Cacute", 600, NULL },
- { "Icircumflex", 600, NULL },
- { "guillemotleft", 600, NULL },
- { "germandbls", 600, NULL },
- { "seven", 600, NULL },
- { "Amacron", 600, NULL },
- { "Sacute", 600, NULL },
- { "ordmasculine", 600, NULL },
- { "dotlessi", 600, NULL },
- { "sterling", 600, NULL },
- { "notequal", 600, NULL },
- { "Imacron", 600, NULL },
- { "rcommaaccent", 600, NULL },
- { "Zdotaccent", 600, NULL },
- { "acircumflex", 600, NULL },
- { "cacute", 600, NULL },
- { "Ecaron", 600, NULL },
- { "braceright", 600, NULL },
- { "icircumflex", 600, NULL },
- { "quotedblright", 600, NULL },
- { "amacron", 600, NULL },
- { "sacute", 600, NULL },
- { "imacron", 600, NULL },
- { "cent", 600, NULL },
- { "currency", 600, NULL },
- { "logicalnot", 600, NULL },
- { "zdotaccent", 600, NULL },
- { "Atilde", 600, NULL },
- { "breve", 600, NULL },
- { "bar", 600, NULL },
- { "fraction", 600, NULL },
- { "less", 600, NULL },
- { "ecaron", 600, NULL },
- { "guilsinglleft", 600, NULL },
- { "exclam", 600, NULL },
- { "period", 600, NULL },
- { "Rcaron", 600, NULL },
- { "Kcommaaccent", 600, NULL },
- { "greater", 600, NULL },
- { "atilde", 600, NULL },
- { "brokenbar", 600, NULL },
- { "quoteleft", 600, NULL },
- { "Edotaccent", 600, NULL },
- { "onesuperior", 600, NULL }
-};
-
-static BuiltinFontWidth courierBoldWidthsTab[] = {
- { "Ntilde", 600, NULL },
- { "rcaron", 600, NULL },
- { "kcommaaccent", 600, NULL },
- { "Ncommaaccent", 600, NULL },
- { "Zacute", 600, NULL },
- { "comma", 600, NULL },
- { "cedilla", 600, NULL },
- { "plusminus", 600, NULL },
- { "circumflex", 600, NULL },
- { "dotaccent", 600, NULL },
- { "edotaccent", 600, NULL },
- { "asciitilde", 600, NULL },
- { "colon", 600, NULL },
- { "onehalf", 600, NULL },
- { "dollar", 600, NULL },
- { "Lcaron", 600, NULL },
- { "ntilde", 600, NULL },
- { "Aogonek", 600, NULL },
- { "ncommaaccent", 600, NULL },
- { "minus", 600, NULL },
- { "Iogonek", 600, NULL },
- { "zacute", 600, NULL },
- { "yen", 600, NULL },
- { "space", 600, NULL },
- { "Omacron", 600, NULL },
- { "questiondown", 600, NULL },
- { "emdash", 600, NULL },
- { "Agrave", 600, NULL },
- { "three", 600, NULL },
- { "numbersign", 600, NULL },
- { "lcaron", 600, NULL },
- { "A", 600, NULL },
- { "B", 600, NULL },
- { "C", 600, NULL },
- { "aogonek", 600, NULL },
- { "D", 600, NULL },
- { "E", 600, NULL },
- { "onequarter", 600, NULL },
- { "F", 600, NULL },
- { "G", 600, NULL },
- { "H", 600, NULL },
- { "I", 600, NULL },
- { "J", 600, NULL },
- { "K", 600, NULL },
- { "iogonek", 600, NULL },
- { "backslash", 600, NULL },
- { "L", 600, NULL },
- { "periodcentered", 600, NULL },
- { "M", 600, NULL },
- { "N", 600, NULL },
- { "omacron", 600, NULL },
- { "Tcommaaccent", 600, NULL },
- { "O", 600, NULL },
- { "P", 600, NULL },
- { "Q", 600, NULL },
- { "Uhungarumlaut", 600, NULL },
- { "R", 600, NULL },
- { "Aacute", 600, NULL },
- { "caron", 600, NULL },
- { "S", 600, NULL },
- { "T", 600, NULL },
- { "U", 600, NULL },
- { "agrave", 600, NULL },
- { "V", 600, NULL },
- { "W", 600, NULL },
- { "X", 600, NULL },
- { "question", 600, NULL },
- { "equal", 600, NULL },
- { "Y", 600, NULL },
- { "Z", 600, NULL },
- { "four", 600, NULL },
- { "a", 600, NULL },
- { "Gcommaaccent", 600, NULL },
- { "b", 600, NULL },
- { "c", 600, NULL },
- { "d", 600, NULL },
- { "e", 600, NULL },
- { "f", 600, NULL },
- { "g", 600, NULL },
- { "bullet", 600, NULL },
- { "h", 600, NULL },
- { "i", 600, NULL },
- { "Oslash", 600, NULL },
- { "dagger", 600, NULL },
- { "j", 600, NULL },
- { "k", 600, NULL },
- { "l", 600, NULL },
- { "m", 600, NULL },
- { "n", 600, NULL },
- { "tcommaaccent", 600, NULL },
- { "o", 600, NULL },
- { "ordfeminine", 600, NULL },
- { "ring", 600, NULL },
- { "p", 600, NULL },
- { "q", 600, NULL },
- { "uhungarumlaut", 600, NULL },
- { "r", 600, NULL },
- { "twosuperior", 600, NULL },
- { "aacute", 600, NULL },
- { "s", 600, NULL },
- { "OE", 600, NULL },
- { "t", 600, NULL },
- { "divide", 600, NULL },
- { "u", 600, NULL },
- { "Ccaron", 600, NULL },
- { "v", 600, NULL },
- { "w", 600, NULL },
- { "x", 600, NULL },
- { "y", 600, NULL },
- { "z", 600, NULL },
- { "Gbreve", 600, NULL },
- { "commaaccent", 600, NULL },
- { "hungarumlaut", 600, NULL },
- { "Idotaccent", 600, NULL },
- { "Nacute", 600, NULL },
- { "quotedbl", 600, NULL },
- { "gcommaaccent", 600, NULL },
- { "mu", 600, NULL },
- { "greaterequal", 600, NULL },
- { "Scaron", 600, NULL },
- { "Lslash", 600, NULL },
- { "semicolon", 600, NULL },
- { "oslash", 600, NULL },
- { "lessequal", 600, NULL },
- { "lozenge", 600, NULL },
- { "parenright", 600, NULL },
- { "ccaron", 600, NULL },
- { "Ecircumflex", 600, NULL },
- { "gbreve", 600, NULL },
- { "trademark", 600, NULL },
- { "daggerdbl", 600, NULL },
- { "nacute", 600, NULL },
- { "macron", 600, NULL },
- { "Otilde", 600, NULL },
- { "Emacron", 600, NULL },
- { "ellipsis", 600, NULL },
- { "scaron", 600, NULL },
- { "AE", 600, NULL },
- { "Ucircumflex", 600, NULL },
- { "lslash", 600, NULL },
- { "quotedblleft", 600, NULL },
- { "guilsinglright", 600, NULL },
- { "hyphen", 600, NULL },
- { "quotesingle", 600, NULL },
- { "eight", 600, NULL },
- { "exclamdown", 600, NULL },
- { "endash", 600, NULL },
- { "oe", 600, NULL },
- { "Abreve", 600, NULL },
- { "Umacron", 600, NULL },
- { "ecircumflex", 600, NULL },
- { "Adieresis", 600, NULL },
- { "copyright", 600, NULL },
- { "Egrave", 600, NULL },
- { "slash", 600, NULL },
- { "Edieresis", 600, NULL },
- { "otilde", 600, NULL },
- { "Idieresis", 600, NULL },
- { "parenleft", 600, NULL },
- { "one", 600, NULL },
- { "emacron", 600, NULL },
- { "Odieresis", 600, NULL },
- { "ucircumflex", 600, NULL },
- { "bracketleft", 600, NULL },
- { "Ugrave", 600, NULL },
- { "quoteright", 600, NULL },
- { "Udieresis", 600, NULL },
- { "perthousand", 600, NULL },
- { "Ydieresis", 600, NULL },
- { "umacron", 600, NULL },
- { "abreve", 600, NULL },
- { "Eacute", 600, NULL },
- { "adieresis", 600, NULL },
- { "egrave", 600, NULL },
- { "edieresis", 600, NULL },
- { "idieresis", 600, NULL },
- { "Eth", 600, NULL },
- { "ae", 600, NULL },
- { "asterisk", 600, NULL },
- { "odieresis", 600, NULL },
- { "Uacute", 600, NULL },
- { "ugrave", 600, NULL },
- { "nine", 600, NULL },
- { "five", 600, NULL },
- { "udieresis", 600, NULL },
- { "Zcaron", 600, NULL },
- { "Scommaaccent", 600, NULL },
- { "threequarters", 600, NULL },
- { "guillemotright", 600, NULL },
- { "Ccedilla", 600, NULL },
- { "ydieresis", 600, NULL },
- { "tilde", 600, NULL },
- { "at", 600, NULL },
- { "eacute", 600, NULL },
- { "underscore", 600, NULL },
- { "Euro", 600, NULL },
- { "Dcroat", 600, NULL },
- { "multiply", 600, NULL },
- { "zero", 600, NULL },
- { "eth", 600, NULL },
- { "Scedilla", 600, NULL },
- { "Ograve", 600, NULL },
- { "Racute", 600, NULL },
- { "partialdiff", 600, NULL },
- { "uacute", 600, NULL },
- { "braceleft", 600, NULL },
- { "Thorn", 600, NULL },
- { "zcaron", 600, NULL },
- { "scommaaccent", 600, NULL },
- { "ccedilla", 600, NULL },
- { "Dcaron", 600, NULL },
- { "dcroat", 600, NULL },
- { "Ocircumflex", 600, NULL },
- { "Oacute", 600, NULL },
- { "scedilla", 600, NULL },
- { "ogonek", 600, NULL },
- { "ograve", 600, NULL },
- { "racute", 600, NULL },
- { "Tcaron", 600, NULL },
- { "Eogonek", 600, NULL },
- { "thorn", 600, NULL },
- { "degree", 600, NULL },
- { "registered", 600, NULL },
- { "radical", 600, NULL },
- { "Aring", 600, NULL },
- { "percent", 600, NULL },
- { "six", 600, NULL },
- { "paragraph", 600, NULL },
- { "dcaron", 600, NULL },
- { "Uogonek", 600, NULL },
- { "two", 600, NULL },
- { "summation", 600, NULL },
- { "Igrave", 600, NULL },
- { "Lacute", 600, NULL },
- { "ocircumflex", 600, NULL },
- { "oacute", 600, NULL },
- { "Uring", 600, NULL },
- { "Lcommaaccent", 600, NULL },
- { "tcaron", 600, NULL },
- { "eogonek", 600, NULL },
- { "Delta", 600, NULL },
- { "Ohungarumlaut", 600, NULL },
- { "asciicircum", 600, NULL },
- { "aring", 600, NULL },
- { "grave", 600, NULL },
- { "uogonek", 600, NULL },
- { "bracketright", 600, NULL },
- { "Iacute", 600, NULL },
- { "ampersand", 600, NULL },
- { "igrave", 600, NULL },
- { "lacute", 600, NULL },
- { "Ncaron", 600, NULL },
- { "plus", 600, NULL },
- { "uring", 600, NULL },
- { "quotesinglbase", 600, NULL },
- { "lcommaaccent", 600, NULL },
- { "Yacute", 600, NULL },
- { "ohungarumlaut", 600, NULL },
- { "threesuperior", 600, NULL },
- { "acute", 600, NULL },
- { "section", 600, NULL },
- { "dieresis", 600, NULL },
- { "iacute", 600, NULL },
- { "quotedblbase", 600, NULL },
- { "ncaron", 600, NULL },
- { "florin", 600, NULL },
- { "yacute", 600, NULL },
- { "Rcommaaccent", 600, NULL },
- { "fi", 600, NULL },
- { "fl", 600, NULL },
- { "Acircumflex", 600, NULL },
- { "Cacute", 600, NULL },
- { "Icircumflex", 600, NULL },
- { "guillemotleft", 600, NULL },
- { "germandbls", 600, NULL },
- { "Amacron", 600, NULL },
- { "seven", 600, NULL },
- { "Sacute", 600, NULL },
- { "ordmasculine", 600, NULL },
- { "dotlessi", 600, NULL },
- { "sterling", 600, NULL },
- { "notequal", 600, NULL },
- { "Imacron", 600, NULL },
- { "rcommaaccent", 600, NULL },
- { "Zdotaccent", 600, NULL },
- { "acircumflex", 600, NULL },
- { "cacute", 600, NULL },
- { "Ecaron", 600, NULL },
- { "icircumflex", 600, NULL },
- { "braceright", 600, NULL },
- { "quotedblright", 600, NULL },
- { "amacron", 600, NULL },
- { "sacute", 600, NULL },
- { "imacron", 600, NULL },
- { "cent", 600, NULL },
- { "currency", 600, NULL },
- { "logicalnot", 600, NULL },
- { "zdotaccent", 600, NULL },
- { "Atilde", 600, NULL },
- { "breve", 600, NULL },
- { "bar", 600, NULL },
- { "fraction", 600, NULL },
- { "less", 600, NULL },
- { "ecaron", 600, NULL },
- { "guilsinglleft", 600, NULL },
- { "exclam", 600, NULL },
- { "period", 600, NULL },
- { "Rcaron", 600, NULL },
- { "Kcommaaccent", 600, NULL },
- { "greater", 600, NULL },
- { "atilde", 600, NULL },
- { "brokenbar", 600, NULL },
- { "quoteleft", 600, NULL },
- { "Edotaccent", 600, NULL },
- { "onesuperior", 600, NULL }
-};
-
-static BuiltinFontWidth courierBoldObliqueWidthsTab[] = {
- { "Ntilde", 600, NULL },
- { "rcaron", 600, NULL },
- { "kcommaaccent", 600, NULL },
- { "Ncommaaccent", 600, NULL },
- { "Zacute", 600, NULL },
- { "comma", 600, NULL },
- { "cedilla", 600, NULL },
- { "plusminus", 600, NULL },
- { "circumflex", 600, NULL },
- { "dotaccent", 600, NULL },
- { "edotaccent", 600, NULL },
- { "asciitilde", 600, NULL },
- { "colon", 600, NULL },
- { "onehalf", 600, NULL },
- { "dollar", 600, NULL },
- { "Lcaron", 600, NULL },
- { "ntilde", 600, NULL },
- { "Aogonek", 600, NULL },
- { "ncommaaccent", 600, NULL },
- { "minus", 600, NULL },
- { "Iogonek", 600, NULL },
- { "zacute", 600, NULL },
- { "yen", 600, NULL },
- { "space", 600, NULL },
- { "Omacron", 600, NULL },
- { "questiondown", 600, NULL },
- { "emdash", 600, NULL },
- { "Agrave", 600, NULL },
- { "three", 600, NULL },
- { "numbersign", 600, NULL },
- { "lcaron", 600, NULL },
- { "A", 600, NULL },
- { "B", 600, NULL },
- { "C", 600, NULL },
- { "aogonek", 600, NULL },
- { "D", 600, NULL },
- { "E", 600, NULL },
- { "onequarter", 600, NULL },
- { "F", 600, NULL },
- { "G", 600, NULL },
- { "H", 600, NULL },
- { "I", 600, NULL },
- { "J", 600, NULL },
- { "K", 600, NULL },
- { "iogonek", 600, NULL },
- { "backslash", 600, NULL },
- { "L", 600, NULL },
- { "periodcentered", 600, NULL },
- { "M", 600, NULL },
- { "N", 600, NULL },
- { "omacron", 600, NULL },
- { "Tcommaaccent", 600, NULL },
- { "O", 600, NULL },
- { "P", 600, NULL },
- { "Q", 600, NULL },
- { "Uhungarumlaut", 600, NULL },
- { "R", 600, NULL },
- { "Aacute", 600, NULL },
- { "caron", 600, NULL },
- { "S", 600, NULL },
- { "T", 600, NULL },
- { "U", 600, NULL },
- { "agrave", 600, NULL },
- { "V", 600, NULL },
- { "W", 600, NULL },
- { "X", 600, NULL },
- { "question", 600, NULL },
- { "equal", 600, NULL },
- { "Y", 600, NULL },
- { "Z", 600, NULL },
- { "four", 600, NULL },
- { "a", 600, NULL },
- { "Gcommaaccent", 600, NULL },
- { "b", 600, NULL },
- { "c", 600, NULL },
- { "d", 600, NULL },
- { "e", 600, NULL },
- { "f", 600, NULL },
- { "g", 600, NULL },
- { "bullet", 600, NULL },
- { "h", 600, NULL },
- { "i", 600, NULL },
- { "Oslash", 600, NULL },
- { "dagger", 600, NULL },
- { "j", 600, NULL },
- { "k", 600, NULL },
- { "l", 600, NULL },
- { "m", 600, NULL },
- { "n", 600, NULL },
- { "tcommaaccent", 600, NULL },
- { "o", 600, NULL },
- { "ordfeminine", 600, NULL },
- { "ring", 600, NULL },
- { "p", 600, NULL },
- { "q", 600, NULL },
- { "uhungarumlaut", 600, NULL },
- { "r", 600, NULL },
- { "twosuperior", 600, NULL },
- { "aacute", 600, NULL },
- { "s", 600, NULL },
- { "OE", 600, NULL },
- { "t", 600, NULL },
- { "divide", 600, NULL },
- { "u", 600, NULL },
- { "Ccaron", 600, NULL },
- { "v", 600, NULL },
- { "w", 600, NULL },
- { "x", 600, NULL },
- { "y", 600, NULL },
- { "z", 600, NULL },
- { "Gbreve", 600, NULL },
- { "commaaccent", 600, NULL },
- { "hungarumlaut", 600, NULL },
- { "Idotaccent", 600, NULL },
- { "Nacute", 600, NULL },
- { "quotedbl", 600, NULL },
- { "gcommaaccent", 600, NULL },
- { "mu", 600, NULL },
- { "greaterequal", 600, NULL },
- { "Scaron", 600, NULL },
- { "Lslash", 600, NULL },
- { "semicolon", 600, NULL },
- { "oslash", 600, NULL },
- { "lessequal", 600, NULL },
- { "lozenge", 600, NULL },
- { "parenright", 600, NULL },
- { "ccaron", 600, NULL },
- { "Ecircumflex", 600, NULL },
- { "gbreve", 600, NULL },
- { "trademark", 600, NULL },
- { "daggerdbl", 600, NULL },
- { "nacute", 600, NULL },
- { "macron", 600, NULL },
- { "Otilde", 600, NULL },
- { "Emacron", 600, NULL },
- { "ellipsis", 600, NULL },
- { "scaron", 600, NULL },
- { "AE", 600, NULL },
- { "Ucircumflex", 600, NULL },
- { "lslash", 600, NULL },
- { "quotedblleft", 600, NULL },
- { "guilsinglright", 600, NULL },
- { "hyphen", 600, NULL },
- { "quotesingle", 600, NULL },
- { "eight", 600, NULL },
- { "exclamdown", 600, NULL },
- { "endash", 600, NULL },
- { "oe", 600, NULL },
- { "Abreve", 600, NULL },
- { "Umacron", 600, NULL },
- { "ecircumflex", 600, NULL },
- { "Adieresis", 600, NULL },
- { "copyright", 600, NULL },
- { "Egrave", 600, NULL },
- { "slash", 600, NULL },
- { "Edieresis", 600, NULL },
- { "otilde", 600, NULL },
- { "Idieresis", 600, NULL },
- { "parenleft", 600, NULL },
- { "one", 600, NULL },
- { "emacron", 600, NULL },
- { "Odieresis", 600, NULL },
- { "ucircumflex", 600, NULL },
- { "bracketleft", 600, NULL },
- { "Ugrave", 600, NULL },
- { "quoteright", 600, NULL },
- { "Udieresis", 600, NULL },
- { "perthousand", 600, NULL },
- { "Ydieresis", 600, NULL },
- { "umacron", 600, NULL },
- { "abreve", 600, NULL },
- { "Eacute", 600, NULL },
- { "adieresis", 600, NULL },
- { "egrave", 600, NULL },
- { "edieresis", 600, NULL },
- { "idieresis", 600, NULL },
- { "Eth", 600, NULL },
- { "ae", 600, NULL },
- { "asterisk", 600, NULL },
- { "odieresis", 600, NULL },
- { "Uacute", 600, NULL },
- { "ugrave", 600, NULL },
- { "nine", 600, NULL },
- { "five", 600, NULL },
- { "udieresis", 600, NULL },
- { "Zcaron", 600, NULL },
- { "Scommaaccent", 600, NULL },
- { "threequarters", 600, NULL },
- { "guillemotright", 600, NULL },
- { "Ccedilla", 600, NULL },
- { "ydieresis", 600, NULL },
- { "tilde", 600, NULL },
- { "at", 600, NULL },
- { "eacute", 600, NULL },
- { "underscore", 600, NULL },
- { "Euro", 600, NULL },
- { "Dcroat", 600, NULL },
- { "multiply", 600, NULL },
- { "zero", 600, NULL },
- { "eth", 600, NULL },
- { "Scedilla", 600, NULL },
- { "Ograve", 600, NULL },
- { "Racute", 600, NULL },
- { "partialdiff", 600, NULL },
- { "uacute", 600, NULL },
- { "braceleft", 600, NULL },
- { "Thorn", 600, NULL },
- { "zcaron", 600, NULL },
- { "scommaaccent", 600, NULL },
- { "ccedilla", 600, NULL },
- { "Dcaron", 600, NULL },
- { "dcroat", 600, NULL },
- { "Ocircumflex", 600, NULL },
- { "Oacute", 600, NULL },
- { "scedilla", 600, NULL },
- { "ogonek", 600, NULL },
- { "ograve", 600, NULL },
- { "racute", 600, NULL },
- { "Tcaron", 600, NULL },
- { "Eogonek", 600, NULL },
- { "thorn", 600, NULL },
- { "degree", 600, NULL },
- { "registered", 600, NULL },
- { "radical", 600, NULL },
- { "Aring", 600, NULL },
- { "percent", 600, NULL },
- { "six", 600, NULL },
- { "paragraph", 600, NULL },
- { "dcaron", 600, NULL },
- { "Uogonek", 600, NULL },
- { "two", 600, NULL },
- { "summation", 600, NULL },
- { "Igrave", 600, NULL },
- { "Lacute", 600, NULL },
- { "ocircumflex", 600, NULL },
- { "oacute", 600, NULL },
- { "Uring", 600, NULL },
- { "Lcommaaccent", 600, NULL },
- { "tcaron", 600, NULL },
- { "eogonek", 600, NULL },
- { "Delta", 600, NULL },
- { "Ohungarumlaut", 600, NULL },
- { "asciicircum", 600, NULL },
- { "aring", 600, NULL },
- { "grave", 600, NULL },
- { "uogonek", 600, NULL },
- { "bracketright", 600, NULL },
- { "Iacute", 600, NULL },
- { "ampersand", 600, NULL },
- { "igrave", 600, NULL },
- { "lacute", 600, NULL },
- { "Ncaron", 600, NULL },
- { "plus", 600, NULL },
- { "uring", 600, NULL },
- { "quotesinglbase", 600, NULL },
- { "lcommaaccent", 600, NULL },
- { "Yacute", 600, NULL },
- { "ohungarumlaut", 600, NULL },
- { "threesuperior", 600, NULL },
- { "acute", 600, NULL },
- { "section", 600, NULL },
- { "dieresis", 600, NULL },
- { "iacute", 600, NULL },
- { "quotedblbase", 600, NULL },
- { "ncaron", 600, NULL },
- { "florin", 600, NULL },
- { "yacute", 600, NULL },
- { "Rcommaaccent", 600, NULL },
- { "fi", 600, NULL },
- { "fl", 600, NULL },
- { "Acircumflex", 600, NULL },
- { "Cacute", 600, NULL },
- { "Icircumflex", 600, NULL },
- { "guillemotleft", 600, NULL },
- { "germandbls", 600, NULL },
- { "Amacron", 600, NULL },
- { "seven", 600, NULL },
- { "Sacute", 600, NULL },
- { "ordmasculine", 600, NULL },
- { "dotlessi", 600, NULL },
- { "sterling", 600, NULL },
- { "notequal", 600, NULL },
- { "Imacron", 600, NULL },
- { "rcommaaccent", 600, NULL },
- { "Zdotaccent", 600, NULL },
- { "acircumflex", 600, NULL },
- { "cacute", 600, NULL },
- { "Ecaron", 600, NULL },
- { "icircumflex", 600, NULL },
- { "braceright", 600, NULL },
- { "quotedblright", 600, NULL },
- { "amacron", 600, NULL },
- { "sacute", 600, NULL },
- { "imacron", 600, NULL },
- { "cent", 600, NULL },
- { "currency", 600, NULL },
- { "logicalnot", 600, NULL },
- { "zdotaccent", 600, NULL },
- { "Atilde", 600, NULL },
- { "breve", 600, NULL },
- { "bar", 600, NULL },
- { "fraction", 600, NULL },
- { "less", 600, NULL },
- { "ecaron", 600, NULL },
- { "guilsinglleft", 600, NULL },
- { "exclam", 600, NULL },
- { "period", 600, NULL },
- { "Rcaron", 600, NULL },
- { "Kcommaaccent", 600, NULL },
- { "greater", 600, NULL },
- { "atilde", 600, NULL },
- { "brokenbar", 600, NULL },
- { "quoteleft", 600, NULL },
- { "Edotaccent", 600, NULL },
- { "onesuperior", 600, NULL }
-};
-
-static BuiltinFontWidth courierObliqueWidthsTab[] = {
- { "Ntilde", 600, NULL },
- { "rcaron", 600, NULL },
- { "kcommaaccent", 600, NULL },
- { "Ncommaaccent", 600, NULL },
- { "Zacute", 600, NULL },
- { "comma", 600, NULL },
- { "cedilla", 600, NULL },
- { "plusminus", 600, NULL },
- { "circumflex", 600, NULL },
- { "dotaccent", 600, NULL },
- { "edotaccent", 600, NULL },
- { "asciitilde", 600, NULL },
- { "colon", 600, NULL },
- { "onehalf", 600, NULL },
- { "dollar", 600, NULL },
- { "Lcaron", 600, NULL },
- { "ntilde", 600, NULL },
- { "Aogonek", 600, NULL },
- { "ncommaaccent", 600, NULL },
- { "minus", 600, NULL },
- { "Iogonek", 600, NULL },
- { "zacute", 600, NULL },
- { "yen", 600, NULL },
- { "space", 600, NULL },
- { "Omacron", 600, NULL },
- { "questiondown", 600, NULL },
- { "emdash", 600, NULL },
- { "Agrave", 600, NULL },
- { "three", 600, NULL },
- { "numbersign", 600, NULL },
- { "lcaron", 600, NULL },
- { "A", 600, NULL },
- { "B", 600, NULL },
- { "C", 600, NULL },
- { "aogonek", 600, NULL },
- { "D", 600, NULL },
- { "E", 600, NULL },
- { "onequarter", 600, NULL },
- { "F", 600, NULL },
- { "G", 600, NULL },
- { "H", 600, NULL },
- { "I", 600, NULL },
- { "J", 600, NULL },
- { "K", 600, NULL },
- { "iogonek", 600, NULL },
- { "backslash", 600, NULL },
- { "L", 600, NULL },
- { "periodcentered", 600, NULL },
- { "M", 600, NULL },
- { "N", 600, NULL },
- { "omacron", 600, NULL },
- { "Tcommaaccent", 600, NULL },
- { "O", 600, NULL },
- { "P", 600, NULL },
- { "Q", 600, NULL },
- { "Uhungarumlaut", 600, NULL },
- { "R", 600, NULL },
- { "Aacute", 600, NULL },
- { "caron", 600, NULL },
- { "S", 600, NULL },
- { "T", 600, NULL },
- { "U", 600, NULL },
- { "agrave", 600, NULL },
- { "V", 600, NULL },
- { "W", 600, NULL },
- { "X", 600, NULL },
- { "question", 600, NULL },
- { "equal", 600, NULL },
- { "Y", 600, NULL },
- { "Z", 600, NULL },
- { "four", 600, NULL },
- { "a", 600, NULL },
- { "Gcommaaccent", 600, NULL },
- { "b", 600, NULL },
- { "c", 600, NULL },
- { "d", 600, NULL },
- { "e", 600, NULL },
- { "f", 600, NULL },
- { "g", 600, NULL },
- { "bullet", 600, NULL },
- { "h", 600, NULL },
- { "i", 600, NULL },
- { "Oslash", 600, NULL },
- { "dagger", 600, NULL },
- { "j", 600, NULL },
- { "k", 600, NULL },
- { "l", 600, NULL },
- { "m", 600, NULL },
- { "n", 600, NULL },
- { "tcommaaccent", 600, NULL },
- { "o", 600, NULL },
- { "ordfeminine", 600, NULL },
- { "ring", 600, NULL },
- { "p", 600, NULL },
- { "q", 600, NULL },
- { "uhungarumlaut", 600, NULL },
- { "r", 600, NULL },
- { "twosuperior", 600, NULL },
- { "aacute", 600, NULL },
- { "s", 600, NULL },
- { "OE", 600, NULL },
- { "t", 600, NULL },
- { "divide", 600, NULL },
- { "u", 600, NULL },
- { "Ccaron", 600, NULL },
- { "v", 600, NULL },
- { "w", 600, NULL },
- { "x", 600, NULL },
- { "y", 600, NULL },
- { "z", 600, NULL },
- { "Gbreve", 600, NULL },
- { "commaaccent", 600, NULL },
- { "hungarumlaut", 600, NULL },
- { "Idotaccent", 600, NULL },
- { "Nacute", 600, NULL },
- { "quotedbl", 600, NULL },
- { "gcommaaccent", 600, NULL },
- { "mu", 600, NULL },
- { "greaterequal", 600, NULL },
- { "Scaron", 600, NULL },
- { "Lslash", 600, NULL },
- { "semicolon", 600, NULL },
- { "oslash", 600, NULL },
- { "lessequal", 600, NULL },
- { "lozenge", 600, NULL },
- { "parenright", 600, NULL },
- { "ccaron", 600, NULL },
- { "Ecircumflex", 600, NULL },
- { "gbreve", 600, NULL },
- { "trademark", 600, NULL },
- { "daggerdbl", 600, NULL },
- { "nacute", 600, NULL },
- { "macron", 600, NULL },
- { "Otilde", 600, NULL },
- { "Emacron", 600, NULL },
- { "ellipsis", 600, NULL },
- { "scaron", 600, NULL },
- { "AE", 600, NULL },
- { "Ucircumflex", 600, NULL },
- { "lslash", 600, NULL },
- { "quotedblleft", 600, NULL },
- { "guilsinglright", 600, NULL },
- { "hyphen", 600, NULL },
- { "quotesingle", 600, NULL },
- { "eight", 600, NULL },
- { "exclamdown", 600, NULL },
- { "endash", 600, NULL },
- { "oe", 600, NULL },
- { "Abreve", 600, NULL },
- { "Umacron", 600, NULL },
- { "ecircumflex", 600, NULL },
- { "Adieresis", 600, NULL },
- { "copyright", 600, NULL },
- { "Egrave", 600, NULL },
- { "slash", 600, NULL },
- { "Edieresis", 600, NULL },
- { "otilde", 600, NULL },
- { "Idieresis", 600, NULL },
- { "parenleft", 600, NULL },
- { "one", 600, NULL },
- { "emacron", 600, NULL },
- { "Odieresis", 600, NULL },
- { "ucircumflex", 600, NULL },
- { "bracketleft", 600, NULL },
- { "Ugrave", 600, NULL },
- { "quoteright", 600, NULL },
- { "Udieresis", 600, NULL },
- { "perthousand", 600, NULL },
- { "Ydieresis", 600, NULL },
- { "umacron", 600, NULL },
- { "abreve", 600, NULL },
- { "Eacute", 600, NULL },
- { "adieresis", 600, NULL },
- { "egrave", 600, NULL },
- { "edieresis", 600, NULL },
- { "idieresis", 600, NULL },
- { "Eth", 600, NULL },
- { "ae", 600, NULL },
- { "asterisk", 600, NULL },
- { "odieresis", 600, NULL },
- { "Uacute", 600, NULL },
- { "ugrave", 600, NULL },
- { "nine", 600, NULL },
- { "five", 600, NULL },
- { "udieresis", 600, NULL },
- { "Zcaron", 600, NULL },
- { "Scommaaccent", 600, NULL },
- { "threequarters", 600, NULL },
- { "guillemotright", 600, NULL },
- { "Ccedilla", 600, NULL },
- { "ydieresis", 600, NULL },
- { "tilde", 600, NULL },
- { "at", 600, NULL },
- { "eacute", 600, NULL },
- { "underscore", 600, NULL },
- { "Euro", 600, NULL },
- { "Dcroat", 600, NULL },
- { "multiply", 600, NULL },
- { "zero", 600, NULL },
- { "eth", 600, NULL },
- { "Scedilla", 600, NULL },
- { "Ograve", 600, NULL },
- { "Racute", 600, NULL },
- { "partialdiff", 600, NULL },
- { "uacute", 600, NULL },
- { "braceleft", 600, NULL },
- { "Thorn", 600, NULL },
- { "zcaron", 600, NULL },
- { "scommaaccent", 600, NULL },
- { "ccedilla", 600, NULL },
- { "Dcaron", 600, NULL },
- { "dcroat", 600, NULL },
- { "Ocircumflex", 600, NULL },
- { "Oacute", 600, NULL },
- { "scedilla", 600, NULL },
- { "ogonek", 600, NULL },
- { "ograve", 600, NULL },
- { "racute", 600, NULL },
- { "Tcaron", 600, NULL },
- { "Eogonek", 600, NULL },
- { "thorn", 600, NULL },
- { "degree", 600, NULL },
- { "registered", 600, NULL },
- { "radical", 600, NULL },
- { "Aring", 600, NULL },
- { "percent", 600, NULL },
- { "six", 600, NULL },
- { "paragraph", 600, NULL },
- { "dcaron", 600, NULL },
- { "Uogonek", 600, NULL },
- { "two", 600, NULL },
- { "summation", 600, NULL },
- { "Igrave", 600, NULL },
- { "Lacute", 600, NULL },
- { "ocircumflex", 600, NULL },
- { "oacute", 600, NULL },
- { "Uring", 600, NULL },
- { "Lcommaaccent", 600, NULL },
- { "tcaron", 600, NULL },
- { "eogonek", 600, NULL },
- { "Delta", 600, NULL },
- { "Ohungarumlaut", 600, NULL },
- { "asciicircum", 600, NULL },
- { "aring", 600, NULL },
- { "grave", 600, NULL },
- { "uogonek", 600, NULL },
- { "bracketright", 600, NULL },
- { "Iacute", 600, NULL },
- { "ampersand", 600, NULL },
- { "igrave", 600, NULL },
- { "lacute", 600, NULL },
- { "Ncaron", 600, NULL },
- { "plus", 600, NULL },
- { "uring", 600, NULL },
- { "quotesinglbase", 600, NULL },
- { "lcommaaccent", 600, NULL },
- { "Yacute", 600, NULL },
- { "ohungarumlaut", 600, NULL },
- { "threesuperior", 600, NULL },
- { "acute", 600, NULL },
- { "section", 600, NULL },
- { "dieresis", 600, NULL },
- { "iacute", 600, NULL },
- { "quotedblbase", 600, NULL },
- { "ncaron", 600, NULL },
- { "florin", 600, NULL },
- { "yacute", 600, NULL },
- { "Rcommaaccent", 600, NULL },
- { "fi", 600, NULL },
- { "fl", 600, NULL },
- { "Acircumflex", 600, NULL },
- { "Cacute", 600, NULL },
- { "Icircumflex", 600, NULL },
- { "guillemotleft", 600, NULL },
- { "germandbls", 600, NULL },
- { "Amacron", 600, NULL },
- { "seven", 600, NULL },
- { "Sacute", 600, NULL },
- { "ordmasculine", 600, NULL },
- { "dotlessi", 600, NULL },
- { "sterling", 600, NULL },
- { "notequal", 600, NULL },
- { "Imacron", 600, NULL },
- { "rcommaaccent", 600, NULL },
- { "Zdotaccent", 600, NULL },
- { "acircumflex", 600, NULL },
- { "cacute", 600, NULL },
- { "Ecaron", 600, NULL },
- { "icircumflex", 600, NULL },
- { "braceright", 600, NULL },
- { "quotedblright", 600, NULL },
- { "amacron", 600, NULL },
- { "sacute", 600, NULL },
- { "imacron", 600, NULL },
- { "cent", 600, NULL },
- { "currency", 600, NULL },
- { "logicalnot", 600, NULL },
- { "zdotaccent", 600, NULL },
- { "Atilde", 600, NULL },
- { "breve", 600, NULL },
- { "bar", 600, NULL },
- { "fraction", 600, NULL },
- { "less", 600, NULL },
- { "ecaron", 600, NULL },
- { "guilsinglleft", 600, NULL },
- { "exclam", 600, NULL },
- { "period", 600, NULL },
- { "Rcaron", 600, NULL },
- { "Kcommaaccent", 600, NULL },
- { "greater", 600, NULL },
- { "atilde", 600, NULL },
- { "brokenbar", 600, NULL },
- { "quoteleft", 600, NULL },
- { "Edotaccent", 600, NULL },
- { "onesuperior", 600, NULL }
-};
-
-static BuiltinFontWidth helveticaWidthsTab[] = {
- { "Ntilde", 722, NULL },
- { "rcaron", 333, NULL },
- { "kcommaaccent", 500, NULL },
- { "Ncommaaccent", 722, NULL },
- { "Zacute", 611, NULL },
- { "comma", 278, NULL },
- { "cedilla", 333, NULL },
- { "plusminus", 584, NULL },
- { "circumflex", 333, NULL },
- { "dotaccent", 333, NULL },
- { "edotaccent", 556, NULL },
- { "asciitilde", 584, NULL },
- { "colon", 278, NULL },
- { "onehalf", 834, NULL },
- { "dollar", 556, NULL },
- { "Lcaron", 556, NULL },
- { "ntilde", 556, NULL },
- { "Aogonek", 667, NULL },
- { "ncommaaccent", 556, NULL },
- { "minus", 584, NULL },
- { "Iogonek", 278, NULL },
- { "zacute", 500, NULL },
- { "yen", 556, NULL },
- { "space", 278, NULL },
- { "Omacron", 778, NULL },
- { "questiondown", 611, NULL },
- { "emdash", 1000, NULL },
- { "Agrave", 667, NULL },
- { "three", 556, NULL },
- { "numbersign", 556, NULL },
- { "lcaron", 299, NULL },
- { "A", 667, NULL },
- { "B", 667, NULL },
- { "C", 722, NULL },
- { "aogonek", 556, NULL },
- { "D", 722, NULL },
- { "E", 667, NULL },
- { "onequarter", 834, NULL },
- { "F", 611, NULL },
- { "G", 778, NULL },
- { "H", 722, NULL },
- { "I", 278, NULL },
- { "J", 500, NULL },
- { "K", 667, NULL },
- { "iogonek", 222, NULL },
- { "backslash", 278, NULL },
- { "L", 556, NULL },
- { "periodcentered", 278, NULL },
- { "M", 833, NULL },
- { "N", 722, NULL },
- { "omacron", 556, NULL },
- { "Tcommaaccent", 611, NULL },
- { "O", 778, NULL },
- { "P", 667, NULL },
- { "Q", 778, NULL },
- { "Uhungarumlaut", 722, NULL },
- { "R", 722, NULL },
- { "Aacute", 667, NULL },
- { "caron", 333, NULL },
- { "S", 667, NULL },
- { "T", 611, NULL },
- { "U", 722, NULL },
- { "agrave", 556, NULL },
- { "V", 667, NULL },
- { "W", 944, NULL },
- { "X", 667, NULL },
- { "question", 556, NULL },
- { "equal", 584, NULL },
- { "Y", 667, NULL },
- { "Z", 611, NULL },
- { "four", 556, NULL },
- { "a", 556, NULL },
- { "Gcommaaccent", 778, NULL },
- { "b", 556, NULL },
- { "c", 500, NULL },
- { "d", 556, NULL },
- { "e", 556, NULL },
- { "f", 278, NULL },
- { "g", 556, NULL },
- { "bullet", 350, NULL },
- { "h", 556, NULL },
- { "i", 222, NULL },
- { "Oslash", 778, NULL },
- { "dagger", 556, NULL },
- { "j", 222, NULL },
- { "k", 500, NULL },
- { "l", 222, NULL },
- { "m", 833, NULL },
- { "n", 556, NULL },
- { "tcommaaccent", 278, NULL },
- { "o", 556, NULL },
- { "ordfeminine", 370, NULL },
- { "ring", 333, NULL },
- { "p", 556, NULL },
- { "q", 556, NULL },
- { "uhungarumlaut", 556, NULL },
- { "r", 333, NULL },
- { "twosuperior", 333, NULL },
- { "aacute", 556, NULL },
- { "s", 500, NULL },
- { "OE", 1000, NULL },
- { "t", 278, NULL },
- { "divide", 584, NULL },
- { "u", 556, NULL },
- { "Ccaron", 722, NULL },
- { "v", 500, NULL },
- { "w", 722, NULL },
- { "x", 500, NULL },
- { "y", 500, NULL },
- { "z", 500, NULL },
- { "Gbreve", 778, NULL },
- { "commaaccent", 250, NULL },
- { "hungarumlaut", 333, NULL },
- { "Idotaccent", 278, NULL },
- { "Nacute", 722, NULL },
- { "quotedbl", 355, NULL },
- { "gcommaaccent", 556, NULL },
- { "mu", 556, NULL },
- { "greaterequal", 549, NULL },
- { "Scaron", 667, NULL },
- { "Lslash", 556, NULL },
- { "semicolon", 278, NULL },
- { "oslash", 611, NULL },
- { "lessequal", 549, NULL },
- { "lozenge", 471, NULL },
- { "parenright", 333, NULL },
- { "ccaron", 500, NULL },
- { "Ecircumflex", 667, NULL },
- { "gbreve", 556, NULL },
- { "trademark", 1000, NULL },
- { "daggerdbl", 556, NULL },
- { "nacute", 556, NULL },
- { "macron", 333, NULL },
- { "Otilde", 778, NULL },
- { "Emacron", 667, NULL },
- { "ellipsis", 1000, NULL },
- { "scaron", 500, NULL },
- { "AE", 1000, NULL },
- { "Ucircumflex", 722, NULL },
- { "lslash", 222, NULL },
- { "quotedblleft", 333, NULL },
- { "guilsinglright", 333, NULL },
- { "hyphen", 333, NULL },
- { "quotesingle", 191, NULL },
- { "eight", 556, NULL },
- { "exclamdown", 333, NULL },
- { "endash", 556, NULL },
- { "oe", 944, NULL },
- { "Abreve", 667, NULL },
- { "Umacron", 722, NULL },
- { "ecircumflex", 556, NULL },
- { "Adieresis", 667, NULL },
- { "copyright", 737, NULL },
- { "Egrave", 667, NULL },
- { "slash", 278, NULL },
- { "Edieresis", 667, NULL },
- { "otilde", 556, NULL },
- { "Idieresis", 278, NULL },
- { "parenleft", 333, NULL },
- { "one", 556, NULL },
- { "emacron", 556, NULL },
- { "Odieresis", 778, NULL },
- { "ucircumflex", 556, NULL },
- { "bracketleft", 278, NULL },
- { "Ugrave", 722, NULL },
- { "quoteright", 222, NULL },
- { "Udieresis", 722, NULL },
- { "perthousand", 1000, NULL },
- { "Ydieresis", 667, NULL },
- { "umacron", 556, NULL },
- { "abreve", 556, NULL },
- { "Eacute", 667, NULL },
- { "adieresis", 556, NULL },
- { "egrave", 556, NULL },
- { "edieresis", 556, NULL },
- { "idieresis", 278, NULL },
- { "Eth", 722, NULL },
- { "ae", 889, NULL },
- { "asterisk", 389, NULL },
- { "odieresis", 556, NULL },
- { "Uacute", 722, NULL },
- { "ugrave", 556, NULL },
- { "nine", 556, NULL },
- { "five", 556, NULL },
- { "udieresis", 556, NULL },
- { "Zcaron", 611, NULL },
- { "Scommaaccent", 667, NULL },
- { "threequarters", 834, NULL },
- { "guillemotright", 556, NULL },
- { "Ccedilla", 722, NULL },
- { "ydieresis", 500, NULL },
- { "tilde", 333, NULL },
- { "at", 1015, NULL },
- { "eacute", 556, NULL },
- { "underscore", 556, NULL },
- { "Euro", 556, NULL },
- { "Dcroat", 722, NULL },
- { "multiply", 584, NULL },
- { "zero", 556, NULL },
- { "eth", 556, NULL },
- { "Scedilla", 667, NULL },
- { "Ograve", 778, NULL },
- { "Racute", 722, NULL },
- { "partialdiff", 476, NULL },
- { "uacute", 556, NULL },
- { "braceleft", 334, NULL },
- { "Thorn", 667, NULL },
- { "zcaron", 500, NULL },
- { "scommaaccent", 500, NULL },
- { "ccedilla", 500, NULL },
- { "Dcaron", 722, NULL },
- { "dcroat", 556, NULL },
- { "Ocircumflex", 778, NULL },
- { "Oacute", 778, NULL },
- { "scedilla", 500, NULL },
- { "ogonek", 333, NULL },
- { "ograve", 556, NULL },
- { "racute", 333, NULL },
- { "Tcaron", 611, NULL },
- { "Eogonek", 667, NULL },
- { "thorn", 556, NULL },
- { "degree", 400, NULL },
- { "registered", 737, NULL },
- { "radical", 453, NULL },
- { "Aring", 667, NULL },
- { "percent", 889, NULL },
- { "six", 556, NULL },
- { "paragraph", 537, NULL },
- { "dcaron", 643, NULL },
- { "Uogonek", 722, NULL },
- { "two", 556, NULL },
- { "summation", 600, NULL },
- { "Igrave", 278, NULL },
- { "Lacute", 556, NULL },
- { "ocircumflex", 556, NULL },
- { "oacute", 556, NULL },
- { "Uring", 722, NULL },
- { "Lcommaaccent", 556, NULL },
- { "tcaron", 317, NULL },
- { "eogonek", 556, NULL },
- { "Delta", 612, NULL },
- { "Ohungarumlaut", 778, NULL },
- { "asciicircum", 469, NULL },
- { "aring", 556, NULL },
- { "grave", 333, NULL },
- { "uogonek", 556, NULL },
- { "bracketright", 278, NULL },
- { "Iacute", 278, NULL },
- { "ampersand", 667, NULL },
- { "igrave", 278, NULL },
- { "lacute", 222, NULL },
- { "Ncaron", 722, NULL },
- { "plus", 584, NULL },
- { "uring", 556, NULL },
- { "quotesinglbase", 222, NULL },
- { "lcommaaccent", 222, NULL },
- { "Yacute", 667, NULL },
- { "ohungarumlaut", 556, NULL },
- { "threesuperior", 333, NULL },
- { "acute", 333, NULL },
- { "section", 556, NULL },
- { "dieresis", 333, NULL },
- { "iacute", 278, NULL },
- { "quotedblbase", 333, NULL },
- { "ncaron", 556, NULL },
- { "florin", 556, NULL },
- { "yacute", 500, NULL },
- { "Rcommaaccent", 722, NULL },
- { "fi", 500, NULL },
- { "fl", 500, NULL },
- { "Acircumflex", 667, NULL },
- { "Cacute", 722, NULL },
- { "Icircumflex", 278, NULL },
- { "guillemotleft", 556, NULL },
- { "germandbls", 611, NULL },
- { "Amacron", 667, NULL },
- { "seven", 556, NULL },
- { "Sacute", 667, NULL },
- { "ordmasculine", 365, NULL },
- { "dotlessi", 278, NULL },
- { "sterling", 556, NULL },
- { "notequal", 549, NULL },
- { "Imacron", 278, NULL },
- { "rcommaaccent", 333, NULL },
- { "Zdotaccent", 611, NULL },
- { "acircumflex", 556, NULL },
- { "cacute", 500, NULL },
- { "Ecaron", 667, NULL },
- { "icircumflex", 278, NULL },
- { "braceright", 334, NULL },
- { "quotedblright", 333, NULL },
- { "amacron", 556, NULL },
- { "sacute", 500, NULL },
- { "imacron", 278, NULL },
- { "cent", 556, NULL },
- { "currency", 556, NULL },
- { "logicalnot", 584, NULL },
- { "zdotaccent", 500, NULL },
- { "Atilde", 667, NULL },
- { "breve", 333, NULL },
- { "bar", 260, NULL },
- { "fraction", 167, NULL },
- { "less", 584, NULL },
- { "ecaron", 556, NULL },
- { "guilsinglleft", 333, NULL },
- { "exclam", 278, NULL },
- { "period", 278, NULL },
- { "Rcaron", 722, NULL },
- { "Kcommaaccent", 667, NULL },
- { "greater", 584, NULL },
- { "atilde", 556, NULL },
- { "brokenbar", 260, NULL },
- { "quoteleft", 222, NULL },
- { "Edotaccent", 667, NULL },
- { "onesuperior", 333, NULL }
-};
-
-static BuiltinFontWidth helveticaBoldWidthsTab[] = {
- { "Ntilde", 722, NULL },
- { "rcaron", 389, NULL },
- { "kcommaaccent", 556, NULL },
- { "Ncommaaccent", 722, NULL },
- { "Zacute", 611, NULL },
- { "comma", 278, NULL },
- { "cedilla", 333, NULL },
- { "plusminus", 584, NULL },
- { "circumflex", 333, NULL },
- { "dotaccent", 333, NULL },
- { "edotaccent", 556, NULL },
- { "asciitilde", 584, NULL },
- { "colon", 333, NULL },
- { "onehalf", 834, NULL },
- { "dollar", 556, NULL },
- { "Lcaron", 611, NULL },
- { "ntilde", 611, NULL },
- { "Aogonek", 722, NULL },
- { "ncommaaccent", 611, NULL },
- { "minus", 584, NULL },
- { "Iogonek", 278, NULL },
- { "zacute", 500, NULL },
- { "yen", 556, NULL },
- { "space", 278, NULL },
- { "Omacron", 778, NULL },
- { "questiondown", 611, NULL },
- { "emdash", 1000, NULL },
- { "Agrave", 722, NULL },
- { "three", 556, NULL },
- { "numbersign", 556, NULL },
- { "lcaron", 400, NULL },
- { "A", 722, NULL },
- { "B", 722, NULL },
- { "C", 722, NULL },
- { "aogonek", 556, NULL },
- { "D", 722, NULL },
- { "E", 667, NULL },
- { "onequarter", 834, NULL },
- { "F", 611, NULL },
- { "G", 778, NULL },
- { "H", 722, NULL },
- { "I", 278, NULL },
- { "J", 556, NULL },
- { "K", 722, NULL },
- { "iogonek", 278, NULL },
- { "backslash", 278, NULL },
- { "L", 611, NULL },
- { "periodcentered", 278, NULL },
- { "M", 833, NULL },
- { "N", 722, NULL },
- { "omacron", 611, NULL },
- { "Tcommaaccent", 611, NULL },
- { "O", 778, NULL },
- { "P", 667, NULL },
- { "Q", 778, NULL },
- { "Uhungarumlaut", 722, NULL },
- { "R", 722, NULL },
- { "Aacute", 722, NULL },
- { "caron", 333, NULL },
- { "S", 667, NULL },
- { "T", 611, NULL },
- { "U", 722, NULL },
- { "agrave", 556, NULL },
- { "V", 667, NULL },
- { "W", 944, NULL },
- { "X", 667, NULL },
- { "question", 611, NULL },
- { "equal", 584, NULL },
- { "Y", 667, NULL },
- { "Z", 611, NULL },
- { "four", 556, NULL },
- { "a", 556, NULL },
- { "Gcommaaccent", 778, NULL },
- { "b", 611, NULL },
- { "c", 556, NULL },
- { "d", 611, NULL },
- { "e", 556, NULL },
- { "f", 333, NULL },
- { "g", 611, NULL },
- { "bullet", 350, NULL },
- { "h", 611, NULL },
- { "i", 278, NULL },
- { "Oslash", 778, NULL },
- { "dagger", 556, NULL },
- { "j", 278, NULL },
- { "k", 556, NULL },
- { "l", 278, NULL },
- { "m", 889, NULL },
- { "n", 611, NULL },
- { "tcommaaccent", 333, NULL },
- { "o", 611, NULL },
- { "ordfeminine", 370, NULL },
- { "ring", 333, NULL },
- { "p", 611, NULL },
- { "q", 611, NULL },
- { "uhungarumlaut", 611, NULL },
- { "r", 389, NULL },
- { "twosuperior", 333, NULL },
- { "aacute", 556, NULL },
- { "s", 556, NULL },
- { "OE", 1000, NULL },
- { "t", 333, NULL },
- { "divide", 584, NULL },
- { "u", 611, NULL },
- { "Ccaron", 722, NULL },
- { "v", 556, NULL },
- { "w", 778, NULL },
- { "x", 556, NULL },
- { "y", 556, NULL },
- { "z", 500, NULL },
- { "Gbreve", 778, NULL },
- { "commaaccent", 250, NULL },
- { "hungarumlaut", 333, NULL },
- { "Idotaccent", 278, NULL },
- { "Nacute", 722, NULL },
- { "quotedbl", 474, NULL },
- { "gcommaaccent", 611, NULL },
- { "mu", 611, NULL },
- { "greaterequal", 549, NULL },
- { "Scaron", 667, NULL },
- { "Lslash", 611, NULL },
- { "semicolon", 333, NULL },
- { "oslash", 611, NULL },
- { "lessequal", 549, NULL },
- { "lozenge", 494, NULL },
- { "parenright", 333, NULL },
- { "ccaron", 556, NULL },
- { "Ecircumflex", 667, NULL },
- { "gbreve", 611, NULL },
- { "trademark", 1000, NULL },
- { "daggerdbl", 556, NULL },
- { "nacute", 611, NULL },
- { "macron", 333, NULL },
- { "Otilde", 778, NULL },
- { "Emacron", 667, NULL },
- { "ellipsis", 1000, NULL },
- { "scaron", 556, NULL },
- { "AE", 1000, NULL },
- { "Ucircumflex", 722, NULL },
- { "lslash", 278, NULL },
- { "quotedblleft", 500, NULL },
- { "guilsinglright", 333, NULL },
- { "hyphen", 333, NULL },
- { "quotesingle", 238, NULL },
- { "eight", 556, NULL },
- { "exclamdown", 333, NULL },
- { "endash", 556, NULL },
- { "oe", 944, NULL },
- { "Abreve", 722, NULL },
- { "Umacron", 722, NULL },
- { "ecircumflex", 556, NULL },
- { "Adieresis", 722, NULL },
- { "copyright", 737, NULL },
- { "Egrave", 667, NULL },
- { "slash", 278, NULL },
- { "Edieresis", 667, NULL },
- { "otilde", 611, NULL },
- { "Idieresis", 278, NULL },
- { "parenleft", 333, NULL },
- { "one", 556, NULL },
- { "emacron", 556, NULL },
- { "Odieresis", 778, NULL },
- { "ucircumflex", 611, NULL },
- { "bracketleft", 333, NULL },
- { "Ugrave", 722, NULL },
- { "quoteright", 278, NULL },
- { "Udieresis", 722, NULL },
- { "perthousand", 1000, NULL },
- { "Ydieresis", 667, NULL },
- { "umacron", 611, NULL },
- { "abreve", 556, NULL },
- { "Eacute", 667, NULL },
- { "adieresis", 556, NULL },
- { "egrave", 556, NULL },
- { "edieresis", 556, NULL },
- { "idieresis", 278, NULL },
- { "Eth", 722, NULL },
- { "ae", 889, NULL },
- { "asterisk", 389, NULL },
- { "odieresis", 611, NULL },
- { "Uacute", 722, NULL },
- { "ugrave", 611, NULL },
- { "nine", 556, NULL },
- { "five", 556, NULL },
- { "udieresis", 611, NULL },
- { "Zcaron", 611, NULL },
- { "Scommaaccent", 667, NULL },
- { "threequarters", 834, NULL },
- { "guillemotright", 556, NULL },
- { "Ccedilla", 722, NULL },
- { "ydieresis", 556, NULL },
- { "tilde", 333, NULL },
- { "dbldaggerumlaut", 556, NULL },
- { "at", 975, NULL },
- { "eacute", 556, NULL },
- { "underscore", 556, NULL },
- { "Euro", 556, NULL },
- { "Dcroat", 722, NULL },
- { "multiply", 584, NULL },
- { "zero", 556, NULL },
- { "eth", 611, NULL },
- { "Scedilla", 667, NULL },
- { "Ograve", 778, NULL },
- { "Racute", 722, NULL },
- { "partialdiff", 494, NULL },
- { "uacute", 611, NULL },
- { "braceleft", 389, NULL },
- { "Thorn", 667, NULL },
- { "zcaron", 500, NULL },
- { "scommaaccent", 556, NULL },
- { "ccedilla", 556, NULL },
- { "Dcaron", 722, NULL },
- { "dcroat", 611, NULL },
- { "Ocircumflex", 778, NULL },
- { "Oacute", 778, NULL },
- { "scedilla", 556, NULL },
- { "ogonek", 333, NULL },
- { "ograve", 611, NULL },
- { "racute", 389, NULL },
- { "Tcaron", 611, NULL },
- { "Eogonek", 667, NULL },
- { "thorn", 611, NULL },
- { "degree", 400, NULL },
- { "registered", 737, NULL },
- { "radical", 549, NULL },
- { "Aring", 722, NULL },
- { "percent", 889, NULL },
- { "six", 556, NULL },
- { "paragraph", 556, NULL },
- { "dcaron", 743, NULL },
- { "Uogonek", 722, NULL },
- { "two", 556, NULL },
- { "summation", 600, NULL },
- { "Igrave", 278, NULL },
- { "Lacute", 611, NULL },
- { "ocircumflex", 611, NULL },
- { "oacute", 611, NULL },
- { "Uring", 722, NULL },
- { "Lcommaaccent", 611, NULL },
- { "tcaron", 389, NULL },
- { "eogonek", 556, NULL },
- { "Delta", 612, NULL },
- { "Ohungarumlaut", 778, NULL },
- { "asciicircum", 584, NULL },
- { "aring", 556, NULL },
- { "grave", 333, NULL },
- { "uogonek", 611, NULL },
- { "bracketright", 333, NULL },
- { "Iacute", 278, NULL },
- { "ampersand", 722, NULL },
- { "igrave", 278, NULL },
- { "lacute", 278, NULL },
- { "Ncaron", 722, NULL },
- { "plus", 584, NULL },
- { "uring", 611, NULL },
- { "quotesinglbase", 278, NULL },
- { "lcommaaccent", 278, NULL },
- { "Yacute", 667, NULL },
- { "ohungarumlaut", 611, NULL },
- { "threesuperior", 333, NULL },
- { "acute", 333, NULL },
- { "section", 556, NULL },
- { "dieresis", 333, NULL },
- { "iacute", 278, NULL },
- { "quotedblbase", 500, NULL },
- { "ncaron", 611, NULL },
- { "florin", 556, NULL },
- { "yacute", 556, NULL },
- { "Rcommaaccent", 722, NULL },
- { "fi", 611, NULL },
- { "fl", 611, NULL },
- { "Acircumflex", 722, NULL },
- { "Cacute", 722, NULL },
- { "Icircumflex", 278, NULL },
- { "guillemotleft", 556, NULL },
- { "germandbls", 611, NULL },
- { "Amacron", 722, NULL },
- { "seven", 556, NULL },
- { "Sacute", 667, NULL },
- { "ordmasculine", 365, NULL },
- { "dotlessi", 278, NULL },
- { "sterling", 556, NULL },
- { "notequal", 549, NULL },
- { "Imacron", 278, NULL },
- { "rcommaaccent", 389, NULL },
- { "Zdotaccent", 611, NULL },
- { "acircumflex", 556, NULL },
- { "cacute", 556, NULL },
- { "Ecaron", 667, NULL },
- { "icircumflex", 278, NULL },
- { "braceright", 389, NULL },
- { "quotedblright", 500, NULL },
- { "amacron", 556, NULL },
- { "sacute", 556, NULL },
- { "imacron", 278, NULL },
- { "cent", 556, NULL },
- { "currency", 556, NULL },
- { "logicalnot", 584, NULL },
- { "zdotaccent", 500, NULL },
- { "Atilde", 722, NULL },
- { "breve", 333, NULL },
- { "bar", 280, NULL },
- { "fraction", 167, NULL },
- { "less", 584, NULL },
- { "ecaron", 556, NULL },
- { "guilsinglleft", 333, NULL },
- { "exclam", 333, NULL },
- { "period", 278, NULL },
- { "Rcaron", 722, NULL },
- { "Kcommaaccent", 722, NULL },
- { "greater", 584, NULL },
- { "atilde", 556, NULL },
- { "brokenbar", 280, NULL },
- { "quoteleft", 278, NULL },
- { "Edotaccent", 667, NULL },
- { "onesuperior", 333, NULL }
-};
-
-static BuiltinFontWidth helveticaBoldObliqueWidthsTab[] = {
- { "Ntilde", 722, NULL },
- { "rcaron", 389, NULL },
- { "kcommaaccent", 556, NULL },
- { "Ncommaaccent", 722, NULL },
- { "Zacute", 611, NULL },
- { "comma", 278, NULL },
- { "cedilla", 333, NULL },
- { "plusminus", 584, NULL },
- { "circumflex", 333, NULL },
- { "dotaccent", 333, NULL },
- { "edotaccent", 556, NULL },
- { "asciitilde", 584, NULL },
- { "colon", 333, NULL },
- { "onehalf", 834, NULL },
- { "dollar", 556, NULL },
- { "Lcaron", 611, NULL },
- { "ntilde", 611, NULL },
- { "Aogonek", 722, NULL },
- { "ncommaaccent", 611, NULL },
- { "minus", 584, NULL },
- { "Iogonek", 278, NULL },
- { "zacute", 500, NULL },
- { "yen", 556, NULL },
- { "space", 278, NULL },
- { "Omacron", 778, NULL },
- { "questiondown", 611, NULL },
- { "emdash", 1000, NULL },
- { "Agrave", 722, NULL },
- { "three", 556, NULL },
- { "numbersign", 556, NULL },
- { "lcaron", 400, NULL },
- { "A", 722, NULL },
- { "B", 722, NULL },
- { "C", 722, NULL },
- { "aogonek", 556, NULL },
- { "D", 722, NULL },
- { "E", 667, NULL },
- { "onequarter", 834, NULL },
- { "F", 611, NULL },
- { "G", 778, NULL },
- { "H", 722, NULL },
- { "I", 278, NULL },
- { "J", 556, NULL },
- { "K", 722, NULL },
- { "iogonek", 278, NULL },
- { "backslash", 278, NULL },
- { "L", 611, NULL },
- { "periodcentered", 278, NULL },
- { "M", 833, NULL },
- { "N", 722, NULL },
- { "omacron", 611, NULL },
- { "Tcommaaccent", 611, NULL },
- { "O", 778, NULL },
- { "P", 667, NULL },
- { "Q", 778, NULL },
- { "Uhungarumlaut", 722, NULL },
- { "R", 722, NULL },
- { "Aacute", 722, NULL },
- { "caron", 333, NULL },
- { "S", 667, NULL },
- { "T", 611, NULL },
- { "U", 722, NULL },
- { "agrave", 556, NULL },
- { "V", 667, NULL },
- { "W", 944, NULL },
- { "X", 667, NULL },
- { "question", 611, NULL },
- { "equal", 584, NULL },
- { "Y", 667, NULL },
- { "Z", 611, NULL },
- { "four", 556, NULL },
- { "a", 556, NULL },
- { "Gcommaaccent", 778, NULL },
- { "b", 611, NULL },
- { "c", 556, NULL },
- { "d", 611, NULL },
- { "e", 556, NULL },
- { "f", 333, NULL },
- { "g", 611, NULL },
- { "bullet", 350, NULL },
- { "h", 611, NULL },
- { "i", 278, NULL },
- { "Oslash", 778, NULL },
- { "dagger", 556, NULL },
- { "j", 278, NULL },
- { "k", 556, NULL },
- { "l", 278, NULL },
- { "m", 889, NULL },
- { "n", 611, NULL },
- { "tcommaaccent", 333, NULL },
- { "o", 611, NULL },
- { "ordfeminine", 370, NULL },
- { "ring", 333, NULL },
- { "p", 611, NULL },
- { "q", 611, NULL },
- { "uhungarumlaut", 611, NULL },
- { "r", 389, NULL },
- { "twosuperior", 333, NULL },
- { "aacute", 556, NULL },
- { "s", 556, NULL },
- { "OE", 1000, NULL },
- { "t", 333, NULL },
- { "divide", 584, NULL },
- { "u", 611, NULL },
- { "Ccaron", 722, NULL },
- { "v", 556, NULL },
- { "w", 778, NULL },
- { "x", 556, NULL },
- { "y", 556, NULL },
- { "z", 500, NULL },
- { "Gbreve", 778, NULL },
- { "commaaccent", 250, NULL },
- { "hungarumlaut", 333, NULL },
- { "Idotaccent", 278, NULL },
- { "Nacute", 722, NULL },
- { "quotedbl", 474, NULL },
- { "gcommaaccent", 611, NULL },
- { "mu", 611, NULL },
- { "greaterequal", 549, NULL },
- { "Scaron", 667, NULL },
- { "Lslash", 611, NULL },
- { "semicolon", 333, NULL },
- { "oslash", 611, NULL },
- { "lessequal", 549, NULL },
- { "lozenge", 494, NULL },
- { "parenright", 333, NULL },
- { "ccaron", 556, NULL },
- { "Ecircumflex", 667, NULL },
- { "gbreve", 611, NULL },
- { "trademark", 1000, NULL },
- { "daggerdbl", 556, NULL },
- { "nacute", 611, NULL },
- { "macron", 333, NULL },
- { "Otilde", 778, NULL },
- { "Emacron", 667, NULL },
- { "ellipsis", 1000, NULL },
- { "scaron", 556, NULL },
- { "AE", 1000, NULL },
- { "Ucircumflex", 722, NULL },
- { "lslash", 278, NULL },
- { "quotedblleft", 500, NULL },
- { "guilsinglright", 333, NULL },
- { "hyphen", 333, NULL },
- { "quotesingle", 238, NULL },
- { "eight", 556, NULL },
- { "exclamdown", 333, NULL },
- { "endash", 556, NULL },
- { "oe", 944, NULL },
- { "Abreve", 722, NULL },
- { "Umacron", 722, NULL },
- { "ecircumflex", 556, NULL },
- { "Adieresis", 722, NULL },
- { "copyright", 737, NULL },
- { "Egrave", 667, NULL },
- { "slash", 278, NULL },
- { "Edieresis", 667, NULL },
- { "otilde", 611, NULL },
- { "Idieresis", 278, NULL },
- { "parenleft", 333, NULL },
- { "one", 556, NULL },
- { "emacron", 556, NULL },
- { "Odieresis", 778, NULL },
- { "ucircumflex", 611, NULL },
- { "bracketleft", 333, NULL },
- { "Ugrave", 722, NULL },
- { "quoteright", 278, NULL },
- { "Udieresis", 722, NULL },
- { "perthousand", 1000, NULL },
- { "Ydieresis", 667, NULL },
- { "umacron", 611, NULL },
- { "abreve", 556, NULL },
- { "Eacute", 667, NULL },
- { "adieresis", 556, NULL },
- { "egrave", 556, NULL },
- { "edieresis", 556, NULL },
- { "idieresis", 278, NULL },
- { "Eth", 722, NULL },
- { "ae", 889, NULL },
- { "asterisk", 389, NULL },
- { "odieresis", 611, NULL },
- { "Uacute", 722, NULL },
- { "ugrave", 611, NULL },
- { "nine", 556, NULL },
- { "five", 556, NULL },
- { "udieresis", 611, NULL },
- { "Zcaron", 611, NULL },
- { "Scommaaccent", 667, NULL },
- { "threequarters", 834, NULL },
- { "guillemotright", 556, NULL },
- { "Ccedilla", 722, NULL },
- { "ydieresis", 556, NULL },
- { "tilde", 333, NULL },
- { "at", 975, NULL },
- { "eacute", 556, NULL },
- { "underscore", 556, NULL },
- { "Euro", 556, NULL },
- { "Dcroat", 722, NULL },
- { "multiply", 584, NULL },
- { "zero", 556, NULL },
- { "eth", 611, NULL },
- { "Scedilla", 667, NULL },
- { "Ograve", 778, NULL },
- { "Racute", 722, NULL },
- { "partialdiff", 494, NULL },
- { "uacute", 611, NULL },
- { "braceleft", 389, NULL },
- { "Thorn", 667, NULL },
- { "zcaron", 500, NULL },
- { "scommaaccent", 556, NULL },
- { "ccedilla", 556, NULL },
- { "Dcaron", 722, NULL },
- { "dcroat", 611, NULL },
- { "Ocircumflex", 778, NULL },
- { "Oacute", 778, NULL },
- { "scedilla", 556, NULL },
- { "ogonek", 333, NULL },
- { "ograve", 611, NULL },
- { "racute", 389, NULL },
- { "Tcaron", 611, NULL },
- { "Eogonek", 667, NULL },
- { "thorn", 611, NULL },
- { "degree", 400, NULL },
- { "registered", 737, NULL },
- { "radical", 549, NULL },
- { "Aring", 722, NULL },
- { "percent", 889, NULL },
- { "six", 556, NULL },
- { "paragraph", 556, NULL },
- { "dcaron", 743, NULL },
- { "Uogonek", 722, NULL },
- { "two", 556, NULL },
- { "summation", 600, NULL },
- { "Igrave", 278, NULL },
- { "Lacute", 611, NULL },
- { "ocircumflex", 611, NULL },
- { "oacute", 611, NULL },
- { "Uring", 722, NULL },
- { "Lcommaaccent", 611, NULL },
- { "tcaron", 389, NULL },
- { "eogonek", 556, NULL },
- { "Delta", 612, NULL },
- { "Ohungarumlaut", 778, NULL },
- { "asciicircum", 584, NULL },
- { "aring", 556, NULL },
- { "grave", 333, NULL },
- { "uogonek", 611, NULL },
- { "bracketright", 333, NULL },
- { "Iacute", 278, NULL },
- { "ampersand", 722, NULL },
- { "igrave", 278, NULL },
- { "lacute", 278, NULL },
- { "Ncaron", 722, NULL },
- { "plus", 584, NULL },
- { "uring", 611, NULL },
- { "quotesinglbase", 278, NULL },
- { "lcommaaccent", 278, NULL },
- { "Yacute", 667, NULL },
- { "ohungarumlaut", 611, NULL },
- { "threesuperior", 333, NULL },
- { "acute", 333, NULL },
- { "section", 556, NULL },
- { "dieresis", 333, NULL },
- { "iacute", 278, NULL },
- { "quotedblbase", 500, NULL },
- { "ncaron", 611, NULL },
- { "florin", 556, NULL },
- { "yacute", 556, NULL },
- { "Rcommaaccent", 722, NULL },
- { "fi", 611, NULL },
- { "fl", 611, NULL },
- { "Acircumflex", 722, NULL },
- { "Cacute", 722, NULL },
- { "Icircumflex", 278, NULL },
- { "guillemotleft", 556, NULL },
- { "germandbls", 611, NULL },
- { "Amacron", 722, NULL },
- { "seven", 556, NULL },
- { "Sacute", 667, NULL },
- { "ordmasculine", 365, NULL },
- { "dotlessi", 278, NULL },
- { "sterling", 556, NULL },
- { "notequal", 549, NULL },
- { "Imacron", 278, NULL },
- { "rcommaaccent", 389, NULL },
- { "Zdotaccent", 611, NULL },
- { "acircumflex", 556, NULL },
- { "cacute", 556, NULL },
- { "Ecaron", 667, NULL },
- { "icircumflex", 278, NULL },
- { "braceright", 389, NULL },
- { "quotedblright", 500, NULL },
- { "amacron", 556, NULL },
- { "sacute", 556, NULL },
- { "imacron", 278, NULL },
- { "cent", 556, NULL },
- { "currency", 556, NULL },
- { "logicalnot", 584, NULL },
- { "zdotaccent", 500, NULL },
- { "Atilde", 722, NULL },
- { "breve", 333, NULL },
- { "bar", 280, NULL },
- { "fraction", 167, NULL },
- { "less", 584, NULL },
- { "ecaron", 556, NULL },
- { "guilsinglleft", 333, NULL },
- { "exclam", 333, NULL },
- { "period", 278, NULL },
- { "Rcaron", 722, NULL },
- { "Kcommaaccent", 722, NULL },
- { "greater", 584, NULL },
- { "atilde", 556, NULL },
- { "brokenbar", 280, NULL },
- { "quoteleft", 278, NULL },
- { "Edotaccent", 667, NULL },
- { "onesuperior", 333, NULL }
-};
-
-static BuiltinFontWidth helveticaObliqueWidthsTab[] = {
- { "Ntilde", 722, NULL },
- { "rcaron", 333, NULL },
- { "kcommaaccent", 500, NULL },
- { "Ncommaaccent", 722, NULL },
- { "Zacute", 611, NULL },
- { "comma", 278, NULL },
- { "cedilla", 333, NULL },
- { "plusminus", 584, NULL },
- { "circumflex", 333, NULL },
- { "dotaccent", 333, NULL },
- { "edotaccent", 556, NULL },
- { "asciitilde", 584, NULL },
- { "colon", 278, NULL },
- { "onehalf", 834, NULL },
- { "dollar", 556, NULL },
- { "Lcaron", 556, NULL },
- { "ntilde", 556, NULL },
- { "Aogonek", 667, NULL },
- { "ncommaaccent", 556, NULL },
- { "minus", 584, NULL },
- { "Iogonek", 278, NULL },
- { "zacute", 500, NULL },
- { "yen", 556, NULL },
- { "space", 278, NULL },
- { "Omacron", 778, NULL },
- { "questiondown", 611, NULL },
- { "emdash", 1000, NULL },
- { "Agrave", 667, NULL },
- { "three", 556, NULL },
- { "numbersign", 556, NULL },
- { "lcaron", 299, NULL },
- { "A", 667, NULL },
- { "B", 667, NULL },
- { "C", 722, NULL },
- { "aogonek", 556, NULL },
- { "D", 722, NULL },
- { "E", 667, NULL },
- { "onequarter", 834, NULL },
- { "F", 611, NULL },
- { "G", 778, NULL },
- { "H", 722, NULL },
- { "I", 278, NULL },
- { "J", 500, NULL },
- { "K", 667, NULL },
- { "iogonek", 222, NULL },
- { "backslash", 278, NULL },
- { "L", 556, NULL },
- { "periodcentered", 278, NULL },
- { "M", 833, NULL },
- { "N", 722, NULL },
- { "omacron", 556, NULL },
- { "Tcommaaccent", 611, NULL },
- { "O", 778, NULL },
- { "P", 667, NULL },
- { "Q", 778, NULL },
- { "Uhungarumlaut", 722, NULL },
- { "R", 722, NULL },
- { "Aacute", 667, NULL },
- { "caron", 333, NULL },
- { "S", 667, NULL },
- { "T", 611, NULL },
- { "U", 722, NULL },
- { "agrave", 556, NULL },
- { "V", 667, NULL },
- { "W", 944, NULL },
- { "X", 667, NULL },
- { "question", 556, NULL },
- { "equal", 584, NULL },
- { "Y", 667, NULL },
- { "Z", 611, NULL },
- { "four", 556, NULL },
- { "a", 556, NULL },
- { "Gcommaaccent", 778, NULL },
- { "b", 556, NULL },
- { "c", 500, NULL },
- { "d", 556, NULL },
- { "e", 556, NULL },
- { "f", 278, NULL },
- { "g", 556, NULL },
- { "bullet", 350, NULL },
- { "h", 556, NULL },
- { "i", 222, NULL },
- { "Oslash", 778, NULL },
- { "dagger", 556, NULL },
- { "j", 222, NULL },
- { "k", 500, NULL },
- { "l", 222, NULL },
- { "m", 833, NULL },
- { "n", 556, NULL },
- { "tcommaaccent", 278, NULL },
- { "o", 556, NULL },
- { "ordfeminine", 370, NULL },
- { "ring", 333, NULL },
- { "p", 556, NULL },
- { "q", 556, NULL },
- { "uhungarumlaut", 556, NULL },
- { "r", 333, NULL },
- { "twosuperior", 333, NULL },
- { "aacute", 556, NULL },
- { "s", 500, NULL },
- { "OE", 1000, NULL },
- { "t", 278, NULL },
- { "divide", 584, NULL },
- { "u", 556, NULL },
- { "Ccaron", 722, NULL },
- { "v", 500, NULL },
- { "w", 722, NULL },
- { "x", 500, NULL },
- { "y", 500, NULL },
- { "z", 500, NULL },
- { "Gbreve", 778, NULL },
- { "commaaccent", 250, NULL },
- { "hungarumlaut", 333, NULL },
- { "Idotaccent", 278, NULL },
- { "Nacute", 722, NULL },
- { "quotedbl", 355, NULL },
- { "gcommaaccent", 556, NULL },
- { "mu", 556, NULL },
- { "greaterequal", 549, NULL },
- { "Scaron", 667, NULL },
- { "Lslash", 556, NULL },
- { "semicolon", 278, NULL },
- { "oslash", 611, NULL },
- { "lessequal", 549, NULL },
- { "lozenge", 471, NULL },
- { "parenright", 333, NULL },
- { "ccaron", 500, NULL },
- { "Ecircumflex", 667, NULL },
- { "gbreve", 556, NULL },
- { "trademark", 1000, NULL },
- { "daggerdbl", 556, NULL },
- { "nacute", 556, NULL },
- { "macron", 333, NULL },
- { "Otilde", 778, NULL },
- { "Emacron", 667, NULL },
- { "ellipsis", 1000, NULL },
- { "scaron", 500, NULL },
- { "AE", 1000, NULL },
- { "Ucircumflex", 722, NULL },
- { "lslash", 222, NULL },
- { "quotedblleft", 333, NULL },
- { "guilsinglright", 333, NULL },
- { "hyphen", 333, NULL },
- { "quotesingle", 191, NULL },
- { "eight", 556, NULL },
- { "exclamdown", 333, NULL },
- { "endash", 556, NULL },
- { "oe", 944, NULL },
- { "Abreve", 667, NULL },
- { "Umacron", 722, NULL },
- { "ecircumflex", 556, NULL },
- { "Adieresis", 667, NULL },
- { "copyright", 737, NULL },
- { "Egrave", 667, NULL },
- { "slash", 278, NULL },
- { "Edieresis", 667, NULL },
- { "otilde", 556, NULL },
- { "Idieresis", 278, NULL },
- { "parenleft", 333, NULL },
- { "one", 556, NULL },
- { "emacron", 556, NULL },
- { "Odieresis", 778, NULL },
- { "ucircumflex", 556, NULL },
- { "bracketleft", 278, NULL },
- { "Ugrave", 722, NULL },
- { "quoteright", 222, NULL },
- { "Udieresis", 722, NULL },
- { "perthousand", 1000, NULL },
- { "Ydieresis", 667, NULL },
- { "umacron", 556, NULL },
- { "abreve", 556, NULL },
- { "Eacute", 667, NULL },
- { "adieresis", 556, NULL },
- { "egrave", 556, NULL },
- { "edieresis", 556, NULL },
- { "idieresis", 278, NULL },
- { "Eth", 722, NULL },
- { "ae", 889, NULL },
- { "asterisk", 389, NULL },
- { "odieresis", 556, NULL },
- { "Uacute", 722, NULL },
- { "ugrave", 556, NULL },
- { "nine", 556, NULL },
- { "five", 556, NULL },
- { "udieresis", 556, NULL },
- { "Zcaron", 611, NULL },
- { "Scommaaccent", 667, NULL },
- { "threequarters", 834, NULL },
- { "guillemotright", 556, NULL },
- { "Ccedilla", 722, NULL },
- { "ydieresis", 500, NULL },
- { "tilde", 333, NULL },
- { "at", 1015, NULL },
- { "eacute", 556, NULL },
- { "underscore", 556, NULL },
- { "Euro", 556, NULL },
- { "Dcroat", 722, NULL },
- { "multiply", 584, NULL },
- { "zero", 556, NULL },
- { "eth", 556, NULL },
- { "Scedilla", 667, NULL },
- { "Ograve", 778, NULL },
- { "Racute", 722, NULL },
- { "partialdiff", 476, NULL },
- { "uacute", 556, NULL },
- { "braceleft", 334, NULL },
- { "Thorn", 667, NULL },
- { "zcaron", 500, NULL },
- { "scommaaccent", 500, NULL },
- { "ccedilla", 500, NULL },
- { "Dcaron", 722, NULL },
- { "dcroat", 556, NULL },
- { "Ocircumflex", 778, NULL },
- { "Oacute", 778, NULL },
- { "scedilla", 500, NULL },
- { "ogonek", 333, NULL },
- { "ograve", 556, NULL },
- { "racute", 333, NULL },
- { "Tcaron", 611, NULL },
- { "Eogonek", 667, NULL },
- { "thorn", 556, NULL },
- { "degree", 400, NULL },
- { "registered", 737, NULL },
- { "radical", 453, NULL },
- { "Aring", 667, NULL },
- { "percent", 889, NULL },
- { "six", 556, NULL },
- { "paragraph", 537, NULL },
- { "dcaron", 643, NULL },
- { "Uogonek", 722, NULL },
- { "two", 556, NULL },
- { "summation", 600, NULL },
- { "Igrave", 278, NULL },
- { "Lacute", 556, NULL },
- { "ocircumflex", 556, NULL },
- { "oacute", 556, NULL },
- { "Uring", 722, NULL },
- { "Lcommaaccent", 556, NULL },
- { "tcaron", 317, NULL },
- { "eogonek", 556, NULL },
- { "Delta", 612, NULL },
- { "Ohungarumlaut", 778, NULL },
- { "asciicircum", 469, NULL },
- { "aring", 556, NULL },
- { "grave", 333, NULL },
- { "uogonek", 556, NULL },
- { "bracketright", 278, NULL },
- { "Iacute", 278, NULL },
- { "ampersand", 667, NULL },
- { "igrave", 278, NULL },
- { "lacute", 222, NULL },
- { "Ncaron", 722, NULL },
- { "plus", 584, NULL },
- { "uring", 556, NULL },
- { "quotesinglbase", 222, NULL },
- { "lcommaaccent", 222, NULL },
- { "Yacute", 667, NULL },
- { "ohungarumlaut", 556, NULL },
- { "threesuperior", 333, NULL },
- { "acute", 333, NULL },
- { "section", 556, NULL },
- { "dieresis", 333, NULL },
- { "iacute", 278, NULL },
- { "quotedblbase", 333, NULL },
- { "ncaron", 556, NULL },
- { "florin", 556, NULL },
- { "yacute", 500, NULL },
- { "Rcommaaccent", 722, NULL },
- { "fi", 500, NULL },
- { "fl", 500, NULL },
- { "Acircumflex", 667, NULL },
- { "Cacute", 722, NULL },
- { "Icircumflex", 278, NULL },
- { "guillemotleft", 556, NULL },
- { "germandbls", 611, NULL },
- { "Amacron", 667, NULL },
- { "seven", 556, NULL },
- { "Sacute", 667, NULL },
- { "ordmasculine", 365, NULL },
- { "dotlessi", 278, NULL },
- { "sterling", 556, NULL },
- { "notequal", 549, NULL },
- { "Imacron", 278, NULL },
- { "rcommaaccent", 333, NULL },
- { "Zdotaccent", 611, NULL },
- { "acircumflex", 556, NULL },
- { "cacute", 500, NULL },
- { "Ecaron", 667, NULL },
- { "icircumflex", 278, NULL },
- { "braceright", 334, NULL },
- { "quotedblright", 333, NULL },
- { "amacron", 556, NULL },
- { "sacute", 500, NULL },
- { "imacron", 278, NULL },
- { "cent", 556, NULL },
- { "currency", 556, NULL },
- { "logicalnot", 584, NULL },
- { "zdotaccent", 500, NULL },
- { "Atilde", 667, NULL },
- { "breve", 333, NULL },
- { "bar", 260, NULL },
- { "fraction", 167, NULL },
- { "less", 584, NULL },
- { "ecaron", 556, NULL },
- { "guilsinglleft", 333, NULL },
- { "exclam", 278, NULL },
- { "period", 278, NULL },
- { "Rcaron", 722, NULL },
- { "Kcommaaccent", 667, NULL },
- { "greater", 584, NULL },
- { "atilde", 556, NULL },
- { "brokenbar", 260, NULL },
- { "quoteleft", 222, NULL },
- { "Edotaccent", 667, NULL },
- { "onesuperior", 333, NULL }
-};
-
-static BuiltinFontWidth symbolWidthsTab[] = {
- { "bracketleftex", 384, NULL },
- { "alpha", 631, NULL },
- { "union", 768, NULL },
- { "infinity", 713, NULL },
- { "comma", 250, NULL },
- { "copyrightsans", 790, NULL },
- { "plusminus", 549, NULL },
- { "arrowup", 603, NULL },
- { "apple", 790, NULL },
- { "parenleftbt", 384, NULL },
- { "notelement", 713, NULL },
- { "colon", 278, NULL },
- { "beta", 549, NULL },
- { "braceleftbt", 494, NULL },
- { "Lambda", 686, NULL },
- { "Phi", 763, NULL },
- { "minus", 549, NULL },
- { "space", 250, NULL },
- { "Sigma", 592, NULL },
- { "approxequal", 549, NULL },
- { "minute", 247, NULL },
- { "circleplus", 768, NULL },
- { "Omicron", 722, NULL },
- { "three", 500, NULL },
- { "numbersign", 500, NULL },
- { "lambda", 549, NULL },
- { "phi", 521, NULL },
- { "aleph", 823, NULL },
- { "Tau", 611, NULL },
- { "spade", 753, NULL },
- { "logicaland", 603, NULL },
- { "sigma", 603, NULL },
- { "propersuperset", 713, NULL },
- { "omicron", 549, NULL },
- { "question", 444, NULL },
- { "equal", 549, NULL },
- { "Epsilon", 611, NULL },
- { "emptyset", 823, NULL },
- { "diamond", 753, NULL },
- { "four", 500, NULL },
- { "Mu", 889, NULL },
- { "parenlefttp", 384, NULL },
- { "club", 753, NULL },
- { "bullet", 460, NULL },
- { "Omega", 768, NULL },
- { "tau", 439, NULL },
- { "Upsilon", 690, NULL },
- { "bracelefttp", 494, NULL },
- { "heart", 753, NULL },
- { "divide", 549, NULL },
- { "epsilon", 439, NULL },
- { "logicalor", 603, NULL },
- { "parenleftex", 384, NULL },
- { "greaterequal", 549, NULL },
- { "mu", 576, NULL },
- { "Nu", 722, NULL },
- { "therefore", 863, NULL },
- { "notsubset", 713, NULL },
- { "omega", 686, NULL },
- { "semicolon", 278, NULL },
- { "element", 713, NULL },
- { "upsilon", 576, NULL },
- { "existential", 549, NULL },
- { "integralbt", 686, NULL },
- { "lessequal", 549, NULL },
- { "phi1", 603, NULL },
- { "lozenge", 494, NULL },
- { "trademarkserif", 890, NULL },
- { "parenright", 333, NULL },
- { "reflexsuperset", 713, NULL },
- { "sigma1", 439, NULL },
- { "nu", 521, NULL },
- { "Gamma", 603, NULL },
- { "angleright", 329, NULL },
- { "ellipsis", 1000, NULL },
- { "Rho", 556, NULL },
- { "parenrightbt", 384, NULL },
- { "radicalex", 500, NULL },
- { "eight", 500, NULL },
- { "angleleft", 329, NULL },
- { "arrowdbldown", 603, NULL },
- { "congruent", 549, NULL },
- { "Theta", 741, NULL },
- { "intersection", 768, NULL },
- { "Pi", 768, NULL },
- { "slash", 278, NULL },
- { "registerserif", 790, NULL },
- { "parenleft", 333, NULL },
- { "one", 500, NULL },
- { "gamma", 411, NULL },
- { "bracketleft", 333, NULL },
- { "rho", 549, NULL },
- { "circlemultiply", 768, NULL },
- { "Chi", 722, NULL },
- { "theta", 521, NULL },
- { "pi", 549, NULL },
- { "integraltp", 686, NULL },
- { "Eta", 722, NULL },
- { "product", 823, NULL },
- { "nine", 500, NULL },
- { "five", 500, NULL },
- { "propersubset", 713, NULL },
- { "bracketrightbt", 384, NULL },
- { "trademarksans", 786, NULL },
- { "dotmath", 250, NULL },
- { "integralex", 686, NULL },
- { "chi", 549, NULL },
- { "parenrighttp", 384, NULL },
- { "eta", 603, NULL },
- { "underscore", 500, NULL },
- { "Euro", 750, NULL },
- { "multiply", 549, NULL },
- { "zero", 500, NULL },
- { "partialdiff", 494, NULL },
- { "angle", 768, NULL },
- { "arrowdblleft", 987, NULL },
- { "braceleft", 480, NULL },
- { "parenrightex", 384, NULL },
- { "Rfraktur", 795, NULL },
- { "Zeta", 611, NULL },
- { "braceex", 494, NULL },
- { "arrowdblup", 603, NULL },
- { "arrowdown", 603, NULL },
- { "Ifraktur", 686, NULL },
- { "degree", 400, NULL },
- { "Iota", 333, NULL },
- { "perpendicular", 658, NULL },
- { "radical", 549, NULL },
- { "asteriskmath", 500, NULL },
- { "percent", 833, NULL },
- { "zeta", 494, NULL },
- { "six", 500, NULL },
- { "two", 500, NULL },
- { "weierstrass", 987, NULL },
- { "summation", 713, NULL },
- { "bracketrighttp", 384, NULL },
- { "carriagereturn", 658, NULL },
- { "suchthat", 439, NULL },
- { "arrowvertex", 603, NULL },
- { "Delta", 612, NULL },
- { "iota", 329, NULL },
- { "arrowhorizex", 1000, NULL },
- { "bracketrightex", 384, NULL },
- { "bracketright", 333, NULL },
- { "ampersand", 778, NULL },
- { "plus", 549, NULL },
- { "proportional", 713, NULL },
- { "delta", 494, NULL },
- { "copyrightserif", 790, NULL },
- { "bracerightmid", 494, NULL },
- { "arrowleft", 987, NULL },
- { "second", 411, NULL },
- { "arrowdblboth", 1042, NULL },
- { "florin", 500, NULL },
- { "Psi", 795, NULL },
- { "bracerightbt", 494, NULL },
- { "bracketleftbt", 384, NULL },
- { "seven", 500, NULL },
- { "braceleftmid", 494, NULL },
- { "notequal", 549, NULL },
- { "psi", 686, NULL },
- { "equivalence", 549, NULL },
- { "universal", 713, NULL },
- { "arrowdblright", 987, NULL },
- { "braceright", 480, NULL },
- { "reflexsubset", 713, NULL },
- { "Xi", 645, NULL },
- { "theta1", 631, NULL },
- { "logicalnot", 713, NULL },
- { "Kappa", 722, NULL },
- { "similar", 549, NULL },
- { "bar", 200, NULL },
- { "fraction", 167, NULL },
- { "less", 549, NULL },
- { "registersans", 790, NULL },
- { "omega1", 713, NULL },
- { "exclam", 333, NULL },
- { "Upsilon1", 620, NULL },
- { "bracerighttp", 494, NULL },
- { "xi", 493, NULL },
- { "period", 250, NULL },
- { "Alpha", 722, NULL },
- { "arrowright", 987, NULL },
- { "greater", 549, NULL },
- { "bracketlefttp", 384, NULL },
- { "kappa", 549, NULL },
- { "gradient", 713, NULL },
- { "integral", 274, NULL },
- { "arrowboth", 1042, NULL },
- { "Beta", 667, NULL }
-};
-
-static BuiltinFontWidth timesBoldWidthsTab[] = {
- { "Ntilde", 722, NULL },
- { "rcaron", 444, NULL },
- { "kcommaaccent", 556, NULL },
- { "Ncommaaccent", 722, NULL },
- { "Zacute", 667, NULL },
- { "comma", 250, NULL },
- { "cedilla", 333, NULL },
- { "plusminus", 570, NULL },
- { "circumflex", 333, NULL },
- { "dotaccent", 333, NULL },
- { "edotaccent", 444, NULL },
- { "asciitilde", 520, NULL },
- { "colon", 333, NULL },
- { "onehalf", 750, NULL },
- { "dollar", 500, NULL },
- { "Lcaron", 667, NULL },
- { "ntilde", 556, NULL },
- { "Aogonek", 722, NULL },
- { "ncommaaccent", 556, NULL },
- { "minus", 570, NULL },
- { "Iogonek", 389, NULL },
- { "zacute", 444, NULL },
- { "yen", 500, NULL },
- { "space", 250, NULL },
- { "Omacron", 778, NULL },
- { "questiondown", 500, NULL },
- { "emdash", 1000, NULL },
- { "Agrave", 722, NULL },
- { "three", 500, NULL },
- { "numbersign", 500, NULL },
- { "lcaron", 394, NULL },
- { "A", 722, NULL },
- { "B", 667, NULL },
- { "C", 722, NULL },
- { "aogonek", 500, NULL },
- { "D", 722, NULL },
- { "E", 667, NULL },
- { "onequarter", 750, NULL },
- { "F", 611, NULL },
- { "G", 778, NULL },
- { "H", 778, NULL },
- { "I", 389, NULL },
- { "J", 500, NULL },
- { "K", 778, NULL },
- { "iogonek", 278, NULL },
- { "backslash", 278, NULL },
- { "L", 667, NULL },
- { "periodcentered", 250, NULL },
- { "M", 944, NULL },
- { "N", 722, NULL },
- { "omacron", 500, NULL },
- { "Tcommaaccent", 667, NULL },
- { "O", 778, NULL },
- { "P", 611, NULL },
- { "Q", 778, NULL },
- { "Uhungarumlaut", 722, NULL },
- { "R", 722, NULL },
- { "Aacute", 722, NULL },
- { "caron", 333, NULL },
- { "S", 556, NULL },
- { "T", 667, NULL },
- { "U", 722, NULL },
- { "agrave", 500, NULL },
- { "V", 722, NULL },
- { "W", 1000, NULL },
- { "X", 722, NULL },
- { "question", 500, NULL },
- { "equal", 570, NULL },
- { "Y", 722, NULL },
- { "Z", 667, NULL },
- { "four", 500, NULL },
- { "a", 500, NULL },
- { "Gcommaaccent", 778, NULL },
- { "b", 556, NULL },
- { "c", 444, NULL },
- { "d", 556, NULL },
- { "e", 444, NULL },
- { "f", 333, NULL },
- { "g", 500, NULL },
- { "bullet", 350, NULL },
- { "h", 556, NULL },
- { "i", 278, NULL },
- { "Oslash", 778, NULL },
- { "dagger", 500, NULL },
- { "j", 333, NULL },
- { "k", 556, NULL },
- { "l", 278, NULL },
- { "m", 833, NULL },
- { "n", 556, NULL },
- { "tcommaaccent", 333, NULL },
- { "o", 500, NULL },
- { "ordfeminine", 300, NULL },
- { "ring", 333, NULL },
- { "p", 556, NULL },
- { "q", 556, NULL },
- { "uhungarumlaut", 556, NULL },
- { "r", 444, NULL },
- { "twosuperior", 300, NULL },
- { "aacute", 500, NULL },
- { "s", 389, NULL },
- { "OE", 1000, NULL },
- { "t", 333, NULL },
- { "divide", 570, NULL },
- { "u", 556, NULL },
- { "Ccaron", 722, NULL },
- { "v", 500, NULL },
- { "w", 722, NULL },
- { "x", 500, NULL },
- { "y", 500, NULL },
- { "z", 444, NULL },
- { "Gbreve", 778, NULL },
- { "commaaccent", 250, NULL },
- { "hungarumlaut", 333, NULL },
- { "Idotaccent", 389, NULL },
- { "Nacute", 722, NULL },
- { "quotedbl", 555, NULL },
- { "gcommaaccent", 500, NULL },
- { "mu", 556, NULL },
- { "greaterequal", 549, NULL },
- { "Scaron", 556, NULL },
- { "Lslash", 667, NULL },
- { "semicolon", 333, NULL },
- { "oslash", 500, NULL },
- { "lessequal", 549, NULL },
- { "lozenge", 494, NULL },
- { "parenright", 333, NULL },
- { "ccaron", 444, NULL },
- { "Ecircumflex", 667, NULL },
- { "gbreve", 500, NULL },
- { "trademark", 1000, NULL },
- { "daggerdbl", 500, NULL },
- { "nacute", 556, NULL },
- { "macron", 333, NULL },
- { "Otilde", 778, NULL },
- { "Emacron", 667, NULL },
- { "ellipsis", 1000, NULL },
- { "scaron", 389, NULL },
- { "AE", 1000, NULL },
- { "Ucircumflex", 722, NULL },
- { "lslash", 278, NULL },
- { "quotedblleft", 500, NULL },
- { "guilsinglright", 333, NULL },
- { "hyphen", 333, NULL },
- { "quotesingle", 278, NULL },
- { "eight", 500, NULL },
- { "exclamdown", 333, NULL },
- { "endash", 500, NULL },
- { "oe", 722, NULL },
- { "Abreve", 722, NULL },
- { "Umacron", 722, NULL },
- { "ecircumflex", 444, NULL },
- { "Adieresis", 722, NULL },
- { "copyright", 747, NULL },
- { "Egrave", 667, NULL },
- { "slash", 278, NULL },
- { "Edieresis", 667, NULL },
- { "otilde", 500, NULL },
- { "Idieresis", 389, NULL },
- { "parenleft", 333, NULL },
- { "one", 500, NULL },
- { "emacron", 444, NULL },
- { "Odieresis", 778, NULL },
- { "ucircumflex", 556, NULL },
- { "bracketleft", 333, NULL },
- { "Ugrave", 722, NULL },
- { "quoteright", 333, NULL },
- { "Udieresis", 722, NULL },
- { "perthousand", 1000, NULL },
- { "Ydieresis", 722, NULL },
- { "umacron", 556, NULL },
- { "abreve", 500, NULL },
- { "Eacute", 667, NULL },
- { "adieresis", 500, NULL },
- { "egrave", 444, NULL },
- { "edieresis", 444, NULL },
- { "idieresis", 278, NULL },
- { "Eth", 722, NULL },
- { "ae", 722, NULL },
- { "asterisk", 500, NULL },
- { "odieresis", 500, NULL },
- { "Uacute", 722, NULL },
- { "ugrave", 556, NULL },
- { "nine", 500, NULL },
- { "five", 500, NULL },
- { "udieresis", 556, NULL },
- { "Zcaron", 667, NULL },
- { "Scommaaccent", 556, NULL },
- { "threequarters", 750, NULL },
- { "guillemotright", 500, NULL },
- { "Ccedilla", 722, NULL },
- { "ydieresis", 500, NULL },
- { "tilde", 333, NULL },
- { "at", 930, NULL },
- { "eacute", 444, NULL },
- { "underscore", 500, NULL },
- { "Euro", 500, NULL },
- { "Dcroat", 722, NULL },
- { "multiply", 570, NULL },
- { "zero", 500, NULL },
- { "eth", 500, NULL },
- { "Scedilla", 556, NULL },
- { "Ograve", 778, NULL },
- { "Racute", 722, NULL },
- { "partialdiff", 494, NULL },
- { "uacute", 556, NULL },
- { "braceleft", 394, NULL },
- { "Thorn", 611, NULL },
- { "zcaron", 444, NULL },
- { "scommaaccent", 389, NULL },
- { "ccedilla", 444, NULL },
- { "Dcaron", 722, NULL },
- { "dcroat", 556, NULL },
- { "Ocircumflex", 778, NULL },
- { "Oacute", 778, NULL },
- { "scedilla", 389, NULL },
- { "ogonek", 333, NULL },
- { "ograve", 500, NULL },
- { "racute", 444, NULL },
- { "Tcaron", 667, NULL },
- { "Eogonek", 667, NULL },
- { "thorn", 556, NULL },
- { "degree", 400, NULL },
- { "registered", 747, NULL },
- { "radical", 549, NULL },
- { "Aring", 722, NULL },
- { "percent", 1000, NULL },
- { "six", 500, NULL },
- { "paragraph", 540, NULL },
- { "dcaron", 672, NULL },
- { "Uogonek", 722, NULL },
- { "two", 500, NULL },
- { "summation", 600, NULL },
- { "Igrave", 389, NULL },
- { "Lacute", 667, NULL },
- { "ocircumflex", 500, NULL },
- { "oacute", 500, NULL },
- { "Uring", 722, NULL },
- { "Lcommaaccent", 667, NULL },
- { "tcaron", 416, NULL },
- { "eogonek", 444, NULL },
- { "Delta", 612, NULL },
- { "Ohungarumlaut", 778, NULL },
- { "asciicircum", 581, NULL },
- { "aring", 500, NULL },
- { "grave", 333, NULL },
- { "uogonek", 556, NULL },
- { "bracketright", 333, NULL },
- { "Iacute", 389, NULL },
- { "ampersand", 833, NULL },
- { "igrave", 278, NULL },
- { "lacute", 278, NULL },
- { "Ncaron", 722, NULL },
- { "plus", 570, NULL },
- { "uring", 556, NULL },
- { "quotesinglbase", 333, NULL },
- { "lcommaaccent", 278, NULL },
- { "Yacute", 722, NULL },
- { "ohungarumlaut", 500, NULL },
- { "threesuperior", 300, NULL },
- { "acute", 333, NULL },
- { "section", 500, NULL },
- { "dieresis", 333, NULL },
- { "iacute", 278, NULL },
- { "quotedblbase", 500, NULL },
- { "ncaron", 556, NULL },
- { "florin", 500, NULL },
- { "yacute", 500, NULL },
- { "Rcommaaccent", 722, NULL },
- { "fi", 556, NULL },
- { "fl", 556, NULL },
- { "Acircumflex", 722, NULL },
- { "Cacute", 722, NULL },
- { "Icircumflex", 389, NULL },
- { "guillemotleft", 500, NULL },
- { "germandbls", 556, NULL },
- { "Amacron", 722, NULL },
- { "seven", 500, NULL },
- { "Sacute", 556, NULL },
- { "ordmasculine", 330, NULL },
- { "dotlessi", 278, NULL },
- { "sterling", 500, NULL },
- { "notequal", 549, NULL },
- { "Imacron", 389, NULL },
- { "rcommaaccent", 444, NULL },
- { "Zdotaccent", 667, NULL },
- { "acircumflex", 500, NULL },
- { "cacute", 444, NULL },
- { "Ecaron", 667, NULL },
- { "icircumflex", 278, NULL },
- { "braceright", 394, NULL },
- { "quotedblright", 500, NULL },
- { "amacron", 500, NULL },
- { "sacute", 389, NULL },
- { "imacron", 278, NULL },
- { "cent", 500, NULL },
- { "currency", 500, NULL },
- { "logicalnot", 570, NULL },
- { "zdotaccent", 444, NULL },
- { "Atilde", 722, NULL },
- { "breve", 333, NULL },
- { "bar", 220, NULL },
- { "fraction", 167, NULL },
- { "less", 570, NULL },
- { "ecaron", 444, NULL },
- { "guilsinglleft", 333, NULL },
- { "exclam", 333, NULL },
- { "period", 250, NULL },
- { "Rcaron", 722, NULL },
- { "Kcommaaccent", 778, NULL },
- { "greater", 570, NULL },
- { "atilde", 500, NULL },
- { "brokenbar", 220, NULL },
- { "quoteleft", 333, NULL },
- { "Edotaccent", 667, NULL },
- { "onesuperior", 300, NULL }
-};
-
-static BuiltinFontWidth timesBoldItalicWidthsTab[] = {
- { "Ntilde", 722, NULL },
- { "rcaron", 389, NULL },
- { "kcommaaccent", 500, NULL },
- { "Ncommaaccent", 722, NULL },
- { "Zacute", 611, NULL },
- { "comma", 250, NULL },
- { "cedilla", 333, NULL },
- { "plusminus", 570, NULL },
- { "circumflex", 333, NULL },
- { "dotaccent", 333, NULL },
- { "edotaccent", 444, NULL },
- { "asciitilde", 570, NULL },
- { "colon", 333, NULL },
- { "onehalf", 750, NULL },
- { "dollar", 500, NULL },
- { "Lcaron", 611, NULL },
- { "ntilde", 556, NULL },
- { "Aogonek", 667, NULL },
- { "ncommaaccent", 556, NULL },
- { "minus", 606, NULL },
- { "Iogonek", 389, NULL },
- { "zacute", 389, NULL },
- { "yen", 500, NULL },
- { "space", 250, NULL },
- { "Omacron", 722, NULL },
- { "questiondown", 500, NULL },
- { "emdash", 1000, NULL },
- { "Agrave", 667, NULL },
- { "three", 500, NULL },
- { "numbersign", 500, NULL },
- { "lcaron", 382, NULL },
- { "A", 667, NULL },
- { "B", 667, NULL },
- { "C", 667, NULL },
- { "aogonek", 500, NULL },
- { "D", 722, NULL },
- { "E", 667, NULL },
- { "onequarter", 750, NULL },
- { "F", 667, NULL },
- { "G", 722, NULL },
- { "H", 778, NULL },
- { "I", 389, NULL },
- { "J", 500, NULL },
- { "K", 667, NULL },
- { "iogonek", 278, NULL },
- { "backslash", 278, NULL },
- { "L", 611, NULL },
- { "periodcentered", 250, NULL },
- { "M", 889, NULL },
- { "N", 722, NULL },
- { "omacron", 500, NULL },
- { "Tcommaaccent", 611, NULL },
- { "O", 722, NULL },
- { "P", 611, NULL },
- { "Q", 722, NULL },
- { "Uhungarumlaut", 722, NULL },
- { "R", 667, NULL },
- { "Aacute", 667, NULL },
- { "caron", 333, NULL },
- { "S", 556, NULL },
- { "T", 611, NULL },
- { "U", 722, NULL },
- { "agrave", 500, NULL },
- { "V", 667, NULL },
- { "W", 889, NULL },
- { "X", 667, NULL },
- { "question", 500, NULL },
- { "equal", 570, NULL },
- { "Y", 611, NULL },
- { "Z", 611, NULL },
- { "four", 500, NULL },
- { "a", 500, NULL },
- { "Gcommaaccent", 722, NULL },
- { "b", 500, NULL },
- { "c", 444, NULL },
- { "d", 500, NULL },
- { "e", 444, NULL },
- { "f", 333, NULL },
- { "g", 500, NULL },
- { "bullet", 350, NULL },
- { "h", 556, NULL },
- { "i", 278, NULL },
- { "Oslash", 722, NULL },
- { "dagger", 500, NULL },
- { "j", 278, NULL },
- { "k", 500, NULL },
- { "l", 278, NULL },
- { "m", 778, NULL },
- { "n", 556, NULL },
- { "tcommaaccent", 278, NULL },
- { "o", 500, NULL },
- { "ordfeminine", 266, NULL },
- { "ring", 333, NULL },
- { "p", 500, NULL },
- { "q", 500, NULL },
- { "uhungarumlaut", 556, NULL },
- { "r", 389, NULL },
- { "twosuperior", 300, NULL },
- { "aacute", 500, NULL },
- { "s", 389, NULL },
- { "OE", 944, NULL },
- { "t", 278, NULL },
- { "divide", 570, NULL },
- { "u", 556, NULL },
- { "Ccaron", 667, NULL },
- { "v", 444, NULL },
- { "w", 667, NULL },
- { "x", 500, NULL },
- { "y", 444, NULL },
- { "z", 389, NULL },
- { "Gbreve", 722, NULL },
- { "commaaccent", 250, NULL },
- { "hungarumlaut", 333, NULL },
- { "Idotaccent", 389, NULL },
- { "Nacute", 722, NULL },
- { "quotedbl", 555, NULL },
- { "gcommaaccent", 500, NULL },
- { "mu", 576, NULL },
- { "greaterequal", 549, NULL },
- { "Scaron", 556, NULL },
- { "Lslash", 611, NULL },
- { "semicolon", 333, NULL },
- { "oslash", 500, NULL },
- { "lessequal", 549, NULL },
- { "lozenge", 494, NULL },
- { "parenright", 333, NULL },
- { "ccaron", 444, NULL },
- { "Ecircumflex", 667, NULL },
- { "gbreve", 500, NULL },
- { "trademark", 1000, NULL },
- { "daggerdbl", 500, NULL },
- { "nacute", 556, NULL },
- { "macron", 333, NULL },
- { "Otilde", 722, NULL },
- { "Emacron", 667, NULL },
- { "ellipsis", 1000, NULL },
- { "scaron", 389, NULL },
- { "AE", 944, NULL },
- { "Ucircumflex", 722, NULL },
- { "lslash", 278, NULL },
- { "quotedblleft", 500, NULL },
- { "guilsinglright", 333, NULL },
- { "hyphen", 333, NULL },
- { "quotesingle", 278, NULL },
- { "eight", 500, NULL },
- { "exclamdown", 389, NULL },
- { "endash", 500, NULL },
- { "oe", 722, NULL },
- { "Abreve", 667, NULL },
- { "Umacron", 722, NULL },
- { "ecircumflex", 444, NULL },
- { "Adieresis", 667, NULL },
- { "copyright", 747, NULL },
- { "Egrave", 667, NULL },
- { "slash", 278, NULL },
- { "Edieresis", 667, NULL },
- { "otilde", 500, NULL },
- { "Idieresis", 389, NULL },
- { "parenleft", 333, NULL },
- { "one", 500, NULL },
- { "emacron", 444, NULL },
- { "Odieresis", 722, NULL },
- { "ucircumflex", 556, NULL },
- { "bracketleft", 333, NULL },
- { "Ugrave", 722, NULL },
- { "quoteright", 333, NULL },
- { "Udieresis", 722, NULL },
- { "perthousand", 1000, NULL },
- { "Ydieresis", 611, NULL },
- { "umacron", 556, NULL },
- { "abreve", 500, NULL },
- { "Eacute", 667, NULL },
- { "adieresis", 500, NULL },
- { "egrave", 444, NULL },
- { "edieresis", 444, NULL },
- { "idieresis", 278, NULL },
- { "Eth", 722, NULL },
- { "ae", 722, NULL },
- { "asterisk", 500, NULL },
- { "odieresis", 500, NULL },
- { "Uacute", 722, NULL },
- { "ugrave", 556, NULL },
- { "nine", 500, NULL },
- { "five", 500, NULL },
- { "udieresis", 556, NULL },
- { "Zcaron", 611, NULL },
- { "Scommaaccent", 556, NULL },
- { "threequarters", 750, NULL },
- { "guillemotright", 500, NULL },
- { "Ccedilla", 667, NULL },
- { "ydieresis", 444, NULL },
- { "tilde", 333, NULL },
- { "at", 832, NULL },
- { "eacute", 444, NULL },
- { "underscore", 500, NULL },
- { "Euro", 500, NULL },
- { "Dcroat", 722, NULL },
- { "multiply", 570, NULL },
- { "zero", 500, NULL },
- { "eth", 500, NULL },
- { "Scedilla", 556, NULL },
- { "Ograve", 722, NULL },
- { "Racute", 667, NULL },
- { "partialdiff", 494, NULL },
- { "uacute", 556, NULL },
- { "braceleft", 348, NULL },
- { "Thorn", 611, NULL },
- { "zcaron", 389, NULL },
- { "scommaaccent", 389, NULL },
- { "ccedilla", 444, NULL },
- { "Dcaron", 722, NULL },
- { "dcroat", 500, NULL },
- { "Ocircumflex", 722, NULL },
- { "Oacute", 722, NULL },
- { "scedilla", 389, NULL },
- { "ogonek", 333, NULL },
- { "ograve", 500, NULL },
- { "racute", 389, NULL },
- { "Tcaron", 611, NULL },
- { "Eogonek", 667, NULL },
- { "thorn", 500, NULL },
- { "degree", 400, NULL },
- { "registered", 747, NULL },
- { "radical", 549, NULL },
- { "Aring", 667, NULL },
- { "percent", 833, NULL },
- { "six", 500, NULL },
- { "paragraph", 500, NULL },
- { "dcaron", 608, NULL },
- { "Uogonek", 722, NULL },
- { "two", 500, NULL },
- { "summation", 600, NULL },
- { "Igrave", 389, NULL },
- { "Lacute", 611, NULL },
- { "ocircumflex", 500, NULL },
- { "oacute", 500, NULL },
- { "Uring", 722, NULL },
- { "Lcommaaccent", 611, NULL },
- { "tcaron", 366, NULL },
- { "eogonek", 444, NULL },
- { "Delta", 612, NULL },
- { "Ohungarumlaut", 722, NULL },
- { "asciicircum", 570, NULL },
- { "aring", 500, NULL },
- { "grave", 333, NULL },
- { "uogonek", 556, NULL },
- { "bracketright", 333, NULL },
- { "Iacute", 389, NULL },
- { "ampersand", 778, NULL },
- { "igrave", 278, NULL },
- { "lacute", 278, NULL },
- { "Ncaron", 722, NULL },
- { "plus", 570, NULL },
- { "uring", 556, NULL },
- { "quotesinglbase", 333, NULL },
- { "lcommaaccent", 278, NULL },
- { "Yacute", 611, NULL },
- { "ohungarumlaut", 500, NULL },
- { "threesuperior", 300, NULL },
- { "acute", 333, NULL },
- { "section", 500, NULL },
- { "dieresis", 333, NULL },
- { "iacute", 278, NULL },
- { "quotedblbase", 500, NULL },
- { "ncaron", 556, NULL },
- { "florin", 500, NULL },
- { "yacute", 444, NULL },
- { "Rcommaaccent", 667, NULL },
- { "fi", 556, NULL },
- { "fl", 556, NULL },
- { "Acircumflex", 667, NULL },
- { "Cacute", 667, NULL },
- { "Icircumflex", 389, NULL },
- { "guillemotleft", 500, NULL },
- { "germandbls", 500, NULL },
- { "Amacron", 667, NULL },
- { "seven", 500, NULL },
- { "Sacute", 556, NULL },
- { "ordmasculine", 300, NULL },
- { "dotlessi", 278, NULL },
- { "sterling", 500, NULL },
- { "notequal", 549, NULL },
- { "Imacron", 389, NULL },
- { "rcommaaccent", 389, NULL },
- { "Zdotaccent", 611, NULL },
- { "acircumflex", 500, NULL },
- { "cacute", 444, NULL },
- { "Ecaron", 667, NULL },
- { "icircumflex", 278, NULL },
- { "braceright", 348, NULL },
- { "quotedblright", 500, NULL },
- { "amacron", 500, NULL },
- { "sacute", 389, NULL },
- { "imacron", 278, NULL },
- { "cent", 500, NULL },
- { "currency", 500, NULL },
- { "logicalnot", 606, NULL },
- { "zdotaccent", 389, NULL },
- { "Atilde", 667, NULL },
- { "breve", 333, NULL },
- { "bar", 220, NULL },
- { "fraction", 167, NULL },
- { "less", 570, NULL },
- { "ecaron", 444, NULL },
- { "guilsinglleft", 333, NULL },
- { "exclam", 389, NULL },
- { "period", 250, NULL },
- { "Rcaron", 667, NULL },
- { "Kcommaaccent", 667, NULL },
- { "greater", 570, NULL },
- { "atilde", 500, NULL },
- { "brokenbar", 220, NULL },
- { "quoteleft", 333, NULL },
- { "Edotaccent", 667, NULL },
- { "onesuperior", 300, NULL }
-};
-
-static BuiltinFontWidth timesItalicWidthsTab[] = {
- { "Ntilde", 667, NULL },
- { "rcaron", 389, NULL },
- { "kcommaaccent", 444, NULL },
- { "Ncommaaccent", 667, NULL },
- { "Zacute", 556, NULL },
- { "comma", 250, NULL },
- { "cedilla", 333, NULL },
- { "plusminus", 675, NULL },
- { "circumflex", 333, NULL },
- { "dotaccent", 333, NULL },
- { "edotaccent", 444, NULL },
- { "asciitilde", 541, NULL },
- { "colon", 333, NULL },
- { "onehalf", 750, NULL },
- { "dollar", 500, NULL },
- { "Lcaron", 611, NULL },
- { "ntilde", 500, NULL },
- { "Aogonek", 611, NULL },
- { "ncommaaccent", 500, NULL },
- { "minus", 675, NULL },
- { "Iogonek", 333, NULL },
- { "zacute", 389, NULL },
- { "yen", 500, NULL },
- { "space", 250, NULL },
- { "Omacron", 722, NULL },
- { "questiondown", 500, NULL },
- { "emdash", 889, NULL },
- { "Agrave", 611, NULL },
- { "three", 500, NULL },
- { "numbersign", 500, NULL },
- { "lcaron", 300, NULL },
- { "A", 611, NULL },
- { "B", 611, NULL },
- { "C", 667, NULL },
- { "aogonek", 500, NULL },
- { "D", 722, NULL },
- { "E", 611, NULL },
- { "onequarter", 750, NULL },
- { "F", 611, NULL },
- { "G", 722, NULL },
- { "H", 722, NULL },
- { "I", 333, NULL },
- { "J", 444, NULL },
- { "K", 667, NULL },
- { "iogonek", 278, NULL },
- { "backslash", 278, NULL },
- { "L", 556, NULL },
- { "periodcentered", 250, NULL },
- { "M", 833, NULL },
- { "N", 667, NULL },
- { "omacron", 500, NULL },
- { "Tcommaaccent", 556, NULL },
- { "O", 722, NULL },
- { "P", 611, NULL },
- { "Q", 722, NULL },
- { "Uhungarumlaut", 722, NULL },
- { "R", 611, NULL },
- { "Aacute", 611, NULL },
- { "caron", 333, NULL },
- { "S", 500, NULL },
- { "T", 556, NULL },
- { "U", 722, NULL },
- { "agrave", 500, NULL },
- { "V", 611, NULL },
- { "W", 833, NULL },
- { "X", 611, NULL },
- { "question", 500, NULL },
- { "equal", 675, NULL },
- { "Y", 556, NULL },
- { "Z", 556, NULL },
- { "four", 500, NULL },
- { "a", 500, NULL },
- { "Gcommaaccent", 722, NULL },
- { "b", 500, NULL },
- { "c", 444, NULL },
- { "d", 500, NULL },
- { "e", 444, NULL },
- { "f", 278, NULL },
- { "g", 500, NULL },
- { "bullet", 350, NULL },
- { "h", 500, NULL },
- { "i", 278, NULL },
- { "Oslash", 722, NULL },
- { "dagger", 500, NULL },
- { "j", 278, NULL },
- { "k", 444, NULL },
- { "l", 278, NULL },
- { "m", 722, NULL },
- { "n", 500, NULL },
- { "tcommaaccent", 278, NULL },
- { "o", 500, NULL },
- { "ordfeminine", 276, NULL },
- { "ring", 333, NULL },
- { "p", 500, NULL },
- { "q", 500, NULL },
- { "uhungarumlaut", 500, NULL },
- { "r", 389, NULL },
- { "twosuperior", 300, NULL },
- { "aacute", 500, NULL },
- { "s", 389, NULL },
- { "OE", 944, NULL },
- { "t", 278, NULL },
- { "divide", 675, NULL },
- { "u", 500, NULL },
- { "Ccaron", 667, NULL },
- { "v", 444, NULL },
- { "w", 667, NULL },
- { "x", 444, NULL },
- { "y", 444, NULL },
- { "z", 389, NULL },
- { "Gbreve", 722, NULL },
- { "commaaccent", 250, NULL },
- { "hungarumlaut", 333, NULL },
- { "Idotaccent", 333, NULL },
- { "Nacute", 667, NULL },
- { "quotedbl", 420, NULL },
- { "gcommaaccent", 500, NULL },
- { "mu", 500, NULL },
- { "greaterequal", 549, NULL },
- { "Scaron", 500, NULL },
- { "Lslash", 556, NULL },
- { "semicolon", 333, NULL },
- { "oslash", 500, NULL },
- { "lessequal", 549, NULL },
- { "lozenge", 471, NULL },
- { "parenright", 333, NULL },
- { "ccaron", 444, NULL },
- { "Ecircumflex", 611, NULL },
- { "gbreve", 500, NULL },
- { "trademark", 980, NULL },
- { "daggerdbl", 500, NULL },
- { "nacute", 500, NULL },
- { "macron", 333, NULL },
- { "Otilde", 722, NULL },
- { "Emacron", 611, NULL },
- { "ellipsis", 889, NULL },
- { "scaron", 389, NULL },
- { "AE", 889, NULL },
- { "Ucircumflex", 722, NULL },
- { "lslash", 278, NULL },
- { "quotedblleft", 556, NULL },
- { "guilsinglright", 333, NULL },
- { "hyphen", 333, NULL },
- { "quotesingle", 214, NULL },
- { "eight", 500, NULL },
- { "exclamdown", 389, NULL },
- { "endash", 500, NULL },
- { "oe", 667, NULL },
- { "Abreve", 611, NULL },
- { "Umacron", 722, NULL },
- { "ecircumflex", 444, NULL },
- { "Adieresis", 611, NULL },
- { "copyright", 760, NULL },
- { "Egrave", 611, NULL },
- { "slash", 278, NULL },
- { "Edieresis", 611, NULL },
- { "otilde", 500, NULL },
- { "Idieresis", 333, NULL },
- { "parenleft", 333, NULL },
- { "one", 500, NULL },
- { "emacron", 444, NULL },
- { "Odieresis", 722, NULL },
- { "ucircumflex", 500, NULL },
- { "bracketleft", 389, NULL },
- { "Ugrave", 722, NULL },
- { "quoteright", 333, NULL },
- { "Udieresis", 722, NULL },
- { "perthousand", 1000, NULL },
- { "Ydieresis", 556, NULL },
- { "umacron", 500, NULL },
- { "abreve", 500, NULL },
- { "Eacute", 611, NULL },
- { "adieresis", 500, NULL },
- { "egrave", 444, NULL },
- { "edieresis", 444, NULL },
- { "idieresis", 278, NULL },
- { "Eth", 722, NULL },
- { "ae", 667, NULL },
- { "asterisk", 500, NULL },
- { "odieresis", 500, NULL },
- { "Uacute", 722, NULL },
- { "ugrave", 500, NULL },
- { "nine", 500, NULL },
- { "five", 500, NULL },
- { "udieresis", 500, NULL },
- { "Zcaron", 556, NULL },
- { "Scommaaccent", 500, NULL },
- { "threequarters", 750, NULL },
- { "guillemotright", 500, NULL },
- { "Ccedilla", 667, NULL },
- { "ydieresis", 444, NULL },
- { "tilde", 333, NULL },
- { "at", 920, NULL },
- { "eacute", 444, NULL },
- { "underscore", 500, NULL },
- { "Euro", 500, NULL },
- { "Dcroat", 722, NULL },
- { "multiply", 675, NULL },
- { "zero", 500, NULL },
- { "eth", 500, NULL },
- { "Scedilla", 500, NULL },
- { "Ograve", 722, NULL },
- { "Racute", 611, NULL },
- { "partialdiff", 476, NULL },
- { "uacute", 500, NULL },
- { "braceleft", 400, NULL },
- { "Thorn", 611, NULL },
- { "zcaron", 389, NULL },
- { "scommaaccent", 389, NULL },
- { "ccedilla", 444, NULL },
- { "Dcaron", 722, NULL },
- { "dcroat", 500, NULL },
- { "Ocircumflex", 722, NULL },
- { "Oacute", 722, NULL },
- { "scedilla", 389, NULL },
- { "ogonek", 333, NULL },
- { "ograve", 500, NULL },
- { "racute", 389, NULL },
- { "Tcaron", 556, NULL },
- { "Eogonek", 611, NULL },
- { "thorn", 500, NULL },
- { "degree", 400, NULL },
- { "registered", 760, NULL },
- { "radical", 453, NULL },
- { "Aring", 611, NULL },
- { "percent", 833, NULL },
- { "six", 500, NULL },
- { "paragraph", 523, NULL },
- { "dcaron", 544, NULL },
- { "Uogonek", 722, NULL },
- { "two", 500, NULL },
- { "summation", 600, NULL },
- { "Igrave", 333, NULL },
- { "Lacute", 556, NULL },
- { "ocircumflex", 500, NULL },
- { "oacute", 500, NULL },
- { "Uring", 722, NULL },
- { "Lcommaaccent", 556, NULL },
- { "tcaron", 300, NULL },
- { "eogonek", 444, NULL },
- { "Delta", 612, NULL },
- { "Ohungarumlaut", 722, NULL },
- { "asciicircum", 422, NULL },
- { "aring", 500, NULL },
- { "grave", 333, NULL },
- { "uogonek", 500, NULL },
- { "bracketright", 389, NULL },
- { "Iacute", 333, NULL },
- { "ampersand", 778, NULL },
- { "igrave", 278, NULL },
- { "lacute", 278, NULL },
- { "Ncaron", 667, NULL },
- { "plus", 675, NULL },
- { "uring", 500, NULL },
- { "quotesinglbase", 333, NULL },
- { "lcommaaccent", 278, NULL },
- { "Yacute", 556, NULL },
- { "ohungarumlaut", 500, NULL },
- { "threesuperior", 300, NULL },
- { "acute", 333, NULL },
- { "section", 500, NULL },
- { "dieresis", 333, NULL },
- { "iacute", 278, NULL },
- { "quotedblbase", 556, NULL },
- { "ncaron", 500, NULL },
- { "florin", 500, NULL },
- { "yacute", 444, NULL },
- { "Rcommaaccent", 611, NULL },
- { "fi", 500, NULL },
- { "fl", 500, NULL },
- { "Acircumflex", 611, NULL },
- { "Cacute", 667, NULL },
- { "Icircumflex", 333, NULL },
- { "guillemotleft", 500, NULL },
- { "germandbls", 500, NULL },
- { "Amacron", 611, NULL },
- { "seven", 500, NULL },
- { "Sacute", 500, NULL },
- { "ordmasculine", 310, NULL },
- { "dotlessi", 278, NULL },
- { "sterling", 500, NULL },
- { "notequal", 549, NULL },
- { "Imacron", 333, NULL },
- { "rcommaaccent", 389, NULL },
- { "Zdotaccent", 556, NULL },
- { "acircumflex", 500, NULL },
- { "cacute", 444, NULL },
- { "Ecaron", 611, NULL },
- { "icircumflex", 278, NULL },
- { "braceright", 400, NULL },
- { "quotedblright", 556, NULL },
- { "amacron", 500, NULL },
- { "sacute", 389, NULL },
- { "imacron", 278, NULL },
- { "cent", 500, NULL },
- { "currency", 500, NULL },
- { "logicalnot", 675, NULL },
- { "zdotaccent", 389, NULL },
- { "Atilde", 611, NULL },
- { "breve", 333, NULL },
- { "bar", 275, NULL },
- { "fraction", 167, NULL },
- { "less", 675, NULL },
- { "ecaron", 444, NULL },
- { "guilsinglleft", 333, NULL },
- { "exclam", 333, NULL },
- { "period", 250, NULL },
- { "Rcaron", 611, NULL },
- { "Kcommaaccent", 667, NULL },
- { "greater", 675, NULL },
- { "atilde", 500, NULL },
- { "brokenbar", 275, NULL },
- { "quoteleft", 333, NULL },
- { "Edotaccent", 611, NULL },
- { "onesuperior", 300, NULL }
-};
-
-static BuiltinFontWidth timesRomanWidthsTab[] = {
- { "Ntilde", 722, NULL },
- { "rcaron", 333, NULL },
- { "kcommaaccent", 500, NULL },
- { "Ncommaaccent", 722, NULL },
- { "Zacute", 611, NULL },
- { "comma", 250, NULL },
- { "cedilla", 333, NULL },
- { "plusminus", 564, NULL },
- { "circumflex", 333, NULL },
- { "dotaccent", 333, NULL },
- { "edotaccent", 444, NULL },
- { "asciitilde", 541, NULL },
- { "colon", 278, NULL },
- { "onehalf", 750, NULL },
- { "dollar", 500, NULL },
- { "Lcaron", 611, NULL },
- { "ntilde", 500, NULL },
- { "Aogonek", 722, NULL },
- { "ncommaaccent", 500, NULL },
- { "minus", 564, NULL },
- { "Iogonek", 333, NULL },
- { "zacute", 444, NULL },
- { "yen", 500, NULL },
- { "space", 250, NULL },
- { "Omacron", 722, NULL },
- { "questiondown", 444, NULL },
- { "emdash", 1000, NULL },
- { "Agrave", 722, NULL },
- { "three", 500, NULL },
- { "numbersign", 500, NULL },
- { "lcaron", 344, NULL },
- { "A", 722, NULL },
- { "B", 667, NULL },
- { "C", 667, NULL },
- { "aogonek", 444, NULL },
- { "D", 722, NULL },
- { "E", 611, NULL },
- { "onequarter", 750, NULL },
- { "F", 556, NULL },
- { "G", 722, NULL },
- { "H", 722, NULL },
- { "I", 333, NULL },
- { "J", 389, NULL },
- { "K", 722, NULL },
- { "iogonek", 278, NULL },
- { "backslash", 278, NULL },
- { "L", 611, NULL },
- { "periodcentered", 250, NULL },
- { "M", 889, NULL },
- { "N", 722, NULL },
- { "omacron", 500, NULL },
- { "Tcommaaccent", 611, NULL },
- { "O", 722, NULL },
- { "P", 556, NULL },
- { "Q", 722, NULL },
- { "Uhungarumlaut", 722, NULL },
- { "R", 667, NULL },
- { "Aacute", 722, NULL },
- { "caron", 333, NULL },
- { "S", 556, NULL },
- { "T", 611, NULL },
- { "U", 722, NULL },
- { "agrave", 444, NULL },
- { "V", 722, NULL },
- { "W", 944, NULL },
- { "X", 722, NULL },
- { "question", 444, NULL },
- { "equal", 564, NULL },
- { "Y", 722, NULL },
- { "Z", 611, NULL },
- { "four", 500, NULL },
- { "a", 444, NULL },
- { "Gcommaaccent", 722, NULL },
- { "b", 500, NULL },
- { "c", 444, NULL },
- { "d", 500, NULL },
- { "e", 444, NULL },
- { "f", 333, NULL },
- { "g", 500, NULL },
- { "bullet", 350, NULL },
- { "h", 500, NULL },
- { "i", 278, NULL },
- { "Oslash", 722, NULL },
- { "dagger", 500, NULL },
- { "j", 278, NULL },
- { "k", 500, NULL },
- { "l", 278, NULL },
- { "m", 778, NULL },
- { "n", 500, NULL },
- { "tcommaaccent", 278, NULL },
- { "o", 500, NULL },
- { "ordfeminine", 276, NULL },
- { "ring", 333, NULL },
- { "p", 500, NULL },
- { "q", 500, NULL },
- { "uhungarumlaut", 500, NULL },
- { "r", 333, NULL },
- { "twosuperior", 300, NULL },
- { "aacute", 444, NULL },
- { "s", 389, NULL },
- { "OE", 889, NULL },
- { "t", 278, NULL },
- { "divide", 564, NULL },
- { "u", 500, NULL },
- { "Ccaron", 667, NULL },
- { "v", 500, NULL },
- { "w", 722, NULL },
- { "x", 500, NULL },
- { "y", 500, NULL },
- { "z", 444, NULL },
- { "Gbreve", 722, NULL },
- { "commaaccent", 250, NULL },
- { "hungarumlaut", 333, NULL },
- { "Idotaccent", 333, NULL },
- { "Nacute", 722, NULL },
- { "quotedbl", 408, NULL },
- { "gcommaaccent", 500, NULL },
- { "mu", 500, NULL },
- { "greaterequal", 549, NULL },
- { "Scaron", 556, NULL },
- { "Lslash", 611, NULL },
- { "semicolon", 278, NULL },
- { "oslash", 500, NULL },
- { "lessequal", 549, NULL },
- { "lozenge", 471, NULL },
- { "parenright", 333, NULL },
- { "ccaron", 444, NULL },
- { "Ecircumflex", 611, NULL },
- { "gbreve", 500, NULL },
- { "trademark", 980, NULL },
- { "daggerdbl", 500, NULL },
- { "nacute", 500, NULL },
- { "macron", 333, NULL },
- { "Otilde", 722, NULL },
- { "Emacron", 611, NULL },
- { "ellipsis", 1000, NULL },
- { "scaron", 389, NULL },
- { "AE", 889, NULL },
- { "Ucircumflex", 722, NULL },
- { "lslash", 278, NULL },
- { "quotedblleft", 444, NULL },
- { "guilsinglright", 333, NULL },
- { "hyphen", 333, NULL },
- { "quotesingle", 180, NULL },
- { "eight", 500, NULL },
- { "exclamdown", 333, NULL },
- { "endash", 500, NULL },
- { "oe", 722, NULL },
- { "Abreve", 722, NULL },
- { "Umacron", 722, NULL },
- { "ecircumflex", 444, NULL },
- { "Adieresis", 722, NULL },
- { "copyright", 760, NULL },
- { "Egrave", 611, NULL },
- { "slash", 278, NULL },
- { "Edieresis", 611, NULL },
- { "otilde", 500, NULL },
- { "Idieresis", 333, NULL },
- { "parenleft", 333, NULL },
- { "one", 500, NULL },
- { "emacron", 444, NULL },
- { "Odieresis", 722, NULL },
- { "ucircumflex", 500, NULL },
- { "bracketleft", 333, NULL },
- { "Ugrave", 722, NULL },
- { "quoteright", 333, NULL },
- { "Udieresis", 722, NULL },
- { "perthousand", 1000, NULL },
- { "Ydieresis", 722, NULL },
- { "umacron", 500, NULL },
- { "abreve", 444, NULL },
- { "Eacute", 611, NULL },
- { "adieresis", 444, NULL },
- { "egrave", 444, NULL },
- { "edieresis", 444, NULL },
- { "idieresis", 278, NULL },
- { "Eth", 722, NULL },
- { "ae", 667, NULL },
- { "asterisk", 500, NULL },
- { "odieresis", 500, NULL },
- { "Uacute", 722, NULL },
- { "ugrave", 500, NULL },
- { "nine", 500, NULL },
- { "five", 500, NULL },
- { "udieresis", 500, NULL },
- { "Zcaron", 611, NULL },
- { "Scommaaccent", 556, NULL },
- { "threequarters", 750, NULL },
- { "guillemotright", 500, NULL },
- { "Ccedilla", 667, NULL },
- { "ydieresis", 500, NULL },
- { "tilde", 333, NULL },
- { "at", 921, NULL },
- { "eacute", 444, NULL },
- { "underscore", 500, NULL },
- { "Euro", 500, NULL },
- { "Dcroat", 722, NULL },
- { "multiply", 564, NULL },
- { "zero", 500, NULL },
- { "eth", 500, NULL },
- { "Scedilla", 556, NULL },
- { "Ograve", 722, NULL },
- { "Racute", 667, NULL },
- { "partialdiff", 476, NULL },
- { "uacute", 500, NULL },
- { "braceleft", 480, NULL },
- { "Thorn", 556, NULL },
- { "zcaron", 444, NULL },
- { "scommaaccent", 389, NULL },
- { "ccedilla", 444, NULL },
- { "Dcaron", 722, NULL },
- { "dcroat", 500, NULL },
- { "Ocircumflex", 722, NULL },
- { "Oacute", 722, NULL },
- { "scedilla", 389, NULL },
- { "ogonek", 333, NULL },
- { "ograve", 500, NULL },
- { "racute", 333, NULL },
- { "Tcaron", 611, NULL },
- { "Eogonek", 611, NULL },
- { "thorn", 500, NULL },
- { "degree", 400, NULL },
- { "registered", 760, NULL },
- { "radical", 453, NULL },
- { "Aring", 722, NULL },
- { "percent", 833, NULL },
- { "six", 500, NULL },
- { "paragraph", 453, NULL },
- { "dcaron", 588, NULL },
- { "Uogonek", 722, NULL },
- { "two", 500, NULL },
- { "summation", 600, NULL },
- { "Igrave", 333, NULL },
- { "Lacute", 611, NULL },
- { "ocircumflex", 500, NULL },
- { "oacute", 500, NULL },
- { "Uring", 722, NULL },
- { "Lcommaaccent", 611, NULL },
- { "tcaron", 326, NULL },
- { "eogonek", 444, NULL },
- { "Delta", 612, NULL },
- { "Ohungarumlaut", 722, NULL },
- { "asciicircum", 469, NULL },
- { "aring", 444, NULL },
- { "grave", 333, NULL },
- { "uogonek", 500, NULL },
- { "bracketright", 333, NULL },
- { "Iacute", 333, NULL },
- { "ampersand", 778, NULL },
- { "igrave", 278, NULL },
- { "lacute", 278, NULL },
- { "Ncaron", 722, NULL },
- { "plus", 564, NULL },
- { "uring", 500, NULL },
- { "quotesinglbase", 333, NULL },
- { "lcommaaccent", 278, NULL },
- { "Yacute", 722, NULL },
- { "ohungarumlaut", 500, NULL },
- { "threesuperior", 300, NULL },
- { "acute", 333, NULL },
- { "section", 500, NULL },
- { "dieresis", 333, NULL },
- { "iacute", 278, NULL },
- { "quotedblbase", 444, NULL },
- { "ncaron", 500, NULL },
- { "florin", 500, NULL },
- { "yacute", 500, NULL },
- { "Rcommaaccent", 667, NULL },
- { "fi", 556, NULL },
- { "fl", 556, NULL },
- { "Acircumflex", 722, NULL },
- { "Cacute", 667, NULL },
- { "Icircumflex", 333, NULL },
- { "guillemotleft", 500, NULL },
- { "germandbls", 500, NULL },
- { "Amacron", 722, NULL },
- { "seven", 500, NULL },
- { "Sacute", 556, NULL },
- { "ordmasculine", 310, NULL },
- { "dotlessi", 278, NULL },
- { "sterling", 500, NULL },
- { "notequal", 549, NULL },
- { "Imacron", 333, NULL },
- { "rcommaaccent", 333, NULL },
- { "Zdotaccent", 611, NULL },
- { "acircumflex", 444, NULL },
- { "cacute", 444, NULL },
- { "Ecaron", 611, NULL },
- { "icircumflex", 278, NULL },
- { "braceright", 480, NULL },
- { "quotedblright", 444, NULL },
- { "amacron", 444, NULL },
- { "sacute", 389, NULL },
- { "imacron", 278, NULL },
- { "cent", 500, NULL },
- { "currency", 500, NULL },
- { "logicalnot", 564, NULL },
- { "zdotaccent", 444, NULL },
- { "Atilde", 722, NULL },
- { "breve", 333, NULL },
- { "bar", 200, NULL },
- { "fraction", 167, NULL },
- { "less", 564, NULL },
- { "ecaron", 444, NULL },
- { "guilsinglleft", 333, NULL },
- { "exclam", 333, NULL },
- { "period", 250, NULL },
- { "Rcaron", 667, NULL },
- { "Kcommaaccent", 722, NULL },
- { "greater", 564, NULL },
- { "atilde", 444, NULL },
- { "brokenbar", 200, NULL },
- { "quoteleft", 333, NULL },
- { "Edotaccent", 611, NULL },
- { "onesuperior", 300, NULL }
-};
-
-static BuiltinFontWidth zapfDingbatsWidthsTab[] = {
- { "a81", 438, NULL },
- { "a82", 138, NULL },
- { "a83", 277, NULL },
- { "a84", 415, NULL },
- { "a85", 509, NULL },
- { "a86", 410, NULL },
- { "a87", 234, NULL },
- { "a88", 234, NULL },
- { "a89", 390, NULL },
- { "a140", 788, NULL },
- { "a141", 788, NULL },
- { "a142", 788, NULL },
- { "a143", 788, NULL },
- { "a144", 788, NULL },
- { "a145", 788, NULL },
- { "a146", 788, NULL },
- { "a147", 788, NULL },
- { "a148", 788, NULL },
- { "a149", 788, NULL },
- { "a90", 390, NULL },
- { "a91", 276, NULL },
- { "a92", 276, NULL },
- { "space", 278, NULL },
- { "a93", 317, NULL },
- { "a94", 317, NULL },
- { "a95", 334, NULL },
- { "a96", 334, NULL },
- { "a97", 392, NULL },
- { "a98", 392, NULL },
- { "a99", 668, NULL },
- { "a150", 788, NULL },
- { "a151", 788, NULL },
- { "a152", 788, NULL },
- { "a153", 788, NULL },
- { "a154", 788, NULL },
- { "a155", 788, NULL },
- { "a156", 788, NULL },
- { "a157", 788, NULL },
- { "a158", 788, NULL },
- { "a159", 788, NULL },
- { "a160", 894, NULL },
- { "a161", 838, NULL },
- { "a162", 924, NULL },
- { "a163", 1016, NULL },
- { "a164", 458, NULL },
- { "a165", 924, NULL },
- { "a166", 918, NULL },
- { "a167", 927, NULL },
- { "a168", 928, NULL },
- { "a169", 928, NULL },
- { "a170", 834, NULL },
- { "a171", 873, NULL },
- { "a172", 828, NULL },
- { "a173", 924, NULL },
- { "a174", 917, NULL },
- { "a175", 930, NULL },
- { "a176", 931, NULL },
- { "a177", 463, NULL },
- { "a178", 883, NULL },
- { "a179", 836, NULL },
- { "a180", 867, NULL },
- { "a181", 696, NULL },
- { "a182", 874, NULL },
- { "a183", 760, NULL },
- { "a184", 946, NULL },
- { "a185", 865, NULL },
- { "a186", 967, NULL },
- { "a187", 831, NULL },
- { "a188", 873, NULL },
- { "a189", 927, NULL },
- { "a1", 974, NULL },
- { "a2", 961, NULL },
- { "a3", 980, NULL },
- { "a4", 719, NULL },
- { "a5", 789, NULL },
- { "a6", 494, NULL },
- { "a7", 552, NULL },
- { "a8", 537, NULL },
- { "a9", 577, NULL },
- { "a190", 970, NULL },
- { "a191", 918, NULL },
- { "a192", 748, NULL },
- { "a193", 836, NULL },
- { "a194", 771, NULL },
- { "a195", 888, NULL },
- { "a196", 748, NULL },
- { "a197", 771, NULL },
- { "a198", 888, NULL },
- { "a199", 867, NULL },
- { "a10", 692, NULL },
- { "a11", 960, NULL },
- { "a12", 939, NULL },
- { "a13", 549, NULL },
- { "a14", 855, NULL },
- { "a15", 911, NULL },
- { "a16", 933, NULL },
- { "a17", 945, NULL },
- { "a18", 974, NULL },
- { "a19", 755, NULL },
- { "a20", 846, NULL },
- { "a21", 762, NULL },
- { "a22", 761, NULL },
- { "a23", 571, NULL },
- { "a24", 677, NULL },
- { "a25", 763, NULL },
- { "a26", 760, NULL },
- { "a27", 759, NULL },
- { "a28", 754, NULL },
- { "a29", 786, NULL },
- { "a30", 788, NULL },
- { "a31", 788, NULL },
- { "a32", 790, NULL },
- { "a33", 793, NULL },
- { "a34", 794, NULL },
- { "a35", 816, NULL },
- { "a36", 823, NULL },
- { "a37", 789, NULL },
- { "a38", 841, NULL },
- { "a39", 823, NULL },
- { "a40", 833, NULL },
- { "a41", 816, NULL },
- { "a42", 831, NULL },
- { "a43", 923, NULL },
- { "a44", 744, NULL },
- { "a45", 723, NULL },
- { "a46", 749, NULL },
- { "a47", 790, NULL },
- { "a48", 792, NULL },
- { "a49", 695, NULL },
- { "a100", 668, NULL },
- { "a101", 732, NULL },
- { "a102", 544, NULL },
- { "a103", 544, NULL },
- { "a104", 910, NULL },
- { "a105", 911, NULL },
- { "a106", 667, NULL },
- { "a107", 760, NULL },
- { "a108", 760, NULL },
- { "a109", 626, NULL },
- { "a50", 776, NULL },
- { "a51", 768, NULL },
- { "a52", 792, NULL },
- { "a53", 759, NULL },
- { "a54", 707, NULL },
- { "a55", 708, NULL },
- { "a56", 682, NULL },
- { "a57", 701, NULL },
- { "a58", 826, NULL },
- { "a59", 815, NULL },
- { "a110", 694, NULL },
- { "a111", 595, NULL },
- { "a112", 776, NULL },
- { "a117", 690, NULL },
- { "a118", 791, NULL },
- { "a119", 790, NULL },
- { "a60", 789, NULL },
- { "a61", 789, NULL },
- { "a62", 707, NULL },
- { "a63", 687, NULL },
- { "a64", 696, NULL },
- { "a65", 689, NULL },
- { "a66", 786, NULL },
- { "a67", 787, NULL },
- { "a68", 713, NULL },
- { "a69", 791, NULL },
- { "a200", 696, NULL },
- { "a201", 874, NULL },
- { "a120", 788, NULL },
- { "a121", 788, NULL },
- { "a202", 974, NULL },
- { "a122", 788, NULL },
- { "a203", 762, NULL },
- { "a123", 788, NULL },
- { "a204", 759, NULL },
- { "a124", 788, NULL },
- { "a205", 509, NULL },
- { "a125", 788, NULL },
- { "a206", 410, NULL },
- { "a126", 788, NULL },
- { "a127", 788, NULL },
- { "a128", 788, NULL },
- { "a129", 788, NULL },
- { "a70", 785, NULL },
- { "a71", 791, NULL },
- { "a72", 873, NULL },
- { "a73", 761, NULL },
- { "a74", 762, NULL },
- { "a75", 759, NULL },
- { "a76", 892, NULL },
- { "a77", 892, NULL },
- { "a78", 788, NULL },
- { "a79", 784, NULL },
- { "a130", 788, NULL },
- { "a131", 788, NULL },
- { "a132", 788, NULL },
- { "a133", 788, NULL },
- { "a134", 788, NULL },
- { "a135", 788, NULL },
- { "a136", 788, NULL },
- { "a137", 788, NULL },
- { "a138", 788, NULL },
- { "a139", 788, NULL }
-};
-
-BuiltinFont builtinFonts[] = {
- { "Courier", standardEncoding, 629, -157, { -23, -250, 715, 805}, NULL },
- { "Courier-Bold", standardEncoding, 629, -157, {-113, -250, 749, 801}, NULL },
- { "Courier-BoldOblique", standardEncoding, 629, -157, { -57, -250, 869, 801}, NULL },
- { "Courier-Oblique", standardEncoding, 629, -157, { -27, -250, 849, 805}, NULL },
- { "Helvetica", standardEncoding, 718, -207, {-166, -225, 1000, 931}, NULL },
- { "Helvetica-Bold", standardEncoding, 718, -207, {-170, -228, 1003, 962}, NULL },
- { "Helvetica-BoldOblique", standardEncoding, 718, -207, {-174, -228, 1114, 962}, NULL },
- { "Helvetica-Oblique", standardEncoding, 718, -207, {-170, -225, 1116, 931}, NULL },
- { "Symbol", symbolEncoding, 1010, -293, {-180, -293, 1090, 1010}, NULL },
- { "Times-Bold", standardEncoding, 683, -217, {-168, -218, 1000, 935}, NULL },
- { "Times-BoldItalic", standardEncoding, 683, -217, {-200, -218, 996, 921}, NULL },
- { "Times-Italic", standardEncoding, 683, -217, {-169, -217, 1010, 883}, NULL },
- { "Times-Roman", standardEncoding, 683, -217, {-168, -218, 1000, 898}, NULL },
- { "ZapfDingbats", zapfDingbatsEncoding, 820, -143, { -1, -143, 981, 820}, NULL }
-};
-
-BuiltinFont *builtinFontSubst[] = {
- &builtinFonts[0],
- &builtinFonts[3],
- &builtinFonts[1],
- &builtinFonts[2],
- &builtinFonts[4],
- &builtinFonts[7],
- &builtinFonts[5],
- &builtinFonts[6],
- &builtinFonts[12],
- &builtinFonts[11],
- &builtinFonts[9],
- &builtinFonts[10]
-};
-
-void initBuiltinFontTables() {
- builtinFonts[0].widths = new BuiltinFontWidths(courierWidthsTab, 315);
- builtinFonts[1].widths = new BuiltinFontWidths(courierBoldWidthsTab, 315);
- builtinFonts[2].widths = new BuiltinFontWidths(courierBoldObliqueWidthsTab, 315);
- builtinFonts[3].widths = new BuiltinFontWidths(courierObliqueWidthsTab, 315);
- builtinFonts[4].widths = new BuiltinFontWidths(helveticaWidthsTab, 315);
- builtinFonts[5].widths = new BuiltinFontWidths(helveticaBoldWidthsTab, 316);
- builtinFonts[6].widths = new BuiltinFontWidths(helveticaBoldObliqueWidthsTab, 315);
- builtinFonts[7].widths = new BuiltinFontWidths(helveticaObliqueWidthsTab, 315);
- builtinFonts[8].widths = new BuiltinFontWidths(symbolWidthsTab, 190);
- builtinFonts[9].widths = new BuiltinFontWidths(timesBoldWidthsTab, 315);
- builtinFonts[10].widths = new BuiltinFontWidths(timesBoldItalicWidthsTab, 315);
- builtinFonts[11].widths = new BuiltinFontWidths(timesItalicWidthsTab, 315);
- builtinFonts[12].widths = new BuiltinFontWidths(timesRomanWidthsTab, 315);
- builtinFonts[13].widths = new BuiltinFontWidths(zapfDingbatsWidthsTab, 202);
-}
-
-void freeBuiltinFontTables() {
- int i;
-
- for (i = 0; i < 14; ++i) {
- delete builtinFonts[i].widths;
- }
-}
+++ /dev/null
-//========================================================================
-//
-// BuiltinFontTables.h
-//
-// Copyright 2001-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#ifndef BUILTINFONTTABLES_H
-#define BUILTINFONTTABLES_H
-
-#include "BuiltinFont.h"
-
-#define nBuiltinFonts 14
-#define nBuiltinFontSubsts 12
-
-extern BuiltinFont builtinFonts[nBuiltinFonts];
-extern BuiltinFont *builtinFontSubst[nBuiltinFontSubsts];
-
-extern void initBuiltinFontTables();
-extern void freeBuiltinFontTables();
-
-#endif
+++ /dev/null
-//========================================================================
-//
-// CMap.cc
-//
-// Copyright 2001-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma implementation
-#endif
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include "gmem.h"
-#include "gfile.h"
-#include "GString.h"
-#include "Error.h"
-#include "GlobalParams.h"
-#include "PSTokenizer.h"
-#include "CMap.h"
-
-//------------------------------------------------------------------------
-
-struct CMapVectorEntry {
- GBool isVector;
- union {
- CMapVectorEntry *vector;
- CID cid;
- };
-};
-
-//------------------------------------------------------------------------
-
-static int getCharFromFile(void *data) {
- return fgetc((FILE *)data);
-}
-
-//------------------------------------------------------------------------
-
-CMap *CMap::parse(CMapCache *cache, GString *collectionA,
- GString *cMapNameA) {
- FILE *f;
- CMap *cmap;
- PSTokenizer *pst;
- char tok1[256], tok2[256], tok3[256];
- int n1, n2, n3;
- Guint start, end, code;
-
- if (!(f = globalParams->findCMapFile(collectionA, cMapNameA))) {
-
- // Check for an identity CMap.
- if (!cMapNameA->cmp("Identity") || !cMapNameA->cmp("Identity-H")) {
- return new CMap(collectionA->copy(), cMapNameA->copy(), 0);
- }
- if (!cMapNameA->cmp("Identity-V")) {
- return new CMap(collectionA->copy(), cMapNameA->copy(), 1);
- }
-
- error(-1, "Couldn't find '%s' CMap file for '%s' collection",
- cMapNameA->getCString(), collectionA->getCString());
- return NULL;
- }
-
- cmap = new CMap(collectionA->copy(), cMapNameA->copy());
-
- pst = new PSTokenizer(&getCharFromFile, f);
- pst->getToken(tok1, sizeof(tok1), &n1);
- while (pst->getToken(tok2, sizeof(tok2), &n2)) {
- if (!strcmp(tok2, "usecmap")) {
- if (tok1[0] == '/') {
- cmap->useCMap(cache, tok1 + 1);
- }
- pst->getToken(tok1, sizeof(tok1), &n1);
- } else if (!strcmp(tok1, "/WMode")) {
- cmap->wMode = atoi(tok2);
- pst->getToken(tok1, sizeof(tok1), &n1);
- } else if (!strcmp(tok2, "begincodespacerange")) {
- while (pst->getToken(tok1, sizeof(tok1), &n1)) {
- if (!strcmp(tok1, "endcodespacerange")) {
- break;
- }
- if (!pst->getToken(tok2, sizeof(tok2), &n2) ||
- !strcmp(tok2, "endcodespacerange")) {
- error(-1, "Illegal entry in codespacerange block in CMap");
- break;
- }
- if (tok1[0] == '<' && tok2[0] == '<' &&
- n1 == n2 && n1 >= 4 && (n1 & 1) == 0) {
- tok1[n1 - 1] = tok2[n1 - 1] = '\0';
- sscanf(tok1 + 1, "%x", &start);
- sscanf(tok2 + 1, "%x", &end);
- n1 = (n1 - 2) / 2;
- cmap->addCodeSpace(cmap->vector, start, end, n1);
- }
- }
- pst->getToken(tok1, sizeof(tok1), &n1);
- } else if (!strcmp(tok2, "begincidchar")) {
- while (pst->getToken(tok1, sizeof(tok1), &n1)) {
- if (!strcmp(tok1, "endcidchar")) {
- break;
- }
- if (!pst->getToken(tok2, sizeof(tok2), &n2) ||
- !strcmp(tok2, "endcidchar")) {
- error(-1, "Illegal entry in cidchar block in CMap");
- break;
- }
- if (!(tok1[0] == '<' && tok1[n1 - 1] == '>' &&
- n1 >= 4 && (n1 & 1) == 0)) {
- error(-1, "Illegal entry in cidchar block in CMap");
- continue;
- }
- tok1[n1 - 1] = '\0';
- if (sscanf(tok1 + 1, "%x", &code) != 1) {
- error(-1, "Illegal entry in cidchar block in CMap");
- continue;
- }
- n1 = (n1 - 2) / 2;
- cmap->addCIDs(code, code, n1, (CID)atoi(tok2));
- }
- pst->getToken(tok1, sizeof(tok1), &n1);
- } else if (!strcmp(tok2, "begincidrange")) {
- while (pst->getToken(tok1, sizeof(tok1), &n1)) {
- if (!strcmp(tok1, "endcidrange")) {
- break;
- }
- if (!pst->getToken(tok2, sizeof(tok2), &n2) ||
- !strcmp(tok2, "endcidrange") ||
- !pst->getToken(tok3, sizeof(tok3), &n3) ||
- !strcmp(tok3, "endcidrange")) {
- error(-1, "Illegal entry in cidrange block in CMap");
- break;
- }
- if (tok1[0] == '<' && tok2[0] == '<' &&
- n1 == n2 && n1 >= 4 && (n1 & 1) == 0) {
- tok1[n1 - 1] = tok2[n1 - 1] = '\0';
- sscanf(tok1 + 1, "%x", &start);
- sscanf(tok2 + 1, "%x", &end);
- n1 = (n1 - 2) / 2;
- cmap->addCIDs(start, end, n1, (CID)atoi(tok3));
- }
- }
- pst->getToken(tok1, sizeof(tok1), &n1);
- } else {
- strcpy(tok1, tok2);
- }
- }
- delete pst;
-
- fclose(f);
-
- return cmap;
-}
-
-CMap::CMap(GString *collectionA, GString *cMapNameA) {
- int i;
-
- collection = collectionA;
- cMapName = cMapNameA;
- wMode = 0;
- vector = (CMapVectorEntry *)gmallocn(256, sizeof(CMapVectorEntry));
- for (i = 0; i < 256; ++i) {
- vector[i].isVector = gFalse;
- vector[i].cid = 0;
- }
- refCnt = 1;
-#if MULTITHREADED
- gInitMutex(&mutex);
-#endif
-}
-
-CMap::CMap(GString *collectionA, GString *cMapNameA, int wModeA) {
- collection = collectionA;
- cMapName = cMapNameA;
- wMode = wModeA;
- vector = NULL;
- refCnt = 1;
-#if MULTITHREADED
- gInitMutex(&mutex);
-#endif
-}
-
-void CMap::useCMap(CMapCache *cache, char *useName) {
- GString *useNameStr;
- CMap *subCMap;
-
- useNameStr = new GString(useName);
- subCMap = cache->getCMap(collection, useNameStr);
- delete useNameStr;
- if (!subCMap) {
- return;
- }
- copyVector(vector, subCMap->vector);
- subCMap->decRefCnt();
-}
-
-void CMap::copyVector(CMapVectorEntry *dest, CMapVectorEntry *src) {
- int i, j;
-
- for (i = 0; i < 256; ++i) {
- if (src[i].isVector) {
- if (!dest[i].isVector) {
- dest[i].isVector = gTrue;
- dest[i].vector =
- (CMapVectorEntry *)gmallocn(256, sizeof(CMapVectorEntry));
- for (j = 0; j < 256; ++j) {
- dest[i].vector[j].isVector = gFalse;
- dest[i].vector[j].cid = 0;
- }
- }
- copyVector(dest[i].vector, src[i].vector);
- } else {
- if (dest[i].isVector) {
- error(-1, "Collision in usecmap");
- } else {
- dest[i].cid = src[i].cid;
- }
- }
- }
-}
-
-void CMap::addCodeSpace(CMapVectorEntry *vec, Guint start, Guint end,
- Guint nBytes) {
- Guint start2, end2;
- int startByte, endByte, i, j;
-
- if (nBytes > 1) {
- startByte = (start >> (8 * (nBytes - 1))) & 0xff;
- endByte = (end >> (8 * (nBytes - 1))) & 0xff;
- start2 = start & ((1 << (8 * (nBytes - 1))) - 1);
- end2 = end & ((1 << (8 * (nBytes - 1))) - 1);
- for (i = startByte; i <= endByte; ++i) {
- if (!vec[i].isVector) {
- vec[i].isVector = gTrue;
- vec[i].vector =
- (CMapVectorEntry *)gmallocn(256, sizeof(CMapVectorEntry));
- for (j = 0; j < 256; ++j) {
- vec[i].vector[j].isVector = gFalse;
- vec[i].vector[j].cid = 0;
- }
- }
- addCodeSpace(vec[i].vector, start2, end2, nBytes - 1);
- }
- }
-}
-
-void CMap::addCIDs(Guint start, Guint end, Guint nBytes, CID firstCID) {
- CMapVectorEntry *vec;
- CID cid;
- int byte;
- Guint i;
-
- vec = vector;
- for (i = nBytes - 1; i >= 1; --i) {
- byte = (start >> (8 * i)) & 0xff;
- if (!vec[byte].isVector) {
- error(-1, "Invalid CID (%0*x - %0*x) in CMap",
- 2*nBytes, start, 2*nBytes, end);
- return;
- }
- vec = vec[byte].vector;
- }
- cid = firstCID;
- for (byte = (int)(start & 0xff); byte <= (int)(end & 0xff); ++byte) {
- if (vec[byte].isVector) {
- error(-1, "Invalid CID (%0*x - %0*x) in CMap",
- 2*nBytes, start, 2*nBytes, end);
- } else {
- vec[byte].cid = cid;
- }
- ++cid;
- }
-}
-
-CMap::~CMap() {
- delete collection;
- delete cMapName;
- if (vector) {
- freeCMapVector(vector);
- }
-#if MULTITHREADED
- gDestroyMutex(&mutex);
-#endif
-}
-
-void CMap::freeCMapVector(CMapVectorEntry *vec) {
- int i;
-
- for (i = 0; i < 256; ++i) {
- if (vec[i].isVector) {
- freeCMapVector(vec[i].vector);
- }
- }
- gfree(vec);
-}
-
-void CMap::incRefCnt() {
-#if MULTITHREADED
- gLockMutex(&mutex);
-#endif
- ++refCnt;
-#if MULTITHREADED
- gUnlockMutex(&mutex);
-#endif
-}
-
-void CMap::decRefCnt() {
- GBool done;
-
-#if MULTITHREADED
- gLockMutex(&mutex);
-#endif
- done = --refCnt == 0;
-#if MULTITHREADED
- gUnlockMutex(&mutex);
-#endif
- if (done) {
- delete this;
- }
-}
-
-GBool CMap::match(GString *collectionA, GString *cMapNameA) {
- return !collection->cmp(collectionA) && !cMapName->cmp(cMapNameA);
-}
-
-CID CMap::getCID(char *s, int len, int *nUsed) {
- CMapVectorEntry *vec;
- int n, i;
-
- if (!(vec = vector)) {
- // identity CMap
- *nUsed = 2;
- if (len < 2) {
- return 0;
- }
- return ((s[0] & 0xff) << 8) + (s[1] & 0xff);
- }
- n = 0;
- while (1) {
- if (n >= len) {
- *nUsed = n;
- return 0;
- }
- i = s[n++] & 0xff;
- if (!vec[i].isVector) {
- *nUsed = n;
- return vec[i].cid;
- }
- vec = vec[i].vector;
- }
-}
-
-//------------------------------------------------------------------------
-
-CMapCache::CMapCache() {
- int i;
-
- for (i = 0; i < cMapCacheSize; ++i) {
- cache[i] = NULL;
- }
-}
-
-CMapCache::~CMapCache() {
- int i;
-
- for (i = 0; i < cMapCacheSize; ++i) {
- if (cache[i]) {
- cache[i]->decRefCnt();
- }
- }
-}
-
-CMap *CMapCache::getCMap(GString *collection, GString *cMapName) {
- CMap *cmap;
- int i, j;
-
- if (cache[0] && cache[0]->match(collection, cMapName)) {
- cache[0]->incRefCnt();
- return cache[0];
- }
- for (i = 1; i < cMapCacheSize; ++i) {
- if (cache[i] && cache[i]->match(collection, cMapName)) {
- cmap = cache[i];
- for (j = i; j >= 1; --j) {
- cache[j] = cache[j - 1];
- }
- cache[0] = cmap;
- cmap->incRefCnt();
- return cmap;
- }
- }
- if ((cmap = CMap::parse(this, collection, cMapName))) {
- if (cache[cMapCacheSize - 1]) {
- cache[cMapCacheSize - 1]->decRefCnt();
- }
- for (j = cMapCacheSize - 1; j >= 1; --j) {
- cache[j] = cache[j - 1];
- }
- cache[0] = cmap;
- cmap->incRefCnt();
- return cmap;
- }
- return NULL;
-}
+++ /dev/null
-//========================================================================
-//
-// CMap.h
-//
-// Copyright 2001-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#ifndef CMAP_H
-#define CMAP_H
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma interface
-#endif
-
-#include "gtypes.h"
-#include "CharTypes.h"
-
-#if MULTITHREADED
-#include "GMutex.h"
-#endif
-
-class GString;
-struct CMapVectorEntry;
-class CMapCache;
-
-//------------------------------------------------------------------------
-
-class CMap {
-public:
-
- // Create the CMap specified by <collection> and <cMapName>. Sets
- // the initial reference count to 1. Returns NULL on failure.
- static CMap *parse(CMapCache *cache, GString *collectionA,
- GString *cMapNameA);
-
- ~CMap();
-
- void incRefCnt();
- void decRefCnt();
-
- // Return collection name (<registry>-<ordering>).
- GString *getCollection() { return collection; }
-
- // Return true if this CMap matches the specified <collectionA>, and
- // <cMapNameA>.
- GBool match(GString *collectionA, GString *cMapNameA);
-
- // Return the CID corresponding to the character code starting at
- // <s>, which contains <len> bytes. Sets *<nUsed> to the number of
- // bytes used by the char code.
- CID getCID(char *s, int len, int *nUsed);
-
- // Return the writing mode (0=horizontal, 1=vertical).
- int getWMode() { return wMode; }
-
-private:
-
- CMap(GString *collectionA, GString *cMapNameA);
- CMap(GString *collectionA, GString *cMapNameA, int wModeA);
- void useCMap(CMapCache *cache, char *useName);
- void copyVector(CMapVectorEntry *dest, CMapVectorEntry *src);
- void addCodeSpace(CMapVectorEntry *vec, Guint start, Guint end,
- Guint nBytes);
- void addCIDs(Guint start, Guint end, Guint nBytes, CID firstCID);
- void freeCMapVector(CMapVectorEntry *vec);
-
- GString *collection;
- GString *cMapName;
- int wMode; // writing mode (0=horizontal, 1=vertical)
- CMapVectorEntry *vector; // vector for first byte (NULL for
- // identity CMap)
- int refCnt;
-#if MULTITHREADED
- GMutex mutex;
-#endif
-};
-
-//------------------------------------------------------------------------
-
-#define cMapCacheSize 4
-
-class CMapCache {
-public:
-
- CMapCache();
- ~CMapCache();
-
- // Get the <cMapName> CMap for the specified character collection.
- // Increments its reference count; there will be one reference for
- // the cache plus one for the caller of this function. Returns NULL
- // on failure.
- CMap *getCMap(GString *collection, GString *cMapName);
-
-private:
-
- CMap *cache[cMapCacheSize];
-};
-
-#endif
+++ /dev/null
-//========================================================================
-//
-// Catalog.cc
-//
-// Copyright 1996-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma implementation
-#endif
-
-#include <stddef.h>
-#include "gmem.h"
-#include "Object.h"
-#include "XRef.h"
-#include "Array.h"
-#include "Dict.h"
-#include "Page.h"
-#include "Error.h"
-#include "Link.h"
-#include "Catalog.h"
-
-//------------------------------------------------------------------------
-// Catalog
-//------------------------------------------------------------------------
-
-Catalog::Catalog(XRef *xrefA) {
- Object catDict, pagesDict;
- Object obj, obj2;
- int numPages0;
- int i;
-
- ok = gTrue;
- xref = xrefA;
- pages = NULL;
- pageRefs = NULL;
- numPages = pagesSize = 0;
- baseURI = NULL;
-
- xref->getCatalog(&catDict);
- if (!catDict.isDict()) {
- error(-1, "Catalog object is wrong type (%s)", catDict.getTypeName());
- goto err1;
- }
-
- // read page tree
- catDict.dictLookup("Pages", &pagesDict);
- // This should really be isDict("Pages"), but I've seen at least one
- // PDF file where the /Type entry is missing.
- if (!pagesDict.isDict()) {
- error(-1, "Top-level pages object is wrong type (%s)",
- pagesDict.getTypeName());
- goto err2;
- }
- pagesDict.dictLookup("Count", &obj);
- // some PDF files actually use real numbers here ("/Count 9.0")
- if (!obj.isNum()) {
- error(-1, "Page count in top-level pages object is wrong type (%s)",
- obj.getTypeName());
- goto err3;
- }
- pagesSize = numPages0 = (int)obj.getNum();
- obj.free();
- pages = (Page **)gmallocn(pagesSize, sizeof(Page *));
- pageRefs = (Ref *)gmallocn(pagesSize, sizeof(Ref));
- for (i = 0; i < pagesSize; ++i) {
- pages[i] = NULL;
- pageRefs[i].num = -1;
- pageRefs[i].gen = -1;
- }
- numPages = readPageTree(pagesDict.getDict(), NULL, 0);
- if (numPages != numPages0) {
- error(-1, "Page count in top-level pages object is incorrect");
- }
- pagesDict.free();
-
- // read named destination dictionary
- catDict.dictLookup("Dests", &dests);
-
- // read root of named destination tree
- if (catDict.dictLookup("Names", &obj)->isDict())
- obj.dictLookup("Dests", &nameTree);
- else
- nameTree.initNull();
- obj.free();
-
- // read base URI
- if (catDict.dictLookup("URI", &obj)->isDict()) {
- if (obj.dictLookup("Base", &obj2)->isString()) {
- baseURI = obj2.getString()->copy();
- }
- obj2.free();
- }
- obj.free();
-
- // get the metadata stream
- catDict.dictLookup("Metadata", &metadata);
-
- // get the structure tree root
- catDict.dictLookup("StructTreeRoot", &structTreeRoot);
-
- // get the outline dictionary
- catDict.dictLookup("Outlines", &outline);
-
- // get the AcroForm dictionary
- catDict.dictLookup("AcroForm", &acroForm);
-
- catDict.free();
- return;
-
- err3:
- obj.free();
- err2:
- pagesDict.free();
- err1:
- catDict.free();
- dests.initNull();
- nameTree.initNull();
- ok = gFalse;
-}
-
-Catalog::~Catalog() {
- int i;
-
- if (pages) {
- for (i = 0; i < pagesSize; ++i) {
- if (pages[i]) {
- delete pages[i];
- }
- }
- gfree(pages);
- gfree(pageRefs);
- }
- dests.free();
- nameTree.free();
- if (baseURI) {
- delete baseURI;
- }
- metadata.free();
- structTreeRoot.free();
- outline.free();
- acroForm.free();
-}
-
-GString *Catalog::readMetadata() {
- GString *s;
- Dict *dict;
- Object obj;
- int c;
-
- if (!metadata.isStream()) {
- return NULL;
- }
- dict = metadata.streamGetDict();
- if (!dict->lookup("Subtype", &obj)->isName("XML")) {
- error(-1, "Unknown Metadata type: '%s'",
- obj.isName() ? obj.getName() : "???");
- }
- obj.free();
- s = new GString();
- metadata.streamReset();
- while ((c = metadata.streamGetChar()) != EOF) {
- s->append(c);
- }
- metadata.streamClose();
- return s;
-}
-
-int Catalog::readPageTree(Dict *pagesDict, PageAttrs *attrs, int start) {
- Object kids;
- Object kid;
- Object kidRef;
- PageAttrs *attrs1, *attrs2;
- Page *page;
- int i, j;
-
- attrs1 = new PageAttrs(attrs, pagesDict);
- pagesDict->lookup("Kids", &kids);
- if (!kids.isArray()) {
- error(-1, "Kids object (page %d) is wrong type (%s)",
- start+1, kids.getTypeName());
- goto err1;
- }
- for (i = 0; i < kids.arrayGetLength(); ++i) {
- kids.arrayGet(i, &kid);
- if (kid.isDict("Page")) {
- attrs2 = new PageAttrs(attrs1, kid.getDict());
- page = new Page(xref, start+1, kid.getDict(), attrs2);
- if (!page->isOk()) {
- ++start;
- goto err3;
- }
- if (start >= pagesSize) {
- pagesSize += 32;
- pages = (Page **)greallocn(pages, pagesSize, sizeof(Page *));
- pageRefs = (Ref *)greallocn(pageRefs, pagesSize, sizeof(Ref));
- for (j = pagesSize - 32; j < pagesSize; ++j) {
- pages[j] = NULL;
- pageRefs[j].num = -1;
- pageRefs[j].gen = -1;
- }
- }
- pages[start] = page;
- kids.arrayGetNF(i, &kidRef);
- if (kidRef.isRef()) {
- pageRefs[start].num = kidRef.getRefNum();
- pageRefs[start].gen = kidRef.getRefGen();
- }
- kidRef.free();
- ++start;
- // This should really be isDict("Pages"), but I've seen at least one
- // PDF file where the /Type entry is missing.
- } else if (kid.isDict()) {
- if ((start = readPageTree(kid.getDict(), attrs1, start))
- < 0)
- goto err2;
- } else {
- error(-1, "Kid object (page %d) is wrong type (%s)",
- start+1, kid.getTypeName());
- }
- kid.free();
- }
- delete attrs1;
- kids.free();
- return start;
-
- err3:
- delete page;
- err2:
- kid.free();
- err1:
- kids.free();
- delete attrs1;
- ok = gFalse;
- return -1;
-}
-
-int Catalog::findPage(int num, int gen) {
- int i;
-
- for (i = 0; i < numPages; ++i) {
- if (pageRefs[i].num == num && pageRefs[i].gen == gen)
- return i + 1;
- }
- return 0;
-}
-
-LinkDest *Catalog::findDest(GString *name) {
- LinkDest *dest;
- Object obj1, obj2;
- GBool found;
-
- // try named destination dictionary then name tree
- found = gFalse;
- if (dests.isDict()) {
- if (!dests.dictLookup(name->getCString(), &obj1)->isNull())
- found = gTrue;
- else
- obj1.free();
- }
- if (!found && nameTree.isDict()) {
- if (!findDestInTree(&nameTree, name, &obj1)->isNull())
- found = gTrue;
- else
- obj1.free();
- }
- if (!found)
- return NULL;
-
- // construct LinkDest
- dest = NULL;
- if (obj1.isArray()) {
- dest = new LinkDest(obj1.getArray());
- } else if (obj1.isDict()) {
- if (obj1.dictLookup("D", &obj2)->isArray())
- dest = new LinkDest(obj2.getArray());
- else
- error(-1, "Bad named destination value");
- obj2.free();
- } else {
- error(-1, "Bad named destination value");
- }
- obj1.free();
- if (dest && !dest->isOk()) {
- delete dest;
- dest = NULL;
- }
-
- return dest;
-}
-
-Object *Catalog::findDestInTree(Object *tree, GString *name, Object *obj) {
- Object names, name1;
- Object kids, kid, limits, low, high;
- GBool done, found;
- int cmp, i;
-
- // leaf node
- if (tree->dictLookup("Names", &names)->isArray()) {
- done = found = gFalse;
- for (i = 0; !done && i < names.arrayGetLength(); i += 2) {
- if (names.arrayGet(i, &name1)->isString()) {
- cmp = name->cmp(name1.getString());
- if (cmp == 0) {
- names.arrayGet(i+1, obj);
- found = gTrue;
- done = gTrue;
- } else if (cmp < 0) {
- done = gTrue;
- }
- }
- name1.free();
- }
- names.free();
- if (!found)
- obj->initNull();
- return obj;
- }
- names.free();
-
- // root or intermediate node
- done = gFalse;
- if (tree->dictLookup("Kids", &kids)->isArray()) {
- for (i = 0; !done && i < kids.arrayGetLength(); ++i) {
- if (kids.arrayGet(i, &kid)->isDict()) {
- if (kid.dictLookup("Limits", &limits)->isArray()) {
- if (limits.arrayGet(0, &low)->isString() &&
- name->cmp(low.getString()) >= 0) {
- if (limits.arrayGet(1, &high)->isString() &&
- name->cmp(high.getString()) <= 0) {
- findDestInTree(&kid, name, obj);
- done = gTrue;
- }
- high.free();
- }
- low.free();
- }
- limits.free();
- }
- kid.free();
- }
- }
- kids.free();
-
- // name was outside of ranges of all kids
- if (!done)
- obj->initNull();
-
- return obj;
-}
+++ /dev/null
-//========================================================================
-//
-// Catalog.h
-//
-// Copyright 1996-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#ifndef CATALOG_H
-#define CATALOG_H
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma interface
-#endif
-
-class XRef;
-class Object;
-class Page;
-class PageAttrs;
-struct Ref;
-class LinkDest;
-
-//------------------------------------------------------------------------
-// Catalog
-//------------------------------------------------------------------------
-
-class Catalog {
-public:
-
- // Constructor.
- Catalog(XRef *xrefA);
-
- // Destructor.
- ~Catalog();
-
- // Is catalog valid?
- GBool isOk() { return ok; }
-
- // Get number of pages.
- int getNumPages() { return numPages; }
-
- // Get a page.
- Page *getPage(int i) { return pages[i-1]; }
-
- // Get the reference for a page object.
- Ref *getPageRef(int i) { return &pageRefs[i-1]; }
-
- // Return base URI, or NULL if none.
- GString *getBaseURI() { return baseURI; }
-
- // Return the contents of the metadata stream, or NULL if there is
- // no metadata.
- GString *readMetadata();
-
- // Return the structure tree root object.
- Object *getStructTreeRoot() { return &structTreeRoot; }
-
- // Find a page, given its object ID. Returns page number, or 0 if
- // not found.
- int findPage(int num, int gen);
-
- // Find a named destination. Returns the link destination, or
- // NULL if <name> is not a destination.
- LinkDest *findDest(GString *name);
-
- Object *getOutline() { return &outline; }
-
- Object *getAcroForm() { return &acroForm; }
-
-private:
-
- XRef *xref; // the xref table for this PDF file
- Page **pages; // array of pages
- Ref *pageRefs; // object ID for each page
- int numPages; // number of pages
- int pagesSize; // size of pages array
- Object dests; // named destination dictionary
- Object nameTree; // name tree
- GString *baseURI; // base URI for URI-type links
- Object metadata; // metadata stream
- Object structTreeRoot; // structure tree root dictionary
- Object outline; // outline dictionary
- Object acroForm; // AcroForm dictionary
- GBool ok; // true if catalog is valid
-
- int readPageTree(Dict *pages, PageAttrs *attrs, int start);
- Object *findDestInTree(Object *tree, GString *name, Object *obj);
-};
-
-#endif
+++ /dev/null
-//========================================================================
-//
-// CharCodeToUnicode.cc
-//
-// Copyright 2001-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma implementation
-#endif
-
-#include <stdio.h>
-#include <string.h>
-#include "gmem.h"
-#include "gfile.h"
-#include "GString.h"
-#include "Error.h"
-#include "GlobalParams.h"
-#include "PSTokenizer.h"
-#include "CharCodeToUnicode.h"
-
-//------------------------------------------------------------------------
-
-#define maxUnicodeString 8
-
-struct CharCodeToUnicodeString {
- CharCode c;
- Unicode u[maxUnicodeString];
- int len;
-};
-
-//------------------------------------------------------------------------
-
-static int getCharFromString(void *data) {
- char *p;
- int c;
-
- p = *(char **)data;
- if (*p) {
- c = *p++;
- *(char **)data = p;
- } else {
- c = EOF;
- }
- return c;
-}
-
-static int getCharFromFile(void *data) {
- return fgetc((FILE *)data);
-}
-
-//------------------------------------------------------------------------
-
-CharCodeToUnicode *CharCodeToUnicode::parseCIDToUnicode(GString *fileName,
- GString *collection) {
- FILE *f;
- Unicode *mapA;
- CharCode size, mapLenA;
- char buf[64];
- Unicode u;
- CharCodeToUnicode *ctu;
-
- if (!(f = fopen(fileName->getCString(), "r"))) {
- error(-1, "Couldn't open cidToUnicode file '%s'",
- fileName->getCString());
- return NULL;
- }
-
- size = 32768;
- mapA = (Unicode *)gmallocn(size, sizeof(Unicode));
- mapLenA = 0;
-
- while (getLine(buf, sizeof(buf), f)) {
- if (mapLenA == size) {
- size *= 2;
- mapA = (Unicode *)greallocn(mapA, size, sizeof(Unicode));
- }
- if (sscanf(buf, "%x", &u) == 1) {
- mapA[mapLenA] = u;
- } else {
- error(-1, "Bad line (%d) in cidToUnicode file '%s'",
- (int)(mapLenA + 1), fileName->getCString());
- mapA[mapLenA] = 0;
- }
- ++mapLenA;
- }
- fclose(f);
-
- ctu = new CharCodeToUnicode(collection->copy(), mapA, mapLenA, gTrue,
- NULL, 0, 0);
- gfree(mapA);
- return ctu;
-}
-
-CharCodeToUnicode *CharCodeToUnicode::parseUnicodeToUnicode(
- GString *fileName) {
- FILE *f;
- Unicode *mapA;
- CharCodeToUnicodeString *sMapA;
- CharCode size, oldSize, len, sMapSizeA, sMapLenA;
- char buf[256];
- char *tok;
- Unicode u0;
- Unicode uBuf[maxUnicodeString];
- CharCodeToUnicode *ctu;
- int line, n, i;
-
- if (!(f = fopen(fileName->getCString(), "r"))) {
- error(-1, "Couldn't open unicodeToUnicode file '%s'",
- fileName->getCString());
- return NULL;
- }
-
- size = 4096;
- mapA = (Unicode *)gmallocn(size, sizeof(Unicode));
- memset(mapA, 0, size * sizeof(Unicode));
- len = 0;
- sMapA = NULL;
- sMapSizeA = sMapLenA = 0;
-
- line = 0;
- while (getLine(buf, sizeof(buf), f)) {
- ++line;
- if (!(tok = strtok(buf, " \t\r\n")) ||
- sscanf(tok, "%x", &u0) != 1) {
- error(-1, "Bad line (%d) in unicodeToUnicode file '%s'",
- line, fileName->getCString());
- continue;
- }
- n = 0;
- while (n < maxUnicodeString) {
- if (!(tok = strtok(NULL, " \t\r\n"))) {
- break;
- }
- if (sscanf(tok, "%x", &uBuf[n]) != 1) {
- error(-1, "Bad line (%d) in unicodeToUnicode file '%s'",
- line, fileName->getCString());
- break;
- }
- ++n;
- }
- if (n < 1) {
- error(-1, "Bad line (%d) in unicodeToUnicode file '%s'",
- line, fileName->getCString());
- continue;
- }
- if (u0 >= size) {
- oldSize = size;
- while (u0 >= size) {
- size *= 2;
- }
- mapA = (Unicode *)greallocn(mapA, size, sizeof(Unicode));
- memset(mapA + oldSize, 0, (size - oldSize) * sizeof(Unicode));
- }
- if (n == 1) {
- mapA[u0] = uBuf[0];
- } else {
- mapA[u0] = 0;
- if (sMapLenA == sMapSizeA) {
- sMapSizeA += 16;
- sMapA = (CharCodeToUnicodeString *)
- greallocn(sMapA, sMapSizeA, sizeof(CharCodeToUnicodeString));
- }
- sMapA[sMapLenA].c = u0;
- for (i = 0; i < n; ++i) {
- sMapA[sMapLenA].u[i] = uBuf[i];
- }
- sMapA[sMapLenA].len = n;
- ++sMapLenA;
- }
- if (u0 >= len) {
- len = u0 + 1;
- }
- }
- fclose(f);
-
- ctu = new CharCodeToUnicode(fileName->copy(), mapA, len, gTrue,
- sMapA, sMapLenA, sMapSizeA);
- gfree(mapA);
- return ctu;
-}
-
-CharCodeToUnicode *CharCodeToUnicode::make8BitToUnicode(Unicode *toUnicode) {
- return new CharCodeToUnicode(NULL, toUnicode, 256, gTrue, NULL, 0, 0);
-}
-
-CharCodeToUnicode *CharCodeToUnicode::parseCMap(GString *buf, int nBits) {
- CharCodeToUnicode *ctu;
- char *p;
-
- ctu = new CharCodeToUnicode(NULL);
- p = buf->getCString();
- ctu->parseCMap1(&getCharFromString, &p, nBits);
- return ctu;
-}
-
-void CharCodeToUnicode::mergeCMap(GString *buf, int nBits) {
- char *p;
-
- p = buf->getCString();
- parseCMap1(&getCharFromString, &p, nBits);
-}
-
-void CharCodeToUnicode::parseCMap1(int (*getCharFunc)(void *), void *data,
- int nBits) {
- PSTokenizer *pst;
- char tok1[256], tok2[256], tok3[256];
- int nDigits, n1, n2, n3;
- CharCode i;
- CharCode code1, code2;
- GString *name;
- FILE *f;
-
- nDigits = nBits / 4;
- pst = new PSTokenizer(getCharFunc, data);
- pst->getToken(tok1, sizeof(tok1), &n1);
- while (pst->getToken(tok2, sizeof(tok2), &n2)) {
- if (!strcmp(tok2, "usecmap")) {
- if (tok1[0] == '/') {
- name = new GString(tok1 + 1);
- if ((f = globalParams->findToUnicodeFile(name))) {
- parseCMap1(&getCharFromFile, f, nBits);
- fclose(f);
- } else {
- error(-1, "Couldn't find ToUnicode CMap file for '%s'",
- name->getCString());
- }
- delete name;
- }
- pst->getToken(tok1, sizeof(tok1), &n1);
- } else if (!strcmp(tok2, "beginbfchar")) {
- while (pst->getToken(tok1, sizeof(tok1), &n1)) {
- if (!strcmp(tok1, "endbfchar")) {
- break;
- }
- if (!pst->getToken(tok2, sizeof(tok2), &n2) ||
- !strcmp(tok2, "endbfchar")) {
- error(-1, "Illegal entry in bfchar block in ToUnicode CMap");
- break;
- }
- if (!(n1 == 2 + nDigits && tok1[0] == '<' && tok1[n1 - 1] == '>' &&
- tok2[0] == '<' && tok2[n2 - 1] == '>')) {
- error(-1, "Illegal entry in bfchar block in ToUnicode CMap");
- continue;
- }
- tok1[n1 - 1] = tok2[n2 - 1] = '\0';
- if (sscanf(tok1 + 1, "%x", &code1) != 1) {
- error(-1, "Illegal entry in bfchar block in ToUnicode CMap");
- continue;
- }
- addMapping(code1, tok2 + 1, n2 - 2, 0);
- }
- pst->getToken(tok1, sizeof(tok1), &n1);
- } else if (!strcmp(tok2, "beginbfrange")) {
- while (pst->getToken(tok1, sizeof(tok1), &n1)) {
- if (!strcmp(tok1, "endbfrange")) {
- break;
- }
- if (!pst->getToken(tok2, sizeof(tok2), &n2) ||
- !strcmp(tok2, "endbfrange") ||
- !pst->getToken(tok3, sizeof(tok3), &n3) ||
- !strcmp(tok3, "endbfrange")) {
- error(-1, "Illegal entry in bfrange block in ToUnicode CMap");
- break;
- }
- if (!(n1 == 2 + nDigits && tok1[0] == '<' && tok1[n1 - 1] == '>' &&
- n2 == 2 + nDigits && tok2[0] == '<' && tok2[n2 - 1] == '>')) {
- error(-1, "Illegal entry in bfrange block in ToUnicode CMap");
- continue;
- }
- tok1[n1 - 1] = tok2[n2 - 1] = '\0';
- if (sscanf(tok1 + 1, "%x", &code1) != 1 ||
- sscanf(tok2 + 1, "%x", &code2) != 1) {
- error(-1, "Illegal entry in bfrange block in ToUnicode CMap");
- continue;
- }
- if (!strcmp(tok3, "[")) {
- i = 0;
- while (pst->getToken(tok1, sizeof(tok1), &n1) &&
- code1 + i <= code2) {
- if (!strcmp(tok1, "]")) {
- break;
- }
- if (tok1[0] == '<' && tok1[n1 - 1] == '>') {
- tok1[n1 - 1] = '\0';
- addMapping(code1 + i, tok1 + 1, n1 - 2, 0);
- } else {
- error(-1, "Illegal entry in bfrange block in ToUnicode CMap");
- }
- ++i;
- }
- } else if (tok3[0] == '<' && tok3[n3 - 1] == '>') {
- tok3[n3 - 1] = '\0';
- for (i = 0; code1 <= code2; ++code1, ++i) {
- addMapping(code1, tok3 + 1, n3 - 2, i);
- }
-
- } else {
- error(-1, "Illegal entry in bfrange block in ToUnicode CMap");
- }
- }
- pst->getToken(tok1, sizeof(tok1), &n1);
- } else {
- strcpy(tok1, tok2);
- }
- }
- delete pst;
-}
-
-void CharCodeToUnicode::addMapping(CharCode code, char *uStr, int n,
- int offset) {
- CharCode oldLen, i;
- Unicode u;
- char uHex[5];
- int j;
-
- if (code >= mapLen) {
- oldLen = mapLen;
- mapLen = (code + 256) & ~255;
- map = (Unicode *)greallocn(map, mapLen, sizeof(Unicode));
- for (i = oldLen; i < mapLen; ++i) {
- map[i] = 0;
- }
- }
- if (n <= 4) {
- if (sscanf(uStr, "%x", &u) != 1) {
- error(-1, "Illegal entry in ToUnicode CMap");
- return;
- }
- map[code] = u + offset;
- } else {
- if (sMapLen >= sMapSize) {
- sMapSize = sMapSize + 16;
- sMap = (CharCodeToUnicodeString *)
- greallocn(sMap, sMapSize, sizeof(CharCodeToUnicodeString));
- }
- map[code] = 0;
- sMap[sMapLen].c = code;
- sMap[sMapLen].len = n / 4;
- for (j = 0; j < sMap[sMapLen].len && j < maxUnicodeString; ++j) {
- strncpy(uHex, uStr + j*4, 4);
- uHex[4] = '\0';
- if (sscanf(uHex, "%x", &sMap[sMapLen].u[j]) != 1) {
- error(-1, "Illegal entry in ToUnicode CMap");
- }
- }
- sMap[sMapLen].u[sMap[sMapLen].len - 1] += offset;
- ++sMapLen;
- }
-}
-
-CharCodeToUnicode::CharCodeToUnicode(GString *tagA) {
- CharCode i;
-
- tag = tagA;
- mapLen = 256;
- map = (Unicode *)gmallocn(mapLen, sizeof(Unicode));
- for (i = 0; i < mapLen; ++i) {
- map[i] = 0;
- }
- sMap = NULL;
- sMapLen = sMapSize = 0;
- refCnt = 1;
-#if MULTITHREADED
- gInitMutex(&mutex);
-#endif
-}
-
-CharCodeToUnicode::CharCodeToUnicode(GString *tagA, Unicode *mapA,
- CharCode mapLenA, GBool copyMap,
- CharCodeToUnicodeString *sMapA,
- int sMapLenA, int sMapSizeA) {
- tag = tagA;
- mapLen = mapLenA;
- if (copyMap) {
- map = (Unicode *)gmallocn(mapLen, sizeof(Unicode));
- memcpy(map, mapA, mapLen * sizeof(Unicode));
- } else {
- map = mapA;
- }
- sMap = sMapA;
- sMapLen = sMapLenA;
- sMapSize = sMapSizeA;
- refCnt = 1;
-#if MULTITHREADED
- gInitMutex(&mutex);
-#endif
-}
-
-CharCodeToUnicode::~CharCodeToUnicode() {
- if (tag) {
- delete tag;
- }
- gfree(map);
- if (sMap) {
- gfree(sMap);
- }
-#if MULTITHREADED
- gDestroyMutex(&mutex);
-#endif
-}
-
-void CharCodeToUnicode::incRefCnt() {
-#if MULTITHREADED
- gLockMutex(&mutex);
-#endif
- ++refCnt;
-#if MULTITHREADED
- gUnlockMutex(&mutex);
-#endif
-}
-
-void CharCodeToUnicode::decRefCnt() {
- GBool done;
-
-#if MULTITHREADED
- gLockMutex(&mutex);
-#endif
- done = --refCnt == 0;
-#if MULTITHREADED
- gUnlockMutex(&mutex);
-#endif
- if (done) {
- delete this;
- }
-}
-
-GBool CharCodeToUnicode::match(GString *tagA) {
- return tag && !tag->cmp(tagA);
-}
-
-void CharCodeToUnicode::setMapping(CharCode c, Unicode *u, int len) {
- int i, j;
-
- if (len == 1) {
- map[c] = u[0];
- } else {
- for (i = 0; i < sMapLen; ++i) {
- if (sMap[i].c == c) {
- break;
- }
- }
- if (i == sMapLen) {
- if (sMapLen == sMapSize) {
- sMapSize += 8;
- sMap = (CharCodeToUnicodeString *)
- greallocn(sMap, sMapSize, sizeof(CharCodeToUnicodeString));
- }
- ++sMapLen;
- }
- map[c] = 0;
- sMap[i].c = c;
- sMap[i].len = len;
- for (j = 0; j < len && j < maxUnicodeString; ++j) {
- sMap[i].u[j] = u[j];
- }
- }
-}
-
-int CharCodeToUnicode::mapToUnicode(CharCode c, Unicode *u, int size) {
- int i, j;
-
- if (c >= mapLen) {
- return 0;
- }
- if (map[c]) {
- u[0] = map[c];
- return 1;
- }
- for (i = 0; i < sMapLen; ++i) {
- if (sMap[i].c == c) {
- for (j = 0; j < sMap[i].len && j < size; ++j) {
- u[j] = sMap[i].u[j];
- }
- return j;
- }
- }
- return 0;
-}
-
-//------------------------------------------------------------------------
-
-CharCodeToUnicodeCache::CharCodeToUnicodeCache(int sizeA) {
- int i;
-
- size = sizeA;
- cache = (CharCodeToUnicode **)gmallocn(size, sizeof(CharCodeToUnicode *));
- for (i = 0; i < size; ++i) {
- cache[i] = NULL;
- }
-}
-
-CharCodeToUnicodeCache::~CharCodeToUnicodeCache() {
- int i;
-
- for (i = 0; i < size; ++i) {
- if (cache[i]) {
- cache[i]->decRefCnt();
- }
- }
- gfree(cache);
-}
-
-CharCodeToUnicode *CharCodeToUnicodeCache::getCharCodeToUnicode(GString *tag) {
- CharCodeToUnicode *ctu;
- int i, j;
-
- if (cache[0] && cache[0]->match(tag)) {
- cache[0]->incRefCnt();
- return cache[0];
- }
- for (i = 1; i < size; ++i) {
- if (cache[i] && cache[i]->match(tag)) {
- ctu = cache[i];
- for (j = i; j >= 1; --j) {
- cache[j] = cache[j - 1];
- }
- cache[0] = ctu;
- ctu->incRefCnt();
- return ctu;
- }
- }
- return NULL;
-}
-
-void CharCodeToUnicodeCache::add(CharCodeToUnicode *ctu) {
- int i;
-
- if (cache[size - 1]) {
- cache[size - 1]->decRefCnt();
- }
- for (i = size - 1; i >= 1; --i) {
- cache[i] = cache[i - 1];
- }
- cache[0] = ctu;
- ctu->incRefCnt();
-}
+++ /dev/null
-//========================================================================
-//
-// CharCodeToUnicode.h
-//
-// Mapping from character codes to Unicode.
-//
-// Copyright 2001-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#ifndef CHARCODETOUNICODE_H
-#define CHARCODETOUNICODE_H
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma interface
-#endif
-
-#include "CharTypes.h"
-
-#if MULTITHREADED
-#include "GMutex.h"
-#endif
-
-struct CharCodeToUnicodeString;
-
-//------------------------------------------------------------------------
-
-class CharCodeToUnicode {
-public:
-
- // Read the CID-to-Unicode mapping for <collection> from the file
- // specified by <fileName>. Sets the initial reference count to 1.
- // Returns NULL on failure.
- static CharCodeToUnicode *parseCIDToUnicode(GString *fileName,
- GString *collection);
-
- // Create a Unicode-to-Unicode mapping from the file specified by
- // <fileName>. Sets the initial reference count to 1. Returns NULL
- // on failure.
- static CharCodeToUnicode *parseUnicodeToUnicode(GString *fileName);
-
- // Create the CharCode-to-Unicode mapping for an 8-bit font.
- // <toUnicode> is an array of 256 Unicode indexes. Sets the initial
- // reference count to 1.
- static CharCodeToUnicode *make8BitToUnicode(Unicode *toUnicode);
-
- // Parse a ToUnicode CMap for an 8- or 16-bit font.
- static CharCodeToUnicode *parseCMap(GString *buf, int nBits);
-
- // Parse a ToUnicode CMap for an 8- or 16-bit font, merging it into
- // <this>.
- void mergeCMap(GString *buf, int nBits);
-
- ~CharCodeToUnicode();
-
- void incRefCnt();
- void decRefCnt();
-
- // Return true if this mapping matches the specified <tagA>.
- GBool match(GString *tagA);
-
- // Set the mapping for <c>.
- void setMapping(CharCode c, Unicode *u, int len);
-
- // Map a CharCode to Unicode.
- int mapToUnicode(CharCode c, Unicode *u, int size);
-
- // Return the mapping's length, i.e., one more than the max char
- // code supported by the mapping.
- CharCode getLength() { return mapLen; }
-
-private:
-
- void parseCMap1(int (*getCharFunc)(void *), void *data, int nBits);
- void addMapping(CharCode code, char *uStr, int n, int offset);
- CharCodeToUnicode(GString *tagA);
- CharCodeToUnicode(GString *tagA, Unicode *mapA,
- CharCode mapLenA, GBool copyMap,
- CharCodeToUnicodeString *sMapA,
- int sMapLenA, int sMapSizeA);
-
- GString *tag;
- Unicode *map;
- CharCode mapLen;
- CharCodeToUnicodeString *sMap;
- int sMapLen, sMapSize;
- int refCnt;
-#if MULTITHREADED
- GMutex mutex;
-#endif
-};
-
-//------------------------------------------------------------------------
-
-class CharCodeToUnicodeCache {
-public:
-
- CharCodeToUnicodeCache(int sizeA);
- ~CharCodeToUnicodeCache();
-
- // Get the CharCodeToUnicode object for <tag>. Increments its
- // reference count; there will be one reference for the cache plus
- // one for the caller of this function. Returns NULL on failure.
- CharCodeToUnicode *getCharCodeToUnicode(GString *tag);
-
- // Insert <ctu> into the cache, in the most-recently-used position.
- void add(CharCodeToUnicode *ctu);
-
-private:
-
- CharCodeToUnicode **cache;
- int size;
-};
-
-#endif
+++ /dev/null
-//========================================================================
-//
-// CharTypes.h
-//
-// Copyright 2001-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#ifndef CHARTYPES_H
-#define CHARTYPES_H
-
-// Unicode character.
-typedef unsigned int Unicode;
-
-// Character ID for CID character collections.
-typedef unsigned int CID;
-
-// This is large enough to hold any of the following:
-// - 8-bit char code
-// - 16-bit CID
-// - Unicode
-typedef unsigned int CharCode;
-
-#endif
+++ /dev/null
-//========================================================================
-//
-// Decrypt.cc
-//
-// Copyright 1996-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma implementation
-#endif
-
-#include <string.h>
-#include "gmem.h"
-#include "Decrypt.h"
-
-static void rc4InitKey(Guchar *key, int keyLen, Guchar *state);
-static Guchar rc4DecryptByte(Guchar *state, Guchar *x, Guchar *y, Guchar c);
-static void md5(Guchar *msg, int msgLen, Guchar *digest);
-
-static Guchar passwordPad[32] = {
- 0x28, 0xbf, 0x4e, 0x5e, 0x4e, 0x75, 0x8a, 0x41,
- 0x64, 0x00, 0x4e, 0x56, 0xff, 0xfa, 0x01, 0x08,
- 0x2e, 0x2e, 0x00, 0xb6, 0xd0, 0x68, 0x3e, 0x80,
- 0x2f, 0x0c, 0xa9, 0xfe, 0x64, 0x53, 0x69, 0x7a
-};
-
-//------------------------------------------------------------------------
-// Decrypt
-//------------------------------------------------------------------------
-
-Decrypt::Decrypt(Guchar *fileKey, int keyLength, int objNum, int objGen) {
- int i;
-
- // construct object key
- for (i = 0; i < keyLength; ++i) {
- objKey[i] = fileKey[i];
- }
- objKey[keyLength] = objNum & 0xff;
- objKey[keyLength + 1] = (objNum >> 8) & 0xff;
- objKey[keyLength + 2] = (objNum >> 16) & 0xff;
- objKey[keyLength + 3] = objGen & 0xff;
- objKey[keyLength + 4] = (objGen >> 8) & 0xff;
- md5(objKey, keyLength + 5, objKey);
-
- // set up for decryption
- x = y = 0;
- if ((objKeyLength = keyLength + 5) > 16) {
- objKeyLength = 16;
- }
- rc4InitKey(objKey, objKeyLength, state);
-}
-
-void Decrypt::reset() {
- x = y = 0;
- rc4InitKey(objKey, objKeyLength, state);
-}
-
-Guchar Decrypt::decryptByte(Guchar c) {
- return rc4DecryptByte(state, &x, &y, c);
-}
-
-GBool Decrypt::makeFileKey(int encVersion, int encRevision, int keyLength,
- GString *ownerKey, GString *userKey,
- int permissions, GString *fileID,
- GString *ownerPassword, GString *userPassword,
- Guchar *fileKey, GBool encryptMetadata,
- GBool *ownerPasswordOk) {
- Guchar test[32], test2[32];
- GString *userPassword2;
- Guchar fState[256];
- Guchar tmpKey[16];
- Guchar fx, fy;
- int len, i, j;
-
- // try using the supplied owner password to generate the user password
- *ownerPasswordOk = gFalse;
- if (ownerPassword) {
- len = ownerPassword->getLength();
- if (len < 32) {
- memcpy(test, ownerPassword->getCString(), len);
- memcpy(test + len, passwordPad, 32 - len);
- } else {
- memcpy(test, ownerPassword->getCString(), 32);
- }
- md5(test, 32, test);
- if (encRevision == 3) {
- for (i = 0; i < 50; ++i) {
- md5(test, 16, test);
- }
- }
- if (encRevision == 2) {
- rc4InitKey(test, keyLength, fState);
- fx = fy = 0;
- for (i = 0; i < 32; ++i) {
- test2[i] = rc4DecryptByte(fState, &fx, &fy, ownerKey->getChar(i));
- }
- } else {
- memcpy(test2, ownerKey->getCString(), 32);
- for (i = 19; i >= 0; --i) {
- for (j = 0; j < keyLength; ++j) {
- tmpKey[j] = test[j] ^ i;
- }
- rc4InitKey(tmpKey, keyLength, fState);
- fx = fy = 0;
- for (j = 0; j < 32; ++j) {
- test2[j] = rc4DecryptByte(fState, &fx, &fy, test2[j]);
- }
- }
- }
- userPassword2 = new GString((char *)test2, 32);
- if (makeFileKey2(encVersion, encRevision, keyLength, ownerKey, userKey,
- permissions, fileID, userPassword2, fileKey,
- encryptMetadata)) {
- *ownerPasswordOk = gTrue;
- delete userPassword2;
- return gTrue;
- }
- delete userPassword2;
- }
-
- // try using the supplied user password
- return makeFileKey2(encVersion, encRevision, keyLength, ownerKey, userKey,
- permissions, fileID, userPassword, fileKey,
- encryptMetadata);
-}
-
-GBool Decrypt::makeFileKey2(int encVersion, int encRevision, int keyLength,
- GString *ownerKey, GString *userKey,
- int permissions, GString *fileID,
- GString *userPassword, Guchar *fileKey,
- GBool encryptMetadata) {
- Guchar *buf;
- Guchar test[32];
- Guchar fState[256];
- Guchar tmpKey[16];
- Guchar fx, fy;
- int len, i, j;
- GBool ok;
-
- // generate file key
- buf = (Guchar *)gmalloc(72 + fileID->getLength());
- if (userPassword) {
- len = userPassword->getLength();
- if (len < 32) {
- memcpy(buf, userPassword->getCString(), len);
- memcpy(buf + len, passwordPad, 32 - len);
- } else {
- memcpy(buf, userPassword->getCString(), 32);
- }
- } else {
- memcpy(buf, passwordPad, 32);
- }
- memcpy(buf + 32, ownerKey->getCString(), 32);
- buf[64] = permissions & 0xff;
- buf[65] = (permissions >> 8) & 0xff;
- buf[66] = (permissions >> 16) & 0xff;
- buf[67] = (permissions >> 24) & 0xff;
- memcpy(buf + 68, fileID->getCString(), fileID->getLength());
- len = 68 + fileID->getLength();
- if (!encryptMetadata) {
- buf[len++] = 0xff;
- buf[len++] = 0xff;
- buf[len++] = 0xff;
- buf[len++] = 0xff;
- }
- md5(buf, len, fileKey);
- if (encRevision == 3) {
- for (i = 0; i < 50; ++i) {
- md5(fileKey, keyLength, fileKey);
- }
- }
-
- // test user password
- if (encRevision == 2) {
- rc4InitKey(fileKey, keyLength, fState);
- fx = fy = 0;
- for (i = 0; i < 32; ++i) {
- test[i] = rc4DecryptByte(fState, &fx, &fy, userKey->getChar(i));
- }
- ok = memcmp(test, passwordPad, 32) == 0;
- } else if (encRevision == 3) {
- memcpy(test, userKey->getCString(), 32);
- for (i = 19; i >= 0; --i) {
- for (j = 0; j < keyLength; ++j) {
- tmpKey[j] = fileKey[j] ^ i;
- }
- rc4InitKey(tmpKey, keyLength, fState);
- fx = fy = 0;
- for (j = 0; j < 32; ++j) {
- test[j] = rc4DecryptByte(fState, &fx, &fy, test[j]);
- }
- }
- memcpy(buf, passwordPad, 32);
- memcpy(buf + 32, fileID->getCString(), fileID->getLength());
- md5(buf, 32 + fileID->getLength(), buf);
- ok = memcmp(test, buf, 16) == 0;
- } else {
- ok = gFalse;
- }
-
- gfree(buf);
- return ok;
-}
-
-//------------------------------------------------------------------------
-// RC4-compatible decryption
-//------------------------------------------------------------------------
-
-static void rc4InitKey(Guchar *key, int keyLen, Guchar *state) {
- Guchar index1, index2;
- Guchar t;
- int i;
-
- for (i = 0; i < 256; ++i)
- state[i] = i;
- index1 = index2 = 0;
- for (i = 0; i < 256; ++i) {
- index2 = (key[index1] + state[i] + index2) % 256;
- t = state[i];
- state[i] = state[index2];
- state[index2] = t;
- index1 = (index1 + 1) % keyLen;
- }
-}
-
-static Guchar rc4DecryptByte(Guchar *state, Guchar *x, Guchar *y, Guchar c) {
- Guchar x1, y1, tx, ty;
-
- x1 = *x = (*x + 1) % 256;
- y1 = *y = (state[*x] + *y) % 256;
- tx = state[x1];
- ty = state[y1];
- state[x1] = ty;
- state[y1] = tx;
- return c ^ state[(tx + ty) % 256];
-}
-
-//------------------------------------------------------------------------
-// MD5 message digest
-//------------------------------------------------------------------------
-
-// this works around a bug in older Sun compilers
-static inline Gulong rotateLeft(Gulong x, int r) {
- x &= 0xffffffff;
- return ((x << r) | (x >> (32 - r))) & 0xffffffff;
-}
-
-static inline Gulong md5Round1(Gulong a, Gulong b, Gulong c, Gulong d,
- Gulong Xk, Gulong s, Gulong Ti) {
- return b + rotateLeft((a + ((b & c) | (~b & d)) + Xk + Ti), s);
-}
-
-static inline Gulong md5Round2(Gulong a, Gulong b, Gulong c, Gulong d,
- Gulong Xk, Gulong s, Gulong Ti) {
- return b + rotateLeft((a + ((b & d) | (c & ~d)) + Xk + Ti), s);
-}
-
-static inline Gulong md5Round3(Gulong a, Gulong b, Gulong c, Gulong d,
- Gulong Xk, Gulong s, Gulong Ti) {
- return b + rotateLeft((a + (b ^ c ^ d) + Xk + Ti), s);
-}
-
-static inline Gulong md5Round4(Gulong a, Gulong b, Gulong c, Gulong d,
- Gulong Xk, Gulong s, Gulong Ti) {
- return b + rotateLeft((a + (c ^ (b | ~d)) + Xk + Ti), s);
-}
-
-static void md5(Guchar *msg, int msgLen, Guchar *digest) {
- Gulong x[16];
- Gulong a, b, c, d, aa, bb, cc, dd;
- int n64;
- int i, j, k;
-
- // compute number of 64-byte blocks
- // (length + pad byte (0x80) + 8 bytes for length)
- n64 = (msgLen + 1 + 8 + 63) / 64;
-
- // initialize a, b, c, d
- a = 0x67452301;
- b = 0xefcdab89;
- c = 0x98badcfe;
- d = 0x10325476;
-
- // loop through blocks
- k = 0;
- for (i = 0; i < n64; ++i) {
-
- // grab a 64-byte block
- for (j = 0; j < 16 && k < msgLen - 3; ++j, k += 4)
- x[j] = (((((msg[k+3] << 8) + msg[k+2]) << 8) + msg[k+1]) << 8) + msg[k];
- if (i == n64 - 1) {
- if (k == msgLen - 3)
- x[j] = 0x80000000 + (((msg[k+2] << 8) + msg[k+1]) << 8) + msg[k];
- else if (k == msgLen - 2)
- x[j] = 0x800000 + (msg[k+1] << 8) + msg[k];
- else if (k == msgLen - 1)
- x[j] = 0x8000 + msg[k];
- else
- x[j] = 0x80;
- ++j;
- while (j < 16)
- x[j++] = 0;
- x[14] = msgLen << 3;
- }
-
- // save a, b, c, d
- aa = a;
- bb = b;
- cc = c;
- dd = d;
-
- // round 1
- a = md5Round1(a, b, c, d, x[0], 7, 0xd76aa478);
- d = md5Round1(d, a, b, c, x[1], 12, 0xe8c7b756);
- c = md5Round1(c, d, a, b, x[2], 17, 0x242070db);
- b = md5Round1(b, c, d, a, x[3], 22, 0xc1bdceee);
- a = md5Round1(a, b, c, d, x[4], 7, 0xf57c0faf);
- d = md5Round1(d, a, b, c, x[5], 12, 0x4787c62a);
- c = md5Round1(c, d, a, b, x[6], 17, 0xa8304613);
- b = md5Round1(b, c, d, a, x[7], 22, 0xfd469501);
- a = md5Round1(a, b, c, d, x[8], 7, 0x698098d8);
- d = md5Round1(d, a, b, c, x[9], 12, 0x8b44f7af);
- c = md5Round1(c, d, a, b, x[10], 17, 0xffff5bb1);
- b = md5Round1(b, c, d, a, x[11], 22, 0x895cd7be);
- a = md5Round1(a, b, c, d, x[12], 7, 0x6b901122);
- d = md5Round1(d, a, b, c, x[13], 12, 0xfd987193);
- c = md5Round1(c, d, a, b, x[14], 17, 0xa679438e);
- b = md5Round1(b, c, d, a, x[15], 22, 0x49b40821);
-
- // round 2
- a = md5Round2(a, b, c, d, x[1], 5, 0xf61e2562);
- d = md5Round2(d, a, b, c, x[6], 9, 0xc040b340);
- c = md5Round2(c, d, a, b, x[11], 14, 0x265e5a51);
- b = md5Round2(b, c, d, a, x[0], 20, 0xe9b6c7aa);
- a = md5Round2(a, b, c, d, x[5], 5, 0xd62f105d);
- d = md5Round2(d, a, b, c, x[10], 9, 0x02441453);
- c = md5Round2(c, d, a, b, x[15], 14, 0xd8a1e681);
- b = md5Round2(b, c, d, a, x[4], 20, 0xe7d3fbc8);
- a = md5Round2(a, b, c, d, x[9], 5, 0x21e1cde6);
- d = md5Round2(d, a, b, c, x[14], 9, 0xc33707d6);
- c = md5Round2(c, d, a, b, x[3], 14, 0xf4d50d87);
- b = md5Round2(b, c, d, a, x[8], 20, 0x455a14ed);
- a = md5Round2(a, b, c, d, x[13], 5, 0xa9e3e905);
- d = md5Round2(d, a, b, c, x[2], 9, 0xfcefa3f8);
- c = md5Round2(c, d, a, b, x[7], 14, 0x676f02d9);
- b = md5Round2(b, c, d, a, x[12], 20, 0x8d2a4c8a);
-
- // round 3
- a = md5Round3(a, b, c, d, x[5], 4, 0xfffa3942);
- d = md5Round3(d, a, b, c, x[8], 11, 0x8771f681);
- c = md5Round3(c, d, a, b, x[11], 16, 0x6d9d6122);
- b = md5Round3(b, c, d, a, x[14], 23, 0xfde5380c);
- a = md5Round3(a, b, c, d, x[1], 4, 0xa4beea44);
- d = md5Round3(d, a, b, c, x[4], 11, 0x4bdecfa9);
- c = md5Round3(c, d, a, b, x[7], 16, 0xf6bb4b60);
- b = md5Round3(b, c, d, a, x[10], 23, 0xbebfbc70);
- a = md5Round3(a, b, c, d, x[13], 4, 0x289b7ec6);
- d = md5Round3(d, a, b, c, x[0], 11, 0xeaa127fa);
- c = md5Round3(c, d, a, b, x[3], 16, 0xd4ef3085);
- b = md5Round3(b, c, d, a, x[6], 23, 0x04881d05);
- a = md5Round3(a, b, c, d, x[9], 4, 0xd9d4d039);
- d = md5Round3(d, a, b, c, x[12], 11, 0xe6db99e5);
- c = md5Round3(c, d, a, b, x[15], 16, 0x1fa27cf8);
- b = md5Round3(b, c, d, a, x[2], 23, 0xc4ac5665);
-
- // round 4
- a = md5Round4(a, b, c, d, x[0], 6, 0xf4292244);
- d = md5Round4(d, a, b, c, x[7], 10, 0x432aff97);
- c = md5Round4(c, d, a, b, x[14], 15, 0xab9423a7);
- b = md5Round4(b, c, d, a, x[5], 21, 0xfc93a039);
- a = md5Round4(a, b, c, d, x[12], 6, 0x655b59c3);
- d = md5Round4(d, a, b, c, x[3], 10, 0x8f0ccc92);
- c = md5Round4(c, d, a, b, x[10], 15, 0xffeff47d);
- b = md5Round4(b, c, d, a, x[1], 21, 0x85845dd1);
- a = md5Round4(a, b, c, d, x[8], 6, 0x6fa87e4f);
- d = md5Round4(d, a, b, c, x[15], 10, 0xfe2ce6e0);
- c = md5Round4(c, d, a, b, x[6], 15, 0xa3014314);
- b = md5Round4(b, c, d, a, x[13], 21, 0x4e0811a1);
- a = md5Round4(a, b, c, d, x[4], 6, 0xf7537e82);
- d = md5Round4(d, a, b, c, x[11], 10, 0xbd3af235);
- c = md5Round4(c, d, a, b, x[2], 15, 0x2ad7d2bb);
- b = md5Round4(b, c, d, a, x[9], 21, 0xeb86d391);
-
- // increment a, b, c, d
- a += aa;
- b += bb;
- c += cc;
- d += dd;
- }
-
- // break digest into bytes
- digest[0] = (Guchar)(a & 0xff);
- digest[1] = (Guchar)((a >>= 8) & 0xff);
- digest[2] = (Guchar)((a >>= 8) & 0xff);
- digest[3] = (Guchar)((a >>= 8) & 0xff);
- digest[4] = (Guchar)(b & 0xff);
- digest[5] = (Guchar)((b >>= 8) & 0xff);
- digest[6] = (Guchar)((b >>= 8) & 0xff);
- digest[7] = (Guchar)((b >>= 8) & 0xff);
- digest[8] = (Guchar)(c & 0xff);
- digest[9] = (Guchar)((c >>= 8) & 0xff);
- digest[10] = (Guchar)((c >>= 8) & 0xff);
- digest[11] = (Guchar)((c >>= 8) & 0xff);
- digest[12] = (Guchar)(d & 0xff);
- digest[13] = (Guchar)((d >>= 8) & 0xff);
- digest[14] = (Guchar)((d >>= 8) & 0xff);
- digest[15] = (Guchar)((d >>= 8) & 0xff);
-}
+++ /dev/null
-//========================================================================
-//
-// Decrypt.h
-//
-// Copyright 1996-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#ifndef DECRYPT_H
-#define DECRYPT_H
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma interface
-#endif
-
-#include "gtypes.h"
-#include "GString.h"
-
-//------------------------------------------------------------------------
-// Decrypt
-//------------------------------------------------------------------------
-
-class Decrypt {
-public:
-
- // Initialize the decryptor object.
- Decrypt(Guchar *fileKey, int keyLength, int objNum, int objGen);
-
- // Reset decryption.
- void reset();
-
- // Decrypt one byte.
- Guchar decryptByte(Guchar c);
-
- // Generate a file key. The <fileKey> buffer must have space for at
- // least 16 bytes. Checks <ownerPassword> and then <userPassword>
- // and returns true if either is correct. Sets <ownerPasswordOk> if
- // the owner password was correct. Either or both of the passwords
- // may be NULL, which is treated as an empty string.
- static GBool makeFileKey(int encVersion, int encRevision, int keyLength,
- GString *ownerKey, GString *userKey,
- int permissions, GString *fileID,
- GString *ownerPassword, GString *userPassword,
- Guchar *fileKey, GBool encryptMetadata,
- GBool *ownerPasswordOk);
-
-private:
-
- static GBool makeFileKey2(int encVersion, int encRevision, int keyLength,
- GString *ownerKey, GString *userKey,
- int permissions, GString *fileID,
- GString *userPassword, Guchar *fileKey,
- GBool encryptMetadata);
-
- int objKeyLength;
- Guchar objKey[21];
- Guchar state[256];
- Guchar x, y;
-};
-
-#endif
+++ /dev/null
-//========================================================================
-//
-// Dict.cc
-//
-// Copyright 1996-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma implementation
-#endif
-
-#include <stddef.h>
-#include <string.h>
-#include "gmem.h"
-#include "Object.h"
-#include "XRef.h"
-#include "Dict.h"
-
-//------------------------------------------------------------------------
-// Dict
-//------------------------------------------------------------------------
-
-Dict::Dict(XRef *xrefA) {
- xref = xrefA;
- entries = NULL;
- size = length = 0;
- ref = 1;
-}
-
-Dict::~Dict() {
- int i;
-
- for (i = 0; i < length; ++i) {
- gfree(entries[i].key);
- entries[i].val.free();
- }
- gfree(entries);
-}
-
-void Dict::add(char *key, Object *val) {
- if (length == size) {
- if (length == 0) {
- size = 8;
- } else {
- size *= 2;
- }
- entries = (DictEntry *)greallocn(entries, size, sizeof(DictEntry));
- }
- entries[length].key = key;
- entries[length].val = *val;
- ++length;
-}
-
-inline DictEntry *Dict::find(char *key) {
- int i;
-
- for (i = 0; i < length; ++i) {
- if (!strcmp(key, entries[i].key))
- return &entries[i];
- }
- return NULL;
-}
-
-GBool Dict::is(char *type) {
- DictEntry *e;
-
- return (e = find("Type")) && e->val.isName(type);
-}
-
-Object *Dict::lookup(char *key, Object *obj) {
- DictEntry *e;
-
- return (e = find(key)) ? e->val.fetch(xref, obj) : obj->initNull();
-}
-
-Object *Dict::lookupNF(char *key, Object *obj) {
- DictEntry *e;
-
- return (e = find(key)) ? e->val.copy(obj) : obj->initNull();
-}
-
-char *Dict::getKey(int i) {
- return entries[i].key;
-}
-
-Object *Dict::getVal(int i, Object *obj) {
- return entries[i].val.fetch(xref, obj);
-}
-
-Object *Dict::getValNF(int i, Object *obj) {
- return entries[i].val.copy(obj);
-}
+++ /dev/null
-//========================================================================
-//
-// Dict.h
-//
-// Copyright 1996-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#ifndef DICT_H
-#define DICT_H
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma interface
-#endif
-
-#include "Object.h"
-
-//------------------------------------------------------------------------
-// Dict
-//------------------------------------------------------------------------
-
-struct DictEntry {
- char *key;
- Object val;
-};
-
-class Dict {
-public:
-
- // Constructor.
- Dict(XRef *xrefA);
-
- // Destructor.
- ~Dict();
-
- // Reference counting.
- int incRef() { return ++ref; }
- int decRef() { return --ref; }
-
- // Get number of entries.
- int getLength() { return length; }
-
- // Add an entry. NB: does not copy key.
- void add(char *key, Object *val);
-
- // Check if dictionary is of specified type.
- GBool is(char *type);
-
- // Look up an entry and return the value. Returns a null object
- // if <key> is not in the dictionary.
- Object *lookup(char *key, Object *obj);
- Object *lookupNF(char *key, Object *obj);
-
- // Iterative accessors.
- char *getKey(int i);
- Object *getVal(int i, Object *obj);
- Object *getValNF(int i, Object *obj);
-
- // Set the xref pointer. This is only used in one special case: the
- // trailer dictionary, which is read before the xref table is
- // parsed.
- void setXRef(XRef *xrefA) { xref = xrefA; }
-
-private:
-
- XRef *xref; // the xref table for this PDF file
- DictEntry *entries; // array of entries
- int size; // size of <entries> array
- int length; // number of entries in dictionary
- int ref; // reference count
-
- DictEntry *find(char *key);
-};
-
-#endif
+++ /dev/null
-//========================================================================
-//
-// Error.cc
-//
-// Copyright 1996-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma implementation
-#endif
-
-#include <stdio.h>
-#include <stddef.h>
-#include <stdarg.h>
-#include "GlobalParams.h"
-#include "Error.h"
-
-void CDECL error(int pos, char *msg, ...) {
- va_list args;
-
- // NB: this can be called before the globalParams object is created
- if (globalParams && globalParams->getErrQuiet()) {
- return;
- }
- if (pos >= 0) {
- fprintf(stderr, "Error (%d): ", pos);
- } else {
- fprintf(stderr, "Error: ");
- }
- va_start(args, msg);
- vfprintf(stderr, msg, args);
- va_end(args);
- fprintf(stderr, "\n");
- fflush(stderr);
-}
+++ /dev/null
-//========================================================================
-//
-// Error.h
-//
-// Copyright 1996-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#ifndef ERROR_H
-#define ERROR_H
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma interface
-#endif
-
-#include <stdio.h>
-#include "config.h"
-
-extern void CDECL error(int pos, char *msg, ...);
-
-#endif
+++ /dev/null
-//========================================================================
-//
-// ErrorCodes.h
-//
-// Copyright 2002-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#ifndef ERRORCODES_H
-#define ERRORCODES_H
-
-#define errNone 0 // no error
-
-#define errOpenFile 1 // couldn't open the PDF file
-
-#define errBadCatalog 2 // couldn't read the page catalog
-
-#define errDamaged 3 // PDF file was damaged and couldn't be
- // repaired
-
-#define errEncrypted 4 // file was encrypted and password was
- // incorrect or not supplied
-
-#define errHighlightFile 5 // nonexistent or invalid highlight file
-
-#define errBadPrinter 6 // invalid printer
-
-#define errPrinting 7 // error during printing
-
-#define errPermission 8 // PDF file doesn't allow that operation
-
-#define errBadPageNum 9 // invalid page number
-
-#define errFileIO 10 // file I/O error
-
-#endif
+++ /dev/null
-//========================================================================
-//
-// FoFiBase.cc
-//
-// Copyright 1999-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma implementation
-#endif
-
-#include <stdio.h>
-#include "gmem.h"
-#include "FoFiBase.h"
-
-//------------------------------------------------------------------------
-// FoFiBase
-//------------------------------------------------------------------------
-
-FoFiBase::FoFiBase(char *fileA, int lenA, GBool freeFileDataA) {
- fileData = file = (Guchar *)fileA;
- len = lenA;
- freeFileData = freeFileDataA;
-}
-
-FoFiBase::~FoFiBase() {
- if (freeFileData) {
- gfree(fileData);
- }
-}
-
-char *FoFiBase::readFile(char *fileName, int *fileLen) {
- FILE *f;
- char *buf;
- int n;
-
- if (!(f = fopen(fileName, "rb"))) {
- return NULL;
- }
- fseek(f, 0, SEEK_END);
- n = (int)ftell(f);
- fseek(f, 0, SEEK_SET);
- buf = (char *)gmalloc(n);
- if ((int)fread(buf, 1, n, f) != n) {
- gfree(buf);
- fclose(f);
- return NULL;
- }
- fclose(f);
- *fileLen = n;
- return buf;
-}
-
-int FoFiBase::getS8(int pos, GBool *ok) {
- int x;
-
- if (pos < 0 || pos >= len) {
- *ok = gFalse;
- return 0;
- }
- x = file[pos];
- if (x & 0x80) {
- x |= ~0xff;
- }
- return x;
-}
-
-int FoFiBase::getU8(int pos, GBool *ok) {
- if (pos < 0 || pos >= len) {
- *ok = gFalse;
- return 0;
- }
- return file[pos];
-}
-
-int FoFiBase::getS16BE(int pos, GBool *ok) {
- int x;
-
- if (pos < 0 || pos+1 >= len) {
- *ok = gFalse;
- return 0;
- }
- x = file[pos];
- x = (x << 8) + file[pos+1];
- if (x & 0x8000) {
- x |= ~0xffff;
- }
- return x;
-}
-
-int FoFiBase::getU16BE(int pos, GBool *ok) {
- int x;
-
- if (pos < 0 || pos+1 >= len) {
- *ok = gFalse;
- return 0;
- }
- x = file[pos];
- x = (x << 8) + file[pos+1];
- return x;
-}
-
-int FoFiBase::getS32BE(int pos, GBool *ok) {
- int x;
-
- if (pos < 0 || pos+3 >= len) {
- *ok = gFalse;
- return 0;
- }
- x = file[pos];
- x = (x << 8) + file[pos+1];
- x = (x << 8) + file[pos+2];
- x = (x << 8) + file[pos+3];
- if (x & 0x80000000) {
- x |= ~0xffffffff;
- }
- return x;
-}
-
-Guint FoFiBase::getU32BE(int pos, GBool *ok) {
- Guint x;
-
- if (pos < 0 || pos+3 >= len) {
- *ok = gFalse;
- return 0;
- }
- x = file[pos];
- x = (x << 8) + file[pos+1];
- x = (x << 8) + file[pos+2];
- x = (x << 8) + file[pos+3];
- return x;
-}
-
-Guint FoFiBase::getUVarBE(int pos, int size, GBool *ok) {
- Guint x;
- int i;
-
- if (pos < 0 || pos + size > len) {
- *ok = gFalse;
- return 0;
- }
- x = 0;
- for (i = 0; i < size; ++i) {
- x = (x << 8) + file[pos + i];
- }
- return x;
-}
-
-GBool FoFiBase::checkRegion(int pos, int size) {
- return pos >= 0 &&
- pos + size >= pos &&
- pos + size <= len;
-}
+++ /dev/null
-//========================================================================
-//
-// FoFiBase.h
-//
-// Copyright 1999-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#ifndef FOFIBASE_H
-#define FOFIBASE_H
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma interface
-#endif
-
-#include "gtypes.h"
-
-//------------------------------------------------------------------------
-
-typedef void (*FoFiOutputFunc)(void *stream, char *data, int len);
-
-//------------------------------------------------------------------------
-// FoFiBase
-//------------------------------------------------------------------------
-
-class FoFiBase {
-public:
-
- virtual ~FoFiBase();
-
-protected:
-
- FoFiBase(char *fileA, int lenA, GBool freeFileDataA);
- static char *readFile(char *fileName, int *fileLen);
-
- // S = signed / U = unsigned
- // 8/16/32/Var = word length, in bytes
- // BE = big endian
- int getS8(int pos, GBool *ok);
- int getU8(int pos, GBool *ok);
- int getS16BE(int pos, GBool *ok);
- int getU16BE(int pos, GBool *ok);
- int getS32BE(int pos, GBool *ok);
- Guint getU32BE(int pos, GBool *ok);
- Guint getUVarBE(int pos, int size, GBool *ok);
-
- GBool checkRegion(int pos, int size);
-
- Guchar *fileData;
- Guchar *file;
- int len;
- GBool freeFileData;
-};
-
-#endif
+++ /dev/null
-//========================================================================
-//
-// FoFiEncodings.cc
-//
-// Copyright 1999-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma implementation
-#endif
-
-#include <stdlib.h>
-#include "FoFiEncodings.h"
-
-//------------------------------------------------------------------------
-// Type 1 and 1C font data
-//------------------------------------------------------------------------
-
-char *fofiType1StandardEncoding[256] = {
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- "space",
- "exclam",
- "quotedbl",
- "numbersign",
- "dollar",
- "percent",
- "ampersand",
- "quoteright",
- "parenleft",
- "parenright",
- "asterisk",
- "plus",
- "comma",
- "hyphen",
- "period",
- "slash",
- "zero",
- "one",
- "two",
- "three",
- "four",
- "five",
- "six",
- "seven",
- "eight",
- "nine",
- "colon",
- "semicolon",
- "less",
- "equal",
- "greater",
- "question",
- "at",
- "A",
- "B",
- "C",
- "D",
- "E",
- "F",
- "G",
- "H",
- "I",
- "J",
- "K",
- "L",
- "M",
- "N",
- "O",
- "P",
- "Q",
- "R",
- "S",
- "T",
- "U",
- "V",
- "W",
- "X",
- "Y",
- "Z",
- "bracketleft",
- "backslash",
- "bracketright",
- "asciicircum",
- "underscore",
- "quoteleft",
- "a",
- "b",
- "c",
- "d",
- "e",
- "f",
- "g",
- "h",
- "i",
- "j",
- "k",
- "l",
- "m",
- "n",
- "o",
- "p",
- "q",
- "r",
- "s",
- "t",
- "u",
- "v",
- "w",
- "x",
- "y",
- "z",
- "braceleft",
- "bar",
- "braceright",
- "asciitilde",
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- "exclamdown",
- "cent",
- "sterling",
- "fraction",
- "yen",
- "florin",
- "section",
- "currency",
- "quotesingle",
- "quotedblleft",
- "guillemotleft",
- "guilsinglleft",
- "guilsinglright",
- "fi",
- "fl",
- NULL,
- "endash",
- "dagger",
- "daggerdbl",
- "periodcentered",
- NULL,
- "paragraph",
- "bullet",
- "quotesinglbase",
- "quotedblbase",
- "quotedblright",
- "guillemotright",
- "ellipsis",
- "perthousand",
- NULL,
- "questiondown",
- NULL,
- "grave",
- "acute",
- "circumflex",
- "tilde",
- "macron",
- "breve",
- "dotaccent",
- "dieresis",
- NULL,
- "ring",
- "cedilla",
- NULL,
- "hungarumlaut",
- "ogonek",
- "caron",
- "emdash",
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- "AE",
- NULL,
- "ordfeminine",
- NULL,
- NULL,
- NULL,
- NULL,
- "Lslash",
- "Oslash",
- "OE",
- "ordmasculine",
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- "ae",
- NULL,
- NULL,
- NULL,
- "dotlessi",
- NULL,
- NULL,
- "lslash",
- "oslash",
- "oe",
- "germandbls",
- NULL,
- NULL,
- NULL,
- NULL
-};
-
-char *fofiType1ExpertEncoding[256] = {
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- "space",
- "exclamsmall",
- "Hungarumlautsmall",
- NULL,
- "dollaroldstyle",
- "dollarsuperior",
- "ampersandsmall",
- "Acutesmall",
- "parenleftsuperior",
- "parenrightsuperior",
- "twodotenleader",
- "onedotenleader",
- "comma",
- "hyphen",
- "period",
- "fraction",
- "zerooldstyle",
- "oneoldstyle",
- "twooldstyle",
- "threeoldstyle",
- "fouroldstyle",
- "fiveoldstyle",
- "sixoldstyle",
- "sevenoldstyle",
- "eightoldstyle",
- "nineoldstyle",
- "colon",
- "semicolon",
- "commasuperior",
- "threequartersemdash",
- "periodsuperior",
- "questionsmall",
- NULL,
- "asuperior",
- "bsuperior",
- "centsuperior",
- "dsuperior",
- "esuperior",
- NULL,
- NULL,
- NULL,
- "isuperior",
- NULL,
- NULL,
- "lsuperior",
- "msuperior",
- "nsuperior",
- "osuperior",
- NULL,
- NULL,
- "rsuperior",
- "ssuperior",
- "tsuperior",
- NULL,
- "ff",
- "fi",
- "fl",
- "ffi",
- "ffl",
- "parenleftinferior",
- NULL,
- "parenrightinferior",
- "Circumflexsmall",
- "hyphensuperior",
- "Gravesmall",
- "Asmall",
- "Bsmall",
- "Csmall",
- "Dsmall",
- "Esmall",
- "Fsmall",
- "Gsmall",
- "Hsmall",
- "Ismall",
- "Jsmall",
- "Ksmall",
- "Lsmall",
- "Msmall",
- "Nsmall",
- "Osmall",
- "Psmall",
- "Qsmall",
- "Rsmall",
- "Ssmall",
- "Tsmall",
- "Usmall",
- "Vsmall",
- "Wsmall",
- "Xsmall",
- "Ysmall",
- "Zsmall",
- "colonmonetary",
- "onefitted",
- "rupiah",
- "Tildesmall",
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- "exclamdownsmall",
- "centoldstyle",
- "Lslashsmall",
- NULL,
- NULL,
- "Scaronsmall",
- "Zcaronsmall",
- "Dieresissmall",
- "Brevesmall",
- "Caronsmall",
- NULL,
- "Dotaccentsmall",
- NULL,
- NULL,
- "Macronsmall",
- NULL,
- NULL,
- "figuredash",
- "hypheninferior",
- NULL,
- NULL,
- "Ogoneksmall",
- "Ringsmall",
- "Cedillasmall",
- NULL,
- NULL,
- NULL,
- "onequarter",
- "onehalf",
- "threequarters",
- "questiondownsmall",
- "oneeighth",
- "threeeighths",
- "fiveeighths",
- "seveneighths",
- "onethird",
- "twothirds",
- NULL,
- NULL,
- "zerosuperior",
- "onesuperior",
- "twosuperior",
- "threesuperior",
- "foursuperior",
- "fivesuperior",
- "sixsuperior",
- "sevensuperior",
- "eightsuperior",
- "ninesuperior",
- "zeroinferior",
- "oneinferior",
- "twoinferior",
- "threeinferior",
- "fourinferior",
- "fiveinferior",
- "sixinferior",
- "seveninferior",
- "eightinferior",
- "nineinferior",
- "centinferior",
- "dollarinferior",
- "periodinferior",
- "commainferior",
- "Agravesmall",
- "Aacutesmall",
- "Acircumflexsmall",
- "Atildesmall",
- "Adieresissmall",
- "Aringsmall",
- "AEsmall",
- "Ccedillasmall",
- "Egravesmall",
- "Eacutesmall",
- "Ecircumflexsmall",
- "Edieresissmall",
- "Igravesmall",
- "Iacutesmall",
- "Icircumflexsmall",
- "Idieresissmall",
- "Ethsmall",
- "Ntildesmall",
- "Ogravesmall",
- "Oacutesmall",
- "Ocircumflexsmall",
- "Otildesmall",
- "Odieresissmall",
- "OEsmall",
- "Oslashsmall",
- "Ugravesmall",
- "Uacutesmall",
- "Ucircumflexsmall",
- "Udieresissmall",
- "Yacutesmall",
- "Thornsmall",
- "Ydieresissmall"
-};
-
-//------------------------------------------------------------------------
-// Type 1C font data
-//------------------------------------------------------------------------
-
-char *fofiType1CStdStrings[391] = {
- ".notdef",
- "space",
- "exclam",
- "quotedbl",
- "numbersign",
- "dollar",
- "percent",
- "ampersand",
- "quoteright",
- "parenleft",
- "parenright",
- "asterisk",
- "plus",
- "comma",
- "hyphen",
- "period",
- "slash",
- "zero",
- "one",
- "two",
- "three",
- "four",
- "five",
- "six",
- "seven",
- "eight",
- "nine",
- "colon",
- "semicolon",
- "less",
- "equal",
- "greater",
- "question",
- "at",
- "A",
- "B",
- "C",
- "D",
- "E",
- "F",
- "G",
- "H",
- "I",
- "J",
- "K",
- "L",
- "M",
- "N",
- "O",
- "P",
- "Q",
- "R",
- "S",
- "T",
- "U",
- "V",
- "W",
- "X",
- "Y",
- "Z",
- "bracketleft",
- "backslash",
- "bracketright",
- "asciicircum",
- "underscore",
- "quoteleft",
- "a",
- "b",
- "c",
- "d",
- "e",
- "f",
- "g",
- "h",
- "i",
- "j",
- "k",
- "l",
- "m",
- "n",
- "o",
- "p",
- "q",
- "r",
- "s",
- "t",
- "u",
- "v",
- "w",
- "x",
- "y",
- "z",
- "braceleft",
- "bar",
- "braceright",
- "asciitilde",
- "exclamdown",
- "cent",
- "sterling",
- "fraction",
- "yen",
- "florin",
- "section",
- "currency",
- "quotesingle",
- "quotedblleft",
- "guillemotleft",
- "guilsinglleft",
- "guilsinglright",
- "fi",
- "fl",
- "endash",
- "dagger",
- "daggerdbl",
- "periodcentered",
- "paragraph",
- "bullet",
- "quotesinglbase",
- "quotedblbase",
- "quotedblright",
- "guillemotright",
- "ellipsis",
- "perthousand",
- "questiondown",
- "grave",
- "acute",
- "circumflex",
- "tilde",
- "macron",
- "breve",
- "dotaccent",
- "dieresis",
- "ring",
- "cedilla",
- "hungarumlaut",
- "ogonek",
- "caron",
- "emdash",
- "AE",
- "ordfeminine",
- "Lslash",
- "Oslash",
- "OE",
- "ordmasculine",
- "ae",
- "dotlessi",
- "lslash",
- "oslash",
- "oe",
- "germandbls",
- "onesuperior",
- "logicalnot",
- "mu",
- "trademark",
- "Eth",
- "onehalf",
- "plusminus",
- "Thorn",
- "onequarter",
- "divide",
- "brokenbar",
- "degree",
- "thorn",
- "threequarters",
- "twosuperior",
- "registered",
- "minus",
- "eth",
- "multiply",
- "threesuperior",
- "copyright",
- "Aacute",
- "Acircumflex",
- "Adieresis",
- "Agrave",
- "Aring",
- "Atilde",
- "Ccedilla",
- "Eacute",
- "Ecircumflex",
- "Edieresis",
- "Egrave",
- "Iacute",
- "Icircumflex",
- "Idieresis",
- "Igrave",
- "Ntilde",
- "Oacute",
- "Ocircumflex",
- "Odieresis",
- "Ograve",
- "Otilde",
- "Scaron",
- "Uacute",
- "Ucircumflex",
- "Udieresis",
- "Ugrave",
- "Yacute",
- "Ydieresis",
- "Zcaron",
- "aacute",
- "acircumflex",
- "adieresis",
- "agrave",
- "aring",
- "atilde",
- "ccedilla",
- "eacute",
- "ecircumflex",
- "edieresis",
- "egrave",
- "iacute",
- "icircumflex",
- "idieresis",
- "igrave",
- "ntilde",
- "oacute",
- "ocircumflex",
- "odieresis",
- "ograve",
- "otilde",
- "scaron",
- "uacute",
- "ucircumflex",
- "udieresis",
- "ugrave",
- "yacute",
- "ydieresis",
- "zcaron",
- "exclamsmall",
- "Hungarumlautsmall",
- "dollaroldstyle",
- "dollarsuperior",
- "ampersandsmall",
- "Acutesmall",
- "parenleftsuperior",
- "parenrightsuperior",
- "twodotenleader",
- "onedotenleader",
- "zerooldstyle",
- "oneoldstyle",
- "twooldstyle",
- "threeoldstyle",
- "fouroldstyle",
- "fiveoldstyle",
- "sixoldstyle",
- "sevenoldstyle",
- "eightoldstyle",
- "nineoldstyle",
- "commasuperior",
- "threequartersemdash",
- "periodsuperior",
- "questionsmall",
- "asuperior",
- "bsuperior",
- "centsuperior",
- "dsuperior",
- "esuperior",
- "isuperior",
- "lsuperior",
- "msuperior",
- "nsuperior",
- "osuperior",
- "rsuperior",
- "ssuperior",
- "tsuperior",
- "ff",
- "ffi",
- "ffl",
- "parenleftinferior",
- "parenrightinferior",
- "Circumflexsmall",
- "hyphensuperior",
- "Gravesmall",
- "Asmall",
- "Bsmall",
- "Csmall",
- "Dsmall",
- "Esmall",
- "Fsmall",
- "Gsmall",
- "Hsmall",
- "Ismall",
- "Jsmall",
- "Ksmall",
- "Lsmall",
- "Msmall",
- "Nsmall",
- "Osmall",
- "Psmall",
- "Qsmall",
- "Rsmall",
- "Ssmall",
- "Tsmall",
- "Usmall",
- "Vsmall",
- "Wsmall",
- "Xsmall",
- "Ysmall",
- "Zsmall",
- "colonmonetary",
- "onefitted",
- "rupiah",
- "Tildesmall",
- "exclamdownsmall",
- "centoldstyle",
- "Lslashsmall",
- "Scaronsmall",
- "Zcaronsmall",
- "Dieresissmall",
- "Brevesmall",
- "Caronsmall",
- "Dotaccentsmall",
- "Macronsmall",
- "figuredash",
- "hypheninferior",
- "Ogoneksmall",
- "Ringsmall",
- "Cedillasmall",
- "questiondownsmall",
- "oneeighth",
- "threeeighths",
- "fiveeighths",
- "seveneighths",
- "onethird",
- "twothirds",
- "zerosuperior",
- "foursuperior",
- "fivesuperior",
- "sixsuperior",
- "sevensuperior",
- "eightsuperior",
- "ninesuperior",
- "zeroinferior",
- "oneinferior",
- "twoinferior",
- "threeinferior",
- "fourinferior",
- "fiveinferior",
- "sixinferior",
- "seveninferior",
- "eightinferior",
- "nineinferior",
- "centinferior",
- "dollarinferior",
- "periodinferior",
- "commainferior",
- "Agravesmall",
- "Aacutesmall",
- "Acircumflexsmall",
- "Atildesmall",
- "Adieresissmall",
- "Aringsmall",
- "AEsmall",
- "Ccedillasmall",
- "Egravesmall",
- "Eacutesmall",
- "Ecircumflexsmall",
- "Edieresissmall",
- "Igravesmall",
- "Iacutesmall",
- "Icircumflexsmall",
- "Idieresissmall",
- "Ethsmall",
- "Ntildesmall",
- "Ogravesmall",
- "Oacutesmall",
- "Ocircumflexsmall",
- "Otildesmall",
- "Odieresissmall",
- "OEsmall",
- "Oslashsmall",
- "Ugravesmall",
- "Uacutesmall",
- "Ucircumflexsmall",
- "Udieresissmall",
- "Yacutesmall",
- "Thornsmall",
- "Ydieresissmall",
- "001.000",
- "001.001",
- "001.002",
- "001.003",
- "Black",
- "Bold",
- "Book",
- "Light",
- "Medium",
- "Regular",
- "Roman",
- "Semibold"
-};
-
-Gushort fofiType1CISOAdobeCharset[229] = {
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
- 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
- 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
- 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
- 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
- 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
- 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
- 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
- 80, 81, 82, 83, 84, 85, 86, 87, 88, 89,
- 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,
- 100, 101, 102, 103, 104, 105, 106, 107, 108, 109,
- 110, 111, 112, 113, 114, 115, 116, 117, 118, 119,
- 120, 121, 122, 123, 124, 125, 126, 127, 128, 129,
- 130, 131, 132, 133, 134, 135, 136, 137, 138, 139,
- 140, 141, 142, 143, 144, 145, 146, 147, 148, 149,
- 150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
- 160, 161, 162, 163, 164, 165, 166, 167, 168, 169,
- 170, 171, 172, 173, 174, 175, 176, 177, 178, 179,
- 180, 181, 182, 183, 184, 185, 186, 187, 188, 189,
- 190, 191, 192, 193, 194, 195, 196, 197, 198, 199,
- 200, 201, 202, 203, 204, 205, 206, 207, 208, 209,
- 210, 211, 212, 213, 214, 215, 216, 217, 218, 219,
- 220, 221, 222, 223, 224, 225, 226, 227, 228
-};
-
-Gushort fofiType1CExpertCharset[166] = {
- 0, 1, 229, 230, 231, 232, 233, 234, 235, 236,
- 237, 238, 13, 14, 15, 99, 239, 240, 241, 242,
- 243, 244, 245, 246, 247, 248, 27, 28, 249, 250,
- 251, 252, 253, 254, 255, 256, 257, 258, 259, 260,
- 261, 262, 263, 264, 265, 266, 109, 110, 267, 268,
- 269, 270, 271, 272, 273, 274, 275, 276, 277, 278,
- 279, 280, 281, 282, 283, 284, 285, 286, 287, 288,
- 289, 290, 291, 292, 293, 294, 295, 296, 297, 298,
- 299, 300, 301, 302, 303, 304, 305, 306, 307, 308,
- 309, 310, 311, 312, 313, 314, 315, 316, 317, 318,
- 158, 155, 163, 319, 320, 321, 322, 323, 324, 325,
- 326, 150, 164, 169, 327, 328, 329, 330, 331, 332,
- 333, 334, 335, 336, 337, 338, 339, 340, 341, 342,
- 343, 344, 345, 346, 347, 348, 349, 350, 351, 352,
- 353, 354, 355, 356, 357, 358, 359, 360, 361, 362,
- 363, 364, 365, 366, 367, 368, 369, 370, 371, 372,
- 373, 374, 375, 376, 377, 378
-};
-
-Gushort fofiType1CExpertSubsetCharset[87] = {
- 0, 1, 231, 232, 235, 236, 237, 238, 13, 14,
- 15, 99, 239, 240, 241, 242, 243, 244, 245, 246,
- 247, 248, 27, 28, 249, 250, 251, 253, 254, 255,
- 256, 257, 258, 259, 260, 261, 262, 263, 264, 265,
- 266, 109, 110, 267, 268, 269, 270, 272, 300, 301,
- 302, 305, 314, 315, 158, 155, 163, 320, 321, 322,
- 323, 324, 325, 326, 150, 164, 169, 327, 328, 329,
- 330, 331, 332, 333, 334, 335, 336, 337, 338, 339,
- 340, 341, 342, 343, 344, 345, 346
-};
+++ /dev/null
-//========================================================================
-//
-// FoFiEncodings.h
-//
-// Copyright 1999-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#ifndef FOFIENCODINGS_H
-#define FOFIENCODINGS_H
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma interface
-#endif
-
-#include "gtypes.h"
-
-//------------------------------------------------------------------------
-// Type 1 and 1C font data
-//------------------------------------------------------------------------
-
-extern char *fofiType1StandardEncoding[256];
-extern char *fofiType1ExpertEncoding[256];
-
-//------------------------------------------------------------------------
-// Type 1C font data
-//------------------------------------------------------------------------
-
-extern char *fofiType1CStdStrings[391];
-extern Gushort fofiType1CISOAdobeCharset[229];
-extern Gushort fofiType1CExpertCharset[166];
-extern Gushort fofiType1CExpertSubsetCharset[87];
-
-#endif
+++ /dev/null
-//========================================================================
-//
-// FoFiTrueType.cc
-//
-// Copyright 1999-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma implementation
-#endif
-
-#include <stdlib.h>
-#include <string.h>
-#include "gtypes.h"
-#include "gmem.h"
-#include "GString.h"
-#include "GHash.h"
-#include "FoFiTrueType.h"
-
-//
-// Terminology
-// -----------
-//
-// character code = number used as an element of a text string
-//
-// character name = glyph name = name for a particular glyph within a
-// font
-//
-// glyph index = GID = position (within some internal table in the font)
-// where the instructions to draw a particular glyph are
-// stored
-//
-// Type 1 fonts
-// ------------
-//
-// Type 1 fonts contain:
-//
-// Encoding: array of glyph names, maps char codes to glyph names
-//
-// Encoding[charCode] = charName
-//
-// CharStrings: dictionary of instructions, keyed by character names,
-// maps character name to glyph data
-//
-// CharStrings[charName] = glyphData
-//
-// TrueType fonts
-// --------------
-//
-// TrueType fonts contain:
-//
-// 'cmap' table: mapping from character code to glyph index; there may
-// be multiple cmaps in a TrueType font
-//
-// cmap[charCode] = gid
-//
-// 'post' table: mapping from glyph index to glyph name
-//
-// post[gid] = glyphName
-//
-// Type 42 fonts
-// -------------
-//
-// Type 42 fonts contain:
-//
-// Encoding: array of glyph names, maps char codes to glyph names
-//
-// Encoding[charCode] = charName
-//
-// CharStrings: dictionary of glyph indexes, keyed by character names,
-// maps character name to glyph index
-//
-// CharStrings[charName] = gid
-//
-
-//------------------------------------------------------------------------
-
-#define ttcfTag 0x74746366
-
-//------------------------------------------------------------------------
-
-struct TrueTypeTable {
- Guint tag;
- Guint checksum;
- int offset;
- int origOffset;
- int len;
-};
-
-struct TrueTypeCmap {
- int platform;
- int encoding;
- int offset;
- int len;
- int fmt;
-};
-
-struct TrueTypeLoca {
- int idx;
- int origOffset;
- int newOffset;
- int len;
-};
-
-#define cmapTag 0x636d6170
-#define glyfTag 0x676c7966
-#define headTag 0x68656164
-#define locaTag 0x6c6f6361
-#define nameTag 0x6e616d65
-#define postTag 0x706f7374
-
-static int cmpTrueTypeLocaOffset(const void *p1, const void *p2) {
- TrueTypeLoca *loca1 = (TrueTypeLoca *)p1;
- TrueTypeLoca *loca2 = (TrueTypeLoca *)p2;
-
- if (loca1->origOffset == loca2->origOffset) {
- return loca1->idx - loca2->idx;
- }
- return loca1->origOffset - loca2->origOffset;
-}
-
-static int cmpTrueTypeLocaIdx(const void *p1, const void *p2) {
- TrueTypeLoca *loca1 = (TrueTypeLoca *)p1;
- TrueTypeLoca *loca2 = (TrueTypeLoca *)p2;
-
- return loca1->idx - loca2->idx;
-}
-
-static int cmpTrueTypeTableTag(const void *p1, const void *p2) {
- TrueTypeTable *tab1 = (TrueTypeTable *)p1;
- TrueTypeTable *tab2 = (TrueTypeTable *)p2;
-
- return (int)tab1->tag - (int)tab2->tag;
-}
-
-//------------------------------------------------------------------------
-
-struct T42Table {
- char *tag; // 4-byte tag
- GBool required; // required by the TrueType spec?
-};
-
-// TrueType tables to be embedded in Type 42 fonts.
-// NB: the table names must be in alphabetical order here.
-#define nT42Tables 11
-static T42Table t42Tables[nT42Tables] = {
- { "cvt ", gTrue },
- { "fpgm", gTrue },
- { "glyf", gTrue },
- { "head", gTrue },
- { "hhea", gTrue },
- { "hmtx", gTrue },
- { "loca", gTrue },
- { "maxp", gTrue },
- { "prep", gTrue },
- { "vhea", gFalse },
- { "vmtx", gFalse }
-};
-#define t42HeadTable 3
-#define t42LocaTable 6
-#define t42GlyfTable 2
-#define t42VheaTable 9
-#define t42VmtxTable 10
-
-//------------------------------------------------------------------------
-
-// Glyph names in some arbitrary standard order that Apple uses for
-// their TrueType fonts.
-static char *macGlyphNames[258] = {
- ".notdef", "null", "CR", "space",
- "exclam", "quotedbl", "numbersign", "dollar",
- "percent", "ampersand", "quotesingle", "parenleft",
- "parenright", "asterisk", "plus", "comma",
- "hyphen", "period", "slash", "zero",
- "one", "two", "three", "four",
- "five", "six", "seven", "eight",
- "nine", "colon", "semicolon", "less",
- "equal", "greater", "question", "at",
- "A", "B", "C", "D",
- "E", "F", "G", "H",
- "I", "J", "K", "L",
- "M", "N", "O", "P",
- "Q", "R", "S", "T",
- "U", "V", "W", "X",
- "Y", "Z", "bracketleft", "backslash",
- "bracketright", "asciicircum", "underscore", "grave",
- "a", "b", "c", "d",
- "e", "f", "g", "h",
- "i", "j", "k", "l",
- "m", "n", "o", "p",
- "q", "r", "s", "t",
- "u", "v", "w", "x",
- "y", "z", "braceleft", "bar",
- "braceright", "asciitilde", "Adieresis", "Aring",
- "Ccedilla", "Eacute", "Ntilde", "Odieresis",
- "Udieresis", "aacute", "agrave", "acircumflex",
- "adieresis", "atilde", "aring", "ccedilla",
- "eacute", "egrave", "ecircumflex", "edieresis",
- "iacute", "igrave", "icircumflex", "idieresis",
- "ntilde", "oacute", "ograve", "ocircumflex",
- "odieresis", "otilde", "uacute", "ugrave",
- "ucircumflex", "udieresis", "dagger", "degree",
- "cent", "sterling", "section", "bullet",
- "paragraph", "germandbls", "registered", "copyright",
- "trademark", "acute", "dieresis", "notequal",
- "AE", "Oslash", "infinity", "plusminus",
- "lessequal", "greaterequal", "yen", "mu1",
- "partialdiff", "summation", "product", "pi",
- "integral", "ordfeminine", "ordmasculine", "Ohm",
- "ae", "oslash", "questiondown", "exclamdown",
- "logicalnot", "radical", "florin", "approxequal",
- "increment", "guillemotleft", "guillemotright", "ellipsis",
- "nbspace", "Agrave", "Atilde", "Otilde",
- "OE", "oe", "endash", "emdash",
- "quotedblleft", "quotedblright", "quoteleft", "quoteright",
- "divide", "lozenge", "ydieresis", "Ydieresis",
- "fraction", "currency", "guilsinglleft", "guilsinglright",
- "fi", "fl", "daggerdbl", "periodcentered",
- "quotesinglbase", "quotedblbase", "perthousand", "Acircumflex",
- "Ecircumflex", "Aacute", "Edieresis", "Egrave",
- "Iacute", "Icircumflex", "Idieresis", "Igrave",
- "Oacute", "Ocircumflex", "applelogo", "Ograve",
- "Uacute", "Ucircumflex", "Ugrave", "dotlessi",
- "circumflex", "tilde", "overscore", "breve",
- "dotaccent", "ring", "cedilla", "hungarumlaut",
- "ogonek", "caron", "Lslash", "lslash",
- "Scaron", "scaron", "Zcaron", "zcaron",
- "brokenbar", "Eth", "eth", "Yacute",
- "yacute", "Thorn", "thorn", "minus",
- "multiply", "onesuperior", "twosuperior", "threesuperior",
- "onehalf", "onequarter", "threequarters", "franc",
- "Gbreve", "gbreve", "Idot", "Scedilla",
- "scedilla", "Cacute", "cacute", "Ccaron",
- "ccaron", "dmacron"
-};
-
-//------------------------------------------------------------------------
-// FoFiTrueType
-//------------------------------------------------------------------------
-
-FoFiTrueType *FoFiTrueType::make(char *fileA, int lenA) {
- FoFiTrueType *ff;
-
- ff = new FoFiTrueType(fileA, lenA, gFalse);
- if (!ff->parsedOk) {
- delete ff;
- return NULL;
- }
- return ff;
-}
-
-FoFiTrueType *FoFiTrueType::load(char *fileName) {
- FoFiTrueType *ff;
- char *fileA;
- int lenA;
-
- if (!(fileA = FoFiBase::readFile(fileName, &lenA))) {
- return NULL;
- }
- ff = new FoFiTrueType(fileA, lenA, gTrue);
- if (!ff->parsedOk) {
- delete ff;
- return NULL;
- }
- return ff;
-}
-
-FoFiTrueType::FoFiTrueType(char *fileA, int lenA, GBool freeFileDataA):
- FoFiBase(fileA, lenA, freeFileDataA)
-{
- tables = NULL;
- nTables = 0;
- cmaps = NULL;
- nCmaps = 0;
- nameToGID = NULL;
- parsedOk = gFalse;
-
- parse();
-}
-
-FoFiTrueType::~FoFiTrueType() {
- gfree(tables);
- gfree(cmaps);
- if (nameToGID) {
- delete nameToGID;
- }
-}
-
-int FoFiTrueType::getNumCmaps() {
- return nCmaps;
-}
-
-int FoFiTrueType::getCmapPlatform(int i) {
- return cmaps[i].platform;
-}
-
-int FoFiTrueType::getCmapEncoding(int i) {
- return cmaps[i].encoding;
-}
-
-int FoFiTrueType::findCmap(int platform, int encoding) {
- int i;
-
- for (i = 0; i < nCmaps; ++i) {
- if (cmaps[i].platform == platform && cmaps[i].encoding == encoding) {
- return i;
- }
- }
- return -1;
-}
-
-Gushort FoFiTrueType::mapCodeToGID(int i, int c) {
- Gushort gid;
- int segCnt, segEnd, segStart, segDelta, segOffset;
- int cmapFirst, cmapLen;
- int pos, a, b, m;
- GBool ok;
-
- if (i < 0 || i >= nCmaps) {
- return 0;
- }
- ok = gTrue;
- pos = cmaps[i].offset;
- switch (cmaps[i].fmt) {
- case 0:
- if (c < 0 || c >= cmaps[i].len - 6) {
- return 0;
- }
- gid = getU8(cmaps[i].offset + 6 + c, &ok);
- break;
- case 4:
- segCnt = getU16BE(pos + 6, &ok) / 2;
- a = -1;
- b = segCnt - 1;
- segEnd = getU16BE(pos + 14 + 2*b, &ok);
- if (c > segEnd) {
- // malformed font -- the TrueType spec requires the last segEnd
- // to be 0xffff
- return 0;
- }
- // invariant: seg[a].end < code <= seg[b].end
- while (b - a > 1 && ok) {
- m = (a + b) / 2;
- segEnd = getU16BE(pos + 14 + 2*m, &ok);
- if (segEnd < c) {
- a = m;
- } else {
- b = m;
- }
- }
- segStart = getU16BE(pos + 16 + 2*segCnt + 2*b, &ok);
- segDelta = getU16BE(pos + 16 + 4*segCnt + 2*b, &ok);
- segOffset = getU16BE(pos + 16 + 6*segCnt + 2*b, &ok);
- if (c < segStart) {
- return 0;
- }
- if (segOffset == 0) {
- gid = (c + segDelta) & 0xffff;
- } else {
- gid = getU16BE(pos + 16 + 6*segCnt + 2*b +
- segOffset + 2 * (c - segStart), &ok);
- if (gid != 0) {
- gid = (gid + segDelta) & 0xffff;
- }
- }
- break;
- case 6:
- cmapFirst = getU16BE(pos + 6, &ok);
- cmapLen = getU16BE(pos + 8, &ok);
- if (c < cmapFirst || c >= cmapFirst + cmapLen) {
- return 0;
- }
- gid = getU16BE(pos + 10 + 2 * (c - cmapFirst), &ok);
- break;
- default:
- return 0;
- }
- if (!ok) {
- return 0;
- }
- return gid;
-}
-
-int FoFiTrueType::mapNameToGID(char *name) {
- if (!nameToGID) {
- return 0;
- }
- return nameToGID->lookupInt(name);
-}
-
-int FoFiTrueType::getEmbeddingRights() {
- int i, fsType;
- GBool ok;
-
- if ((i = seekTable("OS/2")) < 0) {
- return 4;
- }
- ok = gTrue;
- fsType = getU16BE(tables[i].offset + 8, &ok);
- if (!ok) {
- return 4;
- }
- if (fsType & 0x0008) {
- return 2;
- }
- if (fsType & 0x0004) {
- return 1;
- }
- if (fsType & 0x0002) {
- return 0;
- }
- return 3;
-}
-
-void FoFiTrueType::convertToType42(char *psName, char **encoding,
- Gushort *codeToGID,
- FoFiOutputFunc outputFunc,
- void *outputStream) {
- char buf[512];
- GBool ok;
-
- // write the header
- ok = gTrue;
- sprintf(buf, "%%!PS-TrueTypeFont-%g\n", (double)getS32BE(0, &ok) / 65536.0);
- (*outputFunc)(outputStream, buf, strlen(buf));
-
- // begin the font dictionary
- (*outputFunc)(outputStream, "10 dict begin\n", 14);
- (*outputFunc)(outputStream, "/FontName /", 11);
- (*outputFunc)(outputStream, psName, strlen(psName));
- (*outputFunc)(outputStream, " def\n", 5);
- (*outputFunc)(outputStream, "/FontType 42 def\n", 17);
- (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
- sprintf(buf, "/FontBBox [%d %d %d %d] def\n",
- bbox[0], bbox[1], bbox[2], bbox[3]);
- (*outputFunc)(outputStream, buf, strlen(buf));
- (*outputFunc)(outputStream, "/PaintType 0 def\n", 17);
-
- // write the guts of the dictionary
- cvtEncoding(encoding, outputFunc, outputStream);
- cvtCharStrings(encoding, codeToGID, outputFunc, outputStream);
- cvtSfnts(outputFunc, outputStream, NULL, gFalse);
-
- // end the dictionary and define the font
- (*outputFunc)(outputStream, "FontName currentdict end definefont pop\n", 40);
-}
-
-void FoFiTrueType::convertToCIDType2(char *psName,
- Gushort *cidMap, int nCIDs,
- GBool needVerticalMetrics,
- FoFiOutputFunc outputFunc,
- void *outputStream) {
- char buf[512];
- Gushort cid;
- GBool ok;
- int i, j, k;
-
- // write the header
- ok = gTrue;
- sprintf(buf, "%%!PS-TrueTypeFont-%g\n", (double)getS32BE(0, &ok) / 65536.0);
- (*outputFunc)(outputStream, buf, strlen(buf));
-
- // begin the font dictionary
- (*outputFunc)(outputStream, "20 dict begin\n", 14);
- (*outputFunc)(outputStream, "/CIDFontName /", 14);
- (*outputFunc)(outputStream, psName, strlen(psName));
- (*outputFunc)(outputStream, " def\n", 5);
- (*outputFunc)(outputStream, "/CIDFontType 2 def\n", 19);
- (*outputFunc)(outputStream, "/FontType 42 def\n", 17);
- (*outputFunc)(outputStream, "/CIDSystemInfo 3 dict dup begin\n", 32);
- (*outputFunc)(outputStream, " /Registry (Adobe) def\n", 24);
- (*outputFunc)(outputStream, " /Ordering (Identity) def\n", 27);
- (*outputFunc)(outputStream, " /Supplement 0 def\n", 20);
- (*outputFunc)(outputStream, " end def\n", 10);
- (*outputFunc)(outputStream, "/GDBytes 2 def\n", 15);
- if (cidMap) {
- sprintf(buf, "/CIDCount %d def\n", nCIDs);
- (*outputFunc)(outputStream, buf, strlen(buf));
- if (nCIDs > 32767) {
- (*outputFunc)(outputStream, "/CIDMap [", 9);
- for (i = 0; i < nCIDs; i += 32768 - 16) {
- (*outputFunc)(outputStream, "<\n", 2);
- for (j = 0; j < 32768 - 16 && i+j < nCIDs; j += 16) {
- (*outputFunc)(outputStream, " ", 2);
- for (k = 0; k < 16 && i+j+k < nCIDs; ++k) {
- cid = cidMap[i+j+k];
- sprintf(buf, "%02x%02x", (cid >> 8) & 0xff, cid & 0xff);
- (*outputFunc)(outputStream, buf, strlen(buf));
- }
- (*outputFunc)(outputStream, "\n", 1);
- }
- (*outputFunc)(outputStream, " >", 3);
- }
- (*outputFunc)(outputStream, "\n", 1);
- (*outputFunc)(outputStream, "] def\n", 6);
- } else {
- (*outputFunc)(outputStream, "/CIDMap <\n", 10);
- for (i = 0; i < nCIDs; i += 16) {
- (*outputFunc)(outputStream, " ", 2);
- for (j = 0; j < 16 && i+j < nCIDs; ++j) {
- cid = cidMap[i+j];
- sprintf(buf, "%02x%02x", (cid >> 8) & 0xff, cid & 0xff);
- (*outputFunc)(outputStream, buf, strlen(buf));
- }
- (*outputFunc)(outputStream, "\n", 1);
- }
- (*outputFunc)(outputStream, "> def\n", 6);
- }
- } else {
- // direct mapping - just fill the string(s) with s[i]=i
- sprintf(buf, "/CIDCount %d def\n", nGlyphs);
- (*outputFunc)(outputStream, buf, strlen(buf));
- if (nGlyphs > 32767) {
- (*outputFunc)(outputStream, "/CIDMap [\n", 10);
- for (i = 0; i < nGlyphs; i += 32767) {
- j = nGlyphs - i < 32767 ? nGlyphs - i : 32767;
- sprintf(buf, " %d string 0 1 %d {\n", 2 * j, j - 1);
- (*outputFunc)(outputStream, buf, strlen(buf));
- sprintf(buf, " 2 copy dup 2 mul exch %d add -8 bitshift put\n", i);
- (*outputFunc)(outputStream, buf, strlen(buf));
- sprintf(buf, " 1 index exch dup 2 mul 1 add exch %d add"
- " 255 and put\n", i);
- (*outputFunc)(outputStream, buf, strlen(buf));
- (*outputFunc)(outputStream, " } for\n", 8);
- }
- (*outputFunc)(outputStream, "] def\n", 6);
- } else {
- sprintf(buf, "/CIDMap %d string\n", 2 * nGlyphs);
- (*outputFunc)(outputStream, buf, strlen(buf));
- sprintf(buf, " 0 1 %d {\n", nGlyphs - 1);
- (*outputFunc)(outputStream, buf, strlen(buf));
- (*outputFunc)(outputStream,
- " 2 copy dup 2 mul exch -8 bitshift put\n", 42);
- (*outputFunc)(outputStream,
- " 1 index exch dup 2 mul 1 add exch 255 and put\n", 50);
- (*outputFunc)(outputStream, " } for\n", 8);
- (*outputFunc)(outputStream, "def\n", 4);
- }
- }
- (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
- sprintf(buf, "/FontBBox [%d %d %d %d] def\n",
- bbox[0], bbox[1], bbox[2], bbox[3]);
- (*outputFunc)(outputStream, buf, strlen(buf));
- (*outputFunc)(outputStream, "/PaintType 0 def\n", 17);
- (*outputFunc)(outputStream, "/Encoding [] readonly def\n", 26);
- (*outputFunc)(outputStream, "/CharStrings 1 dict dup begin\n", 30);
- (*outputFunc)(outputStream, " /.notdef 0 def\n", 17);
- (*outputFunc)(outputStream, " end readonly def\n", 19);
-
- // write the guts of the dictionary
- cvtSfnts(outputFunc, outputStream, NULL, needVerticalMetrics);
-
- // end the dictionary and define the font
- (*outputFunc)(outputStream,
- "CIDFontName currentdict end /CIDFont defineresource pop\n",
- 56);
-}
-
-void FoFiTrueType::convertToType0(char *psName, Gushort *cidMap, int nCIDs,
- GBool needVerticalMetrics,
- FoFiOutputFunc outputFunc,
- void *outputStream) {
- char buf[512];
- GString *sfntsName;
- int n, i, j;
-
- // write the Type 42 sfnts array
- sfntsName = (new GString(psName))->append("_sfnts");
- cvtSfnts(outputFunc, outputStream, sfntsName, needVerticalMetrics);
- delete sfntsName;
-
- // write the descendant Type 42 fonts
- n = cidMap ? nCIDs : nGlyphs;
- for (i = 0; i < n; i += 256) {
- (*outputFunc)(outputStream, "10 dict begin\n", 14);
- (*outputFunc)(outputStream, "/FontName /", 11);
- (*outputFunc)(outputStream, psName, strlen(psName));
- sprintf(buf, "_%02x def\n", i >> 8);
- (*outputFunc)(outputStream, buf, strlen(buf));
- (*outputFunc)(outputStream, "/FontType 42 def\n", 17);
- (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
- sprintf(buf, "/FontBBox [%d %d %d %d] def\n",
- bbox[0], bbox[1], bbox[2], bbox[3]);
- (*outputFunc)(outputStream, buf, strlen(buf));
- (*outputFunc)(outputStream, "/PaintType 0 def\n", 17);
- (*outputFunc)(outputStream, "/sfnts ", 7);
- (*outputFunc)(outputStream, psName, strlen(psName));
- (*outputFunc)(outputStream, "_sfnts def\n", 11);
- (*outputFunc)(outputStream, "/Encoding 256 array\n", 20);
- for (j = 0; j < 256 && i+j < n; ++j) {
- sprintf(buf, "dup %d /c%02x put\n", j, j);
- (*outputFunc)(outputStream, buf, strlen(buf));
- }
- (*outputFunc)(outputStream, "readonly def\n", 13);
- (*outputFunc)(outputStream, "/CharStrings 257 dict dup begin\n", 32);
- (*outputFunc)(outputStream, "/.notdef 0 def\n", 15);
- for (j = 0; j < 256 && i+j < n; ++j) {
- sprintf(buf, "/c%02x %d def\n", j, cidMap ? cidMap[i+j] : i+j);
- (*outputFunc)(outputStream, buf, strlen(buf));
- }
- (*outputFunc)(outputStream, "end readonly def\n", 17);
- (*outputFunc)(outputStream,
- "FontName currentdict end definefont pop\n", 40);
- }
-
- // write the Type 0 parent font
- (*outputFunc)(outputStream, "16 dict begin\n", 14);
- (*outputFunc)(outputStream, "/FontName /", 11);
- (*outputFunc)(outputStream, psName, strlen(psName));
- (*outputFunc)(outputStream, " def\n", 5);
- (*outputFunc)(outputStream, "/FontType 0 def\n", 16);
- (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
- (*outputFunc)(outputStream, "/FMapType 2 def\n", 16);
- (*outputFunc)(outputStream, "/Encoding [\n", 12);
- for (i = 0; i < n; i += 256) {
- sprintf(buf, "%d\n", i >> 8);
- (*outputFunc)(outputStream, buf, strlen(buf));
- }
- (*outputFunc)(outputStream, "] def\n", 6);
- (*outputFunc)(outputStream, "/FDepVector [\n", 14);
- for (i = 0; i < n; i += 256) {
- (*outputFunc)(outputStream, "/", 1);
- (*outputFunc)(outputStream, psName, strlen(psName));
- sprintf(buf, "_%02x findfont\n", i >> 8);
- (*outputFunc)(outputStream, buf, strlen(buf));
- }
- (*outputFunc)(outputStream, "] def\n", 6);
- (*outputFunc)(outputStream, "FontName currentdict end definefont pop\n", 40);
-}
-
-void FoFiTrueType::writeTTF(FoFiOutputFunc outputFunc,
- void *outputStream, char *name,
- Gushort *codeToGID) {
- // this substitute cmap table maps char codes 0000-ffff directly to
- // glyphs 0000-ffff
- static char cmapTab[36] = {
- 0, 0, // table version number
- 0, 1, // number of encoding tables
- 0, 1, // platform ID
- 0, 0, // encoding ID
- 0, 0, 0, 12, // offset of subtable
- 0, 4, // subtable format
- 0, 24, // subtable length
- 0, 0, // subtable version
- 0, 2, // segment count * 2
- 0, 2, // 2 * 2 ^ floor(log2(segCount))
- 0, 0, // floor(log2(segCount))
- 0, 0, // 2*segCount - 2*2^floor(log2(segCount))
- (char)0xff, (char)0xff, // endCount[0]
- 0, 0, // reserved
- 0, 0, // startCount[0]
- 0, 0, // idDelta[0]
- 0, 0 // pad to a mulitple of four bytes
- };
- static char nameTab[8] = {
- 0, 0, // format
- 0, 0, // number of name records
- 0, 6, // offset to start of string storage
- 0, 0 // pad to multiple of four bytes
- };
- static char postTab[32] = {
- 0, 1, 0, 0, // format
- 0, 0, 0, 0, // italic angle
- 0, 0, // underline position
- 0, 0, // underline thickness
- 0, 0, 0, 0, // fixed pitch
- 0, 0, 0, 0, // min Type 42 memory
- 0, 0, 0, 0, // max Type 42 memory
- 0, 0, 0, 0, // min Type 1 memory
- 0, 0, 0, 0 // max Type 1 memory
- };
- GBool missingCmap, missingName, missingPost, unsortedLoca, badCmapLen;
- int nZeroLengthTables;
- TrueTypeLoca *locaTable;
- TrueTypeTable *newTables;
- char *newNameTab, *newCmapTab;
- int nNewTables, cmapIdx, cmapLen, glyfLen, newNameLen, newCmapLen, next;
- Guint locaChecksum, glyfChecksum, fileChecksum;
- char *tableDir;
- char locaBuf[4], checksumBuf[4];
- GBool ok;
- Guint t;
- int pos, i, j, k, n;
-
- // check for missing tables
- missingCmap = (cmapIdx = seekTable("cmap")) < 0;
- missingName = seekTable("name") < 0;
- missingPost = seekTable("post") < 0;
-
- // read the loca table, check to see if it's sorted
- locaTable = (TrueTypeLoca *)gmallocn(nGlyphs + 1, sizeof(TrueTypeLoca));
- unsortedLoca = gFalse;
- i = seekTable("loca");
- pos = tables[i].offset;
- ok = gTrue;
- for (i = 0; i <= nGlyphs; ++i) {
- if (locaFmt) {
- locaTable[i].origOffset = (int)getU32BE(pos + i*4, &ok);
- } else {
- locaTable[i].origOffset = 2 * getU16BE(pos + i*2, &ok);
- }
- if (i > 0 && locaTable[i].origOffset < locaTable[i-1].origOffset) {
- unsortedLoca = gTrue;
- }
- locaTable[i].idx = i;
- }
-
- // check for zero-length tables
- nZeroLengthTables = 0;
- for (i = 0; i < nTables; ++i) {
- if (tables[i].len == 0) {
- ++nZeroLengthTables;
- }
- }
-
- // check for an incorrect cmap table length
- badCmapLen = gFalse;
- cmapLen = 0; // make gcc happy
- if (!missingCmap) {
- cmapLen = cmaps[0].offset + cmaps[0].len;
- for (i = 1; i < nCmaps; ++i) {
- if (cmaps[i].offset + cmaps[i].len > cmapLen) {
- cmapLen = cmaps[i].offset + cmaps[i].len;
- }
- }
- cmapLen -= tables[cmapIdx].offset;
- if (cmapLen > tables[cmapIdx].len) {
- badCmapLen = gTrue;
- }
- }
-
- // if nothing is broken, just write the TTF file as is
- if (!missingCmap && !missingName && !missingPost && !unsortedLoca &&
- !badCmapLen && nZeroLengthTables == 0 && !name && !codeToGID) {
- (*outputFunc)(outputStream, (char *)file, len);
- goto done1;
- }
-
- // sort the 'loca' table: some (non-compliant) fonts have
- // out-of-order loca tables; in order to correctly handle the case
- // where (compliant) fonts have empty entries in the middle of the
- // table, cmpTrueTypeLocaOffset uses offset as its primary sort key,
- // and idx as its secondary key (ensuring that adjacent entries with
- // the same pos value remain in the same order)
- glyfLen = 0; // make gcc happy
- if (unsortedLoca) {
- qsort(locaTable, nGlyphs + 1, sizeof(TrueTypeLoca),
- &cmpTrueTypeLocaOffset);
- for (i = 0; i < nGlyphs; ++i) {
- locaTable[i].len = locaTable[i+1].origOffset - locaTable[i].origOffset;
- }
- locaTable[nGlyphs].len = 0;
- qsort(locaTable, nGlyphs + 1, sizeof(TrueTypeLoca),
- &cmpTrueTypeLocaIdx);
- pos = 0;
- for (i = 0; i <= nGlyphs; ++i) {
- locaTable[i].newOffset = pos;
- pos += locaTable[i].len;
- if (pos & 3) {
- pos += 4 - (pos & 3);
- }
- }
- glyfLen = pos;
- }
-
- // compute checksums for the loca and glyf tables
- locaChecksum = glyfChecksum = 0;
- if (unsortedLoca) {
- if (locaFmt) {
- for (j = 0; j <= nGlyphs; ++j) {
- locaChecksum += locaTable[j].newOffset;
- }
- } else {
- for (j = 0; j <= nGlyphs; j += 2) {
- locaChecksum += locaTable[j].newOffset << 16;
- if (j + 1 <= nGlyphs) {
- locaChecksum += locaTable[j+1].newOffset;
- }
- }
- }
- pos = tables[seekTable("glyf")].offset;
- for (j = 0; j < nGlyphs; ++j) {
- n = locaTable[j].len;
- if (n > 0) {
- k = locaTable[j].origOffset;
- if (checkRegion(pos + k, n)) {
- glyfChecksum += computeTableChecksum(file + pos + k, n);
- }
- }
- }
- }
-
- // construct the new name table
- if (name) {
- n = strlen(name);
- newNameLen = (6 + 4*12 + 2 * (3*n + 7) + 3) & ~3;
- newNameTab = (char *)gmalloc(newNameLen);
- memset(newNameTab, 0, newNameLen);
- newNameTab[0] = 0; // format selector
- newNameTab[1] = 0;
- newNameTab[2] = 0; // number of name records
- newNameTab[3] = 4;
- newNameTab[4] = 0; // offset to start of string storage
- newNameTab[5] = 6 + 4*12;
- next = 0;
- for (i = 0; i < 4; ++i) {
- newNameTab[6 + i*12 + 0] = 0; // platform ID = Microsoft
- newNameTab[6 + i*12 + 1] = 3;
- newNameTab[6 + i*12 + 2] = 0; // encoding ID = Unicode
- newNameTab[6 + i*12 + 3] = 1;
- newNameTab[6 + i*12 + 4] = 0x04; // language ID = American English
- newNameTab[6 + i*12 + 5] = 0x09;
- newNameTab[6 + i*12 + 6] = 0; // name ID
- newNameTab[6 + i*12 + 7] = i + 1;
- newNameTab[6 + i*12 + 8] = i+1 == 2 ? 0 : ((2*n) >> 8); // string length
- newNameTab[6 + i*12 + 9] = i+1 == 2 ? 14 : ((2*n) & 0xff);
- newNameTab[6 + i*12 + 10] = next >> 8; // string offset
- newNameTab[6 + i*12 + 11] = next & 0xff;
- if (i+1 == 2) {
- memcpy(newNameTab + 6 + 4*12 + next, "\0R\0e\0g\0u\0l\0a\0r", 14);
- next += 14;
- } else {
- for (j = 0; j < n; ++j) {
- newNameTab[6 + 4*12 + next + 2*j] = 0;
- newNameTab[6 + 4*12 + next + 2*j + 1] = name[j];
- }
- next += 2*n;
- }
- }
- } else {
- newNameLen = 0;
- newNameTab = NULL;
- }
-
- // construct the new cmap table
- if (codeToGID) {
- newCmapLen = 44 + 256 * 2;
- newCmapTab = (char *)gmalloc(newCmapLen);
- newCmapTab[0] = 0; // table version number = 0
- newCmapTab[1] = 0;
- newCmapTab[2] = 0; // number of encoding tables = 1
- newCmapTab[3] = 1;
- newCmapTab[4] = 0; // platform ID = Microsoft
- newCmapTab[5] = 3;
- newCmapTab[6] = 0; // encoding ID = Unicode
- newCmapTab[7] = 1;
- newCmapTab[8] = 0; // offset of subtable
- newCmapTab[9] = 0;
- newCmapTab[10] = 0;
- newCmapTab[11] = 12;
- newCmapTab[12] = 0; // subtable format = 4
- newCmapTab[13] = 4;
- newCmapTab[14] = 0x02; // subtable length
- newCmapTab[15] = 0x20;
- newCmapTab[16] = 0; // subtable version = 0
- newCmapTab[17] = 0;
- newCmapTab[18] = 0; // segment count * 2
- newCmapTab[19] = 4;
- newCmapTab[20] = 0; // 2 * 2 ^ floor(log2(segCount))
- newCmapTab[21] = 4;
- newCmapTab[22] = 0; // floor(log2(segCount))
- newCmapTab[23] = 1;
- newCmapTab[24] = 0; // 2*segCount - 2*2^floor(log2(segCount))
- newCmapTab[25] = 0;
- newCmapTab[26] = 0x00; // endCount[0]
- newCmapTab[27] = (char)0xff;
- newCmapTab[28] = (char)0xff; // endCount[1]
- newCmapTab[29] = (char)0xff;
- newCmapTab[30] = 0; // reserved
- newCmapTab[31] = 0;
- newCmapTab[32] = 0x00; // startCount[0]
- newCmapTab[33] = 0x00;
- newCmapTab[34] = (char)0xff; // startCount[1]
- newCmapTab[35] = (char)0xff;
- newCmapTab[36] = 0; // idDelta[0]
- newCmapTab[37] = 0;
- newCmapTab[38] = 0; // idDelta[1]
- newCmapTab[39] = 1;
- newCmapTab[40] = 0; // idRangeOffset[0]
- newCmapTab[41] = 4;
- newCmapTab[42] = 0; // idRangeOffset[1]
- newCmapTab[43] = 0;
- for (i = 0; i < 256; ++i) {
- newCmapTab[44 + 2*i] = codeToGID[i] >> 8;
- newCmapTab[44 + 2*i + 1] = codeToGID[i] & 0xff;
- }
- } else {
- newCmapLen = 0;
- newCmapTab = NULL;
- }
-
- // construct the new table directory:
- // - keep all original tables with non-zero length
- // - fix the cmap table's length, if necessary
- // - add missing tables
- // - sort the table by tag
- // - compute new table positions, including 4-byte alignment
- // - (re)compute table checksums
- nNewTables = nTables - nZeroLengthTables +
- (missingCmap ? 1 : 0) + (missingName ? 1 : 0) +
- (missingPost ? 1 : 0);
- newTables = (TrueTypeTable *)gmallocn(nNewTables, sizeof(TrueTypeTable));
- j = 0;
- for (i = 0; i < nTables; ++i) {
- if (tables[i].len > 0) {
- newTables[j] = tables[i];
- newTables[j].origOffset = tables[i].offset;
- if (checkRegion(tables[i].offset, newTables[i].len)) {
- newTables[j].checksum =
- computeTableChecksum(file + tables[i].offset, tables[i].len);
- if (tables[i].tag == headTag) {
- // don't include the file checksum
- newTables[j].checksum -= getU32BE(tables[i].offset + 8, &ok);
- }
- }
- if (newTables[j].tag == cmapTag && codeToGID) {
- newTables[j].len = newCmapLen;
- newTables[j].checksum = computeTableChecksum((Guchar *)newCmapTab,
- newCmapLen);
- } else if (newTables[j].tag == cmapTag && badCmapLen) {
- newTables[j].len = cmapLen;
- } else if (newTables[j].tag == locaTag && unsortedLoca) {
- newTables[j].len = (nGlyphs + 1) * (locaFmt ? 4 : 2);
- newTables[j].checksum = locaChecksum;
- } else if (newTables[j].tag == glyfTag && unsortedLoca) {
- newTables[j].len = glyfLen;
- newTables[j].checksum = glyfChecksum;
- } else if (newTables[j].tag == nameTag && name) {
- newTables[j].len = newNameLen;
- newTables[j].checksum = computeTableChecksum((Guchar *)newNameTab,
- newNameLen);
- }
- ++j;
- }
- }
- if (missingCmap) {
- newTables[j].tag = cmapTag;
- if (codeToGID) {
- newTables[j].checksum = computeTableChecksum((Guchar *)newCmapTab,
- newCmapLen);
- newTables[j].len = newCmapLen;
- } else {
- newTables[j].checksum = computeTableChecksum((Guchar *)cmapTab,
- sizeof(cmapTab));
- newTables[j].len = sizeof(cmapTab);
- }
- ++j;
- }
- if (missingName) {
- newTables[j].tag = nameTag;
- if (name) {
- newTables[j].checksum = computeTableChecksum((Guchar *)newNameTab,
- newNameLen);
- newTables[j].len = newNameLen;
- } else {
- newTables[j].checksum = computeTableChecksum((Guchar *)nameTab,
- sizeof(nameTab));
- newTables[j].len = sizeof(nameTab);
- }
- ++j;
- }
- if (missingPost) {
- newTables[j].tag = postTag;
- newTables[j].checksum = computeTableChecksum((Guchar *)postTab,
- sizeof(postTab));
- newTables[j].len = sizeof(postTab);
- ++j;
- }
- qsort(newTables, nNewTables, sizeof(TrueTypeTable),
- &cmpTrueTypeTableTag);
- pos = 12 + nNewTables * 16;
- for (i = 0; i < nNewTables; ++i) {
- newTables[i].offset = pos;
- pos += newTables[i].len;
- if (pos & 3) {
- pos += 4 - (pos & 3);
- }
- }
-
- // write the table directory
- tableDir = (char *)gmalloc(12 + nNewTables * 16);
- tableDir[0] = 0x00; // sfnt version
- tableDir[1] = 0x01;
- tableDir[2] = 0x00;
- tableDir[3] = 0x00;
- tableDir[4] = (char)((nNewTables >> 8) & 0xff); // numTables
- tableDir[5] = (char)(nNewTables & 0xff);
- for (i = -1, t = (Guint)nNewTables; t; ++i, t >>= 1) ;
- t = 1 << (4 + i);
- tableDir[6] = (char)((t >> 8) & 0xff); // searchRange
- tableDir[7] = (char)(t & 0xff);
- tableDir[8] = (char)((i >> 8) & 0xff); // entrySelector
- tableDir[9] = (char)(i & 0xff);
- t = nNewTables * 16 - t;
- tableDir[10] = (char)((t >> 8) & 0xff); // rangeShift
- tableDir[11] = (char)(t & 0xff);
- pos = 12;
- for (i = 0; i < nNewTables; ++i) {
- tableDir[pos ] = (char)(newTables[i].tag >> 24);
- tableDir[pos+ 1] = (char)(newTables[i].tag >> 16);
- tableDir[pos+ 2] = (char)(newTables[i].tag >> 8);
- tableDir[pos+ 3] = (char) newTables[i].tag;
- tableDir[pos+ 4] = (char)(newTables[i].checksum >> 24);
- tableDir[pos+ 5] = (char)(newTables[i].checksum >> 16);
- tableDir[pos+ 6] = (char)(newTables[i].checksum >> 8);
- tableDir[pos+ 7] = (char) newTables[i].checksum;
- tableDir[pos+ 8] = (char)(newTables[i].offset >> 24);
- tableDir[pos+ 9] = (char)(newTables[i].offset >> 16);
- tableDir[pos+10] = (char)(newTables[i].offset >> 8);
- tableDir[pos+11] = (char) newTables[i].offset;
- tableDir[pos+12] = (char)(newTables[i].len >> 24);
- tableDir[pos+13] = (char)(newTables[i].len >> 16);
- tableDir[pos+14] = (char)(newTables[i].len >> 8);
- tableDir[pos+15] = (char) newTables[i].len;
- pos += 16;
- }
- (*outputFunc)(outputStream, tableDir, 12 + nNewTables * 16);
-
- // compute the file checksum
- fileChecksum = computeTableChecksum((Guchar *)tableDir,
- 12 + nNewTables * 16);
- for (i = 0; i < nNewTables; ++i) {
- fileChecksum += newTables[i].checksum;
- }
- fileChecksum = 0xb1b0afba - fileChecksum;
-
- // write the tables
- for (i = 0; i < nNewTables; ++i) {
- if (newTables[i].tag == headTag) {
- if (checkRegion(newTables[i].origOffset, newTables[i].len)) {
- (*outputFunc)(outputStream, (char *)file + newTables[i].origOffset, 8);
- checksumBuf[0] = fileChecksum >> 24;
- checksumBuf[1] = fileChecksum >> 16;
- checksumBuf[2] = fileChecksum >> 8;
- checksumBuf[3] = fileChecksum;
- (*outputFunc)(outputStream, checksumBuf, 4);
- (*outputFunc)(outputStream,
- (char *)file + newTables[i].origOffset + 12,
- newTables[i].len - 12);
- } else {
- for (j = 0; j < newTables[i].len; ++j) {
- (*outputFunc)(outputStream, "\0", 1);
- }
- }
- } else if (newTables[i].tag == cmapTag && codeToGID) {
- (*outputFunc)(outputStream, newCmapTab, newTables[i].len);
- } else if (newTables[i].tag == cmapTag && missingCmap) {
- (*outputFunc)(outputStream, cmapTab, newTables[i].len);
- } else if (newTables[i].tag == nameTag && name) {
- (*outputFunc)(outputStream, newNameTab, newTables[i].len);
- } else if (newTables[i].tag == nameTag && missingName) {
- (*outputFunc)(outputStream, nameTab, newTables[i].len);
- } else if (newTables[i].tag == postTag && missingPost) {
- (*outputFunc)(outputStream, postTab, newTables[i].len);
- } else if (newTables[i].tag == locaTag && unsortedLoca) {
- for (j = 0; j <= nGlyphs; ++j) {
- if (locaFmt) {
- locaBuf[0] = (char)(locaTable[j].newOffset >> 24);
- locaBuf[1] = (char)(locaTable[j].newOffset >> 16);
- locaBuf[2] = (char)(locaTable[j].newOffset >> 8);
- locaBuf[3] = (char) locaTable[j].newOffset;
- (*outputFunc)(outputStream, locaBuf, 4);
- } else {
- locaBuf[0] = (char)(locaTable[j].newOffset >> 9);
- locaBuf[1] = (char)(locaTable[j].newOffset >> 1);
- (*outputFunc)(outputStream, locaBuf, 2);
- }
- }
- } else if (newTables[i].tag == glyfTag && unsortedLoca) {
- pos = tables[seekTable("glyf")].offset;
- for (j = 0; j < nGlyphs; ++j) {
- n = locaTable[j].len;
- if (n > 0) {
- k = locaTable[j].origOffset;
- if (checkRegion(pos + k, n)) {
- (*outputFunc)(outputStream, (char *)file + pos + k, n);
- } else {
- for (k = 0; k < n; ++k) {
- (*outputFunc)(outputStream, "\0", 1);
- }
- }
- if ((k = locaTable[j].len & 3)) {
- (*outputFunc)(outputStream, "\0\0\0\0", 4 - k);
- }
- }
- }
- } else {
- if (checkRegion(newTables[i].origOffset, newTables[i].len)) {
- (*outputFunc)(outputStream, (char *)file + newTables[i].origOffset,
- newTables[i].len);
- } else {
- for (j = 0; j < newTables[i].len; ++j) {
- (*outputFunc)(outputStream, "\0", 1);
- }
- }
- }
- if (newTables[i].len & 3) {
- (*outputFunc)(outputStream, "\0\0\0", 4 - (newTables[i].len & 3));
- }
- }
-
- gfree(newCmapTab);
- gfree(newNameTab);
- gfree(tableDir);
- gfree(newTables);
- done1:
- gfree(locaTable);
-}
-
-void FoFiTrueType::cvtEncoding(char **encoding,
- FoFiOutputFunc outputFunc,
- void *outputStream) {
- char *name;
- char buf[64];
- int i;
-
- (*outputFunc)(outputStream, "/Encoding 256 array\n", 20);
- if (encoding) {
- for (i = 0; i < 256; ++i) {
- if (!(name = encoding[i])) {
- name = ".notdef";
- }
- sprintf(buf, "dup %d /", i);
- (*outputFunc)(outputStream, buf, strlen(buf));
- (*outputFunc)(outputStream, name, strlen(name));
- (*outputFunc)(outputStream, " put\n", 5);
- }
- } else {
- for (i = 0; i < 256; ++i) {
- sprintf(buf, "dup %d /c%02x put\n", i, i);
- (*outputFunc)(outputStream, buf, strlen(buf));
- }
- }
- (*outputFunc)(outputStream, "readonly def\n", 13);
-}
-
-void FoFiTrueType::cvtCharStrings(char **encoding,
- Gushort *codeToGID,
- FoFiOutputFunc outputFunc,
- void *outputStream) {
- char *name;
- char buf[64], buf2[16];
- int i, k;
-
- // always define '.notdef'
- (*outputFunc)(outputStream, "/CharStrings 256 dict dup begin\n", 32);
- (*outputFunc)(outputStream, "/.notdef 0 def\n", 15);
-
- // if there's no 'cmap' table, punt
- if (nCmaps == 0) {
- goto err;
- }
-
- // map char name to glyph index:
- // 1. use encoding to map name to char code
- // 2. use codeToGID to map char code to glyph index
- // N.B. We do this in reverse order because font subsets can have
- // weird encodings that use the same character name twice, and
- // the first definition is probably the one we want.
- k = 0; // make gcc happy
- for (i = 255; i >= 0; --i) {
- if (encoding) {
- name = encoding[i];
- } else {
- sprintf(buf2, "c%02x", i);
- name = buf2;
- }
- if (name && strcmp(name, ".notdef")) {
- k = codeToGID[i];
- // note: Distiller (maybe Adobe's PS interpreter in general)
- // doesn't like TrueType fonts that have CharStrings entries
- // which point to nonexistent glyphs, hence the (k < nGlyphs)
- // test
- if (k > 0 && k < nGlyphs) {
- (*outputFunc)(outputStream, "/", 1);
- (*outputFunc)(outputStream, name, strlen(name));
- sprintf(buf, " %d def\n", k);
- (*outputFunc)(outputStream, buf, strlen(buf));
- }
- }
- }
-
- err:
- (*outputFunc)(outputStream, "end readonly def\n", 17);
-}
-
-void FoFiTrueType::cvtSfnts(FoFiOutputFunc outputFunc,
- void *outputStream, GString *name,
- GBool needVerticalMetrics) {
- Guchar headData[54];
- TrueTypeLoca *locaTable;
- Guchar *locaData;
- TrueTypeTable newTables[nT42Tables];
- Guchar tableDir[12 + nT42Tables*16];
- GBool ok;
- Guint checksum;
- int nNewTables;
- int length, pos, glyfPos, i, j, k;
- Guchar vheaTab[36] = {
- 0, 1, 0, 0, // table version number
- 0, 0, // ascent
- 0, 0, // descent
- 0, 0, // reserved
- 0, 0, // max advance height
- 0, 0, // min top side bearing
- 0, 0, // min bottom side bearing
- 0, 0, // y max extent
- 0, 0, // caret slope rise
- 0, 1, // caret slope run
- 0, 0, // caret offset
- 0, 0, // reserved
- 0, 0, // reserved
- 0, 0, // reserved
- 0, 0, // reserved
- 0, 0, // metric data format
- 0, 1 // number of advance heights in vmtx table
- };
- Guchar *vmtxTab;
- GBool needVhea, needVmtx;
- int advance;
-
- // construct the 'head' table, zero out the font checksum
- i = seekTable("head");
- pos = tables[i].offset;
- if (!checkRegion(pos, 54)) {
- return;
- }
- memcpy(headData, file + pos, 54);
- headData[8] = headData[9] = headData[10] = headData[11] = (Guchar)0;
-
- // read the original 'loca' table, pad entries out to 4 bytes, and
- // sort it into proper order -- some (non-compliant) fonts have
- // out-of-order loca tables; in order to correctly handle the case
- // where (compliant) fonts have empty entries in the middle of the
- // table, cmpTrueTypeLocaPos uses offset as its primary sort key,
- // and idx as its secondary key (ensuring that adjacent entries with
- // the same pos value remain in the same order)
- locaTable = (TrueTypeLoca *)gmallocn(nGlyphs + 1, sizeof(TrueTypeLoca));
- i = seekTable("loca");
- pos = tables[i].offset;
- ok = gTrue;
- for (i = 0; i <= nGlyphs; ++i) {
- locaTable[i].idx = i;
- if (locaFmt) {
- locaTable[i].origOffset = (int)getU32BE(pos + i*4, &ok);
- } else {
- locaTable[i].origOffset = 2 * getU16BE(pos + i*2, &ok);
- }
- }
- qsort(locaTable, nGlyphs + 1, sizeof(TrueTypeLoca),
- &cmpTrueTypeLocaOffset);
- for (i = 0; i < nGlyphs; ++i) {
- locaTable[i].len = locaTable[i+1].origOffset - locaTable[i].origOffset;
- }
- locaTable[nGlyphs].len = 0;
- qsort(locaTable, nGlyphs + 1, sizeof(TrueTypeLoca),
- &cmpTrueTypeLocaIdx);
- pos = 0;
- for (i = 0; i <= nGlyphs; ++i) {
- locaTable[i].newOffset = pos;
- pos += locaTable[i].len;
- if (pos & 3) {
- pos += 4 - (pos & 3);
- }
- }
-
- // construct the new 'loca' table
- locaData = (Guchar *)gmallocn(nGlyphs + 1, (locaFmt ? 4 : 2));
- for (i = 0; i <= nGlyphs; ++i) {
- pos = locaTable[i].newOffset;
- if (locaFmt) {
- locaData[4*i ] = (Guchar)(pos >> 24);
- locaData[4*i+1] = (Guchar)(pos >> 16);
- locaData[4*i+2] = (Guchar)(pos >> 8);
- locaData[4*i+3] = (Guchar) pos;
- } else {
- locaData[2*i ] = (Guchar)(pos >> 9);
- locaData[2*i+1] = (Guchar)(pos >> 1);
- }
- }
-
- // count the number of tables
- nNewTables = 0;
- for (i = 0; i < nT42Tables; ++i) {
- if (t42Tables[i].required ||
- seekTable(t42Tables[i].tag) >= 0) {
- ++nNewTables;
- }
- }
- vmtxTab = NULL; // make gcc happy
- advance = 0; // make gcc happy
- if (needVerticalMetrics) {
- needVhea = seekTable("vhea") < 0;
- needVmtx = seekTable("vmtx") < 0;
- if (needVhea || needVmtx) {
- i = seekTable("head");
- advance = getU16BE(tables[i].offset + 18, &ok); // units per em
- if (needVhea) {
- ++nNewTables;
- }
- if (needVmtx) {
- ++nNewTables;
- }
- }
- }
-
- // construct the new table headers, including table checksums
- // (pad each table out to a multiple of 4 bytes)
- pos = 12 + nNewTables*16;
- k = 0;
- for (i = 0; i < nT42Tables; ++i) {
- length = -1;
- checksum = 0; // make gcc happy
- if (i == t42HeadTable) {
- length = 54;
- checksum = computeTableChecksum(headData, 54);
- } else if (i == t42LocaTable) {
- length = (nGlyphs + 1) * (locaFmt ? 4 : 2);
- checksum = computeTableChecksum(locaData, length);
- } else if (i == t42GlyfTable) {
- length = 0;
- checksum = 0;
- glyfPos = tables[seekTable("glyf")].offset;
- for (j = 0; j < nGlyphs; ++j) {
- length += locaTable[j].len;
- if (length & 3) {
- length += 4 - (length & 3);
- }
- if (checkRegion(glyfPos + locaTable[j].origOffset, locaTable[j].len)) {
- checksum +=
- computeTableChecksum(file + glyfPos + locaTable[j].origOffset,
- locaTable[j].len);
- }
- }
- } else {
- if ((j = seekTable(t42Tables[i].tag)) >= 0) {
- length = tables[j].len;
- if (checkRegion(tables[j].offset, length)) {
- checksum = computeTableChecksum(file + tables[j].offset, length);
- }
- } else if (needVerticalMetrics && i == t42VheaTable) {
- vheaTab[10] = advance / 256; // max advance height
- vheaTab[11] = advance % 256;
- length = sizeof(vheaTab);
- checksum = computeTableChecksum(vheaTab, length);
- } else if (needVerticalMetrics && i == t42VmtxTable) {
- length = 4 + (nGlyphs - 1) * 4;
- vmtxTab = (Guchar *)gmalloc(length);
- vmtxTab[0] = advance / 256;
- vmtxTab[1] = advance % 256;
- for (j = 2; j < length; j += 2) {
- vmtxTab[j] = 0;
- vmtxTab[j+1] = 0;
- }
- checksum = computeTableChecksum(vmtxTab, length);
- } else if (t42Tables[i].required) {
- //~ error(-1, "Embedded TrueType font is missing a required table ('%s')",
- //~ t42Tables[i].tag);
- length = 0;
- checksum = 0;
- }
- }
- if (length >= 0) {
- newTables[k].tag = ((t42Tables[i].tag[0] & 0xff) << 24) |
- ((t42Tables[i].tag[1] & 0xff) << 16) |
- ((t42Tables[i].tag[2] & 0xff) << 8) |
- (t42Tables[i].tag[3] & 0xff);
- newTables[k].checksum = checksum;
- newTables[k].offset = pos;
- newTables[k].len = length;
- pos += length;
- if (pos & 3) {
- pos += 4 - (length & 3);
- }
- ++k;
- }
- }
-
- // construct the table directory
- tableDir[0] = 0x00; // sfnt version
- tableDir[1] = 0x01;
- tableDir[2] = 0x00;
- tableDir[3] = 0x00;
- tableDir[4] = 0; // numTables
- tableDir[5] = nNewTables;
- tableDir[6] = 0; // searchRange
- tableDir[7] = (Guchar)128;
- tableDir[8] = 0; // entrySelector
- tableDir[9] = 3;
- tableDir[10] = 0; // rangeShift
- tableDir[11] = (Guchar)(16 * nNewTables - 128);
- pos = 12;
- for (i = 0; i < nNewTables; ++i) {
- tableDir[pos ] = (Guchar)(newTables[i].tag >> 24);
- tableDir[pos+ 1] = (Guchar)(newTables[i].tag >> 16);
- tableDir[pos+ 2] = (Guchar)(newTables[i].tag >> 8);
- tableDir[pos+ 3] = (Guchar) newTables[i].tag;
- tableDir[pos+ 4] = (Guchar)(newTables[i].checksum >> 24);
- tableDir[pos+ 5] = (Guchar)(newTables[i].checksum >> 16);
- tableDir[pos+ 6] = (Guchar)(newTables[i].checksum >> 8);
- tableDir[pos+ 7] = (Guchar) newTables[i].checksum;
- tableDir[pos+ 8] = (Guchar)(newTables[i].offset >> 24);
- tableDir[pos+ 9] = (Guchar)(newTables[i].offset >> 16);
- tableDir[pos+10] = (Guchar)(newTables[i].offset >> 8);
- tableDir[pos+11] = (Guchar) newTables[i].offset;
- tableDir[pos+12] = (Guchar)(newTables[i].len >> 24);
- tableDir[pos+13] = (Guchar)(newTables[i].len >> 16);
- tableDir[pos+14] = (Guchar)(newTables[i].len >> 8);
- tableDir[pos+15] = (Guchar) newTables[i].len;
- pos += 16;
- }
-
- // compute the font checksum and store it in the head table
- checksum = computeTableChecksum(tableDir, 12 + nNewTables*16);
- for (i = 0; i < nNewTables; ++i) {
- checksum += newTables[i].checksum;
- }
- checksum = 0xb1b0afba - checksum; // because the TrueType spec says so
- headData[ 8] = (Guchar)(checksum >> 24);
- headData[ 9] = (Guchar)(checksum >> 16);
- headData[10] = (Guchar)(checksum >> 8);
- headData[11] = (Guchar) checksum;
-
- // start the sfnts array
- if (name) {
- (*outputFunc)(outputStream, "/", 1);
- (*outputFunc)(outputStream, name->getCString(), name->getLength());
- (*outputFunc)(outputStream, " [\n", 3);
- } else {
- (*outputFunc)(outputStream, "/sfnts [\n", 9);
- }
-
- // write the table directory
- dumpString(tableDir, 12 + nNewTables*16, outputFunc, outputStream);
-
- // write the tables
- for (i = 0; i < nNewTables; ++i) {
- if (i == t42HeadTable) {
- dumpString(headData, 54, outputFunc, outputStream);
- } else if (i == t42LocaTable) {
- length = (nGlyphs + 1) * (locaFmt ? 4 : 2);
- dumpString(locaData, length, outputFunc, outputStream);
- } else if (i == t42GlyfTable) {
- glyfPos = tables[seekTable("glyf")].offset;
- for (j = 0; j < nGlyphs; ++j) {
- if (locaTable[j].len > 0 &&
- checkRegion(glyfPos + locaTable[j].origOffset, locaTable[j].len)) {
- dumpString(file + glyfPos + locaTable[j].origOffset,
- locaTable[j].len, outputFunc, outputStream);
- }
- }
- } else {
- // length == 0 means the table is missing and the error was
- // already reported during the construction of the table
- // headers
- if ((length = newTables[i].len) > 0) {
- if ((j = seekTable(t42Tables[i].tag)) >= 0 &&
- checkRegion(tables[j].offset, tables[j].len)) {
- dumpString(file + tables[j].offset, tables[j].len,
- outputFunc, outputStream);
- } else if (needVerticalMetrics && i == t42VheaTable) {
- dumpString(vheaTab, length, outputFunc, outputStream);
- } else if (needVerticalMetrics && i == t42VmtxTable) {
- dumpString(vmtxTab, length, outputFunc, outputStream);
- gfree(vmtxTab);
- }
- }
- }
- }
-
- // end the sfnts array
- (*outputFunc)(outputStream, "] def\n", 6);
-
- gfree(locaData);
- gfree(locaTable);
-}
-
-void FoFiTrueType::dumpString(Guchar *s, int length,
- FoFiOutputFunc outputFunc,
- void *outputStream) {
- char buf[64];
- int pad, i, j;
-
- (*outputFunc)(outputStream, "<", 1);
- for (i = 0; i < length; i += 32) {
- for (j = 0; j < 32 && i+j < length; ++j) {
- sprintf(buf, "%02X", s[i+j] & 0xff);
- (*outputFunc)(outputStream, buf, strlen(buf));
- }
- if (i % (65536 - 32) == 65536 - 64) {
- (*outputFunc)(outputStream, ">\n<", 3);
- } else if (i+32 < length) {
- (*outputFunc)(outputStream, "\n", 1);
- }
- }
- if (length & 3) {
- pad = 4 - (length & 3);
- for (i = 0; i < pad; ++i) {
- (*outputFunc)(outputStream, "00", 2);
- }
- }
- // add an extra zero byte because the Adobe Type 42 spec says so
- (*outputFunc)(outputStream, "00>\n", 4);
-}
-
-Guint FoFiTrueType::computeTableChecksum(Guchar *data, int length) {
- Guint checksum, word;
- int i;
-
- checksum = 0;
- for (i = 0; i+3 < length; i += 4) {
- word = ((data[i ] & 0xff) << 24) +
- ((data[i+1] & 0xff) << 16) +
- ((data[i+2] & 0xff) << 8) +
- (data[i+3] & 0xff);
- checksum += word;
- }
- if (length & 3) {
- word = 0;
- i = length & ~3;
- switch (length & 3) {
- case 3:
- word |= (data[i+2] & 0xff) << 8;
- case 2:
- word |= (data[i+1] & 0xff) << 16;
- case 1:
- word |= (data[i ] & 0xff) << 24;
- break;
- }
- checksum += word;
- }
- return checksum;
-}
-
-void FoFiTrueType::parse() {
- Guint topTag;
- int pos, i, j;
-
- parsedOk = gTrue;
-
- // look for a collection (TTC)
- topTag = getU32BE(0, &parsedOk);
- if (!parsedOk) {
- return;
- }
- if (topTag == ttcfTag) {
- pos = getU32BE(12, &parsedOk);
- if (!parsedOk) {
- return;
- }
- } else {
- pos = 0;
- }
-
- // read the table directory
- nTables = getU16BE(pos + 4, &parsedOk);
- if (!parsedOk) {
- return;
- }
- tables = (TrueTypeTable *)gmallocn(nTables, sizeof(TrueTypeTable));
- pos += 12;
- for (i = 0; i < nTables; ++i) {
- tables[i].tag = getU32BE(pos, &parsedOk);
- tables[i].checksum = getU32BE(pos + 4, &parsedOk);
- tables[i].offset = (int)getU32BE(pos + 8, &parsedOk);
- tables[i].len = (int)getU32BE(pos + 12, &parsedOk);
- if (tables[i].offset + tables[i].len < tables[i].offset ||
- tables[i].offset + tables[i].len > len) {
- parsedOk = gFalse;
- }
- pos += 16;
- }
- if (!parsedOk) {
- return;
- }
-
- // check for tables that are required by both the TrueType spec and
- // the Type 42 spec
- if (seekTable("head") < 0 ||
- seekTable("hhea") < 0 ||
- seekTable("loca") < 0 ||
- seekTable("maxp") < 0 ||
- seekTable("glyf") < 0 ||
- seekTable("hmtx") < 0) {
- parsedOk = gFalse;
- return;
- }
-
- // read the cmaps
- if ((i = seekTable("cmap")) >= 0) {
- pos = tables[i].offset + 2;
- nCmaps = getU16BE(pos, &parsedOk);
- pos += 2;
- if (!parsedOk) {
- return;
- }
- cmaps = (TrueTypeCmap *)gmallocn(nCmaps, sizeof(TrueTypeCmap));
- for (j = 0; j < nCmaps; ++j) {
- cmaps[j].platform = getU16BE(pos, &parsedOk);
- cmaps[j].encoding = getU16BE(pos + 2, &parsedOk);
- cmaps[j].offset = tables[i].offset + getU32BE(pos + 4, &parsedOk);
- pos += 8;
- cmaps[j].fmt = getU16BE(cmaps[j].offset, &parsedOk);
- cmaps[j].len = getU16BE(cmaps[j].offset + 2, &parsedOk);
- }
- if (!parsedOk) {
- return;
- }
- } else {
- nCmaps = 0;
- }
-
- // get the number of glyphs from the maxp table
- i = seekTable("maxp");
- nGlyphs = getU16BE(tables[i].offset + 4, &parsedOk);
- if (!parsedOk) {
- return;
- }
-
- // get the bbox and loca table format from the head table
- i = seekTable("head");
- bbox[0] = getS16BE(tables[i].offset + 36, &parsedOk);
- bbox[1] = getS16BE(tables[i].offset + 38, &parsedOk);
- bbox[2] = getS16BE(tables[i].offset + 40, &parsedOk);
- bbox[3] = getS16BE(tables[i].offset + 42, &parsedOk);
- locaFmt = getS16BE(tables[i].offset + 50, &parsedOk);
- if (!parsedOk) {
- return;
- }
-
- // make sure the loca table is sane (correct length and entries are
- // in bounds)
- i = seekTable("loca");
- if (tables[i].len < (nGlyphs + 1) * (locaFmt ? 4 : 2)) {
- parsedOk = gFalse;
- return;
- }
- for (j = 0; j <= nGlyphs; ++j) {
- if (locaFmt) {
- pos = (int)getU32BE(tables[i].offset + j*4, &parsedOk);
- } else {
- pos = getU16BE(tables[i].offset + j*2, &parsedOk);
- }
- if (pos < 0 || pos > len) {
- parsedOk = gFalse;
- }
- }
- if (!parsedOk) {
- return;
- }
-
- // read the post table
- readPostTable();
-}
-
-void FoFiTrueType::readPostTable() {
- GString *name;
- int tablePos, postFmt, stringIdx, stringPos;
- GBool ok;
- int i, j, n, m;
-
- ok = gTrue;
- if ((i = seekTable("post")) < 0) {
- return;
- }
- tablePos = tables[i].offset;
- postFmt = getU32BE(tablePos, &ok);
- if (!ok) {
- goto err;
- }
- if (postFmt == 0x00010000) {
- nameToGID = new GHash(gTrue);
- for (i = 0; i < 258; ++i) {
- nameToGID->add(new GString(macGlyphNames[i]), i);
- }
- } else if (postFmt == 0x00020000) {
- nameToGID = new GHash(gTrue);
- n = getU16BE(tablePos + 32, &ok);
- if (!ok) {
- goto err;
- }
- if (n > nGlyphs) {
- n = nGlyphs;
- }
- stringIdx = 0;
- stringPos = tablePos + 34 + 2*n;
- for (i = 0; i < n; ++i) {
- j = getU16BE(tablePos + 34 + 2*i, &ok);
- if (j < 258) {
- nameToGID->removeInt(macGlyphNames[j]);
- nameToGID->add(new GString(macGlyphNames[j]), i);
- } else {
- j -= 258;
- if (j != stringIdx) {
- for (stringIdx = 0, stringPos = tablePos + 34 + 2*n;
- stringIdx < j;
- ++stringIdx, stringPos += 1 + getU8(stringPos, &ok)) ;
- if (!ok) {
- goto err;
- }
- }
- m = getU8(stringPos, &ok);
- if (!ok || !checkRegion(stringPos + 1, m)) {
- goto err;
- }
- name = new GString((char *)&file[stringPos + 1], m);
- nameToGID->removeInt(name);
- nameToGID->add(name, i);
- ++stringIdx;
- stringPos += 1 + m;
- }
- }
- } else if (postFmt == 0x00028000) {
- nameToGID = new GHash(gTrue);
- for (i = 0; i < nGlyphs; ++i) {
- j = getU8(tablePos + 32 + i, &ok);
- if (!ok) {
- goto err;
- }
- if (j < 258) {
- nameToGID->removeInt(macGlyphNames[j]);
- nameToGID->add(new GString(macGlyphNames[j]), i);
- }
- }
- }
-
- return;
-
- err:
- if (nameToGID) {
- delete nameToGID;
- nameToGID = NULL;
- }
-}
-
-int FoFiTrueType::seekTable(char *tag) {
- Guint tagI;
- int i;
-
- tagI = ((tag[0] & 0xff) << 24) |
- ((tag[1] & 0xff) << 16) |
- ((tag[2] & 0xff) << 8) |
- (tag[3] & 0xff);
- for (i = 0; i < nTables; ++i) {
- if (tables[i].tag == tagI) {
- return i;
- }
- }
- return -1;
-}
+++ /dev/null
-//========================================================================
-//
-// FoFiTrueType.h
-//
-// Copyright 1999-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#ifndef FOFITRUETYPE_H
-#define FOFITRUETYPE_H
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma interface
-#endif
-
-#include "gtypes.h"
-#include "FoFiBase.h"
-
-class GString;
-class GHash;
-struct TrueTypeTable;
-struct TrueTypeCmap;
-
-//------------------------------------------------------------------------
-// FoFiTrueType
-//------------------------------------------------------------------------
-
-class FoFiTrueType: public FoFiBase {
-public:
-
- // Create a FoFiTrueType object from a memory buffer.
- static FoFiTrueType *make(char *fileA, int lenA);
-
- // Create a FoFiTrueType object from a file on disk.
- static FoFiTrueType *load(char *fileName);
-
- virtual ~FoFiTrueType();
-
- // Return the number of cmaps defined by this font.
- int getNumCmaps();
-
- // Return the platform ID of the <i>th cmap.
- int getCmapPlatform(int i);
-
- // Return the encoding ID of the <i>th cmap.
- int getCmapEncoding(int i);
-
- // Return the index of the cmap for <platform>, <encoding>. Returns
- // -1 if there is no corresponding cmap.
- int findCmap(int platform, int encoding);
-
- // Return the GID corresponding to <c> according to the <i>th cmap.
- Gushort mapCodeToGID(int i, int c);
-
- // Returns the GID corresponding to <name> according to the post
- // table. Returns 0 if there is no mapping for <name> or if the
- // font does not have a post table.
- int mapNameToGID(char *name);
-
- // Returns the least restrictive embedding licensing right (as
- // defined by the TrueType spec):
- // * 4: OS/2 table is missing or invalid
- // * 3: installable embedding
- // * 2: editable embedding
- // * 1: preview & print embedding
- // * 0: restricted license embedding
- int getEmbeddingRights();
-
- // Convert to a Type 42 font, suitable for embedding in a PostScript
- // file. <psName> will be used as the PostScript font name (so we
- // don't need to depend on the 'name' table in the font). The
- // <encoding> array specifies the mapping from char codes to names.
- // If <encoding> is NULL, the encoding is unknown or undefined. The
- // <codeToGID> array specifies the mapping from char codes to GIDs.
- void convertToType42(char *psName, char **encoding,
- Gushort *codeToGID,
- FoFiOutputFunc outputFunc, void *outputStream);
-
- // Convert to a Type 2 CIDFont, suitable for embedding in a
- // PostScript file. <psName> will be used as the PostScript font
- // name (so we don't need to depend on the 'name' table in the
- // font). The <cidMap> array maps CIDs to GIDs; it has <nCIDs>
- // entries.
- void convertToCIDType2(char *psName, Gushort *cidMap, int nCIDs,
- GBool needVerticalMetrics,
- FoFiOutputFunc outputFunc, void *outputStream);
-
- // Convert to a Type 0 (but non-CID) composite font, suitable for
- // embedding in a PostScript file. <psName> will be used as the
- // PostScript font name (so we don't need to depend on the 'name'
- // table in the font). The <cidMap> array maps CIDs to GIDs; it has
- // <nCIDs> entries.
- void convertToType0(char *psName, Gushort *cidMap, int nCIDs,
- GBool needVerticalMetrics,
- FoFiOutputFunc outputFunc, void *outputStream);
-
- // Write a clean TTF file, filling in missing tables and correcting
- // various other errors. If <name> is non-NULL, the font is renamed
- // to <name>. If <codeToGID> is non-NULL, the font is re-encoded,
- // using a Windows Unicode cmap. If <name> is NULL and the font is
- // complete and correct, it will be written unmodified.
- void writeTTF(FoFiOutputFunc outputFunc, void *outputStream,
- char *name = NULL, Gushort *codeToGID = NULL);
-
-private:
-
- FoFiTrueType(char *fileA, int lenA, GBool freeFileDataA);
- void cvtEncoding(char **encoding,
- FoFiOutputFunc outputFunc,
- void *outputStream);
- void cvtCharStrings(char **encoding,
- Gushort *codeToGID,
- FoFiOutputFunc outputFunc,
- void *outputStream);
- void cvtSfnts(FoFiOutputFunc outputFunc,
- void *outputStream, GString *name,
- GBool needVerticalMetrics);
- void dumpString(Guchar *s, int length,
- FoFiOutputFunc outputFunc,
- void *outputStream);
- Guint computeTableChecksum(Guchar *data, int length);
- void parse();
- void readPostTable();
- int seekTable(char *tag);
-
- TrueTypeTable *tables;
- int nTables;
- TrueTypeCmap *cmaps;
- int nCmaps;
- int nGlyphs;
- int locaFmt;
- int bbox[4];
- GHash *nameToGID;
-
- GBool parsedOk;
-};
-
-#endif
+++ /dev/null
-//========================================================================
-//
-// FoFiType1.cc
-//
-// Copyright 1999-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma implementation
-#endif
-
-#include <stdlib.h>
-#include <string.h>
-#include "gmem.h"
-#include "FoFiEncodings.h"
-#include "FoFiType1.h"
-
-//------------------------------------------------------------------------
-// FoFiType1
-//------------------------------------------------------------------------
-
-FoFiType1 *FoFiType1::make(char *fileA, int lenA) {
- return new FoFiType1(fileA, lenA, gFalse);
-}
-
-FoFiType1 *FoFiType1::load(char *fileName) {
- char *fileA;
- int lenA;
-
- if (!(fileA = FoFiBase::readFile(fileName, &lenA))) {
- return NULL;
- }
- return new FoFiType1(fileA, lenA, gTrue);
-}
-
-FoFiType1::FoFiType1(char *fileA, int lenA, GBool freeFileDataA):
- FoFiBase(fileA, lenA, freeFileDataA)
-{
- name = NULL;
- encoding = NULL;
- parsed = gFalse;
-}
-
-FoFiType1::~FoFiType1() {
- int i;
-
- if (name) {
- gfree(name);
- }
- if (encoding && encoding != fofiType1StandardEncoding) {
- for (i = 0; i < 256; ++i) {
- gfree(encoding[i]);
- }
- gfree(encoding);
- }
-}
-
-char *FoFiType1::getName() {
- if (!parsed) {
- parse();
- }
- return name;
-}
-
-char **FoFiType1::getEncoding() {
- if (!parsed) {
- parse();
- }
- return encoding;
-}
-
-void FoFiType1::writeEncoded(char **newEncoding,
- FoFiOutputFunc outputFunc, void *outputStream) {
- char buf[512];
- char *line;
- int i;
-
- // copy everything up to the encoding
- for (line = (char *)file;
- line && strncmp(line, "/Encoding", 9);
- line = getNextLine(line)) ;
- if (!line) {
- // no encoding - just copy the whole font file
- (*outputFunc)(outputStream, (char *)file, len);
- return;
- }
- (*outputFunc)(outputStream, (char *)file, line - (char *)file);
-
- // write the new encoding
- (*outputFunc)(outputStream, "/Encoding 256 array\n", 20);
- (*outputFunc)(outputStream,
- "0 1 255 {1 index exch /.notdef put} for\n", 40);
- for (i = 0; i < 256; ++i) {
- if (newEncoding[i]) {
- sprintf(buf, "dup %d /%s put\n", i, newEncoding[i]);
- (*outputFunc)(outputStream, buf, strlen(buf));
- }
- }
- (*outputFunc)(outputStream, "readonly def\n", 13);
-
- // copy everything after the encoding
- if (!strncmp(line, "/Encoding StandardEncoding def", 30)) {
- line = getNextLine(line);
- } else {
- for (line = getNextLine(line);
- line && strncmp(line, "readonly def", 12);
- line = getNextLine(line)) ;
- if (line) {
- line = getNextLine(line);
- }
- }
- if (line) {
- (*outputFunc)(outputStream, line, ((char *)file + len) - line);
- }
-}
-
-char *FoFiType1::getNextLine(char *line) {
- while (line < (char *)file + len && *line != '\x0a' && *line != '\x0d') {
- ++line;
- }
- if (line < (char *)file + len && *line == '\x0d') {
- ++line;
- }
- if (line < (char *)file + len && *line == '\x0a') {
- ++line;
- }
- if (line >= (char *)file + len) {
- return NULL;
- }
- return line;
-}
-
-void FoFiType1::parse() {
- char *line, *line1, *p, *p2;
- char buf[256];
- char c;
- int n, code, i, j;
-
- for (i = 1, line = (char *)file;
- i <= 100 && line && (!name || !encoding);
- ++i) {
-
- // get font name
- if (!name && !strncmp(line, "/FontName", 9)) {
- strncpy(buf, line, 255);
- buf[255] = '\0';
- if ((p = strchr(buf+9, '/')) &&
- (p = strtok(p+1, " \t\n\r"))) {
- name = copyString(p);
- }
- line = getNextLine(line);
-
- // get encoding
- } else if (!encoding &&
- !strncmp(line, "/Encoding StandardEncoding def", 30)) {
- encoding = fofiType1StandardEncoding;
- } else if (!encoding &&
- !strncmp(line, "/Encoding 256 array", 19)) {
- encoding = (char **)gmallocn(256, sizeof(char *));
- for (j = 0; j < 256; ++j) {
- encoding[j] = NULL;
- }
- for (j = 0, line = getNextLine(line);
- j < 300 && line && (line1 = getNextLine(line));
- ++j, line = line1) {
- if ((n = line1 - line) > 255) {
- n = 255;
- }
- strncpy(buf, line, n);
- buf[n] = '\0';
- for (p = buf; *p == ' ' || *p == '\t'; ++p) ;
- if (!strncmp(p, "dup", 3)) {
- for (p += 3; *p == ' ' || *p == '\t'; ++p) ;
- for (p2 = p; *p2 >= '0' && *p2 <= '9'; ++p2) ;
- if (*p2) {
- c = *p2;
- *p2 = '\0';
- if ((code = atoi(p)) < 256) {
- *p2 = c;
- for (p = p2; *p == ' ' || *p == '\t'; ++p) ;
- if (*p == '/') {
- ++p;
- for (p2 = p; *p2 && *p2 != ' ' && *p2 != '\t'; ++p2) ;
- *p2 = '\0';
- encoding[code] = copyString(p);
- }
- }
- }
- } else {
- p = strtok(buf, " \t\n\r");
- if (p)
- {
- if (!strcmp(p, "def")) break;
- if (!strcmp(p, "readonly")) break;
- // the spec does not says this but i'm mantaining old xpdf behaviour that accepts "foo def" as end of the encoding array
- p = strtok(buf, " \t\n\r");
- if (p && !strcmp(p, "def")) break;
- }
- }
- }
- //~ check for getinterval/putinterval junk
-
- } else {
- line = getNextLine(line);
- }
- }
-
- parsed = gTrue;
-}
+++ /dev/null
-//========================================================================
-//
-// FoFiType1.h
-//
-// Copyright 1999-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#ifndef FOFITYPE1_H
-#define FOFITYPE1_H
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma interface
-#endif
-
-#include "gtypes.h"
-#include "FoFiBase.h"
-
-//------------------------------------------------------------------------
-// FoFiType1
-//------------------------------------------------------------------------
-
-class FoFiType1: public FoFiBase {
-public:
-
- // Create a FoFiType1 object from a memory buffer.
- static FoFiType1 *make(char *fileA, int lenA);
-
- // Create a FoFiType1 object from a file on disk.
- static FoFiType1 *load(char *fileName);
-
- virtual ~FoFiType1();
-
- // Return the font name.
- char *getName();
-
- // Return the encoding, as an array of 256 names (any of which may
- // be NULL).
- char **getEncoding();
-
- // Write a version of the Type 1 font file with a new encoding.
- void writeEncoded(char **newEncoding,
- FoFiOutputFunc outputFunc, void *outputStream);
-
-private:
-
- FoFiType1(char *fileA, int lenA, GBool freeFileDataA);
-
- char *getNextLine(char *line);
- void parse();
-
- char *name;
- char **encoding;
- GBool parsed;
-};
-
-#endif
+++ /dev/null
-//========================================================================
-//
-// FoFiType1C.cc
-//
-// Copyright 1999-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma implementation
-#endif
-
-#include <stdlib.h>
-#include <string.h>
-#include <math.h>
-#include "gmem.h"
-#include "GString.h"
-#include "FoFiEncodings.h"
-#include "FoFiType1C.h"
-
-//------------------------------------------------------------------------
-
-static char hexChars[17] = "0123456789ABCDEF";
-
-//------------------------------------------------------------------------
-// FoFiType1C
-//------------------------------------------------------------------------
-
-FoFiType1C *FoFiType1C::make(char *fileA, int lenA) {
- FoFiType1C *ff;
-
- ff = new FoFiType1C(fileA, lenA, gFalse);
- if (!ff->parse()) {
- delete ff;
- return NULL;
- }
- return ff;
-}
-
-FoFiType1C *FoFiType1C::load(char *fileName) {
- FoFiType1C *ff;
- char *fileA;
- int lenA;
-
- if (!(fileA = FoFiBase::readFile(fileName, &lenA))) {
- return NULL;
- }
- ff = new FoFiType1C(fileA, lenA, gTrue);
- if (!ff->parse()) {
- delete ff;
- return NULL;
- }
- return ff;
-}
-
-FoFiType1C::FoFiType1C(char *fileA, int lenA, GBool freeFileDataA):
- FoFiBase(fileA, lenA, freeFileDataA)
-{
- name = NULL;
- encoding = NULL;
- privateDicts = NULL;
- fdSelect = NULL;
- charset = NULL;
-}
-
-FoFiType1C::~FoFiType1C() {
- int i;
-
- if (name) {
- delete name;
- }
- if (encoding &&
- encoding != fofiType1StandardEncoding &&
- encoding != fofiType1ExpertEncoding) {
- for (i = 0; i < 256; ++i) {
- gfree(encoding[i]);
- }
- gfree(encoding);
- }
- if (privateDicts) {
- gfree(privateDicts);
- }
- if (fdSelect) {
- gfree(fdSelect);
- }
- if (charset &&
- charset != fofiType1CISOAdobeCharset &&
- charset != fofiType1CExpertCharset &&
- charset != fofiType1CExpertSubsetCharset) {
- gfree(charset);
- }
-}
-
-char *FoFiType1C::getName() {
- return name ? name->getCString() : (char *)NULL;
-}
-
-char **FoFiType1C::getEncoding() {
- return encoding;
-}
-
-Gushort *FoFiType1C::getCIDToGIDMap(int *nCIDs) {
- Gushort *map;
- int n, i;
-
- // a CID font's top dict has ROS as the first operator
- if (topDict.firstOp != 0x0c1e) {
- *nCIDs = 0;
- return NULL;
- }
-
- // in a CID font, the charset data is the GID-to-CID mapping, so all
- // we have to do is reverse it
- n = 0;
- for (i = 0; i < nGlyphs; ++i) {
- if (charset[i] > n) {
- n = charset[i];
- }
- }
- ++n;
- map = (Gushort *)gmallocn(n, sizeof(Gushort));
- memset(map, 0, n * sizeof(Gushort));
- for (i = 0; i < nGlyphs; ++i) {
- map[charset[i]] = i;
- }
- *nCIDs = n;
- return map;
-}
-
-void FoFiType1C::convertToType1(char **newEncoding, GBool ascii,
- FoFiOutputFunc outputFunc,
- void *outputStream) {
- Type1CEexecBuf eb;
- Type1CIndex subrIdx;
- Type1CIndexVal val;
- char buf[512];
- char **enc;
- GBool ok;
- int i;
-
- // write header and font dictionary, up to encoding
- ok = gTrue;
- (*outputFunc)(outputStream, "%!FontType1-1.0: ", 17);
- (*outputFunc)(outputStream, name->getCString(), name->getLength());
- if (topDict.versionSID != 0) {
- getString(topDict.versionSID, buf, &ok);
- (*outputFunc)(outputStream, buf, strlen(buf));
- }
- (*outputFunc)(outputStream, "\n", 1);
- // the dictionary needs room for 12 entries: the following 9, plus
- // Private and CharStrings (in the eexec section) and FID (which is
- // added by definefont)
- (*outputFunc)(outputStream, "12 dict begin\n", 14);
- (*outputFunc)(outputStream, "/FontInfo 10 dict dup begin\n", 28);
- if (topDict.versionSID != 0) {
- (*outputFunc)(outputStream, "/version (", 10);
- (*outputFunc)(outputStream, buf, strlen(buf));
- (*outputFunc)(outputStream, ") readonly def\n", 15);
- }
- if (topDict.noticeSID != 0) {
- getString(topDict.noticeSID, buf, &ok);
- (*outputFunc)(outputStream, "/Notice (", 9);
- (*outputFunc)(outputStream, buf, strlen(buf));
- (*outputFunc)(outputStream, ") readonly def\n", 15);
- }
- if (topDict.copyrightSID != 0) {
- getString(topDict.copyrightSID, buf, &ok);
- (*outputFunc)(outputStream, "/Copyright (", 12);
- (*outputFunc)(outputStream, buf, strlen(buf));
- (*outputFunc)(outputStream, ") readonly def\n", 15);
- }
- if (topDict.fullNameSID != 0) {
- getString(topDict.fullNameSID, buf, &ok);
- (*outputFunc)(outputStream, "/FullName (", 11);
- (*outputFunc)(outputStream, buf, strlen(buf));
- (*outputFunc)(outputStream, ") readonly def\n", 15);
- }
- if (topDict.familyNameSID != 0) {
- getString(topDict.familyNameSID, buf, &ok);
- (*outputFunc)(outputStream, "/FamilyName (", 13);
- (*outputFunc)(outputStream, buf, strlen(buf));
- (*outputFunc)(outputStream, ") readonly def\n", 15);
- }
- if (topDict.weightSID != 0) {
- getString(topDict.weightSID, buf, &ok);
- (*outputFunc)(outputStream, "/Weight (", 9);
- (*outputFunc)(outputStream, buf, strlen(buf));
- (*outputFunc)(outputStream, ") readonly def\n", 15);
- }
- if (topDict.isFixedPitch) {
- (*outputFunc)(outputStream, "/isFixedPitch true def\n", 23);
- } else {
- (*outputFunc)(outputStream, "/isFixedPitch false def\n", 24);
- }
- sprintf(buf, "/ItalicAngle %g def\n", topDict.italicAngle);
- (*outputFunc)(outputStream, buf, strlen(buf));
- sprintf(buf, "/UnderlinePosition %g def\n", topDict.underlinePosition);
- (*outputFunc)(outputStream, buf, strlen(buf));
- sprintf(buf, "/UnderlineThickness %g def\n", topDict.underlineThickness);
- (*outputFunc)(outputStream, buf, strlen(buf));
- (*outputFunc)(outputStream, "end readonly def\n", 17);
- (*outputFunc)(outputStream, "/FontName /", 11);
- (*outputFunc)(outputStream, name->getCString(), name->getLength());
- (*outputFunc)(outputStream, " def\n", 5);
- sprintf(buf, "/PaintType %d def\n", topDict.paintType);
- (*outputFunc)(outputStream, buf, strlen(buf));
- (*outputFunc)(outputStream, "/FontType 1 def\n", 16);
- sprintf(buf, "/FontMatrix [%g %g %g %g %g %g] readonly def\n",
- topDict.fontMatrix[0], topDict.fontMatrix[1], topDict.fontMatrix[2],
- topDict.fontMatrix[3], topDict.fontMatrix[4], topDict.fontMatrix[5]);
- (*outputFunc)(outputStream, buf, strlen(buf));
- sprintf(buf, "/FontBBox [%g %g %g %g] readonly def\n",
- topDict.fontBBox[0], topDict.fontBBox[1],
- topDict.fontBBox[2], topDict.fontBBox[3]);
- (*outputFunc)(outputStream, buf, strlen(buf));
- sprintf(buf, "/StrokeWidth %g def\n", topDict.strokeWidth);
- (*outputFunc)(outputStream, buf, strlen(buf));
- if (topDict.uniqueID != 0) {
- sprintf(buf, "/UniqueID %d def\n", topDict.uniqueID);
- (*outputFunc)(outputStream, buf, strlen(buf));
- }
-
- // write the encoding
- (*outputFunc)(outputStream, "/Encoding ", 10);
- if (!newEncoding && encoding == fofiType1StandardEncoding) {
- (*outputFunc)(outputStream, "StandardEncoding def\n", 21);
- } else {
- (*outputFunc)(outputStream, "256 array\n", 10);
- (*outputFunc)(outputStream,
- "0 1 255 {1 index exch /.notdef put} for\n", 40);
- enc = newEncoding ? newEncoding : encoding;
- if(!enc) {
- fprintf(stderr, "convertToType1: Warning: No Encoding\n");
- }
- for (i = 0; i < 256; ++i) {
- if (enc && enc[i]) {
- sprintf(buf, "dup %d /%s put\n", i, enc[i]);
- (*outputFunc)(outputStream, buf, strlen(buf));
- }
- }
- (*outputFunc)(outputStream, "readonly def\n", 13);
- }
- (*outputFunc)(outputStream, "currentdict end\n", 16);
-
- // start the binary section
- (*outputFunc)(outputStream, "currentfile eexec\n", 18);
- eb.outputFunc = outputFunc;
- eb.outputStream = outputStream;
- eb.ascii = ascii;
- eb.r1 = 55665;
- eb.line = 0;
-
- // write the private dictionary
- eexecWrite(&eb, "\x83\xca\x73\xd5");
- eexecWrite(&eb, "dup /Private 32 dict dup begin\n");
- eexecWrite(&eb, "/RD {string currentfile exch readstring pop}"
- " executeonly def\n");
- eexecWrite(&eb, "/ND {noaccess def} executeonly def\n");
- eexecWrite(&eb, "/NP {noaccess put} executeonly def\n");
- eexecWrite(&eb, "/MinFeature {16 16} def\n");
- eexecWrite(&eb, "/password 5839 def\n");
- if (privateDicts[0].nBlueValues) {
- eexecWrite(&eb, "/BlueValues [");
- for (i = 0; i < privateDicts[0].nBlueValues; ++i) {
- sprintf(buf, "%s%d", i > 0 ? " " : "", privateDicts[0].blueValues[i]);
- eexecWrite(&eb, buf);
- }
- eexecWrite(&eb, "] def\n");
- }
- if (privateDicts[0].nOtherBlues) {
- eexecWrite(&eb, "/OtherBlues [");
- for (i = 0; i < privateDicts[0].nOtherBlues; ++i) {
- sprintf(buf, "%s%d", i > 0 ? " " : "", privateDicts[0].otherBlues[i]);
- eexecWrite(&eb, buf);
- }
- eexecWrite(&eb, "] def\n");
- }
- if (privateDicts[0].nFamilyBlues) {
- eexecWrite(&eb, "/FamilyBlues [");
- for (i = 0; i < privateDicts[0].nFamilyBlues; ++i) {
- sprintf(buf, "%s%d", i > 0 ? " " : "", privateDicts[0].familyBlues[i]);
- eexecWrite(&eb, buf);
- }
- eexecWrite(&eb, "] def\n");
- }
- if (privateDicts[0].nFamilyOtherBlues) {
- eexecWrite(&eb, "/FamilyOtherBlues [");
- for (i = 0; i < privateDicts[0].nFamilyOtherBlues; ++i) {
- sprintf(buf, "%s%d", i > 0 ? " " : "",
- privateDicts[0].familyOtherBlues[i]);
- eexecWrite(&eb, buf);
- }
- eexecWrite(&eb, "] def\n");
- }
- if (privateDicts[0].blueScale != 0.039625) {
- sprintf(buf, "/BlueScale %g def\n", privateDicts[0].blueScale);
- eexecWrite(&eb, buf);
- }
- if (privateDicts[0].blueShift != 7) {
- sprintf(buf, "/BlueShift %d def\n", privateDicts[0].blueShift);
- eexecWrite(&eb, buf);
- }
- if (privateDicts[0].blueFuzz != 1) {
- sprintf(buf, "/BlueFuzz %d def\n", privateDicts[0].blueFuzz);
- eexecWrite(&eb, buf);
- }
- if (privateDicts[0].hasStdHW) {
- sprintf(buf, "/StdHW [%g] def\n", privateDicts[0].stdHW);
- eexecWrite(&eb, buf);
- }
- if (privateDicts[0].hasStdVW) {
- sprintf(buf, "/StdVW [%g] def\n", privateDicts[0].stdVW);
- eexecWrite(&eb, buf);
- }
- if (privateDicts[0].nStemSnapH) {
- eexecWrite(&eb, "/StemSnapH [");
- for (i = 0; i < privateDicts[0].nStemSnapH; ++i) {
- sprintf(buf, "%s%g", i > 0 ? " " : "", privateDicts[0].stemSnapH[i]);
- eexecWrite(&eb, buf);
- }
- eexecWrite(&eb, "] def\n");
- }
- if (privateDicts[0].nStemSnapV) {
- eexecWrite(&eb, "/StemSnapV [");
- for (i = 0; i < privateDicts[0].nStemSnapV; ++i) {
- sprintf(buf, "%s%g", i > 0 ? " " : "", privateDicts[0].stemSnapV[i]);
- eexecWrite(&eb, buf);
- }
- eexecWrite(&eb, "] def\n");
- }
- if (privateDicts[0].hasForceBold) {
- sprintf(buf, "/ForceBold %s def\n",
- privateDicts[0].forceBold ? "true" : "false");
- eexecWrite(&eb, buf);
- }
- if (privateDicts[0].forceBoldThreshold != 0) {
- sprintf(buf, "/ForceBoldThreshold %g def\n",
- privateDicts[0].forceBoldThreshold);
- eexecWrite(&eb, buf);
- }
- if (privateDicts[0].languageGroup != 0) {
- sprintf(buf, "/LanguageGroup %d def\n", privateDicts[0].languageGroup);
- eexecWrite(&eb, buf);
- }
- if (privateDicts[0].expansionFactor != 0.06) {
- sprintf(buf, "/ExpansionFactor %g def\n", privateDicts[0].expansionFactor);
- eexecWrite(&eb, buf);
- }
-
- // set up subroutines
- ok = gTrue;
- getIndex(privateDicts[0].subrsOffset, &subrIdx, &ok);
- if (!ok) {
- subrIdx.pos = -1;
- }
-
- // write the CharStrings
- sprintf(buf, "2 index /CharStrings %d dict dup begin\n", nGlyphs);
- eexecWrite(&eb, buf);
- for (i = 0; i < nGlyphs; ++i) {
- ok = gTrue;
- getIndexVal(&charStringsIdx, i, &val, &ok);
- if (ok) {
- getString(charset[i], buf, &ok);
- if (ok) {
- eexecCvtGlyph(&eb, buf, val.pos, val.len, &subrIdx, &privateDicts[0]);
- }
- }
- }
- eexecWrite(&eb, "end\n");
- eexecWrite(&eb, "end\n");
- eexecWrite(&eb, "readonly put\n");
- eexecWrite(&eb, "noaccess put\n");
- eexecWrite(&eb, "dup /FontName get exch definefont pop\n");
- eexecWrite(&eb, "mark currentfile closefile\n");
-
- // trailer
- if (ascii && eb.line > 0) {
- (*outputFunc)(outputStream, "\n", 1);
- }
- for (i = 0; i < 8; ++i) {
- (*outputFunc)(outputStream, "0000000000000000000000000000000000000000000000000000000000000000\n", 65);
- }
- (*outputFunc)(outputStream, "cleartomark\n", 12);
-}
-
-void FoFiType1C::convertToCIDType0(char *psName,
- FoFiOutputFunc outputFunc,
- void *outputStream) {
- int *cidMap;
- GString *charStrings;
- int *charStringOffsets;
- Type1CIndex subrIdx;
- Type1CIndexVal val;
- int nCIDs, gdBytes;
- char buf[512], buf2[512];
- GBool ok;
- int gid, offset, n, i, j, k;
-
- // compute the CID count and build the CID-to-GID mapping
- nCIDs = 0;
- for (i = 0; i < nGlyphs; ++i) {
- if (charset[i] >= nCIDs) {
- nCIDs = charset[i] + 1;
- }
- }
- cidMap = (int *)gmallocn(nCIDs, sizeof(int));
- for (i = 0; i < nCIDs; ++i) {
- cidMap[i] = -1;
- }
- for (i = 0; i < nGlyphs; ++i) {
- cidMap[charset[i]] = i;
- }
-
- // build the charstrings
- charStrings = new GString();
- charStringOffsets = (int *)gmallocn(nCIDs + 1, sizeof(int));
- for (i = 0; i < nCIDs; ++i) {
- charStringOffsets[i] = charStrings->getLength();
- if ((gid = cidMap[i]) >= 0) {
- ok = gTrue;
- getIndexVal(&charStringsIdx, gid, &val, &ok);
- if (ok) {
- getIndex(privateDicts[fdSelect[gid]].subrsOffset, &subrIdx, &ok);
- if (!ok) {
- subrIdx.pos = -1;
- }
- cvtGlyph(val.pos, val.len, charStrings,
- &subrIdx, &privateDicts[fdSelect[gid]], gTrue);
- }
- }
- }
- charStringOffsets[nCIDs] = charStrings->getLength();
-
- // compute gdBytes = number of bytes needed for charstring offsets
- // (offset size needs to account for the charstring offset table,
- // with a worst case of five bytes per entry, plus the charstrings
- // themselves)
- i = (nCIDs + 1) * 5 + charStrings->getLength();
- if (i < 0x100) {
- gdBytes = 1;
- } else if (i < 0x10000) {
- gdBytes = 2;
- } else if (i < 0x1000000) {
- gdBytes = 3;
- } else {
- gdBytes = 4;
- }
-
- // begin the font dictionary
- (*outputFunc)(outputStream, "/CIDInit /ProcSet findresource begin\n", 37);
- (*outputFunc)(outputStream, "20 dict begin\n", 14);
- (*outputFunc)(outputStream, "/CIDFontName /", 14);
- (*outputFunc)(outputStream, psName, strlen(psName));
- (*outputFunc)(outputStream, " def\n", 5);
- (*outputFunc)(outputStream, "/CIDFontType 0 def\n", 19);
- (*outputFunc)(outputStream, "/CIDSystemInfo 3 dict dup begin\n", 32);
- if (topDict.registrySID > 0 && topDict.orderingSID > 0) {
- ok = gTrue;
- getString(topDict.registrySID, buf, &ok);
- if (ok) {
- (*outputFunc)(outputStream, " /Registry (", 13);
- (*outputFunc)(outputStream, buf, strlen(buf));
- (*outputFunc)(outputStream, ") def\n", 6);
- }
- ok = gTrue;
- getString(topDict.orderingSID, buf, &ok);
- if (ok) {
- (*outputFunc)(outputStream, " /Ordering (", 13);
- (*outputFunc)(outputStream, buf, strlen(buf));
- (*outputFunc)(outputStream, ") def\n", 6);
- }
- } else {
- (*outputFunc)(outputStream, " /Registry (Adobe) def\n", 24);
- (*outputFunc)(outputStream, " /Ordering (Identity) def\n", 27);
- }
- sprintf(buf, " /Supplement %d def\n", topDict.supplement);
- (*outputFunc)(outputStream, buf, strlen(buf));
- (*outputFunc)(outputStream, "end def\n", 8);
- if (topDict.hasFontMatrix) {
- sprintf(buf, "/FontMatrix [%g %g %g %g %g %g] def\n",
- topDict.fontMatrix[0], topDict.fontMatrix[1],
- topDict.fontMatrix[2], topDict.fontMatrix[3],
- topDict.fontMatrix[4], topDict.fontMatrix[5]);
- (*outputFunc)(outputStream, buf, strlen(buf));
- } else if (privateDicts[0].hasFontMatrix) {
- (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
- } else {
- (*outputFunc)(outputStream,
- "/FontMatrix [0.001 0 0 0.001 0 0] def\n", 38);
- }
- sprintf(buf, "/FontBBox [%g %g %g %g] def\n",
- topDict.fontBBox[0], topDict.fontBBox[1],
- topDict.fontBBox[2], topDict.fontBBox[3]);
- (*outputFunc)(outputStream, buf, strlen(buf));
- (*outputFunc)(outputStream, "/FontInfo 1 dict dup begin\n", 27);
- (*outputFunc)(outputStream, " /FSType 8 def\n", 16);
- (*outputFunc)(outputStream, "end def\n", 8);
-
- // CIDFont-specific entries
- sprintf(buf, "/CIDCount %d def\n", nCIDs);
- (*outputFunc)(outputStream, buf, strlen(buf));
- (*outputFunc)(outputStream, "/FDBytes 1 def\n", 15);
- sprintf(buf, "/GDBytes %d def\n", gdBytes);
- (*outputFunc)(outputStream, buf, strlen(buf));
- (*outputFunc)(outputStream, "/CIDMapOffset 0 def\n", 20);
- if (topDict.paintType != 0) {
- sprintf(buf, "/PaintType %d def\n", topDict.paintType);
- (*outputFunc)(outputStream, buf, strlen(buf));
- sprintf(buf, "/StrokeWidth %g def\n", topDict.strokeWidth);
- (*outputFunc)(outputStream, buf, strlen(buf));
- }
-
- // FDArray entry
- sprintf(buf, "/FDArray %d array\n", nFDs);
- (*outputFunc)(outputStream, buf, strlen(buf));
- for (i = 0; i < nFDs; ++i) {
- sprintf(buf, "dup %d 10 dict begin\n", i);
- (*outputFunc)(outputStream, buf, strlen(buf));
- (*outputFunc)(outputStream, "/FontType 1 def\n", 16);
- if (privateDicts[i].hasFontMatrix) {
- sprintf(buf, "/FontMatrix [%g %g %g %g %g %g] def\n",
- privateDicts[i].fontMatrix[0],
- privateDicts[i].fontMatrix[1],
- privateDicts[i].fontMatrix[2],
- privateDicts[i].fontMatrix[3],
- privateDicts[i].fontMatrix[4],
- privateDicts[i].fontMatrix[5]);
- (*outputFunc)(outputStream, buf, strlen(buf));
- } else {
- (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
- }
- sprintf(buf, "/PaintType %d def\n", topDict.paintType);
- (*outputFunc)(outputStream, buf, strlen(buf));
- (*outputFunc)(outputStream, "/Private 32 dict begin\n", 23);
- if (privateDicts[i].nBlueValues) {
- (*outputFunc)(outputStream, "/BlueValues [", 13);
- for (j = 0; j < privateDicts[i].nBlueValues; ++j) {
- sprintf(buf, "%s%d", j > 0 ? " " : "", privateDicts[i].blueValues[j]);
- (*outputFunc)(outputStream, buf, strlen(buf));
- }
- (*outputFunc)(outputStream, "] def\n", 6);
- }
- if (privateDicts[i].nOtherBlues) {
- (*outputFunc)(outputStream, "/OtherBlues [", 13);
- for (j = 0; j < privateDicts[i].nOtherBlues; ++j) {
- sprintf(buf, "%s%d", j > 0 ? " " : "", privateDicts[i].otherBlues[j]);
- (*outputFunc)(outputStream, buf, strlen(buf));
- }
- (*outputFunc)(outputStream, "] def\n", 6);
- }
- if (privateDicts[i].nFamilyBlues) {
- (*outputFunc)(outputStream, "/FamilyBlues [", 14);
- for (j = 0; j < privateDicts[i].nFamilyBlues; ++j) {
- sprintf(buf, "%s%d", j > 0 ? " " : "", privateDicts[i].familyBlues[j]);
- (*outputFunc)(outputStream, buf, strlen(buf));
- }
- (*outputFunc)(outputStream, "] def\n", 6);
- }
- if (privateDicts[i].nFamilyOtherBlues) {
- (*outputFunc)(outputStream, "/FamilyOtherBlues [", 19);
- for (j = 0; j < privateDicts[i].nFamilyOtherBlues; ++j) {
- sprintf(buf, "%s%d", j > 0 ? " " : "",
- privateDicts[i].familyOtherBlues[j]);
- (*outputFunc)(outputStream, buf, strlen(buf));
- }
- (*outputFunc)(outputStream, "] def\n", 6);
- }
- if (privateDicts[i].blueScale != 0.039625) {
- sprintf(buf, "/BlueScale %g def\n", privateDicts[i].blueScale);
- (*outputFunc)(outputStream, buf, strlen(buf));
- }
- if (privateDicts[i].blueShift != 7) {
- sprintf(buf, "/BlueShift %d def\n", privateDicts[i].blueShift);
- (*outputFunc)(outputStream, buf, strlen(buf));
- }
- if (privateDicts[i].blueFuzz != 1) {
- sprintf(buf, "/BlueFuzz %d def\n", privateDicts[i].blueFuzz);
- (*outputFunc)(outputStream, buf, strlen(buf));
- }
- if (privateDicts[i].hasStdHW) {
- sprintf(buf, "/StdHW [%g] def\n", privateDicts[i].stdHW);
- (*outputFunc)(outputStream, buf, strlen(buf));
- }
- if (privateDicts[i].hasStdVW) {
- sprintf(buf, "/StdVW [%g] def\n", privateDicts[i].stdVW);
- (*outputFunc)(outputStream, buf, strlen(buf));
- }
- if (privateDicts[i].nStemSnapH) {
- (*outputFunc)(outputStream, "/StemSnapH [", 12);
- for (j = 0; j < privateDicts[i].nStemSnapH; ++j) {
- sprintf(buf, "%s%g", j > 0 ? " " : "", privateDicts[i].stemSnapH[j]);
- (*outputFunc)(outputStream, buf, strlen(buf));
- }
- (*outputFunc)(outputStream, "] def\n", 6);
- }
- if (privateDicts[i].nStemSnapV) {
- (*outputFunc)(outputStream, "/StemSnapV [", 12);
- for (j = 0; j < privateDicts[i].nStemSnapV; ++j) {
- sprintf(buf, "%s%g", j > 0 ? " " : "", privateDicts[i].stemSnapV[j]);
- (*outputFunc)(outputStream, buf, strlen(buf));
- }
- (*outputFunc)(outputStream, "] def\n", 6);
- }
- if (privateDicts[i].hasForceBold) {
- sprintf(buf, "/ForceBold %s def\n",
- privateDicts[i].forceBold ? "true" : "false");
- (*outputFunc)(outputStream, buf, strlen(buf));
- }
- if (privateDicts[i].forceBoldThreshold != 0) {
- sprintf(buf, "/ForceBoldThreshold %g def\n",
- privateDicts[i].forceBoldThreshold);
- (*outputFunc)(outputStream, buf, strlen(buf));
- }
- if (privateDicts[i].languageGroup != 0) {
- sprintf(buf, "/LanguageGroup %d def\n", privateDicts[i].languageGroup);
- (*outputFunc)(outputStream, buf, strlen(buf));
- }
- if (privateDicts[i].expansionFactor != 0.06) {
- sprintf(buf, "/ExpansionFactor %g def\n",
- privateDicts[i].expansionFactor);
- (*outputFunc)(outputStream, buf, strlen(buf));
- }
- (*outputFunc)(outputStream, "currentdict end def\n", 20);
- (*outputFunc)(outputStream, "currentdict end put\n", 20);
- }
- (*outputFunc)(outputStream, "def\n", 4);
-
- // start the binary section
- offset = (nCIDs + 1) * (1 + gdBytes);
- sprintf(buf, "(Hex) %d StartData\n",
- offset + charStrings->getLength());
- (*outputFunc)(outputStream, buf, strlen(buf));
-
- // write the charstring offset (CIDMap) table
- for (i = 0; i <= nCIDs; i += 6) {
- for (j = 0; j < 6 && i+j <= nCIDs; ++j) {
- if (i+j < nCIDs && cidMap[i+j] >= 0) {
- buf[0] = (char)fdSelect[cidMap[i+j]];
- } else {
- buf[0] = (char)0;
- }
- n = offset + charStringOffsets[i+j];
- for (k = gdBytes; k >= 1; --k) {
- buf[k] = (char)(n & 0xff);
- n >>= 8;
- }
- for (k = 0; k <= gdBytes; ++k) {
- sprintf(buf2, "%02x", buf[k] & 0xff);
- (*outputFunc)(outputStream, buf2, 2);
- }
- }
- (*outputFunc)(outputStream, "\n", 1);
- }
-
- // write the charstring data
- n = charStrings->getLength();
- for (i = 0; i < n; i += 32) {
- for (j = 0; j < 32 && i+j < n; ++j) {
- sprintf(buf, "%02x", charStrings->getChar(i+j) & 0xff);
- (*outputFunc)(outputStream, buf, strlen(buf));
- }
- if (i + 32 >= n) {
- (*outputFunc)(outputStream, ">", 1);
- }
- (*outputFunc)(outputStream, "\n", 1);
- }
-
- gfree(charStringOffsets);
- delete charStrings;
- gfree(cidMap);
-}
-
-void FoFiType1C::convertToType0(char *psName,
- FoFiOutputFunc outputFunc,
- void *outputStream) {
- int *cidMap;
- Type1CIndex subrIdx;
- Type1CIndexVal val;
- int nCIDs;
- char buf[512];
- Type1CEexecBuf eb;
- GBool ok;
- int fd, i, j, k;
-
- // compute the CID count and build the CID-to-GID mapping
- nCIDs = 0;
- for (i = 0; i < nGlyphs; ++i) {
- if (charset[i] >= nCIDs) {
- nCIDs = charset[i] + 1;
- }
- }
- cidMap = (int *)gmallocn(nCIDs, sizeof(int));
- for (i = 0; i < nCIDs; ++i) {
- cidMap[i] = -1;
- }
- for (i = 0; i < nGlyphs; ++i) {
- cidMap[charset[i]] = i;
- }
-
- // write the descendant Type 1 fonts
- for (i = 0; i < nCIDs; i += 256) {
-
- //~ this assumes that all CIDs in this block have the same FD --
- //~ to handle multiple FDs correctly, need to somehow divide the
- //~ font up by FD
- fd = 0;
- for (j = 0; j < 256 && i+j < nCIDs; ++j) {
- if (cidMap[i+j] >= 0) {
- fd = fdSelect[cidMap[i+j]];
- break;
- }
- }
-
- // font dictionary (unencrypted section)
- (*outputFunc)(outputStream, "16 dict begin\n", 14);
- (*outputFunc)(outputStream, "/FontName /", 11);
- (*outputFunc)(outputStream, psName, strlen(psName));
- sprintf(buf, "_%02x def\n", i >> 8);
- (*outputFunc)(outputStream, buf, strlen(buf));
- (*outputFunc)(outputStream, "/FontType 1 def\n", 16);
- if (privateDicts[fd].hasFontMatrix) {
- sprintf(buf, "/FontMatrix [%g %g %g %g %g %g] def\n",
- privateDicts[fd].fontMatrix[0],
- privateDicts[fd].fontMatrix[1],
- privateDicts[fd].fontMatrix[2],
- privateDicts[fd].fontMatrix[3],
- privateDicts[fd].fontMatrix[4],
- privateDicts[fd].fontMatrix[5]);
- (*outputFunc)(outputStream, buf, strlen(buf));
- } else if (topDict.hasFontMatrix) {
- (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
- } else {
- (*outputFunc)(outputStream,
- "/FontMatrix [0.001 0 0 0.001 0 0] def\n", 38);
- }
- sprintf(buf, "/FontBBox [%g %g %g %g] def\n",
- topDict.fontBBox[0], topDict.fontBBox[1],
- topDict.fontBBox[2], topDict.fontBBox[3]);
- (*outputFunc)(outputStream, buf, strlen(buf));
- sprintf(buf, "/PaintType %d def\n", topDict.paintType);
- (*outputFunc)(outputStream, buf, strlen(buf));
- if (topDict.paintType != 0) {
- sprintf(buf, "/StrokeWidth %g def\n", topDict.strokeWidth);
- (*outputFunc)(outputStream, buf, strlen(buf));
- }
- (*outputFunc)(outputStream, "/Encoding 256 array\n", 20);
- for (j = 0; j < 256 && i+j < nCIDs; ++j) {
- sprintf(buf, "dup %d /c%02x put\n", j, j);
- (*outputFunc)(outputStream, buf, strlen(buf));
- }
- if (j < 256) {
- sprintf(buf, "%d 1 255 { 1 index exch /.notdef put } for\n", j);
- (*outputFunc)(outputStream, buf, strlen(buf));
- }
- (*outputFunc)(outputStream, "readonly def\n", 13);
- (*outputFunc)(outputStream, "currentdict end\n", 16);
-
- // start the binary section
- (*outputFunc)(outputStream, "currentfile eexec\n", 18);
- eb.outputFunc = outputFunc;
- eb.outputStream = outputStream;
- eb.ascii = gTrue;
- eb.r1 = 55665;
- eb.line = 0;
-
- // start the private dictionary
- eexecWrite(&eb, "\x83\xca\x73\xd5");
- eexecWrite(&eb, "dup /Private 32 dict dup begin\n");
- eexecWrite(&eb, "/RD {string currentfile exch readstring pop}"
- " executeonly def\n");
- eexecWrite(&eb, "/ND {noaccess def} executeonly def\n");
- eexecWrite(&eb, "/NP {noaccess put} executeonly def\n");
- eexecWrite(&eb, "/MinFeature {16 16} def\n");
- eexecWrite(&eb, "/password 5839 def\n");
- if (privateDicts[fd].nBlueValues) {
- eexecWrite(&eb, "/BlueValues [");
- for (k = 0; k < privateDicts[fd].nBlueValues; ++k) {
- sprintf(buf, "%s%d", k > 0 ? " " : "", privateDicts[fd].blueValues[k]);
- eexecWrite(&eb, buf);
- }
- eexecWrite(&eb, "] def\n");
- }
- if (privateDicts[fd].nOtherBlues) {
- eexecWrite(&eb, "/OtherBlues [");
- for (k = 0; k < privateDicts[fd].nOtherBlues; ++k) {
- sprintf(buf, "%s%d", k > 0 ? " " : "", privateDicts[fd].otherBlues[k]);
- eexecWrite(&eb, buf);
- }
- eexecWrite(&eb, "] def\n");
- }
- if (privateDicts[fd].nFamilyBlues) {
- eexecWrite(&eb, "/FamilyBlues [");
- for (k = 0; k < privateDicts[fd].nFamilyBlues; ++k) {
- sprintf(buf, "%s%d", k > 0 ? " " : "",
- privateDicts[fd].familyBlues[k]);
- eexecWrite(&eb, buf);
- }
- eexecWrite(&eb, "] def\n");
- }
- if (privateDicts[fd].nFamilyOtherBlues) {
- eexecWrite(&eb, "/FamilyOtherBlues [");
- for (k = 0; k < privateDicts[fd].nFamilyOtherBlues; ++k) {
- sprintf(buf, "%s%d", k > 0 ? " " : "",
- privateDicts[fd].familyOtherBlues[k]);
- eexecWrite(&eb, buf);
- }
- eexecWrite(&eb, "] def\n");
- }
- if (privateDicts[fd].blueScale != 0.039625) {
- sprintf(buf, "/BlueScale %g def\n", privateDicts[fd].blueScale);
- eexecWrite(&eb, buf);
- }
- if (privateDicts[fd].blueShift != 7) {
- sprintf(buf, "/BlueShift %d def\n", privateDicts[fd].blueShift);
- eexecWrite(&eb, buf);
- }
- if (privateDicts[fd].blueFuzz != 1) {
- sprintf(buf, "/BlueFuzz %d def\n", privateDicts[fd].blueFuzz);
- eexecWrite(&eb, buf);
- }
- if (privateDicts[fd].hasStdHW) {
- sprintf(buf, "/StdHW [%g] def\n", privateDicts[fd].stdHW);
- eexecWrite(&eb, buf);
- }
- if (privateDicts[fd].hasStdVW) {
- sprintf(buf, "/StdVW [%g] def\n", privateDicts[fd].stdVW);
- eexecWrite(&eb, buf);
- }
- if (privateDicts[fd].nStemSnapH) {
- eexecWrite(&eb, "/StemSnapH [");
- for (k = 0; k < privateDicts[fd].nStemSnapH; ++k) {
- sprintf(buf, "%s%g", k > 0 ? " " : "", privateDicts[fd].stemSnapH[k]);
- eexecWrite(&eb, buf);
- }
- eexecWrite(&eb, "] def\n");
- }
- if (privateDicts[fd].nStemSnapV) {
- eexecWrite(&eb, "/StemSnapV [");
- for (k = 0; k < privateDicts[fd].nStemSnapV; ++k) {
- sprintf(buf, "%s%g", k > 0 ? " " : "", privateDicts[fd].stemSnapV[k]);
- eexecWrite(&eb, buf);
- }
- eexecWrite(&eb, "] def\n");
- }
- if (privateDicts[fd].hasForceBold) {
- sprintf(buf, "/ForceBold %s def\n",
- privateDicts[fd].forceBold ? "true" : "false");
- eexecWrite(&eb, buf);
- }
- if (privateDicts[fd].forceBoldThreshold != 0) {
- sprintf(buf, "/ForceBoldThreshold %g def\n",
- privateDicts[fd].forceBoldThreshold);
- eexecWrite(&eb, buf);
- }
- if (privateDicts[fd].languageGroup != 0) {
- sprintf(buf, "/LanguageGroup %d def\n", privateDicts[fd].languageGroup);
- eexecWrite(&eb, buf);
- }
- if (privateDicts[fd].expansionFactor != 0.06) {
- sprintf(buf, "/ExpansionFactor %g def\n",
- privateDicts[fd].expansionFactor);
- eexecWrite(&eb, buf);
- }
-
- // set up the subroutines
- ok = gTrue;
- getIndex(privateDicts[fd].subrsOffset, &subrIdx, &ok);
- if (!ok) {
- subrIdx.pos = -1;
- }
-
- // start the CharStrings
- sprintf(buf, "2 index /CharStrings 256 dict dup begin\n");
- eexecWrite(&eb, buf);
-
- // write the .notdef CharString
- ok = gTrue;
- getIndexVal(&charStringsIdx, 0, &val, &ok);
- if (ok) {
- eexecCvtGlyph(&eb, ".notdef", val.pos, val.len,
- &subrIdx, &privateDicts[fd]);
- }
-
- // write the CharStrings
- for (j = 0; j < 256 && i+j < nCIDs; ++j) {
- if (cidMap[i+j] >= 0) {
- ok = gTrue;
- getIndexVal(&charStringsIdx, cidMap[i+j], &val, &ok);
- if (ok) {
- sprintf(buf, "c%02x", j);
- eexecCvtGlyph(&eb, buf, val.pos, val.len,
- &subrIdx, &privateDicts[fd]);
- }
- }
- }
- eexecWrite(&eb, "end\n");
- eexecWrite(&eb, "end\n");
- eexecWrite(&eb, "readonly put\n");
- eexecWrite(&eb, "noaccess put\n");
- eexecWrite(&eb, "dup /FontName get exch definefont pop\n");
- eexecWrite(&eb, "mark currentfile closefile\n");
-
- // trailer
- if (eb.line > 0) {
- (*outputFunc)(outputStream, "\n", 1);
- }
- for (j = 0; j < 8; ++j) {
- (*outputFunc)(outputStream, "0000000000000000000000000000000000000000000000000000000000000000\n", 65);
- }
- (*outputFunc)(outputStream, "cleartomark\n", 12);
- }
-
- // write the Type 0 parent font
- (*outputFunc)(outputStream, "16 dict begin\n", 14);
- (*outputFunc)(outputStream, "/FontName /", 11);
- (*outputFunc)(outputStream, psName, strlen(psName));
- (*outputFunc)(outputStream, " def\n", 5);
- (*outputFunc)(outputStream, "/FontType 0 def\n", 16);
- if (topDict.hasFontMatrix) {
- sprintf(buf, "/FontMatrix [%g %g %g %g %g %g] def\n",
- topDict.fontMatrix[0], topDict.fontMatrix[1],
- topDict.fontMatrix[2], topDict.fontMatrix[3],
- topDict.fontMatrix[4], topDict.fontMatrix[5]);
- (*outputFunc)(outputStream, buf, strlen(buf));
- } else {
- (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
- }
- (*outputFunc)(outputStream, "/FMapType 2 def\n", 16);
- (*outputFunc)(outputStream, "/Encoding [\n", 12);
- for (i = 0; i < nCIDs; i += 256) {
- sprintf(buf, "%d\n", i >> 8);
- (*outputFunc)(outputStream, buf, strlen(buf));
- }
- (*outputFunc)(outputStream, "] def\n", 6);
- (*outputFunc)(outputStream, "/FDepVector [\n", 14);
- for (i = 0; i < nCIDs; i += 256) {
- (*outputFunc)(outputStream, "/", 1);
- (*outputFunc)(outputStream, psName, strlen(psName));
- sprintf(buf, "_%02x findfont\n", i >> 8);
- (*outputFunc)(outputStream, buf, strlen(buf));
- }
- (*outputFunc)(outputStream, "] def\n", 6);
- (*outputFunc)(outputStream, "FontName currentdict end definefont pop\n", 40);
-
- gfree(cidMap);
-}
-
-void FoFiType1C::eexecCvtGlyph(Type1CEexecBuf *eb, char *glyphName,
- int offset, int nBytes,
- Type1CIndex *subrIdx,
- Type1CPrivateDict *pDict) {
- char buf[512];
- GString *charBuf;
-
- // generate the charstring
- charBuf = new GString();
- cvtGlyph(offset, nBytes, charBuf, subrIdx, pDict, gTrue);
-
- sprintf(buf, "/%s %d RD ", glyphName, charBuf->getLength());
- eexecWrite(eb, buf);
- eexecWriteCharstring(eb, (Guchar *)charBuf->getCString(),
- charBuf->getLength());
- eexecWrite(eb, " ND\n");
-
- delete charBuf;
-}
-
-void FoFiType1C::cvtGlyph(int offset, int nBytes, GString *charBuf,
- Type1CIndex *subrIdx, Type1CPrivateDict *pDict,
- GBool top) {
- Type1CIndexVal val;
- GBool ok, dFP;
- double d, dx, dy;
- Gushort r2;
- Guchar byte;
- int pos, subrBias, start, i, k;
-
- start = charBuf->getLength();
- if (top) {
- charBuf->append((char)73);
- charBuf->append((char)58);
- charBuf->append((char)147);
- charBuf->append((char)134);
- nOps = 0;
- nHints = 0;
- firstOp = gTrue;
- openPath = gFalse;
- }
-
- pos = offset;
- while (pos < offset + nBytes) {
- ok = gTrue;
- pos = getOp(pos, gTrue, &ok);
- if (!ok) {
- break;
- }
- if (!ops[nOps - 1].isNum) {
- --nOps; // drop the operator
- switch (ops[nOps].op) {
- case 0x0001: // hstem
- if (firstOp) {
- cvtGlyphWidth(nOps & 1, charBuf, pDict);
- firstOp = gFalse;
- }
- if (nOps & 1) {
- //~ error(-1, "Wrong number of args (%d) to Type 2 hstem", nOps);
- }
- d = 0;
- dFP = gFalse;
- for (k = 0; k < nOps; k += 2) {
- // convert Type 2 edge hints (-20 or -21) to Type 1 ghost hints
- if (ops[k+1].num < 0) {
- d += ops[k].num + ops[k+1].num;
- dFP |= ops[k].isFP | ops[k+1].isFP;
- cvtNum(d, dFP, charBuf);
- cvtNum(-ops[k+1].num, ops[k+1].isFP, charBuf);
- } else {
- d += ops[k].num;
- dFP |= ops[k].isFP;
- cvtNum(d, dFP, charBuf);
- cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
- d += ops[k+1].num;
- dFP |= ops[k+1].isFP;
- }
- charBuf->append((char)1);
- }
- nHints += nOps / 2;
- nOps = 0;
- break;
- case 0x0003: // vstem
- if (firstOp) {
- cvtGlyphWidth(nOps & 1, charBuf, pDict);
- firstOp = gFalse;
- }
- if (nOps & 1) {
- //~ error(-1, "Wrong number of args (%d) to Type 2 vstem", nOps);
- }
- d = 0;
- dFP = gFalse;
- for (k = 0; k < nOps; k += 2) {
- // convert Type 2 edge hints (-20 or -21) to Type 1 ghost hints
- if (ops[k+1].num < 0) {
- d += ops[k].num + ops[k+1].num;
- dFP |= ops[k].isFP | ops[k+1].isFP;
- cvtNum(d, dFP, charBuf);
- cvtNum(-ops[k+1].num, ops[k+1].isFP, charBuf);
- } else {
- d += ops[k].num;
- dFP |= ops[k].isFP;
- cvtNum(d, dFP, charBuf);
- cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
- d += ops[k+1].num;
- dFP |= ops[k+1].isFP;
- }
- charBuf->append((char)3);
- }
- nHints += nOps / 2;
- nOps = 0;
- break;
- case 0x0004: // vmoveto
- if (firstOp) {
- cvtGlyphWidth(nOps == 2, charBuf, pDict);
- firstOp = gFalse;
- }
- if (openPath) {
- charBuf->append((char)9);
- openPath = gFalse;
- }
- if (nOps != 1) {
- //~ error(-1, "Wrong number of args (%d) to Type 2 vmoveto", nOps);
- }
- cvtNum(ops[0].num, ops[0].isFP, charBuf);
- charBuf->append((char)4);
- nOps = 0;
- break;
- case 0x0005: // rlineto
- if (nOps < 2 || nOps % 2 != 0) {
- //~ error(-1, "Wrong number of args (%d) to Type 2 rlineto", nOps);
- }
- for (k = 0; k < nOps; k += 2) {
- cvtNum(ops[k].num, ops[k].isFP, charBuf);
- cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
- charBuf->append((char)5);
- }
- nOps = 0;
- openPath = gTrue;
- break;
- case 0x0006: // hlineto
- if (nOps < 1) {
- //~ error(-1, "Wrong number of args (%d) to Type 2 hlineto", nOps);
- }
- for (k = 0; k < nOps; ++k) {
- cvtNum(ops[k].num, ops[k].isFP, charBuf);
- charBuf->append((char)((k & 1) ? 7 : 6));
- }
- nOps = 0;
- openPath = gTrue;
- break;
- case 0x0007: // vlineto
- if (nOps < 1) {
- //~ error(-1, "Wrong number of args (%d) to Type 2 vlineto", nOps);
- }
- for (k = 0; k < nOps; ++k) {
- cvtNum(ops[k].num, ops[k].isFP, charBuf);
- charBuf->append((char)((k & 1) ? 6 : 7));
- }
- nOps = 0;
- openPath = gTrue;
- break;
- case 0x0008: // rrcurveto
- if (nOps < 6 || nOps % 6 != 0) {
- //~ error(-1, "Wrong number of args (%d) to Type 2 rrcurveto", nOps);
- }
- for (k = 0; k < nOps; k += 6) {
- cvtNum(ops[k].num, ops[k].isFP, charBuf);
- cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
- cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
- cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
- cvtNum(ops[k+4].num, ops[k+4].isFP, charBuf);
- cvtNum(ops[k+5].num, ops[k+5].isFP, charBuf);
- charBuf->append((char)8);
- }
- nOps = 0;
- openPath = gTrue;
- break;
- case 0x000a: // callsubr
- if (nOps >= 1) {
- subrBias = (subrIdx->len < 1240)
- ? 107 : (subrIdx->len < 33900) ? 1131 : 32768;
- k = subrBias + (int)ops[nOps - 1].num;
- --nOps;
- ok = gTrue;
- getIndexVal(subrIdx, k, &val, &ok);
- if (ok) {
- cvtGlyph(val.pos, val.len, charBuf, subrIdx, pDict, gFalse);
- }
- } else {
- //~ error(-1, "Too few args to Type 2 callsubr");
- }
- // don't clear the stack
- break;
- case 0x000b: // return
- // don't clear the stack
- break;
- case 0x000e: // endchar / seac
- if (firstOp) {
- cvtGlyphWidth(nOps == 1 || nOps == 5, charBuf, pDict);
- firstOp = gFalse;
- }
- if (openPath) {
- charBuf->append((char)9);
- openPath = gFalse;
- }
- if (nOps == 4) {
- cvtNum(0, gFalse, charBuf);
- cvtNum(ops[0].num, ops[0].isFP, charBuf);
- cvtNum(ops[1].num, ops[1].isFP, charBuf);
- cvtNum(ops[2].num, ops[2].isFP, charBuf);
- cvtNum(ops[3].num, ops[3].isFP, charBuf);
- charBuf->append((char)12)->append((char)6);
- } else if (nOps == 0) {
- charBuf->append((char)14);
- } else {
- //~ error(-1, "Wrong number of args (%d) to Type 2 endchar", nOps);
- }
- nOps = 0;
- break;
- case 0x000f: // (obsolete)
- // this op is ignored, but we need the glyph width
- if (firstOp) {
- cvtGlyphWidth(nOps > 0, charBuf, pDict);
- firstOp = gFalse;
- }
- nOps = 0;
- break;
- case 0x0010: // blend
- //~ error(-1, "Unimplemented Type 2 charstring op: %d", file[i]);
- nOps = 0;
- break;
- case 0x0012: // hstemhm
- // ignored
- if (firstOp) {
- cvtGlyphWidth(nOps & 1, charBuf, pDict);
- firstOp = gFalse;
- }
- if (nOps & 1) {
- //~ error(-1, "Wrong number of args (%d) to Type 2 hstemhm", nOps);
- }
- nHints += nOps / 2;
- nOps = 0;
- break;
- case 0x0013: // hintmask
- // ignored
- if (firstOp) {
- cvtGlyphWidth(nOps & 1, charBuf, pDict);
- firstOp = gFalse;
- }
- if (nOps > 0) {
- if (nOps & 1) {
- //~ error(-1, "Wrong number of args (%d) to Type 2 hintmask/vstemhm",
- //~ nOps);
- }
- nHints += nOps / 2;
- }
- pos += (nHints + 7) >> 3;
- nOps = 0;
- break;
- case 0x0014: // cntrmask
- // ignored
- if (firstOp) {
- cvtGlyphWidth(nOps & 1, charBuf, pDict);
- firstOp = gFalse;
- }
- if (nOps > 0) {
- if (nOps & 1) {
- //~ error(-1, "Wrong number of args (%d) to Type 2 cntrmask/vstemhm",
- //~ nOps);
- }
- nHints += nOps / 2;
- }
- pos += (nHints + 7) >> 3;
- nOps = 0;
- break;
- case 0x0015: // rmoveto
- if (firstOp) {
- cvtGlyphWidth(nOps == 3, charBuf, pDict);
- firstOp = gFalse;
- }
- if (openPath) {
- charBuf->append((char)9);
- openPath = gFalse;
- }
- if (nOps != 2) {
- //~ error(-1, "Wrong number of args (%d) to Type 2 rmoveto", nOps);
- }
- cvtNum(ops[0].num, ops[0].isFP, charBuf);
- cvtNum(ops[1].num, ops[1].isFP, charBuf);
- charBuf->append((char)21);
- nOps = 0;
- break;
- case 0x0016: // hmoveto
- if (firstOp) {
- cvtGlyphWidth(nOps == 2, charBuf, pDict);
- firstOp = gFalse;
- }
- if (openPath) {
- charBuf->append((char)9);
- openPath = gFalse;
- }
- if (nOps != 1) {
- //~ error(-1, "Wrong number of args (%d) to Type 2 hmoveto", nOps);
- }
- cvtNum(ops[0].num, ops[0].isFP, charBuf);
- charBuf->append((char)22);
- nOps = 0;
- break;
- case 0x0017: // vstemhm
- // ignored
- if (firstOp) {
- cvtGlyphWidth(nOps & 1, charBuf, pDict);
- firstOp = gFalse;
- }
- if (nOps & 1) {
- //~ error(-1, "Wrong number of args (%d) to Type 2 vstemhm", nOps);
- }
- nHints += nOps / 2;
- nOps = 0;
- break;
- case 0x0018: // rcurveline
- if (nOps < 8 || (nOps - 2) % 6 != 0) {
- //~ error(-1, "Wrong number of args (%d) to Type 2 rcurveline", nOps);
- }
- for (k = 0; k < nOps - 2; k += 6) {
- cvtNum(ops[k].num, ops[k].isFP, charBuf);
- cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
- cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
- cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
- cvtNum(ops[k+4].num, ops[k+4].isFP, charBuf);
- cvtNum(ops[k+5].num, ops[k+5].isFP, charBuf);
- charBuf->append((char)8);
- }
- cvtNum(ops[k].num, ops[k].isFP, charBuf);
- cvtNum(ops[k+1].num, ops[k].isFP, charBuf);
- charBuf->append((char)5);
- nOps = 0;
- openPath = gTrue;
- break;
- case 0x0019: // rlinecurve
- if (nOps < 8 || (nOps - 6) % 2 != 0) {
- //~ error(-1, "Wrong number of args (%d) to Type 2 rlinecurve", nOps);
- }
- for (k = 0; k < nOps - 6; k += 2) {
- cvtNum(ops[k].num, ops[k].isFP, charBuf);
- cvtNum(ops[k+1].num, ops[k].isFP, charBuf);
- charBuf->append((char)5);
- }
- cvtNum(ops[k].num, ops[k].isFP, charBuf);
- cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
- cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
- cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
- cvtNum(ops[k+4].num, ops[k+4].isFP, charBuf);
- cvtNum(ops[k+5].num, ops[k+5].isFP, charBuf);
- charBuf->append((char)8);
- nOps = 0;
- openPath = gTrue;
- break;
- case 0x001a: // vvcurveto
- if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
- //~ error(-1, "Wrong number of args (%d) to Type 2 vvcurveto", nOps);
- }
- if (nOps % 2 == 1) {
- cvtNum(ops[0].num, ops[0].isFP, charBuf);
- cvtNum(ops[1].num, ops[1].isFP, charBuf);
- cvtNum(ops[2].num, ops[2].isFP, charBuf);
- cvtNum(ops[3].num, ops[3].isFP, charBuf);
- cvtNum(0, gFalse, charBuf);
- cvtNum(ops[4].num, ops[4].isFP, charBuf);
- charBuf->append((char)8);
- k = 5;
- } else {
- k = 0;
- }
- for (; k < nOps; k += 4) {
- cvtNum(0, gFalse, charBuf);
- cvtNum(ops[k].num, ops[k].isFP, charBuf);
- cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
- cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
- cvtNum(0, gFalse, charBuf);
- cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
- charBuf->append((char)8);
- }
- nOps = 0;
- openPath = gTrue;
- break;
- case 0x001b: // hhcurveto
- if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
- //~ error(-1, "Wrong number of args (%d) to Type 2 hhcurveto", nOps);
- }
- if (nOps % 2 == 1) {
- cvtNum(ops[1].num, ops[1].isFP, charBuf);
- cvtNum(ops[0].num, ops[0].isFP, charBuf);
- cvtNum(ops[2].num, ops[2].isFP, charBuf);
- cvtNum(ops[3].num, ops[3].isFP, charBuf);
- cvtNum(ops[4].num, ops[4].isFP, charBuf);
- cvtNum(0, gFalse, charBuf);
- charBuf->append((char)8);
- k = 5;
- } else {
- k = 0;
- }
- for (; k < nOps; k += 4) {
- cvtNum(ops[k].num, ops[k].isFP, charBuf);
- cvtNum(0, gFalse, charBuf);
- cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
- cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
- cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
- cvtNum(0, gFalse, charBuf);
- charBuf->append((char)8);
- }
- nOps = 0;
- openPath = gTrue;
- break;
- case 0x001d: // callgsubr
- if (nOps >= 1) {
- k = gsubrBias + (int)ops[nOps - 1].num;
- --nOps;
- ok = gTrue;
- getIndexVal(&gsubrIdx, k, &val, &ok);
- if (ok) {
- cvtGlyph(val.pos, val.len, charBuf, subrIdx, pDict, gFalse);
- }
- } else {
- //~ error(-1, "Too few args to Type 2 callgsubr");
- }
- // don't clear the stack
- break;
- case 0x001e: // vhcurveto
- if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
- //~ error(-1, "Wrong number of args (%d) to Type 2 vhcurveto", nOps);
- }
- for (k = 0; k < nOps && k != nOps-5; k += 4) {
- if (k % 8 == 0) {
- cvtNum(ops[k].num, ops[k].isFP, charBuf);
- cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
- cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
- cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
- charBuf->append((char)30);
- } else {
- cvtNum(ops[k].num, ops[k].isFP, charBuf);
- cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
- cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
- cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
- charBuf->append((char)31);
- }
- }
- if (k == nOps-5) {
- if (k % 8 == 0) {
- cvtNum(0, gFalse, charBuf);
- cvtNum(ops[k].num, ops[k].isFP, charBuf);
- cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
- cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
- cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
- cvtNum(ops[k+4].num, ops[k+4].isFP, charBuf);
- } else {
- cvtNum(ops[k].num, ops[k].isFP, charBuf);
- cvtNum(0, gFalse, charBuf);
- cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
- cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
- cvtNum(ops[k+4].num, ops[k+4].isFP, charBuf);
- cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
- }
- charBuf->append((char)8);
- }
- nOps = 0;
- openPath = gTrue;
- break;
- case 0x001f: // hvcurveto
- if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
- //~ error(-1, "Wrong number of args (%d) to Type 2 hvcurveto", nOps);
- }
- for (k = 0; k < nOps && k != nOps-5; k += 4) {
- if (k % 8 == 0) {
- cvtNum(ops[k].num, ops[k].isFP, charBuf);
- cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
- cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
- cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
- charBuf->append((char)31);
- } else {
- cvtNum(ops[k].num, ops[k].isFP, charBuf);
- cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
- cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
- cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
- charBuf->append((char)30);
- }
- }
- if (k == nOps-5) {
- if (k % 8 == 0) {
- cvtNum(ops[k].num, ops[k].isFP, charBuf);
- cvtNum(0, gFalse, charBuf);
- cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
- cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
- cvtNum(ops[k+4].num, ops[k+4].isFP, charBuf);
- cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
- } else {
- cvtNum(0, gFalse, charBuf);
- cvtNum(ops[k].num, ops[k].isFP, charBuf);
- cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
- cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
- cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
- cvtNum(ops[k+4].num, ops[k+4].isFP, charBuf);
- }
- charBuf->append((char)8);
- }
- nOps = 0;
- openPath = gTrue;
- break;
- case 0x0c00: // dotsection (should be Type 1 only?)
- // ignored
- nOps = 0;
- break;
- case 0x0c03: // and
- case 0x0c04: // or
- case 0x0c05: // not
- case 0x0c08: // store
- case 0x0c09: // abs
- case 0x0c0a: // add
- case 0x0c0b: // sub
- case 0x0c0c: // div
- case 0x0c0d: // load
- case 0x0c0e: // neg
- case 0x0c0f: // eq
- case 0x0c12: // drop
- case 0x0c14: // put
- case 0x0c15: // get
- case 0x0c16: // ifelse
- case 0x0c17: // random
- case 0x0c18: // mul
- case 0x0c1a: // sqrt
- case 0x0c1b: // dup
- case 0x0c1c: // exch
- case 0x0c1d: // index
- case 0x0c1e: // roll
- //~ error(-1, "Unimplemented Type 2 charstring op: 12.%d", file[i+1]);
- nOps = 0;
- break;
- case 0x0c22: // hflex
- if (nOps != 7) {
- //~ error(-1, "Wrong number of args (%d) to Type 2 hflex", nOps);
- }
- cvtNum(ops[0].num, ops[0].isFP, charBuf);
- cvtNum(0, gFalse, charBuf);
- cvtNum(ops[1].num, ops[1].isFP, charBuf);
- cvtNum(ops[2].num, ops[2].isFP, charBuf);
- cvtNum(ops[3].num, ops[3].isFP, charBuf);
- cvtNum(0, gFalse, charBuf);
- charBuf->append((char)8);
- cvtNum(ops[4].num, ops[4].isFP, charBuf);
- cvtNum(0, gFalse, charBuf);
- cvtNum(ops[5].num, ops[5].isFP, charBuf);
- cvtNum(-ops[2].num, ops[2].isFP, charBuf);
- cvtNum(ops[6].num, ops[6].isFP, charBuf);
- cvtNum(0, gFalse, charBuf);
- charBuf->append((char)8);
- nOps = 0;
- openPath = gTrue;
- break;
- case 0x0c23: // flex
- if (nOps != 13) {
- //~ error(-1, "Wrong number of args (%d) to Type 2 flex", nOps);
- }
- cvtNum(ops[0].num, ops[0].isFP, charBuf);
- cvtNum(ops[1].num, ops[1].isFP, charBuf);
- cvtNum(ops[2].num, ops[2].isFP, charBuf);
- cvtNum(ops[3].num, ops[3].isFP, charBuf);
- cvtNum(ops[4].num, ops[4].isFP, charBuf);
- cvtNum(ops[5].num, ops[5].isFP, charBuf);
- charBuf->append((char)8);
- cvtNum(ops[6].num, ops[6].isFP, charBuf);
- cvtNum(ops[7].num, ops[7].isFP, charBuf);
- cvtNum(ops[8].num, ops[8].isFP, charBuf);
- cvtNum(ops[9].num, ops[9].isFP, charBuf);
- cvtNum(ops[10].num, ops[10].isFP, charBuf);
- cvtNum(ops[11].num, ops[11].isFP, charBuf);
- charBuf->append((char)8);
- nOps = 0;
- openPath = gTrue;
- break;
- case 0x0c24: // hflex1
- if (nOps != 9) {
- //~ error(-1, "Wrong number of args (%d) to Type 2 hflex1", nOps);
- }
- cvtNum(ops[0].num, ops[0].isFP, charBuf);
- cvtNum(ops[1].num, ops[1].isFP, charBuf);
- cvtNum(ops[2].num, ops[2].isFP, charBuf);
- cvtNum(ops[3].num, ops[3].isFP, charBuf);
- cvtNum(ops[4].num, ops[4].isFP, charBuf);
- cvtNum(0, gFalse, charBuf);
- charBuf->append((char)8);
- cvtNum(ops[5].num, ops[5].isFP, charBuf);
- cvtNum(0, gFalse, charBuf);
- cvtNum(ops[6].num, ops[6].isFP, charBuf);
- cvtNum(ops[7].num, ops[7].isFP, charBuf);
- cvtNum(ops[8].num, ops[8].isFP, charBuf);
- cvtNum(-(ops[1].num + ops[3].num + ops[7].num),
- ops[1].isFP | ops[3].isFP | ops[7].isFP, charBuf);
- charBuf->append((char)8);
- nOps = 0;
- openPath = gTrue;
- break;
- case 0x0c25: // flex1
- if (nOps != 11) {
- //~ error(-1, "Wrong number of args (%d) to Type 2 flex1", nOps);
- }
- cvtNum(ops[0].num, ops[0].isFP, charBuf);
- cvtNum(ops[1].num, ops[1].isFP, charBuf);
- cvtNum(ops[2].num, ops[2].isFP, charBuf);
- cvtNum(ops[3].num, ops[3].isFP, charBuf);
- cvtNum(ops[4].num, ops[4].isFP, charBuf);
- cvtNum(ops[5].num, ops[5].isFP, charBuf);
- charBuf->append((char)8);
- cvtNum(ops[6].num, ops[6].isFP, charBuf);
- cvtNum(ops[7].num, ops[7].isFP, charBuf);
- cvtNum(ops[8].num, ops[8].isFP, charBuf);
- cvtNum(ops[9].num, ops[9].isFP, charBuf);
- dx = ops[0].num + ops[2].num + ops[4].num + ops[6].num + ops[8].num;
- dy = ops[1].num + ops[3].num + ops[5].num + ops[7].num + ops[9].num;
- if (fabs(dx) > fabs(dy)) {
- cvtNum(ops[10].num, ops[10].isFP, charBuf);
- cvtNum(-dy, ops[1].isFP | ops[3].isFP | ops[5].isFP |
- ops[7].isFP | ops[9].isFP, charBuf);
- } else {
- cvtNum(-dx, ops[0].isFP | ops[2].isFP | ops[4].isFP |
- ops[6].isFP | ops[8].isFP, charBuf);
- cvtNum(ops[10].num, ops[10].isFP, charBuf);
- }
- charBuf->append((char)8);
- nOps = 0;
- openPath = gTrue;
- break;
- default:
- //~ error(-1, "Illegal Type 2 charstring op: %04x",
- //~ ops[nOps].op);
- nOps = 0;
- break;
- }
- }
- }
-
- // charstring encryption
- if (top) {
- r2 = 4330;
- for (i = start; i < charBuf->getLength(); ++i) {
- byte = charBuf->getChar(i) ^ (r2 >> 8);
- charBuf->setChar(i, byte);
- r2 = (byte + r2) * 52845 + 22719;
- }
- }
-}
-
-void FoFiType1C::cvtGlyphWidth(GBool useOp, GString *charBuf,
- Type1CPrivateDict *pDict) {
- double w;
- GBool wFP;
- int i;
-
- if (useOp) {
- w = pDict->nominalWidthX + ops[0].num;
- wFP = pDict->nominalWidthXFP | ops[0].isFP;
- for (i = 1; i < nOps; ++i) {
- ops[i-1] = ops[i];
- }
- --nOps;
- } else {
- w = pDict->defaultWidthX;
- wFP = pDict->defaultWidthXFP;
- }
- cvtNum(0, gFalse, charBuf);
- cvtNum(w, wFP, charBuf);
- charBuf->append((char)13);
-}
-
-void FoFiType1C::cvtNum(double x, GBool isFP, GString *charBuf) {
- Guchar buf[12];
- int y, n;
-
- n = 0;
- if (isFP) {
- if (x >= -32768 && x < 32768) {
- y = (int)(x * 256.0);
- buf[0] = 255;
- buf[1] = (Guchar)(y >> 24);
- buf[2] = (Guchar)(y >> 16);
- buf[3] = (Guchar)(y >> 8);
- buf[4] = (Guchar)y;
- buf[5] = 255;
- buf[6] = 0;
- buf[7] = 0;
- buf[8] = 1;
- buf[9] = 0;
- buf[10] = 12;
- buf[11] = 12;
- n = 12;
- } else {
- //~ error(-1, "Type 2 fixed point constant out of range");
- }
- } else {
- y = (int)x;
- if (y >= -107 && y <= 107) {
- buf[0] = (Guchar)(y + 139);
- n = 1;
- } else if (y > 107 && y <= 1131) {
- y -= 108;
- buf[0] = (Guchar)((y >> 8) + 247);
- buf[1] = (Guchar)(y & 0xff);
- n = 2;
- } else if (y < -107 && y >= -1131) {
- y = -y - 108;
- buf[0] = (Guchar)((y >> 8) + 251);
- buf[1] = (Guchar)(y & 0xff);
- n = 2;
- } else {
- buf[0] = 255;
- buf[1] = (Guchar)(y >> 24);
- buf[2] = (Guchar)(y >> 16);
- buf[3] = (Guchar)(y >> 8);
- buf[4] = (Guchar)y;
- n = 5;
- }
- }
- charBuf->append((char *)buf, n);
-}
-
-void FoFiType1C::eexecWrite(Type1CEexecBuf *eb, char *s) {
- Guchar *p;
- Guchar x;
-
- for (p = (Guchar *)s; *p; ++p) {
- x = *p ^ (eb->r1 >> 8);
- eb->r1 = (x + eb->r1) * 52845 + 22719;
- if (eb->ascii) {
- (*eb->outputFunc)(eb->outputStream, &hexChars[x >> 4], 1);
- (*eb->outputFunc)(eb->outputStream, &hexChars[x & 0x0f], 1);
- eb->line += 2;
- if (eb->line == 64) {
- (*eb->outputFunc)(eb->outputStream, "\n", 1);
- eb->line = 0;
- }
- } else {
- (*eb->outputFunc)(eb->outputStream, (char *)&x, 1);
- }
- }
-}
-
-void FoFiType1C::eexecWriteCharstring(Type1CEexecBuf *eb,
- Guchar *s, int n) {
- Guchar x;
- int i;
-
- // eexec encryption
- for (i = 0; i < n; ++i) {
- x = s[i] ^ (eb->r1 >> 8);
- eb->r1 = (x + eb->r1) * 52845 + 22719;
- if (eb->ascii) {
- (*eb->outputFunc)(eb->outputStream, &hexChars[x >> 4], 1);
- (*eb->outputFunc)(eb->outputStream, &hexChars[x & 0x0f], 1);
- eb->line += 2;
- if (eb->line == 64) {
- (*eb->outputFunc)(eb->outputStream, "\n", 1);
- eb->line = 0;
- }
- } else {
- (*eb->outputFunc)(eb->outputStream, (char *)&x, 1);
- }
- }
-}
-
-GBool FoFiType1C::parse() {
- Type1CIndex fdIdx;
- Type1CIndexVal val;
- int i;
-
- parsedOk = gTrue;
-
- // some tools embed Type 1C fonts with an extra whitespace char at
- // the beginning
- if (len > 0 && file[0] != '\x01') {
- ++file;
- --len;
- }
-
- // find the indexes
- getIndex(getU8(2, &parsedOk), &nameIdx, &parsedOk);
- getIndex(nameIdx.endPos, &topDictIdx, &parsedOk);
- getIndex(topDictIdx.endPos, &stringIdx, &parsedOk);
- getIndex(stringIdx.endPos, &gsubrIdx, &parsedOk);
- if (!parsedOk) {
- return gFalse;
- }
- gsubrBias = (gsubrIdx.len < 1240) ? 107
- : (gsubrIdx.len < 33900) ? 1131 : 32768;
-
- // read the first font name
- getIndexVal(&nameIdx, 0, &val, &parsedOk);
- if (!parsedOk) {
- return gFalse;
- }
- name = new GString((char *)&file[val.pos], val.len);
-
- // read the top dict for the first font
- readTopDict();
-
- // for CID fonts: read the FDArray dicts and private dicts
- if (topDict.firstOp == 0x0c1e) {
- if (topDict.fdArrayOffset == 0) {
- nFDs = 1;
- privateDicts = (Type1CPrivateDict *)gmalloc(sizeof(Type1CPrivateDict));
- readPrivateDict(0, 0, &privateDicts[0]);
- } else {
- getIndex(topDict.fdArrayOffset, &fdIdx, &parsedOk);
- if (!parsedOk) {
- return gFalse;
- }
- nFDs = fdIdx.len;
- privateDicts = (Type1CPrivateDict *)
- gmallocn(nFDs, sizeof(Type1CPrivateDict));
- for (i = 0; i < nFDs; ++i) {
- getIndexVal(&fdIdx, i, &val, &parsedOk);
- if (!parsedOk) {
- return gFalse;
- }
- readFD(val.pos, val.len, &privateDicts[i]);
- }
- }
-
- // for 8-bit fonts: read the private dict
- } else {
- privateDicts = (Type1CPrivateDict *)gmalloc(sizeof(Type1CPrivateDict));
- readPrivateDict(topDict.privateOffset, topDict.privateSize,
- &privateDicts[0]);
- }
-
- // check for parse errors in the private dict(s)
- if (!parsedOk) {
- return gFalse;
- }
-
- // get the charstrings index
- if (topDict.charStringsOffset <= 0) {
- parsedOk = gFalse;
- return gFalse;
- }
- getIndex(topDict.charStringsOffset, &charStringsIdx, &parsedOk);
- if (!parsedOk) {
- return gFalse;
- }
- nGlyphs = charStringsIdx.len;
-
- // for CID fonts: read the FDSelect table
- if (topDict.firstOp == 0x0c1e) {
- readFDSelect();
- if (!parsedOk) {
- return gFalse;
- }
- }
-
- // read the charset
- if (!readCharset()) {
- parsedOk = gFalse;
- return gFalse;
- }
-
- // for 8-bit fonts: build the encoding
- if (topDict.firstOp != 0x0c14 && topDict.firstOp != 0x0c1e) {
- buildEncoding();
- if (!parsedOk) {
- return gFalse;
- }
- }
-
- return parsedOk;
-}
-
-void FoFiType1C::readTopDict() {
- Type1CIndexVal topDictPtr;
- int pos;
-
- topDict.firstOp = -1;
- topDict.versionSID = 0;
- topDict.noticeSID = 0;
- topDict.copyrightSID = 0;
- topDict.fullNameSID = 0;
- topDict.familyNameSID = 0;
- topDict.weightSID = 0;
- topDict.isFixedPitch = 0;
- topDict.italicAngle = 0;
- topDict.underlinePosition = -100;
- topDict.underlineThickness = 50;
- topDict.paintType = 0;
- topDict.charstringType = 2;
- topDict.fontMatrix[0] = 0.001;
- topDict.fontMatrix[1] = 0;
- topDict.fontMatrix[2] = 0;
- topDict.fontMatrix[3] = 0.001;
- topDict.fontMatrix[4] = 0;
- topDict.fontMatrix[5] = 0;
- topDict.hasFontMatrix = gFalse;
- topDict.uniqueID = 0;
- topDict.fontBBox[0] = 0;
- topDict.fontBBox[1] = 0;
- topDict.fontBBox[2] = 0;
- topDict.fontBBox[3] = 0;
- topDict.strokeWidth = 0;
- topDict.charsetOffset = 0;
- topDict.encodingOffset = 0;
- topDict.charStringsOffset = 0;
- topDict.privateSize = 0;
- topDict.privateOffset = 0;
- topDict.registrySID = 0;
- topDict.orderingSID = 0;
- topDict.supplement = 0;
- topDict.fdArrayOffset = 0;
- topDict.fdSelectOffset = 0;
-
- getIndexVal(&topDictIdx, 0, &topDictPtr, &parsedOk);
- pos = topDictPtr.pos;
- nOps = 0;
- while (pos < topDictPtr.pos + topDictPtr.len) {
- pos = getOp(pos, gFalse, &parsedOk);
- if (!parsedOk) {
- break;
- }
- if (!ops[nOps - 1].isNum) {
- --nOps; // drop the operator
- if (topDict.firstOp < 0) {
- topDict.firstOp = ops[nOps].op;
- }
- switch (ops[nOps].op) {
- case 0x0000: topDict.versionSID = (int)ops[0].num; break;
- case 0x0001: topDict.noticeSID = (int)ops[0].num; break;
- case 0x0c00: topDict.copyrightSID = (int)ops[0].num; break;
- case 0x0002: topDict.fullNameSID = (int)ops[0].num; break;
- case 0x0003: topDict.familyNameSID = (int)ops[0].num; break;
- case 0x0004: topDict.weightSID = (int)ops[0].num; break;
- case 0x0c01: topDict.isFixedPitch = (int)ops[0].num; break;
- case 0x0c02: topDict.italicAngle = ops[0].num; break;
- case 0x0c03: topDict.underlinePosition = ops[0].num; break;
- case 0x0c04: topDict.underlineThickness = ops[0].num; break;
- case 0x0c05: topDict.paintType = (int)ops[0].num; break;
- case 0x0c06: topDict.charstringType = (int)ops[0].num; break;
- case 0x0c07: topDict.fontMatrix[0] = ops[0].num;
- topDict.fontMatrix[1] = ops[1].num;
- topDict.fontMatrix[2] = ops[2].num;
- topDict.fontMatrix[3] = ops[3].num;
- topDict.fontMatrix[4] = ops[4].num;
- topDict.fontMatrix[5] = ops[5].num;
- topDict.hasFontMatrix = gTrue; break;
- case 0x000d: topDict.uniqueID = (int)ops[0].num; break;
- case 0x0005: topDict.fontBBox[0] = ops[0].num;
- topDict.fontBBox[1] = ops[1].num;
- topDict.fontBBox[2] = ops[2].num;
- topDict.fontBBox[3] = ops[3].num; break;
- case 0x0c08: topDict.strokeWidth = ops[0].num; break;
- case 0x000f: topDict.charsetOffset = (int)ops[0].num; break;
- case 0x0010: topDict.encodingOffset = (int)ops[0].num; break;
- case 0x0011: topDict.charStringsOffset = (int)ops[0].num; break;
- case 0x0012: topDict.privateSize = (int)ops[0].num;
- topDict.privateOffset = (int)ops[1].num; break;
- case 0x0c1e: topDict.registrySID = (int)ops[0].num;
- topDict.orderingSID = (int)ops[1].num;
- topDict.supplement = (int)ops[2].num; break;
- case 0x0c24: topDict.fdArrayOffset = (int)ops[0].num; break;
- case 0x0c25: topDict.fdSelectOffset = (int)ops[0].num; break;
- }
- nOps = 0;
- }
- }
-}
-
-// Read a CID font dict (FD) - this pulls out the private dict
-// pointer, and reads the private dict. It also pulls the FontMatrix
-// (if any) out of the FD.
-void FoFiType1C::readFD(int offset, int length, Type1CPrivateDict *pDict) {
- int pos, pSize, pOffset;
- double fontMatrix[6];
- GBool hasFontMatrix;
-
- hasFontMatrix = gFalse;
- pSize = pOffset = 0;
- pos = offset;
- nOps = 0;
- while (pos < offset + length) {
- pos = getOp(pos, gFalse, &parsedOk);
- if (!parsedOk) {
- return;
- }
- if (!ops[nOps - 1].isNum) {
- if (ops[nOps - 1].op == 0x0012) {
- if (nOps < 3) {
- parsedOk = gFalse;
- return;
- }
- pSize = (int)ops[0].num;
- pOffset = (int)ops[1].num;
- break;
- } else if (ops[nOps - 1].op == 0x0c07) {
- fontMatrix[0] = ops[0].num;
- fontMatrix[1] = ops[1].num;
- fontMatrix[2] = ops[2].num;
- fontMatrix[3] = ops[3].num;
- fontMatrix[4] = ops[4].num;
- fontMatrix[5] = ops[5].num;
- hasFontMatrix = gTrue;
- }
- nOps = 0;
- }
- }
- readPrivateDict(pOffset, pSize, pDict);
- if (hasFontMatrix) {
- pDict->fontMatrix[0] = fontMatrix[0];
- pDict->fontMatrix[1] = fontMatrix[1];
- pDict->fontMatrix[2] = fontMatrix[2];
- pDict->fontMatrix[3] = fontMatrix[3];
- pDict->fontMatrix[4] = fontMatrix[4];
- pDict->fontMatrix[5] = fontMatrix[5];
- pDict->hasFontMatrix = gTrue;
- }
-}
-
-void FoFiType1C::readPrivateDict(int offset, int length,
- Type1CPrivateDict *pDict) {
- int pos;
-
- pDict->hasFontMatrix = gFalse;
- pDict->nBlueValues = 0;
- pDict->nOtherBlues = 0;
- pDict->nFamilyBlues = 0;
- pDict->nFamilyOtherBlues = 0;
- pDict->blueScale = 0.039625;
- pDict->blueShift = 7;
- pDict->blueFuzz = 1;
- pDict->hasStdHW = gFalse;
- pDict->hasStdVW = gFalse;
- pDict->nStemSnapH = 0;
- pDict->nStemSnapV = 0;
- pDict->hasForceBold = gFalse;
- pDict->forceBoldThreshold = 0;
- pDict->languageGroup = 0;
- pDict->expansionFactor = 0.06;
- pDict->initialRandomSeed = 0;
- pDict->subrsOffset = 0;
- pDict->defaultWidthX = 0;
- pDict->defaultWidthXFP = gFalse;
- pDict->nominalWidthX = 0;
- pDict->nominalWidthXFP = gFalse;
-
- // no dictionary
- if (offset == 0 || length == 0) {
- return;
- }
-
- pos = offset;
- nOps = 0;
- while (pos < offset + length) {
- pos = getOp(pos, gFalse, &parsedOk);
- if (!parsedOk) {
- break;
- }
- if (!ops[nOps - 1].isNum) {
- --nOps; // drop the operator
- switch (ops[nOps].op) {
- case 0x0006:
- pDict->nBlueValues = getDeltaIntArray(pDict->blueValues,
- type1CMaxBlueValues);
- break;
- case 0x0007:
- pDict->nOtherBlues = getDeltaIntArray(pDict->otherBlues,
- type1CMaxOtherBlues);
- break;
- case 0x0008:
- pDict->nFamilyBlues = getDeltaIntArray(pDict->familyBlues,
- type1CMaxBlueValues);
- break;
- case 0x0009:
- pDict->nFamilyOtherBlues = getDeltaIntArray(pDict->familyOtherBlues,
- type1CMaxOtherBlues);
- break;
- case 0x0c09:
- pDict->blueScale = ops[0].num;
- break;
- case 0x0c0a:
- pDict->blueShift = (int)ops[0].num;
- break;
- case 0x0c0b:
- pDict->blueFuzz = (int)ops[0].num;
- break;
- case 0x000a:
- pDict->stdHW = ops[0].num;
- pDict->hasStdHW = gTrue;
- break;
- case 0x000b:
- pDict->stdVW = ops[0].num;
- pDict->hasStdVW = gTrue;
- break;
- case 0x0c0c:
- pDict->nStemSnapH = getDeltaFPArray(pDict->stemSnapH,
- type1CMaxStemSnap);
- break;
- case 0x0c0d:
- pDict->nStemSnapV = getDeltaFPArray(pDict->stemSnapV,
- type1CMaxStemSnap);
- break;
- case 0x0c0e:
- pDict->forceBold = ops[0].num != 0;
- pDict->hasForceBold = gTrue;
- break;
- case 0x0c0f:
- pDict->forceBoldThreshold = ops[0].num;
- break;
- case 0x0c11:
- pDict->languageGroup = (int)ops[0].num;
- break;
- case 0x0c12:
- pDict->expansionFactor = ops[0].num;
- break;
- case 0x0c13:
- pDict->initialRandomSeed = (int)ops[0].num;
- break;
- case 0x0013:
- pDict->subrsOffset = offset + (int)ops[0].num;
- break;
- case 0x0014:
- pDict->defaultWidthX = ops[0].num;
- pDict->defaultWidthXFP = ops[0].isFP;
- break;
- case 0x0015:
- pDict->nominalWidthX = ops[0].num;
- pDict->nominalWidthXFP = ops[0].isFP;
- break;
- }
- nOps = 0;
- }
- }
-}
-
-void FoFiType1C::readFDSelect() {
- int fdSelectFmt, pos, nRanges, gid0, gid1, fd, i, j;
-
- fdSelect = (Guchar *)gmalloc(nGlyphs);
- if (topDict.fdSelectOffset == 0) {
- for (i = 0; i < nGlyphs; ++i) {
- fdSelect[i] = 0;
- }
- } else {
- pos = topDict.fdSelectOffset;
- fdSelectFmt = getU8(pos++, &parsedOk);
- if (!parsedOk) {
- return;
- }
- if (fdSelectFmt == 0) {
- if (!checkRegion(pos, nGlyphs)) {
- parsedOk = gFalse;
- return;
- }
- memcpy(fdSelect, file + pos, nGlyphs);
- } else if (fdSelectFmt == 3) {
- nRanges = getU16BE(pos, &parsedOk);
- pos += 2;
- gid0 = getU16BE(pos, &parsedOk);
- pos += 2;
- for (i = 1; i <= nRanges; ++i) {
- fd = getU8(pos++, &parsedOk);
- gid1 = getU16BE(pos, &parsedOk);
- if (!parsedOk) {
- return;
- }
- pos += 2;
- if (gid0 > gid1 || gid1 > nGlyphs) {
- //~ error(-1, "Bad FDSelect table in CID font");
- parsedOk = gFalse;
- return;
- }
- for (j = gid0; j < gid1; ++j) {
- fdSelect[j] = fd;
- }
- gid0 = gid1;
- }
- } else {
- //~ error(-1, "Unknown FDSelect table format in CID font");
- for (i = 0; i < nGlyphs; ++i) {
- fdSelect[i] = 0;
- }
- }
- }
-}
-
-void FoFiType1C::buildEncoding() {
- char buf[256];
- int nCodes, nRanges, encFormat;
- int pos, c, sid, nLeft, nSups, i, j;
-
- if (topDict.encodingOffset == 0) {
- encoding = fofiType1StandardEncoding;
-
- } else if (topDict.encodingOffset == 1) {
- encoding = fofiType1ExpertEncoding;
-
- } else {
- encoding = (char **)gmallocn(256, sizeof(char *));
- for (i = 0; i < 256; ++i) {
- encoding[i] = NULL;
- }
- pos = topDict.encodingOffset;
- encFormat = getU8(pos++, &parsedOk);
- if (!parsedOk) {
- return;
- }
- if ((encFormat & 0x7f) == 0) {
- nCodes = 1 + getU8(pos++, &parsedOk);
- if (!parsedOk) {
- return;
- }
- if (nCodes > nGlyphs) {
- nCodes = nGlyphs;
- }
- for (i = 1; i < nCodes; ++i) {
- c = getU8(pos++, &parsedOk);
- if (!parsedOk) {
- return;
- }
- if (encoding[c]) {
- gfree(encoding[c]);
- }
- encoding[c] = copyString(getString(charset[i], buf, &parsedOk));
- }
- } else if ((encFormat & 0x7f) == 1) {
- nRanges = getU8(pos++, &parsedOk);
- if (!parsedOk) {
- return;
- }
- nCodes = 1;
- for (i = 0; i < nRanges; ++i) {
- c = getU8(pos++, &parsedOk);
- nLeft = getU8(pos++, &parsedOk);
- if (!parsedOk) {
- return;
- }
- for (j = 0; j <= nLeft && nCodes < nGlyphs; ++j) {
- if (c < 256) {
- if (encoding[c]) {
- gfree(encoding[c]);
- }
- encoding[c] = copyString(getString(charset[nCodes], buf,
- &parsedOk));
- }
- ++nCodes;
- ++c;
- }
- }
- }
- if (encFormat & 0x80) {
- nSups = getU8(pos++, &parsedOk);
- if (!parsedOk) {
- return;
- }
- for (i = 0; i < nSups; ++i) {
- c = getU8(pos++, &parsedOk);;
- if (!parsedOk) {
- return;;
- }
- sid = getU16BE(pos, &parsedOk);
- pos += 2;
- if (!parsedOk) {
- return;
- }
- if (encoding[c]) {
- gfree(encoding[c]);
- }
- encoding[c] = copyString(getString(sid, buf, &parsedOk));
- }
- }
- }
-}
-
-GBool FoFiType1C::readCharset() {
- int charsetFormat, c, pos;
- int nLeft, i, j;
-
- if (topDict.charsetOffset == 0) {
- charset = fofiType1CISOAdobeCharset;
- } else if (topDict.charsetOffset == 1) {
- charset = fofiType1CExpertCharset;
- } else if (topDict.charsetOffset == 2) {
- charset = fofiType1CExpertSubsetCharset;
- } else {
- charset = (Gushort *)gmallocn(nGlyphs, sizeof(Gushort));
- for (i = 0; i < nGlyphs; ++i) {
- charset[i] = 0;
- }
- pos = topDict.charsetOffset;
- charsetFormat = getU8(pos++, &parsedOk);
- if (charsetFormat == 0) {
- for (i = 1; i < nGlyphs; ++i) {
- charset[i] = (Gushort)getU16BE(pos, &parsedOk);
- pos += 2;
- if (!parsedOk) {
- break;
- }
- }
- } else if (charsetFormat == 1) {
- i = 1;
- while (i < nGlyphs) {
- c = getU16BE(pos, &parsedOk);
- pos += 2;
- nLeft = getU8(pos++, &parsedOk);
- if (!parsedOk) {
- break;
- }
- for (j = 0; j <= nLeft && i < nGlyphs; ++j) {
- charset[i++] = (Gushort)c++;
- }
- }
- } else if (charsetFormat == 2) {
- i = 1;
- while (i < nGlyphs) {
- c = getU16BE(pos, &parsedOk);
- pos += 2;
- nLeft = getU16BE(pos, &parsedOk);
- pos += 2;
- if (!parsedOk) {
- break;
- }
- for (j = 0; j <= nLeft && i < nGlyphs; ++j) {
- charset[i++] = (Gushort)c++;
- }
- }
- }
- if (!parsedOk) {
- gfree(charset);
- charset = NULL;
- return gFalse;
- }
- }
- return gTrue;
-}
-
-int FoFiType1C::getOp(int pos, GBool charstring, GBool *ok) {
- static char nybChars[16] = "0123456789.ee -";
- Type1COp op;
- char buf[65];
- int b0, b1, nyb0, nyb1, x, i;
-
- b0 = getU8(pos++, ok);
- op.isNum = gTrue;
- op.isFP = gFalse;
-
- if (b0 == 28) {
- x = getU8(pos++, ok);
- x = (x << 8) | getU8(pos++, ok);
- if (x & 0x8000) {
- x |= ~0xffff;
- }
- op.num = x;
-
- } else if (!charstring && b0 == 29) {
- x = getU8(pos++, ok);
- x = (x << 8) | getU8(pos++, ok);
- x = (x << 8) | getU8(pos++, ok);
- x = (x << 8) | getU8(pos++, ok);
- if (x & 0x80000000) {
- x |= ~0xffffffff;
- }
- op.num = x;
-
- } else if (!charstring && b0 == 30) {
- i = 0;
- do {
- b1 = getU8(pos++, ok);
- nyb0 = b1 >> 4;
- nyb1 = b1 & 0x0f;
- if (nyb0 == 0xf) {
- break;
- }
- buf[i++] = nybChars[nyb0];
- if (i == 64) {
- break;
- }
- if (nyb0 == 0xc) {
- buf[i++] = '-';
- }
- if (i == 64) {
- break;
- }
- if (nyb1 == 0xf) {
- break;
- }
- buf[i++] = nybChars[nyb1];
- if (i == 64) {
- break;
- }
- if (nyb1 == 0xc) {
- buf[i++] = '-';
- }
- } while (i < 64);
- buf[i] = '\0';
- op.num = atof(buf);
- op.isFP = gTrue;
-
- } else if (b0 >= 32 && b0 <= 246) {
- op.num = b0 - 139;
-
- } else if (b0 >= 247 && b0 <= 250) {
- op.num = ((b0 - 247) << 8) + getU8(pos++, ok) + 108;
-
- } else if (b0 >= 251 && b0 <= 254) {
- op.num = -((b0 - 251) << 8) - getU8(pos++, ok) - 108;
-
- } else if (charstring && b0 == 255) {
- x = getU8(pos++, ok);
- x = (x << 8) | getU8(pos++, ok);
- x = (x << 8) | getU8(pos++, ok);
- x = (x << 8) | getU8(pos++, ok);
- if (x & 0x80000000) {
- x |= ~0xffffffff;
- }
- op.num = (double)x / 65536.0;
- op.isFP = gTrue;
-
- } else if (b0 == 12) {
- op.isNum = gFalse;
- op.op = 0x0c00 + getU8(pos++, ok);
-
- } else {
- op.isNum = gFalse;
- op.op = b0;
- }
-
- if (nOps < 49) {
- ops[nOps++] = op;
- }
-
- return pos;
-}
-
-// Convert the delta-encoded ops array to an array of ints.
-int FoFiType1C::getDeltaIntArray(int *arr, int maxLen) {
- int x;
- int n, i;
-
- if ((n = nOps) > maxLen) {
- n = maxLen;
- }
- x = 0;
- for (i = 0; i < n; ++i) {
- x += (int)ops[i].num;
- arr[i] = x;
- }
- return n;
-}
-
-// Convert the delta-encoded ops array to an array of doubles.
-int FoFiType1C::getDeltaFPArray(double *arr, int maxLen) {
- double x;
- int n, i;
-
- if ((n = nOps) > maxLen) {
- n = maxLen;
- }
- x = 0;
- for (i = 0; i < n; ++i) {
- x += ops[i].num;
- arr[i] = x;
- }
- return n;
-}
-
-void FoFiType1C::getIndex(int pos, Type1CIndex *idx, GBool *ok) {
- idx->pos = pos;
- idx->len = getU16BE(pos, ok);
- if (idx->len == 0) {
- // empty indexes are legal and contain just the length field
- idx->offSize = 0;
- idx->startPos = idx->endPos = pos + 2;
- } else {
- idx->offSize = getU8(pos + 2, ok);
- if (idx->offSize < 1 || idx->offSize > 4) {
- *ok = gFalse;
- }
- idx->startPos = pos + 3 + (idx->len + 1) * idx->offSize - 1;
- if (idx->startPos < 0 || idx->startPos >= len) {
- *ok = gFalse;
- }
- idx->endPos = idx->startPos + getUVarBE(pos + 3 + idx->len * idx->offSize,
- idx->offSize, ok);
- if (idx->endPos < idx->startPos || idx->endPos > len) {
- *ok = gFalse;
- }
- }
-}
-
-void FoFiType1C::getIndexVal(Type1CIndex *idx, int i,
- Type1CIndexVal *val, GBool *ok) {
- int pos0, pos1;
-
- if (i < 0 || i >= idx->len) {
- *ok = gFalse;
- return;
- }
- pos0 = idx->startPos + getUVarBE(idx->pos + 3 + i * idx->offSize,
- idx->offSize, ok);
- pos1 = idx->startPos + getUVarBE(idx->pos + 3 + (i + 1) * idx->offSize,
- idx->offSize, ok);
- if (pos0 < idx->startPos || pos0 > idx->endPos ||
- pos1 <= idx->startPos || pos1 > idx->endPos ||
- pos1 < pos0) {
- *ok = gFalse;
- }
- val->pos = pos0;
- val->len = pos1 - pos0;
-}
-
-char *FoFiType1C::getString(int sid, char *buf, GBool *ok) {
- Type1CIndexVal val;
- int n;
-
- if (sid < 391) {
- strcpy(buf, fofiType1CStdStrings[sid]);
- } else {
- sid -= 391;
- getIndexVal(&stringIdx, sid, &val, ok);
- if (*ok) {
- if ((n = val.len) > 255) {
- n = 255;
- }
- strncpy(buf, (char *)&file[val.pos], n);
- buf[n] = '\0';
- } else {
- buf[0] = '\0';
- }
- }
- return buf;
-}
+++ /dev/null
-//========================================================================
-//
-// FoFiType1C.h
-//
-// Copyright 1999-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#ifndef FOFITYPE1C_H
-#define FOFITYPE1C_H
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma interface
-#endif
-
-#include "gtypes.h"
-#include "FoFiBase.h"
-
-class GString;
-
-//------------------------------------------------------------------------
-
-struct Type1CIndex {
- int pos; // absolute position in file
- int len; // length (number of entries)
- int offSize; // offset size
- int startPos; // position of start of index data - 1
- int endPos; // position one byte past end of the index
-};
-
-struct Type1CIndexVal {
- int pos; // absolute position in file
- int len; // length, in bytes
-};
-
-struct Type1CTopDict {
- int firstOp;
-
- int versionSID;
- int noticeSID;
- int copyrightSID;
- int fullNameSID;
- int familyNameSID;
- int weightSID;
- int isFixedPitch;
- double italicAngle;
- double underlinePosition;
- double underlineThickness;
- int paintType;
- int charstringType;
- double fontMatrix[6];
- GBool hasFontMatrix; // CID fonts are allowed to put their
- // FontMatrix in the FD instead of the
- // top dict
- int uniqueID;
- double fontBBox[4];
- double strokeWidth;
- int charsetOffset;
- int encodingOffset;
- int charStringsOffset;
- int privateSize;
- int privateOffset;
-
- // CIDFont entries
- int registrySID;
- int orderingSID;
- int supplement;
- int fdArrayOffset;
- int fdSelectOffset;
-};
-
-#define type1CMaxBlueValues 14
-#define type1CMaxOtherBlues 10
-#define type1CMaxStemSnap 12
-
-struct Type1CPrivateDict {
- double fontMatrix[6];
- GBool hasFontMatrix;
- int blueValues[type1CMaxBlueValues];
- int nBlueValues;
- int otherBlues[type1CMaxOtherBlues];
- int nOtherBlues;
- int familyBlues[type1CMaxBlueValues];
- int nFamilyBlues;
- int familyOtherBlues[type1CMaxOtherBlues];
- int nFamilyOtherBlues;
- double blueScale;
- int blueShift;
- int blueFuzz;
- double stdHW;
- GBool hasStdHW;
- double stdVW;
- GBool hasStdVW;
- double stemSnapH[type1CMaxStemSnap];
- int nStemSnapH;
- double stemSnapV[type1CMaxStemSnap];
- int nStemSnapV;
- GBool forceBold;
- GBool hasForceBold;
- double forceBoldThreshold;
- int languageGroup;
- double expansionFactor;
- int initialRandomSeed;
- int subrsOffset;
- double defaultWidthX;
- GBool defaultWidthXFP;
- double nominalWidthX;
- GBool nominalWidthXFP;
-};
-
-struct Type1COp {
- GBool isNum; // true -> number, false -> operator
- GBool isFP; // true -> floating point number, false -> int
- union {
- double num; // if num is true
- int op; // if num is false
- };
-};
-
-struct Type1CEexecBuf {
- FoFiOutputFunc outputFunc;
- void *outputStream;
- GBool ascii; // ASCII encoding?
- Gushort r1; // eexec encryption key
- int line; // number of eexec chars left on current line
-};
-
-//------------------------------------------------------------------------
-// FoFiType1C
-//------------------------------------------------------------------------
-
-class FoFiType1C: public FoFiBase {
-public:
-
- // Create a FoFiType1C object from a memory buffer.
- static FoFiType1C *make(char *fileA, int lenA);
-
- // Create a FoFiType1C object from a file on disk.
- static FoFiType1C *load(char *fileName);
-
- virtual ~FoFiType1C();
-
- // Return the font name.
- char *getName();
-
- // Return the encoding, as an array of 256 names (any of which may
- // be NULL). This is only useful with 8-bit fonts.
- char **getEncoding();
-
- // Return the mapping from CIDs to GIDs, and return the number of
- // CIDs in *<nCIDs>. This is only useful for CID fonts.
- Gushort *getCIDToGIDMap(int *nCIDs);
-
- // Convert to a Type 1 font, suitable for embedding in a PostScript
- // file. This is only useful with 8-bit fonts. If <newEncoding> is
- // not NULL, it will be used in place of the encoding in the Type 1C
- // font. If <ascii> is true the eexec section will be hex-encoded,
- // otherwise it will be left as binary data.
- void convertToType1(char **newEncoding, GBool ascii,
- FoFiOutputFunc outputFunc, void *outputStream);
-
- // Convert to a Type 0 CIDFont, suitable for embedding in a
- // PostScript file. <psName> will be used as the PostScript font
- // name.
- void convertToCIDType0(char *psName,
- FoFiOutputFunc outputFunc, void *outputStream);
-
- // Convert to a Type 0 (but non-CID) composite font, suitable for
- // embedding in a PostScript file. <psName> will be used as the
- // PostScript font name.
- void convertToType0(char *psName,
- FoFiOutputFunc outputFunc, void *outputStream);
-
-private:
-
- FoFiType1C(char *fileA, int lenA, GBool freeFileDataA);
- void eexecCvtGlyph(Type1CEexecBuf *eb, char *glyphName,
- int offset, int nBytes,
- Type1CIndex *subrIdx,
- Type1CPrivateDict *pDict);
- void cvtGlyph(int offset, int nBytes, GString *charBuf,
- Type1CIndex *subrIdx, Type1CPrivateDict *pDict,
- GBool top);
- void cvtGlyphWidth(GBool useOp, GString *charBuf,
- Type1CPrivateDict *pDict);
- void cvtNum(double x, GBool isFP, GString *charBuf);
- void eexecWrite(Type1CEexecBuf *eb, char *s);
- void eexecWriteCharstring(Type1CEexecBuf *eb, Guchar *s, int n);
- GBool parse();
- void readTopDict();
- void readFD(int offset, int length, Type1CPrivateDict *pDict);
- void readPrivateDict(int offset, int length, Type1CPrivateDict *pDict);
- void readFDSelect();
- void buildEncoding();
- GBool readCharset();
- int getOp(int pos, GBool charstring, GBool *ok);
- int getDeltaIntArray(int *arr, int maxLen);
- int getDeltaFPArray(double *arr, int maxLen);
- void getIndex(int pos, Type1CIndex *idx, GBool *ok);
- void getIndexVal(Type1CIndex *idx, int i, Type1CIndexVal *val, GBool *ok);
- char *getString(int sid, char *buf, GBool *ok);
-
- GString *name;
- char **encoding;
-
- Type1CIndex nameIdx;
- Type1CIndex topDictIdx;
- Type1CIndex stringIdx;
- Type1CIndex gsubrIdx;
- Type1CIndex charStringsIdx;
-
- Type1CTopDict topDict;
- Type1CPrivateDict *privateDicts;
-
- int nGlyphs;
- int nFDs;
- Guchar *fdSelect;
- Gushort *charset;
- int gsubrBias;
-
- GBool parsedOk;
-
- Type1COp ops[49]; // operands and operator
- int nOps; // number of operands
- int nHints; // number of hints for the current glyph
- GBool firstOp; // true if we haven't hit the first op yet
- GBool openPath; // true if there is an unclosed path
-};
-
-#endif
+++ /dev/null
-//========================================================================
-//
-// FontEncodingTables.cc
-//
-// Copyright 2001-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#include <aconf.h>
-#include <stdlib.h>
-#include "FontEncodingTables.h"
-
-char *macRomanEncoding[256] = {
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- "space",
- "exclam",
- "quotedbl",
- "numbersign",
- "dollar",
- "percent",
- "ampersand",
- "quotesingle",
- "parenleft",
- "parenright",
- "asterisk",
- "plus",
- "comma",
- "hyphen",
- "period",
- "slash",
- "zero",
- "one",
- "two",
- "three",
- "four",
- "five",
- "six",
- "seven",
- "eight",
- "nine",
- "colon",
- "semicolon",
- "less",
- "equal",
- "greater",
- "question",
- "at",
- "A",
- "B",
- "C",
- "D",
- "E",
- "F",
- "G",
- "H",
- "I",
- "J",
- "K",
- "L",
- "M",
- "N",
- "O",
- "P",
- "Q",
- "R",
- "S",
- "T",
- "U",
- "V",
- "W",
- "X",
- "Y",
- "Z",
- "bracketleft",
- "backslash",
- "bracketright",
- "asciicircum",
- "underscore",
- "grave",
- "a",
- "b",
- "c",
- "d",
- "e",
- "f",
- "g",
- "h",
- "i",
- "j",
- "k",
- "l",
- "m",
- "n",
- "o",
- "p",
- "q",
- "r",
- "s",
- "t",
- "u",
- "v",
- "w",
- "x",
- "y",
- "z",
- "braceleft",
- "bar",
- "braceright",
- "asciitilde",
- NULL,
- "Adieresis",
- "Aring",
- "Ccedilla",
- "Eacute",
- "Ntilde",
- "Odieresis",
- "Udieresis",
- "aacute",
- "agrave",
- "acircumflex",
- "adieresis",
- "atilde",
- "aring",
- "ccedilla",
- "eacute",
- "egrave",
- "ecircumflex",
- "edieresis",
- "iacute",
- "igrave",
- "icircumflex",
- "idieresis",
- "ntilde",
- "oacute",
- "ograve",
- "ocircumflex",
- "odieresis",
- "otilde",
- "uacute",
- "ugrave",
- "ucircumflex",
- "udieresis",
- "dagger",
- "degree",
- "cent",
- "sterling",
- "section",
- "bullet",
- "paragraph",
- "germandbls",
- "registered",
- "copyright",
- "trademark",
- "acute",
- "dieresis",
- "notequal",
- "AE",
- "Oslash",
- "infinity",
- "plusminus",
- "lessequal",
- "greaterequal",
- "yen",
- "mu",
- "partialdiff",
- "summation",
- "product",
- "pi",
- "integral",
- "ordfeminine",
- "ordmasculine",
- "Omega",
- "ae",
- "oslash",
- "questiondown",
- "exclamdown",
- "logicalnot",
- "radical",
- "florin",
- "approxequal",
- "Delta",
- "guillemotleft",
- "guillemotright",
- "ellipsis",
- "space",
- "Agrave",
- "Atilde",
- "Otilde",
- "OE",
- "oe",
- "endash",
- "emdash",
- "quotedblleft",
- "quotedblright",
- "quoteleft",
- "quoteright",
- "divide",
- "lozenge",
- "ydieresis",
- "Ydieresis",
- "fraction",
- "currency",
- "guilsinglleft",
- "guilsinglright",
- "fi",
- "fl",
- "daggerdbl",
- "periodcentered",
- "quotesinglbase",
- "quotedblbase",
- "perthousand",
- "Acircumflex",
- "Ecircumflex",
- "Aacute",
- "Edieresis",
- "Egrave",
- "Iacute",
- "Icircumflex",
- "Idieresis",
- "Igrave",
- "Oacute",
- "Ocircumflex",
- "apple",
- "Ograve",
- "Uacute",
- "Ucircumflex",
- "Ugrave",
- "dotlessi",
- "circumflex",
- "tilde",
- "macron",
- "breve",
- "dotaccent",
- "ring",
- "cedilla",
- "hungarumlaut",
- "ogonek",
- "caron"
-};
-
-char *macExpertEncoding[256] = {
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- "space",
- "exclamsmall",
- "Hungarumlautsmall",
- "centoldstyle",
- "dollaroldstyle",
- "dollarsuperior",
- "ampersandsmall",
- "Acutesmall",
- "parenleftsuperior",
- "parenrightsuperior",
- "twodotenleader",
- "onedotenleader",
- "comma",
- "hyphen",
- "period",
- "fraction",
- "zerooldstyle",
- "oneoldstyle",
- "twooldstyle",
- "threeoldstyle",
- "fouroldstyle",
- "fiveoldstyle",
- "sixoldstyle",
- "sevenoldstyle",
- "eightoldstyle",
- "nineoldstyle",
- "colon",
- "semicolon",
- NULL,
- "threequartersemdash",
- NULL,
- "questionsmall",
- NULL,
- NULL,
- NULL,
- NULL,
- "Ethsmall",
- NULL,
- NULL,
- "onequarter",
- "onehalf",
- "threequarters",
- "oneeighth",
- "threeeighths",
- "fiveeighths",
- "seveneighths",
- "onethird",
- "twothirds",
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- "ff",
- "fi",
- "fl",
- "ffi",
- "ffl",
- "parenleftinferior",
- NULL,
- "parenrightinferior",
- "Circumflexsmall",
- "hypheninferior",
- "Gravesmall",
- "Asmall",
- "Bsmall",
- "Csmall",
- "Dsmall",
- "Esmall",
- "Fsmall",
- "Gsmall",
- "Hsmall",
- "Ismall",
- "Jsmall",
- "Ksmall",
- "Lsmall",
- "Msmall",
- "Nsmall",
- "Osmall",
- "Psmall",
- "Qsmall",
- "Rsmall",
- "Ssmall",
- "Tsmall",
- "Usmall",
- "Vsmall",
- "Wsmall",
- "Xsmall",
- "Ysmall",
- "Zsmall",
- "colonmonetary",
- "onefitted",
- "rupiah",
- "Tildesmall",
- NULL,
- NULL,
- "asuperior",
- "centsuperior",
- NULL,
- NULL,
- NULL,
- NULL,
- "Aacutesmall",
- "Agravesmall",
- "Acircumflexsmall",
- "Adieresissmall",
- "Atildesmall",
- "Aringsmall",
- "Ccedillasmall",
- "Eacutesmall",
- "Egravesmall",
- "Ecircumflexsmall",
- "Edieresissmall",
- "Iacutesmall",
- "Igravesmall",
- "Icircumflexsmall",
- "Idieresissmall",
- "Ntildesmall",
- "Oacutesmall",
- "Ogravesmall",
- "Ocircumflexsmall",
- "Odieresissmall",
- "Otildesmall",
- "Uacutesmall",
- "Ugravesmall",
- "Ucircumflexsmall",
- "Udieresissmall",
- NULL,
- "eightsuperior",
- "fourinferior",
- "threeinferior",
- "sixinferior",
- "eightinferior",
- "seveninferior",
- "Scaronsmall",
- NULL,
- "centinferior",
- "twoinferior",
- NULL,
- "Dieresissmall",
- NULL,
- "Caronsmall",
- "osuperior",
- "fiveinferior",
- NULL,
- "commainferior",
- "periodinferior",
- "Yacutesmall",
- NULL,
- "dollarinferior",
- NULL,
- NULL,
- "Thornsmall",
- NULL,
- "nineinferior",
- "zeroinferior",
- "Zcaronsmall",
- "AEsmall",
- "Oslashsmall",
- "questiondownsmall",
- "oneinferior",
- "Lslashsmall",
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- "Cedillasmall",
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- "OEsmall",
- "figuredash",
- "hyphensuperior",
- NULL,
- NULL,
- NULL,
- NULL,
- "exclamdownsmall",
- NULL,
- "Ydieresissmall",
- NULL,
- "onesuperior",
- "twosuperior",
- "threesuperior",
- "foursuperior",
- "fivesuperior",
- "sixsuperior",
- "sevensuperior",
- "ninesuperior",
- "zerosuperior",
- NULL,
- "esuperior",
- "rsuperior",
- "tsuperior",
- NULL,
- NULL,
- "isuperior",
- "ssuperior",
- "dsuperior",
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- "lsuperior",
- "Ogoneksmall",
- "Brevesmall",
- "Macronsmall",
- "bsuperior",
- "nsuperior",
- "msuperior",
- "commasuperior",
- "periodsuperior",
- "Dotaccentsmall",
- "Ringsmall",
- NULL,
- NULL,
- NULL,
- NULL
-};
-
-char *winAnsiEncoding[256] = {
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- "space",
- "exclam",
- "quotedbl",
- "numbersign",
- "dollar",
- "percent",
- "ampersand",
- "quotesingle",
- "parenleft",
- "parenright",
- "asterisk",
- "plus",
- "comma",
- "hyphen",
- "period",
- "slash",
- "zero",
- "one",
- "two",
- "three",
- "four",
- "five",
- "six",
- "seven",
- "eight",
- "nine",
- "colon",
- "semicolon",
- "less",
- "equal",
- "greater",
- "question",
- "at",
- "A",
- "B",
- "C",
- "D",
- "E",
- "F",
- "G",
- "H",
- "I",
- "J",
- "K",
- "L",
- "M",
- "N",
- "O",
- "P",
- "Q",
- "R",
- "S",
- "T",
- "U",
- "V",
- "W",
- "X",
- "Y",
- "Z",
- "bracketleft",
- "backslash",
- "bracketright",
- "asciicircum",
- "underscore",
- "grave",
- "a",
- "b",
- "c",
- "d",
- "e",
- "f",
- "g",
- "h",
- "i",
- "j",
- "k",
- "l",
- "m",
- "n",
- "o",
- "p",
- "q",
- "r",
- "s",
- "t",
- "u",
- "v",
- "w",
- "x",
- "y",
- "z",
- "braceleft",
- "bar",
- "braceright",
- "asciitilde",
- "bullet",
- "Euro",
- "bullet",
- "quotesinglbase",
- "florin",
- "quotedblbase",
- "ellipsis",
- "dagger",
- "daggerdbl",
- "circumflex",
- "perthousand",
- "Scaron",
- "guilsinglleft",
- "OE",
- "bullet",
- "Zcaron",
- "bullet",
- "bullet",
- "quoteleft",
- "quoteright",
- "quotedblleft",
- "quotedblright",
- "bullet",
- "endash",
- "emdash",
- "tilde",
- "trademark",
- "scaron",
- "guilsinglright",
- "oe",
- "bullet",
- "zcaron",
- "Ydieresis",
- "space",
- "exclamdown",
- "cent",
- "sterling",
- "currency",
- "yen",
- "brokenbar",
- "section",
- "dieresis",
- "copyright",
- "ordfeminine",
- "guillemotleft",
- "logicalnot",
- "hyphen",
- "registered",
- "macron",
- "degree",
- "plusminus",
- "twosuperior",
- "threesuperior",
- "acute",
- "mu",
- "paragraph",
- "periodcentered",
- "cedilla",
- "onesuperior",
- "ordmasculine",
- "guillemotright",
- "onequarter",
- "onehalf",
- "threequarters",
- "questiondown",
- "Agrave",
- "Aacute",
- "Acircumflex",
- "Atilde",
- "Adieresis",
- "Aring",
- "AE",
- "Ccedilla",
- "Egrave",
- "Eacute",
- "Ecircumflex",
- "Edieresis",
- "Igrave",
- "Iacute",
- "Icircumflex",
- "Idieresis",
- "Eth",
- "Ntilde",
- "Ograve",
- "Oacute",
- "Ocircumflex",
- "Otilde",
- "Odieresis",
- "multiply",
- "Oslash",
- "Ugrave",
- "Uacute",
- "Ucircumflex",
- "Udieresis",
- "Yacute",
- "Thorn",
- "germandbls",
- "agrave",
- "aacute",
- "acircumflex",
- "atilde",
- "adieresis",
- "aring",
- "ae",
- "ccedilla",
- "egrave",
- "eacute",
- "ecircumflex",
- "edieresis",
- "igrave",
- "iacute",
- "icircumflex",
- "idieresis",
- "eth",
- "ntilde",
- "ograve",
- "oacute",
- "ocircumflex",
- "otilde",
- "odieresis",
- "divide",
- "oslash",
- "ugrave",
- "uacute",
- "ucircumflex",
- "udieresis",
- "yacute",
- "thorn",
- "ydieresis"
-};
-
-char *standardEncoding[256] = {
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- "space",
- "exclam",
- "quotedbl",
- "numbersign",
- "dollar",
- "percent",
- "ampersand",
- "quoteright",
- "parenleft",
- "parenright",
- "asterisk",
- "plus",
- "comma",
- "hyphen",
- "period",
- "slash",
- "zero",
- "one",
- "two",
- "three",
- "four",
- "five",
- "six",
- "seven",
- "eight",
- "nine",
- "colon",
- "semicolon",
- "less",
- "equal",
- "greater",
- "question",
- "at",
- "A",
- "B",
- "C",
- "D",
- "E",
- "F",
- "G",
- "H",
- "I",
- "J",
- "K",
- "L",
- "M",
- "N",
- "O",
- "P",
- "Q",
- "R",
- "S",
- "T",
- "U",
- "V",
- "W",
- "X",
- "Y",
- "Z",
- "bracketleft",
- "backslash",
- "bracketright",
- "asciicircum",
- "underscore",
- "quoteleft",
- "a",
- "b",
- "c",
- "d",
- "e",
- "f",
- "g",
- "h",
- "i",
- "j",
- "k",
- "l",
- "m",
- "n",
- "o",
- "p",
- "q",
- "r",
- "s",
- "t",
- "u",
- "v",
- "w",
- "x",
- "y",
- "z",
- "braceleft",
- "bar",
- "braceright",
- "asciitilde",
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- "exclamdown",
- "cent",
- "sterling",
- "fraction",
- "yen",
- "florin",
- "section",
- "currency",
- "quotesingle",
- "quotedblleft",
- "guillemotleft",
- "guilsinglleft",
- "guilsinglright",
- "fi",
- "fl",
- NULL,
- "endash",
- "dagger",
- "daggerdbl",
- "periodcentered",
- NULL,
- "paragraph",
- "bullet",
- "quotesinglbase",
- "quotedblbase",
- "quotedblright",
- "guillemotright",
- "ellipsis",
- "perthousand",
- NULL,
- "questiondown",
- NULL,
- "grave",
- "acute",
- "circumflex",
- "tilde",
- "macron",
- "breve",
- "dotaccent",
- "dieresis",
- NULL,
- "ring",
- "cedilla",
- NULL,
- "hungarumlaut",
- "ogonek",
- "caron",
- "emdash",
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- "AE",
- NULL,
- "ordfeminine",
- NULL,
- NULL,
- NULL,
- NULL,
- "Lslash",
- "Oslash",
- "OE",
- "ordmasculine",
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- "ae",
- NULL,
- NULL,
- NULL,
- "dotlessi",
- NULL,
- NULL,
- "lslash",
- "oslash",
- "oe",
- "germandbls",
- NULL,
- NULL,
- NULL,
- NULL
-};
-
-char *expertEncoding[256] = {
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- "space",
- "exclamsmall",
- "Hungarumlautsmall",
- NULL,
- "dollaroldstyle",
- "dollarsuperior",
- "ampersandsmall",
- "Acutesmall",
- "parenleftsuperior",
- "parenrightsuperior",
- "twodotenleader",
- "onedotenleader",
- "comma",
- "hyphen",
- "period",
- "fraction",
- "zerooldstyle",
- "oneoldstyle",
- "twooldstyle",
- "threeoldstyle",
- "fouroldstyle",
- "fiveoldstyle",
- "sixoldstyle",
- "sevenoldstyle",
- "eightoldstyle",
- "nineoldstyle",
- "colon",
- "semicolon",
- "commasuperior",
- "threequartersemdash",
- "periodsuperior",
- "questionsmall",
- NULL,
- "asuperior",
- "bsuperior",
- "centsuperior",
- "dsuperior",
- "esuperior",
- NULL,
- NULL,
- NULL,
- "isuperior",
- NULL,
- NULL,
- "lsuperior",
- "msuperior",
- "nsuperior",
- "osuperior",
- NULL,
- NULL,
- "rsuperior",
- "ssuperior",
- "tsuperior",
- NULL,
- "ff",
- "fi",
- "fl",
- "ffi",
- "ffl",
- "parenleftinferior",
- NULL,
- "parenrightinferior",
- "Circumflexsmall",
- "hyphensuperior",
- "Gravesmall",
- "Asmall",
- "Bsmall",
- "Csmall",
- "Dsmall",
- "Esmall",
- "Fsmall",
- "Gsmall",
- "Hsmall",
- "Ismall",
- "Jsmall",
- "Ksmall",
- "Lsmall",
- "Msmall",
- "Nsmall",
- "Osmall",
- "Psmall",
- "Qsmall",
- "Rsmall",
- "Ssmall",
- "Tsmall",
- "Usmall",
- "Vsmall",
- "Wsmall",
- "Xsmall",
- "Ysmall",
- "Zsmall",
- "colonmonetary",
- "onefitted",
- "rupiah",
- "Tildesmall",
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- "exclamdownsmall",
- "centoldstyle",
- "Lslashsmall",
- NULL,
- NULL,
- "Scaronsmall",
- "Zcaronsmall",
- "Dieresissmall",
- "Brevesmall",
- "Caronsmall",
- NULL,
- "Dotaccentsmall",
- NULL,
- NULL,
- "Macronsmall",
- NULL,
- NULL,
- "figuredash",
- "hypheninferior",
- NULL,
- NULL,
- "Ogoneksmall",
- "Ringsmall",
- "Cedillasmall",
- NULL,
- NULL,
- NULL,
- "onequarter",
- "onehalf",
- "threequarters",
- "questiondownsmall",
- "oneeighth",
- "threeeighths",
- "fiveeighths",
- "seveneighths",
- "onethird",
- "twothirds",
- NULL,
- NULL,
- "zerosuperior",
- "onesuperior",
- "twosuperior",
- "threesuperior",
- "foursuperior",
- "fivesuperior",
- "sixsuperior",
- "sevensuperior",
- "eightsuperior",
- "ninesuperior",
- "zeroinferior",
- "oneinferior",
- "twoinferior",
- "threeinferior",
- "fourinferior",
- "fiveinferior",
- "sixinferior",
- "seveninferior",
- "eightinferior",
- "nineinferior",
- "centinferior",
- "dollarinferior",
- "periodinferior",
- "commainferior",
- "Agravesmall",
- "Aacutesmall",
- "Acircumflexsmall",
- "Atildesmall",
- "Adieresissmall",
- "Aringsmall",
- "AEsmall",
- "Ccedillasmall",
- "Egravesmall",
- "Eacutesmall",
- "Ecircumflexsmall",
- "Edieresissmall",
- "Igravesmall",
- "Iacutesmall",
- "Icircumflexsmall",
- "Idieresissmall",
- "Ethsmall",
- "Ntildesmall",
- "Ogravesmall",
- "Oacutesmall",
- "Ocircumflexsmall",
- "Otildesmall",
- "Odieresissmall",
- "OEsmall",
- "Oslashsmall",
- "Ugravesmall",
- "Uacutesmall",
- "Ucircumflexsmall",
- "Udieresissmall",
- "Yacutesmall",
- "Thornsmall",
- "Ydieresissmall"
-};
-
-char *symbolEncoding[256] = {
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- "space",
- "exclam",
- "universal",
- "numbersign",
- "existential",
- "percent",
- "ampersand",
- "suchthat",
- "parenleft",
- "parenright",
- "asteriskmath",
- "plus",
- "comma",
- "minus",
- "period",
- "slash",
- "zero",
- "one",
- "two",
- "three",
- "four",
- "five",
- "six",
- "seven",
- "eight",
- "nine",
- "colon",
- "semicolon",
- "less",
- "equal",
- "greater",
- "question",
- "congruent",
- "Alpha",
- "Beta",
- "Chi",
- "Delta",
- "Epsilon",
- "Phi",
- "Gamma",
- "Eta",
- "Iota",
- "theta1",
- "Kappa",
- "Lambda",
- "Mu",
- "Nu",
- "Omicron",
- "Pi",
- "Theta",
- "Rho",
- "Sigma",
- "Tau",
- "Upsilon",
- "sigma1",
- "Omega",
- "Xi",
- "Psi",
- "Zeta",
- "bracketleft",
- "therefore",
- "bracketright",
- "perpendicular",
- "underscore",
- "radicalex",
- "alpha",
- "beta",
- "chi",
- "delta",
- "epsilon",
- "phi",
- "gamma",
- "eta",
- "iota",
- "phi1",
- "kappa",
- "lambda",
- "mu",
- "nu",
- "omicron",
- "pi",
- "theta",
- "rho",
- "sigma",
- "tau",
- "upsilon",
- "omega1",
- "omega",
- "xi",
- "psi",
- "zeta",
- "braceleft",
- "bar",
- "braceright",
- "similar",
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- "Upsilon1",
- "minute",
- "lessequal",
- "fraction",
- "infinity",
- "florin",
- "club",
- "diamond",
- "heart",
- "spade",
- "arrowboth",
- "arrowleft",
- "arrowup",
- "arrowright",
- "arrowdown",
- "degree",
- "plusminus",
- "second",
- "greaterequal",
- "multiply",
- "proportional",
- "partialdiff",
- "bullet",
- "divide",
- "notequal",
- "equivalence",
- "approxequal",
- "ellipsis",
- "arrowvertex",
- "arrowhorizex",
- "carriagereturn",
- "aleph",
- "Ifraktur",
- "Rfraktur",
- "weierstrass",
- "circlemultiply",
- "circleplus",
- "emptyset",
- "intersection",
- "union",
- "propersuperset",
- "reflexsuperset",
- "notsubset",
- "propersubset",
- "reflexsubset",
- "element",
- "notelement",
- "angle",
- "gradient",
- "registerserif",
- "copyrightserif",
- "trademarkserif",
- "product",
- "radical",
- "dotmath",
- "logicalnot",
- "logicaland",
- "logicalor",
- "arrowdblboth",
- "arrowdblleft",
- "arrowdblup",
- "arrowdblright",
- "arrowdbldown",
- "lozenge",
- "angleleft",
- "registersans",
- "copyrightsans",
- "trademarksans",
- "summation",
- "parenlefttp",
- "parenleftex",
- "parenleftbt",
- "bracketlefttp",
- "bracketleftex",
- "bracketleftbt",
- "bracelefttp",
- "braceleftmid",
- "braceleftbt",
- "braceex",
- NULL,
- "angleright",
- "integral",
- "integraltp",
- "integralex",
- "integralbt",
- "parenrighttp",
- "parenrightex",
- "parenrightbt",
- "bracketrighttp",
- "bracketrightex",
- "bracketrightbt",
- "bracerighttp",
- "bracerightmid",
- "bracerightbt",
- NULL
-};
-
-char *zapfDingbatsEncoding[256] = {
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- "space",
- "a1",
- "a2",
- "a202",
- "a3",
- "a4",
- "a5",
- "a119",
- "a118",
- "a117",
- "a11",
- "a12",
- "a13",
- "a14",
- "a15",
- "a16",
- "a105",
- "a17",
- "a18",
- "a19",
- "a20",
- "a21",
- "a22",
- "a23",
- "a24",
- "a25",
- "a26",
- "a27",
- "a28",
- "a6",
- "a7",
- "a8",
- "a9",
- "a10",
- "a29",
- "a30",
- "a31",
- "a32",
- "a33",
- "a34",
- "a35",
- "a36",
- "a37",
- "a38",
- "a39",
- "a40",
- "a41",
- "a42",
- "a43",
- "a44",
- "a45",
- "a46",
- "a47",
- "a48",
- "a49",
- "a50",
- "a51",
- "a52",
- "a53",
- "a54",
- "a55",
- "a56",
- "a57",
- "a58",
- "a59",
- "a60",
- "a61",
- "a62",
- "a63",
- "a64",
- "a65",
- "a66",
- "a67",
- "a68",
- "a69",
- "a70",
- "a71",
- "a72",
- "a73",
- "a74",
- "a203",
- "a75",
- "a204",
- "a76",
- "a77",
- "a78",
- "a79",
- "a81",
- "a82",
- "a83",
- "a84",
- "a97",
- "a98",
- "a99",
- "a100",
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- "a101",
- "a102",
- "a103",
- "a104",
- "a106",
- "a107",
- "a108",
- "a112",
- "a111",
- "a110",
- "a109",
- "a120",
- "a121",
- "a122",
- "a123",
- "a124",
- "a125",
- "a126",
- "a127",
- "a128",
- "a129",
- "a130",
- "a131",
- "a132",
- "a133",
- "a134",
- "a135",
- "a136",
- "a137",
- "a138",
- "a139",
- "a140",
- "a141",
- "a142",
- "a143",
- "a144",
- "a145",
- "a146",
- "a147",
- "a148",
- "a149",
- "a150",
- "a151",
- "a152",
- "a153",
- "a154",
- "a155",
- "a156",
- "a157",
- "a158",
- "a159",
- "a160",
- "a161",
- "a163",
- "a164",
- "a196",
- "a165",
- "a192",
- "a166",
- "a167",
- "a168",
- "a169",
- "a170",
- "a171",
- "a172",
- "a173",
- "a162",
- "a174",
- "a175",
- "a176",
- "a177",
- "a178",
- "a179",
- "a193",
- "a180",
- "a199",
- "a181",
- "a200",
- "a182",
- NULL,
- "a201",
- "a183",
- "a184",
- "a197",
- "a185",
- "a194",
- "a198",
- "a186",
- "a195",
- "a187",
- "a188",
- "a189",
- "a190",
- "a191",
- NULL
-};
+++ /dev/null
-//========================================================================
-//
-// FontEncodingTables.h
-//
-// Copyright 2001-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#ifndef FONTENCODINGTABLES_H
-#define FONTENCODINGTABLES_H
-
-extern char *macRomanEncoding[];
-extern char *macExpertEncoding[];
-extern char *winAnsiEncoding[];
-extern char *standardEncoding[];
-extern char *expertEncoding[];
-extern char *symbolEncoding[];
-extern char *zapfDingbatsEncoding[];
-
-#endif
+++ /dev/null
-//========================================================================
-//
-// Function.cc
-//
-// Copyright 2001-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma implementation
-#endif
-
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <math.h>
-#include "gmem.h"
-#include "Object.h"
-#include "Dict.h"
-#include "Stream.h"
-#include "Error.h"
-#include "Function.h"
-
-//------------------------------------------------------------------------
-// Function
-//------------------------------------------------------------------------
-
-Function::Function() {
-}
-
-Function::~Function() {
-}
-
-Function *Function::parse(Object *funcObj) {
- Function *func;
- Dict *dict;
- int funcType;
- Object obj1;
-
- if (funcObj->isStream()) {
- dict = funcObj->streamGetDict();
- } else if (funcObj->isDict()) {
- dict = funcObj->getDict();
- } else if (funcObj->isName("Identity")) {
- return new IdentityFunction();
- } else {
- error(-1, "Expected function dictionary or stream");
- return NULL;
- }
-
- if (!dict->lookup("FunctionType", &obj1)->isInt()) {
- error(-1, "Function type is missing or wrong type");
- obj1.free();
- return NULL;
- }
- funcType = obj1.getInt();
- obj1.free();
-
- if (funcType == 0) {
- func = new SampledFunction(funcObj, dict);
- } else if (funcType == 2) {
- func = new ExponentialFunction(funcObj, dict);
- } else if (funcType == 3) {
- func = new StitchingFunction(funcObj, dict);
- } else if (funcType == 4) {
- func = new PostScriptFunction(funcObj, dict);
- } else {
- error(-1, "Unimplemented function type (%d)", funcType);
- return NULL;
- }
- if (!func->isOk()) {
- delete func;
- return NULL;
- }
-
- return func;
-}
-
-GBool Function::init(Dict *dict) {
- Object obj1, obj2;
- int i;
-
- //----- Domain
- if (!dict->lookup("Domain", &obj1)->isArray()) {
- error(-1, "Function is missing domain");
- goto err2;
- }
- m = obj1.arrayGetLength() / 2;
- if (m > funcMaxInputs) {
- error(-1, "Functions with more than %d inputs are unsupported",
- funcMaxInputs);
- goto err2;
- }
- for (i = 0; i < m; ++i) {
- obj1.arrayGet(2*i, &obj2);
- if (!obj2.isNum()) {
- error(-1, "Illegal value in function domain array");
- goto err1;
- }
- domain[i][0] = obj2.getNum();
- obj2.free();
- obj1.arrayGet(2*i+1, &obj2);
- if (!obj2.isNum()) {
- error(-1, "Illegal value in function domain array");
- goto err1;
- }
- domain[i][1] = obj2.getNum();
- obj2.free();
- }
- obj1.free();
-
- //----- Range
- hasRange = gFalse;
- n = 0;
- if (dict->lookup("Range", &obj1)->isArray()) {
- hasRange = gTrue;
- n = obj1.arrayGetLength() / 2;
- if (n > funcMaxOutputs) {
- error(-1, "Functions with more than %d outputs are unsupported",
- funcMaxOutputs);
- goto err2;
- }
- for (i = 0; i < n; ++i) {
- obj1.arrayGet(2*i, &obj2);
- if (!obj2.isNum()) {
- error(-1, "Illegal value in function range array");
- goto err1;
- }
- range[i][0] = obj2.getNum();
- obj2.free();
- obj1.arrayGet(2*i+1, &obj2);
- if (!obj2.isNum()) {
- error(-1, "Illegal value in function range array");
- goto err1;
- }
- range[i][1] = obj2.getNum();
- obj2.free();
- }
- }
- obj1.free();
-
- return gTrue;
-
- err1:
- obj2.free();
- err2:
- obj1.free();
- return gFalse;
-}
-
-//------------------------------------------------------------------------
-// IdentityFunction
-//------------------------------------------------------------------------
-
-IdentityFunction::IdentityFunction() {
- int i;
-
- // fill these in with arbitrary values just in case they get used
- // somewhere
- m = funcMaxInputs;
- n = funcMaxOutputs;
- for (i = 0; i < funcMaxInputs; ++i) {
- domain[i][0] = 0;
- domain[i][1] = 1;
- }
- hasRange = gFalse;
-}
-
-IdentityFunction::~IdentityFunction() {
-}
-
-void IdentityFunction::transform(double *in, double *out) {
- int i;
-
- for (i = 0; i < funcMaxOutputs; ++i) {
- out[i] = in[i];
- }
-}
-
-//------------------------------------------------------------------------
-// SampledFunction
-//------------------------------------------------------------------------
-
-SampledFunction::SampledFunction(Object *funcObj, Dict *dict) {
- Stream *str;
- int sampleBits;
- double sampleMul;
- Object obj1, obj2;
- Guint buf, bitMask;
- int bits;
- int s;
- int i;
-
- samples = NULL;
- ok = gFalse;
-
- //----- initialize the generic stuff
- if (!init(dict)) {
- goto err1;
- }
- if (!hasRange) {
- error(-1, "Type 0 function is missing range");
- goto err1;
- }
-
- //----- get the stream
- if (!funcObj->isStream()) {
- error(-1, "Type 0 function isn't a stream");
- goto err1;
- }
- str = funcObj->getStream();
-
- //----- Size
- if (!dict->lookup("Size", &obj1)->isArray() ||
- obj1.arrayGetLength() != m) {
- error(-1, "Function has missing or invalid size array");
- goto err2;
- }
- for (i = 0; i < m; ++i) {
- obj1.arrayGet(i, &obj2);
- if (!obj2.isInt()) {
- error(-1, "Illegal value in function size array");
- goto err3;
- }
- sampleSize[i] = obj2.getInt();
- obj2.free();
- }
- obj1.free();
- idxMul[0] = n;
- for (i = 1; i < m; ++i) {
- idxMul[i] = idxMul[i-1] * sampleSize[i-1];
- }
-
- //----- BitsPerSample
- if (!dict->lookup("BitsPerSample", &obj1)->isInt()) {
- error(-1, "Function has missing or invalid BitsPerSample");
- goto err2;
- }
- sampleBits = obj1.getInt();
- sampleMul = 1.0 / (double)((1 << sampleBits) - 1);
- obj1.free();
-
- //----- Encode
- if (dict->lookup("Encode", &obj1)->isArray() &&
- obj1.arrayGetLength() == 2*m) {
- for (i = 0; i < m; ++i) {
- obj1.arrayGet(2*i, &obj2);
- if (!obj2.isNum()) {
- error(-1, "Illegal value in function encode array");
- goto err3;
- }
- encode[i][0] = obj2.getNum();
- obj2.free();
- obj1.arrayGet(2*i+1, &obj2);
- if (!obj2.isNum()) {
- error(-1, "Illegal value in function encode array");
- goto err3;
- }
- encode[i][1] = obj2.getNum();
- obj2.free();
- }
- } else {
- for (i = 0; i < m; ++i) {
- encode[i][0] = 0;
- encode[i][1] = sampleSize[i] - 1;
- }
- }
- obj1.free();
- for (i = 0; i < m; ++i) {
- inputMul[i] = (encode[i][1] - encode[i][0]) /
- (domain[i][1] - domain[i][0]);
- }
-
- //----- Decode
- if (dict->lookup("Decode", &obj1)->isArray() &&
- obj1.arrayGetLength() == 2*n) {
- for (i = 0; i < n; ++i) {
- obj1.arrayGet(2*i, &obj2);
- if (!obj2.isNum()) {
- error(-1, "Illegal value in function decode array");
- goto err3;
- }
- decode[i][0] = obj2.getNum();
- obj2.free();
- obj1.arrayGet(2*i+1, &obj2);
- if (!obj2.isNum()) {
- error(-1, "Illegal value in function decode array");
- goto err3;
- }
- decode[i][1] = obj2.getNum();
- obj2.free();
- }
- } else {
- for (i = 0; i < n; ++i) {
- decode[i][0] = range[i][0];
- decode[i][1] = range[i][1];
- }
- }
- obj1.free();
-
- //----- samples
- nSamples = n;
- for (i = 0; i < m; ++i)
- nSamples *= sampleSize[i];
- samples = (double *)gmallocn(nSamples, sizeof(double));
- buf = 0;
- bits = 0;
- bitMask = (1 << sampleBits) - 1;
- str->reset();
- for (i = 0; i < nSamples; ++i) {
- if (sampleBits == 8) {
- s = str->getChar();
- } else if (sampleBits == 16) {
- s = str->getChar();
- s = (s << 8) + str->getChar();
- } else if (sampleBits == 32) {
- s = str->getChar();
- s = (s << 8) + str->getChar();
- s = (s << 8) + str->getChar();
- s = (s << 8) + str->getChar();
- } else {
- while (bits < sampleBits) {
- buf = (buf << 8) | (str->getChar() & 0xff);
- bits += 8;
- }
- s = (buf >> (bits - sampleBits)) & bitMask;
- bits -= sampleBits;
- }
- samples[i] = (double)s * sampleMul;
- }
- str->close();
-
- ok = gTrue;
- return;
-
- err3:
- obj2.free();
- err2:
- obj1.free();
- err1:
- return;
-}
-
-SampledFunction::~SampledFunction() {
- if (samples) {
- gfree(samples);
- }
-}
-
-SampledFunction::SampledFunction(SampledFunction *func) {
- memcpy(this, func, sizeof(SampledFunction));
- samples = (double *)gmallocn(nSamples, sizeof(double));
- memcpy(samples, func->samples, nSamples * sizeof(double));
-}
-
-void SampledFunction::transform(double *in, double *out) {
- double x;
- int e[funcMaxInputs][2];
- double efrac0[funcMaxInputs];
- double efrac1[funcMaxInputs];
- double s[1 << funcMaxInputs];
- int i, j, k, idx, t;
-
- // map input values into sample array
- for (i = 0; i < m; ++i) {
- x = (in[i] - domain[i][0]) * inputMul[i] + encode[i][0];
- if (x < 0) {
- x = 0;
- } else if (x > sampleSize[i] - 1) {
- x = sampleSize[i] - 1;
- }
- e[i][0] = (int)x;
- if ((e[i][1] = e[i][0] + 1) >= sampleSize[i]) {
- // this happens if in[i] = domain[i][1]
- e[i][1] = e[i][0];
- }
- efrac1[i] = x - e[i][0];
- efrac0[i] = 1 - efrac1[i];
- }
-
- // for each output, do m-linear interpolation
- for (i = 0; i < n; ++i) {
-
- // pull 2^m values out of the sample array
- for (j = 0; j < (1<<m); ++j) {
- idx = i;
- for (k = 0, t = j; k < m; ++k, t >>= 1) {
- idx += idxMul[k] * (e[k][t & 1]);
- }
- s[j] = samples[idx];
- }
-
- // do m sets of interpolations
- for (j = 0, t = (1<<m); j < m; ++j, t >>= 1) {
- for (k = 0; k < t; k += 2) {
- s[k >> 1] = efrac0[j] * s[k] + efrac1[j] * s[k+1];
- }
- }
-
- // map output value to range
- out[i] = s[0] * (decode[i][1] - decode[i][0]) + decode[i][0];
- if (out[i] < range[i][0]) {
- out[i] = range[i][0];
- } else if (out[i] > range[i][1]) {
- out[i] = range[i][1];
- }
- }
-}
-
-//------------------------------------------------------------------------
-// ExponentialFunction
-//------------------------------------------------------------------------
-
-ExponentialFunction::ExponentialFunction(Object *funcObj, Dict *dict) {
- Object obj1, obj2;
- int i;
-
- ok = gFalse;
-
- //----- initialize the generic stuff
- if (!init(dict)) {
- goto err1;
- }
- if (m != 1) {
- error(-1, "Exponential function with more than one input");
- goto err1;
- }
-
- //----- C0
- if (dict->lookup("C0", &obj1)->isArray()) {
- if (hasRange && obj1.arrayGetLength() != n) {
- error(-1, "Function's C0 array is wrong length");
- goto err2;
- }
- n = obj1.arrayGetLength();
- for (i = 0; i < n; ++i) {
- obj1.arrayGet(i, &obj2);
- if (!obj2.isNum()) {
- error(-1, "Illegal value in function C0 array");
- goto err3;
- }
- c0[i] = obj2.getNum();
- obj2.free();
- }
- } else {
- if (hasRange && n != 1) {
- error(-1, "Function's C0 array is wrong length");
- goto err2;
- }
- n = 1;
- c0[0] = 0;
- }
- obj1.free();
-
- //----- C1
- if (dict->lookup("C1", &obj1)->isArray()) {
- if (obj1.arrayGetLength() != n) {
- error(-1, "Function's C1 array is wrong length");
- goto err2;
- }
- for (i = 0; i < n; ++i) {
- obj1.arrayGet(i, &obj2);
- if (!obj2.isNum()) {
- error(-1, "Illegal value in function C1 array");
- goto err3;
- }
- c1[i] = obj2.getNum();
- obj2.free();
- }
- } else {
- if (n != 1) {
- error(-1, "Function's C1 array is wrong length");
- goto err2;
- }
- c1[0] = 1;
- }
- obj1.free();
-
- //----- N (exponent)
- if (!dict->lookup("N", &obj1)->isNum()) {
- error(-1, "Function has missing or invalid N");
- goto err2;
- }
- e = obj1.getNum();
- obj1.free();
-
- ok = gTrue;
- return;
-
- err3:
- obj2.free();
- err2:
- obj1.free();
- err1:
- return;
-}
-
-ExponentialFunction::~ExponentialFunction() {
-}
-
-ExponentialFunction::ExponentialFunction(ExponentialFunction *func) {
- memcpy(this, func, sizeof(ExponentialFunction));
-}
-
-void ExponentialFunction::transform(double *in, double *out) {
- double x;
- int i;
-
- if (in[0] < domain[0][0]) {
- x = domain[0][0];
- } else if (in[0] > domain[0][1]) {
- x = domain[0][1];
- } else {
- x = in[0];
- }
- for (i = 0; i < n; ++i) {
- out[i] = c0[i] + pow(x, e) * (c1[i] - c0[i]);
- if (hasRange) {
- if (out[i] < range[i][0]) {
- out[i] = range[i][0];
- } else if (out[i] > range[i][1]) {
- out[i] = range[i][1];
- }
- }
- }
- return;
-}
-
-//------------------------------------------------------------------------
-// StitchingFunction
-//------------------------------------------------------------------------
-
-StitchingFunction::StitchingFunction(Object *funcObj, Dict *dict) {
- Object obj1, obj2;
- int i;
-
- ok = gFalse;
- funcs = NULL;
- bounds = NULL;
- encode = NULL;
-
- //----- initialize the generic stuff
- if (!init(dict)) {
- goto err1;
- }
- if (m != 1) {
- error(-1, "Stitching function with more than one input");
- goto err1;
- }
-
- //----- Functions
- if (!dict->lookup("Functions", &obj1)->isArray()) {
- error(-1, "Missing 'Functions' entry in stitching function");
- goto err1;
- }
- k = obj1.arrayGetLength();
- funcs = (Function **)gmallocn(k, sizeof(Function *));
- bounds = (double *)gmallocn(k + 1, sizeof(double));
- encode = (double *)gmallocn(2 * k, sizeof(double));
- for (i = 0; i < k; ++i) {
- funcs[i] = NULL;
- }
- for (i = 0; i < k; ++i) {
- if (!(funcs[i] = Function::parse(obj1.arrayGet(i, &obj2)))) {
- goto err2;
- }
- if (i > 0 && (funcs[i]->getInputSize() != 1 ||
- funcs[i]->getOutputSize() != funcs[0]->getOutputSize())) {
- error(-1, "Incompatible subfunctions in stitching function");
- goto err2;
- }
- obj2.free();
- }
- obj1.free();
-
- //----- Bounds
- if (!dict->lookup("Bounds", &obj1)->isArray() ||
- obj1.arrayGetLength() != k - 1) {
- error(-1, "Missing or invalid 'Bounds' entry in stitching function");
- goto err1;
- }
- bounds[0] = domain[0][0];
- for (i = 1; i < k; ++i) {
- if (!obj1.arrayGet(i - 1, &obj2)->isNum()) {
- error(-1, "Invalid type in 'Bounds' array in stitching function");
- goto err2;
- }
- bounds[i] = obj2.getNum();
- obj2.free();
- }
- bounds[k] = domain[0][1];
- obj1.free();
-
- //----- Encode
- if (!dict->lookup("Encode", &obj1)->isArray() ||
- obj1.arrayGetLength() != 2 * k) {
- error(-1, "Missing or invalid 'Encode' entry in stitching function");
- goto err1;
- }
- for (i = 0; i < 2 * k; ++i) {
- if (!obj1.arrayGet(i, &obj2)->isNum()) {
- error(-1, "Invalid type in 'Encode' array in stitching function");
- goto err2;
- }
- encode[i] = obj2.getNum();
- obj2.free();
- }
- obj1.free();
-
- ok = gTrue;
- return;
-
- err2:
- obj2.free();
- err1:
- obj1.free();
-}
-
-StitchingFunction::StitchingFunction(StitchingFunction *func) {
- int i;
-
- k = func->k;
- funcs = (Function **)gmallocn(k, sizeof(Function *));
- for (i = 0; i < k; ++i) {
- funcs[i] = func->funcs[i]->copy();
- }
- bounds = (double *)gmallocn(k + 1, sizeof(double));
- memcpy(bounds, func->bounds, (k + 1) * sizeof(double));
- encode = (double *)gmallocn(2 * k, sizeof(double));
- memcpy(encode, func->encode, 2 * k * sizeof(double));
- ok = gTrue;
-}
-
-StitchingFunction::~StitchingFunction() {
- int i;
-
- if (funcs) {
- for (i = 0; i < k; ++i) {
- if (funcs[i]) {
- delete funcs[i];
- }
- }
- }
- gfree(funcs);
- gfree(bounds);
- gfree(encode);
-}
-
-void StitchingFunction::transform(double *in, double *out) {
- double x;
- int i;
-
- if (in[0] < domain[0][0]) {
- x = domain[0][0];
- } else if (in[0] > domain[0][1]) {
- x = domain[0][1];
- } else {
- x = in[0];
- }
- for (i = 0; i < k - 1; ++i) {
- if (x < bounds[i+1]) {
- break;
- }
- }
- x = encode[2*i] + ((x - bounds[i]) / (bounds[i+1] - bounds[i])) *
- (encode[2*i+1] - encode[2*i]);
- funcs[i]->transform(&x, out);
-}
-
-//------------------------------------------------------------------------
-// PostScriptFunction
-//------------------------------------------------------------------------
-
-enum PSOp {
- psOpAbs,
- psOpAdd,
- psOpAnd,
- psOpAtan,
- psOpBitshift,
- psOpCeiling,
- psOpCopy,
- psOpCos,
- psOpCvi,
- psOpCvr,
- psOpDiv,
- psOpDup,
- psOpEq,
- psOpExch,
- psOpExp,
- psOpFalse,
- psOpFloor,
- psOpGe,
- psOpGt,
- psOpIdiv,
- psOpIndex,
- psOpLe,
- psOpLn,
- psOpLog,
- psOpLt,
- psOpMod,
- psOpMul,
- psOpNe,
- psOpNeg,
- psOpNot,
- psOpOr,
- psOpPop,
- psOpRoll,
- psOpRound,
- psOpSin,
- psOpSqrt,
- psOpSub,
- psOpTrue,
- psOpTruncate,
- psOpXor,
- psOpIf,
- psOpIfelse,
- psOpReturn
-};
-
-// Note: 'if' and 'ifelse' are parsed separately.
-// The rest are listed here in alphabetical order.
-// The index in this table is equivalent to the entry in PSOp.
-char *psOpNames[] = {
- "abs",
- "add",
- "and",
- "atan",
- "bitshift",
- "ceiling",
- "copy",
- "cos",
- "cvi",
- "cvr",
- "div",
- "dup",
- "eq",
- "exch",
- "exp",
- "false",
- "floor",
- "ge",
- "gt",
- "idiv",
- "index",
- "le",
- "ln",
- "log",
- "lt",
- "mod",
- "mul",
- "ne",
- "neg",
- "not",
- "or",
- "pop",
- "roll",
- "round",
- "sin",
- "sqrt",
- "sub",
- "true",
- "truncate",
- "xor"
-};
-
-#define nPSOps (sizeof(psOpNames) / sizeof(char *))
-
-enum PSObjectType {
- psBool,
- psInt,
- psReal,
- psOperator,
- psBlock
-};
-
-// In the code array, 'if'/'ifelse' operators take up three slots
-// plus space for the code in the subclause(s).
-//
-// +---------------------------------+
-// | psOperator: psOpIf / psOpIfelse |
-// +---------------------------------+
-// | psBlock: ptr=<A> |
-// +---------------------------------+
-// | psBlock: ptr=<B> |
-// +---------------------------------+
-// | if clause |
-// | ... |
-// | psOperator: psOpReturn |
-// +---------------------------------+
-// <A> | else clause |
-// | ... |
-// | psOperator: psOpReturn |
-// +---------------------------------+
-// <B> | ... |
-//
-// For 'if', pointer <A> is present in the code stream but unused.
-
-struct PSObject {
- PSObjectType type;
- union {
- GBool booln; // boolean (stack only)
- int intg; // integer (stack and code)
- double real; // real (stack and code)
- PSOp op; // operator (code only)
- int blk; // if/ifelse block pointer (code only)
- };
-};
-
-#define psStackSize 100
-
-class PSStack {
-public:
-
- PSStack() { sp = psStackSize; }
- void pushBool(GBool booln);
- void pushInt(int intg);
- void pushReal(double real);
- GBool popBool();
- int popInt();
- double popNum();
- GBool empty() { return sp == psStackSize; }
- GBool topIsInt() { return sp < psStackSize && stack[sp].type == psInt; }
- GBool topTwoAreInts()
- { return sp < psStackSize - 1 &&
- stack[sp].type == psInt &&
- stack[sp+1].type == psInt; }
- GBool topIsReal() { return sp < psStackSize && stack[sp].type == psReal; }
- GBool topTwoAreNums()
- { return sp < psStackSize - 1 &&
- (stack[sp].type == psInt || stack[sp].type == psReal) &&
- (stack[sp+1].type == psInt || stack[sp+1].type == psReal); }
- void copy(int n);
- void roll(int n, int j);
- void index(int i);
- void pop();
-
-private:
-
- GBool checkOverflow(int n = 1);
- GBool checkUnderflow();
- GBool checkType(PSObjectType t1, PSObjectType t2);
-
- PSObject stack[psStackSize];
- int sp;
-};
-
-GBool PSStack::checkOverflow(int n) {
- if (sp - n < 0) {
- error(-1, "Stack overflow in PostScript function");
- return gFalse;
- }
- return gTrue;
-}
-
-GBool PSStack::checkUnderflow() {
- if (sp == psStackSize) {
- error(-1, "Stack underflow in PostScript function");
- return gFalse;
- }
- return gTrue;
-}
-
-GBool PSStack::checkType(PSObjectType t1, PSObjectType t2) {
- if (stack[sp].type != t1 && stack[sp].type != t2) {
- error(-1, "Type mismatch in PostScript function");
- return gFalse;
- }
- return gTrue;
-}
-
-void PSStack::pushBool(GBool booln) {
- if (checkOverflow()) {
- stack[--sp].type = psBool;
- stack[sp].booln = booln;
- }
-}
-
-void PSStack::pushInt(int intg) {
- if (checkOverflow()) {
- stack[--sp].type = psInt;
- stack[sp].intg = intg;
- }
-}
-
-void PSStack::pushReal(double real) {
- if (checkOverflow()) {
- stack[--sp].type = psReal;
- stack[sp].real = real;
- }
-}
-
-GBool PSStack::popBool() {
- if (checkUnderflow() && checkType(psBool, psBool)) {
- return stack[sp++].booln;
- }
- return gFalse;
-}
-
-int PSStack::popInt() {
- if (checkUnderflow() && checkType(psInt, psInt)) {
- return stack[sp++].intg;
- }
- return 0;
-}
-
-double PSStack::popNum() {
- double ret;
-
- if (checkUnderflow() && checkType(psInt, psReal)) {
- ret = (stack[sp].type == psInt) ? (double)stack[sp].intg : stack[sp].real;
- ++sp;
- return ret;
- }
- return 0;
-}
-
-void PSStack::copy(int n) {
- int i;
-
- if (sp + n > psStackSize) {
- error(-1, "Stack underflow in PostScript function");
- return;
- }
- if (!checkOverflow(n)) {
- return;
- }
- for (i = sp + n - 1; i >= sp; --i) {
- stack[i - n] = stack[i];
- }
- sp -= n;
-}
-
-void PSStack::roll(int n, int j) {
- PSObject obj;
- int i, k;
-
- if (j >= 0) {
- j %= n;
- } else {
- j = -j % n;
- if (j != 0) {
- j = n - j;
- }
- }
- if (n <= 0 || j == 0) {
- return;
- }
- for (i = 0; i < j; ++i) {
- obj = stack[sp];
- for (k = sp; k < sp + n - 1; ++k) {
- stack[k] = stack[k+1];
- }
- stack[sp + n - 1] = obj;
- }
-}
-
-void PSStack::index(int i) {
- if (!checkOverflow()) {
- return;
- }
- --sp;
- stack[sp] = stack[sp + 1 + i];
-}
-
-void PSStack::pop() {
- if (!checkUnderflow()) {
- return;
- }
- ++sp;
-}
-
-PostScriptFunction::PostScriptFunction(Object *funcObj, Dict *dict) {
- Stream *str;
- int codePtr;
- GString *tok;
-
- code = NULL;
- codeSize = 0;
- ok = gFalse;
-
- //----- initialize the generic stuff
- if (!init(dict)) {
- goto err1;
- }
- if (!hasRange) {
- error(-1, "Type 4 function is missing range");
- goto err1;
- }
-
- //----- get the stream
- if (!funcObj->isStream()) {
- error(-1, "Type 4 function isn't a stream");
- goto err1;
- }
- str = funcObj->getStream();
-
- //----- parse the function
- codeString = new GString();
- str->reset();
- if (!(tok = getToken(str)) || tok->cmp("{")) {
- error(-1, "Expected '{' at start of PostScript function");
- if (tok) {
- delete tok;
- }
- goto err1;
- }
- delete tok;
- codePtr = 0;
- if (!parseCode(str, &codePtr)) {
- goto err2;
- }
- str->close();
-
- ok = gTrue;
-
- err2:
- str->close();
- err1:
- return;
-}
-
-PostScriptFunction::PostScriptFunction(PostScriptFunction *func) {
- memcpy(this, func, sizeof(PostScriptFunction));
- code = (PSObject *)gmallocn(codeSize, sizeof(PSObject));
- memcpy(code, func->code, codeSize * sizeof(PSObject));
- codeString = func->codeString->copy();
-}
-
-PostScriptFunction::~PostScriptFunction() {
- gfree(code);
- delete codeString;
-}
-
-void PostScriptFunction::transform(double *in, double *out) {
- PSStack *stack;
- int i;
-
- stack = new PSStack();
- for (i = 0; i < m; ++i) {
- //~ may need to check for integers here
- stack->pushReal(in[i]);
- }
- exec(stack, 0);
- for (i = n - 1; i >= 0; --i) {
- out[i] = stack->popNum();
- if (out[i] < range[i][0]) {
- out[i] = range[i][0];
- } else if (out[i] > range[i][1]) {
- out[i] = range[i][1];
- }
- }
- // if (!stack->empty()) {
- // error(-1, "Extra values on stack at end of PostScript function");
- // }
- delete stack;
-}
-
-GBool PostScriptFunction::parseCode(Stream *str, int *codePtr) {
- GString *tok;
- char *p;
- GBool isReal;
- int opPtr, elsePtr;
- int a, b, mid, cmp;
-
- while (1) {
- if (!(tok = getToken(str))) {
- error(-1, "Unexpected end of PostScript function stream");
- return gFalse;
- }
- p = tok->getCString();
- if (isdigit(*p) || *p == '.' || *p == '-') {
- isReal = gFalse;
- for (++p; *p; ++p) {
- if (*p == '.') {
- isReal = gTrue;
- break;
- }
- }
- resizeCode(*codePtr);
- if (isReal) {
- code[*codePtr].type = psReal;
- code[*codePtr].real = atof(tok->getCString());
- } else {
- code[*codePtr].type = psInt;
- code[*codePtr].intg = atoi(tok->getCString());
- }
- ++*codePtr;
- delete tok;
- } else if (!tok->cmp("{")) {
- delete tok;
- opPtr = *codePtr;
- *codePtr += 3;
- resizeCode(opPtr + 2);
- if (!parseCode(str, codePtr)) {
- return gFalse;
- }
- if (!(tok = getToken(str))) {
- error(-1, "Unexpected end of PostScript function stream");
- return gFalse;
- }
- if (!tok->cmp("{")) {
- elsePtr = *codePtr;
- if (!parseCode(str, codePtr)) {
- return gFalse;
- }
- delete tok;
- if (!(tok = getToken(str))) {
- error(-1, "Unexpected end of PostScript function stream");
- return gFalse;
- }
- } else {
- elsePtr = -1;
- }
- if (!tok->cmp("if")) {
- if (elsePtr >= 0) {
- error(-1, "Got 'if' operator with two blocks in PostScript function");
- return gFalse;
- }
- code[opPtr].type = psOperator;
- code[opPtr].op = psOpIf;
- code[opPtr+2].type = psBlock;
- code[opPtr+2].blk = *codePtr;
- } else if (!tok->cmp("ifelse")) {
- if (elsePtr < 0) {
- error(-1, "Got 'ifelse' operator with one blocks in PostScript function");
- return gFalse;
- }
- code[opPtr].type = psOperator;
- code[opPtr].op = psOpIfelse;
- code[opPtr+1].type = psBlock;
- code[opPtr+1].blk = elsePtr;
- code[opPtr+2].type = psBlock;
- code[opPtr+2].blk = *codePtr;
- } else {
- error(-1, "Expected if/ifelse operator in PostScript function");
- delete tok;
- return gFalse;
- }
- delete tok;
- } else if (!tok->cmp("}")) {
- delete tok;
- resizeCode(*codePtr);
- code[*codePtr].type = psOperator;
- code[*codePtr].op = psOpReturn;
- ++*codePtr;
- break;
- } else {
- a = -1;
- b = nPSOps;
- // invariant: psOpNames[a] < tok < psOpNames[b]
- while (b - a > 1) {
- mid = (a + b) / 2;
- cmp = tok->cmp(psOpNames[mid]);
- if (cmp > 0) {
- a = mid;
- } else if (cmp < 0) {
- b = mid;
- } else {
- a = b = mid;
- }
- }
- if (cmp != 0) {
- error(-1, "Unknown operator '%s' in PostScript function",
- tok->getCString());
- delete tok;
- return gFalse;
- }
- delete tok;
- resizeCode(*codePtr);
- code[*codePtr].type = psOperator;
- code[*codePtr].op = (PSOp)a;
- ++*codePtr;
- }
- }
- return gTrue;
-}
-
-GString *PostScriptFunction::getToken(Stream *str) {
- GString *s;
- int c;
-
- s = new GString();
- do {
- c = str->getChar();
- if (c != EOF) {
- codeString->append(c);
- }
- } while (c != EOF && isspace(c));
- if (c == '{' || c == '}') {
- s->append((char)c);
- } else if (isdigit(c) || c == '.' || c == '-') {
- while (1) {
- s->append((char)c);
- c = str->lookChar();
- if (c == EOF || !(isdigit(c) || c == '.' || c == '-')) {
- break;
- }
- str->getChar();
- codeString->append(c);
- }
- } else {
- while (1) {
- s->append((char)c);
- c = str->lookChar();
- if (c == EOF || !isalnum(c)) {
- break;
- }
- str->getChar();
- codeString->append(c);
- }
- }
- return s;
-}
-
-void PostScriptFunction::resizeCode(int newSize) {
- if (newSize >= codeSize) {
- codeSize += 64;
- code = (PSObject *)greallocn(code, codeSize, sizeof(PSObject));
- }
-}
-
-void PostScriptFunction::exec(PSStack *stack, int codePtr) {
- int i1, i2;
- double r1, r2;
- GBool b1, b2;
-
- while (1) {
- switch (code[codePtr].type) {
- case psInt:
- stack->pushInt(code[codePtr++].intg);
- break;
- case psReal:
- stack->pushReal(code[codePtr++].real);
- break;
- case psOperator:
- switch (code[codePtr++].op) {
- case psOpAbs:
- if (stack->topIsInt()) {
- stack->pushInt(abs(stack->popInt()));
- } else {
- stack->pushReal(fabs(stack->popNum()));
- }
- break;
- case psOpAdd:
- if (stack->topTwoAreInts()) {
- i2 = stack->popInt();
- i1 = stack->popInt();
- stack->pushInt(i1 + i2);
- } else {
- r2 = stack->popNum();
- r1 = stack->popNum();
- stack->pushReal(r1 + r2);
- }
- break;
- case psOpAnd:
- if (stack->topTwoAreInts()) {
- i2 = stack->popInt();
- i1 = stack->popInt();
- stack->pushInt(i1 & i2);
- } else {
- b2 = stack->popBool();
- b1 = stack->popBool();
- stack->pushBool(b1 && b2);
- }
- break;
- case psOpAtan:
- r2 = stack->popNum();
- r1 = stack->popNum();
- stack->pushReal(atan2(r1, r2));
- break;
- case psOpBitshift:
- i2 = stack->popInt();
- i1 = stack->popInt();
- if (i2 > 0) {
- stack->pushInt(i1 << i2);
- } else if (i2 < 0) {
- stack->pushInt((int)((Guint)i1 >> i2));
- } else {
- stack->pushInt(i1);
- }
- break;
- case psOpCeiling:
- if (!stack->topIsInt()) {
- stack->pushReal(ceil(stack->popNum()));
- }
- break;
- case psOpCopy:
- stack->copy(stack->popInt());
- break;
- case psOpCos:
- stack->pushReal(cos(stack->popNum()));
- break;
- case psOpCvi:
- if (!stack->topIsInt()) {
- stack->pushInt((int)stack->popNum());
- }
- break;
- case psOpCvr:
- if (!stack->topIsReal()) {
- stack->pushReal(stack->popNum());
- }
- break;
- case psOpDiv:
- r2 = stack->popNum();
- r1 = stack->popNum();
- stack->pushReal(r1 / r2);
- break;
- case psOpDup:
- stack->copy(1);
- break;
- case psOpEq:
- if (stack->topTwoAreInts()) {
- i2 = stack->popInt();
- i1 = stack->popInt();
- stack->pushBool(i1 == i2);
- } else if (stack->topTwoAreNums()) {
- r2 = stack->popNum();
- r1 = stack->popNum();
- stack->pushBool(r1 == r2);
- } else {
- b2 = stack->popBool();
- b1 = stack->popBool();
- stack->pushBool(b1 == b2);
- }
- break;
- case psOpExch:
- stack->roll(2, 1);
- break;
- case psOpExp:
- r2 = stack->popNum();
- r1 = stack->popNum();
- stack->pushReal(pow(r1, r2));
- break;
- case psOpFalse:
- stack->pushBool(gFalse);
- break;
- case psOpFloor:
- if (!stack->topIsInt()) {
- stack->pushReal(floor(stack->popNum()));
- }
- break;
- case psOpGe:
- if (stack->topTwoAreInts()) {
- i2 = stack->popInt();
- i1 = stack->popInt();
- stack->pushBool(i1 >= i2);
- } else {
- r2 = stack->popNum();
- r1 = stack->popNum();
- stack->pushBool(r1 >= r2);
- }
- break;
- case psOpGt:
- if (stack->topTwoAreInts()) {
- i2 = stack->popInt();
- i1 = stack->popInt();
- stack->pushBool(i1 > i2);
- } else {
- r2 = stack->popNum();
- r1 = stack->popNum();
- stack->pushBool(r1 > r2);
- }
- break;
- case psOpIdiv:
- i2 = stack->popInt();
- i1 = stack->popInt();
- stack->pushInt(i1 / i2);
- break;
- case psOpIndex:
- stack->index(stack->popInt());
- break;
- case psOpLe:
- if (stack->topTwoAreInts()) {
- i2 = stack->popInt();
- i1 = stack->popInt();
- stack->pushBool(i1 <= i2);
- } else {
- r2 = stack->popNum();
- r1 = stack->popNum();
- stack->pushBool(r1 <= r2);
- }
- break;
- case psOpLn:
- stack->pushReal(log(stack->popNum()));
- break;
- case psOpLog:
- stack->pushReal(log10(stack->popNum()));
- break;
- case psOpLt:
- if (stack->topTwoAreInts()) {
- i2 = stack->popInt();
- i1 = stack->popInt();
- stack->pushBool(i1 < i2);
- } else {
- r2 = stack->popNum();
- r1 = stack->popNum();
- stack->pushBool(r1 < r2);
- }
- break;
- case psOpMod:
- i2 = stack->popInt();
- i1 = stack->popInt();
- stack->pushInt(i1 % i2);
- break;
- case psOpMul:
- if (stack->topTwoAreInts()) {
- i2 = stack->popInt();
- i1 = stack->popInt();
- //~ should check for out-of-range, and push a real instead
- stack->pushInt(i1 * i2);
- } else {
- r2 = stack->popNum();
- r1 = stack->popNum();
- stack->pushReal(r1 * r2);
- }
- break;
- case psOpNe:
- if (stack->topTwoAreInts()) {
- i2 = stack->popInt();
- i1 = stack->popInt();
- stack->pushBool(i1 != i2);
- } else if (stack->topTwoAreNums()) {
- r2 = stack->popNum();
- r1 = stack->popNum();
- stack->pushBool(r1 != r2);
- } else {
- b2 = stack->popBool();
- b1 = stack->popBool();
- stack->pushBool(b1 != b2);
- }
- break;
- case psOpNeg:
- if (stack->topIsInt()) {
- stack->pushInt(-stack->popInt());
- } else {
- stack->pushReal(-stack->popNum());
- }
- break;
- case psOpNot:
- if (stack->topIsInt()) {
- stack->pushInt(~stack->popInt());
- } else {
- stack->pushBool(!stack->popBool());
- }
- break;
- case psOpOr:
- if (stack->topTwoAreInts()) {
- i2 = stack->popInt();
- i1 = stack->popInt();
- stack->pushInt(i1 | i2);
- } else {
- b2 = stack->popBool();
- b1 = stack->popBool();
- stack->pushBool(b1 || b2);
- }
- break;
- case psOpPop:
- stack->pop();
- break;
- case psOpRoll:
- i2 = stack->popInt();
- i1 = stack->popInt();
- stack->roll(i1, i2);
- break;
- case psOpRound:
- if (!stack->topIsInt()) {
- r1 = stack->popNum();
- stack->pushReal((r1 >= 0) ? floor(r1 + 0.5) : ceil(r1 - 0.5));
- }
- break;
- case psOpSin:
- stack->pushReal(sin(stack->popNum()));
- break;
- case psOpSqrt:
- stack->pushReal(sqrt(stack->popNum()));
- break;
- case psOpSub:
- if (stack->topTwoAreInts()) {
- i2 = stack->popInt();
- i1 = stack->popInt();
- stack->pushInt(i1 - i2);
- } else {
- r2 = stack->popNum();
- r1 = stack->popNum();
- stack->pushReal(r1 - r2);
- }
- break;
- case psOpTrue:
- stack->pushBool(gTrue);
- break;
- case psOpTruncate:
- if (!stack->topIsInt()) {
- r1 = stack->popNum();
- stack->pushReal((r1 >= 0) ? floor(r1) : ceil(r1));
- }
- break;
- case psOpXor:
- if (stack->topTwoAreInts()) {
- i2 = stack->popInt();
- i1 = stack->popInt();
- stack->pushInt(i1 ^ i2);
- } else {
- b2 = stack->popBool();
- b1 = stack->popBool();
- stack->pushBool(b1 ^ b2);
- }
- break;
- case psOpIf:
- b1 = stack->popBool();
- if (b1) {
- exec(stack, codePtr + 2);
- }
- codePtr = code[codePtr + 1].blk;
- break;
- case psOpIfelse:
- b1 = stack->popBool();
- if (b1) {
- exec(stack, codePtr + 2);
- } else {
- exec(stack, code[codePtr].blk);
- }
- codePtr = code[codePtr + 1].blk;
- break;
- case psOpReturn:
- return;
- }
- break;
- default:
- error(-1, "Internal: bad object in PostScript function code");
- break;
- }
- }
-}
+++ /dev/null
-//========================================================================
-//
-// Function.h
-//
-// Copyright 2001-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#ifndef FUNCTION_H
-#define FUNCTION_H
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma interface
-#endif
-
-#include "gtypes.h"
-#include "Object.h"
-
-class Dict;
-class Stream;
-struct PSObject;
-class PSStack;
-
-//------------------------------------------------------------------------
-// Function
-//------------------------------------------------------------------------
-
-#define funcMaxInputs 8
-#define funcMaxOutputs 32
-
-class Function {
-public:
-
- Function();
-
- virtual ~Function();
-
- // Construct a function. Returns NULL if unsuccessful.
- static Function *parse(Object *funcObj);
-
- // Initialize the entries common to all function types.
- GBool init(Dict *dict);
-
- virtual Function *copy() = 0;
-
- // Return the function type:
- // -1 : identity
- // 0 : sampled
- // 2 : exponential
- // 3 : stitching
- // 4 : PostScript
- virtual int getType() = 0;
-
- // Return size of input and output tuples.
- int getInputSize() { return m; }
- int getOutputSize() { return n; }
-
- double getDomainMin(int i) { return domain[i][0]; }
- double getDomainMax(int i) { return domain[i][1]; }
- double getRangeMin(int i) { return range[i][0]; }
- double getRangeMax(int i) { return range[i][1]; }
- GBool getHasRange() { return hasRange; }
-
- // Transform an input tuple into an output tuple.
- virtual void transform(double *in, double *out) = 0;
-
- virtual GBool isOk() = 0;
-
-protected:
-
- int m, n; // size of input and output tuples
- double // min and max values for function domain
- domain[funcMaxInputs][2];
- double // min and max values for function range
- range[funcMaxOutputs][2];
- GBool hasRange; // set if range is defined
-};
-
-//------------------------------------------------------------------------
-// IdentityFunction
-//------------------------------------------------------------------------
-
-class IdentityFunction: public Function {
-public:
-
- IdentityFunction();
- virtual ~IdentityFunction();
- virtual Function *copy() { return new IdentityFunction(); }
- virtual int getType() { return -1; }
- virtual void transform(double *in, double *out);
- virtual GBool isOk() { return gTrue; }
-
-private:
-};
-
-//------------------------------------------------------------------------
-// SampledFunction
-//------------------------------------------------------------------------
-
-class SampledFunction: public Function {
-public:
-
- SampledFunction(Object *funcObj, Dict *dict);
- virtual ~SampledFunction();
- virtual Function *copy() { return new SampledFunction(this); }
- virtual int getType() { return 0; }
- virtual void transform(double *in, double *out);
- virtual GBool isOk() { return ok; }
-
- int getSampleSize(int i) { return sampleSize[i]; }
- double getEncodeMin(int i) { return encode[i][0]; }
- double getEncodeMax(int i) { return encode[i][1]; }
- double getDecodeMin(int i) { return decode[i][0]; }
- double getDecodeMax(int i) { return decode[i][1]; }
- double *getSamples() { return samples; }
-
-private:
-
- SampledFunction(SampledFunction *func);
-
- int // number of samples for each domain element
- sampleSize[funcMaxInputs];
- double // min and max values for domain encoder
- encode[funcMaxInputs][2];
- double // min and max values for range decoder
- decode[funcMaxOutputs][2];
- double // input multipliers
- inputMul[funcMaxInputs];
- int idxMul[funcMaxInputs]; // sample array index multipliers
- double *samples; // the samples
- int nSamples; // size of the samples array
- GBool ok;
-};
-
-//------------------------------------------------------------------------
-// ExponentialFunction
-//------------------------------------------------------------------------
-
-class ExponentialFunction: public Function {
-public:
-
- ExponentialFunction(Object *funcObj, Dict *dict);
- virtual ~ExponentialFunction();
- virtual Function *copy() { return new ExponentialFunction(this); }
- virtual int getType() { return 2; }
- virtual void transform(double *in, double *out);
- virtual GBool isOk() { return ok; }
-
- double *getC0() { return c0; }
- double *getC1() { return c1; }
- double getE() { return e; }
-
-private:
-
- ExponentialFunction(ExponentialFunction *func);
-
- double c0[funcMaxOutputs];
- double c1[funcMaxOutputs];
- double e;
- GBool ok;
-};
-
-//------------------------------------------------------------------------
-// StitchingFunction
-//------------------------------------------------------------------------
-
-class StitchingFunction: public Function {
-public:
-
- StitchingFunction(Object *funcObj, Dict *dict);
- virtual ~StitchingFunction();
- virtual Function *copy() { return new StitchingFunction(this); }
- virtual int getType() { return 3; }
- virtual void transform(double *in, double *out);
- virtual GBool isOk() { return ok; }
-
- int getNumFuncs() { return k; }
- Function *getFunc(int i) { return funcs[i]; }
- double *getBounds() { return bounds; }
- double *getEncode() { return encode; }
-
-private:
-
- StitchingFunction(StitchingFunction *func);
-
- int k;
- Function **funcs;
- double *bounds;
- double *encode;
- GBool ok;
-};
-
-//------------------------------------------------------------------------
-// PostScriptFunction
-//------------------------------------------------------------------------
-
-class PostScriptFunction: public Function {
-public:
-
- PostScriptFunction(Object *funcObj, Dict *dict);
- virtual ~PostScriptFunction();
- virtual Function *copy() { return new PostScriptFunction(this); }
- virtual int getType() { return 4; }
- virtual void transform(double *in, double *out);
- virtual GBool isOk() { return ok; }
-
- GString *getCodeString() { return codeString; }
-
-private:
-
- PostScriptFunction(PostScriptFunction *func);
- GBool parseCode(Stream *str, int *codePtr);
- GString *getToken(Stream *str);
- void resizeCode(int newSize);
- void exec(PSStack *stack, int codePtr);
-
- GString *codeString;
- PSObject *code;
- int codeSize;
- GBool ok;
-};
-
-#endif
+++ /dev/null
-//========================================================================
-//
-// GHash.cc
-//
-// Copyright 2001-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma implementation
-#endif
-
-#include "gmem.h"
-#include "GString.h"
-#include "GHash.h"
-
-//------------------------------------------------------------------------
-
-struct GHashBucket {
- GString *key;
- union {
- void *p;
- int i;
- } val;
- GHashBucket *next;
-};
-
-struct GHashIter {
- int h;
- GHashBucket *p;
-};
-
-//------------------------------------------------------------------------
-
-GHash::GHash(GBool deleteKeysA) {
- int h;
-
- deleteKeys = deleteKeysA;
- size = 7;
- tab = (GHashBucket **)gmallocn(size, sizeof(GHashBucket *));
- for (h = 0; h < size; ++h) {
- tab[h] = NULL;
- }
- len = 0;
-}
-
-GHash::~GHash() {
- GHashBucket *p;
- int h;
-
- for (h = 0; h < size; ++h) {
- while (tab[h]) {
- p = tab[h];
- tab[h] = p->next;
- if (deleteKeys) {
- delete p->key;
- }
- delete p;
- }
- }
- gfree(tab);
-}
-
-void GHash::add(GString *key, void *val) {
- GHashBucket *p;
- int h;
-
- // expand the table if necessary
- if (len >= size) {
- expand();
- }
-
- // add the new symbol
- p = new GHashBucket;
- p->key = key;
- p->val.p = val;
- h = hash(key);
- p->next = tab[h];
- tab[h] = p;
- ++len;
-}
-
-void GHash::add(GString *key, int val) {
- GHashBucket *p;
- int h;
-
- // expand the table if necessary
- if (len >= size) {
- expand();
- }
-
- // add the new symbol
- p = new GHashBucket;
- p->key = key;
- p->val.i = val;
- h = hash(key);
- p->next = tab[h];
- tab[h] = p;
- ++len;
-}
-
-void GHash::replace(GString *key, void *val) {
- GHashBucket *p;
- int h;
-
- if ((p = find(key, &h))) {
- p->val.p = val;
- delete key;
- } else {
- add(key, val);
- }
-}
-
-void GHash::replace(GString *key, int val) {
- GHashBucket *p;
- int h;
-
- if ((p = find(key, &h))) {
- p->val.i = val;
- delete key;
- } else {
- add(key, val);
- }
-}
-
-void *GHash::lookup(GString *key) {
- GHashBucket *p;
- int h;
-
- if (!(p = find(key, &h))) {
- return NULL;
- }
- return p->val.p;
-}
-
-int GHash::lookupInt(GString *key) {
- GHashBucket *p;
- int h;
-
- if (!(p = find(key, &h))) {
- return 0;
- }
- return p->val.i;
-}
-
-void *GHash::lookup(char *key) {
- GHashBucket *p;
- int h;
-
- if (!(p = find(key, &h))) {
- return NULL;
- }
- return p->val.p;
-}
-
-int GHash::lookupInt(char *key) {
- GHashBucket *p;
- int h;
-
- if (!(p = find(key, &h))) {
- return 0;
- }
- return p->val.i;
-}
-
-void *GHash::remove(GString *key) {
- GHashBucket *p;
- GHashBucket **q;
- void *val;
- int h;
-
- if (!(p = find(key, &h))) {
- return NULL;
- }
- q = &tab[h];
- while (*q != p) {
- q = &((*q)->next);
- }
- *q = p->next;
- if (deleteKeys) {
- delete p->key;
- }
- val = p->val.p;
- delete p;
- --len;
- return val;
-}
-
-int GHash::removeInt(GString *key) {
- GHashBucket *p;
- GHashBucket **q;
- int val;
- int h;
-
- if (!(p = find(key, &h))) {
- return 0;
- }
- q = &tab[h];
- while (*q != p) {
- q = &((*q)->next);
- }
- *q = p->next;
- if (deleteKeys) {
- delete p->key;
- }
- val = p->val.i;
- delete p;
- --len;
- return val;
-}
-
-void *GHash::remove(char *key) {
- GHashBucket *p;
- GHashBucket **q;
- void *val;
- int h;
-
- if (!(p = find(key, &h))) {
- return NULL;
- }
- q = &tab[h];
- while (*q != p) {
- q = &((*q)->next);
- }
- *q = p->next;
- if (deleteKeys) {
- delete p->key;
- }
- val = p->val.p;
- delete p;
- --len;
- return val;
-}
-
-int GHash::removeInt(char *key) {
- GHashBucket *p;
- GHashBucket **q;
- int val;
- int h;
-
- if (!(p = find(key, &h))) {
- return 0;
- }
- q = &tab[h];
- while (*q != p) {
- q = &((*q)->next);
- }
- *q = p->next;
- if (deleteKeys) {
- delete p->key;
- }
- val = p->val.i;
- delete p;
- --len;
- return val;
-}
-
-void GHash::startIter(GHashIter **iter) {
- *iter = new GHashIter;
- (*iter)->h = -1;
- (*iter)->p = NULL;
-}
-
-GBool GHash::getNext(GHashIter **iter, GString **key, void **val) {
- if (!*iter) {
- return gFalse;
- }
- if ((*iter)->p) {
- (*iter)->p = (*iter)->p->next;
- }
- while (!(*iter)->p) {
- if (++(*iter)->h == size) {
- delete *iter;
- *iter = NULL;
- return gFalse;
- }
- (*iter)->p = tab[(*iter)->h];
- }
- *key = (*iter)->p->key;
- *val = (*iter)->p->val.p;
- return gTrue;
-}
-
-GBool GHash::getNext(GHashIter **iter, GString **key, int *val) {
- if (!*iter) {
- return gFalse;
- }
- if ((*iter)->p) {
- (*iter)->p = (*iter)->p->next;
- }
- while (!(*iter)->p) {
- if (++(*iter)->h == size) {
- delete *iter;
- *iter = NULL;
- return gFalse;
- }
- (*iter)->p = tab[(*iter)->h];
- }
- *key = (*iter)->p->key;
- *val = (*iter)->p->val.i;
- return gTrue;
-}
-
-void GHash::killIter(GHashIter **iter) {
- delete *iter;
- *iter = NULL;
-}
-
-void GHash::expand() {
- GHashBucket **oldTab;
- GHashBucket *p;
- int oldSize, h, i;
-
- oldSize = size;
- oldTab = tab;
- size = 2*size + 1;
- tab = (GHashBucket **)gmallocn(size, sizeof(GHashBucket *));
- for (h = 0; h < size; ++h) {
- tab[h] = NULL;
- }
- for (i = 0; i < oldSize; ++i) {
- while (oldTab[i]) {
- p = oldTab[i];
- oldTab[i] = oldTab[i]->next;
- h = hash(p->key);
- p->next = tab[h];
- tab[h] = p;
- }
- }
- gfree(oldTab);
-}
-
-GHashBucket *GHash::find(GString *key, int *h) {
- GHashBucket *p;
-
- *h = hash(key);
- for (p = tab[*h]; p; p = p->next) {
- if (!p->key->cmp(key)) {
- return p;
- }
- }
- return NULL;
-}
-
-GHashBucket *GHash::find(char *key, int *h) {
- GHashBucket *p;
-
- *h = hash(key);
- for (p = tab[*h]; p; p = p->next) {
- if (!p->key->cmp(key)) {
- return p;
- }
- }
- return NULL;
-}
-
-int GHash::hash(GString *key) {
- char *p;
- unsigned int h;
- int i;
-
- h = 0;
- for (p = key->getCString(), i = 0; i < key->getLength(); ++p, ++i) {
- h = 17 * h + (int)(*p & 0xff);
- }
- return (int)(h % size);
-}
-
-int GHash::hash(char *key) {
- char *p;
- unsigned int h;
-
- h = 0;
- for (p = key; *p; ++p) {
- h = 17 * h + (int)(*p & 0xff);
- }
- return (int)(h % size);
-}
+++ /dev/null
-//========================================================================
-//
-// GHash.h
-//
-// Copyright 2001-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#ifndef GHASH_H
-#define GHASH_H
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma interface
-#endif
-
-#include "gtypes.h"
-
-class GString;
-struct GHashBucket;
-struct GHashIter;
-
-//------------------------------------------------------------------------
-
-class GHash {
-public:
-
- GHash(GBool deleteKeysA = gFalse);
- ~GHash();
- void add(GString *key, void *val);
- void add(GString *key, int val);
- void replace(GString *key, void *val);
- void replace(GString *key, int val);
- void *lookup(GString *key);
- int lookupInt(GString *key);
- void *lookup(char *key);
- int lookupInt(char *key);
- void *remove(GString *key);
- int removeInt(GString *key);
- void *remove(char *key);
- int removeInt(char *key);
- int getLength() { return len; }
- void startIter(GHashIter **iter);
- GBool getNext(GHashIter **iter, GString **key, void **val);
- GBool getNext(GHashIter **iter, GString **key, int *val);
- void killIter(GHashIter **iter);
-
-private:
-
- void expand();
- GHashBucket *find(GString *key, int *h);
- GHashBucket *find(char *key, int *h);
- int hash(GString *key);
- int hash(char *key);
-
- GBool deleteKeys; // set if key strings should be deleted
- int size; // number of buckets
- int len; // number of entries
- GHashBucket **tab;
-};
-
-#define deleteGHash(hash, T) \
- do { \
- GHash *_hash = (hash); \
- { \
- GHashIter *_iter; \
- GString *_key; \
- void *_p; \
- _hash->startIter(&_iter); \
- while (_hash->getNext(&_iter, &_key, &_p)) { \
- delete (T*)_p; \
- } \
- delete _hash; \
- } \
- } while(0)
-
-#endif
+++ /dev/null
-//========================================================================
-//
-// GList.cc
-//
-// Copyright 2001-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma implementation
-#endif
-
-#include <stdlib.h>
-#include <string.h>
-#include "gmem.h"
-#include "GList.h"
-
-//------------------------------------------------------------------------
-// GList
-//------------------------------------------------------------------------
-
-GList::GList() {
- size = 8;
- data = (void **)gmallocn(size, sizeof(void*));
- length = 0;
- inc = 0;
-}
-
-GList::GList(int sizeA) {
- size = sizeA;
- data = (void **)gmallocn(size, sizeof(void*));
- length = 0;
- inc = 0;
-}
-
-GList::~GList() {
- gfree(data);
-}
-
-void GList::append(void *p) {
- if (length >= size) {
- expand();
- }
- data[length++] = p;
-}
-
-void GList::append(GList *list) {
- int i;
-
- while (length + list->length > size) {
- expand();
- }
- for (i = 0; i < list->length; ++i) {
- data[length++] = list->data[i];
- }
-}
-
-void GList::insert(int i, void *p) {
- if (length >= size) {
- expand();
- }
- if (i < length) {
- memmove(data+i+1, data+i, (length - i) * sizeof(void *));
- }
- data[i] = p;
- ++length;
-}
-
-void *GList::del(int i) {
- void *p;
-
- p = data[i];
- if (i < length - 1) {
- memmove(data+i, data+i+1, (length - i - 1) * sizeof(void *));
- }
- --length;
- if (size - length >= ((inc > 0) ? inc : size/2)) {
- shrink();
- }
- return p;
-}
-
-void GList::sort(int (*cmp)(const void *obj1, const void *obj2)) {
- qsort(data, length, sizeof(void *), cmp);
-}
-
-void GList::expand() {
- size += (inc > 0) ? inc : size;
- data = (void **)greallocn(data, size, sizeof(void*));
-}
-
-void GList::shrink() {
- size -= (inc > 0) ? inc : size/2;
- data = (void **)greallocn(data, size, sizeof(void*));
-}
+++ /dev/null
-//========================================================================
-//
-// GList.h
-//
-// Copyright 2001-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#ifndef GLIST_H
-#define GLIST_H
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma interface
-#endif
-
-#include "gtypes.h"
-
-//------------------------------------------------------------------------
-// GList
-//------------------------------------------------------------------------
-
-class GList {
-public:
-
- // Create an empty list.
- GList();
-
- // Create an empty list with space for <size1> elements.
- GList(int sizeA);
-
- // Destructor - does not free pointed-to objects.
- ~GList();
-
- //----- general
-
- // Get the number of elements.
- int getLength() { return length; }
-
- //----- ordered list support
-
- // Return the <i>th element.
- // Assumes 0 <= i < length.
- void *get(int i) { return data[i]; }
-
- // Append an element to the end of the list.
- void append(void *p);
-
- // Append another list to the end of this one.
- void append(GList *list);
-
- // Insert an element at index <i>.
- // Assumes 0 <= i <= length.
- void insert(int i, void *p);
-
- // Deletes and returns the element at index <i>.
- // Assumes 0 <= i < length.
- void *del(int i);
-
- // Sort the list accoring to the given comparison function.
- // NB: this sorts an array of pointers, so the pointer args need to
- // be double-dereferenced.
- void sort(int (*cmp)(const void *ptr1, const void *ptr2));
-
- //----- control
-
- // Set allocation increment to <inc>. If inc > 0, that many
- // elements will be allocated every time the list is expanded.
- // If inc <= 0, the list will be doubled in size.
- void setAllocIncr(int incA) { inc = incA; }
-
-private:
-
- void expand();
- void shrink();
-
- void **data; // the list elements
- int size; // size of data array
- int length; // number of elements on list
- int inc; // allocation increment
-};
-
-#define deleteGList(list, T) \
- do { \
- GList *_list = (list); \
- { \
- int _i; \
- for (_i = 0; _i < _list->getLength(); ++_i) { \
- delete (T*)_list->get(_i); \
- } \
- delete _list; \
- } \
- } while (0)
-
-#endif
+++ /dev/null
-//========================================================================
-//
-// GMutex.h
-//
-// Portable mutex macros.
-//
-// Copyright 2002-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#ifndef GMUTEX_H
-#define GMUTEX_H
-
-// Usage:
-//
-// GMutex m;
-// gInitMutex(&m);
-// ...
-// gLockMutex(&m);
-// ... critical section ...
-// gUnlockMutex(&m);
-// ...
-// gDestroyMutex(&m);
-
-#ifdef WIN32
-
-#include <windows.h>
-
-typedef CRITICAL_SECTION GMutex;
-
-#define gInitMutex(m) InitializeCriticalSection(m)
-#define gDestroyMutex(m) DeleteCriticalSection(m)
-#define gLockMutex(m) EnterCriticalSection(m)
-#define gUnlockMutex(m) LeaveCriticalSection(m)
-
-#else // assume pthreads
-
-#include <pthread.h>
-
-typedef pthread_mutex_t GMutex;
-
-#define gInitMutex(m) pthread_mutex_init(m, NULL)
-#define gDestroyMutex(m) pthread_mutex_destroy(m)
-#define gLockMutex(m) pthread_mutex_lock(m)
-#define gUnlockMutex(m) pthread_mutex_unlock(m)
-
-#endif
-
-#endif
+++ /dev/null
-//========================================================================
-//
-// GString.cc
-//
-// Simple variable-length string type.
-//
-// Copyright 1996-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma implementation
-#endif
-
-#include <stdlib.h>
-#include <stddef.h>
-#include <string.h>
-#include <ctype.h>
-#include "gtypes.h"
-#include "GString.h"
-
-static inline int size(int len) {
- int delta;
-
- delta = len < 256 ? 7 : 255;
- return ((len + 1) + delta) & ~delta;
-}
-
-inline void GString::resize(int length1) {
- char *s1;
-
- if (!s) {
- s = new char[size(length1)];
- } else if (size(length1) != size(length)) {
- s1 = new char[size(length1)];
- if (length1 < length) {
- memcpy(s1, s, length1);
- s1[length1] = '\0';
- } else {
- memcpy(s1, s, length + 1);
- }
- delete[] s;
- s = s1;
- }
-}
-
-GString::GString() {
- s = NULL;
- resize(length = 0);
- s[0] = '\0';
-}
-
-GString::GString(const char *sA) {
- int n = strlen(sA);
-
- s = NULL;
- resize(length = n);
- memcpy(s, sA, n + 1);
-}
-
-GString::GString(const char *sA, int lengthA) {
- s = NULL;
- resize(length = lengthA);
- memcpy(s, sA, length * sizeof(char));
- s[length] = '\0';
-}
-
-GString::GString(GString *str, int idx, int lengthA) {
- s = NULL;
- resize(length = lengthA);
- memcpy(s, str->getCString() + idx, length);
- s[length] = '\0';
-}
-
-GString::GString(GString *str) {
- s = NULL;
- resize(length = str->getLength());
- memcpy(s, str->getCString(), length + 1);
-}
-
-GString::GString(GString *str1, GString *str2) {
- int n1 = str1->getLength();
- int n2 = str2->getLength();
-
- s = NULL;
- resize(length = n1 + n2);
- memcpy(s, str1->getCString(), n1);
- memcpy(s + n1, str2->getCString(), n2 + 1);
-}
-
-GString *GString::fromInt(int x) {
- char buf[24]; // enough space for 64-bit ints plus a little extra
- GBool neg;
- Guint y;
- int i;
-
- i = 24;
- if (x == 0) {
- buf[--i] = '0';
- } else {
- if ((neg = x < 0)) {
- y = (Guint)-x;
- } else {
- y = (Guint)x;
- }
- while (i > 0 && y > 0) {
- buf[--i] = '0' + y % 10;
- y /= 10;
- }
- if (neg && i > 0) {
- buf[--i] = '-';
- }
- }
- return new GString(buf + i, 24 - i);
-}
-
-GString::~GString() {
- delete[] s;
-}
-
-GString *GString::clear() {
- s[length = 0] = '\0';
- resize(0);
- return this;
-}
-
-GString *GString::append(char c) {
- resize(length + 1);
- s[length++] = c;
- s[length] = '\0';
- return this;
-}
-
-GString *GString::append(GString *str) {
- int n = str->getLength();
-
- resize(length + n);
- memcpy(s + length, str->getCString(), n + 1);
- length += n;
- return this;
-}
-
-GString *GString::append(const char *str) {
- int n = strlen(str);
-
- resize(length + n);
- memcpy(s + length, str, n + 1);
- length += n;
- return this;
-}
-
-GString *GString::append(const char *str, int lengthA) {
- resize(length + lengthA);
- memcpy(s + length, str, lengthA);
- length += lengthA;
- s[length] = '\0';
- return this;
-}
-
-GString *GString::insert(int i, char c) {
- int j;
-
- resize(length + 1);
- for (j = length + 1; j > i; --j)
- s[j] = s[j-1];
- s[i] = c;
- ++length;
- return this;
-}
-
-GString *GString::insert(int i, GString *str) {
- int n = str->getLength();
- int j;
-
- resize(length + n);
- for (j = length; j >= i; --j)
- s[j+n] = s[j];
- memcpy(s+i, str->getCString(), n);
- length += n;
- return this;
-}
-
-GString *GString::insert(int i, const char *str) {
- int n = strlen(str);
- int j;
-
- resize(length + n);
- for (j = length; j >= i; --j)
- s[j+n] = s[j];
- memcpy(s+i, str, n);
- length += n;
- return this;
-}
-
-GString *GString::insert(int i, const char *str, int lengthA) {
- int j;
-
- resize(length + lengthA);
- for (j = length; j >= i; --j)
- s[j+lengthA] = s[j];
- memcpy(s+i, str, lengthA);
- length += lengthA;
- return this;
-}
-
-GString *GString::del(int i, int n) {
- int j;
-
- if (n > 0) {
- if (i + n > length) {
- n = length - i;
- }
- for (j = i; j <= length - n; ++j) {
- s[j] = s[j + n];
- }
- resize(length -= n);
- }
- return this;
-}
-
-GString *GString::upperCase() {
- int i;
-
- for (i = 0; i < length; ++i) {
- if (islower(s[i]))
- s[i] = toupper(s[i]);
- }
- return this;
-}
-
-GString *GString::lowerCase() {
- int i;
-
- for (i = 0; i < length; ++i) {
- if (isupper(s[i]))
- s[i] = tolower(s[i]);
- }
- return this;
-}
-
-int GString::cmp(GString *str) {
- int n1, n2, i, x;
- char *p1, *p2;
-
- n1 = length;
- n2 = str->length;
- for (i = 0, p1 = s, p2 = str->s; i < n1 && i < n2; ++i, ++p1, ++p2) {
- x = *p1 - *p2;
- if (x != 0) {
- return x;
- }
- }
- return n1 - n2;
-}
-
-int GString::cmpN(GString *str, int n) {
- int n1, n2, i, x;
- char *p1, *p2;
-
- n1 = length;
- n2 = str->length;
- for (i = 0, p1 = s, p2 = str->s;
- i < n1 && i < n2 && i < n;
- ++i, ++p1, ++p2) {
- x = *p1 - *p2;
- if (x != 0) {
- return x;
- }
- }
- if (i == n) {
- return 0;
- }
- return n1 - n2;
-}
-
-int GString::cmp(const char *sA) {
- int n1, i, x;
- const char *p1, *p2;
-
- n1 = length;
- for (i = 0, p1 = s, p2 = sA; i < n1 && *p2; ++i, ++p1, ++p2) {
- x = *p1 - *p2;
- if (x != 0) {
- return x;
- }
- }
- if (i < n1) {
- return 1;
- }
- if (*p2) {
- return -1;
- }
- return 0;
-}
-
-int GString::cmpN(const char *sA, int n) {
- int n1, i, x;
- const char *p1, *p2;
-
- n1 = length;
- for (i = 0, p1 = s, p2 = sA; i < n1 && *p2 && i < n; ++i, ++p1, ++p2) {
- x = *p1 - *p2;
- if (x != 0) {
- return x;
- }
- }
- if (i == n) {
- return 0;
- }
- if (i < n1) {
- return 1;
- }
- if (*p2) {
- return -1;
- }
- return 0;
-}
+++ /dev/null
-//========================================================================
-//
-// GString.h
-//
-// Simple variable-length string type.
-//
-// Copyright 1996-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#ifndef GSTRING_H
-#define GSTRING_H
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma interface
-#endif
-
-class GString {
-public:
-
- // Create an empty string.
- GString();
-
- // Create a string from a C string.
- GString(const char *sA);
-
- // Create a string from <lengthA> chars at <sA>. This string
- // can contain null characters.
- GString(const char *sA, int lengthA);
-
- // Create a string from <lengthA> chars at <idx> in <str>.
- GString(GString *str, int idx, int lengthA);
-
- // Copy a string.
- GString(GString *str);
- GString *copy() { return new GString(this); }
-
- // Concatenate two strings.
- GString(GString *str1, GString *str2);
-
- // Convert an integer to a string.
- static GString *fromInt(int x);
-
- // Destructor.
- ~GString();
-
- // Get length.
- int getLength() { return length; }
-
- // Get C string.
- char *getCString() { return s; }
-
- // Get <i>th character.
- char getChar(int i) { return s[i]; }
-
- // Change <i>th character.
- void setChar(int i, char c) { s[i] = c; }
-
- // Clear string to zero length.
- GString *clear();
-
- // Append a character or string.
- GString *append(char c);
- GString *append(GString *str);
- GString *append(const char *str);
- GString *append(const char *str, int lengthA);
-
- // Insert a character or string.
- GString *insert(int i, char c);
- GString *insert(int i, GString *str);
- GString *insert(int i, const char *str);
- GString *insert(int i, const char *str, int lengthA);
-
- // Delete a character or range of characters.
- GString *del(int i, int n = 1);
-
- // Convert string to all-upper/all-lower case.
- GString *upperCase();
- GString *lowerCase();
-
- // Compare two strings: -1:< 0:= +1:>
- int cmp(GString *str);
- int cmpN(GString *str, int n);
- int cmp(const char *sA);
- int cmpN(const char *sA, int n);
-
-private:
-
- int length;
- char *s;
-
- void resize(int length1);
-};
-
-#endif
+++ /dev/null
-//========================================================================
-//
-// Gfx.cc
-//
-// Copyright 1996-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma implementation
-#endif
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <stddef.h>
-#include <string.h>
-#include <math.h>
-#include "gmem.h"
-#include "GlobalParams.h"
-#include "CharTypes.h"
-#include "Object.h"
-#include "Array.h"
-#include "Dict.h"
-#include "Stream.h"
-#include "Lexer.h"
-#include "Parser.h"
-#include "GfxFont.h"
-#include "GfxState.h"
-#include "OutputDev.h"
-#include "Page.h"
-#include "Error.h"
-#include "Gfx.h"
-
-// the MSVC math.h doesn't define this
-#ifndef M_PI
-#define M_PI 3.14159265358979323846
-#endif
-
-//------------------------------------------------------------------------
-// constants
-//------------------------------------------------------------------------
-
-// Max recursive depth for a function shading fill.
-#define functionMaxDepth 6
-
-// Max delta allowed in any color component for a function shading fill.
-#define functionColorDelta (dblToCol(1 / 256.0))
-
-// Max number of splits along the t axis for an axial shading fill.
-#define axialMaxSplits 256
-
-// Max delta allowed in any color component for an axial shading fill.
-#define axialColorDelta (dblToCol(1 / 256.0))
-
-// Max number of splits along the t axis for a radial shading fill.
-#define radialMaxSplits 256
-
-// Max delta allowed in any color component for a radial shading fill.
-#define radialColorDelta (dblToCol(1 / 256.0))
-
-// Max recursive depth for a Gouraud triangle shading fill.
-#define gouraudMaxDepth 4
-
-// Max delta allowed in any color component for a Gouraud triangle
-// shading fill.
-#define gouraudColorDelta (dblToCol(1 / 256.0))
-
-// Max recursive depth for a patch mesh shading fill.
-#define patchMaxDepth 6
-
-// Max delta allowed in any color component for a patch mesh shading
-// fill.
-#define patchColorDelta (dblToCol(1 / 256.0))
-
-//------------------------------------------------------------------------
-// Operator table
-//------------------------------------------------------------------------
-
-#ifdef WIN32 // this works around a bug in the VC7 compiler
-# pragma optimize("",off)
-#endif
-
-Operator Gfx::opTab[] = {
- {"\"", 3, {tchkNum, tchkNum, tchkString},
- &Gfx::opMoveSetShowText},
- {"'", 1, {tchkString},
- &Gfx::opMoveShowText},
- {"B", 0, {tchkNone},
- &Gfx::opFillStroke},
- {"B*", 0, {tchkNone},
- &Gfx::opEOFillStroke},
- {"BDC", 2, {tchkName, tchkProps},
- &Gfx::opBeginMarkedContent},
- {"BI", 0, {tchkNone},
- &Gfx::opBeginImage},
- {"BMC", 1, {tchkName},
- &Gfx::opBeginMarkedContent},
- {"BT", 0, {tchkNone},
- &Gfx::opBeginText},
- {"BX", 0, {tchkNone},
- &Gfx::opBeginIgnoreUndef},
- {"CS", 1, {tchkName},
- &Gfx::opSetStrokeColorSpace},
- {"DP", 2, {tchkName, tchkProps},
- &Gfx::opMarkPoint},
- {"Do", 1, {tchkName},
- &Gfx::opXObject},
- {"EI", 0, {tchkNone},
- &Gfx::opEndImage},
- {"EMC", 0, {tchkNone},
- &Gfx::opEndMarkedContent},
- {"ET", 0, {tchkNone},
- &Gfx::opEndText},
- {"EX", 0, {tchkNone},
- &Gfx::opEndIgnoreUndef},
- {"F", 0, {tchkNone},
- &Gfx::opFill},
- {"G", 1, {tchkNum},
- &Gfx::opSetStrokeGray},
- {"ID", 0, {tchkNone},
- &Gfx::opImageData},
- {"J", 1, {tchkInt},
- &Gfx::opSetLineCap},
- {"K", 4, {tchkNum, tchkNum, tchkNum, tchkNum},
- &Gfx::opSetStrokeCMYKColor},
- {"M", 1, {tchkNum},
- &Gfx::opSetMiterLimit},
- {"MP", 1, {tchkName},
- &Gfx::opMarkPoint},
- {"Q", 0, {tchkNone},
- &Gfx::opRestore},
- {"RG", 3, {tchkNum, tchkNum, tchkNum},
- &Gfx::opSetStrokeRGBColor},
- {"S", 0, {tchkNone},
- &Gfx::opStroke},
- {"SC", -4, {tchkNum, tchkNum, tchkNum, tchkNum},
- &Gfx::opSetStrokeColor},
- {"SCN", -5, {tchkSCN, tchkSCN, tchkSCN, tchkSCN,
- tchkSCN},
- &Gfx::opSetStrokeColorN},
- {"T*", 0, {tchkNone},
- &Gfx::opTextNextLine},
- {"TD", 2, {tchkNum, tchkNum},
- &Gfx::opTextMoveSet},
- {"TJ", 1, {tchkArray},
- &Gfx::opShowSpaceText},
- {"TL", 1, {tchkNum},
- &Gfx::opSetTextLeading},
- {"Tc", 1, {tchkNum},
- &Gfx::opSetCharSpacing},
- {"Td", 2, {tchkNum, tchkNum},
- &Gfx::opTextMove},
- {"Tf", 2, {tchkName, tchkNum},
- &Gfx::opSetFont},
- {"Tj", 1, {tchkString},
- &Gfx::opShowText},
- {"Tm", 6, {tchkNum, tchkNum, tchkNum, tchkNum,
- tchkNum, tchkNum},
- &Gfx::opSetTextMatrix},
- {"Tr", 1, {tchkInt},
- &Gfx::opSetTextRender},
- {"Ts", 1, {tchkNum},
- &Gfx::opSetTextRise},
- {"Tw", 1, {tchkNum},
- &Gfx::opSetWordSpacing},
- {"Tz", 1, {tchkNum},
- &Gfx::opSetHorizScaling},
- {"W", 0, {tchkNone},
- &Gfx::opClip},
- {"W*", 0, {tchkNone},
- &Gfx::opEOClip},
- {"b", 0, {tchkNone},
- &Gfx::opCloseFillStroke},
- {"b*", 0, {tchkNone},
- &Gfx::opCloseEOFillStroke},
- {"c", 6, {tchkNum, tchkNum, tchkNum, tchkNum,
- tchkNum, tchkNum},
- &Gfx::opCurveTo},
- {"cm", 6, {tchkNum, tchkNum, tchkNum, tchkNum,
- tchkNum, tchkNum},
- &Gfx::opConcat},
- {"cs", 1, {tchkName},
- &Gfx::opSetFillColorSpace},
- {"d", 2, {tchkArray, tchkNum},
- &Gfx::opSetDash},
- {"d0", 2, {tchkNum, tchkNum},
- &Gfx::opSetCharWidth},
- {"d1", 6, {tchkNum, tchkNum, tchkNum, tchkNum,
- tchkNum, tchkNum},
- &Gfx::opSetCacheDevice},
- {"f", 0, {tchkNone},
- &Gfx::opFill},
- {"f*", 0, {tchkNone},
- &Gfx::opEOFill},
- {"g", 1, {tchkNum},
- &Gfx::opSetFillGray},
- {"gs", 1, {tchkName},
- &Gfx::opSetExtGState},
- {"h", 0, {tchkNone},
- &Gfx::opClosePath},
- {"i", 1, {tchkNum},
- &Gfx::opSetFlat},
- {"j", 1, {tchkInt},
- &Gfx::opSetLineJoin},
- {"k", 4, {tchkNum, tchkNum, tchkNum, tchkNum},
- &Gfx::opSetFillCMYKColor},
- {"l", 2, {tchkNum, tchkNum},
- &Gfx::opLineTo},
- {"m", 2, {tchkNum, tchkNum},
- &Gfx::opMoveTo},
- {"n", 0, {tchkNone},
- &Gfx::opEndPath},
- {"q", 0, {tchkNone},
- &Gfx::opSave},
- {"re", 4, {tchkNum, tchkNum, tchkNum, tchkNum},
- &Gfx::opRectangle},
- {"rg", 3, {tchkNum, tchkNum, tchkNum},
- &Gfx::opSetFillRGBColor},
- {"ri", 1, {tchkName},
- &Gfx::opSetRenderingIntent},
- {"s", 0, {tchkNone},
- &Gfx::opCloseStroke},
- {"sc", -4, {tchkNum, tchkNum, tchkNum, tchkNum},
- &Gfx::opSetFillColor},
- {"scn", -5, {tchkSCN, tchkSCN, tchkSCN, tchkSCN,
- tchkSCN},
- &Gfx::opSetFillColorN},
- {"sh", 1, {tchkName},
- &Gfx::opShFill},
- {"v", 4, {tchkNum, tchkNum, tchkNum, tchkNum},
- &Gfx::opCurveTo1},
- {"w", 1, {tchkNum},
- &Gfx::opSetLineWidth},
- {"y", 4, {tchkNum, tchkNum, tchkNum, tchkNum},
- &Gfx::opCurveTo2},
-};
-
-#ifdef WIN32 // this works around a bug in the VC7 compiler
-# pragma optimize("",on)
-#endif
-
-#define numOps (sizeof(opTab) / sizeof(Operator))
-
-//------------------------------------------------------------------------
-// GfxResources
-//------------------------------------------------------------------------
-
-GfxResources::GfxResources(XRef *xref, Dict *resDict, GfxResources *nextA) {
- Object obj1, obj2;
- Ref r;
-
- if (resDict) {
-
- // build font dictionary
- fonts = NULL;
- resDict->lookupNF("Font", &obj1);
- if (obj1.isRef()) {
- obj1.fetch(xref, &obj2);
- if (obj2.isDict()) {
- r = obj1.getRef();
- fonts = new GfxFontDict(xref, &r, obj2.getDict());
- }
- obj2.free();
- } else if (obj1.isDict()) {
- fonts = new GfxFontDict(xref, NULL, obj1.getDict());
- }
- obj1.free();
-
- // get XObject dictionary
- resDict->lookup("XObject", &xObjDict);
-
- // get color space dictionary
- resDict->lookup("ColorSpace", &colorSpaceDict);
-
- // get pattern dictionary
- resDict->lookup("Pattern", &patternDict);
-
- // get shading dictionary
- resDict->lookup("Shading", &shadingDict);
-
- // get graphics state parameter dictionary
- resDict->lookup("ExtGState", &gStateDict);
-
- } else {
- fonts = NULL;
- xObjDict.initNull();
- colorSpaceDict.initNull();
- patternDict.initNull();
- shadingDict.initNull();
- gStateDict.initNull();
- }
-
- next = nextA;
-}
-
-GfxResources::~GfxResources() {
- if (fonts) {
- delete fonts;
- }
- xObjDict.free();
- colorSpaceDict.free();
- patternDict.free();
- shadingDict.free();
- gStateDict.free();
-}
-
-GfxFont *GfxResources::lookupFont(char *name) {
- GfxFont *font;
- GfxResources *resPtr;
-
- for (resPtr = this; resPtr; resPtr = resPtr->next) {
- if (resPtr->fonts) {
- if ((font = resPtr->fonts->lookup(name)))
- return font;
- }
- }
- error(-1, "Unknown font tag '%s'", name);
- return NULL;
-}
-
-GBool GfxResources::lookupXObject(char *name, Object *obj) {
- GfxResources *resPtr;
-
- for (resPtr = this; resPtr; resPtr = resPtr->next) {
- if (resPtr->xObjDict.isDict()) {
- if (!resPtr->xObjDict.dictLookup(name, obj)->isNull())
- return gTrue;
- obj->free();
- }
- }
- error(-1, "XObject '%s' is unknown", name);
- return gFalse;
-}
-
-GBool GfxResources::lookupXObjectNF(char *name, Object *obj) {
- GfxResources *resPtr;
-
- for (resPtr = this; resPtr; resPtr = resPtr->next) {
- if (resPtr->xObjDict.isDict()) {
- if (!resPtr->xObjDict.dictLookupNF(name, obj)->isNull())
- return gTrue;
- obj->free();
- }
- }
- error(-1, "XObject '%s' is unknown", name);
- return gFalse;
-}
-
-void GfxResources::lookupColorSpace(char *name, Object *obj) {
- GfxResources *resPtr;
-
- for (resPtr = this; resPtr; resPtr = resPtr->next) {
- if (resPtr->colorSpaceDict.isDict()) {
- if (!resPtr->colorSpaceDict.dictLookup(name, obj)->isNull()) {
- return;
- }
- obj->free();
- }
- }
- obj->initNull();
-}
-
-GfxPattern *GfxResources::lookupPattern(char *name) {
- GfxResources *resPtr;
- GfxPattern *pattern;
- Object obj;
-
- for (resPtr = this; resPtr; resPtr = resPtr->next) {
- if (resPtr->patternDict.isDict()) {
- if (!resPtr->patternDict.dictLookup(name, &obj)->isNull()) {
- pattern = GfxPattern::parse(&obj);
- obj.free();
- return pattern;
- }
- obj.free();
- }
- }
- error(-1, "Unknown pattern '%s'", name);
- return NULL;
-}
-
-GfxShading *GfxResources::lookupShading(char *name) {
- GfxResources *resPtr;
- GfxShading *shading;
- Object obj;
-
- for (resPtr = this; resPtr; resPtr = resPtr->next) {
- if (resPtr->shadingDict.isDict()) {
- if (!resPtr->shadingDict.dictLookup(name, &obj)->isNull()) {
- shading = GfxShading::parse(&obj);
- obj.free();
- return shading;
- }
- obj.free();
- }
- }
- error(-1, "Unknown shading '%s'", name);
- return NULL;
-}
-
-GBool GfxResources::lookupGState(char *name, Object *obj) {
- GfxResources *resPtr;
-
- for (resPtr = this; resPtr; resPtr = resPtr->next) {
- if (resPtr->gStateDict.isDict()) {
- if (!resPtr->gStateDict.dictLookup(name, obj)->isNull()) {
- return gTrue;
- }
- obj->free();
- }
- }
- error(-1, "ExtGState '%s' is unknown", name);
- return gFalse;
-}
-
-//------------------------------------------------------------------------
-// Gfx
-//------------------------------------------------------------------------
-
-Gfx::Gfx(XRef *xrefA, OutputDev *outA, int pageNum, Dict *resDict,
- double hDPI, double vDPI, PDFRectangle *box,
- PDFRectangle *cropBox, int rotate,
- GBool (*abortCheckCbkA)(void *data),
- void *abortCheckCbkDataA) {
- int i;
-
- xref = xrefA;
- subPage = gFalse;
- printCommands = globalParams->getPrintCommands();
-
- // start the resource stack
- res = new GfxResources(xref, resDict, NULL);
-
- // initialize
- out = outA;
- state = new GfxState(hDPI, vDPI, box, rotate, out->upsideDown());
- fontChanged = gFalse;
- clip = clipNone;
- ignoreUndef = 0;
- out->startPage(pageNum, state, cropBox->x1,cropBox->y1,cropBox->x2,cropBox->y2);
- out->setDefaultCTM(state->getCTM());
- out->updateAll(state);
- for (i = 0; i < 6; ++i) {
- baseMatrix[i] = state->getCTM()[i];
- }
- formDepth = 0;
- abortCheckCbk = abortCheckCbkA;
- abortCheckCbkData = abortCheckCbkDataA;
-
- // set crop box
- /*if (cropBox) {
- state->moveTo(cropBox->x1, cropBox->y1);
- state->lineTo(cropBox->x2, cropBox->y1);
- state->lineTo(cropBox->x2, cropBox->y2);
- state->lineTo(cropBox->x1, cropBox->y2);
- state->closePath();
- state->clip();
- out->clip(state);
- state->clearPath();
- }*/
-}
-
-Gfx::Gfx(XRef *xrefA, OutputDev *outA, Dict *resDict,
- PDFRectangle *box, PDFRectangle *cropBox,
- GBool (*abortCheckCbkA)(void *data),
- void *abortCheckCbkDataA) {
- int i;
-
- xref = xrefA;
- subPage = gTrue;
- printCommands = globalParams->getPrintCommands();
-
- // start the resource stack
- res = new GfxResources(xref, resDict, NULL);
-
- // initialize
- out = outA;
- state = new GfxState(72, 72, box, 0, gFalse);
- fontChanged = gFalse;
- clip = clipNone;
- ignoreUndef = 0;
- for (i = 0; i < 6; ++i) {
- baseMatrix[i] = state->getCTM()[i];
- }
- formDepth = 0;
- abortCheckCbk = abortCheckCbkA;
- abortCheckCbkData = abortCheckCbkDataA;
-
- // set crop box
- if (cropBox) {
- state->moveTo(cropBox->x1, cropBox->y1);
- state->lineTo(cropBox->x2, cropBox->y1);
- state->lineTo(cropBox->x2, cropBox->y2);
- state->lineTo(cropBox->x1, cropBox->y2);
- state->closePath();
- state->clip();
- out->clip(state);
- state->clearPath();
- }
-}
-
-Gfx::~Gfx() {
- while (state->hasSaves()) {
- restoreState();
- }
- if (!subPage) {
- out->endPage();
- }
- while (res) {
- popResources();
- }
- if (state) {
- delete state;
- }
-}
-
-void Gfx::display(Object *obj, GBool topLevel) {
- Object obj2;
- int i;
-
- if (obj->isArray()) {
- for (i = 0; i < obj->arrayGetLength(); ++i) {
- obj->arrayGet(i, &obj2);
- if (!obj2.isStream()) {
- error(-1, "Weird page contents");
- obj2.free();
- return;
- }
- obj2.free();
- }
- } else if (!obj->isStream()) {
- error(-1, "Weird page contents");
- return;
- }
- parser = new Parser(xref, new Lexer(xref, obj));
- go(topLevel);
- delete parser;
- parser = NULL;
-}
-
-void Gfx::go(GBool topLevel) {
- Object obj;
- Object args[maxArgs];
- int numArgs, i;
- int lastAbortCheck;
-
- // scan a sequence of objects
- updateLevel = lastAbortCheck = 0;
- numArgs = 0;
- parser->getObj(&obj);
- while (!obj.isEOF()) {
-
- // got a command - execute it
- if (obj.isCmd()) {
- if (printCommands) {
- obj.print(stdout);
- for (i = 0; i < numArgs; ++i) {
- printf(" ");
- args[i].print(stdout);
- }
- printf("\n");
- fflush(stdout);
- }
- execOp(&obj, args, numArgs);
- obj.free();
- for (i = 0; i < numArgs; ++i)
- args[i].free();
- numArgs = 0;
-
- // periodically update display
- if (++updateLevel >= 20000) {
- out->dump();
- updateLevel = 0;
- }
-
- // check for an abort
- if (abortCheckCbk) {
- if (updateLevel - lastAbortCheck > 10) {
- if ((*abortCheckCbk)(abortCheckCbkData)) {
- break;
- }
- lastAbortCheck = updateLevel;
- }
- }
-
- // got an argument - save it
- } else if (numArgs < maxArgs) {
- args[numArgs++] = obj;
-
- // too many arguments - something is wrong
- } else {
- error(getPos(), "Too many args in content stream");
- if (printCommands) {
- printf("throwing away arg: ");
- obj.print(stdout);
- printf("\n");
- fflush(stdout);
- }
- obj.free();
- }
-
- // grab the next object
- parser->getObj(&obj);
- }
- obj.free();
-
- // args at end with no command
- if (numArgs > 0) {
- error(getPos(), "Leftover args in content stream");
- if (printCommands) {
- printf("%d leftovers:", numArgs);
- for (i = 0; i < numArgs; ++i) {
- printf(" ");
- args[i].print(stdout);
- }
- printf("\n");
- fflush(stdout);
- }
- for (i = 0; i < numArgs; ++i)
- args[i].free();
- }
-
- // update display
- if (topLevel && updateLevel > 0) {
- out->dump();
- }
-}
-
-void Gfx::execOp(Object *cmd, Object args[], int numArgs) {
- Operator *op;
- char *name;
- Object *argPtr;
- int i;
-
- // find operator
- name = cmd->getCmd();
- if (!(op = findOp(name))) {
- if (ignoreUndef == 0)
- error(getPos(), "Unknown operator '%s'", name);
- return;
- }
-
- // type check args
- argPtr = args;
- if (op->numArgs >= 0) {
- if (numArgs < op->numArgs) {
- error(getPos(), "Too few (%d) args to '%s' operator", numArgs, name);
- return;
- }
- if (numArgs > op->numArgs) {
-#if 0
- error(getPos(), "Too many (%d) args to '%s' operator", numArgs, name);
-#endif
- argPtr += numArgs - op->numArgs;
- numArgs = op->numArgs;
- }
- } else {
- if (numArgs > -op->numArgs) {
- error(getPos(), "Too many (%d) args to '%s' operator",
- numArgs, name);
- return;
- }
- }
- for (i = 0; i < numArgs; ++i) {
- if (!checkArg(&argPtr[i], op->tchk[i])) {
- error(getPos(), "Arg #%d to '%s' operator is wrong type (%s)",
- i, name, argPtr[i].getTypeName());
- return;
- }
- }
-
- // do it
- (this->*op->func)(argPtr, numArgs);
-}
-
-Operator *Gfx::findOp(char *name) {
- int a, b, m, cmp;
-
- a = -1;
- b = numOps;
- // invariant: opTab[a] < name < opTab[b]
- while (b - a > 1) {
- m = (a + b) / 2;
- cmp = strcmp(opTab[m].name, name);
- if (cmp < 0)
- a = m;
- else if (cmp > 0)
- b = m;
- else
- a = b = m;
- }
- if (cmp != 0)
- return NULL;
- return &opTab[a];
-}
-
-GBool Gfx::checkArg(Object *arg, TchkType type) {
- switch (type) {
- case tchkBool: return arg->isBool();
- case tchkInt: return arg->isInt();
- case tchkNum: return arg->isNum();
- case tchkString: return arg->isString();
- case tchkName: return arg->isName();
- case tchkArray: return arg->isArray();
- case tchkProps: return arg->isDict() || arg->isName();
- case tchkSCN: return arg->isNum() || arg->isName();
- case tchkNone: return gFalse;
- }
- return gFalse;
-}
-
-int Gfx::getPos() {
- return parser ? parser->getPos() : -1;
-}
-
-//------------------------------------------------------------------------
-// graphics state operators
-//------------------------------------------------------------------------
-
-void Gfx::opSave(Object args[], int numArgs) {
- saveState();
-}
-
-void Gfx::opRestore(Object args[], int numArgs) {
- restoreState();
-}
-
-void Gfx::opConcat(Object args[], int numArgs) {
- state->concatCTM(args[0].getNum(), args[1].getNum(),
- args[2].getNum(), args[3].getNum(),
- args[4].getNum(), args[5].getNum());
- out->updateCTM(state, args[0].getNum(), args[1].getNum(),
- args[2].getNum(), args[3].getNum(),
- args[4].getNum(), args[5].getNum());
- fontChanged = gTrue;
-}
-
-void Gfx::opSetDash(Object args[], int numArgs) {
- Array *a;
- int length;
- Object obj;
- double *dash;
- int i;
-
- a = args[0].getArray();
- length = a->getLength();
- if (length == 0) {
- dash = NULL;
- } else {
- dash = (double *)gmallocn(length, sizeof(double));
- for (i = 0; i < length; ++i) {
- dash[i] = a->get(i, &obj)->getNum();
- obj.free();
- }
- }
- state->setLineDash(dash, length, args[1].getNum());
- out->updateLineDash(state);
-}
-
-void Gfx::opSetFlat(Object args[], int numArgs) {
- state->setFlatness((int)args[0].getNum());
- out->updateFlatness(state);
-}
-
-void Gfx::opSetLineJoin(Object args[], int numArgs) {
- state->setLineJoin(args[0].getInt());
- out->updateLineJoin(state);
-}
-
-void Gfx::opSetLineCap(Object args[], int numArgs) {
- state->setLineCap(args[0].getInt());
- out->updateLineCap(state);
-}
-
-void Gfx::opSetMiterLimit(Object args[], int numArgs) {
- state->setMiterLimit(args[0].getNum());
- out->updateMiterLimit(state);
-}
-
-void Gfx::opSetLineWidth(Object args[], int numArgs) {
- state->setLineWidth(args[0].getNum());
- out->updateLineWidth(state);
-}
-
-void Gfx::opSetExtGState(Object args[], int numArgs) {
- Object obj1, obj2;
- GfxBlendMode mode;
- GBool haveFillOP;
-
- if (!res->lookupGState(args[0].getName(), &obj1)) {
- return;
- }
- if (!obj1.isDict()) {
- error(getPos(), "ExtGState '%s' is wrong type", args[0].getName());
- obj1.free();
- return;
- }
-
- // transparency support: blend mode, fill/stroke opacity
- if (!obj1.dictLookup("BM", &obj2)->isNull()) {
- if (state->parseBlendMode(&obj2, &mode)) {
- state->setBlendMode(mode);
- out->updateBlendMode(state);
- } else {
- error(getPos(), "Invalid blend mode in ExtGState");
- }
- }
- obj2.free();
- if (obj1.dictLookup("ca", &obj2)->isNum()) {
- state->setFillOpacity(obj2.getNum());
- out->updateFillOpacity(state);
- }
- obj2.free();
- if (obj1.dictLookup("CA", &obj2)->isNum()) {
- state->setStrokeOpacity(obj2.getNum());
- out->updateStrokeOpacity(state);
- }
- obj2.free();
-
- // fill/stroke overprint
- if ((haveFillOP = (obj1.dictLookup("op", &obj2)->isBool()))) {
- state->setFillOverprint(obj2.getBool());
- out->updateFillOverprint(state);
- }
- obj2.free();
- if (obj1.dictLookup("OP", &obj2)->isBool()) {
- state->setStrokeOverprint(obj2.getBool());
- out->updateStrokeOverprint(state);
- if (!haveFillOP) {
- state->setFillOverprint(obj2.getBool());
- out->updateFillOverprint(state);
- }
- }
- obj2.free();
-
- obj1.free();
-}
-
-void Gfx::opSetRenderingIntent(Object args[], int numArgs) {
-}
-
-//------------------------------------------------------------------------
-// color operators
-//------------------------------------------------------------------------
-
-void Gfx::opSetFillGray(Object args[], int numArgs) {
- GfxColor color;
-
- state->setFillPattern(NULL);
- state->setFillColorSpace(new GfxDeviceGrayColorSpace());
- out->updateFillColorSpace(state);
- color.c[0] = dblToCol(args[0].getNum());
- state->setFillColor(&color);
- out->updateFillColor(state);
-}
-
-void Gfx::opSetStrokeGray(Object args[], int numArgs) {
- GfxColor color;
-
- state->setStrokePattern(NULL);
- state->setStrokeColorSpace(new GfxDeviceGrayColorSpace());
- out->updateStrokeColorSpace(state);
- color.c[0] = dblToCol(args[0].getNum());
- state->setStrokeColor(&color);
- out->updateStrokeColor(state);
-}
-
-void Gfx::opSetFillCMYKColor(Object args[], int numArgs) {
- GfxColor color;
- int i;
-
- state->setFillPattern(NULL);
- state->setFillColorSpace(new GfxDeviceCMYKColorSpace());
- out->updateFillColorSpace(state);
- for (i = 0; i < 4; ++i) {
- color.c[i] = dblToCol(args[i].getNum());
- }
- state->setFillColor(&color);
- out->updateFillColor(state);
-}
-
-void Gfx::opSetStrokeCMYKColor(Object args[], int numArgs) {
- GfxColor color;
- int i;
-
- state->setStrokePattern(NULL);
- state->setStrokeColorSpace(new GfxDeviceCMYKColorSpace());
- out->updateStrokeColorSpace(state);
- for (i = 0; i < 4; ++i) {
- color.c[i] = dblToCol(args[i].getNum());
- }
- state->setStrokeColor(&color);
- out->updateStrokeColor(state);
-}
-
-void Gfx::opSetFillRGBColor(Object args[], int numArgs) {
- GfxColor color;
- int i;
-
- state->setFillPattern(NULL);
- state->setFillColorSpace(new GfxDeviceRGBColorSpace());
- out->updateFillColorSpace(state);
- for (i = 0; i < 3; ++i) {
- color.c[i] = dblToCol(args[i].getNum());
- }
- state->setFillColor(&color);
- out->updateFillColor(state);
-}
-
-void Gfx::opSetStrokeRGBColor(Object args[], int numArgs) {
- GfxColor color;
- int i;
-
- state->setStrokePattern(NULL);
- state->setStrokeColorSpace(new GfxDeviceRGBColorSpace());
- out->updateStrokeColorSpace(state);
- for (i = 0; i < 3; ++i) {
- color.c[i] = dblToCol(args[i].getNum());
- }
- state->setStrokeColor(&color);
- out->updateStrokeColor(state);
-}
-
-void Gfx::opSetFillColorSpace(Object args[], int numArgs) {
- Object obj;
- GfxColorSpace *colorSpace;
- GfxColor color;
- int i;
-
- state->setFillPattern(NULL);
- res->lookupColorSpace(args[0].getName(), &obj);
- if (obj.isNull()) {
- colorSpace = GfxColorSpace::parse(&args[0]);
- } else {
- colorSpace = GfxColorSpace::parse(&obj);
- }
- obj.free();
- if (colorSpace) {
- state->setFillColorSpace(colorSpace);
- out->updateFillColorSpace(state);
- } else {
- error(getPos(), "Bad color space (fill)");
- }
- for (i = 0; i < gfxColorMaxComps; ++i) {
- color.c[i] = 0;
- }
- state->setFillColor(&color);
- out->updateFillColor(state);
-}
-
-void Gfx::opSetStrokeColorSpace(Object args[], int numArgs) {
- Object obj;
- GfxColorSpace *colorSpace;
- GfxColor color;
- int i;
-
- state->setStrokePattern(NULL);
- res->lookupColorSpace(args[0].getName(), &obj);
- if (obj.isNull()) {
- colorSpace = GfxColorSpace::parse(&args[0]);
- } else {
- colorSpace = GfxColorSpace::parse(&obj);
- }
- obj.free();
- if (colorSpace) {
- state->setStrokeColorSpace(colorSpace);
- out->updateStrokeColorSpace(state);
- } else {
- error(getPos(), "Bad color space (stroke)");
- }
- for (i = 0; i < gfxColorMaxComps; ++i) {
- color.c[i] = 0;
- }
- state->setStrokeColor(&color);
- out->updateStrokeColor(state);
-}
-
-void Gfx::opSetFillColor(Object args[], int numArgs) {
- GfxColor color;
- int i;
-
- state->setFillPattern(NULL);
- for (i = 0; i < numArgs; ++i) {
- color.c[i] = dblToCol(args[i].getNum());
- }
- state->setFillColor(&color);
- out->updateFillColor(state);
-}
-
-void Gfx::opSetStrokeColor(Object args[], int numArgs) {
- GfxColor color;
- int i;
-
- state->setStrokePattern(NULL);
- for (i = 0; i < numArgs; ++i) {
- color.c[i] = dblToCol(args[i].getNum());
- }
- state->setStrokeColor(&color);
- out->updateStrokeColor(state);
-}
-
-void Gfx::opSetFillColorN(Object args[], int numArgs) {
- GfxColor color;
- GfxPattern *pattern;
- int i;
-
- if (state->getFillColorSpace()->getMode() == csPattern) {
- if (numArgs > 1) {
- for (i = 0; i < numArgs && i < 4; ++i) {
- if (args[i].isNum()) {
- color.c[i] = dblToCol(args[i].getNum());
- }
- }
- state->setFillColor(&color);
- out->updateFillColor(state);
- }
- if (args[numArgs-1].isName() &&
- (pattern = res->lookupPattern(args[numArgs-1].getName()))) {
- state->setFillPattern(pattern);
- }
-
- } else {
- state->setFillPattern(NULL);
- for (i = 0; i < numArgs && i < 4; ++i) {
- if (args[i].isNum()) {
- color.c[i] = dblToCol(args[i].getNum());
- }
- }
- state->setFillColor(&color);
- out->updateFillColor(state);
- }
-}
-
-void Gfx::opSetStrokeColorN(Object args[], int numArgs) {
- GfxColor color;
- GfxPattern *pattern;
- int i;
-
- if (state->getStrokeColorSpace()->getMode() == csPattern) {
- if (numArgs > 1) {
- for (i = 0; i < numArgs && i < 4; ++i) {
- if (args[i].isNum()) {
- color.c[i] = dblToCol(args[i].getNum());
- }
- }
- state->setStrokeColor(&color);
- out->updateStrokeColor(state);
- }
- if (args[numArgs-1].isName() &&
- (pattern = res->lookupPattern(args[numArgs-1].getName()))) {
- state->setStrokePattern(pattern);
- }
-
- } else {
- state->setStrokePattern(NULL);
- for (i = 0; i < numArgs && i < 4; ++i) {
- if (args[i].isNum()) {
- color.c[i] = dblToCol(args[i].getNum());
- }
- }
- state->setStrokeColor(&color);
- out->updateStrokeColor(state);
- }
-}
-
-//------------------------------------------------------------------------
-// path segment operators
-//------------------------------------------------------------------------
-
-void Gfx::opMoveTo(Object args[], int numArgs) {
- state->moveTo(args[0].getNum(), args[1].getNum());
-}
-
-void Gfx::opLineTo(Object args[], int numArgs) {
- if (!state->isCurPt()) {
- error(getPos(), "No current point in lineto");
- return;
- }
- state->lineTo(args[0].getNum(), args[1].getNum());
-}
-
-void Gfx::opCurveTo(Object args[], int numArgs) {
- double x1, y1, x2, y2, x3, y3;
-
- if (!state->isCurPt()) {
- error(getPos(), "No current point in curveto");
- return;
- }
- x1 = args[0].getNum();
- y1 = args[1].getNum();
- x2 = args[2].getNum();
- y2 = args[3].getNum();
- x3 = args[4].getNum();
- y3 = args[5].getNum();
- state->curveTo(x1, y1, x2, y2, x3, y3);
-}
-
-void Gfx::opCurveTo1(Object args[], int numArgs) {
- double x1, y1, x2, y2, x3, y3;
-
- if (!state->isCurPt()) {
- error(getPos(), "No current point in curveto1");
- return;
- }
- x1 = state->getCurX();
- y1 = state->getCurY();
- x2 = args[0].getNum();
- y2 = args[1].getNum();
- x3 = args[2].getNum();
- y3 = args[3].getNum();
- state->curveTo(x1, y1, x2, y2, x3, y3);
-}
-
-void Gfx::opCurveTo2(Object args[], int numArgs) {
- double x1, y1, x2, y2, x3, y3;
-
- if (!state->isCurPt()) {
- error(getPos(), "No current point in curveto2");
- return;
- }
- x1 = args[0].getNum();
- y1 = args[1].getNum();
- x2 = args[2].getNum();
- y2 = args[3].getNum();
- x3 = x2;
- y3 = y2;
- state->curveTo(x1, y1, x2, y2, x3, y3);
-}
-
-void Gfx::opRectangle(Object args[], int numArgs) {
- double x, y, w, h;
-
- x = args[0].getNum();
- y = args[1].getNum();
- w = args[2].getNum();
- h = args[3].getNum();
- state->moveTo(x, y);
- state->lineTo(x + w, y);
- state->lineTo(x + w, y + h);
- state->lineTo(x, y + h);
- state->closePath();
-}
-
-void Gfx::opClosePath(Object args[], int numArgs) {
- if (!state->isCurPt()) {
- error(getPos(), "No current point in closepath");
- return;
- }
- state->closePath();
-}
-
-//------------------------------------------------------------------------
-// path painting operators
-//------------------------------------------------------------------------
-
-void Gfx::opEndPath(Object args[], int numArgs) {
- doEndPath();
-}
-
-void Gfx::opStroke(Object args[], int numArgs) {
- if (!state->isCurPt()) {
- //error(getPos(), "No path in stroke");
- return;
- }
- if (state->isPath())
- out->stroke(state);
- doEndPath();
-}
-
-void Gfx::opCloseStroke(Object args[], int numArgs) {
- if (!state->isCurPt()) {
- //error(getPos(), "No path in closepath/stroke");
- return;
- }
- if (state->isPath()) {
- state->closePath();
- out->stroke(state);
- }
- doEndPath();
-}
-
-void Gfx::opFill(Object args[], int numArgs) {
- if (!state->isCurPt()) {
- //error(getPos(), "No path in fill");
- return;
- }
- if (state->isPath()) {
- if (state->getFillColorSpace()->getMode() == csPattern) {
- doPatternFill(gFalse);
- } else {
- out->fill(state);
- }
- }
- doEndPath();
-}
-
-void Gfx::opEOFill(Object args[], int numArgs) {
- if (!state->isCurPt()) {
- //error(getPos(), "No path in eofill");
- return;
- }
- if (state->isPath()) {
- if (state->getFillColorSpace()->getMode() == csPattern) {
- doPatternFill(gTrue);
- } else {
- out->eoFill(state);
- }
- }
- doEndPath();
-}
-
-void Gfx::opFillStroke(Object args[], int numArgs) {
- if (!state->isCurPt()) {
- //error(getPos(), "No path in fill/stroke");
- return;
- }
- if (state->isPath()) {
- if (state->getFillColorSpace()->getMode() == csPattern) {
- doPatternFill(gFalse);
- } else {
- out->fill(state);
- }
- out->stroke(state);
- }
- doEndPath();
-}
-
-void Gfx::opCloseFillStroke(Object args[], int numArgs) {
- if (!state->isCurPt()) {
- //error(getPos(), "No path in closepath/fill/stroke");
- return;
- }
- if (state->isPath()) {
- state->closePath();
- if (state->getFillColorSpace()->getMode() == csPattern) {
- doPatternFill(gFalse);
- } else {
- out->fill(state);
- }
- out->stroke(state);
- }
- doEndPath();
-}
-
-void Gfx::opEOFillStroke(Object args[], int numArgs) {
- if (!state->isCurPt()) {
- //error(getPos(), "No path in eofill/stroke");
- return;
- }
- if (state->isPath()) {
- if (state->getFillColorSpace()->getMode() == csPattern) {
- doPatternFill(gTrue);
- } else {
- out->eoFill(state);
- }
- out->stroke(state);
- }
- doEndPath();
-}
-
-void Gfx::opCloseEOFillStroke(Object args[], int numArgs) {
- if (!state->isCurPt()) {
- //error(getPos(), "No path in closepath/eofill/stroke");
- return;
- }
- if (state->isPath()) {
- state->closePath();
- if (state->getFillColorSpace()->getMode() == csPattern) {
- doPatternFill(gTrue);
- } else {
- out->eoFill(state);
- }
- out->stroke(state);
- }
- doEndPath();
-}
-
-void Gfx::doPatternFill(GBool eoFill) {
- GfxPattern *pattern;
-
- // this is a bit of a kludge -- patterns can be really slow, so we
- // skip them if we're only doing text extraction, since they almost
- // certainly don't contain any text
- if (!out->needNonText()) {
- return;
- }
-
- if (!(pattern = state->getFillPattern())) {
- return;
- }
- switch (pattern->getType()) {
- case 1:
- doTilingPatternFill((GfxTilingPattern *)pattern, eoFill);
- break;
- case 2:
- doShadingPatternFill((GfxShadingPattern *)pattern, eoFill);
- break;
- default:
- error(getPos(), "Unimplemented pattern type (%d) in fill",
- pattern->getType());
- break;
- }
-}
-
-void Gfx::doTilingPatternFill(GfxTilingPattern *tPat, GBool eoFill) {
- GfxPatternColorSpace *patCS;
- GfxColorSpace *cs;
- GfxPath *savedPath;
- double xMin, yMin, xMax, yMax, x, y, x1, y1;
- double cxMin, cyMin, cxMax, cyMax;
- int xi0, yi0, xi1, yi1, xi, yi;
- double *ctm, *btm, *ptm;
- double m[6], ictm[6], m1[6], imb[6];
- double det;
- double xstep, ystep;
- int i;
-
- // get color space
- patCS = (GfxPatternColorSpace *)state->getFillColorSpace();
-
- // construct a (pattern space) -> (current space) transform matrix
- ctm = state->getCTM();
- btm = baseMatrix;
- ptm = tPat->getMatrix();
- // iCTM = invert CTM
- det = 1 / (ctm[0] * ctm[3] - ctm[1] * ctm[2]);
- ictm[0] = ctm[3] * det;
- ictm[1] = -ctm[1] * det;
- ictm[2] = -ctm[2] * det;
- ictm[3] = ctm[0] * det;
- ictm[4] = (ctm[2] * ctm[5] - ctm[3] * ctm[4]) * det;
- ictm[5] = (ctm[1] * ctm[4] - ctm[0] * ctm[5]) * det;
- // m1 = PTM * BTM = PTM * base transform matrix
- m1[0] = ptm[0] * btm[0] + ptm[1] * btm[2];
- m1[1] = ptm[0] * btm[1] + ptm[1] * btm[3];
- m1[2] = ptm[2] * btm[0] + ptm[3] * btm[2];
- m1[3] = ptm[2] * btm[1] + ptm[3] * btm[3];
- m1[4] = ptm[4] * btm[0] + ptm[5] * btm[2] + btm[4];
- m1[5] = ptm[4] * btm[1] + ptm[5] * btm[3] + btm[5];
- // m = m1 * iCTM = (PTM * BTM) * (iCTM)
- m[0] = m1[0] * ictm[0] + m1[1] * ictm[2];
- m[1] = m1[0] * ictm[1] + m1[1] * ictm[3];
- m[2] = m1[2] * ictm[0] + m1[3] * ictm[2];
- m[3] = m1[2] * ictm[1] + m1[3] * ictm[3];
- m[4] = m1[4] * ictm[0] + m1[5] * ictm[2] + ictm[4];
- m[5] = m1[4] * ictm[1] + m1[5] * ictm[3] + ictm[5];
-
- // construct a (device space) -> (pattern space) transform matrix
- det = 1 / (m1[0] * m1[3] - m1[1] * m1[2]);
- imb[0] = m1[3] * det;
- imb[1] = -m1[1] * det;
- imb[2] = -m1[2] * det;
- imb[3] = m1[0] * det;
- imb[4] = (m1[2] * m1[5] - m1[3] * m1[4]) * det;
- imb[5] = (m1[1] * m1[4] - m1[0] * m1[5]) * det;
-
- // save current graphics state
- savedPath = state->getPath()->copy();
- saveState();
-
- // set underlying color space (for uncolored tiling patterns); set
- // various other parameters (stroke color, line width) to match
- // Adobe's behavior
- if (tPat->getPaintType() == 2 && (cs = patCS->getUnder())) {
- state->setFillColorSpace(cs->copy());
- out->updateFillColorSpace(state);
- state->setStrokeColorSpace(cs->copy());
- out->updateStrokeColorSpace(state);
- state->setStrokeColor(state->getFillColor());
- } else {
- state->setFillColorSpace(new GfxDeviceGrayColorSpace());
- out->updateFillColorSpace(state);
- state->setStrokeColorSpace(new GfxDeviceGrayColorSpace());
- out->updateStrokeColorSpace(state);
- }
- state->setFillPattern(NULL);
- out->updateFillColor(state);
- state->setStrokePattern(NULL);
- out->updateStrokeColor(state);
- state->setLineWidth(0);
- out->updateLineWidth(state);
-
- // clip to current path
- state->clip();
- if (eoFill) {
- out->eoClip(state);
- } else {
- out->clip(state);
- }
- state->clearPath();
-
- // get the clip region, check for empty
- state->getClipBBox(&cxMin, &cyMin, &cxMax, &cyMax);
- if (cxMin > cxMax || cyMin > cyMax) {
- goto err;
- }
-
- // transform clip region bbox to pattern space
- xMin = xMax = cxMin * imb[0] + cyMin * imb[2] + imb[4];
- yMin = yMax = cxMin * imb[1] + cyMin * imb[3] + imb[5];
- x1 = cxMin * imb[0] + cyMax * imb[2] + imb[4];
- y1 = cxMin * imb[1] + cyMax * imb[3] + imb[5];
- if (x1 < xMin) {
- xMin = x1;
- } else if (x1 > xMax) {
- xMax = x1;
- }
- if (y1 < yMin) {
- yMin = y1;
- } else if (y1 > yMax) {
- yMax = y1;
- }
- x1 = cxMax * imb[0] + cyMin * imb[2] + imb[4];
- y1 = cxMax * imb[1] + cyMin * imb[3] + imb[5];
- if (x1 < xMin) {
- xMin = x1;
- } else if (x1 > xMax) {
- xMax = x1;
- }
- if (y1 < yMin) {
- yMin = y1;
- } else if (y1 > yMax) {
- yMax = y1;
- }
- x1 = cxMax * imb[0] + cyMax * imb[2] + imb[4];
- y1 = cxMax * imb[1] + cyMax * imb[3] + imb[5];
- if (x1 < xMin) {
- xMin = x1;
- } else if (x1 > xMax) {
- xMax = x1;
- }
- if (y1 < yMin) {
- yMin = y1;
- } else if (y1 > yMax) {
- yMax = y1;
- }
-
- // draw the pattern
- //~ this should treat negative steps differently -- start at right/top
- //~ edge instead of left/bottom (?)
- xstep = fabs(tPat->getXStep());
- ystep = fabs(tPat->getYStep());
- xi0 = (int)floor((xMin - tPat->getBBox()[0]) / xstep);
- xi1 = (int)ceil((xMax - tPat->getBBox()[0]) / xstep);
- yi0 = (int)floor((yMin - tPat->getBBox()[1]) / ystep);
- yi1 = (int)ceil((yMax - tPat->getBBox()[1]) / ystep);
- for (i = 0; i < 4; ++i) {
- m1[i] = m[i];
- }
- if (out->useTilingPatternFill()) {
- m1[4] = m[4];
- m1[5] = m[5];
- out->tilingPatternFill(state, tPat->getContentStream(),
- tPat->getPaintType(), tPat->getResDict(),
- m1, tPat->getBBox(),
- xi0, yi0, xi1, yi1, xstep, ystep);
- } else {
- for (yi = yi0; yi < yi1; ++yi) {
- for (xi = xi0; xi < xi1; ++xi) {
- x = xi * xstep;
- y = yi * ystep;
- m1[4] = x * m[0] + y * m[2] + m[4];
- m1[5] = x * m[1] + y * m[3] + m[5];
- doForm1(tPat->getContentStream(), tPat->getResDict(),
- m1, tPat->getBBox());
- }
- }
- }
-
- // restore graphics state
- err:
- restoreState();
- state->setPath(savedPath);
-}
-
-void Gfx::doShadingPatternFill(GfxShadingPattern *sPat, GBool eoFill) {
- GfxShading *shading;
- GfxPath *savedPath;
- double *ctm, *btm, *ptm;
- double m[6], ictm[6], m1[6];
- double xMin, yMin, xMax, yMax;
- double det;
-
- shading = sPat->getShading();
-
- // save current graphics state
- savedPath = state->getPath()->copy();
- saveState();
-
- // clip to bbox
- if (shading->getHasBBox()) {
- shading->getBBox(&xMin, &yMin, &xMax, &yMax);
- state->moveTo(xMin, yMin);
- state->lineTo(xMax, yMin);
- state->lineTo(xMax, yMax);
- state->lineTo(xMin, yMax);
- state->closePath();
- state->clip();
- out->clip(state);
- state->setPath(savedPath->copy());
- }
-
- // clip to current path
- state->clip();
- if (eoFill) {
- out->eoClip(state);
- } else {
- out->clip(state);
- }
-
- // set the color space
- state->setFillColorSpace(shading->getColorSpace()->copy());
- out->updateFillColorSpace(state);
-
- // background color fill
- if (shading->getHasBackground()) {
- state->setFillColor(shading->getBackground());
- out->updateFillColor(state);
- out->fill(state);
- }
- state->clearPath();
-
- // construct a (pattern space) -> (current space) transform matrix
- ctm = state->getCTM();
- btm = baseMatrix;
- ptm = sPat->getMatrix();
- // iCTM = invert CTM
- det = 1 / (ctm[0] * ctm[3] - ctm[1] * ctm[2]);
- ictm[0] = ctm[3] * det;
- ictm[1] = -ctm[1] * det;
- ictm[2] = -ctm[2] * det;
- ictm[3] = ctm[0] * det;
- ictm[4] = (ctm[2] * ctm[5] - ctm[3] * ctm[4]) * det;
- ictm[5] = (ctm[1] * ctm[4] - ctm[0] * ctm[5]) * det;
- // m1 = PTM * BTM = PTM * base transform matrix
- m1[0] = ptm[0] * btm[0] + ptm[1] * btm[2];
- m1[1] = ptm[0] * btm[1] + ptm[1] * btm[3];
- m1[2] = ptm[2] * btm[0] + ptm[3] * btm[2];
- m1[3] = ptm[2] * btm[1] + ptm[3] * btm[3];
- m1[4] = ptm[4] * btm[0] + ptm[5] * btm[2] + btm[4];
- m1[5] = ptm[4] * btm[1] + ptm[5] * btm[3] + btm[5];
- // m = m1 * iCTM = (PTM * BTM) * (iCTM)
- m[0] = m1[0] * ictm[0] + m1[1] * ictm[2];
- m[1] = m1[0] * ictm[1] + m1[1] * ictm[3];
- m[2] = m1[2] * ictm[0] + m1[3] * ictm[2];
- m[3] = m1[2] * ictm[1] + m1[3] * ictm[3];
- m[4] = m1[4] * ictm[0] + m1[5] * ictm[2] + ictm[4];
- m[5] = m1[4] * ictm[1] + m1[5] * ictm[3] + ictm[5];
-
- // set the new matrix
- state->concatCTM(m[0], m[1], m[2], m[3], m[4], m[5]);
- out->updateCTM(state, m[0], m[1], m[2], m[3], m[4], m[5]);
-
- // do shading type-specific operations
- switch (shading->getType()) {
- case 1:
- doFunctionShFill((GfxFunctionShading *)shading);
- break;
- case 2:
- doAxialShFill((GfxAxialShading *)shading);
- break;
- case 3:
- doRadialShFill((GfxRadialShading *)shading);
- break;
- case 4:
- case 5:
- doGouraudTriangleShFill((GfxGouraudTriangleShading *)shading);
- break;
- case 6:
- case 7:
- doPatchMeshShFill((GfxPatchMeshShading *)shading);
- break;
- }
-
- // restore graphics state
- restoreState();
- state->setPath(savedPath);
-}
-
-void Gfx::opShFill(Object args[], int numArgs) {
- GfxShading *shading;
- GfxPath *savedPath;
- double xMin, yMin, xMax, yMax;
-
- if (!(shading = res->lookupShading(args[0].getName()))) {
- return;
- }
-
- // save current graphics state
- savedPath = state->getPath()->copy();
- saveState();
-
- // clip to bbox
- if (shading->getHasBBox()) {
- shading->getBBox(&xMin, &yMin, &xMax, &yMax);
- state->moveTo(xMin, yMin);
- state->lineTo(xMax, yMin);
- state->lineTo(xMax, yMax);
- state->lineTo(xMin, yMax);
- state->closePath();
- state->clip();
- out->clip(state);
- state->clearPath();
- }
-
- // set the color space
- state->setFillColorSpace(shading->getColorSpace()->copy());
- out->updateFillColorSpace(state);
-
- // do shading type-specific operations
- switch (shading->getType()) {
- case 1:
- doFunctionShFill((GfxFunctionShading *)shading);
- break;
- case 2:
- doAxialShFill((GfxAxialShading *)shading);
- break;
- case 3:
- doRadialShFill((GfxRadialShading *)shading);
- break;
- case 4:
- case 5:
- doGouraudTriangleShFill((GfxGouraudTriangleShading *)shading);
- break;
- case 6:
- case 7:
- doPatchMeshShFill((GfxPatchMeshShading *)shading);
- break;
- }
-
- // restore graphics state
- restoreState();
- state->setPath(savedPath);
-
- delete shading;
-}
-
-void Gfx::doFunctionShFill(GfxFunctionShading *shading) {
- double x0, y0, x1, y1;
- GfxColor colors[4];
-
- if (out->useShadedFills()) {
- out->functionShadedFill(state, shading);
- } else {
- shading->getDomain(&x0, &y0, &x1, &y1);
- shading->getColor(x0, y0, &colors[0]);
- shading->getColor(x0, y1, &colors[1]);
- shading->getColor(x1, y0, &colors[2]);
- shading->getColor(x1, y1, &colors[3]);
- doFunctionShFill1(shading, x0, y0, x1, y1, colors, 0);
- }
-}
-
-void Gfx::doFunctionShFill1(GfxFunctionShading *shading,
- double x0, double y0,
- double x1, double y1,
- GfxColor *colors, int depth) {
- GfxColor fillColor;
- GfxColor color0M, color1M, colorM0, colorM1, colorMM;
- GfxColor colors2[4];
- double *matrix;
- double xM, yM;
- int nComps, i, j;
-
- nComps = shading->getColorSpace()->getNComps();
- matrix = shading->getMatrix();
-
- // compare the four corner colors
- for (i = 0; i < 4; ++i) {
- for (j = 0; j < nComps; ++j) {
- if (abs(colors[i].c[j] - colors[(i+1)&3].c[j]) > functionColorDelta) {
- break;
- }
- }
- if (j < nComps) {
- break;
- }
- }
-
- // center of the rectangle
- xM = 0.5 * (x0 + x1);
- yM = 0.5 * (y0 + y1);
-
- // the four corner colors are close (or we hit the recursive limit)
- // -- fill the rectangle; but require at least one subdivision
- // (depth==0) to avoid problems when the four outer corners of the
- // shaded region are the same color
- if ((i == 4 && depth > 0) || depth == functionMaxDepth) {
-
- // use the center color
- shading->getColor(xM, yM, &fillColor);
- state->setFillColor(&fillColor);
- out->updateFillColor(state);
-
- // fill the rectangle
- state->moveTo(x0 * matrix[0] + y0 * matrix[2] + matrix[4],
- x0 * matrix[1] + y0 * matrix[3] + matrix[5]);
- state->lineTo(x1 * matrix[0] + y0 * matrix[2] + matrix[4],
- x1 * matrix[1] + y0 * matrix[3] + matrix[5]);
- state->lineTo(x1 * matrix[0] + y1 * matrix[2] + matrix[4],
- x1 * matrix[1] + y1 * matrix[3] + matrix[5]);
- state->lineTo(x0 * matrix[0] + y1 * matrix[2] + matrix[4],
- x0 * matrix[1] + y1 * matrix[3] + matrix[5]);
- state->closePath();
- out->fill(state);
- state->clearPath();
-
- // the four corner colors are not close enough -- subdivide the
- // rectangle
- } else {
-
- // colors[0] colorM0 colors[2]
- // (x0,y0) (xM,y0) (x1,y0)
- // +----------+----------+
- // | | |
- // | UL | UR |
- // color0M | colorMM | color1M
- // (x0,yM) +----------+----------+ (x1,yM)
- // | (xM,yM) |
- // | LL | LR |
- // | | |
- // +----------+----------+
- // colors[1] colorM1 colors[3]
- // (x0,y1) (xM,y1) (x1,y1)
-
- shading->getColor(x0, yM, &color0M);
- shading->getColor(x1, yM, &color1M);
- shading->getColor(xM, y0, &colorM0);
- shading->getColor(xM, y1, &colorM1);
- shading->getColor(xM, yM, &colorMM);
-
- // upper-left sub-rectangle
- colors2[0] = colors[0];
- colors2[1] = color0M;
- colors2[2] = colorM0;
- colors2[3] = colorMM;
- doFunctionShFill1(shading, x0, y0, xM, yM, colors2, depth + 1);
-
- // lower-left sub-rectangle
- colors2[0] = color0M;
- colors2[1] = colors[1];
- colors2[2] = colorMM;
- colors2[3] = colorM1;
- doFunctionShFill1(shading, x0, yM, xM, y1, colors2, depth + 1);
-
- // upper-right sub-rectangle
- colors2[0] = colorM0;
- colors2[1] = colorMM;
- colors2[2] = colors[2];
- colors2[3] = color1M;
- doFunctionShFill1(shading, xM, y0, x1, yM, colors2, depth + 1);
-
- // lower-right sub-rectangle
- colors2[0] = colorMM;
- colors2[1] = colorM1;
- colors2[2] = color1M;
- colors2[3] = colors[3];
- doFunctionShFill1(shading, xM, yM, x1, y1, colors2, depth + 1);
- }
-}
-
-void Gfx::doAxialShFill(GfxAxialShading *shading) {
- double xMin, yMin, xMax, yMax;
- double x0, y0, x1, y1;
- double dx, dy, mul;
- GBool dxZero, dyZero;
- double tMin, tMax, t, tx, ty;
- double s[4], sMin, sMax, tmp;
- double ux0, uy0, ux1, uy1, vx0, vy0, vx1, vy1;
- double t0, t1, tt;
- double ta[axialMaxSplits + 1];
- int next[axialMaxSplits + 1];
- GfxColor color0, color1;
- int nComps;
- int i, j, k, kk;
-
- if (out->useShadedFills()) {
-
- out->axialShadedFill(state, shading);
-
- } else {
-
- // get the clip region bbox
- state->getUserClipBBox(&xMin, &yMin, &xMax, &yMax);
-
- // compute min and max t values, based on the four corners of the
- // clip region bbox
- shading->getCoords(&x0, &y0, &x1, &y1);
- dx = x1 - x0;
- dy = y1 - y0;
- dxZero = fabs(dx) < 0.001;
- dyZero = fabs(dy) < 0.001;
- mul = 1 / (dx * dx + dy * dy);
- tMin = tMax = ((xMin - x0) * dx + (yMin - y0) * dy) * mul;
- t = ((xMin - x0) * dx + (yMax - y0) * dy) * mul;
- if (t < tMin) {
- tMin = t;
- } else if (t > tMax) {
- tMax = t;
- }
- t = ((xMax - x0) * dx + (yMin - y0) * dy) * mul;
- if (t < tMin) {
- tMin = t;
- } else if (t > tMax) {
- tMax = t;
- }
- t = ((xMax - x0) * dx + (yMax - y0) * dy) * mul;
- if (t < tMin) {
- tMin = t;
- } else if (t > tMax) {
- tMax = t;
- }
- if (tMin < 0 && !shading->getExtend0()) {
- tMin = 0;
- }
- if (tMax > 1 && !shading->getExtend1()) {
- tMax = 1;
- }
-
- // get the function domain
- t0 = shading->getDomain0();
- t1 = shading->getDomain1();
-
- // Traverse the t axis and do the shading.
- //
- // For each point (tx, ty) on the t axis, consider a line through
- // that point perpendicular to the t axis:
- //
- // x(s) = tx + s * -dy --> s = (x - tx) / -dy
- // y(s) = ty + s * dx --> s = (y - ty) / dx
- //
- // Then look at the intersection of this line with the bounding box
- // (xMin, yMin, xMax, yMax). In the general case, there are four
- // intersection points:
- //
- // s0 = (xMin - tx) / -dy
- // s1 = (xMax - tx) / -dy
- // s2 = (yMin - ty) / dx
- // s3 = (yMax - ty) / dx
- //
- // and we want the middle two s values.
- //
- // In the case where dx = 0, take s0 and s1; in the case where dy =
- // 0, take s2 and s3.
- //
- // Each filled polygon is bounded by two of these line segments
- // perpdendicular to the t axis.
- //
- // The t axis is bisected into smaller regions until the color
- // difference across a region is small enough, and then the region
- // is painted with a single color.
-
- // set up: require at least one split to avoid problems when the two
- // ends of the t axis have the same color
- nComps = shading->getColorSpace()->getNComps();
- ta[0] = tMin;
- next[0] = axialMaxSplits / 2;
- ta[axialMaxSplits / 2] = 0.5 * (tMin + tMax);
- next[axialMaxSplits / 2] = axialMaxSplits;
- ta[axialMaxSplits] = tMax;
-
- // compute the color at t = tMin
- if (tMin < 0) {
- tt = t0;
- } else if (tMin > 1) {
- tt = t1;
- } else {
- tt = t0 + (t1 - t0) * tMin;
- }
- shading->getColor(tt, &color0);
-
- // compute the coordinates of the point on the t axis at t = tMin;
- // then compute the intersection of the perpendicular line with the
- // bounding box
- tx = x0 + tMin * dx;
- ty = y0 + tMin * dy;
- if (dxZero && dyZero) {
- sMin = sMax = 0;
- } if (dxZero) {
- sMin = (xMin - tx) / -dy;
- sMax = (xMax - tx) / -dy;
- if (sMin > sMax) { tmp = sMin; sMin = sMax; sMax = tmp; }
- } else if (dyZero) {
- sMin = (yMin - ty) / dx;
- sMax = (yMax - ty) / dx;
- if (sMin > sMax) { tmp = sMin; sMin = sMax; sMax = tmp; }
- } else {
- s[0] = (yMin - ty) / dx;
- s[1] = (yMax - ty) / dx;
- s[2] = (xMin - tx) / -dy;
- s[3] = (xMax - tx) / -dy;
- for (j = 0; j < 3; ++j) {
- kk = j;
- for (k = j + 1; k < 4; ++k) {
- if (s[k] < s[kk]) {
- kk = k;
- }
- }
- tmp = s[j]; s[j] = s[kk]; s[kk] = tmp;
- }
- sMin = s[1];
- sMax = s[2];
- }
- ux0 = tx - sMin * dy;
- uy0 = ty + sMin * dx;
- vx0 = tx - sMax * dy;
- vy0 = ty + sMax * dx;
-
- i = 0;
- while (i < axialMaxSplits) {
-
- // bisect until color difference is small enough or we hit the
- // bisection limit
- j = next[i];
- while (j > i + 1) {
- if (ta[j] < 0) {
- tt = t0;
- } else if (ta[j] > 1) {
- tt = t1;
- } else {
- tt = t0 + (t1 - t0) * ta[j];
- }
- shading->getColor(tt, &color1);
- for (k = 0; k < nComps; ++k) {
- if (abs(color1.c[k] - color0.c[k]) > axialColorDelta) {
- break;
- }
- }
- if (k == nComps) {
- break;
- }
- k = (i + j) / 2;
- ta[k] = 0.5 * (ta[i] + ta[j]);
- next[i] = k;
- next[k] = j;
- j = k;
- }
-
- // use the average of the colors of the two sides of the region
- for (k = 0; k < nComps; ++k) {
- color0.c[k] = (color0.c[k] + color1.c[k]) / 2;
- }
-
- // compute the coordinates of the point on the t axis; then
- // compute the intersection of the perpendicular line with the
- // bounding box
- tx = x0 + ta[j] * dx;
- ty = y0 + ta[j] * dy;
- if (dxZero && dyZero) {
- sMin = sMax = 0;
- } if (dxZero) {
- sMin = (xMin - tx) / -dy;
- sMax = (xMax - tx) / -dy;
- if (sMin > sMax) { tmp = sMin; sMin = sMax; sMax = tmp; }
- } else if (dyZero) {
- sMin = (yMin - ty) / dx;
- sMax = (yMax - ty) / dx;
- if (sMin > sMax) { tmp = sMin; sMin = sMax; sMax = tmp; }
- } else {
- s[0] = (yMin - ty) / dx;
- s[1] = (yMax - ty) / dx;
- s[2] = (xMin - tx) / -dy;
- s[3] = (xMax - tx) / -dy;
- for (j = 0; j < 3; ++j) {
- kk = j;
- for (k = j + 1; k < 4; ++k) {
- if (s[k] < s[kk]) {
- kk = k;
- }
- }
- tmp = s[j]; s[j] = s[kk]; s[kk] = tmp;
- }
- sMin = s[1];
- sMax = s[2];
- }
- ux1 = tx - sMin * dy;
- uy1 = ty + sMin * dx;
- vx1 = tx - sMax * dy;
- vy1 = ty + sMax * dx;
-
- // set the color
- state->setFillColor(&color0);
- out->updateFillColor(state);
-
- // fill the region
- state->moveTo(ux0, uy0);
- state->lineTo(vx0, vy0);
- state->lineTo(vx1, vy1);
- state->lineTo(ux1, uy1);
- state->closePath();
- out->fill(state);
- state->clearPath();
-
- // set up for next region
- ux0 = ux1;
- uy0 = uy1;
- vx0 = vx1;
- vy0 = vy1;
- color0 = color1;
- i = next[i];
- }
- }
-}
-
-void Gfx::doRadialShFill(GfxRadialShading *shading) {
- double sMin, sMax, xMin, yMin, xMax, yMax;
- double x0, y0, r0, x1, y1, r1, t0, t1;
- int nComps;
- GfxColor colorA, colorB;
- double xa, ya, xb, yb, ra, rb;
- double ta, tb, sa, sb;
- int ia, ib, k, n;
- double *ctm;
- double angle, t, d0, d1;
-
- if (out->useShadedFills()) {
-
- out->radialShadedFill(state, shading);
-
- } else {
-
- // get the shading info
- shading->getCoords(&x0, &y0, &r0, &x1, &y1, &r1);
- t0 = shading->getDomain0();
- t1 = shading->getDomain1();
- nComps = shading->getColorSpace()->getNComps();
-
- // compute the (possibly extended) s range
- sMin = 0;
- sMax = 1;
- if (shading->getExtend0()) {
- if (r0 < r1) {
- // extend the smaller end
- sMin = -r0 / (r1 - r0);
- } else {
- // extend the larger end
- state->getUserClipBBox(&xMin, &yMin, &xMax, &yMax);
- d0 = (x0 - xMin) * (x0 - xMin);
- d1 = (x0 - xMax) * (x0 - xMax);
- sMin = d0 > d1 ? d0 : d1;
- d0 = (y0 - yMin) * (y0 - yMin);
- d1 = (y0 - yMax) * (y0 - yMax);
- sMin += d0 > d1 ? d0 : d1;
- sMin = (sqrt(sMin) - r0) / (r1 - r0);
- if (sMin > 0) {
- sMin = 0;
- } else if (sMin < -20) {
- // sanity check
- sMin = -20;
- }
- }
- }
- if (shading->getExtend1()) {
- if (r1 < r0) {
- // extend the smaller end
- sMax = -r0 / (r1 - r0);
- } else if (r1 > r0) {
- // extend the larger end
- state->getUserClipBBox(&xMin, &yMin, &xMax, &yMax);
- d0 = (x1 - xMin) * (x1 - xMin);
- d1 = (x1 - xMax) * (x1 - xMax);
- sMax = d0 > d1 ? d0 : d1;
- d0 = (y1 - yMin) * (y1 - yMin);
- d1 = (y1 - yMax) * (y1 - yMax);
- sMax += d0 > d1 ? d0 : d1;
- sMax = (sqrt(sMax) - r0) / (r1 - r0);
- if (sMax < 1) {
- sMax = 1;
- } else if (sMax > 20) {
- // sanity check
- sMax = 20;
- }
- }
- }
-
- // compute the number of steps into which circles must be divided to
- // achieve a curve flatness of 0.1 pixel in device space for the
- // largest circle (note that "device space" is 72 dpi when generating
- // PostScript, hence the relatively small 0.1 pixel accuracy)
- ctm = state->getCTM();
- t = fabs(ctm[0]);
- if (fabs(ctm[1]) > t) {
- t = fabs(ctm[1]);
- }
- if (fabs(ctm[2]) > t) {
- t = fabs(ctm[2]);
- }
- if (fabs(ctm[3]) > t) {
- t = fabs(ctm[3]);
- }
- if (r0 > r1) {
- t *= r0;
- } else {
- t *= r1;
- }
- if (t < 1) {
- n = 3;
- } else {
- n = (int)(M_PI / acos(1 - 0.1 / t));
- if (n < 3) {
- n = 3;
- } else if (n > 200) {
- n = 200;
- }
- }
-
- // Traverse the t axis and do the shading.
- //
- // This generates and fills a series of rings. Each ring is defined
- // by two circles:
- // sa, ta, xa, ya, ra, colorA
- // sb, tb, xb, yb, rb, colorB
- //
- // The s/t axis is divided into radialMaxSplits parts; these parts
- // are combined as much as possible while respecting the
- // radialColorDelta parameter.
-
- // setup for the start circle
- ia = 0;
- sa = sMin;
- ta = t0 + sa * (t1 - t0);
- xa = x0 + sa * (x1 - x0);
- ya = y0 + sa * (y1 - y0);
- ra = r0 + sa * (r1 - r0);
- if (ta < t0) {
- shading->getColor(t0, &colorA);
- } else if (ta > t1) {
- shading->getColor(t1, &colorA);
- } else {
- shading->getColor(ta, &colorA);
- }
-
- while (ia < radialMaxSplits) {
-
- // go as far along the t axis (toward t1) as we can, such that the
- // color difference is within the tolerance (radialColorDelta) --
- // this uses bisection (between the current value, t, and t1),
- // limited to radialMaxSplits points along the t axis; require at
- // least one split to avoid problems when the innermost and
- // outermost colors are the same
- ib = radialMaxSplits;
- sb = sMin + ((double)ib / (double)radialMaxSplits) * (sMax - sMin);
- tb = t0 + sb * (t1 - t0);
- if (tb < t0) {
- shading->getColor(t0, &colorB);
- } else if (tb > t1) {
- shading->getColor(t1, &colorB);
- } else {
- shading->getColor(tb, &colorB);
- }
- while (ib - ia > 1) {
- for (k = 0; k < nComps; ++k) {
- if (abs(colorB.c[k] - colorA.c[k]) > radialColorDelta) {
- break;
- }
- }
- if (k == nComps && ib < radialMaxSplits) {
- break;
- }
- ib = (ia + ib) / 2;
- sb = sMin + ((double)ib / (double)radialMaxSplits) * (sMax - sMin);
- tb = t0 + sb * (t1 - t0);
- if (tb < t0) {
- shading->getColor(t0, &colorB);
- } else if (tb > t1) {
- shading->getColor(t1, &colorB);
- } else {
- shading->getColor(tb, &colorB);
- }
- }
-
- // compute center and radius of the circle
- xb = x0 + sb * (x1 - x0);
- yb = y0 + sb * (y1 - y0);
- rb = r0 + sb * (r1 - r0);
-
- // use the average of the colors at the two circles
- for (k = 0; k < nComps; ++k) {
- colorA.c[k] = (colorA.c[k] + colorB.c[k]) / 2;
- }
- state->setFillColor(&colorA);
- out->updateFillColor(state);
-
- // construct path for first circle
- state->moveTo(xa + ra, ya);
- for (k = 1; k < n; ++k) {
- angle = ((double)k / (double)n) * 2 * M_PI;
- state->lineTo(xa + ra * cos(angle), ya + ra * sin(angle));
- }
- state->closePath();
-
- // construct and append path for second circle
- state->moveTo(xb + rb, yb);
- for (k = 1; k < n; ++k) {
- angle = ((double)k / (double)n) * 2 * M_PI;
- state->lineTo(xb + rb * cos(angle), yb + rb * sin(angle));
- }
- state->closePath();
-
- // fill the ring
- out->eoFill(state);
- state->clearPath();
-
- // step to the next value of t
- ia = ib;
- sa = sb;
- ta = tb;
- xa = xb;
- ya = yb;
- ra = rb;
- colorA = colorB;
- }
- }
-}
-
-void Gfx::doGouraudTriangleShFill(GfxGouraudTriangleShading *shading) {
- double x0, y0, x1, y1, x2, y2;
- GfxColor color0, color1, color2;
- int i;
-
- for (i = 0; i < shading->getNTriangles(); ++i) {
- shading->getTriangle(i, &x0, &y0, &color0,
- &x1, &y1, &color1,
- &x2, &y2, &color2);
- gouraudFillTriangle(x0, y0, &color0, x1, y1, &color1, x2, y2, &color2,
- shading->getColorSpace()->getNComps(), 0);
- }
-}
-
-void Gfx::gouraudFillTriangle(double x0, double y0, GfxColor *color0,
- double x1, double y1, GfxColor *color1,
- double x2, double y2, GfxColor *color2,
- int nComps, int depth) {
- double x01, y01, x12, y12, x20, y20;
- GfxColor color01, color12, color20;
- int i;
-
- for (i = 0; i < nComps; ++i) {
- if (abs(color0->c[i] - color1->c[i]) > gouraudColorDelta ||
- abs(color1->c[i] - color2->c[i]) > gouraudColorDelta) {
- break;
- }
- }
- if (i == nComps || depth == gouraudMaxDepth) {
- state->setFillColor(color0);
- out->updateFillColor(state);
- state->moveTo(x0, y0);
- state->lineTo(x1, y1);
- state->lineTo(x2, y2);
- state->closePath();
- out->fill(state);
- state->clearPath();
- } else {
- x01 = 0.5 * (x0 + x1);
- y01 = 0.5 * (y0 + y1);
- x12 = 0.5 * (x1 + x2);
- y12 = 0.5 * (y1 + y2);
- x20 = 0.5 * (x2 + x0);
- y20 = 0.5 * (y2 + y0);
- //~ if the shading has a Function, this should interpolate on the
- //~ function parameter, not on the color components
- for (i = 0; i < nComps; ++i) {
- color01.c[i] = (color0->c[i] + color1->c[i]) / 2;
- color12.c[i] = (color1->c[i] + color2->c[i]) / 2;
- color20.c[i] = (color2->c[i] + color0->c[i]) / 2;
- }
- gouraudFillTriangle(x0, y0, color0, x01, y01, &color01,
- x20, y20, &color20, nComps, depth + 1);
- gouraudFillTriangle(x01, y01, &color01, x1, y1, color1,
- x12, y12, &color12, nComps, depth + 1);
- gouraudFillTriangle(x01, y01, &color01, x12, y12, &color12,
- x20, y20, &color20, nComps, depth + 1);
- gouraudFillTriangle(x20, y20, &color20, x12, y12, &color12,
- x2, y2, color2, nComps, depth + 1);
- }
-}
-
-void Gfx::doPatchMeshShFill(GfxPatchMeshShading *shading) {
- int start, i;
-
- if (shading->getNPatches() > 128) {
- start = 3;
- } else if (shading->getNPatches() > 64) {
- start = 2;
- } else if (shading->getNPatches() > 16) {
- start = 1;
- } else {
- start = 0;
- }
- for (i = 0; i < shading->getNPatches(); ++i) {
- fillPatch(shading->getPatch(i), shading->getColorSpace()->getNComps(),
- start);
- }
-}
-
-void Gfx::fillPatch(GfxPatch *patch, int nComps, int depth) {
- GfxPatch patch00, patch01, patch10, patch11;
- double xx[4][8], yy[4][8];
- double xxm, yym;
- int i;
-
- for (i = 0; i < nComps; ++i) {
- if (abs(patch->color[0][0].c[i] - patch->color[0][1].c[i])
- > patchColorDelta ||
- abs(patch->color[0][1].c[i] - patch->color[1][1].c[i])
- > patchColorDelta ||
- abs(patch->color[1][1].c[i] - patch->color[1][0].c[i])
- > patchColorDelta ||
- abs(patch->color[1][0].c[i] - patch->color[0][0].c[i])
- > patchColorDelta) {
- break;
- }
- }
- if (i == nComps || depth == patchMaxDepth) {
- state->setFillColor(&patch->color[0][0]);
- out->updateFillColor(state);
- state->moveTo(patch->x[0][0], patch->y[0][0]);
- state->curveTo(patch->x[0][1], patch->y[0][1],
- patch->x[0][2], patch->y[0][2],
- patch->x[0][3], patch->y[0][3]);
- state->curveTo(patch->x[1][3], patch->y[1][3],
- patch->x[2][3], patch->y[2][3],
- patch->x[3][3], patch->y[3][3]);
- state->curveTo(patch->x[3][2], patch->y[3][2],
- patch->x[3][1], patch->y[3][1],
- patch->x[3][0], patch->y[3][0]);
- state->curveTo(patch->x[2][0], patch->y[2][0],
- patch->x[1][0], patch->y[1][0],
- patch->x[0][0], patch->y[0][0]);
- state->closePath();
- out->fill(state);
- state->clearPath();
- } else {
- for (i = 0; i < 4; ++i) {
- xx[i][0] = patch->x[i][0];
- yy[i][0] = patch->y[i][0];
- xx[i][1] = 0.5 * (patch->x[i][0] + patch->x[i][1]);
- yy[i][1] = 0.5 * (patch->y[i][0] + patch->y[i][1]);
- xxm = 0.5 * (patch->x[i][1] + patch->x[i][2]);
- yym = 0.5 * (patch->y[i][1] + patch->y[i][2]);
- xx[i][6] = 0.5 * (patch->x[i][2] + patch->x[i][3]);
- yy[i][6] = 0.5 * (patch->y[i][2] + patch->y[i][3]);
- xx[i][2] = 0.5 * (xx[i][1] + xxm);
- yy[i][2] = 0.5 * (yy[i][1] + yym);
- xx[i][5] = 0.5 * (xxm + xx[i][6]);
- yy[i][5] = 0.5 * (yym + yy[i][6]);
- xx[i][3] = xx[i][4] = 0.5 * (xx[i][2] + xx[i][5]);
- yy[i][3] = yy[i][4] = 0.5 * (yy[i][2] + yy[i][5]);
- xx[i][7] = patch->x[i][3];
- yy[i][7] = patch->y[i][3];
- }
- for (i = 0; i < 4; ++i) {
- patch00.x[0][i] = xx[0][i];
- patch00.y[0][i] = yy[0][i];
- patch00.x[1][i] = 0.5 * (xx[0][i] + xx[1][i]);
- patch00.y[1][i] = 0.5 * (yy[0][i] + yy[1][i]);
- xxm = 0.5 * (xx[1][i] + xx[2][i]);
- yym = 0.5 * (yy[1][i] + yy[2][i]);
- patch10.x[2][i] = 0.5 * (xx[2][i] + xx[3][i]);
- patch10.y[2][i] = 0.5 * (yy[2][i] + yy[3][i]);
- patch00.x[2][i] = 0.5 * (patch00.x[1][i] + xxm);
- patch00.y[2][i] = 0.5 * (patch00.y[1][i] + yym);
- patch10.x[1][i] = 0.5 * (xxm + patch10.x[2][i]);
- patch10.y[1][i] = 0.5 * (yym + patch10.y[2][i]);
- patch00.x[3][i] = 0.5 * (patch00.x[2][i] + patch10.x[1][i]);
- patch00.y[3][i] = 0.5 * (patch00.y[2][i] + patch10.y[1][i]);
- patch10.x[0][i] = patch00.x[3][i];
- patch10.y[0][i] = patch00.y[3][i];
- patch10.x[3][i] = xx[3][i];
- patch10.y[3][i] = yy[3][i];
- }
- for (i = 4; i < 8; ++i) {
- patch01.x[0][i-4] = xx[0][i];
- patch01.y[0][i-4] = yy[0][i];
- patch01.x[1][i-4] = 0.5 * (xx[0][i] + xx[1][i]);
- patch01.y[1][i-4] = 0.5 * (yy[0][i] + yy[1][i]);
- xxm = 0.5 * (xx[1][i] + xx[2][i]);
- yym = 0.5 * (yy[1][i] + yy[2][i]);
- patch11.x[2][i-4] = 0.5 * (xx[2][i] + xx[3][i]);
- patch11.y[2][i-4] = 0.5 * (yy[2][i] + yy[3][i]);
- patch01.x[2][i-4] = 0.5 * (patch01.x[1][i-4] + xxm);
- patch01.y[2][i-4] = 0.5 * (patch01.y[1][i-4] + yym);
- patch11.x[1][i-4] = 0.5 * (xxm + patch11.x[2][i-4]);
- patch11.y[1][i-4] = 0.5 * (yym + patch11.y[2][i-4]);
- patch01.x[3][i-4] = 0.5 * (patch01.x[2][i-4] + patch11.x[1][i-4]);
- patch01.y[3][i-4] = 0.5 * (patch01.y[2][i-4] + patch11.y[1][i-4]);
- patch11.x[0][i-4] = patch01.x[3][i-4];
- patch11.y[0][i-4] = patch01.y[3][i-4];
- patch11.x[3][i-4] = xx[3][i];
- patch11.y[3][i-4] = yy[3][i];
- }
- //~ if the shading has a Function, this should interpolate on the
- //~ function parameter, not on the color components
- for (i = 0; i < nComps; ++i) {
- patch00.color[0][0].c[i] = patch->color[0][0].c[i];
- patch00.color[0][1].c[i] = (patch->color[0][0].c[i] +
- patch->color[0][1].c[i]) / 2;
- patch01.color[0][0].c[i] = patch00.color[0][1].c[i];
- patch01.color[0][1].c[i] = patch->color[0][1].c[i];
- patch01.color[1][1].c[i] = (patch->color[0][1].c[i] +
- patch->color[1][1].c[i]) / 2;
- patch11.color[0][1].c[i] = patch01.color[1][1].c[i];
- patch11.color[1][1].c[i] = patch->color[1][1].c[i];
- patch11.color[1][0].c[i] = (patch->color[1][1].c[i] +
- patch->color[1][0].c[i]) / 2;
- patch10.color[1][1].c[i] = patch11.color[1][0].c[i];
- patch10.color[1][0].c[i] = patch->color[1][0].c[i];
- patch10.color[0][0].c[i] = (patch->color[1][0].c[i] +
- patch->color[0][0].c[i]) / 2;
- patch00.color[1][0].c[i] = patch10.color[0][0].c[i];
- patch00.color[1][1].c[i] = (patch00.color[1][0].c[i] +
- patch01.color[1][1].c[i]) / 2;
- patch01.color[1][0].c[i] = patch00.color[1][1].c[i];
- patch11.color[0][0].c[i] = patch00.color[1][1].c[i];
- patch10.color[0][1].c[i] = patch00.color[1][1].c[i];
- }
- fillPatch(&patch00, nComps, depth + 1);
- fillPatch(&patch10, nComps, depth + 1);
- fillPatch(&patch01, nComps, depth + 1);
- fillPatch(&patch11, nComps, depth + 1);
- }
-}
-
-void Gfx::doEndPath() {
- if (state->isCurPt() && clip != clipNone) {
- state->clip();
- if (clip == clipNormal) {
- out->clip(state);
- } else {
- out->eoClip(state);
- }
- }
- clip = clipNone;
- state->clearPath();
-}
-
-//------------------------------------------------------------------------
-// path clipping operators
-//------------------------------------------------------------------------
-
-void Gfx::opClip(Object args[], int numArgs) {
- clip = clipNormal;
-}
-
-void Gfx::opEOClip(Object args[], int numArgs) {
- clip = clipEO;
-}
-
-//------------------------------------------------------------------------
-// text object operators
-//------------------------------------------------------------------------
-
-void Gfx::opBeginText(Object args[], int numArgs) {
- state->setTextMat(1, 0, 0, 1, 0, 0);
- state->textMoveTo(0, 0);
- out->updateTextMat(state);
- out->updateTextPos(state);
- fontChanged = gTrue;
-}
-
-void Gfx::opEndText(Object args[], int numArgs) {
- out->endTextObject(state);
-}
-
-//------------------------------------------------------------------------
-// text state operators
-//------------------------------------------------------------------------
-
-void Gfx::opSetCharSpacing(Object args[], int numArgs) {
- state->setCharSpace(args[0].getNum());
- out->updateCharSpace(state);
-}
-
-void Gfx::opSetFont(Object args[], int numArgs) {
- GfxFont *font;
-
- if (!(font = res->lookupFont(args[0].getName()))) {
- return;
- }
- if (printCommands) {
- printf(" font: tag=%s name='%s' %g\n",
- font->getTag()->getCString(),
- font->getName() ? font->getName()->getCString() : "???",
- args[1].getNum());
- fflush(stdout);
- }
- state->setFont(font, args[1].getNum());
- fontChanged = gTrue;
-}
-
-void Gfx::opSetTextLeading(Object args[], int numArgs) {
- state->setLeading(args[0].getNum());
-}
-
-void Gfx::opSetTextRender(Object args[], int numArgs) {
- state->setRender(args[0].getInt());
- out->updateRender(state);
-}
-
-void Gfx::opSetTextRise(Object args[], int numArgs) {
- state->setRise(args[0].getNum());
- out->updateRise(state);
-}
-
-void Gfx::opSetWordSpacing(Object args[], int numArgs) {
- state->setWordSpace(args[0].getNum());
- out->updateWordSpace(state);
-}
-
-void Gfx::opSetHorizScaling(Object args[], int numArgs) {
- state->setHorizScaling(args[0].getNum());
- out->updateHorizScaling(state);
- fontChanged = gTrue;
-}
-
-//------------------------------------------------------------------------
-// text positioning operators
-//------------------------------------------------------------------------
-
-void Gfx::opTextMove(Object args[], int numArgs) {
- double tx, ty;
-
- tx = state->getLineX() + args[0].getNum();
- ty = state->getLineY() + args[1].getNum();
- state->textMoveTo(tx, ty);
- out->updateTextPos(state);
-}
-
-void Gfx::opTextMoveSet(Object args[], int numArgs) {
- double tx, ty;
-
- tx = state->getLineX() + args[0].getNum();
- ty = args[1].getNum();
- state->setLeading(-ty);
- ty += state->getLineY();
- state->textMoveTo(tx, ty);
- out->updateTextPos(state);
-}
-
-void Gfx::opSetTextMatrix(Object args[], int numArgs) {
- state->setTextMat(args[0].getNum(), args[1].getNum(),
- args[2].getNum(), args[3].getNum(),
- args[4].getNum(), args[5].getNum());
- state->textMoveTo(0, 0);
- out->updateTextMat(state);
- out->updateTextPos(state);
- fontChanged = gTrue;
-}
-
-void Gfx::opTextNextLine(Object args[], int numArgs) {
- double tx, ty;
-
- tx = state->getLineX();
- ty = state->getLineY() - state->getLeading();
- state->textMoveTo(tx, ty);
- out->updateTextPos(state);
-}
-
-//------------------------------------------------------------------------
-// text string operators
-//------------------------------------------------------------------------
-
-void Gfx::opShowText(Object args[], int numArgs) {
- if (!state->getFont()) {
- error(getPos(), "No font in show");
- return;
- }
- if (fontChanged) {
- out->updateFont(state);
- fontChanged = gFalse;
- }
- out->beginStringOp(state);
- doShowText(args[0].getString());
- out->endStringOp(state);
-}
-
-void Gfx::opMoveShowText(Object args[], int numArgs) {
- double tx, ty;
-
- if (!state->getFont()) {
- error(getPos(), "No font in move/show");
- return;
- }
- if (fontChanged) {
- out->updateFont(state);
- fontChanged = gFalse;
- }
- tx = state->getLineX();
- ty = state->getLineY() - state->getLeading();
- state->textMoveTo(tx, ty);
- out->updateTextPos(state);
- out->beginStringOp(state);
- doShowText(args[0].getString());
- out->endStringOp(state);
-}
-
-void Gfx::opMoveSetShowText(Object args[], int numArgs) {
- double tx, ty;
-
- if (!state->getFont()) {
- error(getPos(), "No font in move/set/show");
- return;
- }
- if (fontChanged) {
- out->updateFont(state);
- fontChanged = gFalse;
- }
- state->setWordSpace(args[0].getNum());
- state->setCharSpace(args[1].getNum());
- tx = state->getLineX();
- ty = state->getLineY() - state->getLeading();
- state->textMoveTo(tx, ty);
- out->updateWordSpace(state);
- out->updateCharSpace(state);
- out->updateTextPos(state);
- out->beginStringOp(state);
- doShowText(args[2].getString());
- out->endStringOp(state);
-}
-
-void Gfx::opShowSpaceText(Object args[], int numArgs) {
- Array *a;
- Object obj;
- int wMode;
- int i;
-
- if (!state->getFont()) {
- error(getPos(), "No font in show/space");
- return;
- }
- if (fontChanged) {
- out->updateFont(state);
- fontChanged = gFalse;
- }
- out->beginStringOp(state);
- wMode = state->getFont()->getWMode();
- a = args[0].getArray();
- for (i = 0; i < a->getLength(); ++i) {
- a->get(i, &obj);
- if (obj.isNum()) {
- // this uses the absolute value of the font size to match
- // Acrobat's behavior
- if (wMode) {
- state->textShift(0, -obj.getNum() * 0.001 *
- fabs(state->getFontSize()));
- } else {
- state->textShift(-obj.getNum() * 0.001 *
- fabs(state->getFontSize()), 0);
- }
- out->updateTextShift(state, obj.getNum());
- } else if (obj.isString()) {
- doShowText(obj.getString());
- } else {
- error(getPos(), "Element of show/space array must be number or string");
- }
- obj.free();
- }
- out->endStringOp(state);
-}
-
-void Gfx::doShowText(GString *s) {
- GfxFont *font;
- int wMode;
- double riseX, riseY;
- CharCode code;
- Unicode u[8];
- double x, y, dx, dy, dx2, dy2, curX, curY, tdx, tdy, lineX, lineY;
- double originX, originY, tOriginX, tOriginY;
- double oldCTM[6], newCTM[6];
- double *mat;
- Object charProc;
- Dict *resDict;
- Parser *oldParser;
- char *p;
- int len, n, uLen, nChars, nSpaces, i;
-
- font = state->getFont();
- wMode = font->getWMode();
-
- if (out->useDrawChar()) {
- out->beginString(state, s);
- }
-
- // handle a Type 3 char
- if (font->getType() == fontType3 && out->interpretType3Chars()) {
- mat = state->getCTM();
- for (i = 0; i < 6; ++i) {
- oldCTM[i] = mat[i];
- }
- mat = state->getTextMat();
- newCTM[0] = mat[0] * oldCTM[0] + mat[1] * oldCTM[2];
- newCTM[1] = mat[0] * oldCTM[1] + mat[1] * oldCTM[3];
- newCTM[2] = mat[2] * oldCTM[0] + mat[3] * oldCTM[2];
- newCTM[3] = mat[2] * oldCTM[1] + mat[3] * oldCTM[3];
- mat = font->getFontMatrix();
- newCTM[0] = mat[0] * newCTM[0] + mat[1] * newCTM[2];
- newCTM[1] = mat[0] * newCTM[1] + mat[1] * newCTM[3];
- newCTM[2] = mat[2] * newCTM[0] + mat[3] * newCTM[2];
- newCTM[3] = mat[2] * newCTM[1] + mat[3] * newCTM[3];
- newCTM[0] *= state->getFontSize();
- newCTM[1] *= state->getFontSize();
- newCTM[2] *= state->getFontSize();
- newCTM[3] *= state->getFontSize();
- newCTM[0] *= state->getHorizScaling();
- newCTM[2] *= state->getHorizScaling();
- state->textTransformDelta(0, state->getRise(), &riseX, &riseY);
- curX = state->getCurX();
- curY = state->getCurY();
- lineX = state->getLineX();
- lineY = state->getLineY();
- oldParser = parser;
- p = s->getCString();
- len = s->getLength();
- while (len > 0) {
- n = font->getNextChar(p, len, &code,
- u, (int)(sizeof(u) / sizeof(Unicode)), &uLen,
- &dx, &dy, &originX, &originY);
- dx = dx * state->getFontSize() + state->getCharSpace();
- if (n == 1 && *p == ' ') {
- dx += state->getWordSpace();
- }
- dx *= state->getHorizScaling();
- dy *= state->getFontSize();
- state->textTransformDelta(dx, dy, &tdx, &tdy);
- state->transform(curX + riseX, curY + riseY, &x, &y);
- saveState();
- state->setCTM(newCTM[0], newCTM[1], newCTM[2], newCTM[3], x, y);
- //~ out->updateCTM(???)
- if (!out->beginType3Char(state, curX + riseX, curY + riseY, tdx, tdy,
- code, u, uLen)) {
- ((Gfx8BitFont *)font)->getCharProc(code, &charProc);
- if ((resDict = ((Gfx8BitFont *)font)->getResources())) {
- pushResources(resDict);
- }
- if (charProc.isStream()) {
- display(&charProc, gFalse);
- } else {
- error(getPos(), "Missing or bad Type3 CharProc entry");
- }
- out->endType3Char(state);
- if (resDict) {
- popResources();
- }
- charProc.free();
- }
- restoreState();
- // GfxState::restore() does *not* restore the current position,
- // so we deal with it here using (curX, curY) and (lineX, lineY)
- curX += tdx;
- curY += tdy;
- state->moveTo(curX, curY);
- state->textSetPos(lineX, lineY);
- p += n;
- len -= n;
- }
- parser = oldParser;
-
- } else if (out->useDrawChar()) {
- state->textTransformDelta(0, state->getRise(), &riseX, &riseY);
- p = s->getCString();
- len = s->getLength();
- while (len > 0) {
- n = font->getNextChar(p, len, &code,
- u, (int)(sizeof(u) / sizeof(Unicode)), &uLen,
- &dx, &dy, &originX, &originY);
- if (wMode) {
- dx *= state->getFontSize();
- dy = dy * state->getFontSize() + state->getCharSpace();
- if (n == 1 && *p == ' ') {
- dy += state->getWordSpace();
- }
- } else {
- dx = dx * state->getFontSize() + state->getCharSpace();
- if (n == 1 && *p == ' ') {
- dx += state->getWordSpace();
- }
- dx *= state->getHorizScaling();
- dy *= state->getFontSize();
- }
- state->textTransformDelta(dx, dy, &tdx, &tdy);
- originX *= state->getFontSize();
- originY *= state->getFontSize();
- state->textTransformDelta(originX, originY, &tOriginX, &tOriginY);
- out->drawChar(state, state->getCurX() + riseX, state->getCurY() + riseY,
- tdx, tdy, tOriginX, tOriginY, code, n, u, uLen);
- state->shift(tdx, tdy);
- p += n;
- len -= n;
- }
-
- } else {
- dx = dy = 0;
- p = s->getCString();
- len = s->getLength();
- nChars = nSpaces = 0;
- while (len > 0) {
- n = font->getNextChar(p, len, &code,
- u, (int)(sizeof(u) / sizeof(Unicode)), &uLen,
- &dx2, &dy2, &originX, &originY);
- dx += dx2;
- dy += dy2;
- if (n == 1 && *p == ' ') {
- ++nSpaces;
- }
- ++nChars;
- p += n;
- len -= n;
- }
- if (wMode) {
- dx *= state->getFontSize();
- dy = dy * state->getFontSize()
- + nChars * state->getCharSpace()
- + nSpaces * state->getWordSpace();
- } else {
- dx = dx * state->getFontSize()
- + nChars * state->getCharSpace()
- + nSpaces * state->getWordSpace();
- dx *= state->getHorizScaling();
- dy *= state->getFontSize();
- }
- state->textTransformDelta(dx, dy, &tdx, &tdy);
- out->drawString(state, s);
- state->shift(tdx, tdy);
- }
-
- if (out->useDrawChar()) {
- out->endString(state);
- }
-
- updateLevel += 10 * s->getLength();
-}
-
-//------------------------------------------------------------------------
-// XObject operators
-//------------------------------------------------------------------------
-
-void Gfx::opXObject(Object args[], int numArgs) {
- Object obj1, obj2, obj3, refObj;
-#if OPI_SUPPORT
- Object opiDict;
-#endif
-
- if (!res->lookupXObject(args[0].getName(), &obj1)) {
- return;
- }
- if (!obj1.isStream()) {
- error(getPos(), "XObject '%s' is wrong type", args[0].getName());
- obj1.free();
- return;
- }
-#if OPI_SUPPORT
- obj1.streamGetDict()->lookup("OPI", &opiDict);
- if (opiDict.isDict()) {
- out->opiBegin(state, opiDict.getDict());
- }
-#endif
- obj1.streamGetDict()->lookup("Subtype", &obj2);
- if (obj2.isName("Image")) {
- if (out->needNonText()) {
- res->lookupXObjectNF(args[0].getName(), &refObj);
- doImage(&refObj, obj1.getStream(), gFalse);
- refObj.free();
- }
- } else if (obj2.isName("Form")) {
- doForm(&obj1);
- } else if (obj2.isName("PS")) {
- obj1.streamGetDict()->lookup("Level1", &obj3);
- out->psXObject(obj1.getStream(),
- obj3.isStream() ? obj3.getStream() : (Stream *)NULL);
- } else if (obj2.isName()) {
- error(getPos(), "Unknown XObject subtype '%s'", obj2.getName());
- } else {
- error(getPos(), "XObject subtype is missing or wrong type");
- }
- obj2.free();
-#if OPI_SUPPORT
- if (opiDict.isDict()) {
- out->opiEnd(state, opiDict.getDict());
- }
- opiDict.free();
-#endif
- obj1.free();
-}
-
-void Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) {
- Dict *dict, *maskDict;
- int width, height;
- int bits, maskBits;
- StreamColorSpaceMode csMode;
- GBool mask;
- GBool invert;
- GfxColorSpace *colorSpace, *maskColorSpace;
- GfxImageColorMap *colorMap, *maskColorMap;
- Object maskObj, smaskObj;
- GBool haveColorKeyMask, haveExplicitMask, haveSoftMask;
- int maskColors[2*gfxColorMaxComps];
- int maskWidth, maskHeight;
- GBool maskInvert;
- Stream *maskStr;
- Object obj1, obj2;
- int i;
-
- // get info from the stream
- bits = 0;
- csMode = streamCSNone;
- str->getImageParams(&bits, &csMode);
-
- // get stream dict
- dict = str->getDict();
-
- // get size
- dict->lookup("Width", &obj1);
- if (obj1.isNull()) {
- obj1.free();
- dict->lookup("W", &obj1);
- }
- if (!obj1.isInt())
- goto err2;
- width = obj1.getInt();
- obj1.free();
- dict->lookup("Height", &obj1);
- if (obj1.isNull()) {
- obj1.free();
- dict->lookup("H", &obj1);
- }
- if (!obj1.isInt())
- goto err2;
- height = obj1.getInt();
- obj1.free();
-
- // image or mask?
- dict->lookup("ImageMask", &obj1);
- if (obj1.isNull()) {
- obj1.free();
- dict->lookup("IM", &obj1);
- }
- mask = gFalse;
- if (obj1.isBool())
- mask = obj1.getBool();
- else if (!obj1.isNull())
- goto err2;
- obj1.free();
-
- // bit depth
- if (bits == 0) {
- dict->lookup("BitsPerComponent", &obj1);
- if (obj1.isNull()) {
- obj1.free();
- dict->lookup("BPC", &obj1);
- }
- if (obj1.isInt()) {
- bits = obj1.getInt();
- } else if (mask) {
- bits = 1;
- } else {
- goto err2;
- }
- obj1.free();
- }
-
- // display a mask
- if (mask) {
-
- // check for inverted mask
- if (bits != 1)
- goto err1;
- invert = gFalse;
- dict->lookup("Decode", &obj1);
- if (obj1.isNull()) {
- obj1.free();
- dict->lookup("D", &obj1);
- }
- if (obj1.isArray()) {
- obj1.arrayGet(0, &obj2);
- if (obj2.isInt() && obj2.getInt() == 1)
- invert = gTrue;
- obj2.free();
- } else if (!obj1.isNull()) {
- goto err2;
- }
- obj1.free();
-
- // draw it
- out->drawImageMask(state, ref, str, width, height, invert, inlineImg);
-
- } else {
-
- // get color space and color map
- dict->lookup("ColorSpace", &obj1);
- if (obj1.isNull()) {
- obj1.free();
- dict->lookup("CS", &obj1);
- }
- if (obj1.isName()) {
- res->lookupColorSpace(obj1.getName(), &obj2);
- if (!obj2.isNull()) {
- obj1.free();
- obj1 = obj2;
- } else {
- obj2.free();
- }
- }
- if (!obj1.isNull()) {
- colorSpace = GfxColorSpace::parse(&obj1);
- } else if (csMode == streamCSDeviceGray) {
- colorSpace = new GfxDeviceGrayColorSpace();
- } else if (csMode == streamCSDeviceRGB) {
- colorSpace = new GfxDeviceRGBColorSpace();
- } else if (csMode == streamCSDeviceCMYK) {
- colorSpace = new GfxDeviceCMYKColorSpace();
- } else {
- colorSpace = NULL;
- }
- obj1.free();
- if (!colorSpace) {
- goto err1;
- }
- dict->lookup("Decode", &obj1);
- if (obj1.isNull()) {
- obj1.free();
- dict->lookup("D", &obj1);
- }
- colorMap = new GfxImageColorMap(bits, &obj1, colorSpace);
- obj1.free();
- if (!colorMap->isOk()) {
- delete colorMap;
- goto err1;
- }
-
- // get the mask
- haveColorKeyMask = haveExplicitMask = haveSoftMask = gFalse;
- maskStr = NULL; // make gcc happy
- maskWidth = maskHeight = 0; // make gcc happy
- maskInvert = gFalse; // make gcc happy
- maskColorMap = NULL; // make gcc happy
- dict->lookup("Mask", &maskObj);
- dict->lookup("SMask", &smaskObj);
- if (smaskObj.isStream()) {
- // soft mask
- if (inlineImg) {
- goto err1;
- }
- maskStr = smaskObj.getStream();
- maskDict = smaskObj.streamGetDict();
- maskDict->lookup("Width", &obj1);
- if (obj1.isNull()) {
- obj1.free();
- maskDict->lookup("W", &obj1);
- }
- if (!obj1.isInt()) {
- goto err2;
- }
- maskWidth = obj1.getInt();
- obj1.free();
- maskDict->lookup("Height", &obj1);
- if (obj1.isNull()) {
- obj1.free();
- maskDict->lookup("H", &obj1);
- }
- if (!obj1.isInt()) {
- goto err2;
- }
- maskHeight = obj1.getInt();
- obj1.free();
- maskDict->lookup("BitsPerComponent", &obj1);
- if (obj1.isNull()) {
- obj1.free();
- maskDict->lookup("BPC", &obj1);
- }
- if (!obj1.isInt()) {
- goto err2;
- }
- maskBits = obj1.getInt();
- obj1.free();
- maskDict->lookup("ColorSpace", &obj1);
- if (obj1.isNull()) {
- obj1.free();
- maskDict->lookup("CS", &obj1);
- }
- if (obj1.isName()) {
- res->lookupColorSpace(obj1.getName(), &obj2);
- if (!obj2.isNull()) {
- obj1.free();
- obj1 = obj2;
- } else {
- obj2.free();
- }
- }
- maskColorSpace = GfxColorSpace::parse(&obj1);
- obj1.free();
- if (!maskColorSpace || maskColorSpace->getMode() != csDeviceGray) {
- goto err1;
- }
- maskDict->lookup("Decode", &obj1);
- if (obj1.isNull()) {
- obj1.free();
- maskDict->lookup("D", &obj1);
- }
- maskColorMap = new GfxImageColorMap(maskBits, &obj1, maskColorSpace);
- obj1.free();
- if (!maskColorMap->isOk()) {
- delete maskColorMap;
- goto err1;
- }
- //~ handle the Matte entry
- haveSoftMask = gTrue;
- } else if (maskObj.isArray()) {
- // color key mask
- for (i = 0;
- i < maskObj.arrayGetLength() && i < 2*gfxColorMaxComps;
- ++i) {
- maskObj.arrayGet(i, &obj1);
- maskColors[i] = obj1.getInt();
- obj1.free();
- }
- haveColorKeyMask = gTrue;
- } else if (maskObj.isStream()) {
- // explicit mask
- if (inlineImg) {
- goto err1;
- }
- maskStr = maskObj.getStream();
- maskDict = maskObj.streamGetDict();
- maskDict->lookup("Width", &obj1);
- if (obj1.isNull()) {
- obj1.free();
- maskDict->lookup("W", &obj1);
- }
- if (!obj1.isInt()) {
- goto err2;
- }
- maskWidth = obj1.getInt();
- obj1.free();
- maskDict->lookup("Height", &obj1);
- if (obj1.isNull()) {
- obj1.free();
- maskDict->lookup("H", &obj1);
- }
- if (!obj1.isInt()) {
- goto err2;
- }
- maskHeight = obj1.getInt();
- obj1.free();
- maskDict->lookup("ImageMask", &obj1);
- if (obj1.isNull()) {
- obj1.free();
- maskDict->lookup("IM", &obj1);
- }
- if (!obj1.isBool() || !obj1.getBool()) {
- goto err2;
- }
- obj1.free();
- maskInvert = gFalse;
- maskDict->lookup("Decode", &obj1);
- if (obj1.isNull()) {
- obj1.free();
- maskDict->lookup("D", &obj1);
- }
- if (obj1.isArray()) {
- obj1.arrayGet(0, &obj2);
- if (obj2.isInt() && obj2.getInt() == 1) {
- maskInvert = gTrue;
- }
- obj2.free();
- } else if (!obj1.isNull()) {
- goto err2;
- }
- obj1.free();
- haveExplicitMask = gTrue;
- }
-
- // draw it
- if (haveSoftMask) {
- out->drawSoftMaskedImage(state, ref, str, width, height, colorMap,
- maskStr, maskWidth, maskHeight, maskColorMap);
- delete maskColorMap;
- } else if (haveExplicitMask) {
- out->drawMaskedImage(state, ref, str, width, height, colorMap,
- maskStr, maskWidth, maskHeight, maskInvert);
- } else {
- out->drawImage(state, ref, str, width, height, colorMap,
- haveColorKeyMask ? maskColors : (int *)NULL, inlineImg);
- }
- delete colorMap;
-
- maskObj.free();
- smaskObj.free();
- }
-
- if ((i = width * height) > 1000) {
- i = 1000;
- }
- updateLevel += i;
-
- return;
-
- err2:
- obj1.free();
- err1:
- error(getPos(), "Bad image parameters");
-}
-
-void Gfx::doForm(Object *str) {
- Dict *dict;
- Object matrixObj, bboxObj;
- double m[6], bbox[6];
- Object resObj;
- Dict *resDict;
- Object obj1;
- int i;
-
- // check for excessive recursion
- if (formDepth > 20) {
- return;
- }
-
- // get stream dict
- dict = str->streamGetDict();
-
- // check form type
- dict->lookup("FormType", &obj1);
- if (!(obj1.isNull() || (obj1.isInt() && obj1.getInt() == 1))) {
- error(getPos(), "Unknown form type");
- }
- obj1.free();
-
- // get bounding box
- dict->lookup("BBox", &bboxObj);
- if (!bboxObj.isArray()) {
- matrixObj.free();
- bboxObj.free();
- error(getPos(), "Bad form bounding box");
- return;
- }
- for (i = 0; i < 4; ++i) {
- bboxObj.arrayGet(i, &obj1);
- bbox[i] = obj1.getNum();
- obj1.free();
- }
- bboxObj.free();
-
- // get matrix
- dict->lookup("Matrix", &matrixObj);
- if (matrixObj.isArray()) {
- for (i = 0; i < 6; ++i) {
- matrixObj.arrayGet(i, &obj1);
- m[i] = obj1.getNum();
- obj1.free();
- }
- } else {
- m[0] = 1; m[1] = 0;
- m[2] = 0; m[3] = 1;
- m[4] = 0; m[5] = 0;
- }
- matrixObj.free();
-
- // get resources
- dict->lookup("Resources", &resObj);
- resDict = resObj.isDict() ? resObj.getDict() : (Dict *)NULL;
-
- // draw it
- ++formDepth;
- doForm1(str, resDict, m, bbox);
- --formDepth;
-
- resObj.free();
-}
-
-void Gfx::doAnnot(Object *str, double xMin, double yMin,
- double xMax, double yMax) {
- Dict *dict, *resDict;
- Object matrixObj, bboxObj, resObj;
- Object obj1;
- double m[6], bbox[6], ictm[6];
- double *ctm;
- double formX0, formY0, formX1, formY1;
- double annotX0, annotY0, annotX1, annotY1;
- double det, x, y, sx, sy;
- int i;
-
- // get stream dict
- dict = str->streamGetDict();
-
- // get the form bounding box
- dict->lookup("BBox", &bboxObj);
- if (!bboxObj.isArray()) {
- bboxObj.free();
- error(getPos(), "Bad form bounding box");
- return;
- }
- for (i = 0; i < 4; ++i) {
- bboxObj.arrayGet(i, &obj1);
- bbox[i] = obj1.getNum();
- obj1.free();
- }
- bboxObj.free();
-
- // get the form matrix
- dict->lookup("Matrix", &matrixObj);
- if (matrixObj.isArray()) {
- for (i = 0; i < 6; ++i) {
- matrixObj.arrayGet(i, &obj1);
- m[i] = obj1.getNum();
- obj1.free();
- }
- } else {
- m[0] = 1; m[1] = 0;
- m[2] = 0; m[3] = 1;
- m[4] = 0; m[5] = 0;
- }
- matrixObj.free();
-
- // transform the form bbox from form space to user space
- formX0 = bbox[0] * m[0] + bbox[1] * m[2] + m[4];
- formY0 = bbox[0] * m[1] + bbox[1] * m[3] + m[5];
- formX1 = bbox[2] * m[0] + bbox[3] * m[2] + m[4];
- formY1 = bbox[2] * m[1] + bbox[3] * m[3] + m[5];
-
- // transform the annotation bbox from default user space to user
- // space: (bbox * baseMatrix) * iCTM
- ctm = state->getCTM();
- det = 1 / (ctm[0] * ctm[3] - ctm[1] * ctm[2]);
- ictm[0] = ctm[3] * det;
- ictm[1] = -ctm[1] * det;
- ictm[2] = -ctm[2] * det;
- ictm[3] = ctm[0] * det;
- ictm[4] = (ctm[2] * ctm[5] - ctm[3] * ctm[4]) * det;
- ictm[5] = (ctm[1] * ctm[4] - ctm[0] * ctm[5]) * det;
- x = baseMatrix[0] * xMin + baseMatrix[2] * yMin + baseMatrix[4];
- y = baseMatrix[1] * xMin + baseMatrix[3] * yMin + baseMatrix[5];
- annotX0 = ictm[0] * x + ictm[2] * y + ictm[4];
- annotY0 = ictm[1] * x + ictm[3] * y + ictm[5];
- x = baseMatrix[0] * xMax + baseMatrix[2] * yMax + baseMatrix[4];
- y = baseMatrix[1] * xMax + baseMatrix[3] * yMax + baseMatrix[5];
- annotX1 = ictm[0] * x + ictm[2] * y + ictm[4];
- annotY1 = ictm[1] * x + ictm[3] * y + ictm[5];
-
- // swap min/max coords
- if (formX0 > formX1) {
- x = formX0; formX0 = formX1; formX1 = x;
- }
- if (formY0 > formY1) {
- y = formY0; formY0 = formY1; formY1 = y;
- }
- if (annotX0 > annotX1) {
- x = annotX0; annotX0 = annotX1; annotX1 = x;
- }
- if (annotY0 > annotY1) {
- y = annotY0; annotY0 = annotY1; annotY1 = y;
- }
-
- // scale the form to fit the annotation bbox
- if (formX1 == formX0) {
- // this shouldn't happen
- sx = 1;
- } else {
- sx = (annotX1 - annotX0) / (formX1 - formX0);
- }
- if (formY1 == formY0) {
- // this shouldn't happen
- sy = 1;
- } else {
- sy = (annotY1 - annotY0) / (formY1 - formY0);
- }
- m[0] *= sx;
- m[2] *= sx;
- m[4] = (m[4] - formX0) * sx + annotX0;
- m[1] *= sy;
- m[3] *= sy;
- m[5] = (m[5] - formY0) * sy + annotY0;
-
- // get resources
- dict->lookup("Resources", &resObj);
- resDict = resObj.isDict() ? resObj.getDict() : (Dict *)NULL;
-
- // draw it
- doForm1(str, resDict, m, bbox);
-
- resObj.free();
- bboxObj.free();
-}
-
-void Gfx::doForm1(Object *str, Dict *resDict, double *matrix, double *bbox) {
- Parser *oldParser;
- double oldBaseMatrix[6];
- int i;
-
- // push new resources on stack
- pushResources(resDict);
-
- // save current graphics state
- saveState();
-
- // kill any pre-existing path
- state->clearPath();
-
- // save current parser
- oldParser = parser;
-
- // set form transformation matrix
- state->concatCTM(matrix[0], matrix[1], matrix[2],
- matrix[3], matrix[4], matrix[5]);
- out->updateCTM(state, matrix[0], matrix[1], matrix[2],
- matrix[3], matrix[4], matrix[5]);
-
- // set new base matrix
- for (i = 0; i < 6; ++i) {
- oldBaseMatrix[i] = baseMatrix[i];
- baseMatrix[i] = state->getCTM()[i];
- }
-
- // set form bounding box
- state->moveTo(bbox[0], bbox[1]);
- state->lineTo(bbox[2], bbox[1]);
- state->lineTo(bbox[2], bbox[3]);
- state->lineTo(bbox[0], bbox[3]);
- state->closePath();
- state->clip();
- out->clip(state);
- state->clearPath();
-
- // draw the form
- display(str, gFalse);
-
- // restore base matrix
- for (i = 0; i < 6; ++i) {
- baseMatrix[i] = oldBaseMatrix[i];
- }
-
- // restore parser
- parser = oldParser;
-
- // restore graphics state
- restoreState();
-
- // pop resource stack
- popResources();
-
- return;
-}
-
-//------------------------------------------------------------------------
-// in-line image operators
-//------------------------------------------------------------------------
-
-void Gfx::opBeginImage(Object args[], int numArgs) {
- Stream *str;
- int c1, c2;
-
- // build dict/stream
- str = buildImageStream();
-
- // display the image
- if (str) {
- doImage(NULL, str, gTrue);
-
- // skip 'EI' tag
- c1 = str->getBaseStream()->getChar();
- c2 = str->getBaseStream()->getChar();
- while (!(c1 == 'E' && c2 == 'I') && c2 != EOF) {
- c1 = c2;
- c2 = str->getBaseStream()->getChar();
- }
- delete str;
- }
-}
-
-Stream *Gfx::buildImageStream() {
- Object dict;
- Object obj;
- char *key;
- Stream *str;
-
- // build dictionary
- dict.initDict(xref);
- parser->getObj(&obj);
- while (!obj.isCmd("ID") && !obj.isEOF()) {
- if (!obj.isName()) {
- error(getPos(), "Inline image dictionary key must be a name object");
- obj.free();
- } else {
- key = copyString(obj.getName());
- obj.free();
- parser->getObj(&obj);
- if (obj.isEOF() || obj.isError()) {
- gfree(key);
- break;
- }
- dict.dictAdd(key, &obj);
- }
- parser->getObj(&obj);
- }
- if (obj.isEOF()) {
- error(getPos(), "End of file in inline image");
- obj.free();
- dict.free();
- return NULL;
- }
- obj.free();
-
- // make stream
- str = new EmbedStream(parser->getStream(), &dict, gFalse, 0);
- str = str->addFilters(&dict);
-
- return str;
-}
-
-void Gfx::opImageData(Object args[], int numArgs) {
- error(getPos(), "Internal: got 'ID' operator");
-}
-
-void Gfx::opEndImage(Object args[], int numArgs) {
- error(getPos(), "Internal: got 'EI' operator");
-}
-
-//------------------------------------------------------------------------
-// type 3 font operators
-//------------------------------------------------------------------------
-
-void Gfx::opSetCharWidth(Object args[], int numArgs) {
- out->type3D0(state, args[0].getNum(), args[1].getNum());
-}
-
-void Gfx::opSetCacheDevice(Object args[], int numArgs) {
- out->type3D1(state, args[0].getNum(), args[1].getNum(),
- args[2].getNum(), args[3].getNum(),
- args[4].getNum(), args[5].getNum());
-}
-
-//------------------------------------------------------------------------
-// compatibility operators
-//------------------------------------------------------------------------
-
-void Gfx::opBeginIgnoreUndef(Object args[], int numArgs) {
- ++ignoreUndef;
-}
-
-void Gfx::opEndIgnoreUndef(Object args[], int numArgs) {
- if (ignoreUndef > 0)
- --ignoreUndef;
-}
-
-//------------------------------------------------------------------------
-// marked content operators
-//------------------------------------------------------------------------
-
-void Gfx::opBeginMarkedContent(Object args[], int numArgs) {
- if (printCommands) {
- printf(" marked content: %s ", args[0].getName());
- if (numArgs == 2)
- args[2].print(stdout);
- printf("\n");
- fflush(stdout);
- }
-}
-
-void Gfx::opEndMarkedContent(Object args[], int numArgs) {
-}
-
-void Gfx::opMarkPoint(Object args[], int numArgs) {
- if (printCommands) {
- printf(" mark point: %s ", args[0].getName());
- if (numArgs == 2)
- args[2].print(stdout);
- printf("\n");
- fflush(stdout);
- }
-}
-
-//------------------------------------------------------------------------
-// misc
-//------------------------------------------------------------------------
-
-void Gfx::saveState() {
- out->saveState(state);
- state = state->save();
-}
-
-void Gfx::restoreState() {
- state = state->restore();
- out->restoreState(state);
-}
-
-void Gfx::pushResources(Dict *resDict) {
- res = new GfxResources(xref, resDict, res);
-}
-
-void Gfx::popResources() {
- GfxResources *resPtr;
-
- resPtr = res->getNext();
- delete res;
- res = resPtr;
-}
+++ /dev/null
-//========================================================================
-//
-// Gfx.h
-//
-// Copyright 1996-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#ifndef GFX_H
-#define GFX_H
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma interface
-#endif
-
-#include "gtypes.h"
-
-class GString;
-class XRef;
-class Array;
-class Stream;
-class Parser;
-class Dict;
-class OutputDev;
-class GfxFontDict;
-class GfxFont;
-class GfxPattern;
-class GfxTilingPattern;
-class GfxShadingPattern;
-class GfxShading;
-class GfxFunctionShading;
-class GfxAxialShading;
-class GfxRadialShading;
-class GfxGouraudTriangleShading;
-class GfxPatchMeshShading;
-struct GfxPatch;
-class GfxState;
-struct GfxColor;
-class Gfx;
-class PDFRectangle;
-
-//------------------------------------------------------------------------
-// Gfx
-//------------------------------------------------------------------------
-
-enum GfxClipType {
- clipNone,
- clipNormal,
- clipEO
-};
-
-enum TchkType {
- tchkBool, // boolean
- tchkInt, // integer
- tchkNum, // number (integer or real)
- tchkString, // string
- tchkName, // name
- tchkArray, // array
- tchkProps, // properties (dictionary or name)
- tchkSCN, // scn/SCN args (number of name)
- tchkNone // used to avoid empty initializer lists
-};
-
-#define maxArgs 8
-
-struct Operator {
- char name[4];
- int numArgs;
- TchkType tchk[maxArgs];
- void (Gfx::*func)(Object args[], int numArgs);
-};
-
-class GfxResources {
-public:
-
- GfxResources(XRef *xref, Dict *resDict, GfxResources *nextA);
- ~GfxResources();
-
- GfxFont *lookupFont(char *name);
- GBool lookupXObject(char *name, Object *obj);
- GBool lookupXObjectNF(char *name, Object *obj);
- void lookupColorSpace(char *name, Object *obj);
- GfxPattern *lookupPattern(char *name);
- GfxShading *lookupShading(char *name);
- GBool lookupGState(char *name, Object *obj);
-
- GfxResources *getNext() { return next; }
-
-private:
-
- GfxFontDict *fonts;
- Object xObjDict;
- Object colorSpaceDict;
- Object patternDict;
- Object shadingDict;
- Object gStateDict;
- GfxResources *next;
-};
-
-class Gfx {
-public:
-
- // Constructor for regular output.
- Gfx(XRef *xrefA, OutputDev *outA, int pageNum, Dict *resDict,
- double hDPI, double vDPI, PDFRectangle *box,
- PDFRectangle *cropBox, int rotate,
- GBool (*abortCheckCbkA)(void *data) = NULL,
- void *abortCheckCbkDataA = NULL);
-
- // Constructor for a sub-page object.
- Gfx(XRef *xrefA, OutputDev *outA, Dict *resDict,
- PDFRectangle *box, PDFRectangle *cropBox,
- GBool (*abortCheckCbkA)(void *data) = NULL,
- void *abortCheckCbkDataA = NULL);
-
- ~Gfx();
-
- // Interpret a stream or array of streams.
- void display(Object *obj, GBool topLevel = gTrue);
-
- // Display an annotation, given its appearance (a Form XObject) and
- // bounding box (in default user space).
- void doAnnot(Object *str, double xMin, double yMin,
- double xMax, double yMax);
-
- // Save graphics state.
- void saveState();
-
- // Restore graphics state.
- void restoreState();
-
- // Get the current graphics state object.
- GfxState *getState() { return state; }
-
-private:
-
- XRef *xref; // the xref table for this PDF file
- OutputDev *out; // output device
- GBool subPage; // is this a sub-page object?
- GBool printCommands; // print the drawing commands (for debugging)
- GfxResources *res; // resource stack
- int updateLevel;
-
- GfxState *state; // current graphics state
- GBool fontChanged; // set if font or text matrix has changed
- GfxClipType clip; // do a clip?
- int ignoreUndef; // current BX/EX nesting level
- double baseMatrix[6]; // default matrix for most recent
- // page/form/pattern
- int formDepth;
-
- Parser *parser; // parser for page content stream(s)
-
- GBool // callback to check for an abort
- (*abortCheckCbk)(void *data);
- void *abortCheckCbkData;
-
- static Operator opTab[]; // table of operators
-
- void go(GBool topLevel);
- void execOp(Object *cmd, Object args[], int numArgs);
- Operator *findOp(char *name);
- GBool checkArg(Object *arg, TchkType type);
- int getPos();
-
- // graphics state operators
- void opSave(Object args[], int numArgs);
- void opRestore(Object args[], int numArgs);
- void opConcat(Object args[], int numArgs);
- void opSetDash(Object args[], int numArgs);
- void opSetFlat(Object args[], int numArgs);
- void opSetLineJoin(Object args[], int numArgs);
- void opSetLineCap(Object args[], int numArgs);
- void opSetMiterLimit(Object args[], int numArgs);
- void opSetLineWidth(Object args[], int numArgs);
- void opSetExtGState(Object args[], int numArgs);
- void opSetRenderingIntent(Object args[], int numArgs);
-
- // color operators
- void opSetFillGray(Object args[], int numArgs);
- void opSetStrokeGray(Object args[], int numArgs);
- void opSetFillCMYKColor(Object args[], int numArgs);
- void opSetStrokeCMYKColor(Object args[], int numArgs);
- void opSetFillRGBColor(Object args[], int numArgs);
- void opSetStrokeRGBColor(Object args[], int numArgs);
- void opSetFillColorSpace(Object args[], int numArgs);
- void opSetStrokeColorSpace(Object args[], int numArgs);
- void opSetFillColor(Object args[], int numArgs);
- void opSetStrokeColor(Object args[], int numArgs);
- void opSetFillColorN(Object args[], int numArgs);
- void opSetStrokeColorN(Object args[], int numArgs);
-
- // path segment operators
- void opMoveTo(Object args[], int numArgs);
- void opLineTo(Object args[], int numArgs);
- void opCurveTo(Object args[], int numArgs);
- void opCurveTo1(Object args[], int numArgs);
- void opCurveTo2(Object args[], int numArgs);
- void opRectangle(Object args[], int numArgs);
- void opClosePath(Object args[], int numArgs);
-
- // path painting operators
- void opEndPath(Object args[], int numArgs);
- void opStroke(Object args[], int numArgs);
- void opCloseStroke(Object args[], int numArgs);
- void opFill(Object args[], int numArgs);
- void opEOFill(Object args[], int numArgs);
- void opFillStroke(Object args[], int numArgs);
- void opCloseFillStroke(Object args[], int numArgs);
- void opEOFillStroke(Object args[], int numArgs);
- void opCloseEOFillStroke(Object args[], int numArgs);
- void doPatternFill(GBool eoFill);
- void doTilingPatternFill(GfxTilingPattern *tPat, GBool eoFill);
- void doShadingPatternFill(GfxShadingPattern *sPat, GBool eoFill);
- void opShFill(Object args[], int numArgs);
- void doFunctionShFill(GfxFunctionShading *shading);
- void doFunctionShFill1(GfxFunctionShading *shading,
- double x0, double y0,
- double x1, double y1,
- GfxColor *colors, int depth);
- void doAxialShFill(GfxAxialShading *shading);
- void doRadialShFill(GfxRadialShading *shading);
- void doGouraudTriangleShFill(GfxGouraudTriangleShading *shading);
- void gouraudFillTriangle(double x0, double y0, GfxColor *color0,
- double x1, double y1, GfxColor *color1,
- double x2, double y2, GfxColor *color2,
- int nComps, int depth);
- void doPatchMeshShFill(GfxPatchMeshShading *shading);
- void fillPatch(GfxPatch *patch, int nComps, int depth);
- void doEndPath();
-
- // path clipping operators
- void opClip(Object args[], int numArgs);
- void opEOClip(Object args[], int numArgs);
-
- // text object operators
- void opBeginText(Object args[], int numArgs);
- void opEndText(Object args[], int numArgs);
-
- // text state operators
- void opSetCharSpacing(Object args[], int numArgs);
- void opSetFont(Object args[], int numArgs);
- void opSetTextLeading(Object args[], int numArgs);
- void opSetTextRender(Object args[], int numArgs);
- void opSetTextRise(Object args[], int numArgs);
- void opSetWordSpacing(Object args[], int numArgs);
- void opSetHorizScaling(Object args[], int numArgs);
-
- // text positioning operators
- void opTextMove(Object args[], int numArgs);
- void opTextMoveSet(Object args[], int numArgs);
- void opSetTextMatrix(Object args[], int numArgs);
- void opTextNextLine(Object args[], int numArgs);
-
- // text string operators
- void opShowText(Object args[], int numArgs);
- void opMoveShowText(Object args[], int numArgs);
- void opMoveSetShowText(Object args[], int numArgs);
- void opShowSpaceText(Object args[], int numArgs);
- void doShowText(GString *s);
-
- // XObject operators
- void opXObject(Object args[], int numArgs);
- void doImage(Object *ref, Stream *str, GBool inlineImg);
- void doForm(Object *str);
- void doForm1(Object *str, Dict *resDict, double *matrix, double *bbox);
-
- // in-line image operators
- void opBeginImage(Object args[], int numArgs);
- Stream *buildImageStream();
- void opImageData(Object args[], int numArgs);
- void opEndImage(Object args[], int numArgs);
-
- // type 3 font operators
- void opSetCharWidth(Object args[], int numArgs);
- void opSetCacheDevice(Object args[], int numArgs);
-
- // compatibility operators
- void opBeginIgnoreUndef(Object args[], int numArgs);
- void opEndIgnoreUndef(Object args[], int numArgs);
-
- // marked content operators
- void opBeginMarkedContent(Object args[], int numArgs);
- void opEndMarkedContent(Object args[], int numArgs);
- void opMarkPoint(Object args[], int numArgs);
-
- void pushResources(Dict *resDict);
- void popResources();
-};
-
-#endif
+++ /dev/null
-//========================================================================
-//
-// GfxFont.cc
-//
-// Copyright 1996-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma implementation
-#endif
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include "gmem.h"
-#include "Error.h"
-#include "Object.h"
-#include "Dict.h"
-#include "GlobalParams.h"
-#include "CMap.h"
-#include "CharCodeToUnicode.h"
-#include "FontEncodingTables.h"
-#include "BuiltinFontTables.h"
-#include "FoFiType1.h"
-#include "FoFiType1C.h"
-#include "FoFiTrueType.h"
-#include "GfxFont.h"
-
-//------------------------------------------------------------------------
-
-struct StdFontMapEntry {
- char *altName;
- char *properName;
-};
-
-// Acrobat 4.0 and earlier substituted Base14-compatible fonts without
-// providing Widths and a FontDescriptor, so we munge the names into
-// the proper Base14 names. This table is from implementation note 44
-// in the PDF 1.4 spec, with some additions based on empirical
-// evidence.
-static StdFontMapEntry stdFontMap[] = {
- { "Arial", "Helvetica" },
- { "Arial,Bold", "Helvetica-Bold" },
- { "Arial,BoldItalic", "Helvetica-BoldOblique" },
- { "Arial,Italic", "Helvetica-Oblique" },
- { "Arial-Bold", "Helvetica-Bold" },
- { "Arial-BoldItalic", "Helvetica-BoldOblique" },
- { "Arial-BoldItalicMT", "Helvetica-BoldOblique" },
- { "Arial-BoldMT", "Helvetica-Bold" },
- { "Arial-Italic", "Helvetica-Oblique" },
- { "Arial-ItalicMT", "Helvetica-Oblique" },
- { "ArialMT", "Helvetica" },
- { "Courier,Bold", "Courier-Bold" },
- { "Courier,BoldItalic", "Courier-BoldOblique" },
- { "Courier,Italic", "Courier-Oblique" },
- { "CourierNew", "Courier" },
- { "CourierNew,Bold", "Courier-Bold" },
- { "CourierNew,BoldItalic", "Courier-BoldOblique" },
- { "CourierNew,Italic", "Courier-Oblique" },
- { "CourierNew-Bold", "Courier-Bold" },
- { "CourierNew-BoldItalic", "Courier-BoldOblique" },
- { "CourierNew-Italic", "Courier-Oblique" },
- { "CourierNewPS-BoldItalicMT", "Courier-BoldOblique" },
- { "CourierNewPS-BoldMT", "Courier-Bold" },
- { "CourierNewPS-ItalicMT", "Courier-Oblique" },
- { "CourierNewPSMT", "Courier" },
- { "Helvetica,Bold", "Helvetica-Bold" },
- { "Helvetica,BoldItalic", "Helvetica-BoldOblique" },
- { "Helvetica,Italic", "Helvetica-Oblique" },
- { "Helvetica-BoldItalic", "Helvetica-BoldOblique" },
- { "Helvetica-Italic", "Helvetica-Oblique" },
- { "Symbol,Bold", "Symbol" },
- { "Symbol,BoldItalic", "Symbol" },
- { "Symbol,Italic", "Symbol" },
- { "TimesNewRoman", "Times-Roman" },
- { "TimesNewRoman,Bold", "Times-Bold" },
- { "TimesNewRoman,BoldItalic", "Times-BoldItalic" },
- { "TimesNewRoman,Italic", "Times-Italic" },
- { "TimesNewRoman-Bold", "Times-Bold" },
- { "TimesNewRoman-BoldItalic", "Times-BoldItalic" },
- { "TimesNewRoman-Italic", "Times-Italic" },
- { "TimesNewRomanPS", "Times-Roman" },
- { "TimesNewRomanPS-Bold", "Times-Bold" },
- { "TimesNewRomanPS-BoldItalic", "Times-BoldItalic" },
- { "TimesNewRomanPS-BoldItalicMT", "Times-BoldItalic" },
- { "TimesNewRomanPS-BoldMT", "Times-Bold" },
- { "TimesNewRomanPS-Italic", "Times-Italic" },
- { "TimesNewRomanPS-ItalicMT", "Times-Italic" },
- { "TimesNewRomanPSMT", "Times-Roman" },
- { "TimesNewRomanPSMT,Bold", "Times-Bold" },
- { "TimesNewRomanPSMT,BoldItalic", "Times-BoldItalic" },
- { "TimesNewRomanPSMT,Italic", "Times-Italic" }
-};
-
-//------------------------------------------------------------------------
-// GfxFont
-//------------------------------------------------------------------------
-
-GfxFont *GfxFont::makeFont(XRef *xref, char *tagA, Ref idA, Dict *fontDict) {
- GString *nameA;
- GfxFont *font;
- Object obj1;
-
- // get base font name
- nameA = NULL;
- fontDict->lookup("BaseFont", &obj1);
- if (obj1.isName()) {
- nameA = new GString(obj1.getName());
- }
- obj1.free();
-
- // get font type
- font = NULL;
- fontDict->lookup("Subtype", &obj1);
- if (obj1.isName("Type1") || obj1.isName("MMType1")) {
- font = new Gfx8BitFont(xref, tagA, idA, nameA, fontType1, fontDict);
- } else if (obj1.isName("Type1C")) {
- font = new Gfx8BitFont(xref, tagA, idA, nameA, fontType1C, fontDict);
- } else if (obj1.isName("Type3")) {
- font = new Gfx8BitFont(xref, tagA, idA, nameA, fontType3, fontDict);
- } else if (obj1.isName("TrueType")) {
- font = new Gfx8BitFont(xref, tagA, idA, nameA, fontTrueType, fontDict);
- } else if (obj1.isName("Type0")) {
- font = new GfxCIDFont(xref, tagA, idA, nameA, fontDict);
- } else {
- error(-1, "Unknown font type: '%s'",
- obj1.isName() ? obj1.getName() : "???");
- font = new Gfx8BitFont(xref, tagA, idA, nameA, fontUnknownType, fontDict);
- }
- obj1.free();
-
- return font;
-}
-
-GfxFont::GfxFont(char *tagA, Ref idA, GString *nameA) {
- ok = gFalse;
- tag = new GString(tagA);
- id = idA;
- name = nameA;
- origName = nameA;
- embFontName = NULL;
- extFontFile = NULL;
-}
-
-GfxFont::~GfxFont() {
- delete tag;
- if (origName && origName != name) {
- delete origName;
- }
- if (name) {
- delete name;
- }
- if (embFontName) {
- delete embFontName;
- }
- if (extFontFile) {
- delete extFontFile;
- }
-}
-
-void GfxFont::readFontDescriptor(XRef *xref, Dict *fontDict) {
- Object obj1, obj2, obj3, obj4;
- double t;
- int i;
-
- // assume Times-Roman by default (for substitution purposes)
- flags = fontSerif;
-
- embFontID.num = -1;
- embFontID.gen = -1;
- missingWidth = 0;
-
- if (fontDict->lookup("FontDescriptor", &obj1)->isDict()) {
-
- // get flags
- if (obj1.dictLookup("Flags", &obj2)->isInt()) {
- flags = obj2.getInt();
- }
- obj2.free();
-
- // get name
- obj1.dictLookup("FontName", &obj2);
- if (obj2.isName()) {
- embFontName = new GString(obj2.getName());
- }
- obj2.free();
-
- // look for embedded font file
- if (obj1.dictLookupNF("FontFile", &obj2)->isRef()) {
- embFontID = obj2.getRef();
- if (type != fontType1) {
- error(-1, "Mismatch between font type and embedded font file");
- type = fontType1;
- }
- }
- obj2.free();
- if (embFontID.num == -1 &&
- obj1.dictLookupNF("FontFile2", &obj2)->isRef()) {
- embFontID = obj2.getRef();
- if (type != fontTrueType && type != fontCIDType2) {
- error(-1, "Mismatch between font type and embedded font file");
- type = type == fontCIDType0 ? fontCIDType2 : fontTrueType;
- }
- }
- obj2.free();
- if (embFontID.num == -1 &&
- obj1.dictLookupNF("FontFile3", &obj2)->isRef()) {
- if (obj2.fetch(xref, &obj3)->isStream()) {
- obj3.streamGetDict()->lookup("Subtype", &obj4);
- if (obj4.isName("Type1")) {
- embFontID = obj2.getRef();
- if (type != fontType1) {
- error(-1, "Mismatch between font type and embedded font file");
- type = fontType1;
- }
- } else if (obj4.isName("Type1C")) {
- embFontID = obj2.getRef();
- if (type != fontType1 && type != fontType1C) {
- error(-1, "Mismatch between font type and embedded font file");
- }
- type = fontType1C;
- } else if (obj4.isName("TrueType")) {
- embFontID = obj2.getRef();
- if (type != fontTrueType) {
- error(-1, "Mismatch between font type and embedded font file");
- type = fontTrueType;
- }
- } else if (obj4.isName("CIDFontType0C")) {
- embFontID = obj2.getRef();
- if (type != fontCIDType0) {
- error(-1, "Mismatch between font type and embedded font file");
- }
- type = fontCIDType0C;
- } else {
- error(-1, "Unknown embedded font type '%s'",
- obj4.isName() ? obj4.getName() : "???");
- }
- obj4.free();
- }
- obj3.free();
- }
- obj2.free();
-
- // look for MissingWidth
- obj1.dictLookup("MissingWidth", &obj2);
- if (obj2.isNum()) {
- missingWidth = obj2.getNum();
- }
- obj2.free();
-
- // get Ascent and Descent
- obj1.dictLookup("Ascent", &obj2);
- if (obj2.isNum()) {
- t = 0.001 * obj2.getNum();
- // some broken font descriptors set ascent and descent to 0
- if (t != 0) {
- ascent = t;
- }
- }
- obj2.free();
- obj1.dictLookup("Descent", &obj2);
- if (obj2.isNum()) {
- t = 0.001 * obj2.getNum();
- // some broken font descriptors set ascent and descent to 0
- if (t != 0) {
- descent = t;
- }
- // some broken font descriptors specify a positive descent
- if (descent > 0) {
- descent = -descent;
- }
- }
- obj2.free();
-
- // font FontBBox
- if (obj1.dictLookup("FontBBox", &obj2)->isArray()) {
- for (i = 0; i < 4 && i < obj2.arrayGetLength(); ++i) {
- if (obj2.arrayGet(i, &obj3)->isNum()) {
- fontBBox[i] = 0.001 * obj3.getNum();
- }
- obj3.free();
- }
- }
- obj2.free();
-
- }
- obj1.free();
-}
-
-CharCodeToUnicode *GfxFont::readToUnicodeCMap(Dict *fontDict, int nBits,
- CharCodeToUnicode *ctu) {
- GString *buf;
- Object obj1;
- int c;
-
- if (!fontDict->lookup("ToUnicode", &obj1)->isStream()) {
- obj1.free();
- return NULL;
- }
- buf = new GString();
- obj1.streamReset();
- while ((c = obj1.streamGetChar()) != EOF) {
- buf->append(c);
- }
- obj1.streamClose();
- obj1.free();
- if (ctu) {
- ctu->mergeCMap(buf, nBits);
- } else {
- ctu = CharCodeToUnicode::parseCMap(buf, nBits);
- }
- delete buf;
- return ctu;
-}
-
-void GfxFont::findExtFontFile() {
- static char *type1Exts[] = { ".pfa", ".pfb", ".ps", "", NULL };
- static char *ttExts[] = { ".ttf", NULL };
-
- if (name) {
- if (type == fontType1) {
- extFontFile = globalParams->findFontFile(name, type1Exts);
- } else if (type == fontTrueType) {
- extFontFile = globalParams->findFontFile(name, ttExts);
- }
- }
-}
-
-char *GfxFont::readExtFontFile(int *len) {
- FILE *f;
- char *buf;
-
- if (!(f = fopen(extFontFile->getCString(), "rb"))) {
- error(-1, "External font file '%s' vanished", extFontFile->getCString());
- return NULL;
- }
- fseek(f, 0, SEEK_END);
- *len = (int)ftell(f);
- fseek(f, 0, SEEK_SET);
- buf = (char *)gmalloc(*len);
- if ((int)fread(buf, 1, *len, f) != *len) {
- error(-1, "Error reading external font file '%s'",
- extFontFile->getCString());
- }
- fclose(f);
- return buf;
-}
-
-char *GfxFont::readEmbFontFile(XRef *xref, int *len) {
- char *buf;
- Object obj1, obj2;
- Stream *str;
- int c;
- int size, i;
-
- obj1.initRef(embFontID.num, embFontID.gen);
- obj1.fetch(xref, &obj2);
- if (!obj2.isStream()) {
- error(-1, "Embedded font file is not a stream");
- obj2.free();
- obj1.free();
- embFontID.num = -1;
- return NULL;
- }
- str = obj2.getStream();
-
- buf = NULL;
- i = size = 0;
- str->reset();
- while ((c = str->getChar()) != EOF) {
- if (i == size) {
- size += 4096;
- buf = (char *)grealloc(buf, size);
- }
- buf[i++] = c;
- }
- *len = i;
- str->close();
-
- obj2.free();
- obj1.free();
-
- return buf;
-}
-
-//------------------------------------------------------------------------
-// Gfx8BitFont
-//------------------------------------------------------------------------
-
-Gfx8BitFont::Gfx8BitFont(XRef *xref, char *tagA, Ref idA, GString *nameA,
- GfxFontType typeA, Dict *fontDict):
- GfxFont(tagA, idA, nameA)
-{
- GString *name2;
- BuiltinFont *builtinFont;
- char **baseEnc;
- GBool baseEncFromFontFile;
- char *buf;
- int len;
- FoFiType1 *ffT1;
- FoFiType1C *ffT1C;
- int code, code2;
- char *charName;
- GBool missing, hex;
- Unicode toUnicode[256];
- CharCodeToUnicode *utu, *ctu2;
- Unicode uBuf[8];
- double mul;
- int firstChar, lastChar;
- Gushort w;
- Object obj1, obj2, obj3;
- int n, i, a, b, m;
-
- type = typeA;
- ctu = NULL;
-
- // do font name substitution for various aliases of the Base 14 font
- // names
- if (name) {
- name2 = name->copy();
- i = 0;
- while (i < name2->getLength()) {
- if (name2->getChar(i) == ' ') {
- name2->del(i);
- } else {
- ++i;
- }
- }
- a = 0;
- b = sizeof(stdFontMap) / sizeof(StdFontMapEntry);
- // invariant: stdFontMap[a].altName <= name2 < stdFontMap[b].altName
- while (b - a > 1) {
- m = (a + b) / 2;
- if (name2->cmp(stdFontMap[m].altName) >= 0) {
- a = m;
- } else {
- b = m;
- }
- }
- if (!name2->cmp(stdFontMap[a].altName)) {
- name = new GString(stdFontMap[a].properName);
- }
- delete name2;
- }
-
- // is it a built-in font?
- builtinFont = NULL;
- if (name) {
- for (i = 0; i < nBuiltinFonts; ++i) {
- if (!name->cmp(builtinFonts[i].name)) {
- builtinFont = &builtinFonts[i];
- break;
- }
- }
- }
-
- // default ascent/descent values
- if (builtinFont) {
- ascent = 0.001 * builtinFont->ascent;
- descent = 0.001 * builtinFont->descent;
- fontBBox[0] = 0.001 * builtinFont->bbox[0];
- fontBBox[1] = 0.001 * builtinFont->bbox[1];
- fontBBox[2] = 0.001 * builtinFont->bbox[2];
- fontBBox[3] = 0.001 * builtinFont->bbox[3];
- } else {
- ascent = 0.95;
- descent = -0.35;
- fontBBox[0] = fontBBox[1] = fontBBox[2] = fontBBox[3] = 0;
- }
-
- // get info from font descriptor
- readFontDescriptor(xref, fontDict);
-
- // for non-embedded fonts, don't trust the ascent/descent/bbox
- // values from the font descriptor
- if (builtinFont && embFontID.num < 0) {
- ascent = 0.001 * builtinFont->ascent;
- descent = 0.001 * builtinFont->descent;
- fontBBox[0] = 0.001 * builtinFont->bbox[0];
- fontBBox[1] = 0.001 * builtinFont->bbox[1];
- fontBBox[2] = 0.001 * builtinFont->bbox[2];
- fontBBox[3] = 0.001 * builtinFont->bbox[3];
- }
-
- // look for an external font file
- findExtFontFile();
-
- // get font matrix
- fontMat[0] = fontMat[3] = 1;
- fontMat[1] = fontMat[2] = fontMat[4] = fontMat[5] = 0;
- if (fontDict->lookup("FontMatrix", &obj1)->isArray()) {
- for (i = 0; i < 6 && i < obj1.arrayGetLength(); ++i) {
- if (obj1.arrayGet(i, &obj2)->isNum()) {
- fontMat[i] = obj2.getNum();
- }
- obj2.free();
- }
- }
- obj1.free();
-
- // get Type 3 bounding box, font definition, and resources
- if (type == fontType3) {
- if (fontDict->lookup("FontBBox", &obj1)->isArray()) {
- for (i = 0; i < 4 && i < obj1.arrayGetLength(); ++i) {
- if (obj1.arrayGet(i, &obj2)->isNum()) {
- fontBBox[i] = obj2.getNum();
- }
- obj2.free();
- }
- }
- obj1.free();
- if (!fontDict->lookup("CharProcs", &charProcs)->isDict()) {
- error(-1, "Missing or invalid CharProcs dictionary in Type 3 font");
- charProcs.free();
- }
- if (!fontDict->lookup("Resources", &resources)->isDict()) {
- resources.free();
- }
- }
-
- //----- build the font encoding -----
-
- // Encodings start with a base encoding, which can come from
- // (in order of priority):
- // 1. FontDict.Encoding or FontDict.Encoding.BaseEncoding
- // - MacRoman / MacExpert / WinAnsi / Standard
- // 2. embedded or external font file
- // 3. default:
- // - builtin --> builtin encoding
- // - TrueType --> WinAnsiEncoding
- // - others --> StandardEncoding
- // and then add a list of differences (if any) from
- // FontDict.Encoding.Differences.
-
- // check FontDict for base encoding
- hasEncoding = gFalse;
- usesMacRomanEnc = gFalse;
- baseEnc = NULL;
- baseEncFromFontFile = gFalse;
- fontDict->lookup("Encoding", &obj1);
- if (obj1.isDict()) {
- obj1.dictLookup("BaseEncoding", &obj2);
- if (obj2.isName("MacRomanEncoding")) {
- hasEncoding = gTrue;
- usesMacRomanEnc = gTrue;
- baseEnc = macRomanEncoding;
- } else if (obj2.isName("MacExpertEncoding")) {
- hasEncoding = gTrue;
- baseEnc = macExpertEncoding;
- } else if (obj2.isName("WinAnsiEncoding")) {
- hasEncoding = gTrue;
- baseEnc = winAnsiEncoding;
- }
- obj2.free();
- } else if (obj1.isName("MacRomanEncoding")) {
- hasEncoding = gTrue;
- usesMacRomanEnc = gTrue;
- baseEnc = macRomanEncoding;
- } else if (obj1.isName("MacExpertEncoding")) {
- hasEncoding = gTrue;
- baseEnc = macExpertEncoding;
- } else if (obj1.isName("WinAnsiEncoding")) {
- hasEncoding = gTrue;
- baseEnc = winAnsiEncoding;
- }
-
- // check embedded or external font file for base encoding
- // (only for Type 1 fonts - trying to get an encoding out of a
- // TrueType font is a losing proposition)
- ffT1 = NULL;
- ffT1C = NULL;
- buf = NULL;
- if (type == fontType1 && (extFontFile || embFontID.num >= 0)) {
- if (extFontFile) {
- ffT1 = FoFiType1::load(extFontFile->getCString());
- } else {
- buf = readEmbFontFile(xref, &len);
- ffT1 = FoFiType1::make(buf, len);
- }
- if (ffT1) {
- if (ffT1->getName()) {
- if (embFontName) {
- delete embFontName;
- }
- embFontName = new GString(ffT1->getName());
- }
- if (!baseEnc) {
- baseEnc = ffT1->getEncoding();
- baseEncFromFontFile = gTrue;
- }
- }
- } else if (type == fontType1C && (extFontFile || embFontID.num >= 0)) {
- if (extFontFile) {
- ffT1C = FoFiType1C::load(extFontFile->getCString());
- } else {
- buf = readEmbFontFile(xref, &len);
- ffT1C = FoFiType1C::make(buf, len);
- }
- if (ffT1C) {
- if (ffT1C->getName()) {
- if (embFontName) {
- delete embFontName;
- }
- embFontName = new GString(ffT1C->getName());
- }
- if (!baseEnc) {
- baseEnc = ffT1C->getEncoding();
- baseEncFromFontFile = gTrue;
- }
- }
- }
- if (buf) {
- gfree(buf);
- }
-
- // get default base encoding
- if (!baseEnc) {
- if (builtinFont && embFontID.num < 0) {
- baseEnc = builtinFont->defaultBaseEnc;
- hasEncoding = gTrue;
- } else if (type == fontTrueType) {
- baseEnc = winAnsiEncoding;
- } else {
- baseEnc = standardEncoding;
- }
- }
-
- // copy the base encoding
- for (i = 0; i < 256; ++i) {
- enc[i] = baseEnc[i];
- if ((encFree[i] = baseEncFromFontFile) && enc[i]) {
- enc[i] = copyString(baseEnc[i]);
- }
- }
-
- // some Type 1C font files have empty encodings, which can break the
- // T1C->T1 conversion (since the 'seac' operator depends on having
- // the accents in the encoding), so we fill in any gaps from
- // StandardEncoding
- if (type == fontType1C && (extFontFile || embFontID.num >= 0) &&
- baseEncFromFontFile) {
- for (i = 0; i < 256; ++i) {
- if (!enc[i] && standardEncoding[i]) {
- enc[i] = standardEncoding[i];
- encFree[i] = gFalse;
- }
- }
- }
-
- // merge differences into encoding
- if (obj1.isDict()) {
- obj1.dictLookup("Differences", &obj2);
- if (obj2.isArray()) {
- hasEncoding = gTrue;
- code = 0;
- for (i = 0; i < obj2.arrayGetLength(); ++i) {
- obj2.arrayGet(i, &obj3);
- if (obj3.isInt()) {
- code = obj3.getInt();
- } else if (obj3.isName()) {
- if (code >= 0 && code < 256) {
- if (encFree[code]) {
- gfree(enc[code]);
- }
- enc[code] = copyString(obj3.getName());
- encFree[code] = gTrue;
- }
- ++code;
- } else {
- error(-1, "Wrong type in font encoding resource differences (%s)",
- obj3.getTypeName());
- }
- obj3.free();
- }
- }
- obj2.free();
- }
- obj1.free();
- if (ffT1) {
- delete ffT1;
- }
- if (ffT1C) {
- delete ffT1C;
- }
-
- //----- build the mapping to Unicode -----
-
- // pass 1: use the name-to-Unicode mapping table
- missing = hex = gFalse;
- for (code = 0; code < 256; ++code) {
- if ((charName = enc[code])) {
- if (!(toUnicode[code] = globalParams->mapNameToUnicode(charName)) &&
- strcmp(charName, ".notdef")) {
- // if it wasn't in the name-to-Unicode table, check for a
- // name that looks like 'Axx' or 'xx', where 'A' is any letter
- // and 'xx' is two hex digits
- if ((strlen(charName) == 3 &&
- isalpha(charName[0]) &&
- isxdigit(charName[1]) && isxdigit(charName[2]) &&
- ((charName[1] >= 'a' && charName[1] <= 'f') ||
- (charName[1] >= 'A' && charName[1] <= 'F') ||
- (charName[2] >= 'a' && charName[2] <= 'f') ||
- (charName[2] >= 'A' && charName[2] <= 'F'))) ||
- (strlen(charName) == 2 &&
- isxdigit(charName[0]) && isxdigit(charName[1]) &&
- ((charName[0] >= 'a' && charName[0] <= 'f') ||
- (charName[0] >= 'A' && charName[0] <= 'F') ||
- (charName[1] >= 'a' && charName[1] <= 'f') ||
- (charName[1] >= 'A' && charName[1] <= 'F')))) {
- hex = gTrue;
- }
- missing = gTrue;
- }
- } else {
- toUnicode[code] = 0;
- }
- }
-
- // pass 2: try to fill in the missing chars, looking for names of
- // the form 'Axx', 'xx', 'Ann', 'ABnn', or 'nn', where 'A' and 'B'
- // are any letters, 'xx' is two hex digits, and 'nn' is 2-4
- // decimal digits
- if (missing && globalParams->getMapNumericCharNames()) {
- for (code = 0; code < 256; ++code) {
- if ((charName = enc[code]) && !toUnicode[code] &&
- strcmp(charName, ".notdef")) {
- n = strlen(charName);
- code2 = -1;
- if (hex && n == 3 && isalpha(charName[0]) &&
- isxdigit(charName[1]) && isxdigit(charName[2])) {
- sscanf(charName+1, "%x", &code2);
- } else if (hex && n == 2 &&
- isxdigit(charName[0]) && isxdigit(charName[1])) {
- sscanf(charName, "%x", &code2);
- } else if (!hex && n >= 2 && n <= 4 &&
- isdigit(charName[0]) && isdigit(charName[1])) {
- code2 = atoi(charName);
- } else if (n >= 3 && n <= 5 &&
- isdigit(charName[1]) && isdigit(charName[2])) {
- code2 = atoi(charName+1);
- } else if (n >= 4 && n <= 6 &&
- isdigit(charName[2]) && isdigit(charName[3])) {
- code2 = atoi(charName+2);
- }
- if (code2 >= 0 && code2 <= 0xff) {
- toUnicode[code] = (Unicode)code2;
- }
- }
- }
- }
-
- // construct the char code -> Unicode mapping object
- ctu = CharCodeToUnicode::make8BitToUnicode(toUnicode);
-
- // merge in a ToUnicode CMap, if there is one -- this overwrites
- // existing entries in ctu, i.e., the ToUnicode CMap takes
- // precedence, but the other encoding info is allowed to fill in any
- // holes
- readToUnicodeCMap(fontDict, 8, ctu);
-
- // look for a Unicode-to-Unicode mapping
- if (name && (utu = globalParams->getUnicodeToUnicode(name))) {
- for (i = 0; i < 256; ++i) {
- toUnicode[i] = 0;
- }
- ctu2 = CharCodeToUnicode::make8BitToUnicode(toUnicode);
- for (i = 0; i < 256; ++i) {
- n = ctu->mapToUnicode((CharCode)i, uBuf, 8);
- if (n >= 1) {
- n = utu->mapToUnicode((CharCode)uBuf[0], uBuf, 8);
- if (n >= 1) {
- ctu2->setMapping((CharCode)i, uBuf, n);
- }
- }
- }
- utu->decRefCnt();
- delete ctu;
- ctu = ctu2;
- }
-
- //----- get the character widths -----
-
- // initialize all widths
- for (code = 0; code < 256; ++code) {
- widths[code] = missingWidth * 0.001;
- }
-
- // use widths from font dict, if present
- fontDict->lookup("FirstChar", &obj1);
- firstChar = obj1.isInt() ? obj1.getInt() : 0;
- obj1.free();
- if (firstChar < 0 || firstChar > 255) {
- firstChar = 0;
- }
- fontDict->lookup("LastChar", &obj1);
- lastChar = obj1.isInt() ? obj1.getInt() : 255;
- obj1.free();
- if (lastChar < 0 || lastChar > 255) {
- lastChar = 255;
- }
- mul = (type == fontType3) ? fontMat[0] : 0.001;
- fontDict->lookup("Widths", &obj1);
- if (obj1.isArray()) {
- flags |= fontFixedWidth;
- if (obj1.arrayGetLength() < lastChar - firstChar + 1) {
- lastChar = firstChar + obj1.arrayGetLength() - 1;
- }
- for (code = firstChar; code <= lastChar; ++code) {
- obj1.arrayGet(code - firstChar, &obj2);
- if (obj2.isNum()) {
- widths[code] = obj2.getNum() * mul;
- if (widths[code] != widths[firstChar]) {
- flags &= ~fontFixedWidth;
- }
- }
- obj2.free();
- }
-
- // use widths from built-in font
- } else if (builtinFont) {
- // this is a kludge for broken PDF files that encode char 32
- // as .notdef
- if (builtinFont->widths->getWidth("space", &w)) {
- widths[32] = 0.001 * w;
- }
- for (code = 0; code < 256; ++code) {
- if (enc[code] && builtinFont->widths->getWidth(enc[code], &w)) {
- widths[code] = 0.001 * w;
- }
- }
-
- // couldn't find widths -- use defaults
- } else {
- // this is technically an error -- the Widths entry is required
- // for all but the Base-14 fonts -- but certain PDF generators
- // apparently don't include widths for Arial and TimesNewRoman
- if (isFixedWidth()) {
- i = 0;
- } else if (isSerif()) {
- i = 8;
- } else {
- i = 4;
- }
- if (isBold()) {
- i += 2;
- }
- if (isItalic()) {
- i += 1;
- }
- builtinFont = builtinFontSubst[i];
- // this is a kludge for broken PDF files that encode char 32
- // as .notdef
- if (builtinFont->widths->getWidth("space", &w)) {
- widths[32] = 0.001 * w;
- }
- for (code = 0; code < 256; ++code) {
- if (enc[code] && builtinFont->widths->getWidth(enc[code], &w)) {
- widths[code] = 0.001 * w;
- }
- }
- }
- obj1.free();
-
- ok = gTrue;
-}
-
-Gfx8BitFont::~Gfx8BitFont() {
- int i;
-
- for (i = 0; i < 256; ++i) {
- if (encFree[i] && enc[i]) {
- gfree(enc[i]);
- }
- }
- ctu->decRefCnt();
- if (charProcs.isDict()) {
- charProcs.free();
- }
- if (resources.isDict()) {
- resources.free();
- }
-}
-
-int Gfx8BitFont::getNextChar(char *s, int len, CharCode *code,
- Unicode *u, int uSize, int *uLen,
- double *dx, double *dy, double *ox, double *oy) {
- CharCode c;
-
- *code = c = (CharCode)(*s & 0xff);
- *uLen = ctu->mapToUnicode(c, u, uSize);
- *dx = widths[c];
- *dy = *ox = *oy = 0;
- return 1;
-}
-
-CharCodeToUnicode *Gfx8BitFont::getToUnicode() {
- ctu->incRefCnt();
- return ctu;
-}
-
-Gushort *Gfx8BitFont::getCodeToGIDMap(FoFiTrueType *ff) {
- Gushort *map;
- int cmapPlatform, cmapEncoding;
- int unicodeCmap, macRomanCmap, msSymbolCmap, cmap;
- GBool useMacRoman, useUnicode;
- char *charName;
- Unicode u;
- int code, i, n;
-
- map = (Gushort *)gmallocn(256, sizeof(Gushort));
- for (i = 0; i < 256; ++i) {
- map[i] = 0;
- }
-
- // To match up with the Adobe-defined behaviour, we choose a cmap
- // like this:
- // 1. If the PDF font has an encoding:
- // 1a. If the PDF font specified MacRomanEncoding and the
- // TrueType font has a Macintosh Roman cmap, use it, and
- // reverse map the char names through MacRomanEncoding to
- // get char codes.
- // 1b. If the TrueType font has a Microsoft Unicode cmap or a
- // non-Microsoft Unicode cmap, use it, and use the Unicode
- // indexes, not the char codes.
- // 1c. If the PDF font is symbolic and the TrueType font has a
- // Microsoft Symbol cmap, use it, and use char codes
- // directly (possibly with an offset of 0xf000).
- // 1d. If the TrueType font has a Macintosh Roman cmap, use it,
- // as in case 1a.
- // 2. If the PDF font does not have an encoding or the PDF font is
- // symbolic:
- // 2a. If the TrueType font has a Macintosh Roman cmap, use it,
- // and use char codes directly (possibly with an offset of
- // 0xf000).
- // 2b. If the TrueType font has a Microsoft Symbol cmap, use it,
- // and use char codes directly (possible with an offset of
- // 0xf000).
- // 3. If none of these rules apply, use the first cmap and hope for
- // the best (this shouldn't happen).
- unicodeCmap = macRomanCmap = msSymbolCmap = -1;
- for (i = 0; i < ff->getNumCmaps(); ++i) {
- cmapPlatform = ff->getCmapPlatform(i);
- cmapEncoding = ff->getCmapEncoding(i);
- if ((cmapPlatform == 3 && cmapEncoding == 1) ||
- cmapPlatform == 0) {
- unicodeCmap = i;
- } else if (cmapPlatform == 1 && cmapEncoding == 0) {
- macRomanCmap = i;
- } else if (cmapPlatform == 3 && cmapEncoding == 0) {
- msSymbolCmap = i;
- }
- }
- cmap = 0;
- useMacRoman = gFalse;
- useUnicode = gFalse;
- if (hasEncoding) {
- if (usesMacRomanEnc && macRomanCmap >= 0) {
- cmap = macRomanCmap;
- useMacRoman = gTrue;
- } else if (unicodeCmap >= 0) {
- cmap = unicodeCmap;
- useUnicode = gTrue;
- } else if ((flags & fontSymbolic) && msSymbolCmap >= 0) {
- cmap = msSymbolCmap;
- } else if ((flags & fontSymbolic) && macRomanCmap >= 0) {
- cmap = macRomanCmap;
- } else if (macRomanCmap >= 0) {
- cmap = macRomanCmap;
- useMacRoman = gTrue;
- }
- } else {
- if (macRomanCmap >= 0) {
- cmap = macRomanCmap;
- } else if (msSymbolCmap >= 0) {
- cmap = msSymbolCmap;
- }
- }
-
- // reverse map the char names through MacRomanEncoding, then map the
- // char codes through the cmap
- if (useMacRoman) {
- for (i = 0; i < 256; ++i) {
- if ((charName = enc[i])) {
- if ((code = globalParams->getMacRomanCharCode(charName))) {
- map[i] = ff->mapCodeToGID(cmap, code);
- }
- }
- }
-
- // map Unicode through the cmap
- } else if (useUnicode) {
- for (i = 0; i < 256; ++i) {
- if (((charName = enc[i]) &&
- (u = globalParams->mapNameToUnicode(charName))) ||
- (n = ctu->mapToUnicode((CharCode)i, &u, 1))) {
- map[i] = ff->mapCodeToGID(cmap, u);
- }
- }
-
- // map the char codes through the cmap, possibly with an offset of
- // 0xf000
- } else {
- for (i = 0; i < 256; ++i) {
- if (!(map[i] = ff->mapCodeToGID(cmap, i))) {
- map[i] = ff->mapCodeToGID(cmap, 0xf000 + i);
- }
- }
- }
-
- // try the TrueType 'post' table to handle any unmapped characters
- for (i = 0; i < 256; ++i) {
- if (!map[i] && (charName = enc[i])) {
- map[i] = (Gushort)(int)ff->mapNameToGID(charName);
- }
- }
-
- return map;
-}
-
-Dict *Gfx8BitFont::getCharProcs() {
- return charProcs.isDict() ? charProcs.getDict() : (Dict *)NULL;
-}
-
-Object *Gfx8BitFont::getCharProc(int code, Object *proc) {
- if (enc[code] && charProcs.isDict()) {
- charProcs.dictLookup(enc[code], proc);
- } else {
- proc->initNull();
- }
- return proc;
-}
-
-Dict *Gfx8BitFont::getResources() {
- return resources.isDict() ? resources.getDict() : (Dict *)NULL;
-}
-
-//------------------------------------------------------------------------
-// GfxCIDFont
-//------------------------------------------------------------------------
-
-static int CDECL cmpWidthExcep(const void *w1, const void *w2) {
- return ((GfxFontCIDWidthExcep *)w1)->first -
- ((GfxFontCIDWidthExcep *)w2)->first;
-}
-
-static int CDECL cmpWidthExcepV(const void *w1, const void *w2) {
- return ((GfxFontCIDWidthExcepV *)w1)->first -
- ((GfxFontCIDWidthExcepV *)w2)->first;
-}
-
-GfxCIDFont::GfxCIDFont(XRef *xref, char *tagA, Ref idA, GString *nameA,
- Dict *fontDict):
- GfxFont(tagA, idA, nameA)
-{
- Dict *desFontDict;
- GString *collection, *cMapName;
- Object desFontDictObj;
- Object obj1, obj2, obj3, obj4, obj5, obj6;
- CharCodeToUnicode *utu;
- CharCode c;
- Unicode uBuf[8];
- int c1, c2;
- int excepsSize, i, j, k, n;
-
- ascent = 0.95;
- descent = -0.35;
- fontBBox[0] = fontBBox[1] = fontBBox[2] = fontBBox[3] = 0;
- cMap = NULL;
- ctu = NULL;
- widths.defWidth = 1.0;
- widths.defHeight = -1.0;
- widths.defVY = 0.880;
- widths.exceps = NULL;
- widths.nExceps = 0;
- widths.excepsV = NULL;
- widths.nExcepsV = 0;
- cidToGID = NULL;
- cidToGIDLen = 0;
-
- // get the descendant font
- if (!fontDict->lookup("DescendantFonts", &obj1)->isArray()) {
- error(-1, "Missing DescendantFonts entry in Type 0 font");
- obj1.free();
- goto err1;
- }
- if (!obj1.arrayGet(0, &desFontDictObj)->isDict()) {
- error(-1, "Bad descendant font in Type 0 font");
- goto err3;
- }
- obj1.free();
- desFontDict = desFontDictObj.getDict();
-
- // font type
- if (!desFontDict->lookup("Subtype", &obj1)) {
- error(-1, "Missing Subtype entry in Type 0 descendant font");
- goto err3;
- }
- if (obj1.isName("CIDFontType0")) {
- type = fontCIDType0;
- } else if (obj1.isName("CIDFontType2")) {
- type = fontCIDType2;
- } else {
- error(-1, "Unknown Type 0 descendant font type '%s'",
- obj1.isName() ? obj1.getName() : "???");
- goto err3;
- }
- obj1.free();
-
- // get info from font descriptor
- readFontDescriptor(xref, desFontDict);
-
- // look for an external font file
- findExtFontFile();
-
- //----- encoding info -----
-
- // char collection
- if (!desFontDict->lookup("CIDSystemInfo", &obj1)->isDict()) {
- error(-1, "Missing CIDSystemInfo dictionary in Type 0 descendant font");
- goto err3;
- }
- obj1.dictLookup("Registry", &obj2);
- obj1.dictLookup("Ordering", &obj3);
- if (!obj2.isString() || !obj3.isString()) {
- error(-1, "Invalid CIDSystemInfo dictionary in Type 0 descendant font");
- goto err4;
- }
- collection = obj2.getString()->copy()->append('-')->append(obj3.getString());
- obj3.free();
- obj2.free();
- obj1.free();
-
- // look for a ToUnicode CMap
- if (!(ctu = readToUnicodeCMap(fontDict, 16, NULL))) {
-
- // the "Adobe-Identity" and "Adobe-UCS" collections don't have
- // cidToUnicode files
- if (collection->cmp("Adobe-Identity") &&
- collection->cmp("Adobe-UCS")) {
-
- // look for a user-supplied .cidToUnicode file
- if (!(ctu = globalParams->getCIDToUnicode(collection))) {
- error(-1, "Unknown character collection '%s'",
- collection->getCString());
- // fall-through, assuming the Identity mapping -- this appears
- // to match Adobe's behavior
- }
- }
- }
-
- // look for a Unicode-to-Unicode mapping
- if (name && (utu = globalParams->getUnicodeToUnicode(name))) {
- if (ctu) {
- for (c = 0; c < ctu->getLength(); ++c) {
- n = ctu->mapToUnicode(c, uBuf, 8);
- if (n >= 1) {
- n = utu->mapToUnicode((CharCode)uBuf[0], uBuf, 8);
- if (n >= 1) {
- ctu->setMapping(c, uBuf, n);
- }
- }
- }
- utu->decRefCnt();
- } else {
- ctu = utu;
- }
- }
-
- // encoding (i.e., CMap)
- //~ need to handle a CMap stream here
- //~ also need to deal with the UseCMap entry in the stream dict
- if (!fontDict->lookup("Encoding", &obj1)->isName()) {
- error(-1, "Missing or invalid Encoding entry in Type 0 font");
- delete collection;
- goto err3;
- }
- cMapName = new GString(obj1.getName());
- obj1.free();
- if (!(cMap = globalParams->getCMap(collection, cMapName))) {
- error(-1, "Unknown CMap '%s' for character collection '%s'",
- cMapName->getCString(), collection->getCString());
- delete collection;
- delete cMapName;
- goto err2;
- }
- delete collection;
- delete cMapName;
-
- // CIDToGIDMap (for embedded TrueType fonts)
- if (type == fontCIDType2) {
- desFontDict->lookup("CIDToGIDMap", &obj1);
- if (obj1.isStream()) {
- cidToGIDLen = 0;
- i = 64;
- cidToGID = (Gushort *)gmallocn(i, sizeof(Gushort));
- obj1.streamReset();
- while ((c1 = obj1.streamGetChar()) != EOF &&
- (c2 = obj1.streamGetChar()) != EOF) {
- if (cidToGIDLen == i) {
- i *= 2;
- cidToGID = (Gushort *)greallocn(cidToGID, i, sizeof(Gushort));
- }
- cidToGID[cidToGIDLen++] = (Gushort)((c1 << 8) + c2);
- }
- } else if (!obj1.isName("Identity") && !obj1.isNull()) {
- error(-1, "Invalid CIDToGIDMap entry in CID font");
- }
- obj1.free();
- }
-
- //----- character metrics -----
-
- // default char width
- if (desFontDict->lookup("DW", &obj1)->isInt()) {
- widths.defWidth = obj1.getInt() * 0.001;
- }
- obj1.free();
-
- // char width exceptions
- if (desFontDict->lookup("W", &obj1)->isArray()) {
- excepsSize = 0;
- i = 0;
- while (i + 1 < obj1.arrayGetLength()) {
- obj1.arrayGet(i, &obj2);
- obj1.arrayGet(i + 1, &obj3);
- if (obj2.isInt() && obj3.isInt() && i + 2 < obj1.arrayGetLength()) {
- if (obj1.arrayGet(i + 2, &obj4)->isNum()) {
- if (widths.nExceps == excepsSize) {
- excepsSize += 16;
- widths.exceps = (GfxFontCIDWidthExcep *)
- greallocn(widths.exceps,
- excepsSize, sizeof(GfxFontCIDWidthExcep));
- }
- widths.exceps[widths.nExceps].first = obj2.getInt();
- widths.exceps[widths.nExceps].last = obj3.getInt();
- widths.exceps[widths.nExceps].width = obj4.getNum() * 0.001;
- ++widths.nExceps;
- } else {
- error(-1, "Bad widths array in Type 0 font");
- }
- obj4.free();
- i += 3;
- } else if (obj2.isInt() && obj3.isArray()) {
- if (widths.nExceps + obj3.arrayGetLength() > excepsSize) {
- excepsSize = (widths.nExceps + obj3.arrayGetLength() + 15) & ~15;
- widths.exceps = (GfxFontCIDWidthExcep *)
- greallocn(widths.exceps,
- excepsSize, sizeof(GfxFontCIDWidthExcep));
- }
- j = obj2.getInt();
- for (k = 0; k < obj3.arrayGetLength(); ++k) {
- if (obj3.arrayGet(k, &obj4)->isNum()) {
- widths.exceps[widths.nExceps].first = j;
- widths.exceps[widths.nExceps].last = j;
- widths.exceps[widths.nExceps].width = obj4.getNum() * 0.001;
- ++j;
- ++widths.nExceps;
- } else {
- error(-1, "Bad widths array in Type 0 font");
- }
- obj4.free();
- }
- i += 2;
- } else {
- error(-1, "Bad widths array in Type 0 font");
- ++i;
- }
- obj3.free();
- obj2.free();
- }
- qsort(widths.exceps, widths.nExceps, sizeof(GfxFontCIDWidthExcep),
- &cmpWidthExcep);
- }
- obj1.free();
-
- // default metrics for vertical font
- if (desFontDict->lookup("DW2", &obj1)->isArray() &&
- obj1.arrayGetLength() == 2) {
- if (obj1.arrayGet(0, &obj2)->isNum()) {
- widths.defVY = obj2.getNum() * 0.001;
- }
- obj2.free();
- if (obj1.arrayGet(1, &obj2)->isNum()) {
- widths.defHeight = obj2.getNum() * 0.001;
- }
- obj2.free();
- }
- obj1.free();
-
- // char metric exceptions for vertical font
- if (desFontDict->lookup("W2", &obj1)->isArray()) {
- excepsSize = 0;
- i = 0;
- while (i + 1 < obj1.arrayGetLength()) {
- obj1.arrayGet(i, &obj2);
- obj1.arrayGet(i+ 1, &obj3);
- if (obj2.isInt() && obj3.isInt() && i + 4 < obj1.arrayGetLength()) {
- if (obj1.arrayGet(i + 2, &obj4)->isNum() &&
- obj1.arrayGet(i + 3, &obj5)->isNum() &&
- obj1.arrayGet(i + 4, &obj6)->isNum()) {
- if (widths.nExcepsV == excepsSize) {
- excepsSize += 16;
- widths.excepsV = (GfxFontCIDWidthExcepV *)
- greallocn(widths.excepsV,
- excepsSize, sizeof(GfxFontCIDWidthExcepV));
- }
- widths.excepsV[widths.nExcepsV].first = obj2.getInt();
- widths.excepsV[widths.nExcepsV].last = obj3.getInt();
- widths.excepsV[widths.nExcepsV].height = obj4.getNum() * 0.001;
- widths.excepsV[widths.nExcepsV].vx = obj5.getNum() * 0.001;
- widths.excepsV[widths.nExcepsV].vy = obj6.getNum() * 0.001;
- ++widths.nExcepsV;
- } else {
- error(-1, "Bad widths (W2) array in Type 0 font");
- }
- obj6.free();
- obj5.free();
- obj4.free();
- i += 5;
- } else if (obj2.isInt() && obj3.isArray()) {
- if (widths.nExcepsV + obj3.arrayGetLength() / 3 > excepsSize) {
- excepsSize =
- (widths.nExcepsV + obj3.arrayGetLength() / 3 + 15) & ~15;
- widths.excepsV = (GfxFontCIDWidthExcepV *)
- greallocn(widths.excepsV,
- excepsSize, sizeof(GfxFontCIDWidthExcepV));
- }
- j = obj2.getInt();
- for (k = 0; k < obj3.arrayGetLength(); k += 3) {
- if (obj3.arrayGet(k, &obj4)->isNum() &&
- obj3.arrayGet(k+1, &obj5)->isNum() &&
- obj3.arrayGet(k+2, &obj6)->isNum()) {
- widths.excepsV[widths.nExceps].first = j;
- widths.excepsV[widths.nExceps].last = j;
- widths.excepsV[widths.nExceps].height = obj4.getNum() * 0.001;
- widths.excepsV[widths.nExceps].vx = obj5.getNum() * 0.001;
- widths.excepsV[widths.nExceps].vy = obj6.getNum() * 0.001;
- ++j;
- ++widths.nExcepsV;
- } else {
- error(-1, "Bad widths (W2) array in Type 0 font");
- }
- obj6.free();
- obj5.free();
- obj4.free();
- }
- i += 2;
- } else {
- error(-1, "Bad widths (W2) array in Type 0 font");
- ++i;
- }
- obj3.free();
- obj2.free();
- }
- qsort(widths.excepsV, widths.nExcepsV, sizeof(GfxFontCIDWidthExcepV),
- &cmpWidthExcepV);
- }
- obj1.free();
-
- desFontDictObj.free();
- ok = gTrue;
- return;
-
- err4:
- obj3.free();
- obj2.free();
- err3:
- obj1.free();
- err2:
- desFontDictObj.free();
- err1:;
-}
-
-GfxCIDFont::~GfxCIDFont() {
- if (cMap) {
- cMap->decRefCnt();
- }
- if (ctu) {
- ctu->decRefCnt();
- }
- gfree(widths.exceps);
- gfree(widths.excepsV);
- if (cidToGID) {
- gfree(cidToGID);
- }
-}
-
-int GfxCIDFont::getNextChar(char *s, int len, CharCode *code,
- Unicode *u, int uSize, int *uLen,
- double *dx, double *dy, double *ox, double *oy) {
- CID cid;
- double w, h, vx, vy;
- int n, a, b, m;
-
- if (!cMap) {
- *code = 0;
- *uLen = 0;
- *dx = *dy = 0;
- return 1;
- }
-
- *code = (CharCode)(cid = cMap->getCID(s, len, &n));
- if (ctu) {
- *uLen = ctu->mapToUnicode(cid, u, uSize);
- } else {
- *uLen = 0;
- }
-
- // horizontal
- if (cMap->getWMode() == 0) {
- w = widths.defWidth;
- h = vx = vy = 0;
- if (widths.nExceps > 0 && cid >= widths.exceps[0].first) {
- a = 0;
- b = widths.nExceps;
- // invariant: widths.exceps[a].first <= cid < widths.exceps[b].first
- while (b - a > 1) {
- m = (a + b) / 2;
- if (widths.exceps[m].first <= cid) {
- a = m;
- } else {
- b = m;
- }
- }
- if (cid <= widths.exceps[a].last) {
- w = widths.exceps[a].width;
- }
- }
-
- // vertical
- } else {
- w = 0;
- h = widths.defHeight;
- vx = widths.defWidth / 2;
- vy = widths.defVY;
- if (widths.nExcepsV > 0 && cid >= widths.excepsV[0].first) {
- a = 0;
- b = widths.nExcepsV;
- // invariant: widths.excepsV[a].first <= cid < widths.excepsV[b].first
- while (b - a > 1) {
- m = (a + b) / 2;
- if (widths.excepsV[m].last <= cid) {
- a = m;
- } else {
- b = m;
- }
- }
- if (cid <= widths.excepsV[a].last) {
- h = widths.excepsV[a].height;
- vx = widths.excepsV[a].vx;
- vy = widths.excepsV[a].vy;
- }
- }
- }
-
- *dx = w;
- *dy = h;
- *ox = vx;
- *oy = vy;
-
- return n;
-}
-
-int GfxCIDFont::getWMode() {
- return cMap ? cMap->getWMode() : 0;
-}
-
-CharCodeToUnicode *GfxCIDFont::getToUnicode() {
- if (ctu) {
- ctu->incRefCnt();
- }
- return ctu;
-}
-
-GString *GfxCIDFont::getCollection() {
- return cMap ? cMap->getCollection() : (GString *)NULL;
-}
-
-//------------------------------------------------------------------------
-// GfxFontDict
-//------------------------------------------------------------------------
-
-GfxFontDict::GfxFontDict(XRef *xref, Ref *fontDictRef, Dict *fontDict) {
- int i;
- Object obj1, obj2;
- Ref r;
-
- numFonts = fontDict->getLength();
- fonts = (GfxFont **)gmallocn(numFonts, sizeof(GfxFont *));
- for (i = 0; i < numFonts; ++i) {
- fontDict->getValNF(i, &obj1);
- obj1.fetch(xref, &obj2);
- if (obj2.isDict()) {
- if (obj1.isRef()) {
- r = obj1.getRef();
- } else {
- // no indirect reference for this font, so invent a unique one
- // (legal generation numbers are five digits, so any 6-digit
- // number would be safe)
- r.num = i;
- if (fontDictRef) {
- r.gen = 100000 + fontDictRef->num;
- } else {
- r.gen = 999999;
- }
- }
- fonts[i] = GfxFont::makeFont(xref, fontDict->getKey(i),
- r, obj2.getDict());
- if (fonts[i] && !fonts[i]->isOk()) {
- delete fonts[i];
- fonts[i] = NULL;
- }
- } else {
- error(-1, "font resource is not a dictionary");
- fonts[i] = NULL;
- }
- obj1.free();
- obj2.free();
- }
-}
-
-GfxFontDict::~GfxFontDict() {
- int i;
-
- for (i = 0; i < numFonts; ++i) {
- if (fonts[i]) {
- delete fonts[i];
- }
- }
- gfree(fonts);
-}
-
-GfxFont *GfxFontDict::lookup(char *tag) {
- int i;
-
- for (i = 0; i < numFonts; ++i) {
- if (fonts[i] && fonts[i]->matches(tag)) {
- return fonts[i];
- }
- }
- return NULL;
-}
+++ /dev/null
-//========================================================================
-//
-// GfxFont.h
-//
-// Copyright 1996-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#ifndef GFXFONT_H
-#define GFXFONT_H
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma interface
-#endif
-
-#include "gtypes.h"
-#include "GString.h"
-#include "Object.h"
-#include "CharTypes.h"
-
-class Dict;
-class CMap;
-class CharCodeToUnicode;
-class FoFiTrueType;
-struct GfxFontCIDWidths;
-
-//------------------------------------------------------------------------
-// GfxFontType
-//------------------------------------------------------------------------
-
-enum GfxFontType {
- //----- Gfx8BitFont
- fontUnknownType,
- fontType1,
- fontType1C,
- fontType3,
- fontTrueType,
- //----- GfxCIDFont
- fontCIDType0,
- fontCIDType0C,
- fontCIDType2
-};
-
-//------------------------------------------------------------------------
-// GfxFontCIDWidths
-//------------------------------------------------------------------------
-
-struct GfxFontCIDWidthExcep {
- CID first; // this record applies to
- CID last; // CIDs <first>..<last>
- double width; // char width
-};
-
-struct GfxFontCIDWidthExcepV {
- CID first; // this record applies to
- CID last; // CIDs <first>..<last>
- double height; // char height
- double vx, vy; // origin position
-};
-
-struct GfxFontCIDWidths {
- double defWidth; // default char width
- double defHeight; // default char height
- double defVY; // default origin position
- GfxFontCIDWidthExcep *exceps; // exceptions
- int nExceps; // number of valid entries in exceps
- GfxFontCIDWidthExcepV * // exceptions for vertical font
- excepsV;
- int nExcepsV; // number of valid entries in excepsV
-};
-
-//------------------------------------------------------------------------
-// GfxFont
-//------------------------------------------------------------------------
-
-#define fontFixedWidth (1 << 0)
-#define fontSerif (1 << 1)
-#define fontSymbolic (1 << 2)
-#define fontItalic (1 << 6)
-#define fontBold (1 << 18)
-
-class GfxFont {
-public:
-
- // Build a GfxFont object.
- static GfxFont *makeFont(XRef *xref, char *tagA, Ref idA, Dict *fontDict);
-
- GfxFont(char *tagA, Ref idA, GString *nameA);
-
- virtual ~GfxFont();
-
- GBool isOk() { return ok; }
-
- // Get font tag.
- GString *getTag() { return tag; }
-
- // Get font dictionary ID.
- Ref *getID() { return &id; }
-
- // Does this font match the tag?
- GBool matches(char *tagA) { return !tag->cmp(tagA); }
-
- // Get base font name.
- GString *getName() { return name; }
-
- // Get the original font name (ignornig any munging that might have
- // been done to map to a canonical Base-14 font name).
- GString *getOrigName() { return origName; }
-
- // Get font type.
- GfxFontType getType() { return type; }
- virtual GBool isCIDFont() { return gFalse; }
-
- // Get embedded font ID, i.e., a ref for the font file stream.
- // Returns false if there is no embedded font.
- GBool getEmbeddedFontID(Ref *embID)
- { *embID = embFontID; return embFontID.num >= 0; }
-
- // Get the PostScript font name for the embedded font. Returns
- // NULL if there is no embedded font.
- GString *getEmbeddedFontName() { return embFontName; }
-
- // Get the name of the external font file. Returns NULL if there
- // is no external font file.
- GString *getExtFontFile() { return extFontFile; }
-
- // Get font descriptor flags.
- GBool isFixedWidth() { return flags & fontFixedWidth; }
- GBool isSerif() { return flags & fontSerif; }
- GBool isSymbolic() { return flags & fontSymbolic; }
- GBool isItalic() { return flags & fontItalic; }
- GBool isBold() { return flags & fontBold; }
-
- // Return the font matrix.
- double *getFontMatrix() { return fontMat; }
-
- // Return the font bounding box.
- double *getFontBBox() { return fontBBox; }
-
- // Return the ascent and descent values.
- double getAscent() { return ascent; }
- double getDescent() { return descent; }
-
- // Return the writing mode (0=horizontal, 1=vertical).
- virtual int getWMode() { return 0; }
-
- // Read an external or embedded font file into a buffer.
- char *readExtFontFile(int *len);
- char *readEmbFontFile(XRef *xref, int *len);
-
- // Get the next char from a string <s> of <len> bytes, returning the
- // char <code>, its Unicode mapping <u>, its displacement vector
- // (<dx>, <dy>), and its origin offset vector (<ox>, <oy>). <uSize>
- // is the number of entries available in <u>, and <uLen> is set to
- // the number actually used. Returns the number of bytes used by
- // the char code.
- virtual int getNextChar(char *s, int len, CharCode *code,
- Unicode *u, int uSize, int *uLen,
- double *dx, double *dy, double *ox, double *oy) = 0;
-
-protected:
-
- void readFontDescriptor(XRef *xref, Dict *fontDict);
- CharCodeToUnicode *readToUnicodeCMap(Dict *fontDict, int nBits,
- CharCodeToUnicode *ctu);
- void findExtFontFile();
-
- GString *tag; // PDF font tag
- Ref id; // reference (used as unique ID)
- GString *name; // font name
- GString *origName; // original font name
- GfxFontType type; // type of font
- int flags; // font descriptor flags
- GString *embFontName; // name of embedded font
- Ref embFontID; // ref to embedded font file stream
- GString *extFontFile; // external font file name
- double fontMat[6]; // font matrix (Type 3 only)
- double fontBBox[4]; // font bounding box (Type 3 only)
- double missingWidth; // "default" width
- double ascent; // max height above baseline
- double descent; // max depth below baseline
- GBool ok;
-};
-
-//------------------------------------------------------------------------
-// Gfx8BitFont
-//------------------------------------------------------------------------
-
-class Gfx8BitFont: public GfxFont {
-public:
-
- Gfx8BitFont(XRef *xref, char *tagA, Ref idA, GString *nameA,
- GfxFontType typeA, Dict *fontDict);
-
- virtual ~Gfx8BitFont();
-
- virtual int getNextChar(char *s, int len, CharCode *code,
- Unicode *u, int uSize, int *uLen,
- double *dx, double *dy, double *ox, double *oy);
-
- // Return the encoding.
- char **getEncoding() { return enc; }
-
- // Return the Unicode map.
- CharCodeToUnicode *getToUnicode();
-
- // Return the character name associated with <code>.
- char *getCharName(int code) { return code>=256?0:enc[code]; }
-
- // Returns true if the PDF font specified an encoding.
- GBool getHasEncoding() { return hasEncoding; }
-
- // Returns true if the PDF font specified MacRomanEncoding.
- GBool getUsesMacRomanEnc() { return usesMacRomanEnc; }
-
- // Get width of a character.
- double getWidth(Guchar c) { return widths[c]; }
-
- // Return a char code-to-GID mapping for the provided font file.
- // (This is only useful for TrueType fonts.)
- Gushort *getCodeToGIDMap(FoFiTrueType *ff);
-
- // Return the Type 3 CharProc dictionary, or NULL if none.
- Dict *getCharProcs();
-
- // Return the Type 3 CharProc for the character associated with <code>.
- Object *getCharProc(int code, Object *proc);
-
- // Return the Type 3 Resources dictionary, or NULL if none.
- Dict *getResources();
-
-private:
-
- char *enc[256]; // char code --> char name
- char encFree[256]; // boolean for each char name: if set,
- // the string is malloc'ed
- CharCodeToUnicode *ctu; // char code --> Unicode
- GBool hasEncoding;
- GBool usesMacRomanEnc;
- double widths[256]; // character widths
- Object charProcs; // Type 3 CharProcs dictionary
- Object resources; // Type 3 Resources dictionary
-};
-
-//------------------------------------------------------------------------
-// GfxCIDFont
-//------------------------------------------------------------------------
-
-class GfxCIDFont: public GfxFont {
-public:
-
- GfxCIDFont(XRef *xref, char *tagA, Ref idA, GString *nameA,
- Dict *fontDict);
-
- virtual ~GfxCIDFont();
-
- virtual GBool isCIDFont() { return gTrue; }
-
- virtual int getNextChar(char *s, int len, CharCode *code,
- Unicode *u, int uSize, int *uLen,
- double *dx, double *dy, double *ox, double *oy);
-
- // Return the writing mode (0=horizontal, 1=vertical).
- virtual int getWMode();
-
- // Return the Unicode map.
- CharCodeToUnicode *getToUnicode();
-
- // Get the collection name (<registry>-<ordering>).
- GString *getCollection();
-
- // Return the CID-to-GID mapping table. These should only be called
- // if type is fontCIDType2.
- Gushort *getCIDToGID() { return cidToGID; }
- int getCIDToGIDLen() { return cidToGIDLen; }
-
-private:
-
- CMap *cMap; // char code --> CID
- CharCodeToUnicode *ctu; // CID --> Unicode
- GfxFontCIDWidths widths; // character widths
- Gushort *cidToGID; // CID --> GID mapping (for embedded
- // TrueType fonts)
- int cidToGIDLen;
-};
-
-//------------------------------------------------------------------------
-// GfxFontDict
-//------------------------------------------------------------------------
-
-class GfxFontDict {
-public:
-
- // Build the font dictionary, given the PDF font dictionary.
- GfxFontDict(XRef *xref, Ref *fontDictRef, Dict *fontDict);
-
- // Destructor.
- ~GfxFontDict();
-
- // Get the specified font.
- GfxFont *lookup(char *tag);
-
- // Iterative access.
- int getNumFonts() { return numFonts; }
- GfxFont *getFont(int i) { return fonts[i]; }
-
-private:
-
- GfxFont **fonts; // list of fonts
- int numFonts; // number of fonts
-};
-
-#endif
+++ /dev/null
-//========================================================================
-//
-// GfxState.cc
-//
-// Copyright 1996-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma implementation
-#endif
-
-#include <stddef.h>
-#include <math.h>
-#include <string.h>
-#include "gmem.h"
-#include "Error.h"
-#include "Object.h"
-#include "Array.h"
-#include "Page.h"
-#include "GfxState.h"
-#include "cmyk.h"
-
-//------------------------------------------------------------------------
-
-static inline GfxColorComp clip01(GfxColorComp x) {
- return (x < 0) ? 0 : (x > gfxColorComp1) ? gfxColorComp1 : x;
-}
-
-static inline double clip01(double x) {
- return (x < 0) ? 0 : (x > 1) ? 1 : x;
-}
-
-//------------------------------------------------------------------------
-
-static struct {
- char *name;
- GfxBlendMode mode;
-} gfxBlendModeNames[] = {
- { "Normal", gfxBlendNormal },
- { "Compatible", gfxBlendNormal },
- { "Multiply", gfxBlendMultiply },
- { "Screen", gfxBlendScreen },
- { "Overlay", gfxBlendOverlay },
- { "Darken", gfxBlendDarken },
- { "Lighten", gfxBlendLighten },
- { "ColorDodge", gfxBlendColorDodge },
- { "ColorBurn", gfxBlendColorBurn },
- { "HardLight", gfxBlendHardLight },
- { "SoftLight", gfxBlendSoftLight },
- { "Difference", gfxBlendDifference },
- { "Exclusion", gfxBlendExclusion },
- { "Hue", gfxBlendHue },
- { "Saturation", gfxBlendSaturation },
- { "Color", gfxBlendColor },
- { "Luminosity", gfxBlendLuminosity }
-};
-
-#define nGfxBlendModeNames \
- ((int)((sizeof(gfxBlendModeNames) / sizeof(char *))))
-
-//------------------------------------------------------------------------
-
-// NB: This must match the GfxColorSpaceMode enum defined in
-// GfxState.h
-static char *gfxColorSpaceModeNames[] = {
- "DeviceGray",
- "CalGray",
- "DeviceRGB",
- "CalRGB",
- "DeviceCMYK",
- "Lab",
- "ICCBased",
- "Indexed",
- "Separation",
- "DeviceN",
- "Pattern"
-};
-
-#define nGfxColorSpaceModes ((sizeof(gfxColorSpaceModeNames) / sizeof(char *)))
-
-//------------------------------------------------------------------------
-// GfxColorSpace
-//------------------------------------------------------------------------
-
-GfxColorSpace::GfxColorSpace() {
-}
-
-GfxColorSpace::~GfxColorSpace() {
-}
-
-GfxColorSpace *GfxColorSpace::parse(Object *csObj) {
- GfxColorSpace *cs;
- Object obj1;
-
- cs = NULL;
- if (csObj->isName()) {
- if (csObj->isName("DeviceGray") || csObj->isName("G")) {
- cs = new GfxDeviceGrayColorSpace();
- } else if (csObj->isName("DeviceRGB") || csObj->isName("RGB")) {
- cs = new GfxDeviceRGBColorSpace();
- } else if (csObj->isName("DeviceCMYK") || csObj->isName("CMYK")) {
- cs = new GfxDeviceCMYKColorSpace();
- } else if (csObj->isName("Pattern")) {
- cs = new GfxPatternColorSpace(NULL);
- } else {
- error(-1, "Bad color space '%s'", csObj->getName());
- }
- } else if (csObj->isArray()) {
- csObj->arrayGet(0, &obj1);
- if (obj1.isName("DeviceGray") || obj1.isName("G")) {
- cs = new GfxDeviceGrayColorSpace();
- } else if (obj1.isName("DeviceRGB") || obj1.isName("RGB")) {
- cs = new GfxDeviceRGBColorSpace();
- } else if (obj1.isName("DeviceCMYK") || obj1.isName("CMYK")) {
- cs = new GfxDeviceCMYKColorSpace();
- } else if (obj1.isName("CalGray")) {
- cs = GfxCalGrayColorSpace::parse(csObj->getArray());
- } else if (obj1.isName("CalRGB")) {
- cs = GfxCalRGBColorSpace::parse(csObj->getArray());
- } else if (obj1.isName("Lab")) {
- cs = GfxLabColorSpace::parse(csObj->getArray());
- } else if (obj1.isName("ICCBased")) {
- cs = GfxICCBasedColorSpace::parse(csObj->getArray());
- } else if (obj1.isName("Indexed") || obj1.isName("I")) {
- cs = GfxIndexedColorSpace::parse(csObj->getArray());
- } else if (obj1.isName("Separation")) {
- cs = GfxSeparationColorSpace::parse(csObj->getArray());
- } else if (obj1.isName("DeviceN")) {
- cs = GfxDeviceNColorSpace::parse(csObj->getArray());
- } else if (obj1.isName("Pattern")) {
- cs = GfxPatternColorSpace::parse(csObj->getArray());
- } else {
- error(-1, "Bad color space");
- }
- obj1.free();
- } else {
- error(-1, "Bad color space - expected name or array");
- }
- return cs;
-}
-
-void GfxColorSpace::getDefaultRanges(double *decodeLow, double *decodeRange,
- int maxImgPixel) {
- int i;
-
- for (i = 0; i < getNComps(); ++i) {
- decodeLow[i] = 0;
- decodeRange[i] = 1;
- }
-}
-
-int GfxColorSpace::getNumColorSpaceModes() {
- return nGfxColorSpaceModes;
-}
-
-char *GfxColorSpace::getColorSpaceModeName(int idx) {
- return gfxColorSpaceModeNames[idx];
-}
-
-//------------------------------------------------------------------------
-// GfxDeviceGrayColorSpace
-//------------------------------------------------------------------------
-
-GfxDeviceGrayColorSpace::GfxDeviceGrayColorSpace() {
-}
-
-GfxDeviceGrayColorSpace::~GfxDeviceGrayColorSpace() {
-}
-
-GfxColorSpace *GfxDeviceGrayColorSpace::copy() {
- return new GfxDeviceGrayColorSpace();
-}
-
-void GfxDeviceGrayColorSpace::getGray(GfxColor *color, GfxGray *gray) {
- *gray = clip01(color->c[0]);
-}
-
-void GfxDeviceGrayColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) {
- rgb->r = rgb->g = rgb->b = clip01(color->c[0]);
-}
-
-void GfxDeviceGrayColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
- cmyk->c = cmyk->m = cmyk->y = 0;
- cmyk->k = clip01(gfxColorComp1 - color->c[0]);
-}
-
-//------------------------------------------------------------------------
-// GfxCalGrayColorSpace
-//------------------------------------------------------------------------
-
-GfxCalGrayColorSpace::GfxCalGrayColorSpace() {
- whiteX = whiteY = whiteZ = 1;
- blackX = blackY = blackZ = 0;
- gamma = 1;
-}
-
-GfxCalGrayColorSpace::~GfxCalGrayColorSpace() {
-}
-
-GfxColorSpace *GfxCalGrayColorSpace::copy() {
- GfxCalGrayColorSpace *cs;
-
- cs = new GfxCalGrayColorSpace();
- cs->whiteX = whiteX;
- cs->whiteY = whiteY;
- cs->whiteZ = whiteZ;
- cs->blackX = blackX;
- cs->blackY = blackY;
- cs->blackZ = blackZ;
- cs->gamma = gamma;
- return cs;
-}
-
-GfxColorSpace *GfxCalGrayColorSpace::parse(Array *arr) {
- GfxCalGrayColorSpace *cs;
- Object obj1, obj2, obj3;
-
- arr->get(1, &obj1);
- if (!obj1.isDict()) {
- error(-1, "Bad CalGray color space");
- obj1.free();
- return NULL;
- }
- cs = new GfxCalGrayColorSpace();
- if (obj1.dictLookup("WhitePoint", &obj2)->isArray() &&
- obj2.arrayGetLength() == 3) {
- obj2.arrayGet(0, &obj3);
- cs->whiteX = obj3.getNum();
- obj3.free();
- obj2.arrayGet(1, &obj3);
- cs->whiteY = obj3.getNum();
- obj3.free();
- obj2.arrayGet(2, &obj3);
- cs->whiteZ = obj3.getNum();
- obj3.free();
- }
- obj2.free();
- if (obj1.dictLookup("BlackPoint", &obj2)->isArray() &&
- obj2.arrayGetLength() == 3) {
- obj2.arrayGet(0, &obj3);
- cs->blackX = obj3.getNum();
- obj3.free();
- obj2.arrayGet(1, &obj3);
- cs->blackY = obj3.getNum();
- obj3.free();
- obj2.arrayGet(2, &obj3);
- cs->blackZ = obj3.getNum();
- obj3.free();
- }
- obj2.free();
- if (obj1.dictLookup("Gamma", &obj2)->isNum()) {
- cs->gamma = obj2.getNum();
- }
- obj2.free();
- obj1.free();
- return cs;
-}
-
-void GfxCalGrayColorSpace::getGray(GfxColor *color, GfxGray *gray) {
- *gray = clip01(color->c[0]);
-}
-
-void GfxCalGrayColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) {
- rgb->r = rgb->g = rgb->b = clip01(color->c[0]);
-}
-
-void GfxCalGrayColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
- cmyk->c = cmyk->m = cmyk->y = 0;
- cmyk->k = clip01(gfxColorComp1 - color->c[0]);
-}
-
-//------------------------------------------------------------------------
-// GfxDeviceRGBColorSpace
-//------------------------------------------------------------------------
-
-GfxDeviceRGBColorSpace::GfxDeviceRGBColorSpace() {
-}
-
-GfxDeviceRGBColorSpace::~GfxDeviceRGBColorSpace() {
-}
-
-GfxColorSpace *GfxDeviceRGBColorSpace::copy() {
- return new GfxDeviceRGBColorSpace();
-}
-
-void GfxDeviceRGBColorSpace::getGray(GfxColor *color, GfxGray *gray) {
- *gray = clip01((GfxColorComp)(0.3 * color->c[0] +
- 0.59 * color->c[1] +
- 0.11 * color->c[2] + 0.5));
-}
-
-void GfxDeviceRGBColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) {
- rgb->r = clip01(color->c[0]);
- rgb->g = clip01(color->c[1]);
- rgb->b = clip01(color->c[2]);
-}
-
-void GfxDeviceRGBColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
- GfxColorComp c, m, y, k;
-
- c = clip01(gfxColorComp1 - color->c[0]);
- m = clip01(gfxColorComp1 - color->c[1]);
- y = clip01(gfxColorComp1 - color->c[2]);
- k = c;
- if (m < k) {
- k = m;
- }
- if (y < k) {
- k = y;
- }
- cmyk->c = c - k;
- cmyk->m = m - k;
- cmyk->y = y - k;
- cmyk->k = k;
-}
-
-//------------------------------------------------------------------------
-// GfxCalRGBColorSpace
-//------------------------------------------------------------------------
-
-GfxCalRGBColorSpace::GfxCalRGBColorSpace() {
- whiteX = whiteY = whiteZ = 1;
- blackX = blackY = blackZ = 0;
- gammaR = gammaG = gammaB = 1;
- mat[0] = 1; mat[1] = 0; mat[2] = 0;
- mat[3] = 0; mat[4] = 1; mat[5] = 0;
- mat[6] = 0; mat[7] = 0; mat[8] = 1;
-}
-
-GfxCalRGBColorSpace::~GfxCalRGBColorSpace() {
-}
-
-GfxColorSpace *GfxCalRGBColorSpace::copy() {
- GfxCalRGBColorSpace *cs;
- int i;
-
- cs = new GfxCalRGBColorSpace();
- cs->whiteX = whiteX;
- cs->whiteY = whiteY;
- cs->whiteZ = whiteZ;
- cs->blackX = blackX;
- cs->blackY = blackY;
- cs->blackZ = blackZ;
- cs->gammaR = gammaR;
- cs->gammaG = gammaG;
- cs->gammaB = gammaB;
- for (i = 0; i < 9; ++i) {
- cs->mat[i] = mat[i];
- }
- return cs;
-}
-
-GfxColorSpace *GfxCalRGBColorSpace::parse(Array *arr) {
- GfxCalRGBColorSpace *cs;
- Object obj1, obj2, obj3;
- int i;
-
- arr->get(1, &obj1);
- if (!obj1.isDict()) {
- error(-1, "Bad CalRGB color space");
- obj1.free();
- return NULL;
- }
- cs = new GfxCalRGBColorSpace();
- if (obj1.dictLookup("WhitePoint", &obj2)->isArray() &&
- obj2.arrayGetLength() == 3) {
- obj2.arrayGet(0, &obj3);
- cs->whiteX = obj3.getNum();
- obj3.free();
- obj2.arrayGet(1, &obj3);
- cs->whiteY = obj3.getNum();
- obj3.free();
- obj2.arrayGet(2, &obj3);
- cs->whiteZ = obj3.getNum();
- obj3.free();
- }
- obj2.free();
- if (obj1.dictLookup("BlackPoint", &obj2)->isArray() &&
- obj2.arrayGetLength() == 3) {
- obj2.arrayGet(0, &obj3);
- cs->blackX = obj3.getNum();
- obj3.free();
- obj2.arrayGet(1, &obj3);
- cs->blackY = obj3.getNum();
- obj3.free();
- obj2.arrayGet(2, &obj3);
- cs->blackZ = obj3.getNum();
- obj3.free();
- }
- obj2.free();
- if (obj1.dictLookup("Gamma", &obj2)->isArray() &&
- obj2.arrayGetLength() == 3) {
- obj2.arrayGet(0, &obj3);
- cs->gammaR = obj3.getNum();
- obj3.free();
- obj2.arrayGet(1, &obj3);
- cs->gammaG = obj3.getNum();
- obj3.free();
- obj2.arrayGet(2, &obj3);
- cs->gammaB = obj3.getNum();
- obj3.free();
- }
- obj2.free();
- if (obj1.dictLookup("Matrix", &obj2)->isArray() &&
- obj2.arrayGetLength() == 9) {
- for (i = 0; i < 9; ++i) {
- obj2.arrayGet(i, &obj3);
- cs->mat[i] = obj3.getNum();
- obj3.free();
- }
- }
- obj2.free();
- obj1.free();
- return cs;
-}
-
-void GfxCalRGBColorSpace::getGray(GfxColor *color, GfxGray *gray) {
- *gray = clip01((GfxColorComp)(0.299 * color->c[0] +
- 0.587 * color->c[1] +
- 0.114 * color->c[2] + 0.5));
-}
-
-void GfxCalRGBColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) {
- rgb->r = clip01(color->c[0]);
- rgb->g = clip01(color->c[1]);
- rgb->b = clip01(color->c[2]);
-}
-
-void GfxCalRGBColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
- GfxColorComp c, m, y, k;
-
- c = clip01(gfxColorComp1 - color->c[0]);
- m = clip01(gfxColorComp1 - color->c[1]);
- y = clip01(gfxColorComp1 - color->c[2]);
- k = c;
- if (m < k) {
- k = m;
- }
- if (y < k) {
- k = y;
- }
- cmyk->c = c - k;
- cmyk->m = m - k;
- cmyk->y = y - k;
- cmyk->k = k;
-}
-
-//------------------------------------------------------------------------
-// GfxDeviceCMYKColorSpace
-//------------------------------------------------------------------------
-
-GfxDeviceCMYKColorSpace::GfxDeviceCMYKColorSpace() {
-}
-
-GfxDeviceCMYKColorSpace::~GfxDeviceCMYKColorSpace() {
-}
-
-GfxColorSpace *GfxDeviceCMYKColorSpace::copy() {
- return new GfxDeviceCMYKColorSpace();
-}
-
-void GfxDeviceCMYKColorSpace::getGray(GfxColor *color, GfxGray *gray) {
- *gray = clip01((GfxColorComp)(gfxColorComp1 - color->c[3]
- - 0.3 * color->c[0]
- - 0.59 * color->c[1]
- - 0.11 * color->c[2] + 0.5));
-}
-
-/*void GfxDeviceCMYKColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) {
- unsigned char r,g,b;
- float c = color->c[0];
- float m = color->c[1];
- float y = color->c[2];
- float k = color->c[3];
- convert_cmyk2rgb(c,m,y,k, &r,&g,&b);
- rgb->r = r/255.0;
- rgb->g = g/255.0;
- rgb->b = b/255.0;
-}*/
-
-void GfxDeviceCMYKColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) {
- double c, m, y, k, c1, m1, y1, k1, r, g, b, x;
-
- c = colToDbl(color->c[0]);
- m = colToDbl(color->c[1]);
- y = colToDbl(color->c[2]);
- k = colToDbl(color->c[3]);
- c1 = 1 - c;
- m1 = 1 - m;
- y1 = 1 - y;
- k1 = 1 - k;
- // this is a matrix multiplication, unrolled for performance
- // C M Y K
- x = c1 * m1 * y1 * k1; // 0 0 0 0
- r = g = b = x;
- x = c1 * m1 * y1 * k; // 0 0 0 1
- r += 0.1373 * x;
- g += 0.1216 * x;
- b += 0.1255 * x;
- x = c1 * m1 * y * k1; // 0 0 1 0
- r += x;
- g += 0.9490 * x;
- x = c1 * m1 * y * k; // 0 0 1 1
- r += 0.1098 * x;
- g += 0.1020 * x;
- x = c1 * m * y1 * k1; // 0 1 0 0
- r += 0.9255 * x;
- b += 0.5490 * x;
- x = c1 * m * y1 * k; // 0 1 0 1
- r += 0.1412 * x;
- x = c1 * m * y * k1; // 0 1 1 0
- r += 0.9294 * x;
- g += 0.1098 * x;
- b += 0.1412 * x;
- x = c1 * m * y * k; // 0 1 1 1
- r += 0.1333 * x;
- x = c * m1 * y1 * k1; // 1 0 0 0
- g += 0.6784 * x;
- b += 0.9373 * x;
- x = c * m1 * y1 * k; // 1 0 0 1
- g += 0.0588 * x;
- b += 0.1412 * x;
- x = c * m1 * y * k1; // 1 0 1 0
- g += 0.6510 * x;
- b += 0.3137 * x;
- x = c * m1 * y * k; // 1 0 1 1
- g += 0.0745 * x;
- x = c * m * y1 * k1; // 1 1 0 0
- r += 0.1804 * x;
- g += 0.1922 * x;
- b += 0.5725 * x;
- x = c * m * y1 * k; // 1 1 0 1
- b += 0.0078 * x;
- x = c * m * y * k1; // 1 1 1 0
- r += 0.2118 * x;
- g += 0.2119 * x;
- b += 0.2235 * x;
- rgb->r = clip01(dblToCol(r));
- rgb->g = clip01(dblToCol(g));
- rgb->b = clip01(dblToCol(b));
-}
-
-void GfxDeviceCMYKColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
- cmyk->c = clip01(color->c[0]);
- cmyk->m = clip01(color->c[1]);
- cmyk->y = clip01(color->c[2]);
- cmyk->k = clip01(color->c[3]);
-}
-
-//------------------------------------------------------------------------
-// GfxLabColorSpace
-//------------------------------------------------------------------------
-
-// This is the inverse of MatrixLMN in Example 4.10 from the PostScript
-// Language Reference, Third Edition.
-static double xyzrgb[3][3] = {
- { 3.240449, -1.537136, -0.498531 },
- { -0.969265, 1.876011, 0.041556 },
- { 0.055643, -0.204026, 1.057229 }
-};
-
-GfxLabColorSpace::GfxLabColorSpace() {
- whiteX = whiteY = whiteZ = 1;
- blackX = blackY = blackZ = 0;
- aMin = bMin = -100;
- aMax = bMax = 100;
-}
-
-GfxLabColorSpace::~GfxLabColorSpace() {
-}
-
-GfxColorSpace *GfxLabColorSpace::copy() {
- GfxLabColorSpace *cs;
-
- cs = new GfxLabColorSpace();
- cs->whiteX = whiteX;
- cs->whiteY = whiteY;
- cs->whiteZ = whiteZ;
- cs->blackX = blackX;
- cs->blackY = blackY;
- cs->blackZ = blackZ;
- cs->aMin = aMin;
- cs->aMax = aMax;
- cs->bMin = bMin;
- cs->bMax = bMax;
- cs->kr = kr;
- cs->kg = kg;
- cs->kb = kb;
- return cs;
-}
-
-GfxColorSpace *GfxLabColorSpace::parse(Array *arr) {
- GfxLabColorSpace *cs;
- Object obj1, obj2, obj3;
-
- arr->get(1, &obj1);
- if (!obj1.isDict()) {
- error(-1, "Bad Lab color space");
- obj1.free();
- return NULL;
- }
- cs = new GfxLabColorSpace();
- if (obj1.dictLookup("WhitePoint", &obj2)->isArray() &&
- obj2.arrayGetLength() == 3) {
- obj2.arrayGet(0, &obj3);
- cs->whiteX = obj3.getNum();
- obj3.free();
- obj2.arrayGet(1, &obj3);
- cs->whiteY = obj3.getNum();
- obj3.free();
- obj2.arrayGet(2, &obj3);
- cs->whiteZ = obj3.getNum();
- obj3.free();
- }
- obj2.free();
- if (obj1.dictLookup("BlackPoint", &obj2)->isArray() &&
- obj2.arrayGetLength() == 3) {
- obj2.arrayGet(0, &obj3);
- cs->blackX = obj3.getNum();
- obj3.free();
- obj2.arrayGet(1, &obj3);
- cs->blackY = obj3.getNum();
- obj3.free();
- obj2.arrayGet(2, &obj3);
- cs->blackZ = obj3.getNum();
- obj3.free();
- }
- obj2.free();
- if (obj1.dictLookup("Range", &obj2)->isArray() &&
- obj2.arrayGetLength() == 4) {
- obj2.arrayGet(0, &obj3);
- cs->aMin = obj3.getNum();
- obj3.free();
- obj2.arrayGet(1, &obj3);
- cs->aMax = obj3.getNum();
- obj3.free();
- obj2.arrayGet(2, &obj3);
- cs->bMin = obj3.getNum();
- obj3.free();
- obj2.arrayGet(3, &obj3);
- cs->bMax = obj3.getNum();
- obj3.free();
- }
- obj2.free();
- obj1.free();
-
- cs->kr = 1 / (xyzrgb[0][0] * cs->whiteX +
- xyzrgb[0][1] * cs->whiteY +
- xyzrgb[0][2] * cs->whiteZ);
- cs->kg = 1 / (xyzrgb[1][0] * cs->whiteX +
- xyzrgb[1][1] * cs->whiteY +
- xyzrgb[1][2] * cs->whiteZ);
- cs->kb = 1 / (xyzrgb[2][0] * cs->whiteX +
- xyzrgb[2][1] * cs->whiteY +
- xyzrgb[2][2] * cs->whiteZ);
-
- return cs;
-}
-
-void GfxLabColorSpace::getGray(GfxColor *color, GfxGray *gray) {
- GfxRGB rgb;
-
- getRGB(color, &rgb);
- *gray = clip01((GfxColorComp)(0.299 * rgb.r +
- 0.587 * rgb.g +
- 0.114 * rgb.b + 0.5));
-}
-
-void GfxLabColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) {
- double X, Y, Z;
- double t1, t2;
- double r, g, b;
-
- // convert L*a*b* to CIE 1931 XYZ color space
- t1 = (colToDbl(color->c[0]) + 16) / 116;
- t2 = t1 + colToDbl(color->c[1]) / 500;
- if (t2 >= (6.0 / 29.0)) {
- X = t2 * t2 * t2;
- } else {
- X = (108.0 / 841.0) * (t2 - (4.0 / 29.0));
- }
- X *= whiteX;
- if (t1 >= (6.0 / 29.0)) {
- Y = t1 * t1 * t1;
- } else {
- Y = (108.0 / 841.0) * (t1 - (4.0 / 29.0));
- }
- Y *= whiteY;
- t2 = t1 - colToDbl(color->c[2]) / 200;
- if (t2 >= (6.0 / 29.0)) {
- Z = t2 * t2 * t2;
- } else {
- Z = (108.0 / 841.0) * (t2 - (4.0 / 29.0));
- }
- Z *= whiteZ;
-
- // convert XYZ to RGB, including gamut mapping and gamma correction
- r = xyzrgb[0][0] * X + xyzrgb[0][1] * Y + xyzrgb[0][2] * Z;
- g = xyzrgb[1][0] * X + xyzrgb[1][1] * Y + xyzrgb[1][2] * Z;
- b = xyzrgb[2][0] * X + xyzrgb[2][1] * Y + xyzrgb[2][2] * Z;
- rgb->r = dblToCol(pow(clip01(r * kr), 0.5));
- rgb->g = dblToCol(pow(clip01(g * kg), 0.5));
- rgb->b = dblToCol(pow(clip01(b * kb), 0.5));
-}
-
-void GfxLabColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
- GfxRGB rgb;
- GfxColorComp c, m, y, k;
-
- getRGB(color, &rgb);
- c = clip01(gfxColorComp1 - rgb.r);
- m = clip01(gfxColorComp1 - rgb.g);
- y = clip01(gfxColorComp1 - rgb.b);
- k = c;
- if (m < k) {
- k = m;
- }
- if (y < k) {
- k = y;
- }
- cmyk->c = c - k;
- cmyk->m = m - k;
- cmyk->y = y - k;
- cmyk->k = k;
-}
-
-void GfxLabColorSpace::getDefaultRanges(double *decodeLow, double *decodeRange,
- int maxImgPixel) {
- decodeLow[0] = 0;
- decodeRange[0] = 100;
- decodeLow[1] = aMin;
- decodeRange[1] = aMax - aMin;
- decodeLow[2] = bMin;
- decodeRange[2] = bMax - bMin;
-}
-
-//------------------------------------------------------------------------
-// GfxICCBasedColorSpace
-//------------------------------------------------------------------------
-
-GfxICCBasedColorSpace::GfxICCBasedColorSpace(int nCompsA, GfxColorSpace *altA,
- Ref *iccProfileStreamA) {
- nComps = nCompsA;
- alt = altA;
- iccProfileStream = *iccProfileStreamA;
- rangeMin[0] = rangeMin[1] = rangeMin[2] = rangeMin[3] = 0;
- rangeMax[0] = rangeMax[1] = rangeMax[2] = rangeMax[3] = 1;
-}
-
-GfxICCBasedColorSpace::~GfxICCBasedColorSpace() {
- delete alt;
-}
-
-GfxColorSpace *GfxICCBasedColorSpace::copy() {
- GfxICCBasedColorSpace *cs;
- int i;
-
- cs = new GfxICCBasedColorSpace(nComps, alt->copy(), &iccProfileStream);
- for (i = 0; i < 4; ++i) {
- cs->rangeMin[i] = rangeMin[i];
- cs->rangeMax[i] = rangeMax[i];
- }
- return cs;
-}
-
-GfxColorSpace *GfxICCBasedColorSpace::parse(Array *arr) {
- GfxICCBasedColorSpace *cs;
- Ref iccProfileStreamA;
- int nCompsA;
- GfxColorSpace *altA;
- Dict *dict;
- Object obj1, obj2, obj3;
- int i;
-
- arr->getNF(1, &obj1);
- if (obj1.isRef()) {
- iccProfileStreamA = obj1.getRef();
- } else {
- iccProfileStreamA.num = 0;
- iccProfileStreamA.gen = 0;
- }
- obj1.free();
- arr->get(1, &obj1);
- if (!obj1.isStream()) {
- error(-1, "Bad ICCBased color space (stream)");
- obj1.free();
- return NULL;
- }
- dict = obj1.streamGetDict();
- if (!dict->lookup("N", &obj2)->isInt()) {
- error(-1, "Bad ICCBased color space (N)");
- obj2.free();
- obj1.free();
- return NULL;
- }
- nCompsA = obj2.getInt();
- obj2.free();
- if (nCompsA > gfxColorMaxComps) {
- error(-1, "ICCBased color space with too many (%d > %d) components",
- nCompsA, gfxColorMaxComps);
- nCompsA = gfxColorMaxComps;
- }
- if (dict->lookup("Alternate", &obj2)->isNull() ||
- !(altA = GfxColorSpace::parse(&obj2))) {
- switch (nCompsA) {
- case 1:
- altA = new GfxDeviceGrayColorSpace();
- break;
- case 3:
- altA = new GfxDeviceRGBColorSpace();
- break;
- case 4:
- altA = new GfxDeviceCMYKColorSpace();
- break;
- default:
- error(-1, "Bad ICCBased color space - invalid N");
- obj2.free();
- obj1.free();
- return NULL;
- }
- }
- obj2.free();
- cs = new GfxICCBasedColorSpace(nCompsA, altA, &iccProfileStreamA);
- if (dict->lookup("Range", &obj2)->isArray() &&
- obj2.arrayGetLength() == 2 * nCompsA) {
- for (i = 0; i < nCompsA; ++i) {
- obj2.arrayGet(2*i, &obj3);
- cs->rangeMin[i] = obj3.getNum();
- obj3.free();
- obj2.arrayGet(2*i+1, &obj3);
- cs->rangeMax[i] = obj3.getNum();
- obj3.free();
- }
- }
- obj2.free();
- obj1.free();
- return cs;
-}
-
-void GfxICCBasedColorSpace::getGray(GfxColor *color, GfxGray *gray) {
- alt->getGray(color, gray);
-}
-
-void GfxICCBasedColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) {
- alt->getRGB(color, rgb);
-}
-
-void GfxICCBasedColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
- alt->getCMYK(color, cmyk);
-}
-
-void GfxICCBasedColorSpace::getDefaultRanges(double *decodeLow,
- double *decodeRange,
- int maxImgPixel) {
- alt->getDefaultRanges(decodeLow, decodeRange, maxImgPixel);
-
-#if 0
- // this is nominally correct, but some PDF files don't set the
- // correct ranges in the ICCBased dict
- int i;
-
- for (i = 0; i < nComps; ++i) {
- decodeLow[i] = rangeMin[i];
- decodeRange[i] = rangeMax[i] - rangeMin[i];
- }
-#endif
-}
-
-//------------------------------------------------------------------------
-// GfxIndexedColorSpace
-//------------------------------------------------------------------------
-
-GfxIndexedColorSpace::GfxIndexedColorSpace(GfxColorSpace *baseA,
- int indexHighA) {
- base = baseA;
- indexHigh = indexHighA;
- lookup = (Guchar *)gmallocn((indexHigh + 1) * base->getNComps(),
- sizeof(Guchar));
-}
-
-GfxIndexedColorSpace::~GfxIndexedColorSpace() {
- delete base;
- gfree(lookup);
-}
-
-GfxColorSpace *GfxIndexedColorSpace::copy() {
- GfxIndexedColorSpace *cs;
-
- cs = new GfxIndexedColorSpace(base->copy(), indexHigh);
- memcpy(cs->lookup, lookup,
- (indexHigh + 1) * base->getNComps() * sizeof(Guchar));
- return cs;
-}
-
-GfxColorSpace *GfxIndexedColorSpace::parse(Array *arr) {
- GfxIndexedColorSpace *cs;
- GfxColorSpace *baseA;
- int indexHighA;
- Object obj1;
- int x;
- char *s;
- int n, i, j;
-
- if (arr->getLength() != 4) {
- error(-1, "Bad Indexed color space");
- goto err1;
- }
- arr->get(1, &obj1);
- if (!(baseA = GfxColorSpace::parse(&obj1))) {
- error(-1, "Bad Indexed color space (base color space)");
- goto err2;
- }
- obj1.free();
- if (!arr->get(2, &obj1)->isInt()) {
- error(-1, "Bad Indexed color space (hival)");
- delete baseA;
- goto err2;
- }
- indexHighA = obj1.getInt();
- if (indexHighA < 0 || indexHighA > 255) {
- // the PDF spec requires indexHigh to be in [0,255] -- allowing
- // values larger than 255 creates a security hole: if nComps *
- // indexHigh is greater than 2^31, the loop below may overwrite
- // past the end of the array
- error(-1, "Bad Indexed color space (invalid indexHigh value)");
- delete baseA;
- goto err2;
- }
- obj1.free();
- cs = new GfxIndexedColorSpace(baseA, indexHighA);
- arr->get(3, &obj1);
- n = baseA->getNComps();
- if (obj1.isStream()) {
- obj1.streamReset();
- for (i = 0; i <= indexHighA; ++i) {
- for (j = 0; j < n; ++j) {
- if ((x = obj1.streamGetChar()) == EOF) {
- error(-1, "Bad Indexed color space (lookup table stream too short)");
- goto err3;
- }
- cs->lookup[i*n + j] = (Guchar)x;
- }
- }
- obj1.streamClose();
- } else if (obj1.isString()) {
- if (obj1.getString()->getLength() < (indexHighA + 1) * n) {
- error(-1, "Bad Indexed color space (lookup table string too short)");
- goto err3;
- }
- s = obj1.getString()->getCString();
- for (i = 0; i <= indexHighA; ++i) {
- for (j = 0; j < n; ++j) {
- cs->lookup[i*n + j] = (Guchar)*s++;
- }
- }
- } else {
- error(-1, "Bad Indexed color space (lookup table)");
- goto err3;
- }
- obj1.free();
- return cs;
-
- err3:
- delete cs;
- err2:
- obj1.free();
- err1:
- return NULL;
-}
-
-GfxColor *GfxIndexedColorSpace::mapColorToBase(GfxColor *color,
- GfxColor *baseColor) {
- Guchar *p;
- double low[gfxColorMaxComps], range[gfxColorMaxComps];
- int n, i;
-
- n = base->getNComps();
- base->getDefaultRanges(low, range, indexHigh);
- p = &lookup[(int)(colToDbl(color->c[0]) + 0.5) * n];
- for (i = 0; i < n; ++i) {
- baseColor->c[i] = dblToCol(low[i] + (p[i] / 255.0) * range[i]);
- }
- return baseColor;
-}
-
-void GfxIndexedColorSpace::getGray(GfxColor *color, GfxGray *gray) {
- GfxColor color2;
-
- base->getGray(mapColorToBase(color, &color2), gray);
-}
-
-void GfxIndexedColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) {
- GfxColor color2;
-
- base->getRGB(mapColorToBase(color, &color2), rgb);
-}
-
-void GfxIndexedColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
- GfxColor color2;
-
- base->getCMYK(mapColorToBase(color, &color2), cmyk);
-}
-
-void GfxIndexedColorSpace::getDefaultRanges(double *decodeLow,
- double *decodeRange,
- int maxImgPixel) {
- decodeLow[0] = 0;
- decodeRange[0] = maxImgPixel;
-}
-
-//------------------------------------------------------------------------
-// GfxSeparationColorSpace
-//------------------------------------------------------------------------
-
-GfxSeparationColorSpace::GfxSeparationColorSpace(GString *nameA,
- GfxColorSpace *altA,
- Function *funcA) {
- name = nameA;
- alt = altA;
- func = funcA;
-}
-
-GfxSeparationColorSpace::~GfxSeparationColorSpace() {
- delete name;
- delete alt;
- delete func;
-}
-
-GfxColorSpace *GfxSeparationColorSpace::copy() {
- return new GfxSeparationColorSpace(name->copy(), alt->copy(), func->copy());
-}
-
-//~ handle the 'All' and 'None' colorants
-GfxColorSpace *GfxSeparationColorSpace::parse(Array *arr) {
- GfxSeparationColorSpace *cs;
- GString *nameA;
- GfxColorSpace *altA;
- Function *funcA;
- Object obj1;
-
- if (arr->getLength() != 4) {
- error(-1, "Bad Separation color space");
- goto err1;
- }
- if (!arr->get(1, &obj1)->isName()) {
- error(-1, "Bad Separation color space (name)");
- goto err2;
- }
- nameA = new GString(obj1.getName());
- obj1.free();
- arr->get(2, &obj1);
- if (!(altA = GfxColorSpace::parse(&obj1))) {
- error(-1, "Bad Separation color space (alternate color space)");
- goto err3;
- }
- obj1.free();
- arr->get(3, &obj1);
- if (!(funcA = Function::parse(&obj1))) {
- goto err4;
- }
- obj1.free();
- cs = new GfxSeparationColorSpace(nameA, altA, funcA);
- return cs;
-
- err4:
- delete altA;
- err3:
- delete nameA;
- err2:
- obj1.free();
- err1:
- return NULL;
-}
-
-void GfxSeparationColorSpace::getGray(GfxColor *color, GfxGray *gray) {
- double x;
- double c[gfxColorMaxComps];
- GfxColor color2;
- int i;
-
- x = colToDbl(color->c[0]);
- func->transform(&x, c);
- for (i = 0; i < alt->getNComps(); ++i) {
- color2.c[i] = dblToCol(c[i]);
- }
- alt->getGray(&color2, gray);
-}
-
-void GfxSeparationColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) {
- double x;
- double c[gfxColorMaxComps];
- GfxColor color2;
- int i;
-
- x = colToDbl(color->c[0]);
- func->transform(&x, c);
- for (i = 0; i < alt->getNComps(); ++i) {
- color2.c[i] = dblToCol(c[i]);
- }
- alt->getRGB(&color2, rgb);
-}
-
-void GfxSeparationColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
- double x;
- double c[gfxColorMaxComps];
- GfxColor color2;
- int i;
-
- x = colToDbl(color->c[0]);
- func->transform(&x, c);
- for (i = 0; i < alt->getNComps(); ++i) {
- color2.c[i] = dblToCol(c[i]);
- }
- alt->getCMYK(&color2, cmyk);
-}
-
-//------------------------------------------------------------------------
-// GfxDeviceNColorSpace
-//------------------------------------------------------------------------
-
-GfxDeviceNColorSpace::GfxDeviceNColorSpace(int nCompsA,
- GfxColorSpace *altA,
- Function *funcA) {
- nComps = nCompsA;
- alt = altA;
- func = funcA;
-}
-
-GfxDeviceNColorSpace::~GfxDeviceNColorSpace() {
- int i;
-
- for (i = 0; i < nComps; ++i) {
- delete names[i];
- }
- delete alt;
- delete func;
-}
-
-GfxColorSpace *GfxDeviceNColorSpace::copy() {
- GfxDeviceNColorSpace *cs;
- int i;
-
- cs = new GfxDeviceNColorSpace(nComps, alt->copy(), func->copy());
- for (i = 0; i < nComps; ++i) {
- cs->names[i] = names[i]->copy();
- }
- return cs;
-}
-
-//~ handle the 'None' colorant
-GfxColorSpace *GfxDeviceNColorSpace::parse(Array *arr) {
- GfxDeviceNColorSpace *cs;
- int nCompsA;
- GString *namesA[gfxColorMaxComps];
- GfxColorSpace *altA;
- Function *funcA;
- Object obj1, obj2;
- int i;
-
- if (arr->getLength() != 4 && arr->getLength() != 5) {
- error(-1, "Bad DeviceN color space");
- goto err1;
- }
- if (!arr->get(1, &obj1)->isArray()) {
- error(-1, "Bad DeviceN color space (names)");
- goto err2;
- }
- nCompsA = obj1.arrayGetLength();
- if (nCompsA > gfxColorMaxComps) {
- error(-1, "DeviceN color space with too many (%d > %d) components",
- nCompsA, gfxColorMaxComps);
- nCompsA = gfxColorMaxComps;
- }
- for (i = 0; i < nCompsA; ++i) {
- if (!obj1.arrayGet(i, &obj2)->isName()) {
- error(-1, "Bad DeviceN color space (names)");
- obj2.free();
- goto err2;
- }
- namesA[i] = new GString(obj2.getName());
- obj2.free();
- }
- obj1.free();
- arr->get(2, &obj1);
- if (!(altA = GfxColorSpace::parse(&obj1))) {
- error(-1, "Bad DeviceN color space (alternate color space)");
- goto err3;
- }
- obj1.free();
- arr->get(3, &obj1);
- if (!(funcA = Function::parse(&obj1))) {
- goto err4;
- }
- obj1.free();
- cs = new GfxDeviceNColorSpace(nCompsA, altA, funcA);
- for (i = 0; i < nCompsA; ++i) {
- cs->names[i] = namesA[i];
- }
- return cs;
-
- err4:
- delete altA;
- err3:
- for (i = 0; i < nCompsA; ++i) {
- delete namesA[i];
- }
- err2:
- obj1.free();
- err1:
- return NULL;
-}
-
-void GfxDeviceNColorSpace::getGray(GfxColor *color, GfxGray *gray) {
- double x[gfxColorMaxComps], c[gfxColorMaxComps];
- GfxColor color2;
- int i;
-
- for (i = 0; i < nComps; ++i) {
- x[i] = colToDbl(color->c[i]);
- }
- func->transform(x, c);
- for (i = 0; i < alt->getNComps(); ++i) {
- color2.c[i] = dblToCol(c[i]);
- }
- alt->getGray(&color2, gray);
-}
-
-void GfxDeviceNColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) {
- double x[gfxColorMaxComps], c[gfxColorMaxComps];
- GfxColor color2;
- int i;
-
- for (i = 0; i < nComps; ++i) {
- x[i] = colToDbl(color->c[i]);
- }
- func->transform(x, c);
- for (i = 0; i < alt->getNComps(); ++i) {
- color2.c[i] = dblToCol(c[i]);
- }
- alt->getRGB(&color2, rgb);
-}
-
-void GfxDeviceNColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
- double x[gfxColorMaxComps], c[gfxColorMaxComps];
- GfxColor color2;
- int i;
-
- for (i = 0; i < nComps; ++i) {
- x[i] = colToDbl(color->c[i]);
- }
- func->transform(x, c);
- for (i = 0; i < alt->getNComps(); ++i) {
- color2.c[i] = dblToCol(c[i]);
- }
- alt->getCMYK(&color2, cmyk);
-}
-
-//------------------------------------------------------------------------
-// GfxPatternColorSpace
-//------------------------------------------------------------------------
-
-GfxPatternColorSpace::GfxPatternColorSpace(GfxColorSpace *underA) {
- under = underA;
-}
-
-GfxPatternColorSpace::~GfxPatternColorSpace() {
- if (under) {
- delete under;
- }
-}
-
-GfxColorSpace *GfxPatternColorSpace::copy() {
- return new GfxPatternColorSpace(under ? under->copy() :
- (GfxColorSpace *)NULL);
-}
-
-GfxColorSpace *GfxPatternColorSpace::parse(Array *arr) {
- GfxPatternColorSpace *cs;
- GfxColorSpace *underA;
- Object obj1;
-
- if (arr->getLength() != 1 && arr->getLength() != 2) {
- error(-1, "Bad Pattern color space");
- return NULL;
- }
- underA = NULL;
- if (arr->getLength() == 2) {
- arr->get(1, &obj1);
- if (!(underA = GfxColorSpace::parse(&obj1))) {
- error(-1, "Bad Pattern color space (underlying color space)");
- obj1.free();
- return NULL;
- }
- obj1.free();
- }
- cs = new GfxPatternColorSpace(underA);
- return cs;
-}
-
-void GfxPatternColorSpace::getGray(GfxColor *color, GfxGray *gray) {
- *gray = 0;
-}
-
-void GfxPatternColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) {
- rgb->r = rgb->g = rgb->b = 0;
-}
-
-void GfxPatternColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
- cmyk->c = cmyk->m = cmyk->y = 0;
- cmyk->k = 1;
-}
-
-//------------------------------------------------------------------------
-// Pattern
-//------------------------------------------------------------------------
-
-GfxPattern::GfxPattern(int typeA) {
- type = typeA;
-}
-
-GfxPattern::~GfxPattern() {
-}
-
-GfxPattern *GfxPattern::parse(Object *obj) {
- GfxPattern *pattern;
- Object obj1;
-
- if (obj->isDict()) {
- obj->dictLookup("PatternType", &obj1);
- } else if (obj->isStream()) {
- obj->streamGetDict()->lookup("PatternType", &obj1);
- } else {
- return NULL;
- }
- pattern = NULL;
- if (obj1.isInt() && obj1.getInt() == 1) {
- pattern = GfxTilingPattern::parse(obj);
- } else if (obj1.isInt() && obj1.getInt() == 2) {
- pattern = GfxShadingPattern::parse(obj);
- }
- obj1.free();
- return pattern;
-}
-
-//------------------------------------------------------------------------
-// GfxTilingPattern
-//------------------------------------------------------------------------
-
-GfxTilingPattern *GfxTilingPattern::parse(Object *patObj) {
- GfxTilingPattern *pat;
- Dict *dict;
- int paintTypeA, tilingTypeA;
- double bboxA[4], matrixA[6];
- double xStepA, yStepA;
- Object resDictA;
- Object obj1, obj2;
- int i;
-
- if (!patObj->isStream()) {
- return NULL;
- }
- dict = patObj->streamGetDict();
-
- if (dict->lookup("PaintType", &obj1)->isInt()) {
- paintTypeA = obj1.getInt();
- } else {
- paintTypeA = 1;
- error(-1, "Invalid or missing PaintType in pattern");
- }
- obj1.free();
- if (dict->lookup("TilingType", &obj1)->isInt()) {
- tilingTypeA = obj1.getInt();
- } else {
- tilingTypeA = 1;
- error(-1, "Invalid or missing TilingType in pattern");
- }
- obj1.free();
- bboxA[0] = bboxA[1] = 0;
- bboxA[2] = bboxA[3] = 1;
- if (dict->lookup("BBox", &obj1)->isArray() &&
- obj1.arrayGetLength() == 4) {
- for (i = 0; i < 4; ++i) {
- if (obj1.arrayGet(i, &obj2)->isNum()) {
- bboxA[i] = obj2.getNum();
- }
- obj2.free();
- }
- } else {
- error(-1, "Invalid or missing BBox in pattern");
- }
- obj1.free();
- if (dict->lookup("XStep", &obj1)->isNum()) {
- xStepA = obj1.getNum();
- } else {
- xStepA = 1;
- error(-1, "Invalid or missing XStep in pattern");
- }
- obj1.free();
- if (dict->lookup("YStep", &obj1)->isNum()) {
- yStepA = obj1.getNum();
- } else {
- yStepA = 1;
- error(-1, "Invalid or missing YStep in pattern");
- }
- obj1.free();
- if (!dict->lookup("Resources", &resDictA)->isDict()) {
- resDictA.free();
- resDictA.initNull();
- error(-1, "Invalid or missing Resources in pattern");
- }
- matrixA[0] = 1; matrixA[1] = 0;
- matrixA[2] = 0; matrixA[3] = 1;
- matrixA[4] = 0; matrixA[5] = 0;
- if (dict->lookup("Matrix", &obj1)->isArray() &&
- obj1.arrayGetLength() == 6) {
- for (i = 0; i < 6; ++i) {
- if (obj1.arrayGet(i, &obj2)->isNum()) {
- matrixA[i] = obj2.getNum();
- }
- obj2.free();
- }
- }
- obj1.free();
-
- pat = new GfxTilingPattern(paintTypeA, tilingTypeA, bboxA, xStepA, yStepA,
- &resDictA, matrixA, patObj);
- resDictA.free();
- return pat;
-}
-
-GfxTilingPattern::GfxTilingPattern(int paintTypeA, int tilingTypeA,
- double *bboxA, double xStepA, double yStepA,
- Object *resDictA, double *matrixA,
- Object *contentStreamA):
- GfxPattern(1)
-{
- int i;
-
- paintType = paintTypeA;
- tilingType = tilingTypeA;
- for (i = 0; i < 4; ++i) {
- bbox[i] = bboxA[i];
- }
- xStep = xStepA;
- yStep = yStepA;
- resDictA->copy(&resDict);
- for (i = 0; i < 6; ++i) {
- matrix[i] = matrixA[i];
- }
- contentStreamA->copy(&contentStream);
-}
-
-GfxTilingPattern::~GfxTilingPattern() {
- resDict.free();
- contentStream.free();
-}
-
-GfxPattern *GfxTilingPattern::copy() {
- return new GfxTilingPattern(paintType, tilingType, bbox, xStep, yStep,
- &resDict, matrix, &contentStream);
-}
-
-//------------------------------------------------------------------------
-// GfxShadingPattern
-//------------------------------------------------------------------------
-
-GfxShadingPattern *GfxShadingPattern::parse(Object *patObj) {
- Dict *dict;
- GfxShading *shadingA;
- double matrixA[6];
- Object obj1, obj2;
- int i;
-
- if (!patObj->isDict()) {
- return NULL;
- }
- dict = patObj->getDict();
-
- dict->lookup("Shading", &obj1);
- shadingA = GfxShading::parse(&obj1);
- obj1.free();
- if (!shadingA) {
- return NULL;
- }
-
- matrixA[0] = 1; matrixA[1] = 0;
- matrixA[2] = 0; matrixA[3] = 1;
- matrixA[4] = 0; matrixA[5] = 0;
- if (dict->lookup("Matrix", &obj1)->isArray() &&
- obj1.arrayGetLength() == 6) {
- for (i = 0; i < 6; ++i) {
- if (obj1.arrayGet(i, &obj2)->isNum()) {
- matrixA[i] = obj2.getNum();
- }
- obj2.free();
- }
- }
- obj1.free();
-
- return new GfxShadingPattern(shadingA, matrixA);
-}
-
-GfxShadingPattern::GfxShadingPattern(GfxShading *shadingA, double *matrixA):
- GfxPattern(2)
-{
- int i;
-
- shading = shadingA;
- for (i = 0; i < 6; ++i) {
- matrix[i] = matrixA[i];
- }
-}
-
-GfxShadingPattern::~GfxShadingPattern() {
- delete shading;
-}
-
-GfxPattern *GfxShadingPattern::copy() {
- return new GfxShadingPattern(shading->copy(), matrix);
-}
-
-//------------------------------------------------------------------------
-// GfxShading
-//------------------------------------------------------------------------
-
-GfxShading::GfxShading(int typeA) {
- type = typeA;
- colorSpace = NULL;
-}
-
-GfxShading::GfxShading(GfxShading *shading) {
- int i;
-
- type = shading->type;
- colorSpace = shading->colorSpace->copy();
- for (i = 0; i < gfxColorMaxComps; ++i) {
- background.c[i] = shading->background.c[i];
- }
- hasBackground = shading->hasBackground;
- xMin = shading->xMin;
- yMin = shading->yMin;
- xMax = shading->xMax;
- yMax = shading->yMax;
- hasBBox = shading->hasBBox;
-}
-
-GfxShading::~GfxShading() {
- if (colorSpace) {
- delete colorSpace;
- }
-}
-
-GfxShading *GfxShading::parse(Object *obj) {
- GfxShading *shading;
- Dict *dict;
- int typeA;
- Object obj1;
-
- if (obj->isDict()) {
- dict = obj->getDict();
- } else if (obj->isStream()) {
- dict = obj->streamGetDict();
- } else {
- return NULL;
- }
-
- if (!dict->lookup("ShadingType", &obj1)->isInt()) {
- error(-1, "Invalid ShadingType in shading dictionary");
- obj1.free();
- return NULL;
- }
- typeA = obj1.getInt();
- obj1.free();
-
- switch (typeA) {
- case 1:
- shading = GfxFunctionShading::parse(dict);
- break;
- case 2:
- shading = GfxAxialShading::parse(dict);
- break;
- case 3:
- shading = GfxRadialShading::parse(dict);
- break;
- case 4:
- if (obj->isStream()) {
- shading = GfxGouraudTriangleShading::parse(4, dict, obj->getStream());
- } else {
- error(-1, "Invalid Type 4 shading object");
- goto err1;
- }
- break;
- case 5:
- if (obj->isStream()) {
- shading = GfxGouraudTriangleShading::parse(5, dict, obj->getStream());
- } else {
- error(-1, "Invalid Type 5 shading object");
- goto err1;
- }
- break;
- case 6:
- if (obj->isStream()) {
- shading = GfxPatchMeshShading::parse(6, dict, obj->getStream());
- } else {
- error(-1, "Invalid Type 6 shading object");
- goto err1;
- }
- break;
- case 7:
- if (obj->isStream()) {
- shading = GfxPatchMeshShading::parse(7, dict, obj->getStream());
- } else {
- error(-1, "Invalid Type 7 shading object");
- goto err1;
- }
- break;
- default:
- error(-1, "Unimplemented shading type %d", typeA);
- goto err1;
- }
-
- return shading;
-
- err1:
- return NULL;
-}
-
-GBool GfxShading::init(Dict *dict) {
- Object obj1, obj2;
- int i;
-
- dict->lookup("ColorSpace", &obj1);
- if (!(colorSpace = GfxColorSpace::parse(&obj1))) {
- error(-1, "Bad color space in shading dictionary");
- obj1.free();
- return gFalse;
- }
- obj1.free();
-
- for (i = 0; i < gfxColorMaxComps; ++i) {
- background.c[i] = 0;
- }
- hasBackground = gFalse;
- if (dict->lookup("Background", &obj1)->isArray()) {
- if (obj1.arrayGetLength() == colorSpace->getNComps()) {
- hasBackground = gTrue;
- for (i = 0; i < colorSpace->getNComps(); ++i) {
- background.c[i] = dblToCol(obj1.arrayGet(i, &obj2)->getNum());
- obj2.free();
- }
- } else {
- error(-1, "Bad Background in shading dictionary");
- }
- }
- obj1.free();
-
- xMin = yMin = xMax = yMax = 0;
- hasBBox = gFalse;
- if (dict->lookup("BBox", &obj1)->isArray()) {
- if (obj1.arrayGetLength() == 4) {
- hasBBox = gTrue;
- xMin = obj1.arrayGet(0, &obj2)->getNum();
- obj2.free();
- yMin = obj1.arrayGet(1, &obj2)->getNum();
- obj2.free();
- xMax = obj1.arrayGet(2, &obj2)->getNum();
- obj2.free();
- yMax = obj1.arrayGet(3, &obj2)->getNum();
- obj2.free();
- } else {
- error(-1, "Bad BBox in shading dictionary");
- }
- }
- obj1.free();
-
- return gTrue;
-}
-
-//------------------------------------------------------------------------
-// GfxFunctionShading
-//------------------------------------------------------------------------
-
-GfxFunctionShading::GfxFunctionShading(double x0A, double y0A,
- double x1A, double y1A,
- double *matrixA,
- Function **funcsA, int nFuncsA):
- GfxShading(1)
-{
- int i;
-
- x0 = x0A;
- y0 = y0A;
- x1 = x1A;
- y1 = y1A;
- for (i = 0; i < 6; ++i) {
- matrix[i] = matrixA[i];
- }
- nFuncs = nFuncsA;
- for (i = 0; i < nFuncs; ++i) {
- funcs[i] = funcsA[i];
- }
-}
-
-GfxFunctionShading::GfxFunctionShading(GfxFunctionShading *shading):
- GfxShading(shading)
-{
- int i;
-
- x0 = shading->x0;
- y0 = shading->y0;
- x1 = shading->x1;
- y1 = shading->y1;
- for (i = 0; i < 6; ++i) {
- matrix[i] = shading->matrix[i];
- }
- nFuncs = shading->nFuncs;
- for (i = 0; i < nFuncs; ++i) {
- funcs[i] = shading->funcs[i]->copy();
- }
-}
-
-GfxFunctionShading::~GfxFunctionShading() {
- int i;
-
- for (i = 0; i < nFuncs; ++i) {
- delete funcs[i];
- }
-}
-
-GfxFunctionShading *GfxFunctionShading::parse(Dict *dict) {
- GfxFunctionShading *shading;
- double x0A, y0A, x1A, y1A;
- double matrixA[6];
- Function *funcsA[gfxColorMaxComps];
- int nFuncsA;
- Object obj1, obj2;
- int i;
-
- x0A = y0A = 0;
- x1A = y1A = 1;
- if (dict->lookup("Domain", &obj1)->isArray() &&
- obj1.arrayGetLength() == 4) {
- x0A = obj1.arrayGet(0, &obj2)->getNum();
- obj2.free();
- y0A = obj1.arrayGet(1, &obj2)->getNum();
- obj2.free();
- x1A = obj1.arrayGet(2, &obj2)->getNum();
- obj2.free();
- y1A = obj1.arrayGet(3, &obj2)->getNum();
- obj2.free();
- }
- obj1.free();
-
- matrixA[0] = 1; matrixA[1] = 0;
- matrixA[2] = 0; matrixA[3] = 1;
- matrixA[4] = 0; matrixA[5] = 0;
- if (dict->lookup("Matrix", &obj1)->isArray() &&
- obj1.arrayGetLength() == 6) {
- matrixA[0] = obj1.arrayGet(0, &obj2)->getNum();
- obj2.free();
- matrixA[1] = obj1.arrayGet(1, &obj2)->getNum();
- obj2.free();
- matrixA[2] = obj1.arrayGet(2, &obj2)->getNum();
- obj2.free();
- matrixA[3] = obj1.arrayGet(3, &obj2)->getNum();
- obj2.free();
- matrixA[4] = obj1.arrayGet(4, &obj2)->getNum();
- obj2.free();
- matrixA[5] = obj1.arrayGet(5, &obj2)->getNum();
- obj2.free();
- }
- obj1.free();
-
- dict->lookup("Function", &obj1);
- if (obj1.isArray()) {
- nFuncsA = obj1.arrayGetLength();
- if (nFuncsA > gfxColorMaxComps) {
- error(-1, "Invalid Function array in shading dictionary");
- goto err1;
- }
- for (i = 0; i < nFuncsA; ++i) {
- obj1.arrayGet(i, &obj2);
- if (!(funcsA[i] = Function::parse(&obj2))) {
- goto err2;
- }
- obj2.free();
- }
- } else {
- nFuncsA = 1;
- if (!(funcsA[0] = Function::parse(&obj1))) {
- goto err1;
- }
- }
- obj1.free();
-
- shading = new GfxFunctionShading(x0A, y0A, x1A, y1A, matrixA,
- funcsA, nFuncsA);
- if (!shading->init(dict)) {
- delete shading;
- return NULL;
- }
- return shading;
-
- err2:
- obj2.free();
- err1:
- obj1.free();
- return NULL;
-}
-
-GfxShading *GfxFunctionShading::copy() {
- return new GfxFunctionShading(this);
-}
-
-void GfxFunctionShading::getColor(double x, double y, GfxColor *color) {
- double in[2], out[gfxColorMaxComps];
- int i;
-
- // NB: there can be one function with n outputs or n functions with
- // one output each (where n = number of color components)
- for (i = 0; i < gfxColorMaxComps; ++i) {
- out[i] = 0;
- }
- in[0] = x;
- in[1] = y;
- for (i = 0; i < nFuncs; ++i) {
- funcs[i]->transform(in, &out[i]);
- }
- for (i = 0; i < gfxColorMaxComps; ++i) {
- color->c[i] = dblToCol(out[i]);
- }
-}
-
-//------------------------------------------------------------------------
-// GfxAxialShading
-//------------------------------------------------------------------------
-
-GfxAxialShading::GfxAxialShading(double x0A, double y0A,
- double x1A, double y1A,
- double t0A, double t1A,
- Function **funcsA, int nFuncsA,
- GBool extend0A, GBool extend1A):
- GfxShading(2)
-{
- int i;
-
- x0 = x0A;
- y0 = y0A;
- x1 = x1A;
- y1 = y1A;
- t0 = t0A;
- t1 = t1A;
- nFuncs = nFuncsA;
- for (i = 0; i < nFuncs; ++i) {
- funcs[i] = funcsA[i];
- }
- extend0 = extend0A;
- extend1 = extend1A;
-}
-
-GfxAxialShading::GfxAxialShading(GfxAxialShading *shading):
- GfxShading(shading)
-{
- int i;
-
- x0 = shading->x0;
- y0 = shading->y0;
- x1 = shading->x1;
- y1 = shading->y1;
- t0 = shading->t0;
- y1 = shading->t1;
- nFuncs = shading->nFuncs;
- for (i = 0; i < nFuncs; ++i) {
- funcs[i] = shading->funcs[i]->copy();
- }
- extend0 = shading->extend0;
- extend1 = shading->extend1;
-}
-
-GfxAxialShading::~GfxAxialShading() {
- int i;
-
- for (i = 0; i < nFuncs; ++i) {
- delete funcs[i];
- }
-}
-
-GfxAxialShading *GfxAxialShading::parse(Dict *dict) {
- GfxAxialShading *shading;
- double x0A, y0A, x1A, y1A;
- double t0A, t1A;
- Function *funcsA[gfxColorMaxComps];
- int nFuncsA;
- GBool extend0A, extend1A;
- Object obj1, obj2;
- int i;
-
- x0A = y0A = x1A = y1A = 0;
- if (dict->lookup("Coords", &obj1)->isArray() &&
- obj1.arrayGetLength() == 4) {
- x0A = obj1.arrayGet(0, &obj2)->getNum();
- obj2.free();
- y0A = obj1.arrayGet(1, &obj2)->getNum();
- obj2.free();
- x1A = obj1.arrayGet(2, &obj2)->getNum();
- obj2.free();
- y1A = obj1.arrayGet(3, &obj2)->getNum();
- obj2.free();
- } else {
- error(-1, "Missing or invalid Coords in shading dictionary");
- goto err1;
- }
- obj1.free();
-
- t0A = 0;
- t1A = 1;
- if (dict->lookup("Domain", &obj1)->isArray() &&
- obj1.arrayGetLength() == 2) {
- t0A = obj1.arrayGet(0, &obj2)->getNum();
- obj2.free();
- t1A = obj1.arrayGet(1, &obj2)->getNum();
- obj2.free();
- }
- obj1.free();
-
- dict->lookup("Function", &obj1);
- if (obj1.isArray()) {
- nFuncsA = obj1.arrayGetLength();
- if (nFuncsA > gfxColorMaxComps) {
- error(-1, "Invalid Function array in shading dictionary");
- goto err1;
- }
- for (i = 0; i < nFuncsA; ++i) {
- obj1.arrayGet(i, &obj2);
- if (!(funcsA[i] = Function::parse(&obj2))) {
- obj1.free();
- obj2.free();
- goto err1;
- }
- obj2.free();
- }
- } else {
- nFuncsA = 1;
- if (!(funcsA[0] = Function::parse(&obj1))) {
- obj1.free();
- goto err1;
- }
- }
- obj1.free();
-
- extend0A = extend1A = gFalse;
- if (dict->lookup("Extend", &obj1)->isArray() &&
- obj1.arrayGetLength() == 2) {
- extend0A = obj1.arrayGet(0, &obj2)->getBool();
- obj2.free();
- extend1A = obj1.arrayGet(1, &obj2)->getBool();
- obj2.free();
- }
- obj1.free();
-
- shading = new GfxAxialShading(x0A, y0A, x1A, y1A, t0A, t1A,
- funcsA, nFuncsA, extend0A, extend1A);
- if (!shading->init(dict)) {
- delete shading;
- return NULL;
- }
- return shading;
-
- err1:
- return NULL;
-}
-
-GfxShading *GfxAxialShading::copy() {
- return new GfxAxialShading(this);
-}
-
-void GfxAxialShading::getColor(double t, GfxColor *color) {
- double out[gfxColorMaxComps];
- int i;
-
- // NB: there can be one function with n outputs or n functions with
- // one output each (where n = number of color components)
- for (i = 0; i < gfxColorMaxComps; ++i) {
- out[i] = 0;
- }
- for (i = 0; i < nFuncs; ++i) {
- funcs[i]->transform(&t, &out[i]);
- }
- for (i = 0; i < gfxColorMaxComps; ++i) {
- color->c[i] = dblToCol(out[i]);
- }
-}
-
-//------------------------------------------------------------------------
-// GfxRadialShading
-//------------------------------------------------------------------------
-
-GfxRadialShading::GfxRadialShading(double x0A, double y0A, double r0A,
- double x1A, double y1A, double r1A,
- double t0A, double t1A,
- Function **funcsA, int nFuncsA,
- GBool extend0A, GBool extend1A):
- GfxShading(3)
-{
- int i;
-
- x0 = x0A;
- y0 = y0A;
- r0 = r0A;
- x1 = x1A;
- y1 = y1A;
- r1 = r1A;
- t0 = t0A;
- t1 = t1A;
- nFuncs = nFuncsA;
- for (i = 0; i < nFuncs; ++i) {
- funcs[i] = funcsA[i];
- }
- extend0 = extend0A;
- extend1 = extend1A;
-}
-
-GfxRadialShading::GfxRadialShading(GfxRadialShading *shading):
- GfxShading(shading)
-{
- int i;
-
- x0 = shading->x0;
- y0 = shading->y0;
- r0 = shading->r0;
- x1 = shading->x1;
- y1 = shading->y1;
- r1 = shading->r1;
- t0 = shading->t0;
- y1 = shading->t1;
- nFuncs = shading->nFuncs;
- for (i = 0; i < nFuncs; ++i) {
- funcs[i] = shading->funcs[i]->copy();
- }
- extend0 = shading->extend0;
- extend1 = shading->extend1;
-}
-
-GfxRadialShading::~GfxRadialShading() {
- int i;
-
- for (i = 0; i < nFuncs; ++i) {
- delete funcs[i];
- }
-}
-
-GfxRadialShading *GfxRadialShading::parse(Dict *dict) {
- GfxRadialShading *shading;
- double x0A, y0A, r0A, x1A, y1A, r1A;
- double t0A, t1A;
- Function *funcsA[gfxColorMaxComps];
- int nFuncsA;
- GBool extend0A, extend1A;
- Object obj1, obj2;
- int i;
-
- x0A = y0A = r0A = x1A = y1A = r1A = 0;
- if (dict->lookup("Coords", &obj1)->isArray() &&
- obj1.arrayGetLength() == 6) {
- x0A = obj1.arrayGet(0, &obj2)->getNum();
- obj2.free();
- y0A = obj1.arrayGet(1, &obj2)->getNum();
- obj2.free();
- r0A = obj1.arrayGet(2, &obj2)->getNum();
- obj2.free();
- x1A = obj1.arrayGet(3, &obj2)->getNum();
- obj2.free();
- y1A = obj1.arrayGet(4, &obj2)->getNum();
- obj2.free();
- r1A = obj1.arrayGet(5, &obj2)->getNum();
- obj2.free();
- } else {
- error(-1, "Missing or invalid Coords in shading dictionary");
- goto err1;
- }
- obj1.free();
-
- t0A = 0;
- t1A = 1;
- if (dict->lookup("Domain", &obj1)->isArray() &&
- obj1.arrayGetLength() == 2) {
- t0A = obj1.arrayGet(0, &obj2)->getNum();
- obj2.free();
- t1A = obj1.arrayGet(1, &obj2)->getNum();
- obj2.free();
- }
- obj1.free();
-
- dict->lookup("Function", &obj1);
- if (obj1.isArray()) {
- nFuncsA = obj1.arrayGetLength();
- if (nFuncsA > gfxColorMaxComps) {
- error(-1, "Invalid Function array in shading dictionary");
- goto err1;
- }
- for (i = 0; i < nFuncsA; ++i) {
- obj1.arrayGet(i, &obj2);
- if (!(funcsA[i] = Function::parse(&obj2))) {
- obj1.free();
- obj2.free();
- goto err1;
- }
- obj2.free();
- }
- } else {
- nFuncsA = 1;
- if (!(funcsA[0] = Function::parse(&obj1))) {
- obj1.free();
- goto err1;
- }
- }
- obj1.free();
-
- extend0A = extend1A = gFalse;
- if (dict->lookup("Extend", &obj1)->isArray() &&
- obj1.arrayGetLength() == 2) {
- extend0A = obj1.arrayGet(0, &obj2)->getBool();
- obj2.free();
- extend1A = obj1.arrayGet(1, &obj2)->getBool();
- obj2.free();
- }
- obj1.free();
-
- shading = new GfxRadialShading(x0A, y0A, r0A, x1A, y1A, r1A, t0A, t1A,
- funcsA, nFuncsA, extend0A, extend1A);
- if (!shading->init(dict)) {
- delete shading;
- return NULL;
- }
- return shading;
-
- err1:
- return NULL;
-}
-
-GfxShading *GfxRadialShading::copy() {
- return new GfxRadialShading(this);
-}
-
-void GfxRadialShading::getColor(double t, GfxColor *color) {
- double out[gfxColorMaxComps];
- int i;
-
- // NB: there can be one function with n outputs or n functions with
- // one output each (where n = number of color components)
- for (i = 0; i < gfxColorMaxComps; ++i) {
- out[i] = 0;
- }
- for (i = 0; i < nFuncs; ++i) {
- funcs[i]->transform(&t, &out[i]);
- }
- for (i = 0; i < gfxColorMaxComps; ++i) {
- color->c[i] = dblToCol(out[i]);
- }
-}
-
-//------------------------------------------------------------------------
-// GfxShadingBitBuf
-//------------------------------------------------------------------------
-
-class GfxShadingBitBuf {
-public:
-
- GfxShadingBitBuf(Stream *strA);
- ~GfxShadingBitBuf();
- GBool getBits(int n, Guint *val);
- void flushBits();
-
-private:
-
- Stream *str;
- int bitBuf;
- int nBits;
-};
-
-GfxShadingBitBuf::GfxShadingBitBuf(Stream *strA) {
- str = strA;
- str->reset();
- bitBuf = 0;
- nBits = 0;
-}
-
-GfxShadingBitBuf::~GfxShadingBitBuf() {
- str->close();
-}
-
-GBool GfxShadingBitBuf::getBits(int n, Guint *val) {
- int x;
-
- if (nBits >= n) {
- x = (bitBuf >> (nBits - n)) & ((1 << n) - 1);
- nBits -= n;
- } else {
- x = 0;
- if (nBits > 0) {
- x = bitBuf & ((1 << nBits) - 1);
- n -= nBits;
- nBits = 0;
- }
- while (n > 0) {
- if ((bitBuf = str->getChar()) == EOF) {
- nBits = 0;
- return gFalse;
- }
- if (n >= 8) {
- x = (x << 8) | bitBuf;
- n -= 8;
- } else {
- x = (x << n) | (bitBuf >> (8 - n));
- nBits = 8 - n;
- n = 0;
- }
- }
- }
- *val = x;
- return gTrue;
-}
-
-void GfxShadingBitBuf::flushBits() {
- bitBuf = 0;
- nBits = 0;
-}
-
-//------------------------------------------------------------------------
-// GfxGouraudTriangleShading
-//------------------------------------------------------------------------
-
-GfxGouraudTriangleShading::GfxGouraudTriangleShading(
- int typeA,
- GfxGouraudVertex *verticesA, int nVerticesA,
- int (*trianglesA)[3], int nTrianglesA,
- Function **funcsA, int nFuncsA):
- GfxShading(typeA)
-{
- int i;
-
- vertices = verticesA;
- nVertices = nVerticesA;
- triangles = trianglesA;
- nTriangles = nTrianglesA;
- nFuncs = nFuncsA;
- for (i = 0; i < nFuncs; ++i) {
- funcs[i] = funcsA[i];
- }
-}
-
-GfxGouraudTriangleShading::GfxGouraudTriangleShading(
- GfxGouraudTriangleShading *shading):
- GfxShading(shading)
-{
- int i;
-
- nVertices = shading->nVertices;
- vertices = (GfxGouraudVertex *)gmallocn(nVertices, sizeof(GfxGouraudVertex));
- memcpy(vertices, shading->vertices, nVertices * sizeof(GfxGouraudVertex));
- nTriangles = shading->nTriangles;
- triangles = (int (*)[3])gmallocn(nTriangles * 3, sizeof(int));
- memcpy(triangles, shading->triangles, nTriangles * 3 * sizeof(int));
- nFuncs = shading->nFuncs;
- for (i = 0; i < nFuncs; ++i) {
- funcs[i] = shading->funcs[i]->copy();
- }
-}
-
-GfxGouraudTriangleShading::~GfxGouraudTriangleShading() {
- int i;
-
- gfree(vertices);
- gfree(triangles);
- for (i = 0; i < nFuncs; ++i) {
- delete funcs[i];
- }
-}
-
-GfxGouraudTriangleShading *GfxGouraudTriangleShading::parse(int typeA,
- Dict *dict,
- Stream *str) {
- GfxGouraudTriangleShading *shading;
- Function *funcsA[gfxColorMaxComps];
- int nFuncsA;
- int coordBits, compBits, flagBits, vertsPerRow, nRows;
- double xMin, xMax, yMin, yMax;
- double cMin[gfxColorMaxComps], cMax[gfxColorMaxComps];
- double xMul, yMul;
- double cMul[gfxColorMaxComps];
- GfxGouraudVertex *verticesA;
- int (*trianglesA)[3];
- int nComps, nVerticesA, nTrianglesA, vertSize, triSize;
- Guint x, y, flag;
- Guint c[gfxColorMaxComps];
- GfxShadingBitBuf *bitBuf;
- Object obj1, obj2;
- int i, j, k, state;
-
- if (dict->lookup("BitsPerCoordinate", &obj1)->isInt()) {
- coordBits = obj1.getInt();
- } else {
- error(-1, "Missing or invalid BitsPerCoordinate in shading dictionary");
- goto err2;
- }
- obj1.free();
- if (dict->lookup("BitsPerComponent", &obj1)->isInt()) {
- compBits = obj1.getInt();
- } else {
- error(-1, "Missing or invalid BitsPerComponent in shading dictionary");
- goto err2;
- }
- obj1.free();
- flagBits = vertsPerRow = 0; // make gcc happy
- if (typeA == 4) {
- if (dict->lookup("BitsPerFlag", &obj1)->isInt()) {
- flagBits = obj1.getInt();
- } else {
- error(-1, "Missing or invalid BitsPerFlag in shading dictionary");
- goto err2;
- }
- obj1.free();
- } else {
- if (dict->lookup("VerticesPerRow", &obj1)->isInt()) {
- vertsPerRow = obj1.getInt();
- } else {
- error(-1, "Missing or invalid VerticesPerRow in shading dictionary");
- goto err2;
- }
- obj1.free();
- }
- if (dict->lookup("Decode", &obj1)->isArray() &&
- obj1.arrayGetLength() >= 6) {
- xMin = obj1.arrayGet(0, &obj2)->getNum();
- obj2.free();
- xMax = obj1.arrayGet(1, &obj2)->getNum();
- obj2.free();
- xMul = (xMax - xMin) / (pow(2.0, coordBits) - 1);
- yMin = obj1.arrayGet(2, &obj2)->getNum();
- obj2.free();
- yMax = obj1.arrayGet(3, &obj2)->getNum();
- obj2.free();
- yMul = (yMax - yMin) / (pow(2.0, coordBits) - 1);
- for (i = 0; 5 + 2*i < obj1.arrayGetLength() && i < gfxColorMaxComps; ++i) {
- cMin[i] = obj1.arrayGet(4 + 2*i, &obj2)->getNum();
- obj2.free();
- cMax[i] = obj1.arrayGet(5 + 2*i, &obj2)->getNum();
- obj2.free();
- cMul[i] = (cMax[i] - cMin[i]) / (double)((1 << compBits) - 1);
- }
- nComps = i;
- } else {
- error(-1, "Missing or invalid Decode array in shading dictionary");
- goto err2;
- }
- obj1.free();
-
- if (!dict->lookup("Function", &obj1)->isNull()) {
- if (obj1.isArray()) {
- nFuncsA = obj1.arrayGetLength();
- if (nFuncsA > gfxColorMaxComps) {
- error(-1, "Invalid Function array in shading dictionary");
- goto err1;
- }
- for (i = 0; i < nFuncsA; ++i) {
- obj1.arrayGet(i, &obj2);
- if (!(funcsA[i] = Function::parse(&obj2))) {
- obj1.free();
- obj2.free();
- goto err1;
- }
- obj2.free();
- }
- } else {
- nFuncsA = 1;
- if (!(funcsA[0] = Function::parse(&obj1))) {
- obj1.free();
- goto err1;
- }
- }
- } else {
- nFuncsA = 0;
- }
- obj1.free();
-
- nVerticesA = nTrianglesA = 0;
- verticesA = NULL;
- trianglesA = NULL;
- vertSize = triSize = 0;
- state = 0;
- flag = 0; // make gcc happy
- bitBuf = new GfxShadingBitBuf(str);
- while (1) {
- if (typeA == 4) {
- if (!bitBuf->getBits(flagBits, &flag)) {
- break;
- }
- }
- if (!bitBuf->getBits(coordBits, &x) ||
- !bitBuf->getBits(coordBits, &y)) {
- break;
- }
- for (i = 0; i < nComps; ++i) {
- if (!bitBuf->getBits(compBits, &c[i])) {
- break;
- }
- }
- if (i < nComps) {
- break;
- }
- if (nVerticesA == vertSize) {
- vertSize = (vertSize == 0) ? 16 : 2 * vertSize;
- verticesA = (GfxGouraudVertex *)
- greallocn(verticesA, vertSize, sizeof(GfxGouraudVertex));
- }
- verticesA[nVerticesA].x = xMin + xMul * (double)x;
- verticesA[nVerticesA].y = yMin + yMul * (double)y;
- for (i = 0; i < nComps; ++i) {
- verticesA[nVerticesA].color.c[i] =
- dblToCol(cMin[i] + cMul[i] * (double)c[i]);
- }
- ++nVerticesA;
- bitBuf->flushBits();
- if (typeA == 4) {
- if (state == 0 || state == 1) {
- ++state;
- } else if (state == 2 || flag > 0) {
- if (nTrianglesA == triSize) {
- triSize = (triSize == 0) ? 16 : 2 * triSize;
- trianglesA = (int (*)[3])
- greallocn(trianglesA, triSize * 3, sizeof(int));
- }
- if (state == 2) {
- trianglesA[nTrianglesA][0] = nVerticesA - 3;
- trianglesA[nTrianglesA][1] = nVerticesA - 2;
- trianglesA[nTrianglesA][2] = nVerticesA - 1;
- ++state;
- } else if (flag == 1) {
- trianglesA[nTrianglesA][0] = trianglesA[nTrianglesA - 1][1];
- trianglesA[nTrianglesA][1] = trianglesA[nTrianglesA - 1][2];
- trianglesA[nTrianglesA][2] = nVerticesA - 1;
- } else { // flag == 2
- trianglesA[nTrianglesA][0] = trianglesA[nTrianglesA - 1][0];
- trianglesA[nTrianglesA][1] = trianglesA[nTrianglesA - 1][2];
- trianglesA[nTrianglesA][2] = nVerticesA - 1;
- }
- ++nTrianglesA;
- } else { // state == 3 && flag == 0
- state = 1;
- }
- }
- }
- delete bitBuf;
- if (typeA == 5) {
- nRows = nVerticesA / vertsPerRow;
- nTrianglesA = (nRows - 1) * 2 * (vertsPerRow - 1);
- trianglesA = (int (*)[3])gmallocn(nTrianglesA * 3, sizeof(int));
- k = 0;
- for (i = 0; i < nRows - 1; ++i) {
- for (j = 0; j < vertsPerRow - 1; ++j) {
- trianglesA[k][0] = i * vertsPerRow + j;
- trianglesA[k][1] = i * vertsPerRow + j+1;
- trianglesA[k][2] = (i+1) * vertsPerRow + j;
- ++k;
- trianglesA[k][0] = i * vertsPerRow + j+1;
- trianglesA[k][1] = (i+1) * vertsPerRow + j;
- trianglesA[k][2] = (i+1) * vertsPerRow + j+1;
- ++k;
- }
- }
- }
-
- shading = new GfxGouraudTriangleShading(typeA, verticesA, nVerticesA,
- trianglesA, nTrianglesA,
- funcsA, nFuncsA);
- if (!shading->init(dict)) {
- delete shading;
- return NULL;
- }
- return shading;
-
- err2:
- obj1.free();
- err1:
- return NULL;
-}
-
-GfxShading *GfxGouraudTriangleShading::copy() {
- return new GfxGouraudTriangleShading(this);
-}
-
-void GfxGouraudTriangleShading::getTriangle(
- int i,
- double *x0, double *y0, GfxColor *color0,
- double *x1, double *y1, GfxColor *color1,
- double *x2, double *y2, GfxColor *color2) {
- double in;
- double out[gfxColorMaxComps];
- int v, j;
-
- v = triangles[i][0];
- *x0 = vertices[v].x;
- *y0 = vertices[v].y;
- if (nFuncs > 0) {
- in = colToDbl(vertices[v].color.c[0]);
- for (j = 0; j < nFuncs; ++j) {
- funcs[j]->transform(&in, &out[j]);
- }
- for (j = 0; j < gfxColorMaxComps; ++j) {
- color0->c[j] = dblToCol(out[j]);
- }
- } else {
- *color0 = vertices[v].color;
- }
- v = triangles[i][1];
- *x1 = vertices[v].x;
- *y1 = vertices[v].y;
- if (nFuncs > 0) {
- in = colToDbl(vertices[v].color.c[0]);
- for (j = 0; j < nFuncs; ++j) {
- funcs[j]->transform(&in, &out[j]);
- }
- for (j = 0; j < gfxColorMaxComps; ++j) {
- color1->c[j] = dblToCol(out[j]);
- }
- } else {
- *color1 = vertices[v].color;
- }
- v = triangles[i][2];
- *x2 = vertices[v].x;
- *y2 = vertices[v].y;
- if (nFuncs > 0) {
- in = colToDbl(vertices[v].color.c[0]);
- for (j = 0; j < nFuncs; ++j) {
- funcs[j]->transform(&in, &out[j]);
- }
- for (j = 0; j < gfxColorMaxComps; ++j) {
- color2->c[j] = dblToCol(out[j]);
- }
- } else {
- *color2 = vertices[v].color;
- }
-}
-
-//------------------------------------------------------------------------
-// GfxPatchMeshShading
-//------------------------------------------------------------------------
-
-GfxPatchMeshShading::GfxPatchMeshShading(int typeA,
- GfxPatch *patchesA, int nPatchesA,
- Function **funcsA, int nFuncsA):
- GfxShading(typeA)
-{
- int i;
-
- patches = patchesA;
- nPatches = nPatchesA;
- nFuncs = nFuncsA;
- for (i = 0; i < nFuncs; ++i) {
- funcs[i] = funcsA[i];
- }
-}
-
-GfxPatchMeshShading::GfxPatchMeshShading(GfxPatchMeshShading *shading):
- GfxShading(shading)
-{
- int i;
-
- nPatches = shading->nPatches;
- patches = (GfxPatch *)gmallocn(nPatches, sizeof(GfxPatch));
- memcpy(patches, shading->patches, nPatches * sizeof(GfxPatch));
- nFuncs = shading->nFuncs;
- for (i = 0; i < nFuncs; ++i) {
- funcs[i] = shading->funcs[i]->copy();
- }
-}
-
-GfxPatchMeshShading::~GfxPatchMeshShading() {
- int i;
-
- gfree(patches);
- for (i = 0; i < nFuncs; ++i) {
- delete funcs[i];
- }
-}
-
-GfxPatchMeshShading *GfxPatchMeshShading::parse(int typeA, Dict *dict,
- Stream *str) {
- GfxPatchMeshShading *shading;
- Function *funcsA[gfxColorMaxComps];
- int nFuncsA;
- int coordBits, compBits, flagBits;
- double xMin, xMax, yMin, yMax;
- double cMin[gfxColorMaxComps], cMax[gfxColorMaxComps];
- double xMul, yMul;
- double cMul[gfxColorMaxComps];
- GfxPatch *patchesA, *p;
- int nComps, nPatchesA, patchesSize, nPts, nColors;
- Guint flag;
- double x[16], y[16];
- Guint xi, yi;
- GfxColorComp c[4][gfxColorMaxComps];
- Guint ci[4];
- GfxShadingBitBuf *bitBuf;
- Object obj1, obj2;
- int i, j;
-
- if (dict->lookup("BitsPerCoordinate", &obj1)->isInt()) {
- coordBits = obj1.getInt();
- } else {
- error(-1, "Missing or invalid BitsPerCoordinate in shading dictionary");
- goto err2;
- }
- obj1.free();
- if (dict->lookup("BitsPerComponent", &obj1)->isInt()) {
- compBits = obj1.getInt();
- } else {
- error(-1, "Missing or invalid BitsPerComponent in shading dictionary");
- goto err2;
- }
- obj1.free();
- if (dict->lookup("BitsPerFlag", &obj1)->isInt()) {
- flagBits = obj1.getInt();
- } else {
- error(-1, "Missing or invalid BitsPerFlag in shading dictionary");
- goto err2;
- }
- obj1.free();
- if (dict->lookup("Decode", &obj1)->isArray() &&
- obj1.arrayGetLength() >= 6) {
- xMin = obj1.arrayGet(0, &obj2)->getNum();
- obj2.free();
- xMax = obj1.arrayGet(1, &obj2)->getNum();
- obj2.free();
- xMul = (xMax - xMin) / (pow(2.0, coordBits) - 1);
- yMin = obj1.arrayGet(2, &obj2)->getNum();
- obj2.free();
- yMax = obj1.arrayGet(3, &obj2)->getNum();
- obj2.free();
- yMul = (yMax - yMin) / (pow(2.0, coordBits) - 1);
- for (i = 0; 5 + 2*i < obj1.arrayGetLength() && i < gfxColorMaxComps; ++i) {
- cMin[i] = obj1.arrayGet(4 + 2*i, &obj2)->getNum();
- obj2.free();
- cMax[i] = obj1.arrayGet(5 + 2*i, &obj2)->getNum();
- obj2.free();
- cMul[i] = (cMax[i] - cMin[i]) / (double)((1 << compBits) - 1);
- }
- nComps = i;
- } else {
- error(-1, "Missing or invalid Decode array in shading dictionary");
- goto err2;
- }
- obj1.free();
-
- if (!dict->lookup("Function", &obj1)->isNull()) {
- if (obj1.isArray()) {
- nFuncsA = obj1.arrayGetLength();
- if (nFuncsA > gfxColorMaxComps) {
- error(-1, "Invalid Function array in shading dictionary");
- goto err1;
- }
- for (i = 0; i < nFuncsA; ++i) {
- obj1.arrayGet(i, &obj2);
- if (!(funcsA[i] = Function::parse(&obj2))) {
- obj1.free();
- obj2.free();
- goto err1;
- }
- obj2.free();
- }
- } else {
- nFuncsA = 1;
- if (!(funcsA[0] = Function::parse(&obj1))) {
- obj1.free();
- goto err1;
- }
- }
- } else {
- nFuncsA = 0;
- }
- obj1.free();
-
- nPatchesA = 0;
- patchesA = NULL;
- patchesSize = 0;
- bitBuf = new GfxShadingBitBuf(str);
- while (1) {
- if (!bitBuf->getBits(flagBits, &flag)) {
- break;
- }
- if (typeA == 6) {
- switch (flag) {
- case 0: nPts = 12; nColors = 4; break;
- case 1:
- case 2:
- case 3:
- default: nPts = 8; nColors = 2; break;
- }
- } else {
- switch (flag) {
- case 0: nPts = 16; nColors = 4; break;
- case 1:
- case 2:
- case 3:
- default: nPts = 12; nColors = 2; break;
- }
- }
- for (i = 0; i < nPts; ++i) {
- if (!bitBuf->getBits(coordBits, &xi) ||
- !bitBuf->getBits(coordBits, &yi)) {
- break;
- }
- x[i] = xMin + xMul * (double)xi;
- y[i] = yMin + yMul * (double)yi;
- }
- if (i < nPts) {
- break;
- }
- for (i = 0; i < nColors; ++i) {
- for (j = 0; j < nComps; ++j) {
- if (!bitBuf->getBits(compBits, &ci[j])) {
- break;
- }
- c[i][j] = dblToCol(cMin[j] + cMul[j] * (double)ci[j]);
- }
- if (j < nComps) {
- break;
- }
- }
- if (i < nColors) {
- break;
- }
- if (nPatchesA == patchesSize) {
- patchesSize = (patchesSize == 0) ? 16 : 2 * patchesSize;
- patchesA = (GfxPatch *)greallocn(patchesA,
- patchesSize, sizeof(GfxPatch));
- }
- p = &patchesA[nPatchesA];
- if (typeA == 6) {
- switch (flag) {
- case 0:
- p->x[0][0] = x[0];
- p->y[0][0] = y[0];
- p->x[0][1] = x[1];
- p->y[0][1] = y[1];
- p->x[0][2] = x[2];
- p->y[0][2] = y[2];
- p->x[0][3] = x[3];
- p->y[0][3] = y[3];
- p->x[1][3] = x[4];
- p->y[1][3] = y[4];
- p->x[2][3] = x[5];
- p->y[2][3] = y[5];
- p->x[3][3] = x[6];
- p->y[3][3] = y[6];
- p->x[3][2] = x[7];
- p->y[3][2] = y[7];
- p->x[3][1] = x[8];
- p->y[3][1] = y[8];
- p->x[3][0] = x[9];
- p->y[3][0] = y[9];
- p->x[2][0] = x[10];
- p->y[2][0] = y[10];
- p->x[1][0] = x[11];
- p->y[1][0] = y[11];
- for (j = 0; j < nComps; ++j) {
- p->color[0][0].c[j] = c[0][j];
- p->color[0][1].c[j] = c[1][j];
- p->color[1][1].c[j] = c[2][j];
- p->color[1][0].c[j] = c[3][j];
- }
- break;
- case 1:
- p->x[0][0] = patchesA[nPatchesA-1].x[0][3];
- p->y[0][0] = patchesA[nPatchesA-1].y[0][3];
- p->x[0][1] = patchesA[nPatchesA-1].x[1][3];
- p->y[0][1] = patchesA[nPatchesA-1].y[1][3];
- p->x[0][2] = patchesA[nPatchesA-1].x[2][3];
- p->y[0][2] = patchesA[nPatchesA-1].y[2][3];
- p->x[0][3] = patchesA[nPatchesA-1].x[3][3];
- p->y[0][3] = patchesA[nPatchesA-1].y[3][3];
- p->x[1][3] = x[0];
- p->y[1][3] = y[0];
- p->x[2][3] = x[1];
- p->y[2][3] = y[1];
- p->x[3][3] = x[2];
- p->y[3][3] = y[2];
- p->x[3][2] = x[3];
- p->y[3][2] = y[3];
- p->x[3][1] = x[4];
- p->y[3][1] = y[4];
- p->x[3][0] = x[5];
- p->y[3][0] = y[5];
- p->x[2][0] = x[6];
- p->y[2][0] = y[6];
- p->x[1][0] = x[7];
- p->y[1][0] = y[7];
- for (j = 0; j < nComps; ++j) {
- p->color[0][0].c[j] = patchesA[nPatchesA-1].color[0][1].c[j];
- p->color[0][1].c[j] = patchesA[nPatchesA-1].color[1][1].c[j];
- p->color[1][1].c[j] = c[0][j];
- p->color[1][0].c[j] = c[1][j];
- }
- break;
- case 2:
- p->x[0][0] = patchesA[nPatchesA-1].x[3][3];
- p->y[0][0] = patchesA[nPatchesA-1].y[3][3];
- p->x[0][1] = patchesA[nPatchesA-1].x[3][2];
- p->y[0][1] = patchesA[nPatchesA-1].y[3][2];
- p->x[0][2] = patchesA[nPatchesA-1].x[3][1];
- p->y[0][2] = patchesA[nPatchesA-1].y[3][1];
- p->x[0][3] = patchesA[nPatchesA-1].x[3][0];
- p->y[0][3] = patchesA[nPatchesA-1].y[3][0];
- p->x[1][3] = x[0];
- p->y[1][3] = y[0];
- p->x[2][3] = x[1];
- p->y[2][3] = y[1];
- p->x[3][3] = x[2];
- p->y[3][3] = y[2];
- p->x[3][2] = x[3];
- p->y[3][2] = y[3];
- p->x[3][1] = x[4];
- p->y[3][1] = y[4];
- p->x[3][0] = x[5];
- p->y[3][0] = y[5];
- p->x[2][0] = x[6];
- p->y[2][0] = y[6];
- p->x[1][0] = x[7];
- p->y[1][0] = y[7];
- for (j = 0; j < nComps; ++j) {
- p->color[0][0].c[j] = patchesA[nPatchesA-1].color[1][1].c[j];
- p->color[0][1].c[j] = patchesA[nPatchesA-1].color[1][0].c[j];
- p->color[1][1].c[j] = c[0][j];
- p->color[1][0].c[j] = c[1][j];
- }
- break;
- case 3:
- p->x[0][0] = patchesA[nPatchesA-1].x[3][0];
- p->y[0][0] = patchesA[nPatchesA-1].y[3][0];
- p->x[0][1] = patchesA[nPatchesA-1].x[2][0];
- p->y[0][1] = patchesA[nPatchesA-1].y[2][0];
- p->x[0][2] = patchesA[nPatchesA-1].x[1][0];
- p->y[0][2] = patchesA[nPatchesA-1].y[1][0];
- p->x[0][3] = patchesA[nPatchesA-1].x[0][0];
- p->y[0][3] = patchesA[nPatchesA-1].y[0][0];
- p->x[1][3] = x[0];
- p->y[1][3] = y[0];
- p->x[2][3] = x[1];
- p->y[2][3] = y[1];
- p->x[3][3] = x[2];
- p->y[3][3] = y[2];
- p->x[3][2] = x[3];
- p->y[3][2] = y[3];
- p->x[3][1] = x[4];
- p->y[3][1] = y[4];
- p->x[3][0] = x[5];
- p->y[3][0] = y[5];
- p->x[2][0] = x[6];
- p->y[2][0] = y[6];
- p->x[1][0] = x[7];
- p->y[1][0] = y[7];
- for (j = 0; j < nComps; ++j) {
- p->color[0][1].c[j] = patchesA[nPatchesA-1].color[1][0].c[j];
- p->color[0][1].c[j] = patchesA[nPatchesA-1].color[0][0].c[j];
- p->color[1][1].c[j] = c[0][j];
- p->color[1][0].c[j] = c[1][j];
- }
- break;
- }
- } else {
- switch (flag) {
- case 0:
- p->x[0][0] = x[0];
- p->y[0][0] = y[0];
- p->x[0][1] = x[1];
- p->y[0][1] = y[1];
- p->x[0][2] = x[2];
- p->y[0][2] = y[2];
- p->x[0][3] = x[3];
- p->y[0][3] = y[3];
- p->x[1][3] = x[4];
- p->y[1][3] = y[4];
- p->x[2][3] = x[5];
- p->y[2][3] = y[5];
- p->x[3][3] = x[6];
- p->y[3][3] = y[6];
- p->x[3][2] = x[7];
- p->y[3][2] = y[7];
- p->x[3][1] = x[8];
- p->y[3][1] = y[8];
- p->x[3][0] = x[9];
- p->y[3][0] = y[9];
- p->x[2][0] = x[10];
- p->y[2][0] = y[10];
- p->x[1][0] = x[11];
- p->y[1][0] = y[11];
- p->x[1][1] = x[12];
- p->y[1][1] = y[12];
- p->x[1][2] = x[13];
- p->y[1][2] = y[13];
- p->x[2][2] = x[14];
- p->y[2][2] = y[14];
- p->x[2][1] = x[15];
- p->y[2][1] = y[15];
- for (j = 0; j < nComps; ++j) {
- p->color[0][0].c[j] = c[0][j];
- p->color[0][1].c[j] = c[1][j];
- p->color[1][1].c[j] = c[2][j];
- p->color[1][0].c[j] = c[3][j];
- }
- break;
- case 1:
- p->x[0][0] = patchesA[nPatchesA-1].x[0][3];
- p->y[0][0] = patchesA[nPatchesA-1].y[0][3];
- p->x[0][1] = patchesA[nPatchesA-1].x[1][3];
- p->y[0][1] = patchesA[nPatchesA-1].y[1][3];
- p->x[0][2] = patchesA[nPatchesA-1].x[2][3];
- p->y[0][2] = patchesA[nPatchesA-1].y[2][3];
- p->x[0][3] = patchesA[nPatchesA-1].x[3][3];
- p->y[0][3] = patchesA[nPatchesA-1].y[3][3];
- p->x[1][3] = x[0];
- p->y[1][3] = y[0];
- p->x[2][3] = x[1];
- p->y[2][3] = y[1];
- p->x[3][3] = x[2];
- p->y[3][3] = y[2];
- p->x[3][2] = x[3];
- p->y[3][2] = y[3];
- p->x[3][1] = x[4];
- p->y[3][1] = y[4];
- p->x[3][0] = x[5];
- p->y[3][0] = y[5];
- p->x[2][0] = x[6];
- p->y[2][0] = y[6];
- p->x[1][0] = x[7];
- p->y[1][0] = y[7];
- p->x[1][1] = x[8];
- p->y[1][1] = y[8];
- p->x[1][2] = x[9];
- p->y[1][2] = y[9];
- p->x[2][2] = x[10];
- p->y[2][2] = y[10];
- p->x[2][1] = x[11];
- p->y[2][1] = y[11];
- for (j = 0; j < nComps; ++j) {
- p->color[0][0].c[j] = patchesA[nPatchesA-1].color[0][1].c[j];
- p->color[0][1].c[j] = patchesA[nPatchesA-1].color[1][1].c[j];
- p->color[1][1].c[j] = c[0][j];
- p->color[1][0].c[j] = c[1][j];
- }
- break;
- case 2:
- p->x[0][0] = patchesA[nPatchesA-1].x[3][3];
- p->y[0][0] = patchesA[nPatchesA-1].y[3][3];
- p->x[0][1] = patchesA[nPatchesA-1].x[3][2];
- p->y[0][1] = patchesA[nPatchesA-1].y[3][2];
- p->x[0][2] = patchesA[nPatchesA-1].x[3][1];
- p->y[0][2] = patchesA[nPatchesA-1].y[3][1];
- p->x[0][3] = patchesA[nPatchesA-1].x[3][0];
- p->y[0][3] = patchesA[nPatchesA-1].y[3][0];
- p->x[1][3] = x[0];
- p->y[1][3] = y[0];
- p->x[2][3] = x[1];
- p->y[2][3] = y[1];
- p->x[3][3] = x[2];
- p->y[3][3] = y[2];
- p->x[3][2] = x[3];
- p->y[3][2] = y[3];
- p->x[3][1] = x[4];
- p->y[3][1] = y[4];
- p->x[3][0] = x[5];
- p->y[3][0] = y[5];
- p->x[2][0] = x[6];
- p->y[2][0] = y[6];
- p->x[1][0] = x[7];
- p->y[1][0] = y[7];
- p->x[1][1] = x[8];
- p->y[1][1] = y[8];
- p->x[1][2] = x[9];
- p->y[1][2] = y[9];
- p->x[2][2] = x[10];
- p->y[2][2] = y[10];
- p->x[2][1] = x[11];
- p->y[2][1] = y[11];
- for (j = 0; j < nComps; ++j) {
- p->color[0][0].c[j] = patchesA[nPatchesA-1].color[1][1].c[j];
- p->color[0][1].c[j] = patchesA[nPatchesA-1].color[1][0].c[j];
- p->color[1][1].c[j] = c[0][j];
- p->color[1][0].c[j] = c[1][j];
- }
- break;
- case 3:
- p->x[0][0] = patchesA[nPatchesA-1].x[3][0];
- p->y[0][0] = patchesA[nPatchesA-1].y[3][0];
- p->x[0][1] = patchesA[nPatchesA-1].x[2][0];
- p->y[0][1] = patchesA[nPatchesA-1].y[2][0];
- p->x[0][2] = patchesA[nPatchesA-1].x[1][0];
- p->y[0][2] = patchesA[nPatchesA-1].y[1][0];
- p->x[0][3] = patchesA[nPatchesA-1].x[0][0];
- p->y[0][3] = patchesA[nPatchesA-1].y[0][0];
- p->x[1][3] = x[0];
- p->y[1][3] = y[0];
- p->x[2][3] = x[1];
- p->y[2][3] = y[1];
- p->x[3][3] = x[2];
- p->y[3][3] = y[2];
- p->x[3][2] = x[3];
- p->y[3][2] = y[3];
- p->x[3][1] = x[4];
- p->y[3][1] = y[4];
- p->x[3][0] = x[5];
- p->y[3][0] = y[5];
- p->x[2][0] = x[6];
- p->y[2][0] = y[6];
- p->x[1][0] = x[7];
- p->y[1][0] = y[7];
- p->x[1][1] = x[8];
- p->y[1][1] = y[8];
- p->x[1][2] = x[9];
- p->y[1][2] = y[9];
- p->x[2][2] = x[10];
- p->y[2][2] = y[10];
- p->x[2][1] = x[11];
- p->y[2][1] = y[11];
- for (j = 0; j < nComps; ++j) {
- p->color[0][0].c[j] = patchesA[nPatchesA-1].color[1][0].c[j];
- p->color[0][1].c[j] = patchesA[nPatchesA-1].color[0][0].c[j];
- p->color[1][1].c[j] = c[0][j];
- p->color[1][0].c[j] = c[1][j];
- }
- break;
- }
- }
- ++nPatchesA;
- bitBuf->flushBits();
- }
- delete bitBuf;
-
- if (typeA == 6) {
- for (i = 0; i < nPatchesA; ++i) {
- p = &patchesA[i];
- p->x[1][1] = (-4 * p->x[0][0]
- +6 * (p->x[0][1] + p->x[1][0])
- -2 * (p->x[0][3] + p->x[3][0])
- +3 * (p->x[3][1] + p->x[1][3])
- - p->x[3][3]) / 9;
- p->y[1][1] = (-4 * p->y[0][0]
- +6 * (p->y[0][1] + p->y[1][0])
- -2 * (p->y[0][3] + p->y[3][0])
- +3 * (p->y[3][1] + p->y[1][3])
- - p->y[3][3]) / 9;
- p->x[1][2] = (-4 * p->x[0][3]
- +6 * (p->x[0][2] + p->x[1][3])
- -2 * (p->x[0][0] + p->x[3][3])
- +3 * (p->x[3][2] + p->x[1][0])
- - p->x[3][0]) / 9;
- p->y[1][2] = (-4 * p->y[0][3]
- +6 * (p->y[0][2] + p->y[1][3])
- -2 * (p->y[0][0] + p->y[3][3])
- +3 * (p->y[3][2] + p->y[1][0])
- - p->y[3][0]) / 9;
- p->x[2][1] = (-4 * p->x[3][0]
- +6 * (p->x[3][1] + p->x[2][0])
- -2 * (p->x[3][3] + p->x[0][0])
- +3 * (p->x[0][1] + p->x[2][3])
- - p->x[0][3]) / 9;
- p->y[2][1] = (-4 * p->y[3][0]
- +6 * (p->y[3][1] + p->y[2][0])
- -2 * (p->y[3][3] + p->y[0][0])
- +3 * (p->y[0][1] + p->y[2][3])
- - p->y[0][3]) / 9;
- p->x[2][2] = (-4 * p->x[3][3]
- +6 * (p->x[3][2] + p->x[2][3])
- -2 * (p->x[3][0] + p->x[0][3])
- +3 * (p->x[0][2] + p->x[2][0])
- - p->x[0][0]) / 9;
- p->y[2][2] = (-4 * p->y[3][3]
- +6 * (p->y[3][2] + p->y[2][3])
- -2 * (p->y[3][0] + p->y[0][3])
- +3 * (p->y[0][2] + p->y[2][0])
- - p->y[0][0]) / 9;
- }
- }
-
- shading = new GfxPatchMeshShading(typeA, patchesA, nPatchesA,
- funcsA, nFuncsA);
- if (!shading->init(dict)) {
- delete shading;
- return NULL;
- }
- return shading;
-
- err2:
- obj1.free();
- err1:
- return NULL;
-}
-
-GfxShading *GfxPatchMeshShading::copy() {
- return new GfxPatchMeshShading(this);
-}
-
-//------------------------------------------------------------------------
-// GfxImageColorMap
-//------------------------------------------------------------------------
-
-GfxImageColorMap::GfxImageColorMap(int bitsA, Object *decode,
- GfxColorSpace *colorSpaceA) {
- GfxIndexedColorSpace *indexedCS;
- GfxSeparationColorSpace *sepCS;
- int maxPixel, indexHigh;
- int maxPixelForAlloc;
- Guchar *lookup2;
- Function *sepFunc;
- Object obj;
- double x[gfxColorMaxComps];
- double y[gfxColorMaxComps];
- int i, j, k;
-
- ok = gTrue;
-
- // bits per component and color space
- bits = bitsA;
- maxPixel = (1 << bits) - 1;
- maxPixelForAlloc = (1 << (bits>8?bits:8));
- colorSpace = colorSpaceA;
-
- // get decode map
- if (decode->isNull()) {
- nComps = colorSpace->getNComps();
- colorSpace->getDefaultRanges(decodeLow, decodeRange, maxPixel);
- } else if (decode->isArray()) {
- nComps = decode->arrayGetLength() / 2;
- if (nComps != colorSpace->getNComps()) {
- goto err1;
- }
- for (i = 0; i < nComps; ++i) {
- decode->arrayGet(2*i, &obj);
- if (!obj.isNum()) {
- goto err2;
- }
- decodeLow[i] = obj.getNum();
- obj.free();
- decode->arrayGet(2*i+1, &obj);
- if (!obj.isNum()) {
- goto err2;
- }
- decodeRange[i] = obj.getNum() - decodeLow[i];
- obj.free();
- }
- } else {
- goto err1;
- }
-
- // Construct a lookup table -- this stores pre-computed decoded
- // values for each component, i.e., the result of applying the
- // decode mapping to each possible image pixel component value.
- //
- // Optimization: for Indexed and Separation color spaces (which have
- // only one component), we store color values in the lookup table
- // rather than component values.
- for (k = 0; k < gfxColorMaxComps; ++k) {
- lookup[k] = NULL;
- }
- colorSpace2 = NULL;
- nComps2 = 0;
- if (colorSpace->getMode() == csIndexed) {
- // Note that indexHigh may not be the same as maxPixel --
- // Distiller will remove unused palette entries, resulting in
- // indexHigh < maxPixel.
- indexedCS = (GfxIndexedColorSpace *)colorSpace;
- colorSpace2 = indexedCS->getBase();
- indexHigh = indexedCS->getIndexHigh();
- nComps2 = colorSpace2->getNComps();
- lookup2 = indexedCS->getLookup();
- colorSpace2->getDefaultRanges(x, y, indexHigh);
- for (k = 0; k < nComps2; ++k) {
- lookup[k] = (GfxColorComp *)gmallocn(maxPixelForAlloc + 1,
- sizeof(GfxColorComp));
- for (i = 0; i <= maxPixel; ++i) {
- j = (int)(decodeLow[0] + (i * decodeRange[0]) / maxPixel + 0.5);
- if (j < 0) {
- j = 0;
- } else if (j > indexHigh) {
- j = indexHigh;
- }
- lookup[k][i] =
- dblToCol(x[k] + (lookup2[j*nComps2 + k] / 255.0) * y[k]);
- }
- }
- } else if (colorSpace->getMode() == csSeparation) {
- sepCS = (GfxSeparationColorSpace *)colorSpace;
- colorSpace2 = sepCS->getAlt();
- nComps2 = colorSpace2->getNComps();
- sepFunc = sepCS->getFunc();
- for (k = 0; k < nComps2; ++k) {
- lookup[k] = (GfxColorComp *)gmallocn(maxPixelForAlloc + 1,
- sizeof(GfxColorComp));
- for (i = 0; i <= maxPixel; ++i) {
- x[0] = decodeLow[0] + (i * decodeRange[0]) / maxPixel;
- sepFunc->transform(x, y);
- lookup[k][i] = dblToCol(y[k]);
- }
- }
- } else {
- for (k = 0; k < nComps; ++k) {
- lookup[k] = (GfxColorComp *)gmallocn(maxPixelForAlloc + 1,
- sizeof(GfxColorComp));
- for (i = 0; i <= maxPixel; ++i) {
- lookup[k][i] = dblToCol(decodeLow[k] +
- (i * decodeRange[k]) / maxPixel);
- }
- }
- }
-
- return;
-
- err2:
- obj.free();
- err1:
- ok = gFalse;
-}
-
-GfxImageColorMap::GfxImageColorMap(GfxImageColorMap *colorMap) {
- int n, i, k;
-
- colorSpace = colorMap->colorSpace->copy();
- bits = colorMap->bits;
- nComps = colorMap->nComps;
- nComps2 = colorMap->nComps2;
- colorSpace2 = NULL;
- for (k = 0; k < gfxColorMaxComps; ++k) {
- lookup[k] = NULL;
- }
- n = 1 << bits;
- if (colorSpace->getMode() == csIndexed) {
- colorSpace2 = ((GfxIndexedColorSpace *)colorSpace)->getBase();
- for (k = 0; k < nComps2; ++k) {
- lookup[k] = (GfxColorComp *)gmallocn(n, sizeof(GfxColorComp));
- memcpy(lookup[k], colorMap->lookup[k], n * sizeof(GfxColorComp));
- }
- } else if (colorSpace->getMode() == csSeparation) {
- colorSpace2 = ((GfxSeparationColorSpace *)colorSpace)->getAlt();
- for (k = 0; k < nComps2; ++k) {
- lookup[k] = (GfxColorComp *)gmallocn(n, sizeof(GfxColorComp));
- memcpy(lookup[k], colorMap->lookup[k], n * sizeof(GfxColorComp));
- }
- } else {
- for (k = 0; k < nComps; ++k) {
- lookup[k] = (GfxColorComp *)gmallocn(n, sizeof(GfxColorComp));
- memcpy(lookup[k], colorMap->lookup[k], n * sizeof(GfxColorComp));
- }
- }
- for (i = 0; i < nComps; ++i) {
- decodeLow[i] = colorMap->decodeLow[i];
- decodeRange[i] = colorMap->decodeRange[i];
- }
- ok = gTrue;
-}
-
-GfxImageColorMap::~GfxImageColorMap() {
- int i;
-
- delete colorSpace;
- for (i = 0; i < gfxColorMaxComps; ++i) {
- gfree(lookup[i]);
- }
-}
-
-void GfxImageColorMap::getGray(Guchar *x, GfxGray *gray) {
- GfxColor color;
- int i;
-
- if (colorSpace2) {
- for (i = 0; i < nComps2; ++i) {
- color.c[i] = lookup[i][x[0]];
- }
- colorSpace2->getGray(&color, gray);
- } else {
- for (i = 0; i < nComps; ++i) {
- color.c[i] = lookup[i][x[i]];
- }
- colorSpace->getGray(&color, gray);
- }
-}
-
-void GfxImageColorMap::getRGB(Guchar *x, GfxRGB *rgb) {
- GfxColor color;
- int i;
-
- if (colorSpace2) {
- for (i = 0; i < nComps2; ++i) {
- color.c[i] = lookup[i][x[0]];
- }
- colorSpace2->getRGB(&color, rgb);
- } else {
- for (i = 0; i < nComps; ++i) {
- color.c[i] = lookup[i][x[i]];
- }
- colorSpace->getRGB(&color, rgb);
- }
-}
-
-void GfxImageColorMap::getCMYK(Guchar *x, GfxCMYK *cmyk) {
- GfxColor color;
- int i;
-
- if (colorSpace2) {
- for (i = 0; i < nComps2; ++i) {
- color.c[i] = lookup[i][x[0]];
- }
- colorSpace2->getCMYK(&color, cmyk);
- } else {
- for (i = 0; i < nComps; ++i) {
- color.c[i] = lookup[i][x[i]];
- }
- colorSpace->getCMYK(&color, cmyk);
- }
-}
-
-void GfxImageColorMap::getColor(Guchar *x, GfxColor *color) {
- int maxPixel, i;
-
- maxPixel = (1 << bits) - 1;
- for (i = 0; i < nComps; ++i) {
- color->c[i] = dblToCol(decodeLow[i] + (x[i] * decodeRange[i]) / maxPixel);
- }
-}
-
-//------------------------------------------------------------------------
-// GfxSubpath and GfxPath
-//------------------------------------------------------------------------
-
-GfxSubpath::GfxSubpath(double x1, double y1) {
- size = 16;
- x = (double *)gmallocn(size, sizeof(double));
- y = (double *)gmallocn(size, sizeof(double));
- curve = (GBool *)gmallocn(size, sizeof(GBool));
- n = 1;
- x[0] = x1;
- y[0] = y1;
- curve[0] = gFalse;
- closed = gFalse;
-}
-
-GfxSubpath::~GfxSubpath() {
- gfree(x);
- gfree(y);
- gfree(curve);
-}
-
-// Used for copy().
-GfxSubpath::GfxSubpath(GfxSubpath *subpath) {
- size = subpath->size;
- n = subpath->n;
- x = (double *)gmallocn(size, sizeof(double));
- y = (double *)gmallocn(size, sizeof(double));
- curve = (GBool *)gmallocn(size, sizeof(GBool));
- memcpy(x, subpath->x, n * sizeof(double));
- memcpy(y, subpath->y, n * sizeof(double));
- memcpy(curve, subpath->curve, n * sizeof(GBool));
- closed = subpath->closed;
-}
-
-void GfxSubpath::lineTo(double x1, double y1) {
- if (n >= size) {
- size += 16;
- x = (double *)greallocn(x, size, sizeof(double));
- y = (double *)greallocn(y, size, sizeof(double));
- curve = (GBool *)greallocn(curve, size, sizeof(GBool));
- }
- x[n] = x1;
- y[n] = y1;
- curve[n] = gFalse;
- ++n;
-}
-
-void GfxSubpath::curveTo(double x1, double y1, double x2, double y2,
- double x3, double y3) {
- if (n+3 > size) {
- size += 16;
- x = (double *)greallocn(x, size, sizeof(double));
- y = (double *)greallocn(y, size, sizeof(double));
- curve = (GBool *)greallocn(curve, size, sizeof(GBool));
- }
- x[n] = x1;
- y[n] = y1;
- x[n+1] = x2;
- y[n+1] = y2;
- x[n+2] = x3;
- y[n+2] = y3;
- curve[n] = curve[n+1] = gTrue;
- curve[n+2] = gFalse;
- n += 3;
-}
-
-void GfxSubpath::close() {
- if (x[n-1] != x[0] || y[n-1] != y[0]) {
- lineTo(x[0], y[0]);
- }
- closed = gTrue;
-}
-
-void GfxSubpath::offset(double dx, double dy) {
- int i;
-
- for (i = 0; i < n; ++i) {
- x[i] += dx;
- y[i] += dy;
- }
-}
-
-GfxPath::GfxPath() {
- justMoved = gFalse;
- size = 16;
- n = 0;
- firstX = firstY = 0;
- subpaths = (GfxSubpath **)gmallocn(size, sizeof(GfxSubpath *));
-}
-
-GfxPath::~GfxPath() {
- int i;
-
- for (i = 0; i < n; ++i)
- delete subpaths[i];
- gfree(subpaths);
-}
-
-// Used for copy().
-GfxPath::GfxPath(GBool justMoved1, double firstX1, double firstY1,
- GfxSubpath **subpaths1, int n1, int size1) {
- int i;
-
- justMoved = justMoved1;
- firstX = firstX1;
- firstY = firstY1;
- size = size1;
- n = n1;
- subpaths = (GfxSubpath **)gmallocn(size, sizeof(GfxSubpath *));
- for (i = 0; i < n; ++i)
- subpaths[i] = subpaths1[i]->copy();
-}
-
-void GfxPath::moveTo(double x, double y) {
- justMoved = gTrue;
- firstX = x;
- firstY = y;
-}
-
-void GfxPath::lineTo(double x, double y) {
- if (justMoved) {
- if (n >= size) {
- size += 16;
- subpaths = (GfxSubpath **)
- greallocn(subpaths, size, sizeof(GfxSubpath *));
- }
- subpaths[n] = new GfxSubpath(firstX, firstY);
- ++n;
- justMoved = gFalse;
- }
- subpaths[n-1]->lineTo(x, y);
-}
-
-void GfxPath::curveTo(double x1, double y1, double x2, double y2,
- double x3, double y3) {
- if (justMoved) {
- if (n >= size) {
- size += 16;
- subpaths = (GfxSubpath **)
- greallocn(subpaths, size, sizeof(GfxSubpath *));
- }
- subpaths[n] = new GfxSubpath(firstX, firstY);
- ++n;
- justMoved = gFalse;
- }
- subpaths[n-1]->curveTo(x1, y1, x2, y2, x3, y3);
-}
-
-void GfxPath::close() {
- // this is necessary to handle the pathological case of
- // moveto/closepath/clip, which defines an empty clipping region
- if (justMoved) {
- if (n >= size) {
- size += 16;
- subpaths = (GfxSubpath **)
- greallocn(subpaths, size, sizeof(GfxSubpath *));
- }
- subpaths[n] = new GfxSubpath(firstX, firstY);
- ++n;
- justMoved = gFalse;
- }
- subpaths[n-1]->close();
-}
-
-void GfxPath::append(GfxPath *path) {
- int i;
-
- if (n + path->n > size) {
- size = n + path->n;
- subpaths = (GfxSubpath **)
- greallocn(subpaths, size, sizeof(GfxSubpath *));
- }
- for (i = 0; i < path->n; ++i) {
- subpaths[n++] = path->subpaths[i]->copy();
- }
- justMoved = gFalse;
-}
-
-void GfxPath::offset(double dx, double dy) {
- int i;
-
- for (i = 0; i < n; ++i) {
- subpaths[i]->offset(dx, dy);
- }
-}
-
-//------------------------------------------------------------------------
-// GfxState
-//------------------------------------------------------------------------
-
-GfxState::GfxState(double hDPI, double vDPI, PDFRectangle *pageBox,
- int rotateA, GBool upsideDown) {
- double kx, ky;
-
- rotate = rotateA;
- px1 = pageBox->x1;
- py1 = pageBox->y1;
- px2 = pageBox->x2;
- py2 = pageBox->y2;
- kx = hDPI / 72.0;
- ky = vDPI / 72.0;
- if (rotate == 90) {
- ctm[0] = 0;
- ctm[1] = upsideDown ? ky : -ky;
- ctm[2] = kx;
- ctm[3] = 0;
- ctm[4] = -kx * py1;
- ctm[5] = ky * (upsideDown ? -px1 : px2);
- pageWidth = kx * (py2 - py1);
- pageHeight = ky * (px2 - px1);
- } else if (rotate == 180) {
- ctm[0] = -kx;
- ctm[1] = 0;
- ctm[2] = 0;
- ctm[3] = upsideDown ? ky : -ky;
- ctm[4] = kx * px2;
- ctm[5] = ky * (upsideDown ? -py1 : py2);
- pageWidth = kx * (px2 - px1);
- pageHeight = ky * (py2 - py1);
- } else if (rotate == 270) {
- ctm[0] = 0;
- ctm[1] = upsideDown ? -ky : ky;
- ctm[2] = -kx;
- ctm[3] = 0;
- ctm[4] = kx * py2;
- ctm[5] = ky * (upsideDown ? px2 : -px1);
- pageWidth = kx * (py2 - py1);
- pageHeight = ky * (px2 - px1);
- } else {
- ctm[0] = kx;
- ctm[1] = 0;
- ctm[2] = 0;
- ctm[3] = upsideDown ? -ky : ky;
- ctm[4] = -kx * px1;
- ctm[5] = ky * (upsideDown ? py2 : -py1);
- pageWidth = kx * (px2 - px1);
- pageHeight = ky * (py2 - py1);
- }
-
- fillColorSpace = new GfxDeviceGrayColorSpace();
- strokeColorSpace = new GfxDeviceGrayColorSpace();
- fillColor.c[0] = 0;
- strokeColor.c[0] = 0;
- fillPattern = NULL;
- strokePattern = NULL;
- blendMode = gfxBlendNormal;
- fillOpacity = 1;
- strokeOpacity = 1;
- fillOverprint = gFalse;
- strokeOverprint = gFalse;
-
- lineWidth = 1;
- lineDash = NULL;
- lineDashLength = 0;
- lineDashStart = 0;
- flatness = 1;
- lineJoin = 0;
- lineCap = 0;
- miterLimit = 10;
-
- font = NULL;
- fontSize = 0;
- textMat[0] = 1; textMat[1] = 0;
- textMat[2] = 0; textMat[3] = 1;
- textMat[4] = 0; textMat[5] = 0;
- charSpace = 0;
- wordSpace = 0;
- horizScaling = 1;
- leading = 0;
- rise = 0;
- render = 0;
-
- path = new GfxPath();
- curX = curY = 0;
- lineX = lineY = 0;
-
- clipXMin = 0;
- clipYMin = 0;
- clipXMax = pageWidth;
- clipYMax = pageHeight;
-
- saved = NULL;
-}
-
-GfxState::~GfxState() {
- if (fillColorSpace) {
- delete fillColorSpace;
- }
- if (strokeColorSpace) {
- delete strokeColorSpace;
- }
- if (fillPattern) {
- delete fillPattern;
- }
- if (strokePattern) {
- delete strokePattern;
- }
- gfree(lineDash);
- if (path) {
- // this gets set to NULL by restore()
- delete path;
- }
- if (saved) {
- delete saved;
- }
-}
-
-// Used for copy();
-GfxState::GfxState(GfxState *state) {
- memcpy(this, state, sizeof(GfxState));
- if (fillColorSpace) {
- fillColorSpace = state->fillColorSpace->copy();
- }
- if (strokeColorSpace) {
- strokeColorSpace = state->strokeColorSpace->copy();
- }
- if (fillPattern) {
- fillPattern = state->fillPattern->copy();
- }
- if (strokePattern) {
- strokePattern = state->strokePattern->copy();
- }
- if (lineDashLength > 0) {
- lineDash = (double *)gmallocn(lineDashLength, sizeof(double));
- memcpy(lineDash, state->lineDash, lineDashLength * sizeof(double));
- }
- saved = NULL;
-}
-
-void GfxState::setPath(GfxPath *pathA) {
- delete path;
- path = pathA;
-}
-
-void GfxState::getUserClipBBox(double *xMin, double *yMin,
- double *xMax, double *yMax) {
- double ictm[6];
- double xMin1, yMin1, xMax1, yMax1, det, tx, ty;
-
- // invert the CTM
- det = 1 / (ctm[0] * ctm[3] - ctm[1] * ctm[2]);
- ictm[0] = ctm[3] * det;
- ictm[1] = -ctm[1] * det;
- ictm[2] = -ctm[2] * det;
- ictm[3] = ctm[0] * det;
- ictm[4] = (ctm[2] * ctm[5] - ctm[3] * ctm[4]) * det;
- ictm[5] = (ctm[1] * ctm[4] - ctm[0] * ctm[5]) * det;
-
- // transform all four corners of the clip bbox; find the min and max
- // x and y values
- xMin1 = xMax1 = clipXMin * ictm[0] + clipYMin * ictm[2] + ictm[4];
- yMin1 = yMax1 = clipXMin * ictm[1] + clipYMin * ictm[3] + ictm[5];
- tx = clipXMin * ictm[0] + clipYMax * ictm[2] + ictm[4];
- ty = clipXMin * ictm[1] + clipYMax * ictm[3] + ictm[5];
- if (tx < xMin1) {
- xMin1 = tx;
- } else if (tx > xMax1) {
- xMax1 = tx;
- }
- if (ty < yMin1) {
- yMin1 = ty;
- } else if (ty > yMax1) {
- yMax1 = ty;
- }
- tx = clipXMax * ictm[0] + clipYMin * ictm[2] + ictm[4];
- ty = clipXMax * ictm[1] + clipYMin * ictm[3] + ictm[5];
- if (tx < xMin1) {
- xMin1 = tx;
- } else if (tx > xMax1) {
- xMax1 = tx;
- }
- if (ty < yMin1) {
- yMin1 = ty;
- } else if (ty > yMax1) {
- yMax1 = ty;
- }
- tx = clipXMax * ictm[0] + clipYMax * ictm[2] + ictm[4];
- ty = clipXMax * ictm[1] + clipYMax * ictm[3] + ictm[5];
- if (tx < xMin1) {
- xMin1 = tx;
- } else if (tx > xMax1) {
- xMax1 = tx;
- }
- if (ty < yMin1) {
- yMin1 = ty;
- } else if (ty > yMax1) {
- yMax1 = ty;
- }
-
- *xMin = xMin1;
- *yMin = yMin1;
- *xMax = xMax1;
- *yMax = yMax1;
-}
-
-double GfxState::transformWidth(double w) {
- double x, y;
-
- x = ctm[0] + ctm[2];
- y = ctm[1] + ctm[3];
- return w * sqrt(0.5 * (x * x + y * y));
-}
-
-double GfxState::getTransformedFontSize() {
- double x1, y1, x2, y2;
-
- x1 = textMat[2] * fontSize;
- y1 = textMat[3] * fontSize;
- x2 = ctm[0] * x1 + ctm[2] * y1;
- y2 = ctm[1] * x1 + ctm[3] * y1;
- return sqrt(x2 * x2 + y2 * y2);
-}
-
-void GfxState::getFontTransMat(double *m11, double *m12,
- double *m21, double *m22) {
- *m11 = (textMat[0] * ctm[0] + textMat[1] * ctm[2]) * fontSize;
- *m12 = (textMat[0] * ctm[1] + textMat[1] * ctm[3]) * fontSize;
- *m21 = (textMat[2] * ctm[0] + textMat[3] * ctm[2]) * fontSize;
- *m22 = (textMat[2] * ctm[1] + textMat[3] * ctm[3]) * fontSize;
-}
-
-void GfxState::setCTM(double a, double b, double c,
- double d, double e, double f) {
- int i;
-
- ctm[0] = a;
- ctm[1] = b;
- ctm[2] = c;
- ctm[3] = d;
- ctm[4] = e;
- ctm[5] = f;
-
- // avoid FP exceptions on badly messed up PDF files
- for (i = 0; i < 6; ++i) {
- if (ctm[i] > 1e10) {
- ctm[i] = 1e10;
- } else if (ctm[i] < -1e10) {
- ctm[i] = -1e10;
- }
- }
-}
-
-void GfxState::concatCTM(double a, double b, double c,
- double d, double e, double f) {
- double a1 = ctm[0];
- double b1 = ctm[1];
- double c1 = ctm[2];
- double d1 = ctm[3];
- int i;
-
- ctm[0] = a * a1 + b * c1;
- ctm[1] = a * b1 + b * d1;
- ctm[2] = c * a1 + d * c1;
- ctm[3] = c * b1 + d * d1;
- ctm[4] = e * a1 + f * c1 + ctm[4];
- ctm[5] = e * b1 + f * d1 + ctm[5];
-
- // avoid FP exceptions on badly messed up PDF files
- for (i = 0; i < 6; ++i) {
- if (ctm[i] > 1e10) {
- ctm[i] = 1e10;
- } else if (ctm[i] < -1e10) {
- ctm[i] = -1e10;
- }
- }
-}
-
-void GfxState::setFillColorSpace(GfxColorSpace *colorSpace) {
- if (fillColorSpace) {
- delete fillColorSpace;
- }
- fillColorSpace = colorSpace;
-}
-
-void GfxState::setStrokeColorSpace(GfxColorSpace *colorSpace) {
- if (strokeColorSpace) {
- delete strokeColorSpace;
- }
- strokeColorSpace = colorSpace;
-}
-
-void GfxState::setFillPattern(GfxPattern *pattern) {
- if (fillPattern) {
- delete fillPattern;
- }
- fillPattern = pattern;
-}
-
-void GfxState::setStrokePattern(GfxPattern *pattern) {
- if (strokePattern) {
- delete strokePattern;
- }
- strokePattern = pattern;
-}
-
-void GfxState::setLineDash(double *dash, int length, double start) {
- if (lineDash)
- gfree(lineDash);
- lineDash = dash;
- lineDashLength = length;
- lineDashStart = start;
-}
-
-void GfxState::clearPath() {
- delete path;
- path = new GfxPath();
-}
-
-void GfxState::clip() {
- double xMin, yMin, xMax, yMax, x, y;
- GfxSubpath *subpath;
- int i, j;
-
- xMin = xMax = yMin = yMax = 0; // make gcc happy
- for (i = 0; i < path->getNumSubpaths(); ++i) {
- subpath = path->getSubpath(i);
- for (j = 0; j < subpath->getNumPoints(); ++j) {
- transform(subpath->getX(j), subpath->getY(j), &x, &y);
- if (i == 0 && j == 0) {
- xMin = xMax = x;
- yMin = yMax = y;
- } else {
- if (x < xMin) {
- xMin = x;
- } else if (x > xMax) {
- xMax = x;
- }
- if (y < yMin) {
- yMin = y;
- } else if (y > yMax) {
- yMax = y;
- }
- }
- }
- }
- if (xMin > clipXMin) {
- clipXMin = xMin;
- }
- if (yMin > clipYMin) {
- clipYMin = yMin;
- }
- if (xMax < clipXMax) {
- clipXMax = xMax;
- }
- if (yMax < clipYMax) {
- clipYMax = yMax;
- }
-}
-
-void GfxState::textShift(double tx, double ty) {
- double dx, dy;
-
- textTransformDelta(tx, ty, &dx, &dy);
- curX += dx;
- curY += dy;
-}
-
-void GfxState::shift(double dx, double dy) {
- curX += dx;
- curY += dy;
-}
-
-GfxState *GfxState::save() {
- GfxState *newState;
-
- newState = copy();
- newState->saved = this;
- return newState;
-}
-
-GfxState *GfxState::restore() {
- GfxState *oldState;
-
- if (saved) {
- oldState = saved;
-
- // these attributes aren't saved/restored by the q/Q operators
- oldState->path = path;
- oldState->curX = curX;
- oldState->curY = curY;
- oldState->lineX = lineX;
- oldState->lineY = lineY;
-
- path = NULL;
- saved = NULL;
- delete this;
-
- } else {
- oldState = this;
- }
-
- return oldState;
-}
-
-GBool GfxState::parseBlendMode(Object *obj, GfxBlendMode *mode) {
- Object obj2;
- int i, j;
-
- if (obj->isName()) {
- for (i = 0; i < nGfxBlendModeNames; ++i) {
- if (!strcmp(obj->getName(), gfxBlendModeNames[i].name)) {
- *mode = gfxBlendModeNames[i].mode;
- return gTrue;
- }
- }
- return gFalse;
- } else if (obj->isArray()) {
- for (i = 0; i < obj->arrayGetLength(); ++i) {
- obj->arrayGet(i, &obj2);
- if (!obj2.isName()) {
- obj2.free();
- return gFalse;
- }
- for (j = 0; j < nGfxBlendModeNames; ++j) {
- if (!strcmp(obj2.getName(), gfxBlendModeNames[j].name)) {
- obj2.free();
- *mode = gfxBlendModeNames[j].mode;
- return gTrue;
- }
- }
- obj2.free();
- }
- *mode = gfxBlendNormal;
- return gTrue;
- } else {
- return gFalse;
- }
-}
+++ /dev/null
-//========================================================================
-//
-// GfxState.h
-//
-// Copyright 1996-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#ifndef GFXSTATE_H
-#define GFXSTATE_H
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma interface
-#endif
-
-#include "gtypes.h"
-#include "Object.h"
-#include "Function.h"
-
-class Array;
-class GfxFont;
-class PDFRectangle;
-class GfxShading;
-
-//------------------------------------------------------------------------
-// GfxBlendMode
-//------------------------------------------------------------------------
-
-enum GfxBlendMode {
- gfxBlendNormal,
- gfxBlendMultiply,
- gfxBlendScreen,
- gfxBlendOverlay,
- gfxBlendDarken,
- gfxBlendLighten,
- gfxBlendColorDodge,
- gfxBlendColorBurn,
- gfxBlendHardLight,
- gfxBlendSoftLight,
- gfxBlendDifference,
- gfxBlendExclusion,
- gfxBlendHue,
- gfxBlendSaturation,
- gfxBlendColor,
- gfxBlendLuminosity
-};
-
-//------------------------------------------------------------------------
-// GfxColorComp
-//------------------------------------------------------------------------
-
-// 16.16 fixed point color component
-typedef int GfxColorComp;
-
-#define gfxColorComp1 0x10000
-
-static inline GfxColorComp dblToCol(double x) {
- return (GfxColorComp)(x * gfxColorComp1);
-}
-
-static inline double colToDbl(GfxColorComp x) {
- return (double)x / (double)gfxColorComp1;
-}
-
-static inline GfxColorComp byteToCol(Guchar x) {
- // (x / 255) << 16 = (0.0000000100000001... * x) << 16
- // = ((x << 8) + (x) + (x >> 8) + ...) << 16
- // = (x << 8) + (x) + (x >> 7)
- // [for rounding]
- return (GfxColorComp)((x << 8) + x + (x >> 7));
-}
-
-static inline Guchar colToByte(GfxColorComp x) {
- // 255 * x + 0.5 = 256 * x - x + 0x8000
- return (Guchar)(((x << 8) - x + 0x8000) >> 16);
-}
-
-//------------------------------------------------------------------------
-// GfxColor
-//------------------------------------------------------------------------
-
-#define gfxColorMaxComps funcMaxOutputs
-
-struct GfxColor {
- GfxColorComp c[gfxColorMaxComps];
-};
-
-//------------------------------------------------------------------------
-// GfxGray
-//------------------------------------------------------------------------
-
-typedef GfxColorComp GfxGray;
-
-//------------------------------------------------------------------------
-// GfxRGB
-//------------------------------------------------------------------------
-
-struct GfxRGB {
- GfxColorComp r, g, b;
-};
-
-//------------------------------------------------------------------------
-// GfxCMYK
-//------------------------------------------------------------------------
-
-struct GfxCMYK {
- GfxColorComp c, m, y, k;
-};
-
-//------------------------------------------------------------------------
-// GfxColorSpace
-//------------------------------------------------------------------------
-
-// NB: The nGfxColorSpaceModes constant and the gfxColorSpaceModeNames
-// array defined in GfxState.cc must match this enum.
-enum GfxColorSpaceMode {
- csDeviceGray,
- csCalGray,
- csDeviceRGB,
- csCalRGB,
- csDeviceCMYK,
- csLab,
- csICCBased,
- csIndexed,
- csSeparation,
- csDeviceN,
- csPattern
-};
-
-class GfxColorSpace {
-public:
-
- GfxColorSpace();
- virtual ~GfxColorSpace();
- virtual GfxColorSpace *copy() = 0;
- virtual GfxColorSpaceMode getMode() = 0;
-
- // Construct a color space. Returns NULL if unsuccessful.
- static GfxColorSpace *parse(Object *csObj);
-
- // Convert to gray, RGB, or CMYK.
- virtual void getGray(GfxColor *color, GfxGray *gray) = 0;
- virtual void getRGB(GfxColor *color, GfxRGB *rgb) = 0;
- virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk) = 0;
-
- // Return the number of color components.
- virtual int getNComps() = 0;
-
- // Return the default ranges for each component, assuming an image
- // with a max pixel value of <maxImgPixel>.
- virtual void getDefaultRanges(double *decodeLow, double *decodeRange,
- int maxImgPixel);
-
- // Return the number of color space modes
- static int getNumColorSpaceModes();
-
- // Return the name of the <idx>th color space mode.
- static char *getColorSpaceModeName(int idx);
-
-private:
-};
-
-//------------------------------------------------------------------------
-// GfxDeviceGrayColorSpace
-//------------------------------------------------------------------------
-
-class GfxDeviceGrayColorSpace: public GfxColorSpace {
-public:
-
- GfxDeviceGrayColorSpace();
- virtual ~GfxDeviceGrayColorSpace();
- virtual GfxColorSpace *copy();
- virtual GfxColorSpaceMode getMode() { return csDeviceGray; }
-
- virtual void getGray(GfxColor *color, GfxGray *gray);
- virtual void getRGB(GfxColor *color, GfxRGB *rgb);
- virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk);
-
- virtual int getNComps() { return 1; }
-
-private:
-};
-
-//------------------------------------------------------------------------
-// GfxCalGrayColorSpace
-//------------------------------------------------------------------------
-
-class GfxCalGrayColorSpace: public GfxColorSpace {
-public:
-
- GfxCalGrayColorSpace();
- virtual ~GfxCalGrayColorSpace();
- virtual GfxColorSpace *copy();
- virtual GfxColorSpaceMode getMode() { return csCalGray; }
-
- // Construct a CalGray color space. Returns NULL if unsuccessful.
- static GfxColorSpace *parse(Array *arr);
-
- virtual void getGray(GfxColor *color, GfxGray *gray);
- virtual void getRGB(GfxColor *color, GfxRGB *rgb);
- virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk);
-
- virtual int getNComps() { return 1; }
-
- // CalGray-specific access.
- double getWhiteX() { return whiteX; }
- double getWhiteY() { return whiteY; }
- double getWhiteZ() { return whiteZ; }
- double getBlackX() { return blackX; }
- double getBlackY() { return blackY; }
- double getBlackZ() { return blackZ; }
- double getGamma() { return gamma; }
-
-private:
-
- double whiteX, whiteY, whiteZ; // white point
- double blackX, blackY, blackZ; // black point
- double gamma; // gamma value
-};
-
-//------------------------------------------------------------------------
-// GfxDeviceRGBColorSpace
-//------------------------------------------------------------------------
-
-class GfxDeviceRGBColorSpace: public GfxColorSpace {
-public:
-
- GfxDeviceRGBColorSpace();
- virtual ~GfxDeviceRGBColorSpace();
- virtual GfxColorSpace *copy();
- virtual GfxColorSpaceMode getMode() { return csDeviceRGB; }
-
- virtual void getGray(GfxColor *color, GfxGray *gray);
- virtual void getRGB(GfxColor *color, GfxRGB *rgb);
- virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk);
-
- virtual int getNComps() { return 3; }
-
-private:
-};
-
-//------------------------------------------------------------------------
-// GfxCalRGBColorSpace
-//------------------------------------------------------------------------
-
-class GfxCalRGBColorSpace: public GfxColorSpace {
-public:
-
- GfxCalRGBColorSpace();
- virtual ~GfxCalRGBColorSpace();
- virtual GfxColorSpace *copy();
- virtual GfxColorSpaceMode getMode() { return csCalRGB; }
-
- // Construct a CalRGB color space. Returns NULL if unsuccessful.
- static GfxColorSpace *parse(Array *arr);
-
- virtual void getGray(GfxColor *color, GfxGray *gray);
- virtual void getRGB(GfxColor *color, GfxRGB *rgb);
- virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk);
-
- virtual int getNComps() { return 3; }
-
- // CalRGB-specific access.
- double getWhiteX() { return whiteX; }
- double getWhiteY() { return whiteY; }
- double getWhiteZ() { return whiteZ; }
- double getBlackX() { return blackX; }
- double getBlackY() { return blackY; }
- double getBlackZ() { return blackZ; }
- double getGammaR() { return gammaR; }
- double getGammaG() { return gammaG; }
- double getGammaB() { return gammaB; }
- double *getMatrix() { return mat; }
-
-private:
-
- double whiteX, whiteY, whiteZ; // white point
- double blackX, blackY, blackZ; // black point
- double gammaR, gammaG, gammaB; // gamma values
- double mat[9]; // ABC -> XYZ transform matrix
-};
-
-//------------------------------------------------------------------------
-// GfxDeviceCMYKColorSpace
-//------------------------------------------------------------------------
-
-class GfxDeviceCMYKColorSpace: public GfxColorSpace {
-public:
-
- GfxDeviceCMYKColorSpace();
- virtual ~GfxDeviceCMYKColorSpace();
- virtual GfxColorSpace *copy();
- virtual GfxColorSpaceMode getMode() { return csDeviceCMYK; }
-
- virtual void getGray(GfxColor *color, GfxGray *gray);
- virtual void getRGB(GfxColor *color, GfxRGB *rgb);
- virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk);
-
- virtual int getNComps() { return 4; }
-
-private:
-};
-
-//------------------------------------------------------------------------
-// GfxLabColorSpace
-//------------------------------------------------------------------------
-
-class GfxLabColorSpace: public GfxColorSpace {
-public:
-
- GfxLabColorSpace();
- virtual ~GfxLabColorSpace();
- virtual GfxColorSpace *copy();
- virtual GfxColorSpaceMode getMode() { return csLab; }
-
- // Construct a Lab color space. Returns NULL if unsuccessful.
- static GfxColorSpace *parse(Array *arr);
-
- virtual void getGray(GfxColor *color, GfxGray *gray);
- virtual void getRGB(GfxColor *color, GfxRGB *rgb);
- virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk);
-
- virtual int getNComps() { return 3; }
-
- virtual void getDefaultRanges(double *decodeLow, double *decodeRange,
- int maxImgPixel);
-
- // Lab-specific access.
- double getWhiteX() { return whiteX; }
- double getWhiteY() { return whiteY; }
- double getWhiteZ() { return whiteZ; }
- double getBlackX() { return blackX; }
- double getBlackY() { return blackY; }
- double getBlackZ() { return blackZ; }
- double getAMin() { return aMin; }
- double getAMax() { return aMax; }
- double getBMin() { return bMin; }
- double getBMax() { return bMax; }
-
-private:
-
- double whiteX, whiteY, whiteZ; // white point
- double blackX, blackY, blackZ; // black point
- double aMin, aMax, bMin, bMax; // range for the a and b components
- double kr, kg, kb; // gamut mapping mulitpliers
-};
-
-//------------------------------------------------------------------------
-// GfxICCBasedColorSpace
-//------------------------------------------------------------------------
-
-class GfxICCBasedColorSpace: public GfxColorSpace {
-public:
-
- GfxICCBasedColorSpace(int nCompsA, GfxColorSpace *altA,
- Ref *iccProfileStreamA);
- virtual ~GfxICCBasedColorSpace();
- virtual GfxColorSpace *copy();
- virtual GfxColorSpaceMode getMode() { return csICCBased; }
-
- // Construct an ICCBased color space. Returns NULL if unsuccessful.
- static GfxColorSpace *parse(Array *arr);
-
- virtual void getGray(GfxColor *color, GfxGray *gray);
- virtual void getRGB(GfxColor *color, GfxRGB *rgb);
- virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk);
-
- virtual int getNComps() { return nComps; }
-
- virtual void getDefaultRanges(double *decodeLow, double *decodeRange,
- int maxImgPixel);
-
- // ICCBased-specific access.
- GfxColorSpace *getAlt() { return alt; }
-
-private:
-
- int nComps; // number of color components (1, 3, or 4)
- GfxColorSpace *alt; // alternate color space
- double rangeMin[4]; // min values for each component
- double rangeMax[4]; // max values for each component
- Ref iccProfileStream; // the ICC profile
-};
-
-//------------------------------------------------------------------------
-// GfxIndexedColorSpace
-//------------------------------------------------------------------------
-
-class GfxIndexedColorSpace: public GfxColorSpace {
-public:
-
- GfxIndexedColorSpace(GfxColorSpace *baseA, int indexHighA);
- virtual ~GfxIndexedColorSpace();
- virtual GfxColorSpace *copy();
- virtual GfxColorSpaceMode getMode() { return csIndexed; }
-
- // Construct a Lab color space. Returns NULL if unsuccessful.
- static GfxColorSpace *parse(Array *arr);
-
- virtual void getGray(GfxColor *color, GfxGray *gray);
- virtual void getRGB(GfxColor *color, GfxRGB *rgb);
- virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk);
-
- virtual int getNComps() { return 1; }
-
- virtual void getDefaultRanges(double *decodeLow, double *decodeRange,
- int maxImgPixel);
-
- // Indexed-specific access.
- GfxColorSpace *getBase() { return base; }
- int getIndexHigh() { return indexHigh; }
- Guchar *getLookup() { return lookup; }
- GfxColor *mapColorToBase(GfxColor *color, GfxColor *baseColor);
-
-private:
-
- GfxColorSpace *base; // base color space
- int indexHigh; // max pixel value
- Guchar *lookup; // lookup table
-};
-
-//------------------------------------------------------------------------
-// GfxSeparationColorSpace
-//------------------------------------------------------------------------
-
-class GfxSeparationColorSpace: public GfxColorSpace {
-public:
-
- GfxSeparationColorSpace(GString *nameA, GfxColorSpace *altA,
- Function *funcA);
- virtual ~GfxSeparationColorSpace();
- virtual GfxColorSpace *copy();
- virtual GfxColorSpaceMode getMode() { return csSeparation; }
-
- // Construct a Separation color space. Returns NULL if unsuccessful.
- static GfxColorSpace *parse(Array *arr);
-
- virtual void getGray(GfxColor *color, GfxGray *gray);
- virtual void getRGB(GfxColor *color, GfxRGB *rgb);
- virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk);
-
- virtual int getNComps() { return 1; }
-
- // Separation-specific access.
- GString *getName() { return name; }
- GfxColorSpace *getAlt() { return alt; }
- Function *getFunc() { return func; }
-
-private:
-
- GString *name; // colorant name
- GfxColorSpace *alt; // alternate color space
- Function *func; // tint transform (into alternate color space)
-};
-
-//------------------------------------------------------------------------
-// GfxDeviceNColorSpace
-//------------------------------------------------------------------------
-
-class GfxDeviceNColorSpace: public GfxColorSpace {
-public:
-
- GfxDeviceNColorSpace(int nCompsA, GfxColorSpace *alt, Function *func);
- virtual ~GfxDeviceNColorSpace();
- virtual GfxColorSpace *copy();
- virtual GfxColorSpaceMode getMode() { return csDeviceN; }
-
- // Construct a DeviceN color space. Returns NULL if unsuccessful.
- static GfxColorSpace *parse(Array *arr);
-
- virtual void getGray(GfxColor *color, GfxGray *gray);
- virtual void getRGB(GfxColor *color, GfxRGB *rgb);
- virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk);
-
- virtual int getNComps() { return nComps; }
-
- // DeviceN-specific access.
- GString *getColorantName(int i) { return names[i]; }
- GfxColorSpace *getAlt() { return alt; }
- Function *getTintTransformFunc() { return func; }
-
-private:
-
- int nComps; // number of components
- GString // colorant names
- *names[gfxColorMaxComps];
- GfxColorSpace *alt; // alternate color space
- Function *func; // tint transform (into alternate color space)
-};
-
-//------------------------------------------------------------------------
-// GfxPatternColorSpace
-//------------------------------------------------------------------------
-
-class GfxPatternColorSpace: public GfxColorSpace {
-public:
-
- GfxPatternColorSpace(GfxColorSpace *underA);
- virtual ~GfxPatternColorSpace();
- virtual GfxColorSpace *copy();
- virtual GfxColorSpaceMode getMode() { return csPattern; }
-
- // Construct a Pattern color space. Returns NULL if unsuccessful.
- static GfxColorSpace *parse(Array *arr);
-
- virtual void getGray(GfxColor *color, GfxGray *gray);
- virtual void getRGB(GfxColor *color, GfxRGB *rgb);
- virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk);
-
- virtual int getNComps() { return 0; }
-
- // Pattern-specific access.
- GfxColorSpace *getUnder() { return under; }
-
-private:
-
- GfxColorSpace *under; // underlying color space (for uncolored
- // patterns)
-};
-
-//------------------------------------------------------------------------
-// GfxPattern
-//------------------------------------------------------------------------
-
-class GfxPattern {
-public:
-
- GfxPattern(int typeA);
- virtual ~GfxPattern();
-
- static GfxPattern *parse(Object *obj);
-
- virtual GfxPattern *copy() = 0;
-
- int getType() { return type; }
-
-private:
-
- int type;
-};
-
-//------------------------------------------------------------------------
-// GfxTilingPattern
-//------------------------------------------------------------------------
-
-class GfxTilingPattern: public GfxPattern {
-public:
-
- static GfxTilingPattern *parse(Object *patObj);
- virtual ~GfxTilingPattern();
-
- virtual GfxPattern *copy();
-
- int getPaintType() { return paintType; }
- int getTilingType() { return tilingType; }
- double *getBBox() { return bbox; }
- double getXStep() { return xStep; }
- double getYStep() { return yStep; }
- Dict *getResDict()
- { return resDict.isDict() ? resDict.getDict() : (Dict *)NULL; }
- double *getMatrix() { return matrix; }
- Object *getContentStream() { return &contentStream; }
-
-private:
-
- GfxTilingPattern(int paintTypeA, int tilingTypeA,
- double *bboxA, double xStepA, double yStepA,
- Object *resDictA, double *matrixA,
- Object *contentStreamA);
-
- int paintType;
- int tilingType;
- double bbox[4];
- double xStep, yStep;
- Object resDict;
- double matrix[6];
- Object contentStream;
-};
-
-//------------------------------------------------------------------------
-// GfxShadingPattern
-//------------------------------------------------------------------------
-
-class GfxShadingPattern: public GfxPattern {
-public:
-
- static GfxShadingPattern *parse(Object *patObj);
- virtual ~GfxShadingPattern();
-
- virtual GfxPattern *copy();
-
- GfxShading *getShading() { return shading; }
- double *getMatrix() { return matrix; }
-
-private:
-
- GfxShadingPattern(GfxShading *shadingA, double *matrixA);
-
- GfxShading *shading;
- double matrix[6];
-};
-
-//------------------------------------------------------------------------
-// GfxShading
-//------------------------------------------------------------------------
-
-class GfxShading {
-public:
-
- GfxShading(int typeA);
- GfxShading(GfxShading *shading);
- virtual ~GfxShading();
-
- static GfxShading *parse(Object *obj);
-
- virtual GfxShading *copy() = 0;
-
- int getType() { return type; }
- GfxColorSpace *getColorSpace() { return colorSpace; }
- GfxColor *getBackground() { return &background; }
- GBool getHasBackground() { return hasBackground; }
- void getBBox(double *xMinA, double *yMinA, double *xMaxA, double *yMaxA)
- { *xMinA = xMin; *yMinA = yMin; *xMaxA = xMax; *yMaxA = yMax; }
- GBool getHasBBox() { return hasBBox; }
-
-protected:
-
- GBool init(Dict *dict);
-
- int type;
- GfxColorSpace *colorSpace;
- GfxColor background;
- GBool hasBackground;
- double xMin, yMin, xMax, yMax;
- GBool hasBBox;
-};
-
-//------------------------------------------------------------------------
-// GfxFunctionShading
-//------------------------------------------------------------------------
-
-class GfxFunctionShading: public GfxShading {
-public:
-
- GfxFunctionShading(double x0A, double y0A,
- double x1A, double y1A,
- double *matrixA,
- Function **funcsA, int nFuncsA);
- GfxFunctionShading(GfxFunctionShading *shading);
- virtual ~GfxFunctionShading();
-
- static GfxFunctionShading *parse(Dict *dict);
-
- virtual GfxShading *copy();
-
- void getDomain(double *x0A, double *y0A, double *x1A, double *y1A)
- { *x0A = x0; *y0A = y0; *x1A = x1; *y1A = y1; }
- double *getMatrix() { return matrix; }
- int getNFuncs() { return nFuncs; }
- Function *getFunc(int i) { return funcs[i]; }
- void getColor(double x, double y, GfxColor *color);
-
-private:
-
- double x0, y0, x1, y1;
- double matrix[6];
- Function *funcs[gfxColorMaxComps];
- int nFuncs;
-};
-
-//------------------------------------------------------------------------
-// GfxAxialShading
-//------------------------------------------------------------------------
-
-class GfxAxialShading: public GfxShading {
-public:
-
- GfxAxialShading(double x0A, double y0A,
- double x1A, double y1A,
- double t0A, double t1A,
- Function **funcsA, int nFuncsA,
- GBool extend0A, GBool extend1A);
- GfxAxialShading(GfxAxialShading *shading);
- virtual ~GfxAxialShading();
-
- static GfxAxialShading *parse(Dict *dict);
-
- virtual GfxShading *copy();
-
- void getCoords(double *x0A, double *y0A, double *x1A, double *y1A)
- { *x0A = x0; *y0A = y0; *x1A = x1; *y1A = y1; }
- double getDomain0() { return t0; }
- double getDomain1() { return t1; }
- GBool getExtend0() { return extend0; }
- GBool getExtend1() { return extend1; }
- int getNFuncs() { return nFuncs; }
- Function *getFunc(int i) { return funcs[i]; }
- void getColor(double t, GfxColor *color);
-
-private:
-
- double x0, y0, x1, y1;
- double t0, t1;
- Function *funcs[gfxColorMaxComps];
- int nFuncs;
- GBool extend0, extend1;
-};
-
-//------------------------------------------------------------------------
-// GfxRadialShading
-//------------------------------------------------------------------------
-
-class GfxRadialShading: public GfxShading {
-public:
-
- GfxRadialShading(double x0A, double y0A, double r0A,
- double x1A, double y1A, double r1A,
- double t0A, double t1A,
- Function **funcsA, int nFuncsA,
- GBool extend0A, GBool extend1A);
- GfxRadialShading(GfxRadialShading *shading);
- virtual ~GfxRadialShading();
-
- static GfxRadialShading *parse(Dict *dict);
-
- virtual GfxShading *copy();
-
- void getCoords(double *x0A, double *y0A, double *r0A,
- double *x1A, double *y1A, double *r1A)
- { *x0A = x0; *y0A = y0; *r0A = r0; *x1A = x1; *y1A = y1; *r1A = r1; }
- double getDomain0() { return t0; }
- double getDomain1() { return t1; }
- GBool getExtend0() { return extend0; }
- GBool getExtend1() { return extend1; }
- int getNFuncs() { return nFuncs; }
- Function *getFunc(int i) { return funcs[i]; }
- void getColor(double t, GfxColor *color);
-
-private:
-
- double x0, y0, r0, x1, y1, r1;
- double t0, t1;
- Function *funcs[gfxColorMaxComps];
- int nFuncs;
- GBool extend0, extend1;
-};
-
-//------------------------------------------------------------------------
-// GfxGouraudTriangleShading
-//------------------------------------------------------------------------
-
-struct GfxGouraudVertex {
- double x, y;
- GfxColor color;
-};
-
-class GfxGouraudTriangleShading: public GfxShading {
-public:
-
- GfxGouraudTriangleShading(int typeA,
- GfxGouraudVertex *verticesA, int nVerticesA,
- int (*trianglesA)[3], int nTrianglesA,
- Function **funcsA, int nFuncsA);
- GfxGouraudTriangleShading(GfxGouraudTriangleShading *shading);
- virtual ~GfxGouraudTriangleShading();
-
- static GfxGouraudTriangleShading *parse(int typeA, Dict *dict, Stream *str);
-
- virtual GfxShading *copy();
-
- int getNTriangles() { return nTriangles; }
- void getTriangle(int i, double *x0, double *y0, GfxColor *color0,
- double *x1, double *y1, GfxColor *color1,
- double *x2, double *y2, GfxColor *color2);
-
-private:
-
- GfxGouraudVertex *vertices;
- int nVertices;
- int (*triangles)[3];
- int nTriangles;
- Function *funcs[gfxColorMaxComps];
- int nFuncs;
-};
-
-//------------------------------------------------------------------------
-// GfxPatchMeshShading
-//------------------------------------------------------------------------
-
-struct GfxPatch {
- double x[4][4];
- double y[4][4];
- GfxColor color[2][2];
-};
-
-class GfxPatchMeshShading: public GfxShading {
-public:
-
- GfxPatchMeshShading(int typeA, GfxPatch *patchesA, int nPatchesA,
- Function **funcsA, int nFuncsA);
- GfxPatchMeshShading(GfxPatchMeshShading *shading);
- virtual ~GfxPatchMeshShading();
-
- static GfxPatchMeshShading *parse(int typeA, Dict *dict, Stream *str);
-
- virtual GfxShading *copy();
-
- int getNPatches() { return nPatches; }
- GfxPatch *getPatch(int i) { return &patches[i]; }
-
-private:
-
- GfxPatch *patches;
- int nPatches;
- Function *funcs[gfxColorMaxComps];
- int nFuncs;
-};
-
-//------------------------------------------------------------------------
-// GfxImageColorMap
-//------------------------------------------------------------------------
-
-class GfxImageColorMap {
-public:
-
- // Constructor.
- GfxImageColorMap(int bitsA, Object *decode, GfxColorSpace *colorSpaceA);
-
- // Destructor.
- ~GfxImageColorMap();
-
- // Return a copy of this color map.
- GfxImageColorMap *copy() { return new GfxImageColorMap(this); }
-
- // Is color map valid?
- GBool isOk() { return ok; }
-
- // Get the color space.
- GfxColorSpace *getColorSpace() { return colorSpace; }
-
- // Get stream decoding info.
- int getNumPixelComps() { return nComps; }
- int getBits() { return bits; }
-
- // Get decode table.
- double getDecodeLow(int i) { return decodeLow[i]; }
- double getDecodeHigh(int i) { return decodeLow[i] + decodeRange[i]; }
-
- // Convert an image pixel to a color.
- void getGray(Guchar *x, GfxGray *gray);
- void getRGB(Guchar *x, GfxRGB *rgb);
- void getCMYK(Guchar *x, GfxCMYK *cmyk);
- void getColor(Guchar *x, GfxColor *color);
-
-private:
-
- GfxImageColorMap(GfxImageColorMap *colorMap);
-
- GfxColorSpace *colorSpace; // the image color space
- int bits; // bits per component
- int nComps; // number of components in a pixel
- GfxColorSpace *colorSpace2; // secondary color space
- int nComps2; // number of components in colorSpace2
- GfxColorComp * // lookup table
- lookup[gfxColorMaxComps];
- double // minimum values for each component
- decodeLow[gfxColorMaxComps];
- double // max - min value for each component
- decodeRange[gfxColorMaxComps];
- GBool ok;
-};
-
-//------------------------------------------------------------------------
-// GfxSubpath and GfxPath
-//------------------------------------------------------------------------
-
-class GfxSubpath {
-public:
-
- // Constructor.
- GfxSubpath(double x1, double y1);
-
- // Destructor.
- ~GfxSubpath();
-
- // Copy.
- GfxSubpath *copy() { return new GfxSubpath(this); }
-
- // Get points.
- int getNumPoints() { return n; }
- double getX(int i) { return x[i]; }
- double getY(int i) { return y[i]; }
- GBool getCurve(int i) { return curve[i]; }
-
- // Get last point.
- double getLastX() { return x[n-1]; }
- double getLastY() { return y[n-1]; }
-
- // Add a line segment.
- void lineTo(double x1, double y1);
-
- // Add a Bezier curve.
- void curveTo(double x1, double y1, double x2, double y2,
- double x3, double y3);
-
- // Close the subpath.
- void close();
- GBool isClosed() { return closed; }
-
- // Add (<dx>, <dy>) to each point in the subpath.
- void offset(double dx, double dy);
-
-private:
-
- double *x, *y; // points
- GBool *curve; // curve[i] => point i is a control point
- // for a Bezier curve
- int n; // number of points
- int size; // size of x/y arrays
- GBool closed; // set if path is closed
-
- GfxSubpath(GfxSubpath *subpath);
-};
-
-class GfxPath {
-public:
-
- // Constructor.
- GfxPath();
-
- // Destructor.
- ~GfxPath();
-
- // Copy.
- GfxPath *copy()
- { return new GfxPath(justMoved, firstX, firstY, subpaths, n, size); }
-
- // Is there a current point?
- GBool isCurPt() { return n > 0 || justMoved; }
-
- // Is the path non-empty, i.e., is there at least one segment?
- GBool isPath() { return n > 0; }
-
- // Get subpaths.
- int getNumSubpaths() { return n; }
- GfxSubpath *getSubpath(int i) { return subpaths[i]; }
-
- // Get last point on last subpath.
- double getLastX() { return subpaths[n-1]->getLastX(); }
- double getLastY() { return subpaths[n-1]->getLastY(); }
-
- // Move the current point.
- void moveTo(double x, double y);
-
- // Add a segment to the last subpath.
- void lineTo(double x, double y);
-
- // Add a Bezier curve to the last subpath
- void curveTo(double x1, double y1, double x2, double y2,
- double x3, double y3);
-
- // Close the last subpath.
- void close();
-
- // Append <path> to <this>.
- void append(GfxPath *path);
-
- // Add (<dx>, <dy>) to each point in the path.
- void offset(double dx, double dy);
-
-private:
-
- GBool justMoved; // set if a new subpath was just started
- double firstX, firstY; // first point in new subpath
- GfxSubpath **subpaths; // subpaths
- int n; // number of subpaths
- int size; // size of subpaths array
-
- GfxPath(GBool justMoved1, double firstX1, double firstY1,
- GfxSubpath **subpaths1, int n1, int size1);
-};
-
-//------------------------------------------------------------------------
-// GfxState
-//------------------------------------------------------------------------
-
-class GfxState {
-public:
-
- // Construct a default GfxState, for a device with resolution <hDPI>
- // x <vDPI>, page box <pageBox>, page rotation <rotateA>, and
- // coordinate system specified by <upsideDown>.
- GfxState(double hDPI, double vDPI, PDFRectangle *pageBox,
- int rotateA, GBool upsideDown);
-
- // Destructor.
- ~GfxState();
-
- // Copy.
- GfxState *copy() { return new GfxState(this); }
-
- // Accessors.
- double *getCTM() { return ctm; }
- double getX1() { return px1; }
- double getY1() { return py1; }
- double getX2() { return px2; }
- double getY2() { return py2; }
- double getPageWidth() { return pageWidth; }
- double getPageHeight() { return pageHeight; }
- int getRotate() { return rotate; }
- GfxColor *getFillColor() { return &fillColor; }
- GfxColor *getStrokeColor() { return &strokeColor; }
- void getFillGray(GfxGray *gray)
- { fillColorSpace->getGray(&fillColor, gray); }
- void getStrokeGray(GfxGray *gray)
- { strokeColorSpace->getGray(&strokeColor, gray); }
- void getFillRGB(GfxRGB *rgb)
- { fillColorSpace->getRGB(&fillColor, rgb); }
- void getStrokeRGB(GfxRGB *rgb)
- { strokeColorSpace->getRGB(&strokeColor, rgb); }
- void getFillCMYK(GfxCMYK *cmyk)
- { fillColorSpace->getCMYK(&fillColor, cmyk); }
- void getStrokeCMYK(GfxCMYK *cmyk)
- { strokeColorSpace->getCMYK(&strokeColor, cmyk); }
- GfxColorSpace *getFillColorSpace() { return fillColorSpace; }
- GfxColorSpace *getStrokeColorSpace() { return strokeColorSpace; }
- GfxPattern *getFillPattern() { return fillPattern; }
- GfxPattern *getStrokePattern() { return strokePattern; }
- GfxBlendMode getBlendMode() { return blendMode; }
- double getFillOpacity() { return fillOpacity; }
- double getStrokeOpacity() { return strokeOpacity; }
- GBool getFillOverprint() { return fillOverprint; }
- GBool getStrokeOverprint() { return strokeOverprint; }
- double getLineWidth() { return lineWidth; }
- void getLineDash(double **dash, int *length, double *start)
- { *dash = lineDash; *length = lineDashLength; *start = lineDashStart; }
- int getFlatness() { return flatness; }
- int getLineJoin() { return lineJoin; }
- int getLineCap() { return lineCap; }
- double getMiterLimit() { return miterLimit; }
- GfxFont *getFont() { return font; }
- double getFontSize() { return fontSize; }
- double *getTextMat() { return textMat; }
- double getCharSpace() { return charSpace; }
- double getWordSpace() { return wordSpace; }
- double getHorizScaling() { return horizScaling; }
- double getLeading() { return leading; }
- double getRise() { return rise; }
- int getRender() { return render; }
- GfxPath *getPath() { return path; }
- void setPath(GfxPath *pathA);
- double getCurX() { return curX; }
- double getCurY() { return curY; }
- void getClipBBox(double *xMin, double *yMin, double *xMax, double *yMax)
- { *xMin = clipXMin; *yMin = clipYMin; *xMax = clipXMax; *yMax = clipYMax; }
- void getUserClipBBox(double *xMin, double *yMin, double *xMax, double *yMax);
- double getLineX() { return lineX; }
- double getLineY() { return lineY; }
-
- // Is there a current point/path?
- GBool isCurPt() { return path->isCurPt(); }
- GBool isPath() { return path->isPath(); }
-
- // Transforms.
- void transform(double x1, double y1, double *x2, double *y2)
- { *x2 = ctm[0] * x1 + ctm[2] * y1 + ctm[4];
- *y2 = ctm[1] * x1 + ctm[3] * y1 + ctm[5]; }
- void transformDelta(double x1, double y1, double *x2, double *y2)
- { *x2 = ctm[0] * x1 + ctm[2] * y1;
- *y2 = ctm[1] * x1 + ctm[3] * y1; }
- void textTransform(double x1, double y1, double *x2, double *y2)
- { *x2 = textMat[0] * x1 + textMat[2] * y1 + textMat[4];
- *y2 = textMat[1] * x1 + textMat[3] * y1 + textMat[5]; }
- void textTransformDelta(double x1, double y1, double *x2, double *y2)
- { *x2 = textMat[0] * x1 + textMat[2] * y1;
- *y2 = textMat[1] * x1 + textMat[3] * y1; }
- double transformWidth(double w);
- double getTransformedLineWidth()
- { return transformWidth(lineWidth); }
- double getTransformedFontSize();
- void getFontTransMat(double *m11, double *m12, double *m21, double *m22);
-
- // Change state parameters.
- void setCTM(double a, double b, double c,
- double d, double e, double f);
- void concatCTM(double a, double b, double c,
- double d, double e, double f);
- void setFillColorSpace(GfxColorSpace *colorSpace);
- void setStrokeColorSpace(GfxColorSpace *colorSpace);
- void setFillColor(GfxColor *color) { fillColor = *color; }
- void setStrokeColor(GfxColor *color) { strokeColor = *color; }
- void setFillPattern(GfxPattern *pattern);
- void setStrokePattern(GfxPattern *pattern);
- void setBlendMode(GfxBlendMode mode) { blendMode = mode; }
- void setFillOpacity(double opac) { fillOpacity = opac; }
- void setStrokeOpacity(double opac) { strokeOpacity = opac; }
- void setFillOverprint(GBool op) { fillOverprint = op; }
- void setStrokeOverprint(GBool op) { strokeOverprint = op; }
- void setLineWidth(double width) { lineWidth = width; }
- void setLineDash(double *dash, int length, double start);
- void setFlatness(int flatness1) { flatness = flatness1; }
- void setLineJoin(int lineJoin1) { lineJoin = lineJoin1; }
- void setLineCap(int lineCap1) { lineCap = lineCap1; }
- void setMiterLimit(double limit) { miterLimit = limit; }
- void setFont(GfxFont *fontA, double fontSizeA)
- { font = fontA; fontSize = fontSizeA; }
- void setTextMat(double a, double b, double c,
- double d, double e, double f)
- { textMat[0] = a; textMat[1] = b; textMat[2] = c;
- textMat[3] = d; textMat[4] = e; textMat[5] = f; }
- void setCharSpace(double space)
- { charSpace = space; }
- void setWordSpace(double space)
- { wordSpace = space; }
- void setHorizScaling(double scale)
- { horizScaling = 0.01 * scale; }
- void setLeading(double leadingA)
- { leading = leadingA; }
- void setRise(double riseA)
- { rise = riseA; }
- void setRender(int renderA)
- { render = renderA; }
-
- // Add to path.
- void moveTo(double x, double y)
- { path->moveTo(curX = x, curY = y); }
- void lineTo(double x, double y)
- { path->lineTo(curX = x, curY = y); }
- void curveTo(double x1, double y1, double x2, double y2,
- double x3, double y3)
- { path->curveTo(x1, y1, x2, y2, curX = x3, curY = y3); }
- void closePath()
- { path->close(); curX = path->getLastX(); curY = path->getLastY(); }
- void clearPath();
-
- // Update clip region.
- void clip();
-
- // Text position.
- void textSetPos(double tx, double ty) { lineX = tx; lineY = ty; }
- void textMoveTo(double tx, double ty)
- { lineX = tx; lineY = ty; textTransform(tx, ty, &curX, &curY); }
- void textShift(double tx, double ty);
- void shift(double dx, double dy);
-
- // Push/pop GfxState on/off stack.
- GfxState *save();
- GfxState *restore();
- GBool hasSaves() { return saved != NULL; }
-
- // Misc
- GBool parseBlendMode(Object *obj, GfxBlendMode *mode);
-
-private:
-
- double ctm[6]; // coord transform matrix
- double px1, py1, px2, py2; // page corners (user coords)
- double pageWidth, pageHeight; // page size (pixels)
- int rotate; // page rotation angle
-
- GfxColorSpace *fillColorSpace; // fill color space
- GfxColorSpace *strokeColorSpace; // stroke color space
- GfxColor fillColor; // fill color
- GfxColor strokeColor; // stroke color
- GfxPattern *fillPattern; // fill pattern
- GfxPattern *strokePattern; // stroke pattern
- GfxBlendMode blendMode; // transparency blend mode
- double fillOpacity; // fill opacity
- double strokeOpacity; // stroke opacity
- GBool fillOverprint; // fill overprint
- GBool strokeOverprint; // stroke overprint
-
- double lineWidth; // line width
- double *lineDash; // line dash
- int lineDashLength;
- double lineDashStart;
- int flatness; // curve flatness
- int lineJoin; // line join style
- int lineCap; // line cap style
- double miterLimit; // line miter limit
-
- GfxFont *font; // font
- double fontSize; // font size
- double textMat[6]; // text matrix
- double charSpace; // character spacing
- double wordSpace; // word spacing
- double horizScaling; // horizontal scaling
- double leading; // text leading
- double rise; // text rise
- int render; // text rendering mode
-
- GfxPath *path; // array of path elements
- double curX, curY; // current point (user coords)
- double lineX, lineY; // start of current text line (text coords)
-
- double clipXMin, clipYMin, // bounding box for clip region
- clipXMax, clipYMax;
-
- GfxState *saved; // next GfxState on stack
-
- GfxState(GfxState *state);
-};
-
-#endif
+++ /dev/null
-//========================================================================
-//
-// GlobalParams.cc
-//
-// Copyright 2001-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma implementation
-#endif
-
-#include <string.h>
-#include <stdio.h>
-#include <ctype.h>
-#ifdef ENABLE_PLUGINS
-# ifndef WIN32
-# include <dlfcn.h>
-# endif
-#endif
-#ifdef WIN32
-# include <shlobj.h>
-#endif
-#if HAVE_PAPER_H
-#include <paper.h>
-#endif
-#include "gmem.h"
-#include "GString.h"
-#include "GList.h"
-#include "GHash.h"
-#include "gfile.h"
-#include "Error.h"
-#include "NameToCharCode.h"
-#include "CharCodeToUnicode.h"
-#include "UnicodeMap.h"
-#include "CMap.h"
-#include "BuiltinFontTables.h"
-#include "FontEncodingTables.h"
-#ifdef ENABLE_PLUGINS
-# include "XpdfPluginAPI.h"
-#endif
-#include "GlobalParams.h"
-
-#if MULTITHREADED
-# define lockGlobalParams gLockMutex(&mutex)
-# define lockUnicodeMapCache gLockMutex(&unicodeMapCacheMutex)
-# define lockCMapCache gLockMutex(&cMapCacheMutex)
-# define unlockGlobalParams gUnlockMutex(&mutex)
-# define unlockUnicodeMapCache gUnlockMutex(&unicodeMapCacheMutex)
-# define unlockCMapCache gUnlockMutex(&cMapCacheMutex)
-#else
-# define lockGlobalParams
-# define lockUnicodeMapCache
-# define lockCMapCache
-# define unlockGlobalParams
-# define unlockUnicodeMapCache
-# define unlockCMapCache
-#endif
-
-#include "NameToUnicodeTable.h"
-#include "UnicodeMapTables.h"
-#include "UTF8.h"
-
-#ifdef ENABLE_PLUGINS
-# ifdef WIN32
-extern XpdfPluginVecTable xpdfPluginVecTable;
-# endif
-#endif
-
-//------------------------------------------------------------------------
-
-#define cidToUnicodeCacheSize 4
-#define unicodeToUnicodeCacheSize 4
-
-//------------------------------------------------------------------------
-
-static struct {
- char *name;
- char *t1FileName;
- char *ttFileName;
-} displayFontTab[] = {
- {"Courier", "n022003l.pfb", "cour.ttf"},
- {"Courier-Bold", "n022004l.pfb", "courbd.ttf"},
- {"Courier-BoldOblique", "n022024l.pfb", "courbi.ttf"},
- {"Courier-Oblique", "n022023l.pfb", "couri.ttf"},
- {"Helvetica", "n019003l.pfb", "arial.ttf"},
- {"Helvetica-Bold", "n019004l.pfb", "arialbd.ttf"},
- {"Helvetica-BoldOblique", "n019024l.pfb", "arialbi.ttf"},
- {"Helvetica-Oblique", "n019023l.pfb", "ariali.ttf"},
- {"Symbol", "s050000l.pfb", NULL},
- {"Times-Bold", "n021004l.pfb", "timesbd.ttf"},
- {"Times-BoldItalic", "n021024l.pfb", "timesbi.ttf"},
- {"Times-Italic", "n021023l.pfb", "timesi.ttf"},
- {"Times-Roman", "n021003l.pfb", "times.ttf"},
- {"ZapfDingbats", "d050000l.pfb", NULL},
- {NULL}
-};
-
-#ifdef WIN32
-static char *displayFontDirs[] = {
- "c:/windows/fonts",
- "c:/winnt/fonts",
- NULL
-};
-#else
-static char *displayFontDirs[] = {
- "/usr/share/ghostscript/fonts",
- "/usr/local/share/ghostscript/fonts",
- "/usr/share/fonts/default/Type1",
- "/usr/share/fonts/default/ghostscript",
- "/usr/share/fonts/type1/gsfonts",
- NULL
-};
-#endif
-
-//------------------------------------------------------------------------
-
-GlobalParams *globalParams = NULL;
-
-//------------------------------------------------------------------------
-// DisplayFontParam
-//------------------------------------------------------------------------
-
-DisplayFontParam::DisplayFontParam(GString *nameA,
- DisplayFontParamKind kindA) {
- name = nameA;
- kind = kindA;
- switch (kind) {
- case displayFontT1:
- t1.fileName = NULL;
- break;
- case displayFontTT:
- tt.fileName = NULL;
- break;
- }
-}
-
-DisplayFontParam::~DisplayFontParam() {
- delete name;
- switch (kind) {
- case displayFontT1:
- if (t1.fileName) {
- delete t1.fileName;
- }
- break;
- case displayFontTT:
- if (tt.fileName) {
- delete tt.fileName;
- }
- break;
- }
-}
-
-//------------------------------------------------------------------------
-// PSFontParam
-//------------------------------------------------------------------------
-
-PSFontParam::PSFontParam(GString *pdfFontNameA, int wModeA,
- GString *psFontNameA, GString *encodingA) {
- pdfFontName = pdfFontNameA;
- wMode = wModeA;
- psFontName = psFontNameA;
- encoding = encodingA;
-}
-
-PSFontParam::~PSFontParam() {
- delete pdfFontName;
- delete psFontName;
- if (encoding) {
- delete encoding;
- }
-}
-
-#ifdef ENABLE_PLUGINS
-//------------------------------------------------------------------------
-// Plugin
-//------------------------------------------------------------------------
-
-class Plugin {
-public:
-
- static Plugin *load(char *type, char *name);
- ~Plugin();
-
-private:
-
-#ifdef WIN32
- Plugin(HMODULE libA);
- HMODULE lib;
-#else
- Plugin(void *dlA);
- void *dl;
-#endif
-};
-
-Plugin *Plugin::load(char *type, char *name) {
- GString *path;
- Plugin *plugin;
- XpdfPluginVecTable *vt;
- XpdfBool (*xpdfInitPlugin)(void);
-#ifdef WIN32
- HMODULE libA;
-#else
- void *dlA;
-#endif
-
- path = globalParams->getBaseDir();
- appendToPath(path, "plugins");
- appendToPath(path, type);
- appendToPath(path, name);
-
-#ifdef WIN32
- path->append(".dll");
- if (!(libA = LoadLibrary(path->getCString()))) {
- error(-1, "Failed to load plugin '%s'",
- path->getCString());
- goto err1;
- }
- if (!(vt = (XpdfPluginVecTable *)
- GetProcAddress(libA, "xpdfPluginVecTable"))) {
- error(-1, "Failed to find xpdfPluginVecTable in plugin '%s'",
- path->getCString());
- goto err2;
- }
-#else
- //~ need to deal with other extensions here
- path->append(".so");
- if (!(dlA = dlopen(path->getCString(), RTLD_NOW))) {
- error(-1, "Failed to load plugin '%s': %s",
- path->getCString(), dlerror());
- goto err1;
- }
- if (!(vt = (XpdfPluginVecTable *)dlsym(dlA, "xpdfPluginVecTable"))) {
- error(-1, "Failed to find xpdfPluginVecTable in plugin '%s'",
- path->getCString());
- goto err2;
- }
-#endif
-
- if (vt->version != xpdfPluginVecTable.version) {
- error(-1, "Plugin '%s' is wrong version", path->getCString());
- goto err2;
- }
- memcpy(vt, &xpdfPluginVecTable, sizeof(xpdfPluginVecTable));
-
-#ifdef WIN32
- if (!(xpdfInitPlugin = (XpdfBool (*)(void))
- GetProcAddress(libA, "xpdfInitPlugin"))) {
- error(-1, "Failed to find xpdfInitPlugin in plugin '%s'",
- path->getCString());
- goto err2;
- }
-#else
- if (!(xpdfInitPlugin = (XpdfBool (*)(void))dlsym(dlA, "xpdfInitPlugin"))) {
- error(-1, "Failed to find xpdfInitPlugin in plugin '%s'",
- path->getCString());
- goto err2;
- }
-#endif
-
- if (!(*xpdfInitPlugin)()) {
- error(-1, "Initialization of plugin '%s' failed",
- path->getCString());
- goto err2;
- }
-
-#ifdef WIN32
- plugin = new Plugin(libA);
-#else
- plugin = new Plugin(dlA);
-#endif
-
- delete path;
- return plugin;
-
- err2:
-#ifdef WIN32
- FreeLibrary(libA);
-#else
- dlclose(dlA);
-#endif
- err1:
- delete path;
- return NULL;
-}
-
-#ifdef WIN32
-Plugin::Plugin(HMODULE libA) {
- lib = libA;
-}
-#else
-Plugin::Plugin(void *dlA) {
- dl = dlA;
-}
-#endif
-
-Plugin::~Plugin() {
- void (*xpdfFreePlugin)(void);
-
-#ifdef WIN32
- if ((xpdfFreePlugin = (void (*)(void))
- GetProcAddress(lib, "xpdfFreePlugin"))) {
- (*xpdfFreePlugin)();
- }
- FreeLibrary(lib);
-#else
- if ((xpdfFreePlugin = (void (*)(void))dlsym(dl, "xpdfFreePlugin"))) {
- (*xpdfFreePlugin)();
- }
- dlclose(dl);
-#endif
-}
-
-#endif // ENABLE_PLUGINS
-
-//------------------------------------------------------------------------
-// parsing
-//------------------------------------------------------------------------
-
-GlobalParams::GlobalParams(char *cfgFileName) {
- UnicodeMap *map;
- GString *fileName;
- FILE *f;
- int i;
-
-#if MULTITHREADED
- gInitMutex(&mutex);
- gInitMutex(&unicodeMapCacheMutex);
- gInitMutex(&cMapCacheMutex);
-#endif
-
- initBuiltinFontTables();
-
- // scan the encoding in reverse because we want the lowest-numbered
- // index for each char name ('space' is encoded twice)
- macRomanReverseMap = new NameToCharCode();
- for (i = 255; i >= 0; --i) {
- if (macRomanEncoding[i]) {
- macRomanReverseMap->add(macRomanEncoding[i], (CharCode)i);
- }
- }
-
-#ifdef WIN32
- // baseDir will be set by a call to setBaseDir
- baseDir = new GString();
-#else
- baseDir = appendToPath(getHomeDir(), ".xpdf");
-#endif
- nameToUnicode = new NameToCharCode();
- cidToUnicodes = new GHash(gTrue);
- unicodeToUnicodes = new GHash(gTrue);
- residentUnicodeMaps = new GHash();
- unicodeMaps = new GHash(gTrue);
- cMapDirs = new GHash(gTrue);
- toUnicodeDirs = new GList();
- displayFonts = new GHash();
- displayCIDFonts = new GHash();
- displayNamedCIDFonts = new GHash();
-#if HAVE_PAPER_H
- char *paperName;
- const struct paper *paperType;
- paperinit();
- if ((paperName = systempapername())) {
- paperType = paperinfo(paperName);
- psPaperWidth = (int)paperpswidth(paperType);
- psPaperHeight = (int)paperpsheight(paperType);
- } else {
- error(-1, "No paper information available - using defaults");
- psPaperWidth = defPaperWidth;
- psPaperHeight = defPaperHeight;
- }
- paperdone();
-#else
- psPaperWidth = defPaperWidth;
- psPaperHeight = defPaperHeight;
-#endif
- psImageableLLX = psImageableLLY = 0;
- psImageableURX = psPaperWidth;
- psImageableURY = psPaperHeight;
- psCrop = gTrue;
- psExpandSmaller = gFalse;
- psShrinkLarger = gTrue;
- psCenter = gTrue;
- psDuplex = gFalse;
- psLevel = psLevel2;
- psFile = NULL;
- psFonts = new GHash();
- psNamedFonts16 = new GList();
- psFonts16 = new GList();
- psEmbedType1 = gTrue;
- psEmbedTrueType = gTrue;
- psEmbedCIDPostScript = gTrue;
- psEmbedCIDTrueType = gTrue;
- psOPI = gFalse;
- psASCIIHex = gFalse;
- textEncoding = new GString("Latin1");
-#if defined(WIN32)
- textEOL = eolDOS;
-#elif defined(MACOS)
- textEOL = eolMac;
-#else
- textEOL = eolUnix;
-#endif
- textPageBreaks = gTrue;
- textKeepTinyChars = gFalse;
- fontDirs = new GList();
- initialZoom = new GString("125");
- continuousView = gFalse;
- enableT1lib = gTrue;
- enableFreeType = gTrue;
- antialias = gTrue;
- urlCommand = NULL;
- movieCommand = NULL;
- mapNumericCharNames = gTrue;
- printCommands = gFalse;
- errQuiet = gFalse;
-
- cidToUnicodeCache = new CharCodeToUnicodeCache(cidToUnicodeCacheSize);
- unicodeToUnicodeCache =
- new CharCodeToUnicodeCache(unicodeToUnicodeCacheSize);
- unicodeMapCache = new UnicodeMapCache();
- cMapCache = new CMapCache();
-
-#ifdef ENABLE_PLUGINS
- plugins = new GList();
- securityHandlers = new GList();
-#endif
-
- // set up the initial nameToUnicode table
- for (i = 0; nameToUnicodeTab[i].name; ++i) {
- nameToUnicode->add(nameToUnicodeTab[i].name, nameToUnicodeTab[i].u);
- }
-
- // set up the residentUnicodeMaps table
- map = new UnicodeMap("Latin1", gFalse,
- latin1UnicodeMapRanges, latin1UnicodeMapLen);
- residentUnicodeMaps->add(map->getEncodingName(), map);
- map = new UnicodeMap("ASCII7", gFalse,
- ascii7UnicodeMapRanges, ascii7UnicodeMapLen);
- residentUnicodeMaps->add(map->getEncodingName(), map);
- map = new UnicodeMap("Symbol", gFalse,
- symbolUnicodeMapRanges, symbolUnicodeMapLen);
- residentUnicodeMaps->add(map->getEncodingName(), map);
- map = new UnicodeMap("ZapfDingbats", gFalse, zapfDingbatsUnicodeMapRanges,
- zapfDingbatsUnicodeMapLen);
- residentUnicodeMaps->add(map->getEncodingName(), map);
- map = new UnicodeMap("UTF-8", gTrue, &mapUTF8);
- residentUnicodeMaps->add(map->getEncodingName(), map);
- map = new UnicodeMap("UCS-2", gTrue, &mapUCS2);
- residentUnicodeMaps->add(map->getEncodingName(), map);
-
- // look for a user config file, then a system-wide config file
- f = NULL;
- fileName = NULL;
- if (cfgFileName && cfgFileName[0]) {
- fileName = new GString(cfgFileName);
- if (!(f = fopen(fileName->getCString(), "r"))) {
- delete fileName;
- }
- }
- if (!f) {
- fileName = appendToPath(getHomeDir(), xpdfUserConfigFile);
- if (!(f = fopen(fileName->getCString(), "r"))) {
- delete fileName;
- }
- }
- if (!f) {
-#if defined(WIN32) && !defined(__CYGWIN32__)
- char buf[512];
- i = GetModuleFileName(NULL, buf, sizeof(buf));
- if (i <= 0 || i >= sizeof(buf)) {
- // error or path too long for buffer - just use the current dir
- buf[0] = '\0';
- }
- fileName = grabPath(buf);
- appendToPath(fileName, xpdfSysConfigFile);
-#else
- fileName = new GString(xpdfSysConfigFile);
-#endif
- if (!(f = fopen(fileName->getCString(), "r"))) {
- delete fileName;
- }
- }
- if (f) {
- parseFile(fileName, f);
- delete fileName;
- fclose(f);
- }
-}
-
-void GlobalParams::parseFile(GString *fileName, FILE *f) {
- int line;
- GList *tokens;
- GString *cmd, *incFile;
- char *p1, *p2;
- char buf[512];
- FILE *f2;
-
- /* extract path */
- if(fileName) {
- char* cfgFileName = fileName->getCString();
- char* pos1 = strrchr(cfgFileName, '/');
- char* pos2 = strrchr(cfgFileName, '\\');
- char* p = pos1>pos2?pos1:pos2;
- int pos = p ? p-cfgFileName : -1;
- GString*path = new GString(new GString(cfgFileName), 0, (pos < 0 ? strlen(cfgFileName): pos));
- if(pos1>=0)
- path->append('/');
- else if(pos2>=0)
- path->append('\\');
- else
-#ifdef WIN32
- path->append('\\');
-#else
- path->append('/');
-#endif
- this->path = path;
- } else {
- this->path = new GString();
- }
-
- line = 1;
- while (getLine(buf, sizeof(buf) - 1, f)) {
-
- // break the line into tokens
- tokens = new GList();
- p1 = buf;
- while (*p1) {
- for (; *p1 && isspace(*p1); ++p1) ;
- if (!*p1) {
- break;
- }
- if (*p1 == '"' || *p1 == '\'') {
- for (p2 = p1 + 1; *p2 && *p2 != *p1; ++p2) ;
- ++p1;
- } else {
- for (p2 = p1 + 1; *p2 && !isspace(*p2); ++p2) ;
- }
- tokens->append(new GString(p1, p2 - p1));
- p1 = *p2 ? p2 + 1 : p2;
- }
-
- if (tokens->getLength() > 0 &&
- ((GString *)tokens->get(0))->getChar(0) != '#') {
- cmd = (GString *)tokens->get(0);
- if (!cmd->cmp("include")) {
- if (tokens->getLength() == 2) {
- incFile = (GString *)tokens->get(1);
- if ((f2 = fopen(incFile->getCString(), "r"))) {
- parseFile(incFile, f2);
- fclose(f2);
- } else {
- error(-1, "Couldn't find included config file: '%s' (%s:%d)",
- incFile->getCString(), fileName->getCString(), line);
- }
- } else {
- error(-1, "Bad 'include' config file command (%s:%d)",
- fileName->getCString(), line);
- }
- } else if (!cmd->cmp("nameToUnicode")) {
- parseNameToUnicode(tokens, fileName, line);
- } else if (!cmd->cmp("cidToUnicode")) {
- parseCIDToUnicode(tokens, fileName, line);
- } else if (!cmd->cmp("unicodeToUnicode")) {
- parseUnicodeToUnicode(tokens, fileName, line);
- } else if (!cmd->cmp("unicodeMap")) {
- parseUnicodeMap(tokens, fileName, line);
- } else if (!cmd->cmp("cMapDir")) {
- parseCMapDir(tokens, fileName, line);
- } else if (!cmd->cmp("toUnicodeDir")) {
- parseToUnicodeDir(tokens, fileName, line);
- } else if (!cmd->cmp("displayFontT1")) {
- parseDisplayFont(tokens, displayFonts, displayFontT1, fileName, line);
- } else if (!cmd->cmp("displayFontTT")) {
- parseDisplayFont(tokens, displayFonts, displayFontTT, fileName, line);
- } else if (!cmd->cmp("displayNamedCIDFontT1")) {
- parseDisplayFont(tokens, displayNamedCIDFonts,
- displayFontT1, fileName, line);
- } else if (!cmd->cmp("displayCIDFontT1")) {
- parseDisplayFont(tokens, displayCIDFonts,
- displayFontT1, fileName, line);
- } else if (!cmd->cmp("displayNamedCIDFontTT")) {
- parseDisplayFont(tokens, displayNamedCIDFonts,
- displayFontTT, fileName, line);
- } else if (!cmd->cmp("displayCIDFontTT")) {
- parseDisplayFont(tokens, displayCIDFonts,
- displayFontTT, fileName, line);
- } else if (!cmd->cmp("psFile")) {
- parsePSFile(tokens, fileName, line);
- } else if (!cmd->cmp("psFont")) {
- parsePSFont(tokens, fileName, line);
- } else if (!cmd->cmp("psNamedFont16")) {
- parsePSFont16("psNamedFont16", psNamedFonts16,
- tokens, fileName, line);
- } else if (!cmd->cmp("psFont16")) {
- parsePSFont16("psFont16", psFonts16, tokens, fileName, line);
- } else if (!cmd->cmp("psPaperSize")) {
- parsePSPaperSize(tokens, fileName, line);
- } else if (!cmd->cmp("psImageableArea")) {
- parsePSImageableArea(tokens, fileName, line);
- } else if (!cmd->cmp("psCrop")) {
- parseYesNo("psCrop", &psCrop, tokens, fileName, line);
- } else if (!cmd->cmp("psExpandSmaller")) {
- parseYesNo("psExpandSmaller", &psExpandSmaller,
- tokens, fileName, line);
- } else if (!cmd->cmp("psShrinkLarger")) {
- parseYesNo("psShrinkLarger", &psShrinkLarger, tokens, fileName, line);
- } else if (!cmd->cmp("psCenter")) {
- parseYesNo("psCenter", &psCenter, tokens, fileName, line);
- } else if (!cmd->cmp("psDuplex")) {
- parseYesNo("psDuplex", &psDuplex, tokens, fileName, line);
- } else if (!cmd->cmp("psLevel")) {
- parsePSLevel(tokens, fileName, line);
- } else if (!cmd->cmp("psEmbedType1Fonts")) {
- parseYesNo("psEmbedType1", &psEmbedType1, tokens, fileName, line);
- } else if (!cmd->cmp("psEmbedTrueTypeFonts")) {
- parseYesNo("psEmbedTrueType", &psEmbedTrueType,
- tokens, fileName, line);
- } else if (!cmd->cmp("psEmbedCIDPostScriptFonts")) {
- parseYesNo("psEmbedCIDPostScript", &psEmbedCIDPostScript,
- tokens, fileName, line);
- } else if (!cmd->cmp("psEmbedCIDTrueTypeFonts")) {
- parseYesNo("psEmbedCIDTrueType", &psEmbedCIDTrueType,
- tokens, fileName, line);
- } else if (!cmd->cmp("psOPI")) {
- parseYesNo("psOPI", &psOPI, tokens, fileName, line);
- } else if (!cmd->cmp("psASCIIHex")) {
- parseYesNo("psASCIIHex", &psASCIIHex, tokens, fileName, line);
- } else if (!cmd->cmp("textEncoding")) {
- parseTextEncoding(tokens, fileName, line);
- } else if (!cmd->cmp("textEOL")) {
- parseTextEOL(tokens, fileName, line);
- } else if (!cmd->cmp("textPageBreaks")) {
- parseYesNo("textPageBreaks", &textPageBreaks,
- tokens, fileName, line);
- } else if (!cmd->cmp("textKeepTinyChars")) {
- parseYesNo("textKeepTinyChars", &textKeepTinyChars,
- tokens, fileName, line);
- } else if (!cmd->cmp("fontDir")) {
- parseFontDir(tokens, fileName, line);
- } else if (!cmd->cmp("initialZoom")) {
- parseInitialZoom(tokens, fileName, line);
- } else if (!cmd->cmp("continuousView")) {
- parseYesNo("continuousView", &continuousView, tokens, fileName, line);
- } else if (!cmd->cmp("enableT1lib")) {
- parseYesNo("enableT1lib", &enableT1lib, tokens, fileName, line);
- } else if (!cmd->cmp("enableFreeType")) {
- parseYesNo("enableFreeType", &enableFreeType, tokens, fileName, line);
- } else if (!cmd->cmp("antialias")) {
- parseYesNo("antialias", &antialias, tokens, fileName, line);
- } else if (!cmd->cmp("urlCommand")) {
- parseCommand("urlCommand", &urlCommand, tokens, fileName, line);
- } else if (!cmd->cmp("movieCommand")) {
- parseCommand("movieCommand", &movieCommand, tokens, fileName, line);
- } else if (!cmd->cmp("mapNumericCharNames")) {
- parseYesNo("mapNumericCharNames", &mapNumericCharNames,
- tokens, fileName, line);
- } else if (!cmd->cmp("printCommands")) {
- parseYesNo("printCommands", &printCommands, tokens, fileName, line);
- } else if (!cmd->cmp("errQuiet")) {
- parseYesNo("errQuiet", &errQuiet, tokens, fileName, line);
- } else {
- error(-1, "Unknown config file command '%s' (%s:%d)",
- cmd->getCString(), fileName->getCString(), line);
- if (!cmd->cmp("displayFontX") ||
- !cmd->cmp("displayNamedCIDFontX") ||
- !cmd->cmp("displayCIDFontX")) {
- error(-1, "-- Xpdf no longer supports X fonts");
- } else if (!cmd->cmp("t1libControl") || !cmd->cmp("freetypeControl")) {
- error(-1, "-- The t1libControl and freetypeControl options have been replaced");
- error(-1, " by the enableT1lib, enableFreeType, and antialias options");
- } else if (!cmd->cmp("fontpath") || !cmd->cmp("fontmap")) {
- error(-1, "-- the config file format has changed since Xpdf 0.9x");
- }
- }
- }
-
- deleteGList(tokens, GString);
- ++line;
- }
-}
-
-static GString* qualify_filename(GString*path, GString*filename)
-{
- GString*fullpath = 0;
- char*prefix = "/usr/local/share/xpdf/";
-
- if (filename->getChar(0) != '\\' && filename->getChar(0) != '/') {
- /* relative path */
- fullpath = path->copy();
- fullpath->append(filename);
- } else if (!strncmp(filename->getCString(), prefix, strlen(prefix))) {
- /* xpdf default path */
- char*s = strchr(filename->getCString()+strlen(prefix), '/');
- if(s) {
- fullpath = path->copy();
- fullpath->append(s+1);
- } else {
- fullpath = filename->copy();
- }
- } else {
- /* absolute path */
- fullpath = filename->copy();
- }
- //printf("%s -%s-> %s\n", filename->getCString(), path->getCString(), fullpath->getCString());
- return fullpath;
-}
-
-void GlobalParams::parseNameToUnicode(GList *tokens, GString *fileName,
- int line) {
- GString *name;
- char *tok1, *tok2;
- FILE *f;
- char buf[256];
- int line2;
- Unicode u;
-
- if (tokens->getLength() != 2) {
- error(-1, "Bad 'nameToUnicode' config file command (%s:%d)",
- fileName->getCString(), line);
- return;
- }
- name = qualify_filename(this->path, (GString *)tokens->get(1));
- if (!(f = fopen(name->getCString(), "r"))) {
- error(-1, "Couldn't open 'nameToUnicode' file '%s'",
- name->getCString());
- return;
- }
- line2 = 1;
- while (getLine(buf, sizeof(buf), f)) {
- tok1 = strtok(buf, " \t\r\n");
- tok2 = strtok(NULL, " \t\r\n");
- if (tok1 && tok2) {
- sscanf(tok1, "%x", &u);
- nameToUnicode->add(tok2, u);
- } else {
- error(-1, "Bad line in 'nameToUnicode' file (%s:%d)", name, line2);
- }
- ++line2;
- }
- fclose(f);
-}
-
-void GlobalParams::parseCIDToUnicode(GList *tokens, GString *fileName,
- int line) {
- GString *collection, *name, *old;
-
- if (tokens->getLength() != 3) {
- error(-1, "Bad 'cidToUnicode' config file command (%s:%d)",
- fileName->getCString(), line);
- return;
- }
- collection = (GString *)tokens->get(1);
- name = (GString *)tokens->get(2);
-
- if ((old = (GString *)cidToUnicodes->remove(collection))) {
- delete old;
- }
-
- cidToUnicodes->add(collection->copy(), qualify_filename(this->path, name));
-}
-
-void GlobalParams::parseUnicodeToUnicode(GList *tokens, GString *fileName,
- int line) {
- GString *font, *file, *old;
-
- if (tokens->getLength() != 3) {
- error(-1, "Bad 'unicodeToUnicode' config file command (%s:%d)",
- fileName->getCString(), line);
- return;
- }
- font = (GString *)tokens->get(1);
- file = (GString *)tokens->get(2);
- if ((old = (GString *)unicodeToUnicodes->remove(font))) {
- delete old;
- }
-
- unicodeToUnicodes->add(font->copy(), qualify_filename(this->path, file));
-}
-
-void GlobalParams::parseUnicodeMap(GList *tokens, GString *fileName,
- int line) {
- GString *encodingName, *name, *old;
-
- if (tokens->getLength() != 3) {
- error(-1, "Bad 'unicodeMap' config file command (%s:%d)",
- fileName->getCString(), line);
- return;
- }
- encodingName = (GString *)tokens->get(1);
- name = (GString *)tokens->get(2);
- if ((old = (GString *)unicodeMaps->remove(encodingName))) {
- delete old;
- }
-
- unicodeMaps->add(encodingName->copy(), qualify_filename(this->path, name));
-}
-
-void GlobalParams::parseCMapDir(GList *tokens, GString *fileName, int line) {
- GString *collection, *dir;
- GList *list;
-
- if (tokens->getLength() != 3) {
- error(-1, "Bad 'cMapDir' config file command (%s:%d)",
- fileName->getCString(), line);
- return;
- }
- collection = (GString *)tokens->get(1);
- dir = (GString *)tokens->get(2);
- if (!(list = (GList *)cMapDirs->lookup(collection))) {
- list = new GList();
- cMapDirs->add(collection->copy(), list);
- }
-
- list->append(qualify_filename(this->path, dir));
-}
-
-void GlobalParams::parseToUnicodeDir(GList *tokens, GString *fileName,
- int line) {
- GString *dir;
-
- if (tokens->getLength() != 2) {
- error(-1, "Bad 'toUnicodeDir' config file command (%s:%d)",
- fileName->getCString(), line);
- return;
- }
-
- dir = (GString *)tokens->get(1);
-
- toUnicodeDirs->append(qualify_filename(this->path, dir));
-}
-
-void GlobalParams::parseDisplayFont(GList *tokens, GHash *fontHash,
- DisplayFontParamKind kind,
- GString *fileName, int line) {
- DisplayFontParam *param, *old;
- GString *file;
-
- if (tokens->getLength() < 2) {
- goto err1;
- }
- param = new DisplayFontParam(((GString *)tokens->get(1))->copy(), kind);
-
- switch (kind) {
- case displayFontT1:
- if (tokens->getLength() != 3) {
- goto err2;
- }
- file = (GString *)tokens->get(2);
- param->t1.fileName = qualify_filename(this->path, file);
- break;
- case displayFontTT:
- if (tokens->getLength() != 3) {
- goto err2;
- }
- file = (GString *)tokens->get(2);
- param->tt.fileName = qualify_filename(this->path, file);
- break;
- }
-
- if ((old = (DisplayFontParam *)fontHash->remove(param->name))) {
- delete old;
- }
- fontHash->add(param->name, param);
- return;
-
- err2:
- delete param;
- err1:
- error(-1, "Bad 'display*Font*' config file command (%s:%d)",
- fileName->getCString(), line);
-}
-
-void GlobalParams::parsePSPaperSize(GList *tokens, GString *fileName,
- int line) {
- GString *tok;
-
- if (tokens->getLength() == 2) {
- tok = (GString *)tokens->get(1);
- if (!setPSPaperSize(tok->getCString())) {
- error(-1, "Bad 'psPaperSize' config file command (%s:%d)",
- fileName->getCString(), line);
- }
- } else if (tokens->getLength() == 3) {
- tok = (GString *)tokens->get(1);
- psPaperWidth = atoi(tok->getCString());
- tok = (GString *)tokens->get(2);
- psPaperHeight = atoi(tok->getCString());
- psImageableLLX = psImageableLLY = 0;
- psImageableURX = psPaperWidth;
- psImageableURY = psPaperHeight;
- } else {
- error(-1, "Bad 'psPaperSize' config file command (%s:%d)",
- fileName->getCString(), line);
- }
-}
-
-void GlobalParams::parsePSImageableArea(GList *tokens, GString *fileName,
- int line) {
- if (tokens->getLength() != 5) {
- error(-1, "Bad 'psImageableArea' config file command (%s:%d)",
- fileName->getCString(), line);
- return;
- }
- psImageableLLX = atoi(((GString *)tokens->get(1))->getCString());
- psImageableLLY = atoi(((GString *)tokens->get(2))->getCString());
- psImageableURX = atoi(((GString *)tokens->get(3))->getCString());
- psImageableURY = atoi(((GString *)tokens->get(4))->getCString());
-}
-
-void GlobalParams::parsePSLevel(GList *tokens, GString *fileName, int line) {
- GString *tok;
-
- if (tokens->getLength() != 2) {
- error(-1, "Bad 'psLevel' config file command (%s:%d)",
- fileName->getCString(), line);
- return;
- }
- tok = (GString *)tokens->get(1);
- if (!tok->cmp("level1")) {
- psLevel = psLevel1;
- } else if (!tok->cmp("level1sep")) {
- psLevel = psLevel1Sep;
- } else if (!tok->cmp("level2")) {
- psLevel = psLevel2;
- } else if (!tok->cmp("level2sep")) {
- psLevel = psLevel2Sep;
- } else if (!tok->cmp("level3")) {
- psLevel = psLevel3;
- } else if (!tok->cmp("level3Sep")) {
- psLevel = psLevel3Sep;
- } else {
- error(-1, "Bad 'psLevel' config file command (%s:%d)",
- fileName->getCString(), line);
- }
-}
-
-void GlobalParams::parsePSFile(GList *tokens, GString *fileName, int line) {
- if (tokens->getLength() != 2) {
- error(-1, "Bad 'psFile' config file command (%s:%d)",
- fileName->getCString(), line);
- return;
- }
- if (psFile) {
- delete psFile;
- }
- psFile = ((GString *)tokens->get(1))->copy();
-}
-
-void GlobalParams::parsePSFont(GList *tokens, GString *fileName, int line) {
- PSFontParam *param;
-
- if (tokens->getLength() != 3) {
- error(-1, "Bad 'psFont' config file command (%s:%d)",
- fileName->getCString(), line);
- return;
- }
- param = new PSFontParam(((GString *)tokens->get(1))->copy(), 0,
- ((GString *)tokens->get(2))->copy(), NULL);
- psFonts->add(param->pdfFontName, param);
-}
-
-void GlobalParams::parsePSFont16(char *cmdName, GList *fontList,
- GList *tokens, GString *fileName, int line) {
- PSFontParam *param;
- int wMode;
- GString *tok;
-
- if (tokens->getLength() != 5) {
- error(-1, "Bad '%s' config file command (%s:%d)",
- cmdName, fileName->getCString(), line);
- return;
- }
- tok = (GString *)tokens->get(2);
- if (!tok->cmp("H")) {
- wMode = 0;
- } else if (!tok->cmp("V")) {
- wMode = 1;
- } else {
- error(-1, "Bad '%s' config file command (%s:%d)",
- cmdName, fileName->getCString(), line);
- return;
- }
- param = new PSFontParam(((GString *)tokens->get(1))->copy(),
- wMode,
- ((GString *)tokens->get(3))->copy(),
- ((GString *)tokens->get(4))->copy());
- fontList->append(param);
-}
-
-void GlobalParams::parseTextEncoding(GList *tokens, GString *fileName,
- int line) {
- if (tokens->getLength() != 2) {
- error(-1, "Bad 'textEncoding' config file command (%s:%d)",
- fileName->getCString(), line);
- return;
- }
- delete textEncoding;
- textEncoding = ((GString *)tokens->get(1))->copy();
-}
-
-void GlobalParams::parseTextEOL(GList *tokens, GString *fileName, int line) {
- GString *tok;
-
- if (tokens->getLength() != 2) {
- error(-1, "Bad 'textEOL' config file command (%s:%d)",
- fileName->getCString(), line);
- return;
- }
- tok = (GString *)tokens->get(1);
- if (!tok->cmp("unix")) {
- textEOL = eolUnix;
- } else if (!tok->cmp("dos")) {
- textEOL = eolDOS;
- } else if (!tok->cmp("mac")) {
- textEOL = eolMac;
- } else {
- error(-1, "Bad 'textEOL' config file command (%s:%d)",
- fileName->getCString(), line);
- }
-}
-
-void GlobalParams::parseFontDir(GList *tokens, GString *fileName, int line) {
- if (tokens->getLength() != 2) {
- error(-1, "Bad 'fontDir' config file command (%s:%d)",
- fileName->getCString(), line);
- return;
- }
- fontDirs->append(((GString *)tokens->get(1))->copy());
-}
-
-void GlobalParams::parseInitialZoom(GList *tokens,
- GString *fileName, int line) {
- if (tokens->getLength() != 2) {
- error(-1, "Bad 'initialZoom' config file command (%s:%d)",
- fileName->getCString(), line);
- return;
- }
- delete initialZoom;
- initialZoom = ((GString *)tokens->get(1))->copy();
-}
-
-void GlobalParams::parseCommand(char *cmdName, GString **val,
- GList *tokens, GString *fileName, int line) {
- if (tokens->getLength() != 2) {
- error(-1, "Bad '%s' config file command (%s:%d)",
- cmdName, fileName->getCString(), line);
- return;
- }
- if (*val) {
- delete *val;
- }
- *val = ((GString *)tokens->get(1))->copy();
-}
-
-void GlobalParams::parseYesNo(char *cmdName, GBool *flag,
- GList *tokens, GString *fileName, int line) {
- GString *tok;
-
- if (tokens->getLength() != 2) {
- error(-1, "Bad '%s' config file command (%s:%d)",
- cmdName, fileName->getCString(), line);
- return;
- }
- tok = (GString *)tokens->get(1);
- if (!parseYesNo2(tok->getCString(), flag)) {
- error(-1, "Bad '%s' config file command (%s:%d)",
- cmdName, fileName->getCString(), line);
- }
-}
-
-GBool GlobalParams::parseYesNo2(char *token, GBool *flag) {
- if (!strcmp(token, "yes")) {
- *flag = gTrue;
- } else if (!strcmp(token, "no")) {
- *flag = gFalse;
- } else {
- return gFalse;
- }
- return gTrue;
-}
-
-GlobalParams::~GlobalParams() {
- GHashIter *iter;
- GString *key;
- GList *list;
-
- freeBuiltinFontTables();
-
- delete macRomanReverseMap;
-
- delete baseDir;
- delete nameToUnicode;
- deleteGHash(cidToUnicodes, GString);
- deleteGHash(unicodeToUnicodes, GString);
- deleteGHash(residentUnicodeMaps, UnicodeMap);
- deleteGHash(unicodeMaps, GString);
- deleteGList(toUnicodeDirs, GString);
- deleteGHash(displayFonts, DisplayFontParam);
- deleteGHash(displayCIDFonts, DisplayFontParam);
- deleteGHash(displayNamedCIDFonts, DisplayFontParam);
- if (psFile) {
- delete psFile;
- }
- deleteGHash(psFonts, PSFontParam);
- deleteGList(psNamedFonts16, PSFontParam);
- deleteGList(psFonts16, PSFontParam);
- delete textEncoding;
- deleteGList(fontDirs, GString);
- delete initialZoom;
- if (urlCommand) {
- delete urlCommand;
- }
- if (movieCommand) {
- delete movieCommand;
- }
-
- cMapDirs->startIter(&iter);
- while (cMapDirs->getNext(&iter, &key, (void **)&list)) {
- deleteGList(list, GString);
- }
- delete cMapDirs;
-
- delete cidToUnicodeCache;
- delete unicodeToUnicodeCache;
- delete unicodeMapCache;
- delete cMapCache;
-
-#ifdef ENABLE_PLUGINS
- delete securityHandlers;
- deleteGList(plugins, Plugin);
-#endif
-
-#if MULTITHREADED
- gDestroyMutex(&mutex);
- gDestroyMutex(&unicodeMapCacheMutex);
- gDestroyMutex(&cMapCacheMutex);
-#endif
-}
-
-//------------------------------------------------------------------------
-
-void GlobalParams::setBaseDir(char *dir) {
- delete baseDir;
- baseDir = new GString(dir);
-}
-
-void GlobalParams::setupBaseFonts(char *dir) {
- GString *fontName;
- GString *fileName;
-#ifdef WIN32
- HMODULE shell32Lib;
- BOOL (__stdcall *SHGetSpecialFolderPathFunc)(HWND hwndOwner,
- LPTSTR lpszPath,
- int nFolder,
- BOOL fCreate);
- char winFontDir[MAX_PATH];
-#endif
- FILE *f;
- DisplayFontParamKind kind;
- DisplayFontParam *dfp;
- int i, j;
-
-#ifdef WIN32
- // SHGetSpecialFolderPath isn't available in older versions of
- // shell32.dll (Win95 and WinNT4), so do a dynamic load
- winFontDir[0] = '\0';
- if ((shell32Lib = LoadLibrary("shell32.dll"))) {
- if ((SHGetSpecialFolderPathFunc =
- (BOOL (__stdcall *)(HWND hwndOwner, LPTSTR lpszPath,
- int nFolder, BOOL fCreate))
- GetProcAddress(shell32Lib, "SHGetSpecialFolderPath"))) {
- if (!(*SHGetSpecialFolderPathFunc)(NULL, winFontDir,
- CSIDL_FONTS, FALSE)) {
- winFontDir[0] = '\0';
- }
- }
- }
-#endif
- for (i = 0; displayFontTab[i].name; ++i) {
- fontName = new GString(displayFontTab[i].name);
- if (getDisplayFont(fontName)) {
- delete fontName;
- continue;
- }
- fileName = NULL;
- kind = displayFontT1; // make gcc happy
- if (dir) {
- fileName = appendToPath(new GString(dir), displayFontTab[i].t1FileName);
- kind = displayFontT1;
- if ((f = fopen(fileName->getCString(), "rb"))) {
- fclose(f);
- } else {
- delete fileName;
- fileName = NULL;
- }
- }
-#ifdef WIN32
- if (!fileName && winFontDir[0] && displayFontTab[i].ttFileName) {
- fileName = appendToPath(new GString(winFontDir),
- displayFontTab[i].ttFileName);
- kind = displayFontTT;
- if ((f = fopen(fileName->getCString(), "rb"))) {
- fclose(f);
- } else {
- delete fileName;
- fileName = NULL;
- }
- }
- // SHGetSpecialFolderPath(CSIDL_FONTS) doesn't work on Win 2k Server
- // or Win2003 Server, or with older versions of shell32.dll, so check
- // the "standard" directories
- if (displayFontTab[i].ttFileName) {
- for (j = 0; !fileName && displayFontDirs[j]; ++j) {
- fileName = appendToPath(new GString(displayFontDirs[j]),
- displayFontTab[i].ttFileName);
- kind = displayFontTT;
- if ((f = fopen(fileName->getCString(), "rb"))) {
- fclose(f);
- } else {
- delete fileName;
- fileName = NULL;
- }
- }
- }
-#else
- for (j = 0; !fileName && displayFontDirs[j]; ++j) {
- fileName = appendToPath(new GString(displayFontDirs[j]),
- displayFontTab[i].t1FileName);
- kind = displayFontT1;
- if ((f = fopen(fileName->getCString(), "rb"))) {
- fclose(f);
- } else {
- delete fileName;
- fileName = NULL;
- }
- }
-#endif
- if (!fileName) {
- error(-1, "No display font for '%s'", displayFontTab[i].name);
- delete fontName;
- continue;
- }
- dfp = new DisplayFontParam(fontName, kind);
- dfp->t1.fileName = fileName;
- globalParams->addDisplayFont(dfp);
- }
-}
-
-//------------------------------------------------------------------------
-// accessors
-//------------------------------------------------------------------------
-
-CharCode GlobalParams::getMacRomanCharCode(char *charName) {
- // no need to lock - macRomanReverseMap is constant
- return macRomanReverseMap->lookup(charName);
-}
-
-GString *GlobalParams::getBaseDir() {
- GString *s;
-
- lockGlobalParams;
- s = baseDir->copy();
- unlockGlobalParams;
- return s;
-}
-
-Unicode GlobalParams::mapNameToUnicode(char *charName) {
- // no need to lock - nameToUnicode is constant
- return nameToUnicode->lookup(charName);
-}
-
-UnicodeMap *GlobalParams::getResidentUnicodeMap(GString *encodingName) {
- UnicodeMap *map;
-
- lockGlobalParams;
- map = (UnicodeMap *)residentUnicodeMaps->lookup(encodingName);
- unlockGlobalParams;
- if (map) {
- map->incRefCnt();
- }
- return map;
-}
-
-FILE *GlobalParams::getUnicodeMapFile(GString *encodingName) {
- GString *fileName;
- FILE *f;
-
- lockGlobalParams;
- if ((fileName = (GString *)unicodeMaps->lookup(encodingName))) {
- f = fopen(fileName->getCString(), "r");
- } else {
- f = NULL;
- }
- unlockGlobalParams;
- return f;
-}
-
-FILE *GlobalParams::findCMapFile(GString *collection, GString *cMapName) {
- GList *list;
- GString *dir;
- GString *fileName;
- FILE *f;
- int i;
-
- lockGlobalParams;
- if (!(list = (GList *)cMapDirs->lookup(collection))) {
- unlockGlobalParams;
- return NULL;
- }
- for (i = 0; i < list->getLength(); ++i) {
- dir = (GString *)list->get(i);
- fileName = appendToPath(dir->copy(), cMapName->getCString());
- f = fopen(fileName->getCString(), "r");
- delete fileName;
- if (f) {
- unlockGlobalParams;
- return f;
- }
- }
- unlockGlobalParams;
- return NULL;
-}
-
-FILE *GlobalParams::findToUnicodeFile(GString *name) {
- GString *dir, *fileName;
- FILE *f;
- int i;
-
- lockGlobalParams;
- for (i = 0; i < toUnicodeDirs->getLength(); ++i) {
- dir = (GString *)toUnicodeDirs->get(i);
- fileName = appendToPath(dir->copy(), name->getCString());
- f = fopen(fileName->getCString(), "r");
- delete fileName;
- if (f) {
- unlockGlobalParams;
- return f;
- }
- }
- unlockGlobalParams;
- return NULL;
-}
-
-DisplayFontParam *GlobalParams::getDisplayFont(GString *fontName) {
- DisplayFontParam *dfp;
-
- lockGlobalParams;
- dfp = (DisplayFontParam *)displayFonts->lookup(fontName);
- unlockGlobalParams;
- return dfp;
-}
-
-DisplayFontParam *GlobalParams::getDisplayCIDFont(GString *fontName,
- GString *collection) {
- DisplayFontParam *dfp;
-
- lockGlobalParams;
- if (!fontName ||
- !(dfp = (DisplayFontParam *)displayNamedCIDFonts->lookup(fontName))) {
- dfp = (DisplayFontParam *)displayCIDFonts->lookup(collection);
- }
- unlockGlobalParams;
- return dfp;
-}
-
-GString *GlobalParams::getPSFile() {
- GString *s;
-
- lockGlobalParams;
- s = psFile ? psFile->copy() : (GString *)NULL;
- unlockGlobalParams;
- return s;
-}
-
-int GlobalParams::getPSPaperWidth() {
- int w;
-
- lockGlobalParams;
- w = psPaperWidth;
- unlockGlobalParams;
- return w;
-}
-
-int GlobalParams::getPSPaperHeight() {
- int h;
-
- lockGlobalParams;
- h = psPaperHeight;
- unlockGlobalParams;
- return h;
-}
-
-void GlobalParams::getPSImageableArea(int *llx, int *lly, int *urx, int *ury) {
- lockGlobalParams;
- *llx = psImageableLLX;
- *lly = psImageableLLY;
- *urx = psImageableURX;
- *ury = psImageableURY;
- unlockGlobalParams;
-}
-
-GBool GlobalParams::getPSCrop() {
- GBool f;
-
- lockGlobalParams;
- f = psCrop;
- unlockGlobalParams;
- return f;
-}
-
-GBool GlobalParams::getPSExpandSmaller() {
- GBool f;
-
- lockGlobalParams;
- f = psExpandSmaller;
- unlockGlobalParams;
- return f;
-}
-
-GBool GlobalParams::getPSShrinkLarger() {
- GBool f;
-
- lockGlobalParams;
- f = psShrinkLarger;
- unlockGlobalParams;
- return f;
-}
-
-GBool GlobalParams::getPSCenter() {
- GBool f;
-
- lockGlobalParams;
- f = psCenter;
- unlockGlobalParams;
- return f;
-}
-
-GBool GlobalParams::getPSDuplex() {
- GBool d;
-
- lockGlobalParams;
- d = psDuplex;
- unlockGlobalParams;
- return d;
-}
-
-PSLevel GlobalParams::getPSLevel() {
- PSLevel level;
-
- lockGlobalParams;
- level = psLevel;
- unlockGlobalParams;
- return level;
-}
-
-PSFontParam *GlobalParams::getPSFont(GString *fontName) {
- PSFontParam *p;
-
- lockGlobalParams;
- p = (PSFontParam *)psFonts->lookup(fontName);
- unlockGlobalParams;
- return p;
-}
-
-PSFontParam *GlobalParams::getPSFont16(GString *fontName,
- GString *collection, int wMode) {
- PSFontParam *p;
- int i;
-
- lockGlobalParams;
- p = NULL;
- if (fontName) {
- for (i = 0; i < psNamedFonts16->getLength(); ++i) {
- p = (PSFontParam *)psNamedFonts16->get(i);
- if (!p->pdfFontName->cmp(fontName) &&
- p->wMode == wMode) {
- break;
- }
- p = NULL;
- }
- }
- if (!p && collection) {
- for (i = 0; i < psFonts16->getLength(); ++i) {
- p = (PSFontParam *)psFonts16->get(i);
- if (!p->pdfFontName->cmp(collection) &&
- p->wMode == wMode) {
- break;
- }
- p = NULL;
- }
- }
- unlockGlobalParams;
- return p;
-}
-
-GBool GlobalParams::getPSEmbedType1() {
- GBool e;
-
- lockGlobalParams;
- e = psEmbedType1;
- unlockGlobalParams;
- return e;
-}
-
-GBool GlobalParams::getPSEmbedTrueType() {
- GBool e;
-
- lockGlobalParams;
- e = psEmbedTrueType;
- unlockGlobalParams;
- return e;
-}
-
-GBool GlobalParams::getPSEmbedCIDPostScript() {
- GBool e;
-
- lockGlobalParams;
- e = psEmbedCIDPostScript;
- unlockGlobalParams;
- return e;
-}
-
-GBool GlobalParams::getPSEmbedCIDTrueType() {
- GBool e;
-
- lockGlobalParams;
- e = psEmbedCIDTrueType;
- unlockGlobalParams;
- return e;
-}
-
-GBool GlobalParams::getPSOPI() {
- GBool opi;
-
- lockGlobalParams;
- opi = psOPI;
- unlockGlobalParams;
- return opi;
-}
-
-GBool GlobalParams::getPSASCIIHex() {
- GBool ah;
-
- lockGlobalParams;
- ah = psASCIIHex;
- unlockGlobalParams;
- return ah;
-}
-
-GString *GlobalParams::getTextEncodingName() {
- GString *s;
-
- lockGlobalParams;
- s = textEncoding->copy();
- unlockGlobalParams;
- return s;
-}
-
-EndOfLineKind GlobalParams::getTextEOL() {
- EndOfLineKind eol;
-
- lockGlobalParams;
- eol = textEOL;
- unlockGlobalParams;
- return eol;
-}
-
-GBool GlobalParams::getTextPageBreaks() {
- GBool pageBreaks;
-
- lockGlobalParams;
- pageBreaks = textPageBreaks;
- unlockGlobalParams;
- return pageBreaks;
-}
-
-GBool GlobalParams::getTextKeepTinyChars() {
- GBool tiny;
-
- lockGlobalParams;
- tiny = textKeepTinyChars;
- unlockGlobalParams;
- return tiny;
-}
-
-GString *GlobalParams::findFontFile(GString *fontName, char **exts) {
- GString *dir, *fileName;
- char **ext;
- FILE *f;
- int i;
-
- lockGlobalParams;
- for (i = 0; i < fontDirs->getLength(); ++i) {
- dir = (GString *)fontDirs->get(i);
- for (ext = exts; *ext; ++ext) {
- fileName = appendToPath(dir->copy(), fontName->getCString());
- fileName->append(*ext);
- if ((f = fopen(fileName->getCString(), "rb"))) {
- fclose(f);
- unlockGlobalParams;
- return fileName;
- }
- delete fileName;
- }
- }
- unlockGlobalParams;
- return NULL;
-}
-
-GString *GlobalParams::getInitialZoom() {
- GString *s;
-
- lockGlobalParams;
- s = initialZoom->copy();
- unlockGlobalParams;
- return s;
-}
-
-GBool GlobalParams::getContinuousView() {
- GBool f;
-
- lockGlobalParams;
- f = continuousView;
- unlockGlobalParams;
- return f;
-}
-
-GBool GlobalParams::getEnableT1lib() {
- GBool f;
-
- lockGlobalParams;
- f = enableT1lib;
- unlockGlobalParams;
- return f;
-}
-
-GBool GlobalParams::getEnableFreeType() {
- GBool f;
-
- lockGlobalParams;
- f = enableFreeType;
- unlockGlobalParams;
- return f;
-}
-
-
-GBool GlobalParams::getAntialias() {
- GBool f;
-
- lockGlobalParams;
- f = antialias;
- unlockGlobalParams;
- return f;
-}
-
-GBool GlobalParams::getMapNumericCharNames() {
- GBool map;
-
- lockGlobalParams;
- map = mapNumericCharNames;
- unlockGlobalParams;
- return map;
-}
-
-GBool GlobalParams::getPrintCommands() {
- GBool p;
-
- lockGlobalParams;
- p = printCommands;
- unlockGlobalParams;
- return p;
-}
-
-GBool GlobalParams::getErrQuiet() {
- GBool q;
-
- lockGlobalParams;
- q = errQuiet;
- unlockGlobalParams;
- return q;
-}
-
-CharCodeToUnicode *GlobalParams::getCIDToUnicode(GString *collection) {
- GString *fileName;
- CharCodeToUnicode *ctu;
-
- lockGlobalParams;
- if (!(ctu = cidToUnicodeCache->getCharCodeToUnicode(collection))) {
- if ((fileName = (GString *)cidToUnicodes->lookup(collection)) &&
- (ctu = CharCodeToUnicode::parseCIDToUnicode(fileName, collection))) {
- cidToUnicodeCache->add(ctu);
- }
- }
- unlockGlobalParams;
- return ctu;
-}
-
-CharCodeToUnicode *GlobalParams::getUnicodeToUnicode(GString *fontName) {
- CharCodeToUnicode *ctu;
- GHashIter *iter;
- GString *fontPattern, *fileName;
-
- lockGlobalParams;
- fileName = NULL;
- unicodeToUnicodes->startIter(&iter);
- while (unicodeToUnicodes->getNext(&iter, &fontPattern, (void **)&fileName)) {
- if (strstr(fontName->getCString(), fontPattern->getCString())) {
- unicodeToUnicodes->killIter(&iter);
- break;
- }
- fileName = NULL;
- }
- if (fileName) {
- if (!(ctu = unicodeToUnicodeCache->getCharCodeToUnicode(fileName))) {
- if ((ctu = CharCodeToUnicode::parseUnicodeToUnicode(fileName))) {
- unicodeToUnicodeCache->add(ctu);
- }
- }
- } else {
- ctu = NULL;
- }
- unlockGlobalParams;
- return ctu;
-}
-
-UnicodeMap *GlobalParams::getUnicodeMap(GString *encodingName) {
- return getUnicodeMap2(encodingName);
-}
-
-UnicodeMap *GlobalParams::getUnicodeMap2(GString *encodingName) {
- UnicodeMap *map;
-
- if (!(map = getResidentUnicodeMap(encodingName))) {
- lockUnicodeMapCache;
- map = unicodeMapCache->getUnicodeMap(encodingName);
- unlockUnicodeMapCache;
- }
- return map;
-}
-
-CMap *GlobalParams::getCMap(GString *collection, GString *cMapName) {
- CMap *cMap;
-
- lockCMapCache;
- cMap = cMapCache->getCMap(collection, cMapName);
- unlockCMapCache;
- return cMap;
-}
-
-UnicodeMap *GlobalParams::getTextEncoding() {
- return getUnicodeMap2(textEncoding);
-}
-
-//------------------------------------------------------------------------
-// functions to set parameters
-//------------------------------------------------------------------------
-
-void GlobalParams::addDisplayFont(DisplayFontParam *param) {
- DisplayFontParam *old;
-
- lockGlobalParams;
- if ((old = (DisplayFontParam *)displayFonts->remove(param->name))) {
- delete old;
- }
- displayFonts->add(param->name, param);
- unlockGlobalParams;
-}
-
-void GlobalParams::setPSFile(char *file) {
- lockGlobalParams;
- if (psFile) {
- delete psFile;
- }
- psFile = new GString(file);
- unlockGlobalParams;
-}
-
-GBool GlobalParams::setPSPaperSize(char *size) {
- lockGlobalParams;
- if (!strcmp(size, "match")) {
- psPaperWidth = psPaperHeight = -1;
- } else if (!strcmp(size, "letter")) {
- psPaperWidth = 612;
- psPaperHeight = 792;
- } else if (!strcmp(size, "legal")) {
- psPaperWidth = 612;
- psPaperHeight = 1008;
- } else if (!strcmp(size, "A4")) {
- psPaperWidth = 595;
- psPaperHeight = 842;
- } else if (!strcmp(size, "A3")) {
- psPaperWidth = 842;
- psPaperHeight = 1190;
- } else {
- unlockGlobalParams;
- return gFalse;
- }
- psImageableLLX = psImageableLLY = 0;
- psImageableURX = psPaperWidth;
- psImageableURY = psPaperHeight;
- unlockGlobalParams;
- return gTrue;
-}
-
-void GlobalParams::setPSPaperWidth(int width) {
- lockGlobalParams;
- psPaperWidth = width;
- psImageableLLX = 0;
- psImageableURX = psPaperWidth;
- unlockGlobalParams;
-}
-
-void GlobalParams::setPSPaperHeight(int height) {
- lockGlobalParams;
- psPaperHeight = height;
- psImageableLLY = 0;
- psImageableURY = psPaperHeight;
- unlockGlobalParams;
-}
-
-void GlobalParams::setPSImageableArea(int llx, int lly, int urx, int ury) {
- lockGlobalParams;
- psImageableLLX = llx;
- psImageableLLY = lly;
- psImageableURX = urx;
- psImageableURY = ury;
- unlockGlobalParams;
-}
-
-void GlobalParams::setPSCrop(GBool crop) {
- lockGlobalParams;
- psCrop = crop;
- unlockGlobalParams;
-}
-
-void GlobalParams::setPSExpandSmaller(GBool expand) {
- lockGlobalParams;
- psExpandSmaller = expand;
- unlockGlobalParams;
-}
-
-void GlobalParams::setPSShrinkLarger(GBool shrink) {
- lockGlobalParams;
- psShrinkLarger = shrink;
- unlockGlobalParams;
-}
-
-void GlobalParams::setPSCenter(GBool center) {
- lockGlobalParams;
- psCenter = center;
- unlockGlobalParams;
-}
-
-void GlobalParams::setPSDuplex(GBool duplex) {
- lockGlobalParams;
- psDuplex = duplex;
- unlockGlobalParams;
-}
-
-void GlobalParams::setPSLevel(PSLevel level) {
- lockGlobalParams;
- psLevel = level;
- unlockGlobalParams;
-}
-
-void GlobalParams::setPSEmbedType1(GBool embed) {
- lockGlobalParams;
- psEmbedType1 = embed;
- unlockGlobalParams;
-}
-
-void GlobalParams::setPSEmbedTrueType(GBool embed) {
- lockGlobalParams;
- psEmbedTrueType = embed;
- unlockGlobalParams;
-}
-
-void GlobalParams::setPSEmbedCIDPostScript(GBool embed) {
- lockGlobalParams;
- psEmbedCIDPostScript = embed;
- unlockGlobalParams;
-}
-
-void GlobalParams::setPSEmbedCIDTrueType(GBool embed) {
- lockGlobalParams;
- psEmbedCIDTrueType = embed;
- unlockGlobalParams;
-}
-
-void GlobalParams::setPSOPI(GBool opi) {
- lockGlobalParams;
- psOPI = opi;
- unlockGlobalParams;
-}
-
-void GlobalParams::setPSASCIIHex(GBool hex) {
- lockGlobalParams;
- psASCIIHex = hex;
- unlockGlobalParams;
-}
-
-void GlobalParams::setTextEncoding(char *encodingName) {
- lockGlobalParams;
- delete textEncoding;
- textEncoding = new GString(encodingName);
- unlockGlobalParams;
-}
-
-GBool GlobalParams::setTextEOL(char *s) {
- lockGlobalParams;
- if (!strcmp(s, "unix")) {
- textEOL = eolUnix;
- } else if (!strcmp(s, "dos")) {
- textEOL = eolDOS;
- } else if (!strcmp(s, "mac")) {
- textEOL = eolMac;
- } else {
- unlockGlobalParams;
- return gFalse;
- }
- unlockGlobalParams;
- return gTrue;
-}
-
-void GlobalParams::setTextPageBreaks(GBool pageBreaks) {
- lockGlobalParams;
- textPageBreaks = pageBreaks;
- unlockGlobalParams;
-}
-
-void GlobalParams::setTextKeepTinyChars(GBool keep) {
- lockGlobalParams;
- textKeepTinyChars = keep;
- unlockGlobalParams;
-}
-
-void GlobalParams::setInitialZoom(char *s) {
- lockGlobalParams;
- delete initialZoom;
- initialZoom = new GString(s);
- unlockGlobalParams;
-}
-
-void GlobalParams::setContinuousView(GBool cont) {
- lockGlobalParams;
- continuousView = cont;
- unlockGlobalParams;
-}
-
-GBool GlobalParams::setEnableT1lib(char *s) {
- GBool ok;
-
- lockGlobalParams;
- ok = parseYesNo2(s, &enableT1lib);
- unlockGlobalParams;
- return ok;
-}
-
-GBool GlobalParams::setEnableFreeType(char *s) {
- GBool ok;
-
- lockGlobalParams;
- ok = parseYesNo2(s, &enableFreeType);
- unlockGlobalParams;
- return ok;
-}
-
-
-GBool GlobalParams::setAntialias(char *s) {
- GBool ok;
-
- lockGlobalParams;
- ok = parseYesNo2(s, &antialias);
- unlockGlobalParams;
- return ok;
-}
-
-void GlobalParams::setMapNumericCharNames(GBool map) {
- lockGlobalParams;
- mapNumericCharNames = map;
- unlockGlobalParams;
-}
-
-void GlobalParams::setPrintCommands(GBool printCommandsA) {
- lockGlobalParams;
- printCommands = printCommandsA;
- unlockGlobalParams;
-}
-
-void GlobalParams::setErrQuiet(GBool errQuietA) {
- lockGlobalParams;
- errQuiet = errQuietA;
- unlockGlobalParams;
-}
-
-void GlobalParams::addSecurityHandler(XpdfSecurityHandler *handler) {
-#ifdef ENABLE_PLUGINS
- lockGlobalParams;
- securityHandlers->append(handler);
- unlockGlobalParams;
-#endif
-}
-
-XpdfSecurityHandler *GlobalParams::getSecurityHandler(char *name) {
-#ifdef ENABLE_PLUGINS
- XpdfSecurityHandler *hdlr;
- int i;
-
- lockGlobalParams;
- for (i = 0; i < securityHandlers->getLength(); ++i) {
- hdlr = (XpdfSecurityHandler *)securityHandlers->get(i);
- if (!stricmp(hdlr->name, name)) {
- unlockGlobalParams;
- return hdlr;
- }
- }
- unlockGlobalParams;
-
- if (!loadPlugin("security", name)) {
- return NULL;
- }
-
- lockGlobalParams;
- for (i = 0; i < securityHandlers->getLength(); ++i) {
- hdlr = (XpdfSecurityHandler *)securityHandlers->get(i);
- if (!strcmp(hdlr->name, name)) {
- unlockGlobalParams;
- return hdlr;
- }
- }
- unlockGlobalParams;
-#endif
-
- return NULL;
-}
-
-#ifdef ENABLE_PLUGINS
-//------------------------------------------------------------------------
-// plugins
-//------------------------------------------------------------------------
-
-GBool GlobalParams::loadPlugin(char *type, char *name) {
- Plugin *plugin;
-
- if (!(plugin = Plugin::load(type, name))) {
- return gFalse;
- }
- lockGlobalParams;
- plugins->append(plugin);
- unlockGlobalParams;
- return gTrue;
-}
-
-#endif // ENABLE_PLUGINS
+++ /dev/null
-//========================================================================
-//
-// GlobalParams.h
-//
-// Copyright 2001-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#ifndef GLOBALPARAMS_H
-#define GLOBALPARAMS_H
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma interface
-#endif
-
-#include <stdio.h>
-#include "gtypes.h"
-#include "CharTypes.h"
-
-#if MULTITHREADED
-#include "GMutex.h"
-#endif
-
-class GString;
-class GList;
-class GHash;
-class NameToCharCode;
-class CharCodeToUnicode;
-class CharCodeToUnicodeCache;
-class UnicodeMap;
-class UnicodeMapCache;
-class CMap;
-class CMapCache;
-struct XpdfSecurityHandler;
-class GlobalParams;
-
-//------------------------------------------------------------------------
-
-// The global parameters object.
-extern GlobalParams *globalParams;
-
-//------------------------------------------------------------------------
-
-enum DisplayFontParamKind {
- displayFontT1,
- displayFontTT
-};
-
-struct DisplayFontParamT1 {
- GString *fileName;
-};
-
-struct DisplayFontParamTT {
- GString *fileName;
-};
-
-class DisplayFontParam {
-public:
-
- GString *name; // font name for 8-bit fonts and named
- // CID fonts; collection name for
- // generic CID fonts
- DisplayFontParamKind kind;
- union {
- DisplayFontParamT1 t1;
- DisplayFontParamTT tt;
- };
-
- DisplayFontParam(GString *nameA, DisplayFontParamKind kindA);
- ~DisplayFontParam();
-};
-
-//------------------------------------------------------------------------
-
-class PSFontParam {
-public:
-
- GString *pdfFontName; // PDF font name for 8-bit fonts and
- // named 16-bit fonts; char collection
- // name for generic 16-bit fonts
- int wMode; // writing mode (0=horiz, 1=vert) for
- // 16-bit fonts
- GString *psFontName; // PostScript font name
- GString *encoding; // encoding, for 16-bit fonts only
-
- PSFontParam(GString *pdfFontNameA, int wModeA,
- GString *psFontNameA, GString *encodingA);
- ~PSFontParam();
-};
-
-//------------------------------------------------------------------------
-
-enum PSLevel {
- psLevel1,
- psLevel1Sep,
- psLevel2,
- psLevel2Sep,
- psLevel3,
- psLevel3Sep
-};
-
-//------------------------------------------------------------------------
-
-enum EndOfLineKind {
- eolUnix, // LF
- eolDOS, // CR+LF
- eolMac // CR
-};
-
-//------------------------------------------------------------------------
-
-class GlobalParams {
-public:
-
- // Initialize the global parameters by attempting to read a config
- // file.
- GlobalParams(char *cfgFileName);
-
- ~GlobalParams();
-
- void setBaseDir(char *dir);
- void setupBaseFonts(char *dir);
-
- //----- accessors
-
- CharCode getMacRomanCharCode(char *charName);
-
- GString *getBaseDir();
- Unicode mapNameToUnicode(char *charName);
- UnicodeMap *getResidentUnicodeMap(GString *encodingName);
- FILE *getUnicodeMapFile(GString *encodingName);
- FILE *findCMapFile(GString *collection, GString *cMapName);
- FILE *findToUnicodeFile(GString *name);
- DisplayFontParam *getDisplayFont(GString *fontName);
- DisplayFontParam *getDisplayCIDFont(GString *fontName, GString *collection);
- GString *getPSFile();
- int getPSPaperWidth();
- int getPSPaperHeight();
- void getPSImageableArea(int *llx, int *lly, int *urx, int *ury);
- GBool getPSDuplex();
- GBool getPSCrop();
- GBool getPSExpandSmaller();
- GBool getPSShrinkLarger();
- GBool getPSCenter();
- PSLevel getPSLevel();
- PSFontParam *getPSFont(GString *fontName);
- PSFontParam *getPSFont16(GString *fontName, GString *collection, int wMode);
- GBool getPSEmbedType1();
- GBool getPSEmbedTrueType();
- GBool getPSEmbedCIDPostScript();
- GBool getPSEmbedCIDTrueType();
- GBool getPSOPI();
- GBool getPSASCIIHex();
- GString *getTextEncodingName();
- EndOfLineKind getTextEOL();
- GBool getTextPageBreaks();
- GBool getTextKeepTinyChars();
- GString *findFontFile(GString *fontName, char **exts);
- GString *getInitialZoom();
- GBool getContinuousView();
- GBool getEnableT1lib();
- GBool getEnableFreeType();
- GBool getAntialias();
- GString *getURLCommand() { return urlCommand; }
- GString *getMovieCommand() { return movieCommand; }
- GBool getMapNumericCharNames();
- GBool getPrintCommands();
- GBool getErrQuiet();
-
- CharCodeToUnicode *getCIDToUnicode(GString *collection);
- CharCodeToUnicode *getUnicodeToUnicode(GString *fontName);
- UnicodeMap *getUnicodeMap(GString *encodingName);
- CMap *getCMap(GString *collection, GString *cMapName);
- UnicodeMap *getTextEncoding();
-
- //----- functions to set parameters
-
- void addDisplayFont(DisplayFontParam *param);
- void setPSFile(char *file);
- GBool setPSPaperSize(char *size);
- void setPSPaperWidth(int width);
- void setPSPaperHeight(int height);
- void setPSImageableArea(int llx, int lly, int urx, int ury);
- void setPSDuplex(GBool duplex);
- void setPSCrop(GBool crop);
- void setPSExpandSmaller(GBool expand);
- void setPSShrinkLarger(GBool shrink);
- void setPSCenter(GBool center);
- void setPSLevel(PSLevel level);
- void setPSEmbedType1(GBool embed);
- void setPSEmbedTrueType(GBool embed);
- void setPSEmbedCIDPostScript(GBool embed);
- void setPSEmbedCIDTrueType(GBool embed);
- void setPSOPI(GBool opi);
- void setPSASCIIHex(GBool hex);
- void setTextEncoding(char *encodingName);
- GBool setTextEOL(char *s);
- void setTextPageBreaks(GBool pageBreaks);
- void setTextKeepTinyChars(GBool keep);
- void setInitialZoom(char *s);
- void setContinuousView(GBool cont);
- GBool setEnableT1lib(char *s);
- GBool setEnableFreeType(char *s);
- GBool setAntialias(char *s);
- void setMapNumericCharNames(GBool map);
- void setPrintCommands(GBool printCommandsA);
- void setErrQuiet(GBool errQuietA);
-
- //----- security handlers
-
- void addSecurityHandler(XpdfSecurityHandler *handler);
- XpdfSecurityHandler *getSecurityHandler(char *name);
-
-private:
-
- void parseFile(GString *fileName, FILE *f);
- void parseNameToUnicode(GList *tokens, GString *fileName, int line);
- void parseCIDToUnicode(GList *tokens, GString *fileName, int line);
- void parseUnicodeToUnicode(GList *tokens, GString *fileName, int line);
- void parseUnicodeMap(GList *tokens, GString *fileName, int line);
- void parseCMapDir(GList *tokens, GString *fileName, int line);
- void parseToUnicodeDir(GList *tokens, GString *fileName, int line);
- void parseDisplayFont(GList *tokens, GHash *fontHash,
- DisplayFontParamKind kind,
- GString *fileName, int line);
- void parsePSFile(GList *tokens, GString *fileName, int line);
- void parsePSPaperSize(GList *tokens, GString *fileName, int line);
- void parsePSImageableArea(GList *tokens, GString *fileName, int line);
- void parsePSLevel(GList *tokens, GString *fileName, int line);
- void parsePSFont(GList *tokens, GString *fileName, int line);
- void parsePSFont16(char *cmdName, GList *fontList,
- GList *tokens, GString *fileName, int line);
- void parseTextEncoding(GList *tokens, GString *fileName, int line);
- void parseTextEOL(GList *tokens, GString *fileName, int line);
- void parseFontDir(GList *tokens, GString *fileName, int line);
- void parseInitialZoom(GList *tokens, GString *fileName, int line);
- void parseCommand(char *cmdName, GString **val,
- GList *tokens, GString *fileName, int line);
- void parseYesNo(char *cmdName, GBool *flag,
- GList *tokens, GString *fileName, int line);
- GBool parseYesNo2(char *token, GBool *flag);
- UnicodeMap *getUnicodeMap2(GString *encodingName);
-#ifdef ENABLE_PLUGINS
- GBool loadPlugin(char *type, char *name);
-#endif
-
- //----- static tables
-
- NameToCharCode * // mapping from char name to
- macRomanReverseMap; // MacRomanEncoding index
-
- //----- user-modifiable settings
-
- GString *baseDir; // base directory - for plugins, etc.
- NameToCharCode * // mapping from char name to Unicode
- nameToUnicode;
- GHash *cidToUnicodes; // files for mappings from char collections
- // to Unicode, indexed by collection name
- // [GString]
- GHash *unicodeToUnicodes; // files for Unicode-to-Unicode mappings,
- // indexed by font name pattern [GString]
- GHash *residentUnicodeMaps; // mappings from Unicode to char codes,
- // indexed by encoding name [UnicodeMap]
- GHash *unicodeMaps; // files for mappings from Unicode to char
- // codes, indexed by encoding name [GString]
- GHash *cMapDirs; // list of CMap dirs, indexed by collection
- // name [GList[GString]]
- GList *toUnicodeDirs; // list of ToUnicode CMap dirs [GString]
- GHash *displayFonts; // display font info, indexed by font name
- // [DisplayFontParam]
- GHash *displayCIDFonts; // display CID font info, indexed by
- // collection [DisplayFontParam]
- GHash *displayNamedCIDFonts; // display CID font info, indexed by
- // font name [DisplayFontParam]
- GString *psFile; // PostScript file or command (for xpdf)
- int psPaperWidth; // paper size, in PostScript points, for
- int psPaperHeight; // PostScript output
- int psImageableLLX, // imageable area, in PostScript points,
- psImageableLLY, // for PostScript output
- psImageableURX,
- psImageableURY;
- GBool psCrop; // crop PS output to CropBox
- GBool psExpandSmaller; // expand smaller pages to fill paper
- GBool psShrinkLarger; // shrink larger pages to fit paper
- GBool psCenter; // center pages on the paper
- GBool psDuplex; // enable duplexing in PostScript?
- PSLevel psLevel; // PostScript level to generate
- GHash *psFonts; // PostScript font info, indexed by PDF
- // font name [PSFontParam]
- GList *psNamedFonts16; // named 16-bit fonts [PSFontParam]
- GList *psFonts16; // generic 16-bit fonts [PSFontParam]
- GBool psEmbedType1; // embed Type 1 fonts?
- GBool psEmbedTrueType; // embed TrueType fonts?
- GBool psEmbedCIDPostScript; // embed CID PostScript fonts?
- GBool psEmbedCIDTrueType; // embed CID TrueType fonts?
- GBool psOPI; // generate PostScript OPI comments?
- GBool psASCIIHex; // use ASCIIHex instead of ASCII85?
- GString *textEncoding; // encoding (unicodeMap) to use for text
- // output
- EndOfLineKind textEOL; // type of EOL marker to use for text
- // output
- GBool textPageBreaks; // insert end-of-page markers?
- GBool textKeepTinyChars; // keep all characters in text output
- GList *fontDirs; // list of font dirs [GString]
- GString *initialZoom; // initial zoom level
- GBool continuousView; // continuous view mode
- GBool enableT1lib; // t1lib enable flag
- GBool enableFreeType; // FreeType enable flag
- GBool antialias; // anti-aliasing enable flag
- GString *urlCommand; // command executed for URL links
- GString *movieCommand; // command executed for movie annotations
- GBool mapNumericCharNames; // map numeric char names (from font subsets)?
- GBool printCommands; // print the drawing commands
- GBool errQuiet; // suppress error messages?
-
- CharCodeToUnicodeCache *cidToUnicodeCache;
- CharCodeToUnicodeCache *unicodeToUnicodeCache;
- UnicodeMapCache *unicodeMapCache;
- CMapCache *cMapCache;
-
-#ifdef ENABLE_PLUGINS
- GList *plugins; // list of plugins [Plugin]
- GList *securityHandlers; // list of loaded security handlers
- // [XpdfSecurityHandler]
-#endif
-
-#if MULTITHREADED
- GMutex mutex;
- GMutex unicodeMapCacheMutex;
- GMutex cMapCacheMutex;
-#endif
-};
-
-#endif
+++ /dev/null
-//========================================================================
-//
-// JArithmeticDecoder.cc
-//
-// Copyright 2002-2004 Glyph & Cog, LLC
-//
-//========================================================================
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma implementation
-#endif
-
-#include "Object.h"
-#include "Stream.h"
-#include "JArithmeticDecoder.h"
-
-//------------------------------------------------------------------------
-// JArithmeticDecoderStates
-//------------------------------------------------------------------------
-
-JArithmeticDecoderStats::JArithmeticDecoderStats(int contextSizeA) {
- contextSize = contextSizeA;
- cxTab = (Guchar *)gmallocn(contextSize, sizeof(Guchar));
- reset();
-}
-
-JArithmeticDecoderStats::~JArithmeticDecoderStats() {
- gfree(cxTab);
-}
-
-JArithmeticDecoderStats *JArithmeticDecoderStats::copy() {
- JArithmeticDecoderStats *stats;
-
- stats = new JArithmeticDecoderStats(contextSize);
- memcpy(stats->cxTab, cxTab, contextSize);
- return stats;
-}
-
-void JArithmeticDecoderStats::reset() {
- memset(cxTab, 0, contextSize);
-}
-
-void JArithmeticDecoderStats::copyFrom(JArithmeticDecoderStats *stats) {
- memcpy(cxTab, stats->cxTab, contextSize);
-}
-
-void JArithmeticDecoderStats::setEntry(Guint cx, int i, int mps) {
- cxTab[cx] = (i << 1) + mps;
-}
-
-//------------------------------------------------------------------------
-// JArithmeticDecoder
-//------------------------------------------------------------------------
-
-Guint JArithmeticDecoder::qeTab[47] = {
- 0x56010000, 0x34010000, 0x18010000, 0x0AC10000,
- 0x05210000, 0x02210000, 0x56010000, 0x54010000,
- 0x48010000, 0x38010000, 0x30010000, 0x24010000,
- 0x1C010000, 0x16010000, 0x56010000, 0x54010000,
- 0x51010000, 0x48010000, 0x38010000, 0x34010000,
- 0x30010000, 0x28010000, 0x24010000, 0x22010000,
- 0x1C010000, 0x18010000, 0x16010000, 0x14010000,
- 0x12010000, 0x11010000, 0x0AC10000, 0x09C10000,
- 0x08A10000, 0x05210000, 0x04410000, 0x02A10000,
- 0x02210000, 0x01410000, 0x01110000, 0x00850000,
- 0x00490000, 0x00250000, 0x00150000, 0x00090000,
- 0x00050000, 0x00010000, 0x56010000
-};
-
-int JArithmeticDecoder::nmpsTab[47] = {
- 1, 2, 3, 4, 5, 38, 7, 8, 9, 10, 11, 12, 13, 29, 15, 16,
- 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
- 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 45, 46
-};
-
-int JArithmeticDecoder::nlpsTab[47] = {
- 1, 6, 9, 12, 29, 33, 6, 14, 14, 14, 17, 18, 20, 21, 14, 14,
- 15, 16, 17, 18, 19, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
- 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 46
-};
-
-int JArithmeticDecoder::switchTab[47] = {
- 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-};
-
-JArithmeticDecoder::JArithmeticDecoder() {
- str = NULL;
- dataLen = 0;
- limitStream = gFalse;
-}
-
-inline Guint JArithmeticDecoder::readByte() {
- if (limitStream) {
- --dataLen;
- if (dataLen < 0) {
- return 0xff;
- }
- }
- return (Guint)str->getChar() & 0xff;
-}
-
-JArithmeticDecoder::~JArithmeticDecoder() {
- cleanup();
-}
-
-void JArithmeticDecoder::start() {
- buf0 = readByte();
- buf1 = readByte();
-
- // INITDEC
- c = (buf0 ^ 0xff) << 16;
- byteIn();
- c <<= 7;
- ct -= 7;
- a = 0x80000000;
-}
-
-void JArithmeticDecoder::restart(int dataLenA) {
- int oldDataLen;
-
- oldDataLen = dataLen;
- dataLen = dataLenA;
- if (oldDataLen == -1) {
- buf1 = readByte();
- } else if (oldDataLen <= -2) {
- buf0 = readByte();
- buf1 = readByte();
- }
-}
-
-void JArithmeticDecoder::cleanup() {
- if (limitStream) {
- while (dataLen > 0) {
- buf0 = buf1;
- buf1 = readByte();
- }
- }
-}
-
-int JArithmeticDecoder::decodeBit(Guint context,
- JArithmeticDecoderStats *stats) {
- int bit;
- Guint qe;
- int iCX, mpsCX;
-
- iCX = stats->cxTab[context] >> 1;
- mpsCX = stats->cxTab[context] & 1;
- qe = qeTab[iCX];
- a -= qe;
- if (c < a) {
- if (a & 0x80000000) {
- bit = mpsCX;
- } else {
- // MPS_EXCHANGE
- if (a < qe) {
- bit = 1 - mpsCX;
- if (switchTab[iCX]) {
- stats->cxTab[context] = (nlpsTab[iCX] << 1) | (1 - mpsCX);
- } else {
- stats->cxTab[context] = (nlpsTab[iCX] << 1) | mpsCX;
- }
- } else {
- bit = mpsCX;
- stats->cxTab[context] = (nmpsTab[iCX] << 1) | mpsCX;
- }
- // RENORMD
- do {
- if (ct == 0) {
- byteIn();
- }
- a <<= 1;
- c <<= 1;
- --ct;
- } while (!(a & 0x80000000));
- }
- } else {
- c -= a;
- // LPS_EXCHANGE
- if (a < qe) {
- bit = mpsCX;
- stats->cxTab[context] = (nmpsTab[iCX] << 1) | mpsCX;
- } else {
- bit = 1 - mpsCX;
- if (switchTab[iCX]) {
- stats->cxTab[context] = (nlpsTab[iCX] << 1) | (1 - mpsCX);
- } else {
- stats->cxTab[context] = (nlpsTab[iCX] << 1) | mpsCX;
- }
- }
- a = qe;
- // RENORMD
- do {
- if (ct == 0) {
- byteIn();
- }
- a <<= 1;
- c <<= 1;
- --ct;
- } while (!(a & 0x80000000));
- }
- return bit;
-}
-
-int JArithmeticDecoder::decodeByte(Guint context,
- JArithmeticDecoderStats *stats) {
- int byte;
- int i;
-
- byte = 0;
- for (i = 0; i < 8; ++i) {
- byte = (byte << 1) | decodeBit(context, stats);
- }
- return byte;
-}
-
-GBool JArithmeticDecoder::decodeInt(int *x, JArithmeticDecoderStats *stats) {
- int s;
- Guint v;
- int i;
-
- prev = 1;
- s = decodeIntBit(stats);
- if (decodeIntBit(stats)) {
- if (decodeIntBit(stats)) {
- if (decodeIntBit(stats)) {
- if (decodeIntBit(stats)) {
- if (decodeIntBit(stats)) {
- v = 0;
- for (i = 0; i < 32; ++i) {
- v = (v << 1) | decodeIntBit(stats);
- }
- v += 4436;
- } else {
- v = 0;
- for (i = 0; i < 12; ++i) {
- v = (v << 1) | decodeIntBit(stats);
- }
- v += 340;
- }
- } else {
- v = 0;
- for (i = 0; i < 8; ++i) {
- v = (v << 1) | decodeIntBit(stats);
- }
- v += 84;
- }
- } else {
- v = 0;
- for (i = 0; i < 6; ++i) {
- v = (v << 1) | decodeIntBit(stats);
- }
- v += 20;
- }
- } else {
- v = decodeIntBit(stats);
- v = (v << 1) | decodeIntBit(stats);
- v = (v << 1) | decodeIntBit(stats);
- v = (v << 1) | decodeIntBit(stats);
- v += 4;
- }
- } else {
- v = decodeIntBit(stats);
- v = (v << 1) | decodeIntBit(stats);
- }
-
- if (s) {
- if (v == 0) {
- return gFalse;
- }
- *x = -(int)v;
- } else {
- *x = (int)v;
- }
- return gTrue;
-}
-
-int JArithmeticDecoder::decodeIntBit(JArithmeticDecoderStats *stats) {
- int bit;
-
- bit = decodeBit(prev, stats);
- if (prev < 0x100) {
- prev = (prev << 1) | bit;
- } else {
- prev = (((prev << 1) | bit) & 0x1ff) | 0x100;
- }
- return bit;
-}
-
-Guint JArithmeticDecoder::decodeIAID(Guint codeLen,
- JArithmeticDecoderStats *stats) {
- Guint i;
- int bit;
-
- prev = 1;
- for (i = 0; i < codeLen; ++i) {
- bit = decodeBit(prev, stats);
- prev = (prev << 1) | bit;
- }
- return prev - (1 << codeLen);
-}
-
-void JArithmeticDecoder::byteIn() {
- if (buf0 == 0xff) {
- if (buf1 > 0x8f) {
- ct = 8;
- } else {
- buf0 = buf1;
- buf1 = readByte();
- c = c + 0xfe00 - (buf0 << 9);
- ct = 7;
- }
- } else {
- buf0 = buf1;
- buf1 = readByte();
- c = c + 0xff00 - (buf0 << 8);
- ct = 8;
- }
-}
+++ /dev/null
-//========================================================================
-//
-// JArithmeticDecoder.h
-//
-// Arithmetic decoder used by the JBIG2 and JPEG2000 decoders.
-//
-// Copyright 2002-2004 Glyph & Cog, LLC
-//
-//========================================================================
-
-#ifndef JARITHMETICDECODER_H
-#define JARITHMETICDECODER_H
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma interface
-#endif
-
-#include "gtypes.h"
-
-class Stream;
-
-//------------------------------------------------------------------------
-// JArithmeticDecoderStats
-//------------------------------------------------------------------------
-
-class JArithmeticDecoderStats {
-public:
-
- JArithmeticDecoderStats(int contextSizeA);
- ~JArithmeticDecoderStats();
- JArithmeticDecoderStats *copy();
- void reset();
- int getContextSize() { return contextSize; }
- void copyFrom(JArithmeticDecoderStats *stats);
- void setEntry(Guint cx, int i, int mps);
-
-private:
-
- Guchar *cxTab; // cxTab[cx] = (i[cx] << 1) + mps[cx]
- int contextSize;
-
- friend class JArithmeticDecoder;
-};
-
-//------------------------------------------------------------------------
-// JArithmeticDecoder
-//------------------------------------------------------------------------
-
-class JArithmeticDecoder {
-public:
-
- JArithmeticDecoder();
- ~JArithmeticDecoder();
-
- void setStream(Stream *strA)
- { str = strA; dataLen = 0; limitStream = gFalse; }
- void setStream(Stream *strA, int dataLenA)
- { str = strA; dataLen = dataLenA; limitStream = gTrue; }
-
- // Start decoding on a new stream. This fills the byte buffers and
- // runs INITDEC.
- void start();
-
- // Restart decoding on an interrupted stream. This refills the
- // buffers if needed, but does not run INITDEC. (This is used in
- // JPEG 2000 streams when codeblock data is split across multiple
- // packets/layers.)
- void restart(int dataLenA);
-
- // Read any leftover data in the stream.
- void cleanup();
-
- // Decode one bit.
- int decodeBit(Guint context, JArithmeticDecoderStats *stats);
-
- // Decode eight bits.
- int decodeByte(Guint context, JArithmeticDecoderStats *stats);
-
- // Returns false for OOB, otherwise sets *<x> and returns true.
- GBool decodeInt(int *x, JArithmeticDecoderStats *stats);
-
- Guint decodeIAID(Guint codeLen,
- JArithmeticDecoderStats *stats);
-
-private:
-
- Guint readByte();
- int decodeIntBit(JArithmeticDecoderStats *stats);
- void byteIn();
-
- static Guint qeTab[47];
- static int nmpsTab[47];
- static int nlpsTab[47];
- static int switchTab[47];
-
- Guint buf0, buf1;
- Guint c, a;
- int ct;
-
- Guint prev; // for the integer decoder
-
- Stream *str;
- int dataLen;
- GBool limitStream;
-};
-
-#endif
+++ /dev/null
-//========================================================================
-//
-// JBIG2Stream.cc
-//
-// Copyright 2002-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma implementation
-#endif
-
-#include <stdlib.h>
-#include "GList.h"
-#include "Error.h"
-#include "JArithmeticDecoder.h"
-#include "JBIG2Stream.h"
-
-//~ share these tables
-#include "Stream-CCITT.h"
-
-//------------------------------------------------------------------------
-
-static int contextSize[4] = { 16, 13, 10, 10 };
-static int refContextSize[2] = { 13, 10 };
-
-//------------------------------------------------------------------------
-// JBIG2HuffmanTable
-//------------------------------------------------------------------------
-
-#define jbig2HuffmanLOW 0xfffffffd
-#define jbig2HuffmanOOB 0xfffffffe
-#define jbig2HuffmanEOT 0xffffffff
-
-struct JBIG2HuffmanTable {
- int val;
- Guint prefixLen;
- Guint rangeLen; // can also be LOW, OOB, or EOT
- Guint prefix;
-};
-
-JBIG2HuffmanTable huffTableA[] = {
- { 0, 1, 4, 0x000 },
- { 16, 2, 8, 0x002 },
- { 272, 3, 16, 0x006 },
- { 65808, 3, 32, 0x007 },
- { 0, 0, jbig2HuffmanEOT, 0 }
-};
-
-JBIG2HuffmanTable huffTableB[] = {
- { 0, 1, 0, 0x000 },
- { 1, 2, 0, 0x002 },
- { 2, 3, 0, 0x006 },
- { 3, 4, 3, 0x00e },
- { 11, 5, 6, 0x01e },
- { 75, 6, 32, 0x03e },
- { 0, 6, jbig2HuffmanOOB, 0x03f },
- { 0, 0, jbig2HuffmanEOT, 0 }
-};
-
-JBIG2HuffmanTable huffTableC[] = {
- { 0, 1, 0, 0x000 },
- { 1, 2, 0, 0x002 },
- { 2, 3, 0, 0x006 },
- { 3, 4, 3, 0x00e },
- { 11, 5, 6, 0x01e },
- { 0, 6, jbig2HuffmanOOB, 0x03e },
- { 75, 7, 32, 0x0fe },
- { -256, 8, 8, 0x0fe },
- { -257, 8, jbig2HuffmanLOW, 0x0ff },
- { 0, 0, jbig2HuffmanEOT, 0 }
-};
-
-JBIG2HuffmanTable huffTableD[] = {
- { 1, 1, 0, 0x000 },
- { 2, 2, 0, 0x002 },
- { 3, 3, 0, 0x006 },
- { 4, 4, 3, 0x00e },
- { 12, 5, 6, 0x01e },
- { 76, 5, 32, 0x01f },
- { 0, 0, jbig2HuffmanEOT, 0 }
-};
-
-JBIG2HuffmanTable huffTableE[] = {
- { 1, 1, 0, 0x000 },
- { 2, 2, 0, 0x002 },
- { 3, 3, 0, 0x006 },
- { 4, 4, 3, 0x00e },
- { 12, 5, 6, 0x01e },
- { 76, 6, 32, 0x03e },
- { -255, 7, 8, 0x07e },
- { -256, 7, jbig2HuffmanLOW, 0x07f },
- { 0, 0, jbig2HuffmanEOT, 0 }
-};
-
-JBIG2HuffmanTable huffTableF[] = {
- { 0, 2, 7, 0x000 },
- { 128, 3, 7, 0x002 },
- { 256, 3, 8, 0x003 },
- { -1024, 4, 9, 0x008 },
- { -512, 4, 8, 0x009 },
- { -256, 4, 7, 0x00a },
- { -32, 4, 5, 0x00b },
- { 512, 4, 9, 0x00c },
- { 1024, 4, 10, 0x00d },
- { -2048, 5, 10, 0x01c },
- { -128, 5, 6, 0x01d },
- { -64, 5, 5, 0x01e },
- { -2049, 6, jbig2HuffmanLOW, 0x03e },
- { 2048, 6, 32, 0x03f },
- { 0, 0, jbig2HuffmanEOT, 0 }
-};
-
-JBIG2HuffmanTable huffTableG[] = {
- { -512, 3, 8, 0x000 },
- { 256, 3, 8, 0x001 },
- { 512, 3, 9, 0x002 },
- { 1024, 3, 10, 0x003 },
- { -1024, 4, 9, 0x008 },
- { -256, 4, 7, 0x009 },
- { -32, 4, 5, 0x00a },
- { 0, 4, 5, 0x00b },
- { 128, 4, 7, 0x00c },
- { -128, 5, 6, 0x01a },
- { -64, 5, 5, 0x01b },
- { 32, 5, 5, 0x01c },
- { 64, 5, 6, 0x01d },
- { -1025, 5, jbig2HuffmanLOW, 0x01e },
- { 2048, 5, 32, 0x01f },
- { 0, 0, jbig2HuffmanEOT, 0 }
-};
-
-JBIG2HuffmanTable huffTableH[] = {
- { 0, 2, 1, 0x000 },
- { 0, 2, jbig2HuffmanOOB, 0x001 },
- { 4, 3, 4, 0x004 },
- { -1, 4, 0, 0x00a },
- { 22, 4, 4, 0x00b },
- { 38, 4, 5, 0x00c },
- { 2, 5, 0, 0x01a },
- { 70, 5, 6, 0x01b },
- { 134, 5, 7, 0x01c },
- { 3, 6, 0, 0x03a },
- { 20, 6, 1, 0x03b },
- { 262, 6, 7, 0x03c },
- { 646, 6, 10, 0x03d },
- { -2, 7, 0, 0x07c },
- { 390, 7, 8, 0x07d },
- { -15, 8, 3, 0x0fc },
- { -5, 8, 1, 0x0fd },
- { -7, 9, 1, 0x1fc },
- { -3, 9, 0, 0x1fd },
- { -16, 9, jbig2HuffmanLOW, 0x1fe },
- { 1670, 9, 32, 0x1ff },
- { 0, 0, jbig2HuffmanEOT, 0 }
-};
-
-JBIG2HuffmanTable huffTableI[] = {
- { 0, 2, jbig2HuffmanOOB, 0x000 },
- { -1, 3, 1, 0x002 },
- { 1, 3, 1, 0x003 },
- { 7, 3, 5, 0x004 },
- { -3, 4, 1, 0x00a },
- { 43, 4, 5, 0x00b },
- { 75, 4, 6, 0x00c },
- { 3, 5, 1, 0x01a },
- { 139, 5, 7, 0x01b },
- { 267, 5, 8, 0x01c },
- { 5, 6, 1, 0x03a },
- { 39, 6, 2, 0x03b },
- { 523, 6, 8, 0x03c },
- { 1291, 6, 11, 0x03d },
- { -5, 7, 1, 0x07c },
- { 779, 7, 9, 0x07d },
- { -31, 8, 4, 0x0fc },
- { -11, 8, 2, 0x0fd },
- { -15, 9, 2, 0x1fc },
- { -7, 9, 1, 0x1fd },
- { -32, 9, jbig2HuffmanLOW, 0x1fe },
- { 3339, 9, 32, 0x1ff },
- { 0, 0, jbig2HuffmanEOT, 0 }
-};
-
-JBIG2HuffmanTable huffTableJ[] = {
- { -2, 2, 2, 0x000 },
- { 6, 2, 6, 0x001 },
- { 0, 2, jbig2HuffmanOOB, 0x002 },
- { -3, 5, 0, 0x018 },
- { 2, 5, 0, 0x019 },
- { 70, 5, 5, 0x01a },
- { 3, 6, 0, 0x036 },
- { 102, 6, 5, 0x037 },
- { 134, 6, 6, 0x038 },
- { 198, 6, 7, 0x039 },
- { 326, 6, 8, 0x03a },
- { 582, 6, 9, 0x03b },
- { 1094, 6, 10, 0x03c },
- { -21, 7, 4, 0x07a },
- { -4, 7, 0, 0x07b },
- { 4, 7, 0, 0x07c },
- { 2118, 7, 11, 0x07d },
- { -5, 8, 0, 0x0fc },
- { 5, 8, 0, 0x0fd },
- { -22, 8, jbig2HuffmanLOW, 0x0fe },
- { 4166, 8, 32, 0x0ff },
- { 0, 0, jbig2HuffmanEOT, 0 }
-};
-
-JBIG2HuffmanTable huffTableK[] = {
- { 1, 1, 0, 0x000 },
- { 2, 2, 1, 0x002 },
- { 4, 4, 0, 0x00c },
- { 5, 4, 1, 0x00d },
- { 7, 5, 1, 0x01c },
- { 9, 5, 2, 0x01d },
- { 13, 6, 2, 0x03c },
- { 17, 7, 2, 0x07a },
- { 21, 7, 3, 0x07b },
- { 29, 7, 4, 0x07c },
- { 45, 7, 5, 0x07d },
- { 77, 7, 6, 0x07e },
- { 141, 7, 32, 0x07f },
- { 0, 0, jbig2HuffmanEOT, 0 }
-};
-
-JBIG2HuffmanTable huffTableL[] = {
- { 1, 1, 0, 0x000 },
- { 2, 2, 0, 0x002 },
- { 3, 3, 1, 0x006 },
- { 5, 5, 0, 0x01c },
- { 6, 5, 1, 0x01d },
- { 8, 6, 1, 0x03c },
- { 10, 7, 0, 0x07a },
- { 11, 7, 1, 0x07b },
- { 13, 7, 2, 0x07c },
- { 17, 7, 3, 0x07d },
- { 25, 7, 4, 0x07e },
- { 41, 8, 5, 0x0fe },
- { 73, 8, 32, 0x0ff },
- { 0, 0, jbig2HuffmanEOT, 0 }
-};
-
-JBIG2HuffmanTable huffTableM[] = {
- { 1, 1, 0, 0x000 },
- { 2, 3, 0, 0x004 },
- { 7, 3, 3, 0x005 },
- { 3, 4, 0, 0x00c },
- { 5, 4, 1, 0x00d },
- { 4, 5, 0, 0x01c },
- { 15, 6, 1, 0x03a },
- { 17, 6, 2, 0x03b },
- { 21, 6, 3, 0x03c },
- { 29, 6, 4, 0x03d },
- { 45, 6, 5, 0x03e },
- { 77, 7, 6, 0x07e },
- { 141, 7, 32, 0x07f },
- { 0, 0, jbig2HuffmanEOT, 0 }
-};
-
-JBIG2HuffmanTable huffTableN[] = {
- { 0, 1, 0, 0x000 },
- { -2, 3, 0, 0x004 },
- { -1, 3, 0, 0x005 },
- { 1, 3, 0, 0x006 },
- { 2, 3, 0, 0x007 },
- { 0, 0, jbig2HuffmanEOT, 0 }
-};
-
-JBIG2HuffmanTable huffTableO[] = {
- { 0, 1, 0, 0x000 },
- { -1, 3, 0, 0x004 },
- { 1, 3, 0, 0x005 },
- { -2, 4, 0, 0x00c },
- { 2, 4, 0, 0x00d },
- { -4, 5, 1, 0x01c },
- { 3, 5, 1, 0x01d },
- { -8, 6, 2, 0x03c },
- { 5, 6, 2, 0x03d },
- { -24, 7, 4, 0x07c },
- { 9, 7, 4, 0x07d },
- { -25, 7, jbig2HuffmanLOW, 0x07e },
- { 25, 7, 32, 0x07f },
- { 0, 0, jbig2HuffmanEOT, 0 }
-};
-
-//------------------------------------------------------------------------
-// JBIG2HuffmanDecoder
-//------------------------------------------------------------------------
-
-class JBIG2HuffmanDecoder {
-public:
-
- JBIG2HuffmanDecoder();
- ~JBIG2HuffmanDecoder();
- void setStream(Stream *strA) { str = strA; }
-
- void reset();
-
- // Returns false for OOB, otherwise sets *<x> and returns true.
- GBool decodeInt(int *x, JBIG2HuffmanTable *table);
-
- Guint readBits(Guint n);
- Guint readBit();
-
- // Sort the table by prefix length and assign prefix values.
- void buildTable(JBIG2HuffmanTable *table, Guint len);
-
-private:
-
- Stream *str;
- Guint buf;
- Guint bufLen;
-};
-
-JBIG2HuffmanDecoder::JBIG2HuffmanDecoder() {
- str = NULL;
- reset();
-}
-
-JBIG2HuffmanDecoder::~JBIG2HuffmanDecoder() {
-}
-
-void JBIG2HuffmanDecoder::reset() {
- buf = 0;
- bufLen = 0;
-}
-
-//~ optimize this
-GBool JBIG2HuffmanDecoder::decodeInt(int *x, JBIG2HuffmanTable *table) {
- Guint i, len, prefix;
-
- i = 0;
- len = 0;
- prefix = 0;
- while (table[i].rangeLen != jbig2HuffmanEOT) {
- while (len < table[i].prefixLen) {
- prefix = (prefix << 1) | readBit();
- ++len;
- }
- if (prefix == table[i].prefix) {
- if (table[i].rangeLen == jbig2HuffmanOOB) {
- return gFalse;
- }
- if (table[i].rangeLen == jbig2HuffmanLOW) {
- *x = table[i].val - readBits(32);
- } else if (table[i].rangeLen > 0) {
- *x = table[i].val + readBits(table[i].rangeLen);
- } else {
- *x = table[i].val;
- }
- return gTrue;
- }
- ++i;
- }
- return gFalse;
-}
-
-Guint JBIG2HuffmanDecoder::readBits(Guint n) {
- Guint x, mask, nLeft;
-
- mask = (n == 32) ? 0xffffffff : ((1 << n) - 1);
- if (bufLen >= n) {
- x = (buf >> (bufLen - n)) & mask;
- bufLen -= n;
- } else {
- x = buf & ((1 << bufLen) - 1);
- nLeft = n - bufLen;
- bufLen = 0;
- while (nLeft >= 8) {
- x = (x << 8) | (str->getChar() & 0xff);
- nLeft -= 8;
- }
- if (nLeft > 0) {
- buf = str->getChar();
- bufLen = 8 - nLeft;
- x = (x << nLeft) | ((buf >> bufLen) & ((1 << nLeft) - 1));
- }
- }
- return x;
-}
-
-Guint JBIG2HuffmanDecoder::readBit() {
- if (bufLen == 0) {
- buf = str->getChar();
- bufLen = 8;
- }
- --bufLen;
- return (buf >> bufLen) & 1;
-}
-
-void JBIG2HuffmanDecoder::buildTable(JBIG2HuffmanTable *table, Guint len) {
- Guint i, j, k, prefix;
- JBIG2HuffmanTable tab;
-
- // stable selection sort:
- // - entries with prefixLen > 0, in ascending prefixLen order
- // - entry with prefixLen = 0, rangeLen = EOT
- // - all other entries with prefixLen = 0
- // (on entry, table[len] has prefixLen = 0, rangeLen = EOT)
- for (i = 0; i < len; ++i) {
- for (j = i; j < len && table[j].prefixLen == 0; ++j) ;
- if (j == len) {
- break;
- }
- for (k = j + 1; k < len; ++k) {
- if (table[k].prefixLen > 0 &&
- table[k].prefixLen < table[j].prefixLen) {
- j = k;
- }
- }
- if (j != i) {
- tab = table[j];
- for (k = j; k > i; --k) {
- table[k] = table[k - 1];
- }
- table[i] = tab;
- }
- }
- table[i] = table[len];
-
- // assign prefixes
- i = 0;
- prefix = 0;
- table[i++].prefix = prefix++;
- for (; table[i].rangeLen != jbig2HuffmanEOT; ++i) {
- prefix <<= table[i].prefixLen - table[i-1].prefixLen;
- table[i].prefix = prefix++;
- }
-}
-
-//------------------------------------------------------------------------
-// JBIG2MMRDecoder
-//------------------------------------------------------------------------
-
-class JBIG2MMRDecoder {
-public:
-
- JBIG2MMRDecoder();
- ~JBIG2MMRDecoder();
- void setStream(Stream *strA) { str = strA; }
- void reset();
- int get2DCode();
- int getBlackCode();
- int getWhiteCode();
- Guint get24Bits();
- void skipTo(Guint length);
-
-private:
-
- Stream *str;
- Guint buf;
- Guint bufLen;
- Guint nBytesRead;
-};
-
-JBIG2MMRDecoder::JBIG2MMRDecoder() {
- str = NULL;
- reset();
-}
-
-JBIG2MMRDecoder::~JBIG2MMRDecoder() {
-}
-
-void JBIG2MMRDecoder::reset() {
- buf = 0;
- bufLen = 0;
- nBytesRead = 0;
-}
-
-int JBIG2MMRDecoder::get2DCode() {
- CCITTCode *p;
-
- if (bufLen == 0) {
- buf = str->getChar() & 0xff;
- bufLen = 8;
- ++nBytesRead;
- p = &twoDimTab1[(buf >> 1) & 0x7f];
- } else if (bufLen == 8) {
- p = &twoDimTab1[(buf >> 1) & 0x7f];
- } else {
- p = &twoDimTab1[(buf << (7 - bufLen)) & 0x7f];
- if (p->bits < 0 || p->bits > (int)bufLen) {
- buf = (buf << 8) | (str->getChar() & 0xff);
- bufLen += 8;
- ++nBytesRead;
- p = &twoDimTab1[(buf >> (bufLen - 7)) & 0x7f];
- }
- }
- if (p->bits < 0) {
- error(str->getPos(), "Bad two dim code in JBIG2 MMR stream");
- return 0;
- }
- bufLen -= p->bits;
- return p->n;
-}
-
-int JBIG2MMRDecoder::getWhiteCode() {
- CCITTCode *p;
- Guint code;
-
- if (bufLen == 0) {
- buf = str->getChar() & 0xff;
- bufLen = 8;
- ++nBytesRead;
- }
- while (1) {
- if (bufLen >= 7 && ((buf >> (bufLen - 7)) & 0x7f) == 0) {
- if (bufLen <= 12) {
- code = buf << (12 - bufLen);
- } else {
- code = buf >> (bufLen - 12);
- }
- p = &whiteTab1[code & 0x1f];
- } else {
- if (bufLen <= 9) {
- code = buf << (9 - bufLen);
- } else {
- code = buf >> (bufLen - 9);
- }
- p = &whiteTab2[code & 0x1ff];
- }
- if (p->bits > 0 && p->bits <= (int)bufLen) {
- bufLen -= p->bits;
- return p->n;
- }
- if (bufLen >= 12) {
- break;
- }
- buf = (buf << 8) | (str->getChar() & 0xff);
- bufLen += 8;
- ++nBytesRead;
- }
- error(str->getPos(), "Bad white code in JBIG2 MMR stream");
- // eat a bit and return a positive number so that the caller doesn't
- // go into an infinite loop
- --bufLen;
- return 1;
-}
-
-int JBIG2MMRDecoder::getBlackCode() {
- CCITTCode *p;
- Guint code;
-
- if (bufLen == 0) {
- buf = str->getChar() & 0xff;
- bufLen = 8;
- ++nBytesRead;
- }
- while (1) {
- if (bufLen >= 6 && ((buf >> (bufLen - 6)) & 0x3f) == 0) {
- if (bufLen <= 13) {
- code = buf << (13 - bufLen);
- } else {
- code = buf >> (bufLen - 13);
- }
- p = &blackTab1[code & 0x7f];
- } else if (bufLen >= 4 && ((buf >> (bufLen - 4)) & 0x0f) == 0) {
- if (bufLen <= 12) {
- code = buf << (12 - bufLen);
- } else {
- code = buf >> (bufLen - 12);
- }
- p = &blackTab2[(code & 0xff) - 64];
- } else {
- if (bufLen <= 6) {
- code = buf << (6 - bufLen);
- } else {
- code = buf >> (bufLen - 6);
- }
- p = &blackTab3[code & 0x3f];
- }
- if (p->bits > 0 && p->bits <= (int)bufLen) {
- bufLen -= p->bits;
- return p->n;
- }
- if (bufLen >= 13) {
- break;
- }
- buf = (buf << 8) | (str->getChar() & 0xff);
- bufLen += 8;
- ++nBytesRead;
- }
- error(str->getPos(), "Bad black code in JBIG2 MMR stream");
- // eat a bit and return a positive number so that the caller doesn't
- // go into an infinite loop
- --bufLen;
- return 1;
-}
-
-Guint JBIG2MMRDecoder::get24Bits() {
- while (bufLen < 24) {
- buf = (buf << 8) | (str->getChar() & 0xff);
- bufLen += 8;
- ++nBytesRead;
- }
- return (buf >> (bufLen - 24)) & 0xffffff;
-}
-
-void JBIG2MMRDecoder::skipTo(Guint length) {
- while (nBytesRead < length) {
- str->getChar();
- ++nBytesRead;
- }
-}
-
-//------------------------------------------------------------------------
-// JBIG2Segment
-//------------------------------------------------------------------------
-
-enum JBIG2SegmentType {
- jbig2SegBitmap,
- jbig2SegSymbolDict,
- jbig2SegPatternDict,
- jbig2SegCodeTable
-};
-
-class JBIG2Segment {
-public:
-
- JBIG2Segment(Guint segNumA) { segNum = segNumA; }
- virtual ~JBIG2Segment() {}
- void setSegNum(Guint segNumA) { segNum = segNumA; }
- Guint getSegNum() { return segNum; }
- virtual JBIG2SegmentType getType() = 0;
-
-private:
-
- Guint segNum;
-};
-
-//------------------------------------------------------------------------
-// JBIG2Bitmap
-//------------------------------------------------------------------------
-
-struct JBIG2BitmapPtr {
- Guchar *p;
- int shift;
- int x;
-};
-
-class JBIG2Bitmap: public JBIG2Segment {
-public:
-
- JBIG2Bitmap(Guint segNumA, int wA, int hA);
- virtual ~JBIG2Bitmap();
- virtual JBIG2SegmentType getType() { return jbig2SegBitmap; }
- JBIG2Bitmap *copy() { return new JBIG2Bitmap(0, this); }
- JBIG2Bitmap *getSlice(Guint x, Guint y, Guint wA, Guint hA);
- void expand(int newH, Guint pixel);
- void clearToZero();
- void clearToOne();
- int getWidth() { return w; }
- int getHeight() { return h; }
- int getPixel(int x, int y)
- { return (x < 0 || x >= w || y < 0 || y >= h) ? 0 :
- (data[y * line + (x >> 3)] >> (7 - (x & 7))) & 1; }
- void setPixel(int x, int y)
- { data[y * line + (x >> 3)] |= 1 << (7 - (x & 7)); }
- void clearPixel(int x, int y)
- { data[y * line + (x >> 3)] &= 0x7f7f >> (x & 7); }
- void getPixelPtr(int x, int y, JBIG2BitmapPtr *ptr);
- int nextPixel(JBIG2BitmapPtr *ptr);
- void duplicateRow(int yDest, int ySrc);
- void combine(JBIG2Bitmap *bitmap, int x, int y, Guint combOp);
- Guchar *getDataPtr() { return data; }
- int getDataSize() { return h * line; }
-
-private:
-
- JBIG2Bitmap(Guint segNumA, JBIG2Bitmap *bitmap);
-
- int w, h, line;
- Guchar *data;
-};
-
-JBIG2Bitmap::JBIG2Bitmap(Guint segNumA, int wA, int hA):
- JBIG2Segment(segNumA)
-{
- w = wA;
- h = hA;
- line = (wA + 7) >> 3;
- // need to allocate one extra guard byte for use in combine()
- data = (Guchar *)gmalloc(h * line + 1);
- data[h * line] = 0;
-}
-
-JBIG2Bitmap::JBIG2Bitmap(Guint segNumA, JBIG2Bitmap *bitmap):
- JBIG2Segment(segNumA)
-{
- w = bitmap->w;
- h = bitmap->h;
- line = bitmap->line;
- // need to allocate one extra guard byte for use in combine()
- data = (Guchar *)gmalloc(h * line + 1);
- memcpy(data, bitmap->data, h * line);
- data[h * line] = 0;
-}
-
-JBIG2Bitmap::~JBIG2Bitmap() {
- gfree(data);
-}
-
-//~ optimize this
-JBIG2Bitmap *JBIG2Bitmap::getSlice(Guint x, Guint y, Guint wA, Guint hA) {
- JBIG2Bitmap *slice;
- Guint xx, yy;
-
- slice = new JBIG2Bitmap(0, wA, hA);
- slice->clearToZero();
- for (yy = 0; yy < hA; ++yy) {
- for (xx = 0; xx < wA; ++xx) {
- if (getPixel(x + xx, y + yy)) {
- slice->setPixel(xx, yy);
- }
- }
- }
- return slice;
-}
-
-void JBIG2Bitmap::expand(int newH, Guint pixel) {
- if (newH <= h) {
- return;
- }
- // need to allocate one extra guard byte for use in combine()
- data = (Guchar *)grealloc(data, newH * line + 1);
- if (pixel) {
- memset(data + h * line, 0xff, (newH - h) * line);
- } else {
- memset(data + h * line, 0x00, (newH - h) * line);
- }
- h = newH;
- data[h * line] = 0;
-}
-
-void JBIG2Bitmap::clearToZero() {
- memset(data, 0, h * line);
-}
-
-void JBIG2Bitmap::clearToOne() {
- memset(data, 0xff, h * line);
-}
-
-inline void JBIG2Bitmap::getPixelPtr(int x, int y, JBIG2BitmapPtr *ptr) {
- if (y < 0 || y >= h || x >= w) {
- ptr->p = NULL;
- } else if (x < 0) {
- ptr->p = &data[y * line];
- ptr->shift = 7;
- ptr->x = x;
- } else {
- ptr->p = &data[y * line + (x >> 3)];
- ptr->shift = 7 - (x & 7);
- ptr->x = x;
- }
-}
-
-inline int JBIG2Bitmap::nextPixel(JBIG2BitmapPtr *ptr) {
- int pix;
-
- if (!ptr->p) {
- pix = 0;
- } else if (ptr->x < 0) {
- ++ptr->x;
- pix = 0;
- } else {
- pix = (*ptr->p >> ptr->shift) & 1;
- if (++ptr->x == w) {
- ptr->p = NULL;
- } else if (ptr->shift == 0) {
- ++ptr->p;
- ptr->shift = 7;
- } else {
- --ptr->shift;
- }
- }
- return pix;
-}
-
-void JBIG2Bitmap::duplicateRow(int yDest, int ySrc) {
- memcpy(data + yDest * line, data + ySrc * line, line);
-}
-
-void JBIG2Bitmap::combine(JBIG2Bitmap *bitmap, int x, int y,
- Guint combOp) {
- int x0, x1, y0, y1, xx, yy;
- Guchar *srcPtr, *destPtr;
- Guint src0, src1, src, dest, s1, s2, m1, m2, m3;
- GBool oneByte;
-
- if (y < 0) {
- y0 = -y;
- } else {
- y0 = 0;
- }
- if (y + bitmap->h > h) {
- y1 = h - y;
- } else {
- y1 = bitmap->h;
- }
- if (y0 >= y1) {
- return;
- }
-
- if (x >= 0) {
- x0 = x & ~7;
- } else {
- x0 = 0;
- }
- x1 = x + bitmap->w;
- if (x1 > w) {
- x1 = w;
- }
- if (x0 >= x1) {
- return;
- }
-
- s1 = x & 7;
- s2 = 8 - s1;
- m1 = 0xff >> (x1 & 7);
- m2 = 0xff << (((x1 & 7) == 0) ? 0 : 8 - (x1 & 7));
- m3 = (0xff >> s1) & m2;
-
- oneByte = x0 == ((x1 - 1) & ~7);
-
- for (yy = y0; yy < y1; ++yy) {
-
- // one byte per line -- need to mask both left and right side
- if (oneByte) {
- if (x >= 0) {
- destPtr = data + (y + yy) * line + (x >> 3);
- srcPtr = bitmap->data + yy * bitmap->line;
- dest = *destPtr;
- src1 = *srcPtr;
- switch (combOp) {
- case 0: // or
- dest |= (src1 >> s1) & m2;
- break;
- case 1: // and
- dest &= ((0xff00 | src1) >> s1) | m1;
- break;
- case 2: // xor
- dest ^= (src1 >> s1) & m2;
- break;
- case 3: // xnor
- dest ^= ((src1 ^ 0xff) >> s1) & m2;
- break;
- case 4: // replace
- dest = (dest & ~m3) | ((src1 >> s1) & m3);
- break;
- }
- *destPtr = dest;
- } else {
- destPtr = data + (y + yy) * line;
- srcPtr = bitmap->data + yy * bitmap->line + (-x >> 3);
- dest = *destPtr;
- src1 = *srcPtr;
- switch (combOp) {
- case 0: // or
- dest |= src1 & m2;
- break;
- case 1: // and
- dest &= src1 | m1;
- break;
- case 2: // xor
- dest ^= src1 & m2;
- break;
- case 3: // xnor
- dest ^= (src1 ^ 0xff) & m2;
- break;
- case 4: // replace
- dest = (src1 & m2) | (dest & m1);
- break;
- }
- *destPtr = dest;
- }
-
- // multiple bytes per line -- need to mask left side of left-most
- // byte and right side of right-most byte
- } else {
-
- // left-most byte
- if (x >= 0) {
- destPtr = data + (y + yy) * line + (x >> 3);
- srcPtr = bitmap->data + yy * bitmap->line;
- src1 = *srcPtr++;
- dest = *destPtr;
- switch (combOp) {
- case 0: // or
- dest |= src1 >> s1;
- break;
- case 1: // and
- dest &= (0xff00 | src1) >> s1;
- break;
- case 2: // xor
- dest ^= src1 >> s1;
- break;
- case 3: // xnor
- dest ^= (src1 ^ 0xff) >> s1;
- break;
- case 4: // replace
- dest = (dest & (0xff << s2)) | (src1 >> s1);
- break;
- }
- *destPtr++ = dest;
- xx = x0 + 8;
- } else {
- destPtr = data + (y + yy) * line;
- srcPtr = bitmap->data + yy * bitmap->line + (-x >> 3);
- src1 = *srcPtr++;
- xx = x0;
- }
-
- // middle bytes
- for (; xx < x1 - 8; xx += 8) {
- dest = *destPtr;
- src0 = src1;
- src1 = *srcPtr++;
- src = (((src0 << 8) | src1) >> s1) & 0xff;
- switch (combOp) {
- case 0: // or
- dest |= src;
- break;
- case 1: // and
- dest &= src;
- break;
- case 2: // xor
- dest ^= src;
- break;
- case 3: // xnor
- dest ^= src ^ 0xff;
- break;
- case 4: // replace
- dest = src;
- break;
- }
- *destPtr++ = dest;
- }
-
- // right-most byte
- // note: this last byte (src1) may not actually be used, depending
- // on the values of s1, m1, and m2 - and in fact, it may be off
- // the edge of the source bitmap, which means we need to allocate
- // one extra guard byte at the end of each bitmap
- dest = *destPtr;
- src0 = src1;
- src1 = *srcPtr++;
- src = (((src0 << 8) | src1) >> s1) & 0xff;
- switch (combOp) {
- case 0: // or
- dest |= src & m2;
- break;
- case 1: // and
- dest &= src | m1;
- break;
- case 2: // xor
- dest ^= src & m2;
- break;
- case 3: // xnor
- dest ^= (src ^ 0xff) & m2;
- break;
- case 4: // replace
- dest = (src & m2) | (dest & m1);
- break;
- }
- *destPtr = dest;
- }
- }
-}
-
-//------------------------------------------------------------------------
-// JBIG2SymbolDict
-//------------------------------------------------------------------------
-
-class JBIG2SymbolDict: public JBIG2Segment {
-public:
-
- JBIG2SymbolDict(Guint segNumA, Guint sizeA);
- virtual ~JBIG2SymbolDict();
- virtual JBIG2SegmentType getType() { return jbig2SegSymbolDict; }
- Guint getSize() { return size; }
- void setBitmap(Guint idx, JBIG2Bitmap *bitmap) { bitmaps[idx] = bitmap; }
- JBIG2Bitmap *getBitmap(Guint idx) { return bitmaps[idx]; }
- void setGenericRegionStats(JArithmeticDecoderStats *stats)
- { genericRegionStats = stats; }
- void setRefinementRegionStats(JArithmeticDecoderStats *stats)
- { refinementRegionStats = stats; }
- JArithmeticDecoderStats *getGenericRegionStats()
- { return genericRegionStats; }
- JArithmeticDecoderStats *getRefinementRegionStats()
- { return refinementRegionStats; }
-
-private:
-
- Guint size;
- JBIG2Bitmap **bitmaps;
- JArithmeticDecoderStats *genericRegionStats;
- JArithmeticDecoderStats *refinementRegionStats;
-};
-
-JBIG2SymbolDict::JBIG2SymbolDict(Guint segNumA, Guint sizeA):
- JBIG2Segment(segNumA)
-{
- size = sizeA;
- bitmaps = (JBIG2Bitmap **)gmallocn(size, sizeof(JBIG2Bitmap *));
- genericRegionStats = NULL;
- refinementRegionStats = NULL;
-}
-
-JBIG2SymbolDict::~JBIG2SymbolDict() {
- Guint i;
-
- for (i = 0; i < size; ++i) {
- delete bitmaps[i];
- }
- gfree(bitmaps);
- if (genericRegionStats) {
- delete genericRegionStats;
- }
- if (refinementRegionStats) {
- delete refinementRegionStats;
- }
-}
-
-//------------------------------------------------------------------------
-// JBIG2PatternDict
-//------------------------------------------------------------------------
-
-class JBIG2PatternDict: public JBIG2Segment {
-public:
-
- JBIG2PatternDict(Guint segNumA, Guint sizeA);
- virtual ~JBIG2PatternDict();
- virtual JBIG2SegmentType getType() { return jbig2SegPatternDict; }
- Guint getSize() { return size; }
- void setBitmap(Guint idx, JBIG2Bitmap *bitmap) { bitmaps[idx] = bitmap; }
- JBIG2Bitmap *getBitmap(Guint idx) { return bitmaps[idx]; }
-
-private:
-
- Guint size;
- JBIG2Bitmap **bitmaps;
-};
-
-JBIG2PatternDict::JBIG2PatternDict(Guint segNumA, Guint sizeA):
- JBIG2Segment(segNumA)
-{
- size = sizeA;
- bitmaps = (JBIG2Bitmap **)gmallocn(size, sizeof(JBIG2Bitmap *));
-}
-
-JBIG2PatternDict::~JBIG2PatternDict() {
- Guint i;
-
- for (i = 0; i < size; ++i) {
- delete bitmaps[i];
- }
- gfree(bitmaps);
-}
-
-//------------------------------------------------------------------------
-// JBIG2CodeTable
-//------------------------------------------------------------------------
-
-class JBIG2CodeTable: public JBIG2Segment {
-public:
-
- JBIG2CodeTable(Guint segNumA, JBIG2HuffmanTable *tableA);
- virtual ~JBIG2CodeTable();
- virtual JBIG2SegmentType getType() { return jbig2SegCodeTable; }
- JBIG2HuffmanTable *getHuffTable() { return table; }
-
-private:
-
- JBIG2HuffmanTable *table;
-};
-
-JBIG2CodeTable::JBIG2CodeTable(Guint segNumA, JBIG2HuffmanTable *tableA):
- JBIG2Segment(segNumA)
-{
- table = tableA;
-}
-
-JBIG2CodeTable::~JBIG2CodeTable() {
- gfree(table);
-}
-
-//------------------------------------------------------------------------
-// JBIG2Stream
-//------------------------------------------------------------------------
-
-JBIG2Stream::JBIG2Stream(Stream *strA, Object *globalsStream):
- FilterStream(strA)
-{
- pageBitmap = NULL;
-
- arithDecoder = new JArithmeticDecoder();
- genericRegionStats = new JArithmeticDecoderStats(1 << 1);
- refinementRegionStats = new JArithmeticDecoderStats(1 << 1);
- iadhStats = new JArithmeticDecoderStats(1 << 9);
- iadwStats = new JArithmeticDecoderStats(1 << 9);
- iaexStats = new JArithmeticDecoderStats(1 << 9);
- iaaiStats = new JArithmeticDecoderStats(1 << 9);
- iadtStats = new JArithmeticDecoderStats(1 << 9);
- iaitStats = new JArithmeticDecoderStats(1 << 9);
- iafsStats = new JArithmeticDecoderStats(1 << 9);
- iadsStats = new JArithmeticDecoderStats(1 << 9);
- iardxStats = new JArithmeticDecoderStats(1 << 9);
- iardyStats = new JArithmeticDecoderStats(1 << 9);
- iardwStats = new JArithmeticDecoderStats(1 << 9);
- iardhStats = new JArithmeticDecoderStats(1 << 9);
- iariStats = new JArithmeticDecoderStats(1 << 9);
- iaidStats = new JArithmeticDecoderStats(1 << 1);
- huffDecoder = new JBIG2HuffmanDecoder();
- mmrDecoder = new JBIG2MMRDecoder();
-
- segments = globalSegments = new GList();
- if (globalsStream->isStream()) {
- curStr = globalsStream->getStream();
- curStr->reset();
- arithDecoder->setStream(curStr);
- huffDecoder->setStream(curStr);
- mmrDecoder->setStream(curStr);
- readSegments();
- }
-
- segments = NULL;
- curStr = NULL;
- dataPtr = dataEnd = NULL;
-}
-
-JBIG2Stream::~JBIG2Stream() {
- delete arithDecoder;
- delete genericRegionStats;
- delete refinementRegionStats;
- delete iadhStats;
- delete iadwStats;
- delete iaexStats;
- delete iaaiStats;
- delete iadtStats;
- delete iaitStats;
- delete iafsStats;
- delete iadsStats;
- delete iardxStats;
- delete iardyStats;
- delete iardwStats;
- delete iardhStats;
- delete iariStats;
- delete iaidStats;
- delete huffDecoder;
- delete mmrDecoder;
- if (pageBitmap) {
- delete pageBitmap;
- }
- if (segments) {
- deleteGList(segments, JBIG2Segment);
- }
- if (globalSegments) {
- deleteGList(globalSegments, JBIG2Segment);
- }
- delete str;
-}
-
-void JBIG2Stream::reset() {
- if (pageBitmap) {
- delete pageBitmap;
- pageBitmap = NULL;
- }
- if (segments) {
- deleteGList(segments, JBIG2Segment);
- }
- segments = new GList();
-
- curStr = str;
- curStr->reset();
- arithDecoder->setStream(curStr);
- huffDecoder->setStream(curStr);
- mmrDecoder->setStream(curStr);
- readSegments();
-
- if (pageBitmap) {
- dataPtr = pageBitmap->getDataPtr();
- dataEnd = dataPtr + pageBitmap->getDataSize();
- } else {
- dataPtr = NULL;
- }
-}
-
-int JBIG2Stream::getChar() {
- if (dataPtr && dataPtr < dataEnd) {
- return (*dataPtr++ ^ 0xff) & 0xff;
- }
- return EOF;
-}
-
-int JBIG2Stream::lookChar() {
- if (dataPtr && dataPtr < dataEnd) {
- return (*dataPtr ^ 0xff) & 0xff;
- }
- return EOF;
-}
-
-GString *JBIG2Stream::getPSFilter(int psLevel, char *indent) {
- return NULL;
-}
-
-GBool JBIG2Stream::isBinary(GBool last) {
- return str->isBinary(gTrue);
-}
-
-void JBIG2Stream::readSegments() {
- Guint segNum, segFlags, segType, page, segLength;
- Guint refFlags, nRefSegs;
- Guint *refSegs;
- int c1, c2, c3;
- Guint i;
-
- while (readULong(&segNum)) {
-
- // segment header flags
- if (!readUByte(&segFlags)) {
- goto eofError1;
- }
- segType = segFlags & 0x3f;
-
- // referred-to segment count and retention flags
- if (!readUByte(&refFlags)) {
- goto eofError1;
- }
- nRefSegs = refFlags >> 5;
- if (nRefSegs == 7) {
- if ((c1 = curStr->getChar()) == EOF ||
- (c2 = curStr->getChar()) == EOF ||
- (c3 = curStr->getChar()) == EOF) {
- goto eofError1;
- }
- refFlags = (refFlags << 24) | (c1 << 16) | (c2 << 8) | c3;
- nRefSegs = refFlags & 0x1fffffff;
- for (i = 0; i < (nRefSegs + 9) >> 3; ++i) {
- c1 = curStr->getChar();
- }
- }
-
- // referred-to segment numbers
- refSegs = (Guint *)gmallocn(nRefSegs, sizeof(Guint));
- if (segNum <= 256) {
- for (i = 0; i < nRefSegs; ++i) {
- if (!readUByte(&refSegs[i])) {
- goto eofError2;
- }
- }
- } else if (segNum <= 65536) {
- for (i = 0; i < nRefSegs; ++i) {
- if (!readUWord(&refSegs[i])) {
- goto eofError2;
- }
- }
- } else {
- for (i = 0; i < nRefSegs; ++i) {
- if (!readULong(&refSegs[i])) {
- goto eofError2;
- }
- }
- }
-
- // segment page association
- if (segFlags & 0x40) {
- if (!readULong(&page)) {
- goto eofError2;
- }
- } else {
- if (!readUByte(&page)) {
- goto eofError2;
- }
- }
-
- // segment data length
- if (!readULong(&segLength)) {
- goto eofError2;
- }
-
- // read the segment data
- switch (segType) {
- case 0:
- if (!readSymbolDictSeg(segNum, segLength, refSegs, nRefSegs)) {
- goto syntaxError;
- }
- break;
- case 4:
- readTextRegionSeg(segNum, gFalse, gFalse, segLength, refSegs, nRefSegs);
- break;
- case 6:
- readTextRegionSeg(segNum, gTrue, gFalse, segLength, refSegs, nRefSegs);
- break;
- case 7:
- readTextRegionSeg(segNum, gTrue, gTrue, segLength, refSegs, nRefSegs);
- break;
- case 16:
- readPatternDictSeg(segNum, segLength);
- break;
- case 20:
- readHalftoneRegionSeg(segNum, gFalse, gFalse, segLength,
- refSegs, nRefSegs);
- break;
- case 22:
- readHalftoneRegionSeg(segNum, gTrue, gFalse, segLength,
- refSegs, nRefSegs);
- break;
- case 23:
- readHalftoneRegionSeg(segNum, gTrue, gTrue, segLength,
- refSegs, nRefSegs);
- break;
- case 36:
- readGenericRegionSeg(segNum, gFalse, gFalse, segLength);
- break;
- case 38:
- readGenericRegionSeg(segNum, gTrue, gFalse, segLength);
- break;
- case 39:
- readGenericRegionSeg(segNum, gTrue, gTrue, segLength);
- break;
- case 40:
- readGenericRefinementRegionSeg(segNum, gFalse, gFalse, segLength,
- refSegs, nRefSegs);
- break;
- case 42:
- readGenericRefinementRegionSeg(segNum, gTrue, gFalse, segLength,
- refSegs, nRefSegs);
- break;
- case 43:
- readGenericRefinementRegionSeg(segNum, gTrue, gTrue, segLength,
- refSegs, nRefSegs);
- break;
- case 48:
- readPageInfoSeg(segLength);
- break;
- case 50:
- readEndOfStripeSeg(segLength);
- break;
- case 52:
- readProfilesSeg(segLength);
- break;
- case 53:
- readCodeTableSeg(segNum, segLength);
- break;
- case 62:
- readExtensionSeg(segLength);
- break;
- default:
- error(getPos(), "Unknown segment type in JBIG2 stream");
- for (i = 0; i < segLength; ++i) {
- if ((c1 = curStr->getChar()) == EOF) {
- goto eofError2;
- }
- }
- break;
- }
-
- gfree(refSegs);
- }
-
- return;
-
- syntaxError:
- gfree(refSegs);
- return;
-
- eofError2:
- gfree(refSegs);
- eofError1:
- error(getPos(), "Unexpected EOF in JBIG2 stream");
-}
-
-GBool JBIG2Stream::readSymbolDictSeg(Guint segNum, Guint length,
- Guint *refSegs, Guint nRefSegs) {
- JBIG2SymbolDict *symbolDict;
- JBIG2HuffmanTable *huffDHTable, *huffDWTable;
- JBIG2HuffmanTable *huffBMSizeTable, *huffAggInstTable;
- JBIG2Segment *seg;
- GList *codeTables;
- JBIG2SymbolDict *inputSymbolDict;
- Guint flags, sdTemplate, sdrTemplate, huff, refAgg;
- Guint huffDH, huffDW, huffBMSize, huffAggInst;
- Guint contextUsed, contextRetained;
- int sdATX[4], sdATY[4], sdrATX[2], sdrATY[2];
- Guint numExSyms, numNewSyms, numInputSyms, symCodeLen;
- JBIG2Bitmap **bitmaps;
- JBIG2Bitmap *collBitmap, *refBitmap;
- Guint *symWidths;
- Guint symHeight, symWidth, totalWidth, x, symID;
- int dh, dw, refAggNum, refDX, refDY, bmSize;
- GBool ex;
- int run, cnt;
- Guint i, j, k;
- Guchar *p;
-
- // symbol dictionary flags
- if (!readUWord(&flags)) {
- goto eofError;
- }
- sdTemplate = (flags >> 10) & 3;
- sdrTemplate = (flags >> 12) & 1;
- huff = flags & 1;
- refAgg = (flags >> 1) & 1;
- huffDH = (flags >> 2) & 3;
- huffDW = (flags >> 4) & 3;
- huffBMSize = (flags >> 6) & 1;
- huffAggInst = (flags >> 7) & 1;
- contextUsed = (flags >> 8) & 1;
- contextRetained = (flags >> 9) & 1;
-
- // symbol dictionary AT flags
- if (!huff) {
- if (sdTemplate == 0) {
- if (!readByte(&sdATX[0]) ||
- !readByte(&sdATY[0]) ||
- !readByte(&sdATX[1]) ||
- !readByte(&sdATY[1]) ||
- !readByte(&sdATX[2]) ||
- !readByte(&sdATY[2]) ||
- !readByte(&sdATX[3]) ||
- !readByte(&sdATY[3])) {
- goto eofError;
- }
- } else {
- if (!readByte(&sdATX[0]) ||
- !readByte(&sdATY[0])) {
- goto eofError;
- }
- }
- }
-
- // symbol dictionary refinement AT flags
- if (refAgg && !sdrTemplate) {
- if (!readByte(&sdrATX[0]) ||
- !readByte(&sdrATY[0]) ||
- !readByte(&sdrATX[1]) ||
- !readByte(&sdrATY[1])) {
- goto eofError;
- }
- }
-
- // SDNUMEXSYMS and SDNUMNEWSYMS
- if (!readULong(&numExSyms) || !readULong(&numNewSyms)) {
- goto eofError;
- }
-
- // get referenced segments: input symbol dictionaries and code tables
- codeTables = new GList();
- numInputSyms = 0;
- for (i = 0; i < nRefSegs; ++i) {
- seg = findSegment(refSegs[i]);
- if (seg->getType() == jbig2SegSymbolDict) {
- numInputSyms += ((JBIG2SymbolDict *)seg)->getSize();
- } else if (seg->getType() == jbig2SegCodeTable) {
- codeTables->append(seg);
- }
- }
-
- // compute symbol code length
- symCodeLen = 0;
- i = 1;
- while (i < numInputSyms + numNewSyms) {
- ++symCodeLen;
- i <<= 1;
- }
-
- // get the input symbol bitmaps
- bitmaps = (JBIG2Bitmap **)gmallocn(numInputSyms + numNewSyms,
- sizeof(JBIG2Bitmap *));
- for (i = 0; i < numInputSyms + numNewSyms; ++i) {
- bitmaps[i] = NULL;
- }
- k = 0;
- inputSymbolDict = NULL;
- for (i = 0; i < nRefSegs; ++i) {
- seg = findSegment(refSegs[i]);
- if (seg->getType() == jbig2SegSymbolDict) {
- inputSymbolDict = (JBIG2SymbolDict *)seg;
- for (j = 0; j < inputSymbolDict->getSize(); ++j) {
- bitmaps[k++] = inputSymbolDict->getBitmap(j);
- }
- }
- }
-
- // get the Huffman tables
- huffDHTable = huffDWTable = NULL; // make gcc happy
- huffBMSizeTable = huffAggInstTable = NULL; // make gcc happy
- i = 0;
- if (huff) {
- if (huffDH == 0) {
- huffDHTable = huffTableD;
- } else if (huffDH == 1) {
- huffDHTable = huffTableE;
- } else {
- huffDHTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
- }
- if (huffDW == 0) {
- huffDWTable = huffTableB;
- } else if (huffDW == 1) {
- huffDWTable = huffTableC;
- } else {
- huffDWTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
- }
- if (huffBMSize == 0) {
- huffBMSizeTable = huffTableA;
- } else {
- huffBMSizeTable =
- ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
- }
- if (huffAggInst == 0) {
- huffAggInstTable = huffTableA;
- } else {
- huffAggInstTable =
- ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
- }
- }
- delete codeTables;
-
- // set up the Huffman decoder
- if (huff) {
- huffDecoder->reset();
-
- // set up the arithmetic decoder
- } else {
- if (contextUsed && inputSymbolDict) {
- resetGenericStats(sdTemplate, inputSymbolDict->getGenericRegionStats());
- } else {
- resetGenericStats(sdTemplate, NULL);
- }
- resetIntStats(symCodeLen);
- arithDecoder->start();
- }
-
- // set up the arithmetic decoder for refinement/aggregation
- if (refAgg) {
- if (contextUsed && inputSymbolDict) {
- resetRefinementStats(sdrTemplate,
- inputSymbolDict->getRefinementRegionStats());
- } else {
- resetRefinementStats(sdrTemplate, NULL);
- }
- }
-
- // allocate symbol widths storage
- symWidths = NULL;
- if (huff && !refAgg) {
- symWidths = (Guint *)gmallocn(numNewSyms, sizeof(Guint));
- }
-
- symHeight = 0;
- i = 0;
- while (i < numNewSyms) {
-
- // read the height class delta height
- if (huff) {
- huffDecoder->decodeInt(&dh, huffDHTable);
- } else {
- arithDecoder->decodeInt(&dh, iadhStats);
- }
- if (dh < 0 && (Guint)-dh >= symHeight) {
- error(getPos(), "Bad delta-height value in JBIG2 symbol dictionary");
- goto syntaxError;
- }
- symHeight += dh;
- symWidth = 0;
- totalWidth = 0;
- j = i;
-
- // read the symbols in this height class
- while (1) {
-
- // read the delta width
- if (huff) {
- if (!huffDecoder->decodeInt(&dw, huffDWTable)) {
- break;
- }
- } else {
- if (!arithDecoder->decodeInt(&dw, iadwStats)) {
- break;
- }
- }
- if (dw < 0 && (Guint)-dw >= symWidth) {
- error(getPos(), "Bad delta-height value in JBIG2 symbol dictionary");
- goto syntaxError;
- }
- symWidth += dw;
-
- // using a collective bitmap, so don't read a bitmap here
- if (huff && !refAgg) {
- symWidths[i] = symWidth;
- totalWidth += symWidth;
-
- // refinement/aggregate coding
- } else if (refAgg) {
- if (huff) {
- if (!huffDecoder->decodeInt(&refAggNum, huffAggInstTable)) {
- break;
- }
- } else {
- if (!arithDecoder->decodeInt(&refAggNum, iaaiStats)) {
- break;
- }
- }
-#if 0 //~ This special case was added about a year before the final draft
- //~ of the JBIG2 spec was released. I have encountered some old
- //~ JBIG2 images that predate it.
- if (0) {
-#else
- if (refAggNum == 1) {
-#endif
- if (huff) {
- symID = huffDecoder->readBits(symCodeLen);
- huffDecoder->decodeInt(&refDX, huffTableO);
- huffDecoder->decodeInt(&refDY, huffTableO);
- huffDecoder->decodeInt(&bmSize, huffTableA);
- huffDecoder->reset();
- arithDecoder->start();
- } else {
- symID = arithDecoder->decodeIAID(symCodeLen, iaidStats);
- arithDecoder->decodeInt(&refDX, iardxStats);
- arithDecoder->decodeInt(&refDY, iardyStats);
- }
- refBitmap = bitmaps[symID];
- bitmaps[numInputSyms + i] =
- readGenericRefinementRegion(symWidth, symHeight,
- sdrTemplate, gFalse,
- refBitmap, refDX, refDY,
- sdrATX, sdrATY);
- //~ do we need to use the bmSize value here (in Huffman mode)?
- } else {
- bitmaps[numInputSyms + i] =
- readTextRegion(huff, gTrue, symWidth, symHeight,
- refAggNum, 0, numInputSyms + i, NULL,
- symCodeLen, bitmaps, 0, 0, 0, 1, 0,
- huffTableF, huffTableH, huffTableK, huffTableO,
- huffTableO, huffTableO, huffTableO, huffTableA,
- sdrTemplate, sdrATX, sdrATY);
- }
-
- // non-ref/agg coding
- } else {
- bitmaps[numInputSyms + i] =
- readGenericBitmap(gFalse, symWidth, symHeight,
- sdTemplate, gFalse, gFalse, NULL,
- sdATX, sdATY, 0);
- }
-
- ++i;
- }
-
- // read the collective bitmap
- if (huff && !refAgg) {
- huffDecoder->decodeInt(&bmSize, huffBMSizeTable);
- huffDecoder->reset();
- if (bmSize == 0) {
- collBitmap = new JBIG2Bitmap(0, totalWidth, symHeight);
- bmSize = symHeight * ((totalWidth + 7) >> 3);
- p = collBitmap->getDataPtr();
- for (k = 0; k < (Guint)bmSize; ++k) {
- *p++ = curStr->getChar();
- }
- } else {
- collBitmap = readGenericBitmap(gTrue, totalWidth, symHeight,
- 0, gFalse, gFalse, NULL, NULL, NULL,
- bmSize);
- }
- x = 0;
- for (; j < i; ++j) {
- bitmaps[numInputSyms + j] =
- collBitmap->getSlice(x, 0, symWidths[j], symHeight);
- x += symWidths[j];
- }
- delete collBitmap;
- }
- }
-
- // create the symbol dict object
- symbolDict = new JBIG2SymbolDict(segNum, numExSyms);
-
- // exported symbol list
- i = j = 0;
- ex = gFalse;
- while (i < numInputSyms + numNewSyms) {
- if (huff) {
- huffDecoder->decodeInt(&run, huffTableA);
- } else {
- arithDecoder->decodeInt(&run, iaexStats);
- }
- if (ex) {
- for (cnt = 0; cnt < run; ++cnt) {
- symbolDict->setBitmap(j++, bitmaps[i++]->copy());
- }
- } else {
- i += run;
- }
- ex = !ex;
- }
-
- for (i = 0; i < numNewSyms; ++i) {
- delete bitmaps[numInputSyms + i];
- }
- gfree(bitmaps);
- if (symWidths) {
- gfree(symWidths);
- }
-
- // save the arithmetic decoder stats
- if (!huff && contextRetained) {
- symbolDict->setGenericRegionStats(genericRegionStats->copy());
- if (refAgg) {
- symbolDict->setRefinementRegionStats(refinementRegionStats->copy());
- }
- }
-
- // store the new symbol dict
- segments->append(symbolDict);
-
- return gTrue;
-
- syntaxError:
- for (i = 0; i < numNewSyms; ++i) {
- if (bitmaps[numInputSyms + i]) {
- delete bitmaps[numInputSyms + i];
- }
- }
- gfree(bitmaps);
- if (symWidths) {
- gfree(symWidths);
- }
- return gFalse;
-
- eofError:
- error(getPos(), "Unexpected EOF in JBIG2 stream");
- return gFalse;
-}
-
-void JBIG2Stream::readTextRegionSeg(Guint segNum, GBool imm,
- GBool lossless, Guint length,
- Guint *refSegs, Guint nRefSegs) {
- JBIG2Bitmap *bitmap;
- JBIG2HuffmanTable runLengthTab[36];
- JBIG2HuffmanTable *symCodeTab;
- JBIG2HuffmanTable *huffFSTable, *huffDSTable, *huffDTTable;
- JBIG2HuffmanTable *huffRDWTable, *huffRDHTable;
- JBIG2HuffmanTable *huffRDXTable, *huffRDYTable, *huffRSizeTable;
- JBIG2Segment *seg;
- GList *codeTables;
- JBIG2SymbolDict *symbolDict;
- JBIG2Bitmap **syms;
- Guint w, h, x, y, segInfoFlags, extCombOp;
- Guint flags, huff, refine, logStrips, refCorner, transposed;
- Guint combOp, defPixel, templ;
- int sOffset;
- Guint huffFlags, huffFS, huffDS, huffDT;
- Guint huffRDW, huffRDH, huffRDX, huffRDY, huffRSize;
- Guint numInstances, numSyms, symCodeLen;
- int atx[2], aty[2];
- Guint i, k, kk;
- int j;
-
- // region segment info field
- if (!readULong(&w) || !readULong(&h) ||
- !readULong(&x) || !readULong(&y) ||
- !readUByte(&segInfoFlags)) {
- goto eofError;
- }
- extCombOp = segInfoFlags & 7;
-
- // rest of the text region header
- if (!readUWord(&flags)) {
- goto eofError;
- }
- huff = flags & 1;
- refine = (flags >> 1) & 1;
- logStrips = (flags >> 2) & 3;
- refCorner = (flags >> 4) & 3;
- transposed = (flags >> 6) & 1;
- combOp = (flags >> 7) & 3;
- defPixel = (flags >> 9) & 1;
- sOffset = (flags >> 10) & 0x1f;
- if (sOffset & 0x10) {
- sOffset |= -1 - 0x0f;
- }
- templ = (flags >> 15) & 1;
- huffFS = huffDS = huffDT = 0; // make gcc happy
- huffRDW = huffRDH = huffRDX = huffRDY = huffRSize = 0; // make gcc happy
- if (huff) {
- if (!readUWord(&huffFlags)) {
- goto eofError;
- }
- huffFS = huffFlags & 3;
- huffDS = (huffFlags >> 2) & 3;
- huffDT = (huffFlags >> 4) & 3;
- huffRDW = (huffFlags >> 6) & 3;
- huffRDH = (huffFlags >> 8) & 3;
- huffRDX = (huffFlags >> 10) & 3;
- huffRDY = (huffFlags >> 12) & 3;
- huffRSize = (huffFlags >> 14) & 1;
- }
- if (refine && templ == 0) {
- if (!readByte(&atx[0]) || !readByte(&aty[0]) ||
- !readByte(&atx[1]) || !readByte(&aty[1])) {
- goto eofError;
- }
- }
- if (!readULong(&numInstances)) {
- goto eofError;
- }
-
- // get symbol dictionaries and tables
- codeTables = new GList();
- numSyms = 0;
- for (i = 0; i < nRefSegs; ++i) {
- if ((seg = findSegment(refSegs[i]))) {
- if (seg->getType() == jbig2SegSymbolDict) {
- numSyms += ((JBIG2SymbolDict *)seg)->getSize();
- } else if (seg->getType() == jbig2SegCodeTable) {
- codeTables->append(seg);
- }
- } else {
- error(getPos(), "Invalid segment reference in JBIG2 text region");
- }
- }
- symCodeLen = 0;
- i = 1;
- while (i < numSyms) {
- ++symCodeLen;
- i <<= 1;
- }
-
- // get the symbol bitmaps
- syms = (JBIG2Bitmap **)gmallocn(numSyms, sizeof(JBIG2Bitmap *));
- kk = 0;
- for (i = 0; i < nRefSegs; ++i) {
- if ((seg = findSegment(refSegs[i]))) {
- if (seg->getType() == jbig2SegSymbolDict) {
- symbolDict = (JBIG2SymbolDict *)seg;
- for (k = 0; k < symbolDict->getSize(); ++k) {
- syms[kk++] = symbolDict->getBitmap(k);
- }
- }
- }
- }
-
- // get the Huffman tables
- huffFSTable = huffDSTable = huffDTTable = NULL; // make gcc happy
- huffRDWTable = huffRDHTable = NULL; // make gcc happy
- huffRDXTable = huffRDYTable = huffRSizeTable = NULL; // make gcc happy
- i = 0;
- if (huff) {
- if (huffFS == 0) {
- huffFSTable = huffTableF;
- } else if (huffFS == 1) {
- huffFSTable = huffTableG;
- } else {
- huffFSTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
- }
- if (huffDS == 0) {
- huffDSTable = huffTableH;
- } else if (huffDS == 1) {
- huffDSTable = huffTableI;
- } else if (huffDS == 2) {
- huffDSTable = huffTableJ;
- } else {
- huffDSTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
- }
- if (huffDT == 0) {
- huffDTTable = huffTableK;
- } else if (huffDT == 1) {
- huffDTTable = huffTableL;
- } else if (huffDT == 2) {
- huffDTTable = huffTableM;
- } else {
- huffDTTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
- }
- if (huffRDW == 0) {
- huffRDWTable = huffTableN;
- } else if (huffRDW == 1) {
- huffRDWTable = huffTableO;
- } else {
- huffRDWTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
- }
- if (huffRDH == 0) {
- huffRDHTable = huffTableN;
- } else if (huffRDH == 1) {
- huffRDHTable = huffTableO;
- } else {
- huffRDHTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
- }
- if (huffRDX == 0) {
- huffRDXTable = huffTableN;
- } else if (huffRDX == 1) {
- huffRDXTable = huffTableO;
- } else {
- huffRDXTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
- }
- if (huffRDY == 0) {
- huffRDYTable = huffTableN;
- } else if (huffRDY == 1) {
- huffRDYTable = huffTableO;
- } else {
- huffRDYTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
- }
- if (huffRSize == 0) {
- huffRSizeTable = huffTableA;
- } else {
- huffRSizeTable =
- ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
- }
- }
- delete codeTables;
-
- // symbol ID Huffman decoding table
- if (huff) {
- huffDecoder->reset();
- for (i = 0; i < 32; ++i) {
- runLengthTab[i].val = i;
- runLengthTab[i].prefixLen = huffDecoder->readBits(4);
- runLengthTab[i].rangeLen = 0;
- }
- runLengthTab[32].val = 0x103;
- runLengthTab[32].prefixLen = huffDecoder->readBits(4);
- runLengthTab[32].rangeLen = 2;
- runLengthTab[33].val = 0x203;
- runLengthTab[33].prefixLen = huffDecoder->readBits(4);
- runLengthTab[33].rangeLen = 3;
- runLengthTab[34].val = 0x20b;
- runLengthTab[34].prefixLen = huffDecoder->readBits(4);
- runLengthTab[34].rangeLen = 7;
- runLengthTab[35].prefixLen = 0;
- runLengthTab[35].rangeLen = jbig2HuffmanEOT;
- huffDecoder->buildTable(runLengthTab, 35);
- symCodeTab = (JBIG2HuffmanTable *)gmallocn(numSyms + 1,
- sizeof(JBIG2HuffmanTable));
- for (i = 0; i < numSyms; ++i) {
- symCodeTab[i].val = i;
- symCodeTab[i].rangeLen = 0;
- }
- i = 0;
- while (i < numSyms) {
- huffDecoder->decodeInt(&j, runLengthTab);
- if (j > 0x200) {
- for (j -= 0x200; j && i < numSyms; --j) {
- symCodeTab[i++].prefixLen = 0;
- }
- } else if (j > 0x100) {
- for (j -= 0x100; j && i < numSyms; --j) {
- symCodeTab[i].prefixLen = symCodeTab[i-1].prefixLen;
- ++i;
- }
- } else {
- symCodeTab[i++].prefixLen = j;
- }
- }
- symCodeTab[numSyms].prefixLen = 0;
- symCodeTab[numSyms].rangeLen = jbig2HuffmanEOT;
- huffDecoder->buildTable(symCodeTab, numSyms);
- huffDecoder->reset();
-
- // set up the arithmetic decoder
- } else {
- symCodeTab = NULL;
- resetIntStats(symCodeLen);
- arithDecoder->start();
- }
- if (refine) {
- resetRefinementStats(templ, NULL);
- }
-
- bitmap = readTextRegion(huff, refine, w, h, numInstances,
- logStrips, numSyms, symCodeTab, symCodeLen, syms,
- defPixel, combOp, transposed, refCorner, sOffset,
- huffFSTable, huffDSTable, huffDTTable,
- huffRDWTable, huffRDHTable,
- huffRDXTable, huffRDYTable, huffRSizeTable,
- templ, atx, aty);
-
- gfree(syms);
-
- // combine the region bitmap into the page bitmap
- if (imm) {
- if (pageH == 0xffffffff && y + h > curPageH) {
- pageBitmap->expand(y + h, pageDefPixel);
- }
- pageBitmap->combine(bitmap, x, y, extCombOp);
- delete bitmap;
-
- // store the region bitmap
- } else {
- bitmap->setSegNum(segNum);
- segments->append(bitmap);
- }
-
- // clean up the Huffman decoder
- if (huff) {
- gfree(symCodeTab);
- }
-
- return;
-
- eofError:
- error(getPos(), "Unexpected EOF in JBIG2 stream");
-}
-
-JBIG2Bitmap *JBIG2Stream::readTextRegion(GBool huff, GBool refine,
- int w, int h,
- Guint numInstances,
- Guint logStrips,
- int numSyms,
- JBIG2HuffmanTable *symCodeTab,
- Guint symCodeLen,
- JBIG2Bitmap **syms,
- Guint defPixel, Guint combOp,
- Guint transposed, Guint refCorner,
- int sOffset,
- JBIG2HuffmanTable *huffFSTable,
- JBIG2HuffmanTable *huffDSTable,
- JBIG2HuffmanTable *huffDTTable,
- JBIG2HuffmanTable *huffRDWTable,
- JBIG2HuffmanTable *huffRDHTable,
- JBIG2HuffmanTable *huffRDXTable,
- JBIG2HuffmanTable *huffRDYTable,
- JBIG2HuffmanTable *huffRSizeTable,
- Guint templ,
- int *atx, int *aty) {
- JBIG2Bitmap *bitmap;
- JBIG2Bitmap *symbolBitmap;
- Guint strips;
- int t, dt, tt, s, ds, sFirst, j;
- int rdw, rdh, rdx, rdy, ri, refDX, refDY, bmSize;
- Guint symID, inst, bw, bh;
-
- strips = 1 << logStrips;
-
- // allocate the bitmap
- bitmap = new JBIG2Bitmap(0, w, h);
- if (defPixel) {
- bitmap->clearToOne();
- } else {
- bitmap->clearToZero();
- }
-
- // decode initial T value
- if (huff) {
- huffDecoder->decodeInt(&t, huffDTTable);
- } else {
- arithDecoder->decodeInt(&t, iadtStats);
- }
- t *= -(int)strips;
-
- inst = 0;
- sFirst = 0;
- while (inst < numInstances) {
-
- // decode delta-T
- if (huff) {
- huffDecoder->decodeInt(&dt, huffDTTable);
- } else {
- arithDecoder->decodeInt(&dt, iadtStats);
- }
- t += dt * strips;
-
- // first S value
- if (huff) {
- huffDecoder->decodeInt(&ds, huffFSTable);
- } else {
- arithDecoder->decodeInt(&ds, iafsStats);
- }
- sFirst += ds;
- s = sFirst;
-
- // read the instances
- while (1) {
-
- // T value
- if (strips == 1) {
- dt = 0;
- } else if (huff) {
- dt = huffDecoder->readBits(logStrips);
- } else {
- arithDecoder->decodeInt(&dt, iaitStats);
- }
- tt = t + dt;
-
- // symbol ID
- if (huff) {
- if (symCodeTab) {
- huffDecoder->decodeInt(&j, symCodeTab);
- symID = (Guint)j;
- } else {
- symID = huffDecoder->readBits(symCodeLen);
- }
- } else {
- symID = arithDecoder->decodeIAID(symCodeLen, iaidStats);
- }
-
- if (symID >= (Guint)numSyms) {
- error(getPos(), "Invalid symbol number in JBIG2 text region");
- } else {
-
- // get the symbol bitmap
- symbolBitmap = NULL;
- if (refine) {
- if (huff) {
- ri = (int)huffDecoder->readBit();
- } else {
- arithDecoder->decodeInt(&ri, iariStats);
- }
- } else {
- ri = 0;
- }
- if (ri) {
- if (huff) {
- huffDecoder->decodeInt(&rdw, huffRDWTable);
- huffDecoder->decodeInt(&rdh, huffRDHTable);
- huffDecoder->decodeInt(&rdx, huffRDXTable);
- huffDecoder->decodeInt(&rdy, huffRDYTable);
- huffDecoder->decodeInt(&bmSize, huffRSizeTable);
- huffDecoder->reset();
- arithDecoder->start();
- } else {
- arithDecoder->decodeInt(&rdw, iardwStats);
- arithDecoder->decodeInt(&rdh, iardhStats);
- arithDecoder->decodeInt(&rdx, iardxStats);
- arithDecoder->decodeInt(&rdy, iardyStats);
- }
- refDX = ((rdw >= 0) ? rdw : rdw - 1) / 2 + rdx;
- refDY = ((rdh >= 0) ? rdh : rdh - 1) / 2 + rdy;
-
- symbolBitmap =
- readGenericRefinementRegion(rdw + syms[symID]->getWidth(),
- rdh + syms[symID]->getHeight(),
- templ, gFalse, syms[symID],
- refDX, refDY, atx, aty);
- //~ do we need to use the bmSize value here (in Huffman mode)?
- } else {
- symbolBitmap = syms[symID];
- }
-
- // combine the symbol bitmap into the region bitmap
- //~ something is wrong here - refCorner shouldn't degenerate into
- //~ two cases
- bw = symbolBitmap->getWidth() - 1;
- bh = symbolBitmap->getHeight() - 1;
- if (transposed) {
- switch (refCorner) {
- case 0: // bottom left
- bitmap->combine(symbolBitmap, tt, s, combOp);
- break;
- case 1: // top left
- bitmap->combine(symbolBitmap, tt, s, combOp);
- break;
- case 2: // bottom right
- bitmap->combine(symbolBitmap, tt - bw, s, combOp);
- break;
- case 3: // top right
- bitmap->combine(symbolBitmap, tt - bw, s, combOp);
- break;
- }
- s += bh;
- } else {
- switch (refCorner) {
- case 0: // bottom left
- bitmap->combine(symbolBitmap, s, tt - bh, combOp);
- break;
- case 1: // top left
- bitmap->combine(symbolBitmap, s, tt, combOp);
- break;
- case 2: // bottom right
- bitmap->combine(symbolBitmap, s, tt - bh, combOp);
- break;
- case 3: // top right
- bitmap->combine(symbolBitmap, s, tt, combOp);
- break;
- }
- s += bw;
- }
- if (ri) {
- delete symbolBitmap;
- }
- }
-
- // next instance
- ++inst;
-
- // next S value
- if (huff) {
- if (!huffDecoder->decodeInt(&ds, huffDSTable)) {
- break;
- }
- } else {
- if (!arithDecoder->decodeInt(&ds, iadsStats)) {
- break;
- }
- }
- s += sOffset + ds;
- }
- }
-
- return bitmap;
-}
-
-void JBIG2Stream::readPatternDictSeg(Guint segNum, Guint length) {
- JBIG2PatternDict *patternDict;
- JBIG2Bitmap *bitmap;
- Guint flags, patternW, patternH, grayMax, templ, mmr;
- int atx[4], aty[4];
- Guint i, x;
-
- // halftone dictionary flags, pattern width and height, max gray value
- if (!readUByte(&flags) ||
- !readUByte(&patternW) ||
- !readUByte(&patternH) ||
- !readULong(&grayMax)) {
- goto eofError;
- }
- templ = (flags >> 1) & 3;
- mmr = flags & 1;
-
- // set up the arithmetic decoder
- if (!mmr) {
- resetGenericStats(templ, NULL);
- arithDecoder->start();
- }
-
- // read the bitmap
- atx[0] = -(int)patternW; aty[0] = 0;
- atx[1] = -3; aty[1] = -1;
- atx[2] = 2; aty[2] = -2;
- atx[3] = -2; aty[3] = -2;
- bitmap = readGenericBitmap(mmr, (grayMax + 1) * patternW, patternH,
- templ, gFalse, gFalse, NULL,
- atx, aty, length - 7);
-
- // create the pattern dict object
- patternDict = new JBIG2PatternDict(segNum, grayMax + 1);
-
- // split up the bitmap
- x = 0;
- for (i = 0; i <= grayMax; ++i) {
- patternDict->setBitmap(i, bitmap->getSlice(x, 0, patternW, patternH));
- x += patternW;
- }
-
- // free memory
- delete bitmap;
-
- // store the new pattern dict
- segments->append(patternDict);
-
- return;
-
- eofError:
- error(getPos(), "Unexpected EOF in JBIG2 stream");
-}
-
-void JBIG2Stream::readHalftoneRegionSeg(Guint segNum, GBool imm,
- GBool lossless, Guint length,
- Guint *refSegs, Guint nRefSegs) {
- JBIG2Bitmap *bitmap;
- JBIG2Segment *seg;
- JBIG2PatternDict *patternDict;
- JBIG2Bitmap *skipBitmap;
- Guint *grayImg;
- JBIG2Bitmap *grayBitmap;
- JBIG2Bitmap *patternBitmap;
- Guint w, h, x, y, segInfoFlags, extCombOp;
- Guint flags, mmr, templ, enableSkip, combOp;
- Guint gridW, gridH, stepX, stepY, patW, patH;
- int atx[4], aty[4];
- int gridX, gridY, xx, yy, bit, j;
- Guint bpp, m, n, i;
-
- // region segment info field
- if (!readULong(&w) || !readULong(&h) ||
- !readULong(&x) || !readULong(&y) ||
- !readUByte(&segInfoFlags)) {
- goto eofError;
- }
- extCombOp = segInfoFlags & 7;
-
- // rest of the halftone region header
- if (!readUByte(&flags)) {
- goto eofError;
- }
- mmr = flags & 1;
- templ = (flags >> 1) & 3;
- enableSkip = (flags >> 3) & 1;
- combOp = (flags >> 4) & 7;
- if (!readULong(&gridW) || !readULong(&gridH) ||
- !readLong(&gridX) || !readLong(&gridY) ||
- !readUWord(&stepX) || !readUWord(&stepY)) {
- goto eofError;
- }
-
- // get pattern dictionary
- if (nRefSegs != 1) {
- error(getPos(), "Bad symbol dictionary reference in JBIG2 halftone segment");
- return;
- }
- seg = findSegment(refSegs[0]);
- if (seg->getType() != jbig2SegPatternDict) {
- error(getPos(), "Bad symbol dictionary reference in JBIG2 halftone segment");
- return;
- }
- patternDict = (JBIG2PatternDict *)seg;
- bpp = 0;
- i = 1;
- while (i < patternDict->getSize()) {
- ++bpp;
- i <<= 1;
- }
- patW = patternDict->getBitmap(0)->getWidth();
- patH = patternDict->getBitmap(0)->getHeight();
-
- // set up the arithmetic decoder
- if (!mmr) {
- resetGenericStats(templ, NULL);
- arithDecoder->start();
- }
-
- // allocate the bitmap
- bitmap = new JBIG2Bitmap(segNum, w, h);
- if (flags & 0x80) { // HDEFPIXEL
- bitmap->clearToOne();
- } else {
- bitmap->clearToZero();
- }
-
- // compute the skip bitmap
- skipBitmap = NULL;
- if (enableSkip) {
- skipBitmap = new JBIG2Bitmap(0, gridW, gridH);
- skipBitmap->clearToZero();
- for (m = 0; m < gridH; ++m) {
- xx = gridX + m * stepY;
- yy = gridY + m * stepX;
- for (n = 0; n < gridW; ++n) {
- if (((xx + (int)patW) >> 8) <= 0 || (xx >> 8) >= (int)w ||
- ((yy + (int)patH) >> 8) <= 0 || (yy >> 8) >= (int)h) {
- skipBitmap->setPixel(n, m);
- }
- }
- }
- }
-
- // read the gray-scale image
- grayImg = (Guint *)gmallocn(gridW * gridH, sizeof(Guint));
- memset(grayImg, 0, gridW * gridH * sizeof(Guint));
- atx[0] = templ <= 1 ? 3 : 2; aty[0] = -1;
- atx[1] = -3; aty[1] = -1;
- atx[2] = 2; aty[2] = -2;
- atx[3] = -2; aty[3] = -2;
- for (j = bpp - 1; j >= 0; --j) {
- grayBitmap = readGenericBitmap(mmr, gridW, gridH, templ, gFalse,
- enableSkip, skipBitmap, atx, aty, -1);
- i = 0;
- for (m = 0; m < gridH; ++m) {
- for (n = 0; n < gridW; ++n) {
- bit = grayBitmap->getPixel(n, m) ^ (grayImg[i] & 1);
- grayImg[i] = (grayImg[i] << 1) | bit;
- ++i;
- }
- }
- delete grayBitmap;
- }
-
- // decode the image
- i = 0;
- for (m = 0; m < gridH; ++m) {
- xx = gridX + m * stepY;
- yy = gridY + m * stepX;
- for (n = 0; n < gridW; ++n) {
- if (!(enableSkip && skipBitmap->getPixel(n, m))) {
- patternBitmap = patternDict->getBitmap(grayImg[i]);
- bitmap->combine(patternBitmap, xx >> 8, yy >> 8, combOp);
- }
- xx += stepX;
- yy -= stepY;
- ++i;
- }
- }
-
- gfree(grayImg);
-
- // combine the region bitmap into the page bitmap
- if (imm) {
- if (pageH == 0xffffffff && y + h > curPageH) {
- pageBitmap->expand(y + h, pageDefPixel);
- }
- pageBitmap->combine(bitmap, x, y, extCombOp);
- delete bitmap;
-
- // store the region bitmap
- } else {
- segments->append(bitmap);
- }
-
- return;
-
- eofError:
- error(getPos(), "Unexpected EOF in JBIG2 stream");
-}
-
-void JBIG2Stream::readGenericRegionSeg(Guint segNum, GBool imm,
- GBool lossless, Guint length) {
- JBIG2Bitmap *bitmap;
- Guint w, h, x, y, segInfoFlags, extCombOp;
- Guint flags, mmr, templ, tpgdOn;
- int atx[4], aty[4];
-
- // region segment info field
- if (!readULong(&w) || !readULong(&h) ||
- !readULong(&x) || !readULong(&y) ||
- !readUByte(&segInfoFlags)) {
- goto eofError;
- }
- extCombOp = segInfoFlags & 7;
-
- // rest of the generic region segment header
- if (!readUByte(&flags)) {
- goto eofError;
- }
- mmr = flags & 1;
- templ = (flags >> 1) & 3;
- tpgdOn = (flags >> 3) & 1;
-
- // AT flags
- if (!mmr) {
- if (templ == 0) {
- if (!readByte(&atx[0]) ||
- !readByte(&aty[0]) ||
- !readByte(&atx[1]) ||
- !readByte(&aty[1]) ||
- !readByte(&atx[2]) ||
- !readByte(&aty[2]) ||
- !readByte(&atx[3]) ||
- !readByte(&aty[3])) {
- goto eofError;
- }
- } else {
- if (!readByte(&atx[0]) ||
- !readByte(&aty[0])) {
- goto eofError;
- }
- }
- }
-
- // set up the arithmetic decoder
- if (!mmr) {
- resetGenericStats(templ, NULL);
- arithDecoder->start();
- }
-
- // read the bitmap
- bitmap = readGenericBitmap(mmr, w, h, templ, tpgdOn, gFalse,
- NULL, atx, aty, mmr ? 0 : length - 18);
-
- // combine the region bitmap into the page bitmap
- if (imm) {
- if (pageH == 0xffffffff && y + h > curPageH) {
- pageBitmap->expand(y + h, pageDefPixel);
- }
- pageBitmap->combine(bitmap, x, y, extCombOp);
- delete bitmap;
-
- // store the region bitmap
- } else {
- bitmap->setSegNum(segNum);
- segments->append(bitmap);
- }
-
- return;
-
- eofError:
- error(getPos(), "Unexpected EOF in JBIG2 stream");
-}
-
-JBIG2Bitmap *JBIG2Stream::readGenericBitmap(GBool mmr, int w, int h,
- int templ, GBool tpgdOn,
- GBool useSkip, JBIG2Bitmap *skip,
- int *atx, int *aty,
- int mmrDataLength) {
- JBIG2Bitmap *bitmap;
- GBool ltp;
- Guint ltpCX, cx, cx0, cx1, cx2;
- JBIG2BitmapPtr cxPtr0, cxPtr1;
- JBIG2BitmapPtr atPtr0, atPtr1, atPtr2, atPtr3;
- int *refLine, *codingLine;
- int code1, code2, code3;
- int x, y, a0, pix, i, refI, codingI;
-
- bitmap = new JBIG2Bitmap(0, w, h);
- bitmap->clearToZero();
-
- //----- MMR decode
-
- if (mmr) {
-
- mmrDecoder->reset();
- refLine = (int *)gmallocn(w + 2, sizeof(int));
- codingLine = (int *)gmallocn(w + 2, sizeof(int));
- codingLine[0] = codingLine[1] = w;
-
- for (y = 0; y < h; ++y) {
-
- // copy coding line to ref line
- for (i = 0; codingLine[i] < w; ++i) {
- refLine[i] = codingLine[i];
- }
- refLine[i] = refLine[i + 1] = w;
-
- // decode a line
- refI = 0; // b1 = refLine[refI]
- codingI = 0; // a1 = codingLine[codingI]
- a0 = 0;
- do {
- code1 = mmrDecoder->get2DCode();
- switch (code1) {
- case twoDimPass:
- if (refLine[refI] < w) {
- a0 = refLine[refI + 1];
- refI += 2;
- }
- break;
- case twoDimHoriz:
- if (codingI & 1) {
- code1 = 0;
- do {
- code1 += code3 = mmrDecoder->getBlackCode();
- } while (code3 >= 64);
- code2 = 0;
- do {
- code2 += code3 = mmrDecoder->getWhiteCode();
- } while (code3 >= 64);
- } else {
- code1 = 0;
- do {
- code1 += code3 = mmrDecoder->getWhiteCode();
- } while (code3 >= 64);
- code2 = 0;
- do {
- code2 += code3 = mmrDecoder->getBlackCode();
- } while (code3 >= 64);
- }
- if (code1 > 0 || code2 > 0) {
- a0 = codingLine[codingI++] = a0 + code1;
- a0 = codingLine[codingI++] = a0 + code2;
- while (refLine[refI] <= a0 && refLine[refI] < w) {
- refI += 2;
- }
- }
- break;
- case twoDimVert0:
- a0 = codingLine[codingI++] = refLine[refI];
- if (refLine[refI] < w) {
- ++refI;
- }
- break;
- case twoDimVertR1:
- a0 = codingLine[codingI++] = refLine[refI] + 1;
- if (refLine[refI] < w) {
- ++refI;
- while (refLine[refI] <= a0 && refLine[refI] < w) {
- refI += 2;
- }
- }
- break;
- case twoDimVertR2:
- a0 = codingLine[codingI++] = refLine[refI] + 2;
- if (refLine[refI] < w) {
- ++refI;
- while (refLine[refI] <= a0 && refLine[refI] < w) {
- refI += 2;
- }
- }
- break;
- case twoDimVertR3:
- a0 = codingLine[codingI++] = refLine[refI] + 3;
- if (refLine[refI] < w) {
- ++refI;
- while (refLine[refI] <= a0 && refLine[refI] < w) {
- refI += 2;
- }
- }
- break;
- case twoDimVertL1:
- a0 = codingLine[codingI++] = refLine[refI] - 1;
- if (refI > 0) {
- --refI;
- } else {
- ++refI;
- }
- while (refLine[refI] <= a0 && refLine[refI] < w) {
- refI += 2;
- }
- break;
- case twoDimVertL2:
- a0 = codingLine[codingI++] = refLine[refI] - 2;
- if (refI > 0) {
- --refI;
- } else {
- ++refI;
- }
- while (refLine[refI] <= a0 && refLine[refI] < w) {
- refI += 2;
- }
- break;
- case twoDimVertL3:
- a0 = codingLine[codingI++] = refLine[refI] - 3;
- if (refI > 0) {
- --refI;
- } else {
- ++refI;
- }
- while (refLine[refI] <= a0 && refLine[refI] < w) {
- refI += 2;
- }
- break;
- default:
- error(getPos(), "Illegal code in JBIG2 MMR bitmap data");
- break;
- }
- } while (a0 < w);
- codingLine[codingI++] = w;
-
- // convert the run lengths to a bitmap line
- i = 0;
- while (codingLine[i] < w) {
- for (x = codingLine[i]; x < codingLine[i+1]; ++x) {
- bitmap->setPixel(x, y);
- }
- i += 2;
- }
- }
-
- if (mmrDataLength >= 0) {
- mmrDecoder->skipTo(mmrDataLength);
- } else {
- if (mmrDecoder->get24Bits() != 0x001001) {
- error(getPos(), "Missing EOFB in JBIG2 MMR bitmap data");
- }
- }
-
- gfree(refLine);
- gfree(codingLine);
-
- //----- arithmetic decode
-
- } else {
- // set up the typical row context
- ltpCX = 0; // make gcc happy
- if (tpgdOn) {
- switch (templ) {
- case 0:
- ltpCX = 0x3953; // 001 11001 0101 0011
- break;
- case 1:
- ltpCX = 0x079a; // 0011 11001 101 0
- break;
- case 2:
- ltpCX = 0x0e3; // 001 1100 01 1
- break;
- case 3:
- ltpCX = 0x18a; // 01100 0101 1
- break;
- }
- }
-
- ltp = 0;
- cx = cx0 = cx1 = cx2 = 0; // make gcc happy
- for (y = 0; y < h; ++y) {
-
- // check for a "typical" (duplicate) row
- if (tpgdOn) {
- if (arithDecoder->decodeBit(ltpCX, genericRegionStats)) {
- ltp = !ltp;
- }
- if (ltp) {
- bitmap->duplicateRow(y, y-1);
- continue;
- }
- }
-
- switch (templ) {
- case 0:
-
- // set up the context
- bitmap->getPixelPtr(0, y-2, &cxPtr0);
- cx0 = bitmap->nextPixel(&cxPtr0);
- cx0 = (cx0 << 1) | bitmap->nextPixel(&cxPtr0);
- bitmap->getPixelPtr(0, y-1, &cxPtr1);
- cx1 = bitmap->nextPixel(&cxPtr1);
- cx1 = (cx1 << 1) | bitmap->nextPixel(&cxPtr1);
- cx1 = (cx1 << 1) | bitmap->nextPixel(&cxPtr1);
- cx2 = 0;
- bitmap->getPixelPtr(atx[0], y + aty[0], &atPtr0);
- bitmap->getPixelPtr(atx[1], y + aty[1], &atPtr1);
- bitmap->getPixelPtr(atx[2], y + aty[2], &atPtr2);
- bitmap->getPixelPtr(atx[3], y + aty[3], &atPtr3);
-
- // decode the row
- for (x = 0; x < w; ++x) {
-
- // build the context
- cx = (cx0 << 13) | (cx1 << 8) | (cx2 << 4) |
- (bitmap->nextPixel(&atPtr0) << 3) |
- (bitmap->nextPixel(&atPtr1) << 2) |
- (bitmap->nextPixel(&atPtr2) << 1) |
- bitmap->nextPixel(&atPtr3);
-
- // check for a skipped pixel
- if (useSkip && skip->getPixel(x, y)) {
- pix = 0;
-
- // decode the pixel
- } else if ((pix = arithDecoder->decodeBit(cx, genericRegionStats))) {
- bitmap->setPixel(x, y);
- }
-
- // update the context
- cx0 = ((cx0 << 1) | bitmap->nextPixel(&cxPtr0)) & 0x07;
- cx1 = ((cx1 << 1) | bitmap->nextPixel(&cxPtr1)) & 0x1f;
- cx2 = ((cx2 << 1) | pix) & 0x0f;
- }
- break;
-
- case 1:
-
- // set up the context
- bitmap->getPixelPtr(0, y-2, &cxPtr0);
- cx0 = bitmap->nextPixel(&cxPtr0);
- cx0 = (cx0 << 1) | bitmap->nextPixel(&cxPtr0);
- cx0 = (cx0 << 1) | bitmap->nextPixel(&cxPtr0);
- bitmap->getPixelPtr(0, y-1, &cxPtr1);
- cx1 = bitmap->nextPixel(&cxPtr1);
- cx1 = (cx1 << 1) | bitmap->nextPixel(&cxPtr1);
- cx1 = (cx1 << 1) | bitmap->nextPixel(&cxPtr1);
- cx2 = 0;
- bitmap->getPixelPtr(atx[0], y + aty[0], &atPtr0);
-
- // decode the row
- for (x = 0; x < w; ++x) {
-
- // build the context
- cx = (cx0 << 9) | (cx1 << 4) | (cx2 << 1) |
- bitmap->nextPixel(&atPtr0);
-
- // check for a skipped pixel
- if (useSkip && skip->getPixel(x, y)) {
- pix = 0;
-
- // decode the pixel
- } else if ((pix = arithDecoder->decodeBit(cx, genericRegionStats))) {
- bitmap->setPixel(x, y);
- }
-
- // update the context
- cx0 = ((cx0 << 1) | bitmap->nextPixel(&cxPtr0)) & 0x0f;
- cx1 = ((cx1 << 1) | bitmap->nextPixel(&cxPtr1)) & 0x1f;
- cx2 = ((cx2 << 1) | pix) & 0x07;
- }
- break;
-
- case 2:
-
- // set up the context
- bitmap->getPixelPtr(0, y-2, &cxPtr0);
- cx0 = bitmap->nextPixel(&cxPtr0);
- cx0 = (cx0 << 1) | bitmap->nextPixel(&cxPtr0);
- bitmap->getPixelPtr(0, y-1, &cxPtr1);
- cx1 = bitmap->nextPixel(&cxPtr1);
- cx1 = (cx1 << 1) | bitmap->nextPixel(&cxPtr1);
- cx2 = 0;
- bitmap->getPixelPtr(atx[0], y + aty[0], &atPtr0);
-
- // decode the row
- for (x = 0; x < w; ++x) {
-
- // build the context
- cx = (cx0 << 7) | (cx1 << 3) | (cx2 << 1) |
- bitmap->nextPixel(&atPtr0);
-
- // check for a skipped pixel
- if (useSkip && skip->getPixel(x, y)) {
- pix = 0;
-
- // decode the pixel
- } else if ((pix = arithDecoder->decodeBit(cx, genericRegionStats))) {
- bitmap->setPixel(x, y);
- }
-
- // update the context
- cx0 = ((cx0 << 1) | bitmap->nextPixel(&cxPtr0)) & 0x07;
- cx1 = ((cx1 << 1) | bitmap->nextPixel(&cxPtr1)) & 0x0f;
- cx2 = ((cx2 << 1) | pix) & 0x03;
- }
- break;
-
- case 3:
-
- // set up the context
- bitmap->getPixelPtr(0, y-1, &cxPtr1);
- cx1 = bitmap->nextPixel(&cxPtr1);
- cx1 = (cx1 << 1) | bitmap->nextPixel(&cxPtr1);
- cx2 = 0;
- bitmap->getPixelPtr(atx[0], y + aty[0], &atPtr0);
-
- // decode the row
- for (x = 0; x < w; ++x) {
-
- // build the context
- cx = (cx1 << 5) | (cx2 << 1) |
- bitmap->nextPixel(&atPtr0);
-
- // check for a skipped pixel
- if (useSkip && skip->getPixel(x, y)) {
- pix = 0;
-
- // decode the pixel
- } else if ((pix = arithDecoder->decodeBit(cx, genericRegionStats))) {
- bitmap->setPixel(x, y);
- }
-
- // update the context
- cx1 = ((cx1 << 1) | bitmap->nextPixel(&cxPtr1)) & 0x1f;
- cx2 = ((cx2 << 1) | pix) & 0x0f;
- }
- break;
- }
- }
- }
-
- return bitmap;
-}
-
-void JBIG2Stream::readGenericRefinementRegionSeg(Guint segNum, GBool imm,
- GBool lossless, Guint length,
- Guint *refSegs,
- Guint nRefSegs) {
- JBIG2Bitmap *bitmap, *refBitmap;
- Guint w, h, x, y, segInfoFlags, extCombOp;
- Guint flags, templ, tpgrOn;
- int atx[2], aty[2];
- JBIG2Segment *seg;
-
- // region segment info field
- if (!readULong(&w) || !readULong(&h) ||
- !readULong(&x) || !readULong(&y) ||
- !readUByte(&segInfoFlags)) {
- goto eofError;
- }
- extCombOp = segInfoFlags & 7;
-
- // rest of the generic refinement region segment header
- if (!readUByte(&flags)) {
- goto eofError;
- }
- templ = flags & 1;
- tpgrOn = (flags >> 1) & 1;
-
- // AT flags
- if (!templ) {
- if (!readByte(&atx[0]) || !readByte(&aty[0]) ||
- !readByte(&atx[1]) || !readByte(&aty[1])) {
- goto eofError;
- }
- }
-
- // resize the page bitmap if needed
- if (nRefSegs == 0 || imm) {
- if (pageH == 0xffffffff && y + h > curPageH) {
- pageBitmap->expand(y + h, pageDefPixel);
- }
- }
-
- // get referenced bitmap
- if (nRefSegs > 1) {
- error(getPos(), "Bad reference in JBIG2 generic refinement segment");
- return;
- }
- if (nRefSegs == 1) {
- seg = findSegment(refSegs[0]);
- if (seg->getType() != jbig2SegBitmap) {
- error(getPos(), "Bad bitmap reference in JBIG2 generic refinement segment");
- return;
- }
- refBitmap = (JBIG2Bitmap *)seg;
- } else {
- refBitmap = pageBitmap->getSlice(x, y, w, h);
- }
-
- // set up the arithmetic decoder
- resetRefinementStats(templ, NULL);
- arithDecoder->start();
-
- // read
- bitmap = readGenericRefinementRegion(w, h, templ, tpgrOn,
- refBitmap, 0, 0, atx, aty);
-
- // combine the region bitmap into the page bitmap
- if (imm) {
- pageBitmap->combine(bitmap, x, y, extCombOp);
- delete bitmap;
-
- // store the region bitmap
- } else {
- bitmap->setSegNum(segNum);
- segments->append(bitmap);
- }
-
- // delete the referenced bitmap
- if (nRefSegs == 1) {
- discardSegment(refSegs[0]);
- } else {
- delete refBitmap;
- }
-
- return;
-
- eofError:
- error(getPos(), "Unexpected EOF in JBIG2 stream");
-}
-
-JBIG2Bitmap *JBIG2Stream::readGenericRefinementRegion(int w, int h,
- int templ, GBool tpgrOn,
- JBIG2Bitmap *refBitmap,
- int refDX, int refDY,
- int *atx, int *aty) {
- JBIG2Bitmap *bitmap;
- GBool ltp;
- Guint ltpCX, cx, cx0, cx2, cx3, cx4, tpgrCX0, tpgrCX1, tpgrCX2;
- JBIG2BitmapPtr cxPtr0, cxPtr1, cxPtr2, cxPtr3, cxPtr4, cxPtr5, cxPtr6;
- JBIG2BitmapPtr tpgrCXPtr0, tpgrCXPtr1, tpgrCXPtr2;
- int x, y, pix;
-
- bitmap = new JBIG2Bitmap(0, w, h);
- bitmap->clearToZero();
-
- // set up the typical row context
- if (templ) {
- ltpCX = 0x008;
- } else {
- ltpCX = 0x0010;
- }
-
- ltp = 0;
- for (y = 0; y < h; ++y) {
-
- if (templ) {
-
- // set up the context
- bitmap->getPixelPtr(0, y-1, &cxPtr0);
- cx0 = bitmap->nextPixel(&cxPtr0);
- bitmap->getPixelPtr(-1, y, &cxPtr1);
- refBitmap->getPixelPtr(-refDX, y-1-refDY, &cxPtr2);
- refBitmap->getPixelPtr(-1-refDX, y-refDY, &cxPtr3);
- cx3 = refBitmap->nextPixel(&cxPtr3);
- cx3 = (cx3 << 1) | refBitmap->nextPixel(&cxPtr3);
- refBitmap->getPixelPtr(-refDX, y+1-refDY, &cxPtr4);
- cx4 = refBitmap->nextPixel(&cxPtr4);
-
- // set up the typical prediction context
- tpgrCX0 = tpgrCX1 = tpgrCX2 = 0; // make gcc happy
- if (tpgrOn) {
- refBitmap->getPixelPtr(-1-refDX, y-1-refDY, &tpgrCXPtr0);
- tpgrCX0 = refBitmap->nextPixel(&tpgrCXPtr0);
- tpgrCX0 = (tpgrCX0 << 1) | refBitmap->nextPixel(&tpgrCXPtr0);
- tpgrCX0 = (tpgrCX0 << 1) | refBitmap->nextPixel(&tpgrCXPtr0);
- refBitmap->getPixelPtr(-1-refDX, y-refDY, &tpgrCXPtr1);
- tpgrCX1 = refBitmap->nextPixel(&tpgrCXPtr1);
- tpgrCX1 = (tpgrCX1 << 1) | refBitmap->nextPixel(&tpgrCXPtr1);
- tpgrCX1 = (tpgrCX1 << 1) | refBitmap->nextPixel(&tpgrCXPtr1);
- refBitmap->getPixelPtr(-1-refDX, y+1-refDY, &tpgrCXPtr2);
- tpgrCX2 = refBitmap->nextPixel(&tpgrCXPtr2);
- tpgrCX2 = (tpgrCX2 << 1) | refBitmap->nextPixel(&tpgrCXPtr2);
- tpgrCX2 = (tpgrCX2 << 1) | refBitmap->nextPixel(&tpgrCXPtr2);
- }
-
- for (x = 0; x < w; ++x) {
-
- // update the context
- cx0 = ((cx0 << 1) | bitmap->nextPixel(&cxPtr0)) & 7;
- cx3 = ((cx3 << 1) | refBitmap->nextPixel(&cxPtr3)) & 7;
- cx4 = ((cx4 << 1) | refBitmap->nextPixel(&cxPtr4)) & 3;
-
- if (tpgrOn) {
- // update the typical predictor context
- tpgrCX0 = ((tpgrCX0 << 1) | refBitmap->nextPixel(&tpgrCXPtr0)) & 7;
- tpgrCX1 = ((tpgrCX1 << 1) | refBitmap->nextPixel(&tpgrCXPtr1)) & 7;
- tpgrCX2 = ((tpgrCX2 << 1) | refBitmap->nextPixel(&tpgrCXPtr2)) & 7;
-
- // check for a "typical" pixel
- if (arithDecoder->decodeBit(ltpCX, refinementRegionStats)) {
- ltp = !ltp;
- }
- if (tpgrCX0 == 0 && tpgrCX1 == 0 && tpgrCX2 == 0) {
- bitmap->clearPixel(x, y);
- continue;
- } else if (tpgrCX0 == 7 && tpgrCX1 == 7 && tpgrCX2 == 7) {
- bitmap->setPixel(x, y);
- continue;
- }
- }
-
- // build the context
- cx = (cx0 << 7) | (bitmap->nextPixel(&cxPtr1) << 6) |
- (refBitmap->nextPixel(&cxPtr2) << 5) |
- (cx3 << 2) | cx4;
-
- // decode the pixel
- if ((pix = arithDecoder->decodeBit(cx, refinementRegionStats))) {
- bitmap->setPixel(x, y);
- }
- }
-
- } else {
-
- // set up the context
- bitmap->getPixelPtr(0, y-1, &cxPtr0);
- cx0 = bitmap->nextPixel(&cxPtr0);
- bitmap->getPixelPtr(-1, y, &cxPtr1);
- refBitmap->getPixelPtr(-refDX, y-1-refDY, &cxPtr2);
- cx2 = refBitmap->nextPixel(&cxPtr2);
- refBitmap->getPixelPtr(-1-refDX, y-refDY, &cxPtr3);
- cx3 = refBitmap->nextPixel(&cxPtr3);
- cx3 = (cx3 << 1) | refBitmap->nextPixel(&cxPtr3);
- refBitmap->getPixelPtr(-1-refDX, y+1-refDY, &cxPtr4);
- cx4 = refBitmap->nextPixel(&cxPtr4);
- cx4 = (cx4 << 1) | refBitmap->nextPixel(&cxPtr4);
- bitmap->getPixelPtr(atx[0], y+aty[0], &cxPtr5);
- refBitmap->getPixelPtr(atx[1]-refDX, y+aty[1]-refDY, &cxPtr6);
-
- // set up the typical prediction context
- tpgrCX0 = tpgrCX1 = tpgrCX2 = 0; // make gcc happy
- if (tpgrOn) {
- refBitmap->getPixelPtr(-1-refDX, y-1-refDY, &tpgrCXPtr0);
- tpgrCX0 = refBitmap->nextPixel(&tpgrCXPtr0);
- tpgrCX0 = (tpgrCX0 << 1) | refBitmap->nextPixel(&tpgrCXPtr0);
- tpgrCX0 = (tpgrCX0 << 1) | refBitmap->nextPixel(&tpgrCXPtr0);
- refBitmap->getPixelPtr(-1-refDX, y-refDY, &tpgrCXPtr1);
- tpgrCX1 = refBitmap->nextPixel(&tpgrCXPtr1);
- tpgrCX1 = (tpgrCX1 << 1) | refBitmap->nextPixel(&tpgrCXPtr1);
- tpgrCX1 = (tpgrCX1 << 1) | refBitmap->nextPixel(&tpgrCXPtr1);
- refBitmap->getPixelPtr(-1-refDX, y+1-refDY, &tpgrCXPtr2);
- tpgrCX2 = refBitmap->nextPixel(&tpgrCXPtr2);
- tpgrCX2 = (tpgrCX2 << 1) | refBitmap->nextPixel(&tpgrCXPtr2);
- tpgrCX2 = (tpgrCX2 << 1) | refBitmap->nextPixel(&tpgrCXPtr2);
- }
-
- for (x = 0; x < w; ++x) {
-
- // update the context
- cx0 = ((cx0 << 1) | bitmap->nextPixel(&cxPtr0)) & 3;
- cx2 = ((cx2 << 1) | refBitmap->nextPixel(&cxPtr2)) & 3;
- cx3 = ((cx3 << 1) | refBitmap->nextPixel(&cxPtr3)) & 7;
- cx4 = ((cx4 << 1) | refBitmap->nextPixel(&cxPtr4)) & 7;
-
- if (tpgrOn) {
- // update the typical predictor context
- tpgrCX0 = ((tpgrCX0 << 1) | refBitmap->nextPixel(&tpgrCXPtr0)) & 7;
- tpgrCX1 = ((tpgrCX1 << 1) | refBitmap->nextPixel(&tpgrCXPtr1)) & 7;
- tpgrCX2 = ((tpgrCX2 << 1) | refBitmap->nextPixel(&tpgrCXPtr2)) & 7;
-
- // check for a "typical" pixel
- if (arithDecoder->decodeBit(ltpCX, refinementRegionStats)) {
- ltp = !ltp;
- }
- if (tpgrCX0 == 0 && tpgrCX1 == 0 && tpgrCX2 == 0) {
- bitmap->clearPixel(x, y);
- continue;
- } else if (tpgrCX0 == 7 && tpgrCX1 == 7 && tpgrCX2 == 7) {
- bitmap->setPixel(x, y);
- continue;
- }
- }
-
- // build the context
- cx = (cx0 << 11) | (bitmap->nextPixel(&cxPtr1) << 10) |
- (cx2 << 8) | (cx3 << 5) | (cx4 << 2) |
- (bitmap->nextPixel(&cxPtr5) << 1) |
- refBitmap->nextPixel(&cxPtr6);
-
- // decode the pixel
- if ((pix = arithDecoder->decodeBit(cx, refinementRegionStats))) {
- bitmap->setPixel(x, y);
- }
- }
- }
- }
-
- return bitmap;
-}
-
-void JBIG2Stream::readPageInfoSeg(Guint length) {
- Guint xRes, yRes, flags, striping;
-
- if (!readULong(&pageW) || !readULong(&pageH) ||
- !readULong(&xRes) || !readULong(&yRes) ||
- !readUByte(&flags) || !readUWord(&striping)) {
- goto eofError;
- }
- pageDefPixel = (flags >> 2) & 1;
- defCombOp = (flags >> 3) & 3;
-
- // allocate the page bitmap
- if (pageH == 0xffffffff) {
- curPageH = striping & 0x7fff;
- } else {
- curPageH = pageH;
- }
- pageBitmap = new JBIG2Bitmap(0, pageW, curPageH);
-
- // default pixel value
- if (pageDefPixel) {
- pageBitmap->clearToOne();
- } else {
- pageBitmap->clearToZero();
- }
-
- return;
-
- eofError:
- error(getPos(), "Unexpected EOF in JBIG2 stream");
-}
-
-void JBIG2Stream::readEndOfStripeSeg(Guint length) {
- Guint i;
-
- // skip the segment
- for (i = 0; i < length; ++i) {
- curStr->getChar();
- }
-}
-
-void JBIG2Stream::readProfilesSeg(Guint length) {
- Guint i;
-
- // skip the segment
- for (i = 0; i < length; ++i) {
- curStr->getChar();
- }
-}
-
-void JBIG2Stream::readCodeTableSeg(Guint segNum, Guint length) {
- JBIG2HuffmanTable *huffTab;
- Guint flags, oob, prefixBits, rangeBits;
- int lowVal, highVal, val;
- Guint huffTabSize, i;
-
- if (!readUByte(&flags) || !readLong(&lowVal) || !readLong(&highVal)) {
- goto eofError;
- }
- oob = flags & 1;
- prefixBits = ((flags >> 1) & 7) + 1;
- rangeBits = ((flags >> 4) & 7) + 1;
-
- huffDecoder->reset();
- huffTabSize = 8;
- huffTab = (JBIG2HuffmanTable *)
- gmallocn(huffTabSize, sizeof(JBIG2HuffmanTable));
- i = 0;
- val = lowVal;
- while (val < highVal) {
- if (i == huffTabSize) {
- huffTabSize *= 2;
- huffTab = (JBIG2HuffmanTable *)
- greallocn(huffTab, huffTabSize, sizeof(JBIG2HuffmanTable));
- }
- huffTab[i].val = val;
- huffTab[i].prefixLen = huffDecoder->readBits(prefixBits);
- huffTab[i].rangeLen = huffDecoder->readBits(rangeBits);
- val += 1 << huffTab[i].rangeLen;
- ++i;
- }
- if (i + oob + 3 > huffTabSize) {
- huffTabSize = i + oob + 3;
- huffTab = (JBIG2HuffmanTable *)
- greallocn(huffTab, huffTabSize, sizeof(JBIG2HuffmanTable));
- }
- huffTab[i].val = lowVal - 1;
- huffTab[i].prefixLen = huffDecoder->readBits(prefixBits);
- huffTab[i].rangeLen = jbig2HuffmanLOW;
- ++i;
- huffTab[i].val = highVal;
- huffTab[i].prefixLen = huffDecoder->readBits(prefixBits);
- huffTab[i].rangeLen = 32;
- ++i;
- if (oob) {
- huffTab[i].val = 0;
- huffTab[i].prefixLen = huffDecoder->readBits(prefixBits);
- huffTab[i].rangeLen = jbig2HuffmanOOB;
- ++i;
- }
- huffTab[i].val = 0;
- huffTab[i].prefixLen = 0;
- huffTab[i].rangeLen = jbig2HuffmanEOT;
- huffDecoder->buildTable(huffTab, i);
-
- // create and store the new table segment
- segments->append(new JBIG2CodeTable(segNum, huffTab));
-
- return;
-
- eofError:
- error(getPos(), "Unexpected EOF in JBIG2 stream");
-}
-
-void JBIG2Stream::readExtensionSeg(Guint length) {
- Guint i;
-
- // skip the segment
- for (i = 0; i < length; ++i) {
- curStr->getChar();
- }
-}
-
-JBIG2Segment *JBIG2Stream::findSegment(Guint segNum) {
- JBIG2Segment *seg;
- int i;
-
- for (i = 0; i < globalSegments->getLength(); ++i) {
- seg = (JBIG2Segment *)globalSegments->get(i);
- if (seg->getSegNum() == segNum) {
- return seg;
- }
- }
- for (i = 0; i < segments->getLength(); ++i) {
- seg = (JBIG2Segment *)segments->get(i);
- if (seg->getSegNum() == segNum) {
- return seg;
- }
- }
- return NULL;
-}
-
-void JBIG2Stream::discardSegment(Guint segNum) {
- JBIG2Segment *seg;
- int i;
-
- for (i = 0; i < globalSegments->getLength(); ++i) {
- seg = (JBIG2Segment *)globalSegments->get(i);
- if (seg->getSegNum() == segNum) {
- globalSegments->del(i);
- return;
- }
- }
- for (i = 0; i < segments->getLength(); ++i) {
- seg = (JBIG2Segment *)segments->get(i);
- if (seg->getSegNum() == segNum) {
- segments->del(i);
- return;
- }
- }
-}
-
-void JBIG2Stream::resetGenericStats(Guint templ,
- JArithmeticDecoderStats *prevStats) {
- int size;
-
- size = contextSize[templ];
- if (prevStats && prevStats->getContextSize() == size) {
- if (genericRegionStats->getContextSize() == size) {
- genericRegionStats->copyFrom(prevStats);
- } else {
- delete genericRegionStats;
- genericRegionStats = prevStats->copy();
- }
- } else {
- if (genericRegionStats->getContextSize() == size) {
- genericRegionStats->reset();
- } else {
- delete genericRegionStats;
- genericRegionStats = new JArithmeticDecoderStats(1 << size);
- }
- }
-}
-
-void JBIG2Stream::resetRefinementStats(Guint templ,
- JArithmeticDecoderStats *prevStats) {
- int size;
-
- size = refContextSize[templ];
- if (prevStats && prevStats->getContextSize() == size) {
- if (refinementRegionStats->getContextSize() == size) {
- refinementRegionStats->copyFrom(prevStats);
- } else {
- delete refinementRegionStats;
- refinementRegionStats = prevStats->copy();
- }
- } else {
- if (refinementRegionStats->getContextSize() == size) {
- refinementRegionStats->reset();
- } else {
- delete refinementRegionStats;
- refinementRegionStats = new JArithmeticDecoderStats(1 << size);
- }
- }
-}
-
-void JBIG2Stream::resetIntStats(int symCodeLen) {
- iadhStats->reset();
- iadwStats->reset();
- iaexStats->reset();
- iaaiStats->reset();
- iadtStats->reset();
- iaitStats->reset();
- iafsStats->reset();
- iadsStats->reset();
- iardxStats->reset();
- iardyStats->reset();
- iardwStats->reset();
- iardhStats->reset();
- iariStats->reset();
- if (iaidStats->getContextSize() == symCodeLen + 1) {
- iaidStats->reset();
- } else {
- delete iaidStats;
- iaidStats = new JArithmeticDecoderStats(1 << (symCodeLen + 1));
- }
-}
-
-GBool JBIG2Stream::readUByte(Guint *x) {
- int c0;
-
- if ((c0 = curStr->getChar()) == EOF) {
- return gFalse;
- }
- *x = (Guint)c0;
- return gTrue;
-}
-
-GBool JBIG2Stream::readByte(int *x) {
- int c0;
-
- if ((c0 = curStr->getChar()) == EOF) {
- return gFalse;
- }
- *x = c0;
- if (c0 & 0x80) {
- *x |= -1 - 0xff;
- }
- return gTrue;
-}
-
-GBool JBIG2Stream::readUWord(Guint *x) {
- int c0, c1;
-
- if ((c0 = curStr->getChar()) == EOF ||
- (c1 = curStr->getChar()) == EOF) {
- return gFalse;
- }
- *x = (Guint)((c0 << 8) | c1);
- return gTrue;
-}
-
-GBool JBIG2Stream::readULong(Guint *x) {
- int c0, c1, c2, c3;
-
- if ((c0 = curStr->getChar()) == EOF ||
- (c1 = curStr->getChar()) == EOF ||
- (c2 = curStr->getChar()) == EOF ||
- (c3 = curStr->getChar()) == EOF) {
- return gFalse;
- }
- *x = (Guint)((c0 << 24) | (c1 << 16) | (c2 << 8) | c3);
- return gTrue;
-}
-
-GBool JBIG2Stream::readLong(int *x) {
- int c0, c1, c2, c3;
-
- if ((c0 = curStr->getChar()) == EOF ||
- (c1 = curStr->getChar()) == EOF ||
- (c2 = curStr->getChar()) == EOF ||
- (c3 = curStr->getChar()) == EOF) {
- return gFalse;
- }
- *x = ((c0 << 24) | (c1 << 16) | (c2 << 8) | c3);
- if (c0 & 0x80) {
- *x |= -1 - (int)0xffffffff;
- }
- return gTrue;
-}
+++ /dev/null
-//========================================================================
-//
-// JBIG2Stream.h
-//
-// Copyright 2002-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#ifndef JBIG2STREAM_H
-#define JBIG2STREAM_H
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma interface
-#endif
-
-#include "gtypes.h"
-#include "Object.h"
-#include "Stream.h"
-
-class GList;
-class JBIG2Segment;
-class JBIG2Bitmap;
-class JArithmeticDecoder;
-class JArithmeticDecoderStats;
-class JBIG2HuffmanDecoder;
-struct JBIG2HuffmanTable;
-class JBIG2MMRDecoder;
-
-//------------------------------------------------------------------------
-
-class JBIG2Stream: public FilterStream {
-public:
-
- JBIG2Stream(Stream *strA, Object *globalsStream);
- virtual ~JBIG2Stream();
- virtual StreamKind getKind() { return strJBIG2; }
- virtual void reset();
- virtual int getChar();
- virtual int lookChar();
- virtual GString *getPSFilter(int psLevel, char *indent);
- virtual GBool isBinary(GBool last = gTrue);
-
-private:
-
- void readSegments();
- GBool readSymbolDictSeg(Guint segNum, Guint length,
- Guint *refSegs, Guint nRefSegs);
- void readTextRegionSeg(Guint segNum, GBool imm,
- GBool lossless, Guint length,
- Guint *refSegs, Guint nRefSegs);
- JBIG2Bitmap *readTextRegion(GBool huff, GBool refine,
- int w, int h,
- Guint numInstances,
- Guint logStrips,
- int numSyms,
- JBIG2HuffmanTable *symCodeTab,
- Guint symCodeLen,
- JBIG2Bitmap **syms,
- Guint defPixel, Guint combOp,
- Guint transposed, Guint refCorner,
- int sOffset,
- JBIG2HuffmanTable *huffFSTable,
- JBIG2HuffmanTable *huffDSTable,
- JBIG2HuffmanTable *huffDTTable,
- JBIG2HuffmanTable *huffRDWTable,
- JBIG2HuffmanTable *huffRDHTable,
- JBIG2HuffmanTable *huffRDXTable,
- JBIG2HuffmanTable *huffRDYTable,
- JBIG2HuffmanTable *huffRSizeTable,
- Guint templ,
- int *atx, int *aty);
- void readPatternDictSeg(Guint segNum, Guint length);
- void readHalftoneRegionSeg(Guint segNum, GBool imm,
- GBool lossless, Guint length,
- Guint *refSegs, Guint nRefSegs);
- void readGenericRegionSeg(Guint segNum, GBool imm,
- GBool lossless, Guint length);
- JBIG2Bitmap *readGenericBitmap(GBool mmr, int w, int h,
- int templ, GBool tpgdOn,
- GBool useSkip, JBIG2Bitmap *skip,
- int *atx, int *aty,
- int mmrDataLength);
- void readGenericRefinementRegionSeg(Guint segNum, GBool imm,
- GBool lossless, Guint length,
- Guint *refSegs,
- Guint nRefSegs);
- JBIG2Bitmap *readGenericRefinementRegion(int w, int h,
- int templ, GBool tpgrOn,
- JBIG2Bitmap *refBitmap,
- int refDX, int refDY,
- int *atx, int *aty);
- void readPageInfoSeg(Guint length);
- void readEndOfStripeSeg(Guint length);
- void readProfilesSeg(Guint length);
- void readCodeTableSeg(Guint segNum, Guint length);
- void readExtensionSeg(Guint length);
- JBIG2Segment *findSegment(Guint segNum);
- void discardSegment(Guint segNum);
- void resetGenericStats(Guint templ,
- JArithmeticDecoderStats *prevStats);
- void resetRefinementStats(Guint templ,
- JArithmeticDecoderStats *prevStats);
- void resetIntStats(int symCodeLen);
- GBool readUByte(Guint *x);
- GBool readByte(int *x);
- GBool readUWord(Guint *x);
- GBool readULong(Guint *x);
- GBool readLong(int *x);
-
- Guint pageW, pageH, curPageH;
- Guint pageDefPixel;
- JBIG2Bitmap *pageBitmap;
- Guint defCombOp;
- GList *segments; // [JBIG2Segment]
- GList *globalSegments; // [JBIG2Segment]
- Stream *curStr;
- Guchar *dataPtr;
- Guchar *dataEnd;
-
- JArithmeticDecoder *arithDecoder;
- JArithmeticDecoderStats *genericRegionStats;
- JArithmeticDecoderStats *refinementRegionStats;
- JArithmeticDecoderStats *iadhStats;
- JArithmeticDecoderStats *iadwStats;
- JArithmeticDecoderStats *iaexStats;
- JArithmeticDecoderStats *iaaiStats;
- JArithmeticDecoderStats *iadtStats;
- JArithmeticDecoderStats *iaitStats;
- JArithmeticDecoderStats *iafsStats;
- JArithmeticDecoderStats *iadsStats;
- JArithmeticDecoderStats *iardxStats;
- JArithmeticDecoderStats *iardyStats;
- JArithmeticDecoderStats *iardwStats;
- JArithmeticDecoderStats *iardhStats;
- JArithmeticDecoderStats *iariStats;
- JArithmeticDecoderStats *iaidStats;
- JBIG2HuffmanDecoder *huffDecoder;
- JBIG2MMRDecoder *mmrDecoder;
-};
-
-#endif
+++ /dev/null
-//========================================================================
-//
-// JPXStream.cc
-//
-// Copyright 2002-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma implementation
-#endif
-
-#include "gmem.h"
-#include "Error.h"
-#include "JArithmeticDecoder.h"
-#include "JPXStream.h"
-
-//~ to do:
-// - precincts
-// - ROI
-// - progression order changes
-// - packed packet headers
-// - support for palettes, channel maps, etc.
-// - make sure all needed JP2/JPX subboxes are parsed (readBoxes)
-// - can we assume that QCC segments must come after the QCD segment?
-// - skip EPH markers (readTilePartData)
-// - handle tilePartToEOC in readTilePartData
-// - deal with multiple codeword segments (readTilePartData,
-// readCodeBlockData)
-// - progression orders 2, 3, and 4
-// - in coefficient decoding (readCodeBlockData):
-// - termination pattern: terminate after every coding pass
-// - error resilience segmentation symbol
-// - selective arithmetic coding bypass
-// - vertically causal context formation
-// - coeffs longer than 31 bits (should just ignore the extra bits?)
-// - handle boxes larger than 2^32 bytes
-// - the fixed-point arithmetic won't handle 16-bit pixels
-
-//------------------------------------------------------------------------
-
-// number of contexts for the arithmetic decoder
-#define jpxNContexts 19
-
-#define jpxContextSigProp 0 // 0 - 8: significance prop and cleanup
-#define jpxContextSign 9 // 9 - 13: sign
-#define jpxContextMagRef 14 // 14 -16: magnitude refinement
-#define jpxContextRunLength 17 // cleanup: run length
-#define jpxContextUniform 18 // cleanup: first signif coeff
-
-//------------------------------------------------------------------------
-
-#define jpxPassSigProp 0
-#define jpxPassMagRef 1
-#define jpxPassCleanup 2
-
-//------------------------------------------------------------------------
-
-// arithmetic decoder context for the significance propagation and
-// cleanup passes:
-// [horiz][vert][diag][subband]
-// where subband = 0 for HL
-// = 1 for LH and LL
-// = 2 for HH
-static Guint sigPropContext[3][3][5][3] = {
- {{{ 0, 0, 0 }, // horiz=0, vert=0, diag=0
- { 1, 1, 3 }, // horiz=0, vert=0, diag=1
- { 2, 2, 6 }, // horiz=0, vert=0, diag=2
- { 2, 2, 8 }, // horiz=0, vert=0, diag=3
- { 2, 2, 8 }}, // horiz=0, vert=0, diag=4
- {{ 5, 3, 1 }, // horiz=0, vert=1, diag=0
- { 6, 3, 4 }, // horiz=0, vert=1, diag=1
- { 6, 3, 7 }, // horiz=0, vert=1, diag=2
- { 6, 3, 8 }, // horiz=0, vert=1, diag=3
- { 6, 3, 8 }}, // horiz=0, vert=1, diag=4
- {{ 8, 4, 2 }, // horiz=0, vert=2, diag=0
- { 8, 4, 5 }, // horiz=0, vert=2, diag=1
- { 8, 4, 7 }, // horiz=0, vert=2, diag=2
- { 8, 4, 8 }, // horiz=0, vert=2, diag=3
- { 8, 4, 8 }}}, // horiz=0, vert=2, diag=4
- {{{ 3, 5, 1 }, // horiz=1, vert=0, diag=0
- { 3, 6, 4 }, // horiz=1, vert=0, diag=1
- { 3, 6, 7 }, // horiz=1, vert=0, diag=2
- { 3, 6, 8 }, // horiz=1, vert=0, diag=3
- { 3, 6, 8 }}, // horiz=1, vert=0, diag=4
- {{ 7, 7, 2 }, // horiz=1, vert=1, diag=0
- { 7, 7, 5 }, // horiz=1, vert=1, diag=1
- { 7, 7, 7 }, // horiz=1, vert=1, diag=2
- { 7, 7, 8 }, // horiz=1, vert=1, diag=3
- { 7, 7, 8 }}, // horiz=1, vert=1, diag=4
- {{ 8, 7, 2 }, // horiz=1, vert=2, diag=0
- { 8, 7, 5 }, // horiz=1, vert=2, diag=1
- { 8, 7, 7 }, // horiz=1, vert=2, diag=2
- { 8, 7, 8 }, // horiz=1, vert=2, diag=3
- { 8, 7, 8 }}}, // horiz=1, vert=2, diag=4
- {{{ 4, 8, 2 }, // horiz=2, vert=0, diag=0
- { 4, 8, 5 }, // horiz=2, vert=0, diag=1
- { 4, 8, 7 }, // horiz=2, vert=0, diag=2
- { 4, 8, 8 }, // horiz=2, vert=0, diag=3
- { 4, 8, 8 }}, // horiz=2, vert=0, diag=4
- {{ 7, 8, 2 }, // horiz=2, vert=1, diag=0
- { 7, 8, 5 }, // horiz=2, vert=1, diag=1
- { 7, 8, 7 }, // horiz=2, vert=1, diag=2
- { 7, 8, 8 }, // horiz=2, vert=1, diag=3
- { 7, 8, 8 }}, // horiz=2, vert=1, diag=4
- {{ 8, 8, 2 }, // horiz=2, vert=2, diag=0
- { 8, 8, 5 }, // horiz=2, vert=2, diag=1
- { 8, 8, 7 }, // horiz=2, vert=2, diag=2
- { 8, 8, 8 }, // horiz=2, vert=2, diag=3
- { 8, 8, 8 }}} // horiz=2, vert=2, diag=4
-};
-
-// arithmetic decoder context and xor bit for the sign bit in the
-// significance propagation pass:
-// [horiz][vert][k]
-// where horiz/vert are offset by 2 (i.e., range is -2 .. 2)
-// and k = 0 for the context
-// = 1 for the xor bit
-static Guint signContext[5][5][2] = {
- {{ 13, 1 }, // horiz=-2, vert=-2
- { 13, 1 }, // horiz=-2, vert=-1
- { 12, 1 }, // horiz=-2, vert= 0
- { 11, 1 }, // horiz=-2, vert=+1
- { 11, 1 }}, // horiz=-2, vert=+2
- {{ 13, 1 }, // horiz=-1, vert=-2
- { 13, 1 }, // horiz=-1, vert=-1
- { 12, 1 }, // horiz=-1, vert= 0
- { 11, 1 }, // horiz=-1, vert=+1
- { 11, 1 }}, // horiz=-1, vert=+2
- {{ 10, 1 }, // horiz= 0, vert=-2
- { 10, 1 }, // horiz= 0, vert=-1
- { 9, 0 }, // horiz= 0, vert= 0
- { 10, 0 }, // horiz= 0, vert=+1
- { 10, 0 }}, // horiz= 0, vert=+2
- {{ 11, 0 }, // horiz=+1, vert=-2
- { 11, 0 }, // horiz=+1, vert=-1
- { 12, 0 }, // horiz=+1, vert= 0
- { 13, 0 }, // horiz=+1, vert=+1
- { 13, 0 }}, // horiz=+1, vert=+2
- {{ 11, 0 }, // horiz=+2, vert=-2
- { 11, 0 }, // horiz=+2, vert=-1
- { 12, 0 }, // horiz=+2, vert= 0
- { 13, 0 }, // horiz=+2, vert=+1
- { 13, 0 }}, // horiz=+2, vert=+2
-};
-
-//------------------------------------------------------------------------
-
-// constants used in the IDWT
-#define idwtAlpha -1.586134342059924
-#define idwtBeta -0.052980118572961
-#define idwtGamma 0.882911075530934
-#define idwtDelta 0.443506852043971
-#define idwtKappa 1.230174104914001
-#define idwtIKappa (1.0 / idwtKappa)
-
-// number of bits to the right of the decimal point for the fixed
-// point arithmetic used in the IDWT
-#define fracBits 16
-
-//------------------------------------------------------------------------
-
-// floor(x / y)
-#define jpxFloorDiv(x, y) ((x) / (y))
-
-// floor(x / 2^y)
-#define jpxFloorDivPow2(x, y) ((x) >> (y))
-
-// ceil(x / y)
-#define jpxCeilDiv(x, y) (((x) + (y) - 1) / (y))
-
-// ceil(x / 2^y)
-#define jpxCeilDivPow2(x, y) (((x) + (1 << (y)) - 1) >> (y))
-
-//------------------------------------------------------------------------
-
-JPXStream::JPXStream(Stream *strA):
- FilterStream(strA)
-{
- nComps = 0;
- bpc = NULL;
- width = height = 0;
- haveCS = gFalse;
- havePalette = gFalse;
- haveCompMap = gFalse;
- haveChannelDefn = gFalse;
-
- img.tiles = NULL;
- bitBuf = 0;
- bitBufLen = 0;
- bitBufSkip = gFalse;
- byteCount = 0;
-}
-
-JPXStream::~JPXStream() {
- JPXTile *tile;
- JPXTileComp *tileComp;
- JPXResLevel *resLevel;
- JPXPrecinct *precinct;
- JPXSubband *subband;
- JPXCodeBlock *cb;
- Guint comp, i, k, r, pre, sb;
-
- gfree(bpc);
- if (havePalette) {
- gfree(palette.bpc);
- gfree(palette.c);
- }
- if (haveCompMap) {
- gfree(compMap.comp);
- gfree(compMap.type);
- gfree(compMap.pComp);
- }
- if (haveChannelDefn) {
- gfree(channelDefn.idx);
- gfree(channelDefn.type);
- gfree(channelDefn.assoc);
- }
-
- if (img.tiles) {
- for (i = 0; i < img.nXTiles * img.nYTiles; ++i) {
- tile = &img.tiles[i];
- if (tile->tileComps) {
- for (comp = 0; comp < img.nComps; ++comp) {
- tileComp = &tile->tileComps[comp];
- gfree(tileComp->quantSteps);
- gfree(tileComp->data);
- gfree(tileComp->buf);
- if (tileComp->resLevels) {
- for (r = 0; r <= tileComp->nDecompLevels; ++r) {
- resLevel = &tileComp->resLevels[r];
- if (resLevel->precincts) {
- for (pre = 0; pre < 1; ++pre) {
- precinct = &resLevel->precincts[pre];
- if (precinct->subbands) {
- for (sb = 0; sb < (r == 0 ? 1 : 3); ++sb) {
- subband = &precinct->subbands[sb];
- gfree(subband->inclusion);
- gfree(subband->zeroBitPlane);
- if (subband->cbs) {
- for (k = 0; k < subband->nXCBs * subband->nYCBs; ++k) {
- cb = &subband->cbs[k];
- gfree(cb->coeffs);
- if (cb->arithDecoder) {
- delete cb->arithDecoder;
- }
- if (cb->stats) {
- delete cb->stats;
- }
- }
- gfree(subband->cbs);
- }
- }
- gfree(precinct->subbands);
- }
- }
- gfree(img.tiles[i].tileComps[comp].resLevels[r].precincts);
- }
- }
- gfree(img.tiles[i].tileComps[comp].resLevels);
- }
- }
- gfree(img.tiles[i].tileComps);
- }
- }
- gfree(img.tiles);
- }
- delete str;
-}
-
-void JPXStream::reset() {
- str->reset();
- if (readBoxes()) {
- curY = img.yOffset;
- } else {
- // readBoxes reported an error, so we go immediately to EOF
- curY = img.ySize;
- }
- curX = img.xOffset;
- curComp = 0;
- readBufLen = 0;
-}
-
-int JPXStream::getChar() {
- int c;
-
- if (readBufLen < 8) {
- fillReadBuf();
- }
- if (readBufLen == 8) {
- c = readBuf & 0xff;
- readBufLen = 0;
- } else if (readBufLen > 8) {
- c = (readBuf >> (readBufLen - 8)) & 0xff;
- readBufLen -= 8;
- } else if (readBufLen == 0) {
- c = EOF;
- } else {
- c = (readBuf << (8 - readBufLen)) & 0xff;
- readBufLen = 0;
- }
- return c;
-}
-
-int JPXStream::lookChar() {
- int c;
-
- if (readBufLen < 8) {
- fillReadBuf();
- }
- if (readBufLen == 8) {
- c = readBuf & 0xff;
- } else if (readBufLen > 8) {
- c = (readBuf >> (readBufLen - 8)) & 0xff;
- } else if (readBufLen == 0) {
- c = EOF;
- } else {
- c = (readBuf << (8 - readBufLen)) & 0xff;
- }
- return c;
-}
-
-void JPXStream::fillReadBuf() {
- JPXTileComp *tileComp;
- Guint tileIdx, tx, ty;
- int pix, pixBits;
-
- do {
- if (curY >= img.ySize) {
- return;
- }
- tileIdx = ((curY - img.yTileOffset) / img.yTileSize) * img.nXTiles
- + (curX - img.xTileOffset) / img.xTileSize;
-#if 1 //~ ignore the palette, assume the PDF ColorSpace object is valid
- tileComp = &img.tiles[tileIdx].tileComps[curComp];
-#else
- tileComp = &img.tiles[tileIdx].tileComps[havePalette ? 0 : curComp];
-#endif
- tx = jpxCeilDiv((curX - img.xTileOffset) % img.xTileSize, tileComp->hSep);
- ty = jpxCeilDiv((curY - img.yTileOffset) % img.yTileSize, tileComp->vSep);
- pix = (int)tileComp->data[ty * (tileComp->x1 - tileComp->x0) + tx];
- pixBits = tileComp->prec;
-#if 1 //~ ignore the palette, assume the PDF ColorSpace object is valid
- if (++curComp == img.nComps) {
-#else
- if (havePalette) {
- if (pix >= 0 && pix < palette.nEntries) {
- pix = palette.c[pix * palette.nComps + curComp];
- } else {
- pix =
- pixBits = palette.bpc[curComp];
- }
- if (++curComp == (Guint)(havePalette ? palette.nComps : img.nComps)) {
-#endif
- curComp = 0;
- if (++curX == img.xSize) {
- curX = img.xOffset;
- ++curY;
- }
- }
- if (pixBits == 8) {
- readBuf = (readBuf << 8) | (pix & 0xff);
- } else {
- readBuf = (readBuf << pixBits) | (pix & ((1 << pixBits) - 1));
- }
- readBufLen += pixBits;
- } while (readBufLen < 8);
-}
-
-GString *JPXStream::getPSFilter(int psLevel, char *indent) {
- return NULL;
-}
-
-GBool JPXStream::isBinary(GBool last) {
- return str->isBinary(gTrue);
-}
-
-void JPXStream::getImageParams(int *bitsPerComponent,
- StreamColorSpaceMode *csMode) {
- Guint boxType, boxLen, dataLen, csEnum;
- Guint bpc1, dummy, i;
- int csMeth, csPrec, csPrec1, dummy2;
- StreamColorSpaceMode csMode1;
- GBool haveBPC, haveCSMode;
-
- csPrec = 0; // make gcc happy
- haveBPC = haveCSMode = gFalse;
- str->reset();
- if (str->lookChar() == 0xff) {
- getImageParams2(bitsPerComponent, csMode);
- } else {
- while (readBoxHdr(&boxType, &boxLen, &dataLen)) {
- if (boxType == 0x6a703268) { // JP2 header
- // skip the superbox
- } else if (boxType == 0x69686472) { // image header
- if (readULong(&dummy) &&
- readULong(&dummy) &&
- readUWord(&dummy) &&
- readUByte(&bpc1) &&
- readUByte(&dummy) &&
- readUByte(&dummy) &&
- readUByte(&dummy)) {
- *bitsPerComponent = bpc1 + 1;
- haveBPC = gTrue;
- }
- } else if (boxType == 0x636F6C72) { // color specification
- if (readByte(&csMeth) &&
- readByte(&csPrec1) &&
- readByte(&dummy2)) {
- if (csMeth == 1) {
- if (readULong(&csEnum)) {
- csMode1 = streamCSNone;
- if (csEnum == jpxCSBiLevel ||
- csEnum == jpxCSGrayscale) {
- csMode1 = streamCSDeviceGray;
- } else if (csEnum == jpxCSCMYK) {
- csMode1 = streamCSDeviceCMYK;
- } else if (csEnum == jpxCSsRGB ||
- csEnum == jpxCSCISesRGB ||
- csEnum == jpxCSROMMRGB) {
- csMode1 = streamCSDeviceRGB;
- }
- if (csMode1 != streamCSNone &&
- (!haveCSMode || csPrec1 > csPrec)) {
- *csMode = csMode1;
- csPrec = csPrec1;
- haveCSMode = gTrue;
- }
- for (i = 0; i < dataLen - 7; ++i) {
- str->getChar();
- }
- }
- } else {
- for (i = 0; i < dataLen - 3; ++i) {
- str->getChar();
- }
- }
- }
- } else if (boxType == 0x6A703263) { // codestream
- if (!(haveBPC && haveCSMode)) {
- getImageParams2(bitsPerComponent, csMode);
- }
- break;
- } else {
- for (i = 0; i < dataLen; ++i) {
- str->getChar();
- }
- }
- }
- }
- str->close();
-}
-
-// Get image parameters from the codestream.
-void JPXStream::getImageParams2(int *bitsPerComponent,
- StreamColorSpaceMode *csMode) {
- int segType;
- Guint segLen, nComps1, bpc1, dummy, i;
-
- while (readMarkerHdr(&segType, &segLen)) {
- if (segType == 0x51) { // SIZ - image and tile size
- if (readUWord(&dummy) &&
- readULong(&dummy) &&
- readULong(&dummy) &&
- readULong(&dummy) &&
- readULong(&dummy) &&
- readULong(&dummy) &&
- readULong(&dummy) &&
- readULong(&dummy) &&
- readULong(&dummy) &&
- readUWord(&nComps1) &&
- readUByte(&bpc1)) {
- *bitsPerComponent = (bpc1 & 0x7f) + 1;
- // if there's no color space info, take a guess
- if (nComps1 == 1) {
- *csMode = streamCSDeviceGray;
- } else if (nComps1 == 3) {
- *csMode = streamCSDeviceRGB;
- } else if (nComps1 == 4) {
- *csMode = streamCSDeviceCMYK;
- }
- }
- break;
- } else {
- if (segLen > 2) {
- for (i = 0; i < segLen - 2; ++i) {
- str->getChar();
- }
- }
- }
- }
-}
-
-GBool JPXStream::readBoxes() {
- Guint boxType, boxLen, dataLen;
- Guint bpc1, compression, unknownColorspace, ipr;
- Guint i, j;
-
- haveImgHdr = gFalse;
-
- // check for a naked JPEG 2000 codestream (without the JP2/JPX
- // wrapper) -- this appears to be a violation of the PDF spec, but
- // Acrobat allows it
- if (str->lookChar() == 0xff) {
- error(getPos(), "Naked JPEG 2000 codestream, missing JP2/JPX wrapper");
- readCodestream(0);
- nComps = img.nComps;
- bpc = (Guint *)gmallocn(nComps, sizeof(Guint));
- for (i = 0; i < nComps; ++i) {
- bpc[i] = img.tiles[0].tileComps[i].prec;
- }
- width = img.xSize - img.xOffset;
- height = img.ySize - img.yOffset;
- return gTrue;
- }
-
- while (readBoxHdr(&boxType, &boxLen, &dataLen)) {
- switch (boxType) {
- case 0x6a703268: // JP2 header
- // this is a grouping box ('superbox') which has no real
- // contents and doesn't appear to be used consistently, i.e.,
- // some things which should be subboxes of the JP2 header box
- // show up outside of it - so we simply ignore the JP2 header
- // box
- break;
- case 0x69686472: // image header
- if (!readULong(&height) ||
- !readULong(&width) ||
- !readUWord(&nComps) ||
- !readUByte(&bpc1) ||
- !readUByte(&compression) ||
- !readUByte(&unknownColorspace) ||
- !readUByte(&ipr)) {
- error(getPos(), "Unexpected EOF in JPX stream");
- return gFalse;
- }
- if (compression != 7) {
- error(getPos(), "Unknown compression type in JPX stream");
- return gFalse;
- }
- bpc = (Guint *)gmallocn(nComps, sizeof(Guint));
- for (i = 0; i < nComps; ++i) {
- bpc[i] = bpc1;
- }
- haveImgHdr = gTrue;
- break;
- case 0x62706363: // bits per component
- if (!haveImgHdr) {
- error(getPos(), "Found bits per component box before image header box in JPX stream");
- return gFalse;
- }
- if (dataLen != nComps) {
- error(getPos(), "Invalid bits per component box in JPX stream");
- return gFalse;
- }
- for (i = 0; i < nComps; ++i) {
- if (!readUByte(&bpc[i])) {
- error(getPos(), "Unexpected EOF in JPX stream");
- return gFalse;
- }
- }
- break;
- case 0x636F6C72: // color specification
- if (!readColorSpecBox(dataLen)) {
- return gFalse;
- }
- break;
- case 0x70636c72: // palette
- if (!readUWord(&palette.nEntries) ||
- !readUByte(&palette.nComps)) {
- error(getPos(), "Unexpected EOF in JPX stream");
- return gFalse;
- }
- palette.bpc = (Guint *)gmallocn(palette.nComps, sizeof(Guint));
- palette.c =
- (int *)gmallocn(palette.nEntries * palette.nComps, sizeof(int));
- for (i = 0; i < palette.nComps; ++i) {
- if (!readUByte(&palette.bpc[i])) {
- error(getPos(), "Unexpected EOF in JPX stream");
- return gFalse;
- }
- ++palette.bpc[i];
- }
- for (i = 0; i < palette.nEntries; ++i) {
- for (j = 0; j < palette.nComps; ++j) {
- if (!readNBytes(((palette.bpc[j] & 0x7f) + 7) >> 3,
- (palette.bpc[j] & 0x80) ? gTrue : gFalse,
- &palette.c[i * palette.nComps + j])) {
- error(getPos(), "Unexpected EOF in JPX stream");
- return gFalse;
- }
- }
- }
- havePalette = gTrue;
- break;
- case 0x636d6170: // component mapping
- compMap.nChannels = dataLen / 4;
- compMap.comp = (Guint *)gmallocn(compMap.nChannels, sizeof(Guint));
- compMap.type = (Guint *)gmallocn(compMap.nChannels, sizeof(Guint));
- compMap.pComp = (Guint *)gmallocn(compMap.nChannels, sizeof(Guint));
- for (i = 0; i < compMap.nChannels; ++i) {
- if (!readUWord(&compMap.comp[i]) ||
- !readUByte(&compMap.type[i]) ||
- !readUByte(&compMap.pComp[i])) {
- error(getPos(), "Unexpected EOF in JPX stream");
- return gFalse;
- }
- }
- haveCompMap = gTrue;
- break;
- case 0x63646566: // channel definition
- if (!readUWord(&channelDefn.nChannels)) {
- error(getPos(), "Unexpected EOF in JPX stream");
- return gFalse;
- }
- channelDefn.idx =
- (Guint *)gmallocn(channelDefn.nChannels, sizeof(Guint));
- channelDefn.type =
- (Guint *)gmallocn(channelDefn.nChannels, sizeof(Guint));
- channelDefn.assoc =
- (Guint *)gmallocn(channelDefn.nChannels, sizeof(Guint));
- for (i = 0; i < channelDefn.nChannels; ++i) {
- if (!readUWord(&channelDefn.idx[i]) ||
- !readUWord(&channelDefn.type[i]) ||
- !readUWord(&channelDefn.assoc[i])) {
- error(getPos(), "Unexpected EOF in JPX stream");
- return gFalse;
- }
- }
- haveChannelDefn = gTrue;
- break;
- case 0x6A703263: // contiguous codestream
- if (!bpc) {
- error(getPos(), "JPX stream is missing the image header box");
- }
- if (!haveCS) {
- error(getPos(), "JPX stream has no supported color spec");
- }
- if (!readCodestream(dataLen)) {
- return gFalse;
- }
- break;
- default:
- for (i = 0; i < dataLen; ++i) {
- if (str->getChar() == EOF) {
- error(getPos(), "Unexpected EOF in JPX stream");
- return gFalse;
- }
- }
- break;
- }
- }
- return gTrue;
-}
-
-GBool JPXStream::readColorSpecBox(Guint dataLen) {
- JPXColorSpec newCS;
- Guint csApprox, csEnum;
- Guint i;
- GBool ok;
-
- ok = gFalse;
- if (!readUByte(&newCS.meth) ||
- !readByte(&newCS.prec) ||
- !readUByte(&csApprox)) {
- goto err;
- }
- switch (newCS.meth) {
- case 1: // enumerated colorspace
- if (!readULong(&csEnum)) {
- goto err;
- }
- newCS.enumerated.type = (JPXColorSpaceType)csEnum;
- switch (newCS.enumerated.type) {
- case jpxCSBiLevel:
- ok = gTrue;
- break;
- case jpxCSYCbCr1:
- ok = gTrue;
- break;
- case jpxCSYCbCr2:
- ok = gTrue;
- break;
- case jpxCSYCBCr3:
- ok = gTrue;
- break;
- case jpxCSPhotoYCC:
- ok = gTrue;
- break;
- case jpxCSCMY:
- ok = gTrue;
- break;
- case jpxCSCMYK:
- ok = gTrue;
- break;
- case jpxCSYCCK:
- ok = gTrue;
- break;
- case jpxCSCIELab:
- if (dataLen == 7 + 7*4) {
- if (!readULong(&newCS.enumerated.cieLab.rl) ||
- !readULong(&newCS.enumerated.cieLab.ol) ||
- !readULong(&newCS.enumerated.cieLab.ra) ||
- !readULong(&newCS.enumerated.cieLab.oa) ||
- !readULong(&newCS.enumerated.cieLab.rb) ||
- !readULong(&newCS.enumerated.cieLab.ob) ||
- !readULong(&newCS.enumerated.cieLab.il)) {
- goto err;
- }
- } else if (dataLen == 7) {
- //~ this assumes the 8-bit case
- newCS.enumerated.cieLab.rl = 100;
- newCS.enumerated.cieLab.ol = 0;
- newCS.enumerated.cieLab.ra = 255;
- newCS.enumerated.cieLab.oa = 128;
- newCS.enumerated.cieLab.rb = 255;
- newCS.enumerated.cieLab.ob = 96;
- newCS.enumerated.cieLab.il = 0x00443530;
- } else {
- goto err;
- }
- ok = gTrue;
- break;
- case jpxCSsRGB:
- ok = gTrue;
- break;
- case jpxCSGrayscale:
- ok = gTrue;
- break;
- case jpxCSBiLevel2:
- ok = gTrue;
- break;
- case jpxCSCIEJab:
- // not allowed in PDF
- goto err;
- case jpxCSCISesRGB:
- ok = gTrue;
- break;
- case jpxCSROMMRGB:
- ok = gTrue;
- break;
- case jpxCSsRGBYCbCr:
- ok = gTrue;
- break;
- case jpxCSYPbPr1125:
- ok = gTrue;
- break;
- case jpxCSYPbPr1250:
- ok = gTrue;
- break;
- default:
- goto err;
- }
- break;
- case 2: // restricted ICC profile
- case 3: // any ICC profile (JPX)
- case 4: // vendor color (JPX)
- for (i = 0; i < dataLen - 3; ++i) {
- if (str->getChar() == EOF) {
- goto err;
- }
- }
- break;
- }
-
- if (ok && (!haveCS || newCS.prec > cs.prec)) {
- cs = newCS;
- haveCS = gTrue;
- }
-
- return gTrue;
-
- err:
- error(getPos(), "Error in JPX color spec");
- return gFalse;
-}
-
-GBool JPXStream::readCodestream(Guint len) {
- JPXTile *tile;
- JPXTileComp *tileComp;
- int segType;
- GBool haveSIZ, haveCOD, haveQCD, haveSOT;
- Guint precinctSize, style;
- Guint segLen, capabilities, nTiles, comp, i, j, r;
-
- //----- main header
- haveSIZ = haveCOD = haveQCD = haveSOT = gFalse;
- do {
- if (!readMarkerHdr(&segType, &segLen)) {
- error(getPos(), "Error in JPX codestream");
- return gFalse;
- }
- switch (segType) {
- case 0x4f: // SOC - start of codestream
- // marker only
- break;
- case 0x51: // SIZ - image and tile size
- if (!readUWord(&capabilities) ||
- !readULong(&img.xSize) ||
- !readULong(&img.ySize) ||
- !readULong(&img.xOffset) ||
- !readULong(&img.yOffset) ||
- !readULong(&img.xTileSize) ||
- !readULong(&img.yTileSize) ||
- !readULong(&img.xTileOffset) ||
- !readULong(&img.yTileOffset) ||
- !readUWord(&img.nComps)) {
- error(getPos(), "Error in JPX SIZ marker segment");
- return gFalse;
- }
- if (haveImgHdr && img.nComps != nComps) {
- error(getPos(), "Different number of components in JPX SIZ marker segment");
- return gFalse;
- }
- img.nXTiles = (img.xSize - img.xTileOffset + img.xTileSize - 1)
- / img.xTileSize;
- img.nYTiles = (img.ySize - img.yTileOffset + img.yTileSize - 1)
- / img.yTileSize;
- nTiles = img.nXTiles * img.nYTiles;
- // check for overflow before allocating memory
- if (nTiles == 0 || nTiles / img.nXTiles != img.nYTiles) {
- error(getPos(), "Bad tile count in JPX SIZ marker segment");
- return gFalse;
- }
- img.tiles = (JPXTile *)gmallocn(nTiles, sizeof(JPXTile));
- for (i = 0; i < img.nXTiles * img.nYTiles; ++i) {
- img.tiles[i].tileComps = (JPXTileComp *)gmallocn(img.nComps,
- sizeof(JPXTileComp));
- for (comp = 0; comp < img.nComps; ++comp) {
- img.tiles[i].tileComps[comp].quantSteps = NULL;
- img.tiles[i].tileComps[comp].data = NULL;
- img.tiles[i].tileComps[comp].buf = NULL;
- img.tiles[i].tileComps[comp].resLevels = NULL;
- }
- }
- for (comp = 0; comp < img.nComps; ++comp) {
- if (!readUByte(&img.tiles[0].tileComps[comp].prec) ||
- !readUByte(&img.tiles[0].tileComps[comp].hSep) ||
- !readUByte(&img.tiles[0].tileComps[comp].vSep)) {
- error(getPos(), "Error in JPX SIZ marker segment");
- return gFalse;
- }
- img.tiles[0].tileComps[comp].sgned =
- (img.tiles[0].tileComps[comp].prec & 0x80) ? gTrue : gFalse;
- img.tiles[0].tileComps[comp].prec =
- (img.tiles[0].tileComps[comp].prec & 0x7f) + 1;
- for (i = 1; i < img.nXTiles * img.nYTiles; ++i) {
- img.tiles[i].tileComps[comp] = img.tiles[0].tileComps[comp];
- }
- }
- haveSIZ = gTrue;
- break;
- case 0x52: // COD - coding style default
- if (!readUByte(&img.tiles[0].tileComps[0].style) ||
- !readUByte(&img.tiles[0].progOrder) ||
- !readUWord(&img.tiles[0].nLayers) ||
- !readUByte(&img.tiles[0].multiComp) ||
- !readUByte(&img.tiles[0].tileComps[0].nDecompLevels) ||
- !readUByte(&img.tiles[0].tileComps[0].codeBlockW) ||
- !readUByte(&img.tiles[0].tileComps[0].codeBlockH) ||
- !readUByte(&img.tiles[0].tileComps[0].codeBlockStyle) ||
- !readUByte(&img.tiles[0].tileComps[0].transform)) {
- error(getPos(), "Error in JPX COD marker segment");
- return gFalse;
- }
- img.tiles[0].tileComps[0].codeBlockW += 2;
- img.tiles[0].tileComps[0].codeBlockH += 2;
- for (i = 0; i < img.nXTiles * img.nYTiles; ++i) {
- if (i != 0) {
- img.tiles[i].progOrder = img.tiles[0].progOrder;
- img.tiles[i].nLayers = img.tiles[0].nLayers;
- img.tiles[i].multiComp = img.tiles[0].multiComp;
- }
- for (comp = 0; comp < img.nComps; ++comp) {
- if (!(i == 0 && comp == 0)) {
- img.tiles[i].tileComps[comp].style =
- img.tiles[0].tileComps[0].style;
- img.tiles[i].tileComps[comp].nDecompLevels =
- img.tiles[0].tileComps[0].nDecompLevels;
- img.tiles[i].tileComps[comp].codeBlockW =
- img.tiles[0].tileComps[0].codeBlockW;
- img.tiles[i].tileComps[comp].codeBlockH =
- img.tiles[0].tileComps[0].codeBlockH;
- img.tiles[i].tileComps[comp].codeBlockStyle =
- img.tiles[0].tileComps[0].codeBlockStyle;
- img.tiles[i].tileComps[comp].transform =
- img.tiles[0].tileComps[0].transform;
- }
- img.tiles[i].tileComps[comp].resLevels =
- (JPXResLevel *)gmallocn(
- (img.tiles[i].tileComps[comp].nDecompLevels + 1),
- sizeof(JPXResLevel));
- for (r = 0; r <= img.tiles[i].tileComps[comp].nDecompLevels; ++r) {
- img.tiles[i].tileComps[comp].resLevels[r].precincts = NULL;
- }
- }
- }
- for (r = 0; r <= img.tiles[0].tileComps[0].nDecompLevels; ++r) {
- if (img.tiles[0].tileComps[0].style & 0x01) {
- if (!readUByte(&precinctSize)) {
- error(getPos(), "Error in JPX COD marker segment");
- return gFalse;
- }
- img.tiles[0].tileComps[0].resLevels[r].precinctWidth =
- precinctSize & 0x0f;
- img.tiles[0].tileComps[0].resLevels[r].precinctHeight =
- (precinctSize >> 4) & 0x0f;
- } else {
- img.tiles[0].tileComps[0].resLevels[r].precinctWidth = 15;
- img.tiles[0].tileComps[0].resLevels[r].precinctHeight = 15;
- }
- }
- for (i = 0; i < img.nXTiles * img.nYTiles; ++i) {
- for (comp = 0; comp < img.nComps; ++comp) {
- if (!(i == 0 && comp == 0)) {
- for (r = 0; r <= img.tiles[i].tileComps[comp].nDecompLevels; ++r) {
- img.tiles[i].tileComps[comp].resLevels[r].precinctWidth =
- img.tiles[0].tileComps[0].resLevels[r].precinctWidth;
- img.tiles[i].tileComps[comp].resLevels[r].precinctHeight =
- img.tiles[0].tileComps[0].resLevels[r].precinctHeight;
- }
- }
- }
- }
- haveCOD = gTrue;
- break;
- case 0x53: // COC - coding style component
- if (!haveCOD) {
- error(getPos(), "JPX COC marker segment before COD segment");
- return gFalse;
- }
- if ((img.nComps > 256 && !readUWord(&comp)) ||
- (img.nComps <= 256 && !readUByte(&comp)) ||
- comp >= img.nComps ||
- !readUByte(&style) ||
- !readUByte(&img.tiles[0].tileComps[comp].nDecompLevels) ||
- !readUByte(&img.tiles[0].tileComps[comp].codeBlockW) ||
- !readUByte(&img.tiles[0].tileComps[comp].codeBlockH) ||
- !readUByte(&img.tiles[0].tileComps[comp].codeBlockStyle) ||
- !readUByte(&img.tiles[0].tileComps[comp].transform)) {
- error(getPos(), "Error in JPX COC marker segment");
- return gFalse;
- }
- img.tiles[0].tileComps[comp].style =
- (img.tiles[0].tileComps[comp].style & ~1) | (style & 1);
- img.tiles[0].tileComps[comp].codeBlockW += 2;
- img.tiles[0].tileComps[comp].codeBlockH += 2;
- for (i = 0; i < img.nXTiles * img.nYTiles; ++i) {
- if (i != 0) {
- img.tiles[i].tileComps[comp].style =
- img.tiles[0].tileComps[comp].style;
- img.tiles[i].tileComps[comp].nDecompLevels =
- img.tiles[0].tileComps[comp].nDecompLevels;
- img.tiles[i].tileComps[comp].codeBlockW =
- img.tiles[0].tileComps[comp].codeBlockW;
- img.tiles[i].tileComps[comp].codeBlockH =
- img.tiles[0].tileComps[comp].codeBlockH;
- img.tiles[i].tileComps[comp].codeBlockStyle =
- img.tiles[0].tileComps[comp].codeBlockStyle;
- img.tiles[i].tileComps[comp].transform =
- img.tiles[0].tileComps[comp].transform;
- }
- img.tiles[i].tileComps[comp].resLevels =
- (JPXResLevel *)greallocn(
- img.tiles[i].tileComps[comp].resLevels,
- (img.tiles[i].tileComps[comp].nDecompLevels + 1),
- sizeof(JPXResLevel));
- for (r = 0; r <= img.tiles[i].tileComps[comp].nDecompLevels; ++r) {
- img.tiles[i].tileComps[comp].resLevels[r].precincts = NULL;
- }
- }
- for (r = 0; r <= img.tiles[0].tileComps[comp].nDecompLevels; ++r) {
- if (img.tiles[0].tileComps[comp].style & 0x01) {
- if (!readUByte(&precinctSize)) {
- error(getPos(), "Error in JPX COD marker segment");
- return gFalse;
- }
- img.tiles[0].tileComps[comp].resLevels[r].precinctWidth =
- precinctSize & 0x0f;
- img.tiles[0].tileComps[comp].resLevels[r].precinctHeight =
- (precinctSize >> 4) & 0x0f;
- } else {
- img.tiles[0].tileComps[comp].resLevels[r].precinctWidth = 15;
- img.tiles[0].tileComps[comp].resLevels[r].precinctHeight = 15;
- }
- }
- for (i = 1; i < img.nXTiles * img.nYTiles; ++i) {
- for (r = 0; r <= img.tiles[i].tileComps[comp].nDecompLevels; ++r) {
- img.tiles[i].tileComps[comp].resLevels[r].precinctWidth =
- img.tiles[0].tileComps[comp].resLevels[r].precinctWidth;
- img.tiles[i].tileComps[comp].resLevels[r].precinctHeight =
- img.tiles[0].tileComps[comp].resLevels[r].precinctHeight;
- }
- }
- break;
- case 0x5c: // QCD - quantization default
- if (!readUByte(&img.tiles[0].tileComps[0].quantStyle)) {
- error(getPos(), "Error in JPX QCD marker segment");
- return gFalse;
- }
- if ((img.tiles[0].tileComps[0].quantStyle & 0x1f) == 0x00) {
- img.tiles[0].tileComps[0].nQuantSteps = segLen - 3;
- img.tiles[0].tileComps[0].quantSteps =
- (Guint *)greallocn(img.tiles[0].tileComps[0].quantSteps,
- img.tiles[0].tileComps[0].nQuantSteps,
- sizeof(Guint));
- for (i = 0; i < img.tiles[0].tileComps[0].nQuantSteps; ++i) {
- if (!readUByte(&img.tiles[0].tileComps[0].quantSteps[i])) {
- error(getPos(), "Error in JPX QCD marker segment");
- return gFalse;
- }
- }
- } else if ((img.tiles[0].tileComps[0].quantStyle & 0x1f) == 0x01) {
- img.tiles[0].tileComps[0].nQuantSteps = 1;
- img.tiles[0].tileComps[0].quantSteps =
- (Guint *)greallocn(img.tiles[0].tileComps[0].quantSteps,
- img.tiles[0].tileComps[0].nQuantSteps,
- sizeof(Guint));
- if (!readUWord(&img.tiles[0].tileComps[0].quantSteps[0])) {
- error(getPos(), "Error in JPX QCD marker segment");
- return gFalse;
- }
- } else if ((img.tiles[0].tileComps[0].quantStyle & 0x1f) == 0x02) {
- img.tiles[0].tileComps[0].nQuantSteps = (segLen - 3) / 2;
- img.tiles[0].tileComps[0].quantSteps =
- (Guint *)greallocn(img.tiles[0].tileComps[0].quantSteps,
- img.tiles[0].tileComps[0].nQuantSteps,
- sizeof(Guint));
- for (i = 0; i < img.tiles[0].tileComps[0].nQuantSteps; ++i) {
- if (!readUWord(&img.tiles[0].tileComps[0].quantSteps[i])) {
- error(getPos(), "Error in JPX QCD marker segment");
- return gFalse;
- }
- }
- } else {
- error(getPos(), "Error in JPX QCD marker segment");
- return gFalse;
- }
- for (i = 0; i < img.nXTiles * img.nYTiles; ++i) {
- for (comp = 0; comp < img.nComps; ++comp) {
- if (!(i == 0 && comp == 0)) {
- img.tiles[i].tileComps[comp].quantStyle =
- img.tiles[0].tileComps[0].quantStyle;
- img.tiles[i].tileComps[comp].nQuantSteps =
- img.tiles[0].tileComps[0].nQuantSteps;
- img.tiles[i].tileComps[comp].quantSteps =
- (Guint *)greallocn(img.tiles[i].tileComps[comp].quantSteps,
- img.tiles[0].tileComps[0].nQuantSteps,
- sizeof(Guint));
- for (j = 0; j < img.tiles[0].tileComps[0].nQuantSteps; ++j) {
- img.tiles[i].tileComps[comp].quantSteps[j] =
- img.tiles[0].tileComps[0].quantSteps[j];
- }
- }
- }
- }
- haveQCD = gTrue;
- break;
- case 0x5d: // QCC - quantization component
- if (!haveQCD) {
- error(getPos(), "JPX QCC marker segment before QCD segment");
- return gFalse;
- }
- if ((img.nComps > 256 && !readUWord(&comp)) ||
- (img.nComps <= 256 && !readUByte(&comp)) ||
- comp >= img.nComps ||
- !readUByte(&img.tiles[0].tileComps[comp].quantStyle)) {
- error(getPos(), "Error in JPX QCC marker segment");
- return gFalse;
- }
- if ((img.tiles[0].tileComps[comp].quantStyle & 0x1f) == 0x00) {
- img.tiles[0].tileComps[comp].nQuantSteps =
- segLen - (img.nComps > 256 ? 5 : 4);
- img.tiles[0].tileComps[comp].quantSteps =
- (Guint *)greallocn(img.tiles[0].tileComps[comp].quantSteps,
- img.tiles[0].tileComps[comp].nQuantSteps,
- sizeof(Guint));
- for (i = 0; i < img.tiles[0].tileComps[comp].nQuantSteps; ++i) {
- if (!readUByte(&img.tiles[0].tileComps[comp].quantSteps[i])) {
- error(getPos(), "Error in JPX QCC marker segment");
- return gFalse;
- }
- }
- } else if ((img.tiles[0].tileComps[comp].quantStyle & 0x1f) == 0x01) {
- img.tiles[0].tileComps[comp].nQuantSteps = 1;
- img.tiles[0].tileComps[comp].quantSteps =
- (Guint *)greallocn(img.tiles[0].tileComps[comp].quantSteps,
- img.tiles[0].tileComps[comp].nQuantSteps,
- sizeof(Guint));
- if (!readUWord(&img.tiles[0].tileComps[comp].quantSteps[0])) {
- error(getPos(), "Error in JPX QCC marker segment");
- return gFalse;
- }
- } else if ((img.tiles[0].tileComps[comp].quantStyle & 0x1f) == 0x02) {
- img.tiles[0].tileComps[comp].nQuantSteps =
- (segLen - (img.nComps > 256 ? 5 : 4)) / 2;
- img.tiles[0].tileComps[comp].quantSteps =
- (Guint *)greallocn(img.tiles[0].tileComps[comp].quantSteps,
- img.tiles[0].tileComps[comp].nQuantSteps,
- sizeof(Guint));
- for (i = 0; i < img.tiles[0].tileComps[comp].nQuantSteps; ++i) {
- if (!readUWord(&img.tiles[0].tileComps[comp].quantSteps[i])) {
- error(getPos(), "Error in JPX QCD marker segment");
- return gFalse;
- }
- }
- } else {
- error(getPos(), "Error in JPX QCC marker segment");
- return gFalse;
- }
- for (i = 1; i < img.nXTiles * img.nYTiles; ++i) {
- img.tiles[i].tileComps[comp].quantStyle =
- img.tiles[0].tileComps[comp].quantStyle;
- img.tiles[i].tileComps[comp].nQuantSteps =
- img.tiles[0].tileComps[comp].nQuantSteps;
- img.tiles[i].tileComps[comp].quantSteps =
- (Guint *)greallocn(img.tiles[i].tileComps[comp].quantSteps,
- img.tiles[0].tileComps[comp].nQuantSteps,
- sizeof(Guint));
- for (j = 0; j < img.tiles[0].tileComps[comp].nQuantSteps; ++j) {
- img.tiles[i].tileComps[comp].quantSteps[j] =
- img.tiles[0].tileComps[comp].quantSteps[j];
- }
- }
- break;
- case 0x5e: // RGN - region of interest
-#if 1 //~ ROI is unimplemented
- fprintf(stderr, "RGN\n");
- for (i = 0; i < segLen - 2; ++i) {
- if (str->getChar() == EOF) {
- error(getPos(), "Error in JPX PPM marker segment");
- return gFalse;
- }
- }
-#else
- if ((img.nComps > 256 && !readUWord(&comp)) ||
- (img.nComps <= 256 && !readUByte(&comp)) ||
- comp >= img.nComps ||
- !readUByte(&compInfo[comp].defROI.style) ||
- !readUByte(&compInfo[comp].defROI.shift)) {
- error(getPos(), "Error in JPX RGN marker segment");
- return gFalse;
- }
-#endif
- break;
- case 0x5f: // POC - progression order change
-#if 1 //~ progression order changes are unimplemented
- fprintf(stderr, "POC\n");
- for (i = 0; i < segLen - 2; ++i) {
- if (str->getChar() == EOF) {
- error(getPos(), "Error in JPX PPM marker segment");
- return gFalse;
- }
- }
-#else
- nProgs = (segLen - 2) / (img.nComps > 256 ? 9 : 7);
- progs = (JPXProgOrder *)gmallocn(nProgs, sizeof(JPXProgOrder));
- for (i = 0; i < nProgs; ++i) {
- if (!readUByte(&progs[i].startRes) ||
- !(img.nComps > 256 && readUWord(&progs[i].startComp)) ||
- !(img.nComps <= 256 && readUByte(&progs[i].startComp)) ||
- !readUWord(&progs[i].endLayer) ||
- !readUByte(&progs[i].endRes) ||
- !(img.nComps > 256 && readUWord(&progs[i].endComp)) ||
- !(img.nComps <= 256 && readUByte(&progs[i].endComp)) ||
- !readUByte(&progs[i].progOrder)) {
- error(getPos(), "Error in JPX POC marker segment");
- return gFalse;
- }
- }
-#endif
- break;
- case 0x60: // PPM - packed packet headers, main header
-#if 1 //~ packed packet headers are unimplemented
- fprintf(stderr, "PPM\n");
- for (i = 0; i < segLen - 2; ++i) {
- if (str->getChar() == EOF) {
- error(getPos(), "Error in JPX PPM marker segment");
- return gFalse;
- }
- }
-#endif
- break;
- case 0x55: // TLM - tile-part lengths
- // skipped
- for (i = 0; i < segLen - 2; ++i) {
- if (str->getChar() == EOF) {
- error(getPos(), "Error in JPX TLM marker segment");
- return gFalse;
- }
- }
- break;
- case 0x57: // PLM - packet length, main header
- // skipped
- for (i = 0; i < segLen - 2; ++i) {
- if (str->getChar() == EOF) {
- error(getPos(), "Error in JPX PLM marker segment");
- return gFalse;
- }
- }
- break;
- case 0x63: // CRG - component registration
- // skipped
- for (i = 0; i < segLen - 2; ++i) {
- if (str->getChar() == EOF) {
- error(getPos(), "Error in JPX CRG marker segment");
- return gFalse;
- }
- }
- break;
- case 0x64: // COM - comment
- // skipped
- for (i = 0; i < segLen - 2; ++i) {
- if (str->getChar() == EOF) {
- error(getPos(), "Error in JPX COM marker segment");
- return gFalse;
- }
- }
- break;
- case 0x90: // SOT - start of tile
- haveSOT = gTrue;
- break;
- default:
- error(getPos(), "Unknown marker segment %02x in JPX stream", segType);
- for (i = 0; i < segLen - 2; ++i) {
- if (str->getChar() == EOF) {
- break;
- }
- }
- break;
- }
- } while (!haveSOT);
-
- if (!haveSIZ) {
- error(getPos(), "Missing SIZ marker segment in JPX stream");
- return gFalse;
- }
- if (!haveCOD) {
- error(getPos(), "Missing COD marker segment in JPX stream");
- return gFalse;
- }
- if (!haveQCD) {
- error(getPos(), "Missing QCD marker segment in JPX stream");
- return gFalse;
- }
-
- //----- read the tile-parts
- while (1) {
- if (!readTilePart()) {
- return gFalse;
- }
- if (!readMarkerHdr(&segType, &segLen)) {
- error(getPos(), "Error in JPX codestream");
- return gFalse;
- }
- if (segType != 0x90) { // SOT - start of tile
- break;
- }
- }
-
- if (segType != 0xd9) { // EOC - end of codestream
- error(getPos(), "Missing EOC marker in JPX codestream");
- return gFalse;
- }
-
- //----- finish decoding the image
- for (i = 0; i < img.nXTiles * img.nYTiles; ++i) {
- tile = &img.tiles[i];
- for (comp = 0; comp < img.nComps; ++comp) {
- tileComp = &tile->tileComps[comp];
- inverseTransform(tileComp);
- }
- if (!inverseMultiCompAndDC(tile)) {
- return gFalse;
- }
- }
-
- //~ can free memory below tileComps here, and also tileComp.buf
-
- return gTrue;
-}
-
-GBool JPXStream::readTilePart() {
- JPXTile *tile;
- JPXTileComp *tileComp;
- JPXResLevel *resLevel;
- JPXPrecinct *precinct;
- JPXSubband *subband;
- JPXCodeBlock *cb;
- GBool haveSOD;
- Guint tileIdx, tilePartLen, tilePartIdx, nTileParts;
- GBool tilePartToEOC;
- Guint precinctSize, style;
- Guint n, nSBs, nx, ny, sbx0, sby0, comp, segLen;
- Guint i, j, k, cbX, cbY, r, pre, sb, cbi;
- int segType, level;
-
- // process the SOT marker segment
- if (!readUWord(&tileIdx) ||
- !readULong(&tilePartLen) ||
- !readUByte(&tilePartIdx) ||
- !readUByte(&nTileParts)) {
- error(getPos(), "Error in JPX SOT marker segment");
- return gFalse;
- }
-
- if (tileIdx >= img.nXTiles * img.nYTiles) {
- error(getPos(), "Weird tile index in JPX stream");
- return gFalse;
- }
-
- tilePartToEOC = tilePartLen == 0;
- tilePartLen -= 12; // subtract size of SOT segment
-
- haveSOD = gFalse;
- do {
- if (!readMarkerHdr(&segType, &segLen)) {
- error(getPos(), "Error in JPX tile-part codestream");
- return gFalse;
- }
- tilePartLen -= 2 + segLen;
- switch (segType) {
- case 0x52: // COD - coding style default
- if (!readUByte(&img.tiles[tileIdx].tileComps[0].style) ||
- !readUByte(&img.tiles[tileIdx].progOrder) ||
- !readUWord(&img.tiles[tileIdx].nLayers) ||
- !readUByte(&img.tiles[tileIdx].multiComp) ||
- !readUByte(&img.tiles[tileIdx].tileComps[0].nDecompLevels) ||
- !readUByte(&img.tiles[tileIdx].tileComps[0].codeBlockW) ||
- !readUByte(&img.tiles[tileIdx].tileComps[0].codeBlockH) ||
- !readUByte(&img.tiles[tileIdx].tileComps[0].codeBlockStyle) ||
- !readUByte(&img.tiles[tileIdx].tileComps[0].transform)) {
- error(getPos(), "Error in JPX COD marker segment");
- return gFalse;
- }
- img.tiles[tileIdx].tileComps[0].codeBlockW += 2;
- img.tiles[tileIdx].tileComps[0].codeBlockH += 2;
- for (comp = 0; comp < img.nComps; ++comp) {
- if (comp != 0) {
- img.tiles[tileIdx].tileComps[comp].style =
- img.tiles[tileIdx].tileComps[0].style;
- img.tiles[tileIdx].tileComps[comp].nDecompLevels =
- img.tiles[tileIdx].tileComps[0].nDecompLevels;
- img.tiles[tileIdx].tileComps[comp].codeBlockW =
- img.tiles[tileIdx].tileComps[0].codeBlockW;
- img.tiles[tileIdx].tileComps[comp].codeBlockH =
- img.tiles[tileIdx].tileComps[0].codeBlockH;
- img.tiles[tileIdx].tileComps[comp].codeBlockStyle =
- img.tiles[tileIdx].tileComps[0].codeBlockStyle;
- img.tiles[tileIdx].tileComps[comp].transform =
- img.tiles[tileIdx].tileComps[0].transform;
- }
- img.tiles[tileIdx].tileComps[comp].resLevels =
- (JPXResLevel *)greallocn(
- img.tiles[tileIdx].tileComps[comp].resLevels,
- (img.tiles[tileIdx].tileComps[comp].nDecompLevels + 1),
- sizeof(JPXResLevel));
- for (r = 0;
- r <= img.tiles[tileIdx].tileComps[comp].nDecompLevels;
- ++r) {
- img.tiles[tileIdx].tileComps[comp].resLevels[r].precincts = NULL;
- }
- }
- for (r = 0; r <= img.tiles[tileIdx].tileComps[0].nDecompLevels; ++r) {
- if (img.tiles[tileIdx].tileComps[0].style & 0x01) {
- if (!readUByte(&precinctSize)) {
- error(getPos(), "Error in JPX COD marker segment");
- return gFalse;
- }
- img.tiles[tileIdx].tileComps[0].resLevels[r].precinctWidth =
- precinctSize & 0x0f;
- img.tiles[tileIdx].tileComps[0].resLevels[r].precinctHeight =
- (precinctSize >> 4) & 0x0f;
- } else {
- img.tiles[tileIdx].tileComps[0].resLevels[r].precinctWidth = 15;
- img.tiles[tileIdx].tileComps[0].resLevels[r].precinctHeight = 15;
- }
- }
- for (comp = 1; comp < img.nComps; ++comp) {
- for (r = 0;
- r <= img.tiles[tileIdx].tileComps[comp].nDecompLevels;
- ++r) {
- img.tiles[tileIdx].tileComps[comp].resLevels[r].precinctWidth =
- img.tiles[tileIdx].tileComps[0].resLevels[r].precinctWidth;
- img.tiles[tileIdx].tileComps[comp].resLevels[r].precinctHeight =
- img.tiles[tileIdx].tileComps[0].resLevels[r].precinctHeight;
- }
- }
- break;
- case 0x53: // COC - coding style component
- if ((img.nComps > 256 && !readUWord(&comp)) ||
- (img.nComps <= 256 && !readUByte(&comp)) ||
- comp >= img.nComps ||
- !readUByte(&style) ||
- !readUByte(&img.tiles[tileIdx].tileComps[comp].nDecompLevels) ||
- !readUByte(&img.tiles[tileIdx].tileComps[comp].codeBlockW) ||
- !readUByte(&img.tiles[tileIdx].tileComps[comp].codeBlockH) ||
- !readUByte(&img.tiles[tileIdx].tileComps[comp].codeBlockStyle) ||
- !readUByte(&img.tiles[tileIdx].tileComps[comp].transform)) {
- error(getPos(), "Error in JPX COC marker segment");
- return gFalse;
- }
- img.tiles[tileIdx].tileComps[comp].style =
- (img.tiles[tileIdx].tileComps[comp].style & ~1) | (style & 1);
- img.tiles[tileIdx].tileComps[comp].codeBlockW += 2;
- img.tiles[tileIdx].tileComps[comp].codeBlockH += 2;
- img.tiles[tileIdx].tileComps[comp].resLevels =
- (JPXResLevel *)greallocn(
- img.tiles[tileIdx].tileComps[comp].resLevels,
- (img.tiles[tileIdx].tileComps[comp].nDecompLevels + 1),
- sizeof(JPXResLevel));
- for (r = 0; r <= img.tiles[tileIdx].tileComps[comp].nDecompLevels; ++r) {
- img.tiles[tileIdx].tileComps[comp].resLevels[r].precincts = NULL;
- }
- for (r = 0; r <= img.tiles[tileIdx].tileComps[comp].nDecompLevels; ++r) {
- if (img.tiles[tileIdx].tileComps[comp].style & 0x01) {
- if (!readUByte(&precinctSize)) {
- error(getPos(), "Error in JPX COD marker segment");
- return gFalse;
- }
- img.tiles[tileIdx].tileComps[comp].resLevels[r].precinctWidth =
- precinctSize & 0x0f;
- img.tiles[tileIdx].tileComps[comp].resLevels[r].precinctHeight =
- (precinctSize >> 4) & 0x0f;
- } else {
- img.tiles[tileIdx].tileComps[comp].resLevels[r].precinctWidth = 15;
- img.tiles[tileIdx].tileComps[comp].resLevels[r].precinctHeight = 15;
- }
- }
- break;
- case 0x5c: // QCD - quantization default
- if (!readUByte(&img.tiles[tileIdx].tileComps[0].quantStyle)) {
- error(getPos(), "Error in JPX QCD marker segment");
- return gFalse;
- }
- if ((img.tiles[tileIdx].tileComps[0].quantStyle & 0x1f) == 0x00) {
- img.tiles[tileIdx].tileComps[0].nQuantSteps =
- segLen - 3;
- img.tiles[tileIdx].tileComps[0].quantSteps =
- (Guint *)greallocn(img.tiles[tileIdx].tileComps[0].quantSteps,
- img.tiles[tileIdx].tileComps[0].nQuantSteps,
- sizeof(Guint));
- for (i = 0; i < img.tiles[tileIdx].tileComps[0].nQuantSteps; ++i) {
- if (!readUByte(&img.tiles[tileIdx].tileComps[0].quantSteps[i])) {
- error(getPos(), "Error in JPX QCD marker segment");
- return gFalse;
- }
- }
- } else if ((img.tiles[tileIdx].tileComps[0].quantStyle & 0x1f) == 0x01) {
- img.tiles[tileIdx].tileComps[0].nQuantSteps = 1;
- img.tiles[tileIdx].tileComps[0].quantSteps =
- (Guint *)greallocn(img.tiles[tileIdx].tileComps[0].quantSteps,
- img.tiles[tileIdx].tileComps[0].nQuantSteps,
- sizeof(Guint));
- if (!readUWord(&img.tiles[tileIdx].tileComps[0].quantSteps[0])) {
- error(getPos(), "Error in JPX QCD marker segment");
- return gFalse;
- }
- } else if ((img.tiles[tileIdx].tileComps[0].quantStyle & 0x1f) == 0x02) {
- img.tiles[tileIdx].tileComps[0].nQuantSteps = (segLen - 3) / 2;
- img.tiles[tileIdx].tileComps[0].quantSteps =
- (Guint *)greallocn(img.tiles[tileIdx].tileComps[0].quantSteps,
- img.tiles[tileIdx].tileComps[0].nQuantSteps,
- sizeof(Guint));
- for (i = 0; i < img.tiles[tileIdx].tileComps[0].nQuantSteps; ++i) {
- if (!readUWord(&img.tiles[tileIdx].tileComps[0].quantSteps[i])) {
- error(getPos(), "Error in JPX QCD marker segment");
- return gFalse;
- }
- }
- } else {
- error(getPos(), "Error in JPX QCD marker segment");
- return gFalse;
- }
- for (comp = 1; comp < img.nComps; ++comp) {
- img.tiles[tileIdx].tileComps[comp].quantStyle =
- img.tiles[tileIdx].tileComps[0].quantStyle;
- img.tiles[tileIdx].tileComps[comp].nQuantSteps =
- img.tiles[tileIdx].tileComps[0].nQuantSteps;
- img.tiles[tileIdx].tileComps[comp].quantSteps =
- (Guint *)greallocn(img.tiles[tileIdx].tileComps[comp].quantSteps,
- img.tiles[tileIdx].tileComps[0].nQuantSteps,
- sizeof(Guint));
- for (j = 0; j < img.tiles[tileIdx].tileComps[0].nQuantSteps; ++j) {
- img.tiles[tileIdx].tileComps[comp].quantSteps[j] =
- img.tiles[tileIdx].tileComps[0].quantSteps[j];
- }
- }
- break;
- case 0x5d: // QCC - quantization component
- if ((img.nComps > 256 && !readUWord(&comp)) ||
- (img.nComps <= 256 && !readUByte(&comp)) ||
- comp >= img.nComps ||
- !readUByte(&img.tiles[tileIdx].tileComps[comp].quantStyle)) {
- error(getPos(), "Error in JPX QCC marker segment");
- return gFalse;
- }
- if ((img.tiles[tileIdx].tileComps[comp].quantStyle & 0x1f) == 0x00) {
- img.tiles[tileIdx].tileComps[comp].nQuantSteps =
- segLen - (img.nComps > 256 ? 5 : 4);
- img.tiles[tileIdx].tileComps[comp].quantSteps =
- (Guint *)greallocn(img.tiles[tileIdx].tileComps[comp].quantSteps,
- img.tiles[tileIdx].tileComps[comp].nQuantSteps,
- sizeof(Guint));
- for (i = 0; i < img.tiles[tileIdx].tileComps[comp].nQuantSteps; ++i) {
- if (!readUByte(&img.tiles[tileIdx].tileComps[comp].quantSteps[i])) {
- error(getPos(), "Error in JPX QCC marker segment");
- return gFalse;
- }
- }
- } else if ((img.tiles[tileIdx].tileComps[comp].quantStyle & 0x1f)
- == 0x01) {
- img.tiles[tileIdx].tileComps[comp].nQuantSteps = 1;
- img.tiles[tileIdx].tileComps[comp].quantSteps =
- (Guint *)greallocn(img.tiles[tileIdx].tileComps[comp].quantSteps,
- img.tiles[tileIdx].tileComps[comp].nQuantSteps,
- sizeof(Guint));
- if (!readUWord(&img.tiles[tileIdx].tileComps[comp].quantSteps[0])) {
- error(getPos(), "Error in JPX QCC marker segment");
- return gFalse;
- }
- } else if ((img.tiles[tileIdx].tileComps[comp].quantStyle & 0x1f)
- == 0x02) {
- img.tiles[tileIdx].tileComps[comp].nQuantSteps =
- (segLen - (img.nComps > 256 ? 5 : 4)) / 2;
- img.tiles[tileIdx].tileComps[comp].quantSteps =
- (Guint *)greallocn(img.tiles[tileIdx].tileComps[comp].quantSteps,
- img.tiles[tileIdx].tileComps[comp].nQuantSteps,
- sizeof(Guint));
- for (i = 0; i < img.tiles[tileIdx].tileComps[comp].nQuantSteps; ++i) {
- if (!readUWord(&img.tiles[tileIdx].tileComps[comp].quantSteps[i])) {
- error(getPos(), "Error in JPX QCD marker segment");
- return gFalse;
- }
- }
- } else {
- error(getPos(), "Error in JPX QCC marker segment");
- return gFalse;
- }
- break;
- case 0x5e: // RGN - region of interest
-#if 1 //~ ROI is unimplemented
- fprintf(stderr, "RGN\n");
- for (i = 0; i < segLen - 2; ++i) {
- if (str->getChar() == EOF) {
- error(getPos(), "Error in JPX PPM marker segment");
- return gFalse;
- }
- }
-#else
- if ((img.nComps > 256 && !readUWord(&comp)) ||
- (img.nComps <= 256 && !readUByte(&comp)) ||
- comp >= img.nComps ||
- !readUByte(&compInfo[comp].roi.style) ||
- !readUByte(&compInfo[comp].roi.shift)) {
- error(getPos(), "Error in JPX RGN marker segment");
- return gFalse;
- }
-#endif
- break;
- case 0x5f: // POC - progression order change
-#if 1 //~ progression order changes are unimplemented
- fprintf(stderr, "POC\n");
- for (i = 0; i < segLen - 2; ++i) {
- if (str->getChar() == EOF) {
- error(getPos(), "Error in JPX PPM marker segment");
- return gFalse;
- }
- }
-#else
- nTileProgs = (segLen - 2) / (img.nComps > 256 ? 9 : 7);
- tileProgs = (JPXProgOrder *)gmallocn(nTileProgs, sizeof(JPXProgOrder));
- for (i = 0; i < nTileProgs; ++i) {
- if (!readUByte(&tileProgs[i].startRes) ||
- !(img.nComps > 256 && readUWord(&tileProgs[i].startComp)) ||
- !(img.nComps <= 256 && readUByte(&tileProgs[i].startComp)) ||
- !readUWord(&tileProgs[i].endLayer) ||
- !readUByte(&tileProgs[i].endRes) ||
- !(img.nComps > 256 && readUWord(&tileProgs[i].endComp)) ||
- !(img.nComps <= 256 && readUByte(&tileProgs[i].endComp)) ||
- !readUByte(&tileProgs[i].progOrder)) {
- error(getPos(), "Error in JPX POC marker segment");
- return gFalse;
- }
- }
-#endif
- break;
- case 0x61: // PPT - packed packet headers, tile-part hdr
-#if 1 //~ packed packet headers are unimplemented
- fprintf(stderr, "PPT\n");
- for (i = 0; i < segLen - 2; ++i) {
- if (str->getChar() == EOF) {
- error(getPos(), "Error in JPX PPT marker segment");
- return gFalse;
- }
- }
-#endif
- case 0x58: // PLT - packet length, tile-part header
- // skipped
- for (i = 0; i < segLen - 2; ++i) {
- if (str->getChar() == EOF) {
- error(getPos(), "Error in JPX PLT marker segment");
- return gFalse;
- }
- }
- break;
- case 0x64: // COM - comment
- // skipped
- for (i = 0; i < segLen - 2; ++i) {
- if (str->getChar() == EOF) {
- error(getPos(), "Error in JPX COM marker segment");
- return gFalse;
- }
- }
- break;
- case 0x93: // SOD - start of data
- haveSOD = gTrue;
- break;
- default:
- error(getPos(), "Unknown marker segment %02x in JPX tile-part stream",
- segType);
- for (i = 0; i < segLen - 2; ++i) {
- if (str->getChar() == EOF) {
- break;
- }
- }
- break;
- }
- } while (!haveSOD);
-
- //----- initialize the tile, precincts, and code-blocks
- if (tilePartIdx == 0) {
- tile = &img.tiles[tileIdx];
- i = tileIdx / img.nXTiles;
- j = tileIdx % img.nXTiles;
- if ((tile->x0 = img.xTileOffset + j * img.xTileSize) < img.xOffset) {
- tile->x0 = img.xOffset;
- }
- if ((tile->y0 = img.yTileOffset + i * img.yTileSize) < img.yOffset) {
- tile->y0 = img.yOffset;
- }
- if ((tile->x1 = img.xTileOffset + (j + 1) * img.xTileSize) > img.xSize) {
- tile->x1 = img.xSize;
- }
- if ((tile->y1 = img.yTileOffset + (i + 1) * img.yTileSize) > img.ySize) {
- tile->y1 = img.ySize;
- }
- tile->comp = 0;
- tile->res = 0;
- tile->precinct = 0;
- tile->layer = 0;
- tile->maxNDecompLevels = 0;
- for (comp = 0; comp < img.nComps; ++comp) {
- tileComp = &tile->tileComps[comp];
- if (tileComp->nDecompLevels > tile->maxNDecompLevels) {
- tile->maxNDecompLevels = tileComp->nDecompLevels;
- }
- tileComp->x0 = jpxCeilDiv(tile->x0, tileComp->hSep);
- tileComp->y0 = jpxCeilDiv(tile->y0, tileComp->hSep);
- tileComp->x1 = jpxCeilDiv(tile->x1, tileComp->hSep);
- tileComp->y1 = jpxCeilDiv(tile->y1, tileComp->hSep);
- tileComp->cbW = 1 << tileComp->codeBlockW;
- tileComp->cbH = 1 << tileComp->codeBlockH;
- tileComp->data = (int *)gmallocn((tileComp->x1 - tileComp->x0) *
- (tileComp->y1 - tileComp->y0),
- sizeof(int));
- if (tileComp->x1 - tileComp->x0 > tileComp->y1 - tileComp->y0) {
- n = tileComp->x1 - tileComp->x0;
- } else {
- n = tileComp->y1 - tileComp->y0;
- }
- tileComp->buf = (int *)gmallocn(n + 8, sizeof(int));
- for (r = 0; r <= tileComp->nDecompLevels; ++r) {
- resLevel = &tileComp->resLevels[r];
- k = r == 0 ? tileComp->nDecompLevels
- : tileComp->nDecompLevels - r + 1;
- resLevel->x0 = jpxCeilDivPow2(tileComp->x0, k);
- resLevel->y0 = jpxCeilDivPow2(tileComp->y0, k);
- resLevel->x1 = jpxCeilDivPow2(tileComp->x1, k);
- resLevel->y1 = jpxCeilDivPow2(tileComp->y1, k);
- if (r == 0) {
- resLevel->bx0[0] = resLevel->x0;
- resLevel->by0[0] = resLevel->y0;
- resLevel->bx1[0] = resLevel->x1;
- resLevel->by1[0] = resLevel->y1;
- } else {
- resLevel->bx0[0] = jpxCeilDivPow2(tileComp->x0 - (1 << (k-1)), k);
- resLevel->by0[0] = resLevel->y0;
- resLevel->bx1[0] = jpxCeilDivPow2(tileComp->x1 - (1 << (k-1)), k);
- resLevel->by1[0] = resLevel->y1;
- resLevel->bx0[1] = resLevel->x0;
- resLevel->by0[1] = jpxCeilDivPow2(tileComp->y0 - (1 << (k-1)), k);
- resLevel->bx1[1] = resLevel->x1;
- resLevel->by1[1] = jpxCeilDivPow2(tileComp->y1 - (1 << (k-1)), k);
- resLevel->bx0[2] = jpxCeilDivPow2(tileComp->x0 - (1 << (k-1)), k);
- resLevel->by0[2] = jpxCeilDivPow2(tileComp->y0 - (1 << (k-1)), k);
- resLevel->bx1[2] = jpxCeilDivPow2(tileComp->x1 - (1 << (k-1)), k);
- resLevel->by1[2] = jpxCeilDivPow2(tileComp->y1 - (1 << (k-1)), k);
- }
- resLevel->precincts = (JPXPrecinct *)gmallocn(1, sizeof(JPXPrecinct));
- for (pre = 0; pre < 1; ++pre) {
- precinct = &resLevel->precincts[pre];
- precinct->x0 = resLevel->x0;
- precinct->y0 = resLevel->y0;
- precinct->x1 = resLevel->x1;
- precinct->y1 = resLevel->y1;
- nSBs = r == 0 ? 1 : 3;
- precinct->subbands =
- (JPXSubband *)gmallocn(nSBs, sizeof(JPXSubband));
- for (sb = 0; sb < nSBs; ++sb) {
- subband = &precinct->subbands[sb];
- subband->x0 = resLevel->bx0[sb];
- subband->y0 = resLevel->by0[sb];
- subband->x1 = resLevel->bx1[sb];
- subband->y1 = resLevel->by1[sb];
- subband->nXCBs = jpxCeilDivPow2(subband->x1,
- tileComp->codeBlockW)
- - jpxFloorDivPow2(subband->x0,
- tileComp->codeBlockW);
- subband->nYCBs = jpxCeilDivPow2(subband->y1,
- tileComp->codeBlockH)
- - jpxFloorDivPow2(subband->y0,
- tileComp->codeBlockH);
- n = subband->nXCBs > subband->nYCBs ? subband->nXCBs
- : subband->nYCBs;
- for (subband->maxTTLevel = 0, --n;
- n;
- ++subband->maxTTLevel, n >>= 1) ;
- n = 0;
- for (level = subband->maxTTLevel; level >= 0; --level) {
- nx = jpxCeilDivPow2(subband->nXCBs, level);
- ny = jpxCeilDivPow2(subband->nYCBs, level);
- n += nx * ny;
- }
- subband->inclusion =
- (JPXTagTreeNode *)gmallocn(n, sizeof(JPXTagTreeNode));
- subband->zeroBitPlane =
- (JPXTagTreeNode *)gmallocn(n, sizeof(JPXTagTreeNode));
- for (k = 0; k < n; ++k) {
- subband->inclusion[k].finished = gFalse;
- subband->inclusion[k].val = 0;
- subband->zeroBitPlane[k].finished = gFalse;
- subband->zeroBitPlane[k].val = 0;
- }
- subband->cbs = (JPXCodeBlock *)gmallocn(subband->nXCBs *
- subband->nYCBs,
- sizeof(JPXCodeBlock));
- sbx0 = jpxFloorDivPow2(subband->x0, tileComp->codeBlockW);
- sby0 = jpxFloorDivPow2(subband->y0, tileComp->codeBlockH);
- cb = subband->cbs;
- for (cbY = 0; cbY < subband->nYCBs; ++cbY) {
- for (cbX = 0; cbX < subband->nXCBs; ++cbX) {
- cb->x0 = (sbx0 + cbX) << tileComp->codeBlockW;
- cb->x1 = cb->x0 + tileComp->cbW;
- if (subband->x0 > cb->x0) {
- cb->x0 = subband->x0;
- }
- if (subband->x1 < cb->x1) {
- cb->x1 = subband->x1;
- }
- cb->y0 = (sby0 + cbY) << tileComp->codeBlockH;
- cb->y1 = cb->y0 + tileComp->cbH;
- if (subband->y0 > cb->y0) {
- cb->y0 = subband->y0;
- }
- if (subband->y1 < cb->y1) {
- cb->y1 = subband->y1;
- }
- cb->seen = gFalse;
- cb->lBlock = 3;
- cb->nextPass = jpxPassCleanup;
- cb->nZeroBitPlanes = 0;
- cb->coeffs =
- (JPXCoeff *)gmallocn((1 << (tileComp->codeBlockW
- + tileComp->codeBlockH)),
- sizeof(JPXCoeff));
- for (cbi = 0;
- cbi < (Guint)(1 << (tileComp->codeBlockW
- + tileComp->codeBlockH));
- ++cbi) {
- cb->coeffs[cbi].flags = 0;
- cb->coeffs[cbi].len = 0;
- cb->coeffs[cbi].mag = 0;
- }
- cb->arithDecoder = NULL;
- cb->stats = NULL;
- ++cb;
- }
- }
- }
- }
- }
- }
- }
-
- return readTilePartData(tileIdx, tilePartLen, tilePartToEOC);
-}
-
-GBool JPXStream::readTilePartData(Guint tileIdx,
- Guint tilePartLen, GBool tilePartToEOC) {
- JPXTile *tile;
- JPXTileComp *tileComp;
- JPXResLevel *resLevel;
- JPXPrecinct *precinct;
- JPXSubband *subband;
- JPXCodeBlock *cb;
- Guint ttVal;
- Guint bits, cbX, cbY, nx, ny, i, j, n, sb;
- int level;
-
- tile = &img.tiles[tileIdx];
-
- // read all packets from this tile-part
- while (1) {
- if (tilePartToEOC) {
- //~ peek for an EOC marker
- } else if (tilePartLen == 0) {
- break;
- }
-
- tileComp = &tile->tileComps[tile->comp];
- resLevel = &tileComp->resLevels[tile->res];
- precinct = &resLevel->precincts[tile->precinct];
-
- //----- packet header
-
- // zero-length flag
- if (!readBits(1, &bits)) {
- goto err;
- }
- if (!bits) {
- // packet is empty -- clear all code-block inclusion flags
- for (sb = 0; sb < (tile->res == 0 ? 1 : 3); ++sb) {
- subband = &precinct->subbands[sb];
- for (cbY = 0; cbY < subband->nYCBs; ++cbY) {
- for (cbX = 0; cbX < subband->nXCBs; ++cbX) {
- cb = &subband->cbs[cbY * subband->nXCBs + cbX];
- cb->included = gFalse;
- }
- }
- }
- } else {
-
- for (sb = 0; sb < (tile->res == 0 ? 1 : 3); ++sb) {
- subband = &precinct->subbands[sb];
- for (cbY = 0; cbY < subband->nYCBs; ++cbY) {
- for (cbX = 0; cbX < subband->nXCBs; ++cbX) {
- cb = &subband->cbs[cbY * subband->nXCBs + cbX];
-
- // skip code-blocks with no coefficients
- if (cb->x0 >= cb->x1 || cb->y0 >= cb->y1) {
- cb->included = gFalse;
- continue;
- }
-
- // code-block inclusion
- if (cb->seen) {
- if (!readBits(1, &cb->included)) {
- goto err;
- }
- } else {
- ttVal = 0;
- i = 0;
- for (level = subband->maxTTLevel; level >= 0; --level) {
- nx = jpxCeilDivPow2(subband->nXCBs, level);
- ny = jpxCeilDivPow2(subband->nYCBs, level);
- j = i + (cbY >> level) * nx + (cbX >> level);
- if (!subband->inclusion[j].finished &&
- !subband->inclusion[j].val) {
- subband->inclusion[j].val = ttVal;
- } else {
- ttVal = subband->inclusion[j].val;
- }
- while (!subband->inclusion[j].finished &&
- ttVal <= tile->layer) {
- if (!readBits(1, &bits)) {
- goto err;
- }
- if (bits == 1) {
- subband->inclusion[j].finished = gTrue;
- } else {
- ++ttVal;
- }
- }
- subband->inclusion[j].val = ttVal;
- if (ttVal > tile->layer) {
- break;
- }
- i += nx * ny;
- }
- cb->included = level < 0;
- }
-
- if (cb->included) {
-
- // zero bit-plane count
- if (!cb->seen) {
- ttVal = 0;
- i = 0;
- for (level = subband->maxTTLevel; level >= 0; --level) {
- nx = jpxCeilDivPow2(subband->nXCBs, level);
- ny = jpxCeilDivPow2(subband->nYCBs, level);
- j = i + (cbY >> level) * nx + (cbX >> level);
- if (!subband->zeroBitPlane[j].finished &&
- !subband->zeroBitPlane[j].val) {
- subband->zeroBitPlane[j].val = ttVal;
- } else {
- ttVal = subband->zeroBitPlane[j].val;
- }
- while (!subband->zeroBitPlane[j].finished) {
- if (!readBits(1, &bits)) {
- goto err;
- }
- if (bits == 1) {
- subband->zeroBitPlane[j].finished = gTrue;
- } else {
- ++ttVal;
- }
- }
- subband->zeroBitPlane[j].val = ttVal;
- i += nx * ny;
- }
- cb->nZeroBitPlanes = ttVal;
- }
-
- // number of coding passes
- if (!readBits(1, &bits)) {
- goto err;
- }
- if (bits == 0) {
- cb->nCodingPasses = 1;
- } else {
- if (!readBits(1, &bits)) {
- goto err;
- }
- if (bits == 0) {
- cb->nCodingPasses = 2;
- } else {
- if (!readBits(2, &bits)) {
- goto err;
- }
- if (bits < 3) {
- cb->nCodingPasses = 3 + bits;
- } else {
- if (!readBits(5, &bits)) {
- goto err;
- }
- if (bits < 31) {
- cb->nCodingPasses = 6 + bits;
- } else {
- if (!readBits(7, &bits)) {
- goto err;
- }
- cb->nCodingPasses = 37 + bits;
- }
- }
- }
- }
-
- // update Lblock
- while (1) {
- if (!readBits(1, &bits)) {
- goto err;
- }
- if (!bits) {
- break;
- }
- ++cb->lBlock;
- }
-
- // length of compressed data
- //~ deal with multiple codeword segments
- for (n = cb->lBlock, i = cb->nCodingPasses >> 1;
- i;
- ++n, i >>= 1) ;
- if (!readBits(n, &cb->dataLen)) {
- goto err;
- }
- }
- }
- }
- }
- }
- tilePartLen -= byteCount;
- clearBitBuf();
-
- //----- packet data
-
- for (sb = 0; sb < (tile->res == 0 ? 1 : 3); ++sb) {
- subband = &precinct->subbands[sb];
- for (cbY = 0; cbY < subband->nYCBs; ++cbY) {
- for (cbX = 0; cbX < subband->nXCBs; ++cbX) {
- cb = &subband->cbs[cbY * subband->nXCBs + cbX];
- if (cb->included) {
- if (!readCodeBlockData(tileComp, resLevel, precinct, subband,
- tile->res, sb, cb)) {
- return gFalse;
- }
- tilePartLen -= cb->dataLen;
- cb->seen = gTrue;
- }
- }
- }
- }
-
- //----- next packet
-
- switch (tile->progOrder) {
- case 0: // layer, resolution level, component, precinct
- if (++tile->comp == img.nComps) {
- tile->comp = 0;
- if (++tile->res == tile->maxNDecompLevels + 1) {
- tile->res = 0;
- if (++tile->layer == tile->nLayers) {
- tile->layer = 0;
- }
- }
- }
- break;
- case 1: // resolution level, layer, component, precinct
- if (++tile->comp == img.nComps) {
- tile->comp = 0;
- if (++tile->layer == tile->nLayers) {
- tile->layer = 0;
- if (++tile->res == tile->maxNDecompLevels + 1) {
- tile->res = 0;
- }
- }
- }
- break;
- case 2: // resolution level, precinct, component, layer
- //~ this isn't correct -- see B.12.1.3
- if (++tile->layer == tile->nLayers) {
- tile->layer = 0;
- if (++tile->comp == img.nComps) {
- tile->comp = 0;
- if (++tile->res == tile->maxNDecompLevels + 1) {
- tile->res = 0;
- }
- }
- }
- break;
- case 3: // precinct, component, resolution level, layer
- //~ this isn't correct -- see B.12.1.4
- if (++tile->layer == tile->nLayers) {
- tile->layer = 0;
- if (++tile->res == tile->maxNDecompLevels + 1) {
- tile->res = 0;
- if (++tile->comp == img.nComps) {
- tile->comp = 0;
- }
- }
- }
- break;
- case 4: // component, precinct, resolution level, layer
- //~ this isn't correct -- see B.12.1.5
- if (++tile->layer == tile->nLayers) {
- tile->layer = 0;
- if (++tile->res == tile->maxNDecompLevels + 1) {
- tile->res = 0;
- if (++tile->comp == img.nComps) {
- tile->comp = 0;
- }
- }
- }
- break;
- }
- }
-
- return gTrue;
-
- err:
- error(getPos(), "Error in JPX stream");
- return gFalse;
-}
-
-GBool JPXStream::readCodeBlockData(JPXTileComp *tileComp,
- JPXResLevel *resLevel,
- JPXPrecinct *precinct,
- JPXSubband *subband,
- Guint res, Guint sb,
- JPXCodeBlock *cb) {
- JPXCoeff *coeff0, *coeff1, *coeff;
- Guint horiz, vert, diag, all, cx, xorBit;
- int horizSign, vertSign;
- Guint i, x, y0, y1, y2;
-
- if (cb->arithDecoder) {
- cb->arithDecoder->restart(cb->dataLen);
- } else {
- cb->arithDecoder = new JArithmeticDecoder();
- cb->arithDecoder->setStream(str, cb->dataLen);
- cb->arithDecoder->start();
- cb->stats = new JArithmeticDecoderStats(jpxNContexts);
- cb->stats->setEntry(jpxContextSigProp, 4, 0);
- cb->stats->setEntry(jpxContextRunLength, 3, 0);
- cb->stats->setEntry(jpxContextUniform, 46, 0);
- }
-
- for (i = 0; i < cb->nCodingPasses; ++i) {
- switch (cb->nextPass) {
-
- //----- significance propagation pass
- case jpxPassSigProp:
- for (y0 = cb->y0, coeff0 = cb->coeffs;
- y0 < cb->y1;
- y0 += 4, coeff0 += 4 << tileComp->codeBlockW) {
- for (x = cb->x0, coeff1 = coeff0;
- x < cb->x1;
- ++x, ++coeff1) {
- for (y1 = 0, coeff = coeff1;
- y1 < 4 && y0+y1 < cb->y1;
- ++y1, coeff += tileComp->cbW) {
- if (!(coeff->flags & jpxCoeffSignificant)) {
- horiz = vert = diag = 0;
- horizSign = vertSign = 2;
- if (x > cb->x0) {
- if (coeff[-1].flags & jpxCoeffSignificant) {
- ++horiz;
- horizSign += (coeff[-1].flags & jpxCoeffSign) ? -1 : 1;
- }
- if (y0+y1 > cb->y0) {
- diag += (coeff[-(int)tileComp->cbW - 1].flags
- >> jpxCoeffSignificantB) & 1;
- }
- if (y0+y1 < cb->y1 - 1) {
- diag += (coeff[tileComp->cbW - 1].flags
- >> jpxCoeffSignificantB) & 1;
- }
- }
- if (x < cb->x1 - 1) {
- if (coeff[1].flags & jpxCoeffSignificant) {
- ++horiz;
- horizSign += (coeff[1].flags & jpxCoeffSign) ? -1 : 1;
- }
- if (y0+y1 > cb->y0) {
- diag += (coeff[-(int)tileComp->cbW + 1].flags
- >> jpxCoeffSignificantB) & 1;
- }
- if (y0+y1 < cb->y1 - 1) {
- diag += (coeff[tileComp->cbW + 1].flags
- >> jpxCoeffSignificantB) & 1;
- }
- }
- if (y0+y1 > cb->y0) {
- if (coeff[-(int)tileComp->cbW].flags & jpxCoeffSignificant) {
- ++vert;
- vertSign += (coeff[-(int)tileComp->cbW].flags & jpxCoeffSign)
- ? -1 : 1;
- }
- }
- if (y0+y1 < cb->y1 - 1) {
- if (coeff[tileComp->cbW].flags & jpxCoeffSignificant) {
- ++vert;
- vertSign += (coeff[tileComp->cbW].flags & jpxCoeffSign)
- ? -1 : 1;
- }
- }
- cx = sigPropContext[horiz][vert][diag][res == 0 ? 1 : sb];
- if (cx != 0) {
- if (cb->arithDecoder->decodeBit(cx, cb->stats)) {
- coeff->flags |= jpxCoeffSignificant | jpxCoeffFirstMagRef;
- coeff->mag = (coeff->mag << 1) | 1;
- cx = signContext[horizSign][vertSign][0];
- xorBit = signContext[horizSign][vertSign][1];
- if (cb->arithDecoder->decodeBit(cx, cb->stats) ^ xorBit) {
- coeff->flags |= jpxCoeffSign;
- }
- }
- ++coeff->len;
- coeff->flags |= jpxCoeffTouched;
- }
- }
- }
- }
- }
- ++cb->nextPass;
- break;
-
- //----- magnitude refinement pass
- case jpxPassMagRef:
- for (y0 = cb->y0, coeff0 = cb->coeffs;
- y0 < cb->y1;
- y0 += 4, coeff0 += 4 << tileComp->codeBlockW) {
- for (x = cb->x0, coeff1 = coeff0;
- x < cb->x1;
- ++x, ++coeff1) {
- for (y1 = 0, coeff = coeff1;
- y1 < 4 && y0+y1 < cb->y1;
- ++y1, coeff += tileComp->cbW) {
- if ((coeff->flags & jpxCoeffSignificant) &&
- !(coeff->flags & jpxCoeffTouched)) {
- if (coeff->flags & jpxCoeffFirstMagRef) {
- all = 0;
- if (x > cb->x0) {
- all += (coeff[-1].flags >> jpxCoeffSignificantB) & 1;
- if (y0+y1 > cb->y0) {
- all += (coeff[-(int)tileComp->cbW - 1].flags
- >> jpxCoeffSignificantB) & 1;
- }
- if (y0+y1 < cb->y1 - 1) {
- all += (coeff[tileComp->cbW - 1].flags
- >> jpxCoeffSignificantB) & 1;
- }
- }
- if (x < cb->x1 - 1) {
- all += (coeff[1].flags >> jpxCoeffSignificantB) & 1;
- if (y0+y1 > cb->y0) {
- all += (coeff[-(int)tileComp->cbW + 1].flags
- >> jpxCoeffSignificantB) & 1;
- }
- if (y0+y1 < cb->y1 - 1) {
- all += (coeff[tileComp->cbW + 1].flags
- >> jpxCoeffSignificantB) & 1;
- }
- }
- if (y0+y1 > cb->y0) {
- all += (coeff[-(int)tileComp->cbW].flags
- >> jpxCoeffSignificantB) & 1;
- }
- if (y0+y1 < cb->y1 - 1) {
- all += (coeff[tileComp->cbW].flags
- >> jpxCoeffSignificantB) & 1;
- }
- cx = all ? 15 : 14;
- } else {
- cx = 16;
- }
- coeff->mag = (coeff->mag << 1) |
- cb->arithDecoder->decodeBit(cx, cb->stats);
- ++coeff->len;
- coeff->flags |= jpxCoeffTouched;
- coeff->flags &= ~jpxCoeffFirstMagRef;
- }
- }
- }
- }
- ++cb->nextPass;
- break;
-
- //----- cleanup pass
- case jpxPassCleanup:
- for (y0 = cb->y0, coeff0 = cb->coeffs;
- y0 < cb->y1;
- y0 += 4, coeff0 += 4 << tileComp->codeBlockW) {
- for (x = cb->x0, coeff1 = coeff0;
- x < cb->x1;
- ++x, ++coeff1) {
- y1 = 0;
- if (y0 + 3 < cb->y1 &&
- !(coeff1->flags & jpxCoeffTouched) &&
- !(coeff1[tileComp->cbW].flags & jpxCoeffTouched) &&
- !(coeff1[2 * tileComp->cbW].flags & jpxCoeffTouched) &&
- !(coeff1[3 * tileComp->cbW].flags & jpxCoeffTouched) &&
- (x == cb->x0 || y0 == cb->y0 ||
- !(coeff1[-(int)tileComp->cbW - 1].flags
- & jpxCoeffSignificant)) &&
- (y0 == cb->y0 ||
- !(coeff1[-(int)tileComp->cbW].flags
- & jpxCoeffSignificant)) &&
- (x == cb->x1 - 1 || y0 == cb->y0 ||
- !(coeff1[-(int)tileComp->cbW + 1].flags
- & jpxCoeffSignificant)) &&
- (x == cb->x0 ||
- (!(coeff1[-1].flags & jpxCoeffSignificant) &&
- !(coeff1[tileComp->cbW - 1].flags
- & jpxCoeffSignificant) &&
- !(coeff1[2 * tileComp->cbW - 1].flags
- & jpxCoeffSignificant) &&
- !(coeff1[3 * tileComp->cbW - 1].flags
- & jpxCoeffSignificant))) &&
- (x == cb->x1 - 1 ||
- (!(coeff1[1].flags & jpxCoeffSignificant) &&
- !(coeff1[tileComp->cbW + 1].flags
- & jpxCoeffSignificant) &&
- !(coeff1[2 * tileComp->cbW + 1].flags
- & jpxCoeffSignificant) &&
- !(coeff1[3 * tileComp->cbW + 1].flags
- & jpxCoeffSignificant))) &&
- (x == cb->x0 || y0+4 == cb->y1 ||
- !(coeff1[4 * tileComp->cbW - 1].flags & jpxCoeffSignificant)) &&
- (y0+4 == cb->y1 ||
- !(coeff1[4 * tileComp->cbW].flags & jpxCoeffSignificant)) &&
- (x == cb->x1 - 1 || y0+4 == cb->y1 ||
- !(coeff1[4 * tileComp->cbW + 1].flags
- & jpxCoeffSignificant))) {
- if (cb->arithDecoder->decodeBit(jpxContextRunLength, cb->stats)) {
- y1 = cb->arithDecoder->decodeBit(jpxContextUniform, cb->stats);
- y1 = (y1 << 1) |
- cb->arithDecoder->decodeBit(jpxContextUniform, cb->stats);
- for (y2 = 0, coeff = coeff1;
- y2 < y1;
- ++y2, coeff += tileComp->cbW) {
- ++coeff->len;
- }
- coeff->flags |= jpxCoeffSignificant | jpxCoeffFirstMagRef;
- coeff->mag = (coeff->mag << 1) | 1;
- ++coeff->len;
- cx = signContext[2][2][0];
- xorBit = signContext[2][2][1];
- if (cb->arithDecoder->decodeBit(cx, cb->stats) ^ xorBit) {
- coeff->flags |= jpxCoeffSign;
- }
- ++y1;
- } else {
- for (y1 = 0, coeff = coeff1;
- y1 < 4;
- ++y1, coeff += tileComp->cbW) {
- ++coeff->len;
- }
- y1 = 4;
- }
- }
- for (coeff = &coeff1[y1 << tileComp->codeBlockW];
- y1 < 4 && y0 + y1 < cb->y1;
- ++y1, coeff += tileComp->cbW) {
- if (!(coeff->flags & jpxCoeffTouched)) {
- horiz = vert = diag = 0;
- horizSign = vertSign = 2;
- if (x > cb->x0) {
- if (coeff[-1].flags & jpxCoeffSignificant) {
- ++horiz;
- horizSign += (coeff[-1].flags & jpxCoeffSign) ? -1 : 1;
- }
- if (y0+y1 > cb->y0) {
- diag += (coeff[-(int)tileComp->cbW - 1].flags
- >> jpxCoeffSignificantB) & 1;
- }
- if (y0+y1 < cb->y1 - 1) {
- diag += (coeff[tileComp->cbW - 1].flags
- >> jpxCoeffSignificantB) & 1;
- }
- }
- if (x < cb->x1 - 1) {
- if (coeff[1].flags & jpxCoeffSignificant) {
- ++horiz;
- horizSign += (coeff[1].flags & jpxCoeffSign) ? -1 : 1;
- }
- if (y0+y1 > cb->y0) {
- diag += (coeff[-(int)tileComp->cbW + 1].flags
- >> jpxCoeffSignificantB) & 1;
- }
- if (y0+y1 < cb->y1 - 1) {
- diag += (coeff[tileComp->cbW + 1].flags
- >> jpxCoeffSignificantB) & 1;
- }
- }
- if (y0+y1 > cb->y0) {
- if (coeff[-(int)tileComp->cbW].flags & jpxCoeffSignificant) {
- ++vert;
- vertSign += (coeff[-(int)tileComp->cbW].flags & jpxCoeffSign)
- ? -1 : 1;
- }
- }
- if (y0+y1 < cb->y1 - 1) {
- if (coeff[tileComp->cbW].flags & jpxCoeffSignificant) {
- ++vert;
- vertSign += (coeff[tileComp->cbW].flags & jpxCoeffSign)
- ? -1 : 1;
- }
- }
- cx = sigPropContext[horiz][vert][diag][res == 0 ? 1 : sb];
- if (cb->arithDecoder->decodeBit(cx, cb->stats)) {
- coeff->flags |= jpxCoeffSignificant | jpxCoeffFirstMagRef;
- coeff->mag = (coeff->mag << 1) | 1;
- cx = signContext[horizSign][vertSign][0];
- xorBit = signContext[horizSign][vertSign][1];
- if (cb->arithDecoder->decodeBit(cx, cb->stats) ^ xorBit) {
- coeff->flags |= jpxCoeffSign;
- }
- }
- ++coeff->len;
- } else {
- coeff->flags &= ~jpxCoeffTouched;
- }
- }
- }
- }
- cb->nextPass = jpxPassSigProp;
- break;
- }
- }
-
- cb->arithDecoder->cleanup();
- return gTrue;
-}
-
-// Inverse quantization, and wavelet transform (IDWT). This also does
-// the initial shift to convert to fixed point format.
-void JPXStream::inverseTransform(JPXTileComp *tileComp) {
- JPXResLevel *resLevel;
- JPXPrecinct *precinct;
- JPXSubband *subband;
- JPXCodeBlock *cb;
- JPXCoeff *coeff0, *coeff;
- Guint qStyle, guard, eps, shift;
- int shift2;
- double mu;
- int val;
- int *dataPtr;
- Guint nx0, ny0, nx1, ny1;
- Guint r, cbX, cbY, x, y;
-
- //----- (NL)LL subband (resolution level 0)
-
- resLevel = &tileComp->resLevels[0];
- precinct = &resLevel->precincts[0];
- subband = &precinct->subbands[0];
-
- // i-quant parameters
- qStyle = tileComp->quantStyle & 0x1f;
- guard = (tileComp->quantStyle >> 5) & 7;
- if (qStyle == 0) {
- eps = (tileComp->quantSteps[0] >> 3) & 0x1f;
- shift = guard + eps - 1;
- mu = 0; // make gcc happy
- } else {
- shift = guard - 1 + tileComp->prec;
- mu = (double)(0x800 + (tileComp->quantSteps[0] & 0x7ff)) / 2048.0;
- }
- if (tileComp->transform == 0) {
- shift += fracBits;
- }
-
- // copy (NL)LL into the upper-left corner of the data array, doing
- // the fixed point adjustment and dequantization along the way
- cb = subband->cbs;
- for (cbY = 0; cbY < subband->nYCBs; ++cbY) {
- for (cbX = 0; cbX < subband->nXCBs; ++cbX) {
- for (y = cb->y0, coeff0 = cb->coeffs;
- y < cb->y1;
- ++y, coeff0 += tileComp->cbW) {
- dataPtr = &tileComp->data[(y - subband->y0)
- * (tileComp->x1 - tileComp->x0)
- + (cb->x0 - subband->x0)];
- for (x = cb->x0, coeff = coeff0; x < cb->x1; ++x, ++coeff) {
- val = (int)coeff->mag;
- if (val != 0) {
- shift2 = shift - (cb->nZeroBitPlanes + coeff->len);
- if (shift2 > 0) {
- val = (val << shift2) + (1 << (shift2 - 1));
- } else {
- val >>= -shift2;
- }
- if (qStyle == 0) {
- if (tileComp->transform == 0) {
- val &= -1 << fracBits;
- }
- } else {
- val = (int)((double)val * mu);
- }
- if (coeff->flags & jpxCoeffSign) {
- val = -val;
- }
- }
- *dataPtr++ = val;
- }
- }
- ++cb;
- }
- }
-
- //----- IDWT for each level
-
- for (r = 1; r <= tileComp->nDecompLevels; ++r) {
- resLevel = &tileComp->resLevels[r];
-
- // (n)LL is already in the upper-left corner of the
- // tile-component data array -- interleave with (n)HL/LH/HH
- // and inverse transform to get (n-1)LL, which will be stored
- // in the upper-left corner of the tile-component data array
- if (r == tileComp->nDecompLevels) {
- nx0 = tileComp->x0;
- ny0 = tileComp->y0;
- nx1 = tileComp->x1;
- ny1 = tileComp->y1;
- } else {
- nx0 = tileComp->resLevels[r+1].x0;
- ny0 = tileComp->resLevels[r+1].y0;
- nx1 = tileComp->resLevels[r+1].x1;
- ny1 = tileComp->resLevels[r+1].y1;
- }
- inverseTransformLevel(tileComp, r, resLevel, nx0, ny0, nx1, ny1);
- }
-}
-
-// Do one level of the inverse transform:
-// - take (n)LL from the tile-component data array
-// - take (n)HL/LH/HH from <resLevel>
-// - leave the resulting (n-1)LL in the tile-component data array
-void JPXStream::inverseTransformLevel(JPXTileComp *tileComp,
- Guint r, JPXResLevel *resLevel,
- Guint nx0, Guint ny0,
- Guint nx1, Guint ny1) {
- JPXPrecinct *precinct;
- JPXSubband *subband;
- JPXCodeBlock *cb;
- JPXCoeff *coeff0, *coeff;
- Guint qStyle, guard, eps, shift, t;
- int shift2;
- double mu;
- int val;
- int *dataPtr;
- Guint xo, yo;
- Guint x, y, sb, cbX, cbY;
- int xx, yy;
-
- //----- interleave
-
- // spread out LL
- for (yy = resLevel->y1 - 1; yy >= (int)resLevel->y0; --yy) {
- for (xx = resLevel->x1 - 1; xx >= (int)resLevel->x0; --xx) {
- tileComp->data[(2 * yy - ny0) * (tileComp->x1 - tileComp->x0)
- + (2 * xx - nx0)] =
- tileComp->data[(yy - resLevel->y0) * (tileComp->x1 - tileComp->x0)
- + (xx - resLevel->x0)];
- }
- }
-
- // i-quant parameters
- qStyle = tileComp->quantStyle & 0x1f;
- guard = (tileComp->quantStyle >> 5) & 7;
-
- // interleave HL/LH/HH
- precinct = &resLevel->precincts[0];
- for (sb = 0; sb < 3; ++sb) {
-
- // i-quant parameters
- if (qStyle == 0) {
- eps = (tileComp->quantSteps[3*r - 2 + sb] >> 3) & 0x1f;
- shift = guard + eps - 1;
- mu = 0; // make gcc happy
- } else {
- shift = guard + tileComp->prec;
- if (sb == 2) {
- ++shift;
- }
- t = tileComp->quantSteps[qStyle == 1 ? 0 : (3*r - 2 + sb)];
- mu = (double)(0x800 + (t & 0x7ff)) / 2048.0;
- }
- if (tileComp->transform == 0) {
- shift += fracBits;
- }
-
- // copy the subband coefficients into the data array, doing the
- // fixed point adjustment and dequantization along the way
- xo = (sb & 1) ? 0 : 1;
- yo = (sb > 0) ? 1 : 0;
- subband = &precinct->subbands[sb];
- cb = subband->cbs;
- for (cbY = 0; cbY < subband->nYCBs; ++cbY) {
- for (cbX = 0; cbX < subband->nXCBs; ++cbX) {
- for (y = cb->y0, coeff0 = cb->coeffs;
- y < cb->y1;
- ++y, coeff0 += tileComp->cbW) {
- dataPtr = &tileComp->data[(2 * y + yo - ny0)
- * (tileComp->x1 - tileComp->x0)
- + (2 * cb->x0 + xo - nx0)];
- for (x = cb->x0, coeff = coeff0; x < cb->x1; ++x, ++coeff) {
- val = (int)coeff->mag;
- if (val != 0) {
- shift2 = shift - (cb->nZeroBitPlanes + coeff->len);
- if (shift2 > 0) {
- val = (val << shift2) + (1 << (shift2 - 1));
- } else {
- val >>= -shift2;
- }
- if (qStyle == 0) {
- if (tileComp->transform == 0) {
- val &= -1 << fracBits;
- }
- } else {
- val = (int)((double)val * mu);
- }
- if (coeff->flags & jpxCoeffSign) {
- val = -val;
- }
- }
- *dataPtr = val;
- dataPtr += 2;
- }
- }
- ++cb;
- }
- }
- }
-
- //----- horizontal (row) transforms
- dataPtr = tileComp->data;
- for (y = 0; y < ny1 - ny0; ++y) {
- inverseTransform1D(tileComp, dataPtr, 1, nx0, nx1);
- dataPtr += tileComp->x1 - tileComp->x0;
- }
-
- //----- vertical (column) transforms
- dataPtr = tileComp->data;
- for (x = 0; x < nx1 - nx0; ++x) {
- inverseTransform1D(tileComp, dataPtr,
- tileComp->x1 - tileComp->x0, ny0, ny1);
- ++dataPtr;
- }
-}
-
-void JPXStream::inverseTransform1D(JPXTileComp *tileComp,
- int *data, Guint stride,
- Guint i0, Guint i1) {
- int *buf;
- Guint offset, end, i;
-
- //----- special case for length = 1
- if (i1 - i0 == 1) {
- if (i0 & 1) {
- *data >>= 1;
- }
-
- } else {
-
- // choose an offset: this makes even buf[] indexes correspond to
- // odd values of i, and vice versa
- offset = 3 + (i0 & 1);
- end = offset + i1 - i0;
-
- //----- gather
- buf = tileComp->buf;
- for (i = 0; i < i1 - i0; ++i) {
- buf[offset + i] = data[i * stride];
- }
-
- //----- extend right
- buf[end] = buf[end - 2];
- if (i1 - i0 == 2) {
- buf[end+1] = buf[offset + 1];
- buf[end+2] = buf[offset];
- buf[end+3] = buf[offset + 1];
- } else {
- buf[end+1] = buf[end - 3];
- if (i1 - i0 == 3) {
- buf[end+2] = buf[offset + 1];
- buf[end+3] = buf[offset + 2];
- } else {
- buf[end+2] = buf[end - 4];
- if (i1 - i0 == 4) {
- buf[end+3] = buf[offset + 1];
- } else {
- buf[end+3] = buf[end - 5];
- }
- }
- }
-
- //----- extend left
- buf[offset - 1] = buf[offset + 1];
- buf[offset - 2] = buf[offset + 2];
- buf[offset - 3] = buf[offset + 3];
- if (offset == 4) {
- buf[0] = buf[offset + 4];
- }
-
- //----- 9-7 irreversible filter
-
- if (tileComp->transform == 0) {
- // step 1 (even)
- for (i = 1; i <= end + 2; i += 2) {
- buf[i] = (int)(idwtKappa * buf[i]);
- }
- // step 2 (odd)
- for (i = 0; i <= end + 3; i += 2) {
- buf[i] = (int)(idwtIKappa * buf[i]);
- }
- // step 3 (even)
- for (i = 1; i <= end + 2; i += 2) {
- buf[i] = (int)(buf[i] - idwtDelta * (buf[i-1] + buf[i+1]));
- }
- // step 4 (odd)
- for (i = 2; i <= end + 1; i += 2) {
- buf[i] = (int)(buf[i] - idwtGamma * (buf[i-1] + buf[i+1]));
- }
- // step 5 (even)
- for (i = 3; i <= end; i += 2) {
- buf[i] = (int)(buf[i] - idwtBeta * (buf[i-1] + buf[i+1]));
- }
- // step 6 (odd)
- for (i = 4; i <= end - 1; i += 2) {
- buf[i] = (int)(buf[i] - idwtAlpha * (buf[i-1] + buf[i+1]));
- }
-
- //----- 5-3 reversible filter
-
- } else {
- // step 1 (even)
- for (i = 3; i <= end; i += 2) {
- buf[i] -= (buf[i-1] + buf[i+1] + 2) >> 2;
- }
- // step 2 (odd)
- for (i = 4; i < end; i += 2) {
- buf[i] += (buf[i-1] + buf[i+1]) >> 1;
- }
- }
-
- //----- scatter
- for (i = 0; i < i1 - i0; ++i) {
- data[i * stride] = buf[offset + i];
- }
- }
-}
-
-// Inverse multi-component transform and DC level shift. This also
-// converts fixed point samples back to integers.
-GBool JPXStream::inverseMultiCompAndDC(JPXTile *tile) {
- JPXTileComp *tileComp;
- int coeff, d0, d1, d2, t, minVal, maxVal, zeroVal;
- int *dataPtr;
- Guint j, comp, x, y;
-
- //----- inverse multi-component transform
-
- if (tile->multiComp == 1) {
- if (img.nComps < 3 ||
- tile->tileComps[0].hSep != tile->tileComps[1].hSep ||
- tile->tileComps[0].vSep != tile->tileComps[1].vSep ||
- tile->tileComps[1].hSep != tile->tileComps[2].hSep ||
- tile->tileComps[1].vSep != tile->tileComps[2].vSep) {
- return gFalse;
- }
-
- // inverse irreversible multiple component transform
- if (tile->tileComps[0].transform == 0) {
- j = 0;
- for (y = 0; y < tile->tileComps[0].y1 - tile->tileComps[0].y0; ++y) {
- for (x = 0; x < tile->tileComps[0].x1 - tile->tileComps[0].x0; ++x) {
- d0 = tile->tileComps[0].data[j];
- d1 = tile->tileComps[1].data[j];
- d2 = tile->tileComps[2].data[j];
- tile->tileComps[0].data[j] = (int)(d0 + 1.402 * d2 + 0.5);
- tile->tileComps[1].data[j] =
- (int)(d0 - 0.34413 * d1 - 0.71414 * d2 + 0.5);
- tile->tileComps[2].data[j] = (int)(d0 + 1.772 * d1 + 0.5);
- ++j;
- }
- }
-
- // inverse reversible multiple component transform
- } else {
- j = 0;
- for (y = 0; y < tile->tileComps[0].y1 - tile->tileComps[0].y0; ++y) {
- for (x = 0; x < tile->tileComps[0].x1 - tile->tileComps[0].x0; ++x) {
- d0 = tile->tileComps[0].data[j];
- d1 = tile->tileComps[1].data[j];
- d2 = tile->tileComps[2].data[j];
- tile->tileComps[1].data[j] = t = d0 - ((d2 + d1) >> 2);
- tile->tileComps[0].data[j] = d2 + t;
- tile->tileComps[2].data[j] = d1 + t;
- ++j;
- }
- }
- }
- }
-
- //----- DC level shift
- for (comp = 0; comp < img.nComps; ++comp) {
- tileComp = &tile->tileComps[comp];
-
- // signed: clip
- if (tileComp->sgned) {
- minVal = -(1 << (tileComp->prec - 1));
- maxVal = (1 << (tileComp->prec - 1)) - 1;
- dataPtr = tileComp->data;
- for (y = 0; y < tileComp->y1 - tileComp->y0; ++y) {
- for (x = 0; x < tileComp->x1 - tileComp->x0; ++x) {
- coeff = *dataPtr;
- if (tileComp->transform == 0) {
- coeff >>= fracBits;
- }
- if (coeff < minVal) {
- coeff = minVal;
- } else if (coeff > maxVal) {
- coeff = maxVal;
- }
- *dataPtr++ = coeff;
- }
- }
-
- // unsigned: inverse DC level shift and clip
- } else {
- maxVal = (1 << tileComp->prec) - 1;
- zeroVal = 1 << (tileComp->prec - 1);
- dataPtr = tileComp->data;
- for (y = 0; y < tileComp->y1 - tileComp->y0; ++y) {
- for (x = 0; x < tileComp->x1 - tileComp->x0; ++x) {
- coeff = *dataPtr;
- if (tileComp->transform == 0) {
- coeff >>= fracBits;
- }
- coeff += zeroVal;
- if (coeff < 0) {
- coeff = 0;
- } else if (coeff > maxVal) {
- coeff = maxVal;
- }
- *dataPtr++ = coeff;
- }
- }
- }
- }
-
- return gTrue;
-}
-
-GBool JPXStream::readBoxHdr(Guint *boxType, Guint *boxLen, Guint *dataLen) {
- Guint len, lenH;
-
- if (!readULong(&len) ||
- !readULong(boxType)) {
- return gFalse;
- }
- if (len == 1) {
- if (!readULong(&lenH) || !readULong(&len)) {
- return gFalse;
- }
- if (lenH) {
- error(getPos(), "JPX stream contains a box larger than 2^32 bytes");
- return gFalse;
- }
- *boxLen = len;
- *dataLen = len - 16;
- } else if (len == 0) {
- *boxLen = 0;
- *dataLen = 0;
- } else {
- *boxLen = len;
- *dataLen = len - 8;
- }
- return gTrue;
-}
-
-int JPXStream::readMarkerHdr(int *segType, Guint *segLen) {
- int c;
-
- do {
- do {
- if ((c = str->getChar()) == EOF) {
- return gFalse;
- }
- } while (c != 0xff);
- do {
- if ((c = str->getChar()) == EOF) {
- return gFalse;
- }
- } while (c == 0xff);
- } while (c == 0x00);
- *segType = c;
- if ((c >= 0x30 && c <= 0x3f) ||
- c == 0x4f || c == 0x92 || c == 0x93 || c == 0xd9) {
- *segLen = 0;
- return gTrue;
- }
- return readUWord(segLen);
-}
-
-GBool JPXStream::readUByte(Guint *x) {
- int c0;
-
- if ((c0 = str->getChar()) == EOF) {
- return gFalse;
- }
- *x = (Guint)c0;
- return gTrue;
-}
-
-GBool JPXStream::readByte(int *x) {
- int c0;
-
- if ((c0 = str->getChar()) == EOF) {
- return gFalse;
- }
- *x = c0;
- if (c0 & 0x80) {
- *x |= -1 - 0xff;
- }
- return gTrue;
-}
-
-GBool JPXStream::readUWord(Guint *x) {
- int c0, c1;
-
- if ((c0 = str->getChar()) == EOF ||
- (c1 = str->getChar()) == EOF) {
- return gFalse;
- }
- *x = (Guint)((c0 << 8) | c1);
- return gTrue;
-}
-
-GBool JPXStream::readULong(Guint *x) {
- int c0, c1, c2, c3;
-
- if ((c0 = str->getChar()) == EOF ||
- (c1 = str->getChar()) == EOF ||
- (c2 = str->getChar()) == EOF ||
- (c3 = str->getChar()) == EOF) {
- return gFalse;
- }
- *x = (Guint)((c0 << 24) | (c1 << 16) | (c2 << 8) | c3);
- return gTrue;
-}
-
-GBool JPXStream::readNBytes(int nBytes, GBool signd, int *x) {
- int y, c, i;
-
- y = 0;
- for (i = 0; i < nBytes; ++i) {
- if ((c = str->getChar()) == EOF) {
- return gFalse;
- }
- y = (y << 8) + c;
- }
- if (signd) {
- if (y & (1 << (8 * nBytes - 1))) {
- y |= -1 << (8 * nBytes);
- }
- }
- *x = y;
- return gTrue;
-}
-
-GBool JPXStream::readBits(int nBits, Guint *x) {
- int c;
-
- while (bitBufLen < nBits) {
- if ((c = str->getChar()) == EOF) {
- return gFalse;
- }
- ++byteCount;
- if (bitBufSkip) {
- bitBuf = (bitBuf << 7) | (c & 0x7f);
- bitBufLen += 7;
- } else {
- bitBuf = (bitBuf << 8) | (c & 0xff);
- bitBufLen += 8;
- }
- bitBufSkip = c == 0xff;
- }
- *x = (bitBuf >> (bitBufLen - nBits)) & ((1 << nBits) - 1);
- bitBufLen -= nBits;
- return gTrue;
-}
-
-void JPXStream::clearBitBuf() {
- bitBufLen = 0;
- bitBufSkip = gFalse;
- byteCount = 0;
-}
+++ /dev/null
-//========================================================================
-//
-// JPXStream.h
-//
-// Copyright 2002-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#ifndef JPXSTREAM_H
-#define JPXSTREAM_H
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma interface
-#endif
-
-#include "gtypes.h"
-#include "Object.h"
-#include "Stream.h"
-
-class JArithmeticDecoderStats;
-
-//------------------------------------------------------------------------
-
-enum JPXColorSpaceType {
- jpxCSBiLevel = 0,
- jpxCSYCbCr1 = 1,
- jpxCSYCbCr2 = 3,
- jpxCSYCBCr3 = 4,
- jpxCSPhotoYCC = 9,
- jpxCSCMY = 11,
- jpxCSCMYK = 12,
- jpxCSYCCK = 13,
- jpxCSCIELab = 14,
- jpxCSsRGB = 16,
- jpxCSGrayscale = 17,
- jpxCSBiLevel2 = 18,
- jpxCSCIEJab = 19,
- jpxCSCISesRGB = 20,
- jpxCSROMMRGB = 21,
- jpxCSsRGBYCbCr = 22,
- jpxCSYPbPr1125 = 23,
- jpxCSYPbPr1250 = 24
-};
-
-struct JPXColorSpecCIELab {
- Guint rl, ol, ra, oa, rb, ob, il;
-};
-
-struct JPXColorSpecEnumerated {
- JPXColorSpaceType type; // color space type
- union {
- JPXColorSpecCIELab cieLab;
- };
-};
-
-struct JPXColorSpec {
- Guint meth; // method
- int prec; // precedence
- union {
- JPXColorSpecEnumerated enumerated;
- };
-};
-
-//------------------------------------------------------------------------
-
-struct JPXPalette {
- Guint nEntries; // number of entries in the palette
- Guint nComps; // number of components in each entry
- Guint *bpc; // bits per component, for each component
- int *c; // color data:
- // c[i*nComps+j] = entry i, component j
-};
-
-//------------------------------------------------------------------------
-
-struct JPXCompMap {
- Guint nChannels; // number of channels
- Guint *comp; // codestream components mapped to each channel
- Guint *type; // 0 for direct use, 1 for palette mapping
- Guint *pComp; // palette components to use
-};
-
-//------------------------------------------------------------------------
-
-struct JPXChannelDefn {
- Guint nChannels; // number of channels
- Guint *idx; // channel indexes
- Guint *type; // channel types
- Guint *assoc; // channel associations
-};
-
-//------------------------------------------------------------------------
-
-struct JPXTagTreeNode {
- GBool finished; // true if this node is finished
- Guint val; // current value
-};
-
-//------------------------------------------------------------------------
-
-struct JPXCoeff {
- Gushort flags; // flag bits
- Gushort len; // number of significant bits in mag
- Guint mag; // magnitude value
-};
-
-// coefficient flags
-#define jpxCoeffSignificantB 0
-#define jpxCoeffTouchedB 1
-#define jpxCoeffFirstMagRefB 2
-#define jpxCoeffSignB 7
-#define jpxCoeffSignificant (1 << jpxCoeffSignificantB)
-#define jpxCoeffTouched (1 << jpxCoeffTouchedB)
-#define jpxCoeffFirstMagRef (1 << jpxCoeffFirstMagRefB)
-#define jpxCoeffSign (1 << jpxCoeffSignB)
-
-//------------------------------------------------------------------------
-
-struct JPXCodeBlock {
- //----- size
- Guint x0, y0, x1, y1; // bounds
-
- //----- persistent state
- GBool seen; // true if this code-block has already
- // been seen
- Guint lBlock; // base number of bits used for pkt data length
- Guint nextPass; // next coding pass
-
- //---- info from first packet
- Guint nZeroBitPlanes; // number of zero bit planes
-
- //----- info for the current packet
- Guint included; // code-block inclusion in this packet:
- // 0=not included, 1=included
- Guint nCodingPasses; // number of coding passes in this pkt
- Guint dataLen; // pkt data length
-
- //----- coefficient data
- JPXCoeff *coeffs; // the coefficients
- JArithmeticDecoder // arithmetic decoder
- *arithDecoder;
- JArithmeticDecoderStats // arithmetic decoder stats
- *stats;
-};
-
-//------------------------------------------------------------------------
-
-struct JPXSubband {
- //----- computed
- Guint x0, y0, x1, y1; // bounds
- Guint nXCBs, nYCBs; // number of code-blocks in the x and y
- // directions
-
- //----- tag trees
- Guint maxTTLevel; // max tag tree level
- JPXTagTreeNode *inclusion; // inclusion tag tree for each subband
- JPXTagTreeNode *zeroBitPlane; // zero-bit plane tag tree for each
- // subband
-
- //----- children
- JPXCodeBlock *cbs; // the code-blocks (len = nXCBs * nYCBs)
-};
-
-//------------------------------------------------------------------------
-
-struct JPXPrecinct {
- //----- computed
- Guint x0, y0, x1, y1; // bounds of the precinct
-
- //----- children
- JPXSubband *subbands; // the subbands
-};
-
-//------------------------------------------------------------------------
-
-struct JPXResLevel {
- //----- from the COD and COC segments (main and tile)
- Guint precinctWidth; // log2(precinct width)
- Guint precinctHeight; // log2(precinct height)
-
- //----- computed
- Guint x0, y0, x1, y1; // bounds of the tile-comp (for this res level)
- Guint bx0[3], by0[3], // subband bounds
- bx1[3], by1[3];
-
- //---- children
- JPXPrecinct *precincts; // the precincts
-};
-
-//------------------------------------------------------------------------
-
-struct JPXTileComp {
- //----- from the SIZ segment
- GBool sgned; // 1 for signed, 0 for unsigned
- Guint prec; // precision, in bits
- Guint hSep; // horizontal separation of samples
- Guint vSep; // vertical separation of samples
-
- //----- from the COD and COC segments (main and tile)
- Guint style; // coding style parameter (Scod / Scoc)
- Guint nDecompLevels; // number of decomposition levels
- Guint codeBlockW; // log2(code-block width)
- Guint codeBlockH; // log2(code-block height)
- Guint codeBlockStyle; // code-block style
- Guint transform; // wavelet transformation
-
- //----- from the QCD and QCC segments (main and tile)
- Guint quantStyle; // quantization style
- Guint *quantSteps; // quantization step size for each subband
- Guint nQuantSteps; // number of entries in quantSteps
-
- //----- computed
- Guint x0, y0, x1, y1; // bounds of the tile-comp, in ref coords
- Guint cbW; // code-block width
- Guint cbH; // code-block height
-
- //----- image data
- int *data; // the decoded image data
- int *buf; // intermediate buffer for the inverse
- // transform
-
- //----- children
- JPXResLevel *resLevels; // the resolution levels
- // (len = nDecompLevels + 1)
-};
-
-//------------------------------------------------------------------------
-
-struct JPXTile {
- //----- from the COD segments (main and tile)
- Guint progOrder; // progression order
- Guint nLayers; // number of layers
- Guint multiComp; // multiple component transformation
-
- //----- computed
- Guint x0, y0, x1, y1; // bounds of the tile, in ref coords
- Guint maxNDecompLevels; // max number of decomposition levels used
- // in any component in this tile
-
- //----- progression order loop counters
- Guint comp; // component
- Guint res; // resolution level
- Guint precinct; // precinct
- Guint layer; // layer
-
- //----- children
- JPXTileComp *tileComps; // the tile-components (len = JPXImage.nComps)
-};
-
-//------------------------------------------------------------------------
-
-struct JPXImage {
- //----- from the SIZ segment
- Guint xSize, ySize; // size of reference grid
- Guint xOffset, yOffset; // image offset
- Guint xTileSize, yTileSize; // size of tiles
- Guint xTileOffset, // offset of first tile
- yTileOffset;
- Guint nComps; // number of components
-
- //----- computed
- Guint nXTiles; // number of tiles in x direction
- Guint nYTiles; // number of tiles in y direction
-
- //----- children
- JPXTile *tiles; // the tiles (len = nXTiles * nYTiles)
-};
-
-//------------------------------------------------------------------------
-
-class JPXStream: public FilterStream {
-public:
-
- JPXStream(Stream *strA);
- virtual ~JPXStream();
- virtual StreamKind getKind() { return strJPX; }
- virtual void reset();
- virtual int getChar();
- virtual int lookChar();
- virtual GString *getPSFilter(int psLevel, char *indent);
- virtual GBool isBinary(GBool last = gTrue);
- virtual void getImageParams(int *bitsPerComponent,
- StreamColorSpaceMode *csMode);
-
-private:
-
- void fillReadBuf();
- void getImageParams2(int *bitsPerComponent, StreamColorSpaceMode *csMode);
- GBool readBoxes();
- GBool readColorSpecBox(Guint dataLen);
- GBool readCodestream(Guint len);
- GBool readTilePart();
- GBool readTilePartData(Guint tileIdx,
- Guint tilePartLen, GBool tilePartToEOC);
- GBool readCodeBlockData(JPXTileComp *tileComp,
- JPXResLevel *resLevel,
- JPXPrecinct *precinct,
- JPXSubband *subband,
- Guint res, Guint sb,
- JPXCodeBlock *cb);
- void inverseTransform(JPXTileComp *tileComp);
- void inverseTransformLevel(JPXTileComp *tileComp,
- Guint r, JPXResLevel *resLevel,
- Guint nx0, Guint ny0,
- Guint nx1, Guint ny1);
- void inverseTransform1D(JPXTileComp *tileComp,
- int *data, Guint stride,
- Guint i0, Guint i1);
- GBool inverseMultiCompAndDC(JPXTile *tile);
- GBool readBoxHdr(Guint *boxType, Guint *boxLen, Guint *dataLen);
- int readMarkerHdr(int *segType, Guint *segLen);
- GBool readUByte(Guint *x);
- GBool readByte(int *x);
- GBool readUWord(Guint *x);
- GBool readULong(Guint *x);
- GBool readNBytes(int nBytes, GBool signd, int *x);
- GBool readBits(int nBits, Guint *x);
- void clearBitBuf();
-
- Guint nComps; // number of components
- Guint *bpc; // bits per component, for each component
- Guint width, height; // image size
- GBool haveImgHdr; // set if a JP2/JPX image header has been
- // found
- JPXColorSpec cs; // color specification
- GBool haveCS; // set if a color spec has been found
- JPXPalette palette; // the palette
- GBool havePalette; // set if a palette has been found
- JPXCompMap compMap; // the component mapping
- GBool haveCompMap; // set if a component mapping has been found
- JPXChannelDefn channelDefn; // channel definition
- GBool haveChannelDefn; // set if a channel defn has been found
-
- JPXImage img; // JPEG2000 decoder data
- Guint bitBuf; // buffer for bit reads
- int bitBufLen; // number of bits in bitBuf
- GBool bitBufSkip; // true if next bit should be skipped
- // (for bit stuffing)
- Guint byteCount; // number of bytes read since last call
- // to clearBitBuf
-
- Guint curX, curY, curComp; // current position for lookChar/getChar
- Guint readBuf; // read buffer
- Guint readBufLen; // number of valid bits in readBuf
-};
-
-#endif
+++ /dev/null
-//========================================================================
-//
-// Lexer.cc
-//
-// Copyright 1996-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma implementation
-#endif
-
-#include <stdlib.h>
-#include <stddef.h>
-#include <string.h>
-#include <ctype.h>
-#include "Lexer.h"
-#include "Error.h"
-
-//------------------------------------------------------------------------
-
-// A '1' in this array means the character is white space. A '1' or
-// '2' means the character ends a name or command.
-static char specialChars[256] = {
- 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, // 0x
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1x
- 1, 0, 0, 0, 0, 2, 0, 0, 2, 2, 0, 0, 0, 0, 0, 2, // 2x
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, // 3x
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 4x
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0, // 5x
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 6x
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0, // 7x
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8x
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9x
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // ax
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // bx
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // cx
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // dx
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // ex
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // fx
-};
-
-//------------------------------------------------------------------------
-// Lexer
-//------------------------------------------------------------------------
-
-Lexer::Lexer(XRef *xref, Stream *str) {
- Object obj;
-
- curStr.initStream(str);
- streams = new Array(xref);
- streams->add(curStr.copy(&obj));
- strPtr = 0;
- freeArray = gTrue;
- curStr.streamReset();
-}
-
-Lexer::Lexer(XRef *xref, Object *obj) {
- Object obj2;
-
- if (obj->isStream()) {
- streams = new Array(xref);
- freeArray = gTrue;
- streams->add(obj->copy(&obj2));
- } else {
- streams = obj->getArray();
- freeArray = gFalse;
- }
- strPtr = 0;
- if (streams->getLength() > 0) {
- streams->get(strPtr, &curStr);
- curStr.streamReset();
- }
-}
-static int illegalChars = 0;
-
-Lexer::~Lexer() {
- if (!curStr.isNone()) {
- curStr.streamClose();
- curStr.free();
- }
- if (freeArray) {
- delete streams;
- }
- if(illegalChars)
- error(0, "Illegal characters in hex string (%d)", illegalChars);
- illegalChars = 0;
-}
-
-int Lexer::getChar() {
- int c;
-
- c = EOF;
- while (!curStr.isNone() && (c = curStr.streamGetChar()) == EOF) {
- curStr.streamClose();
- curStr.free();
- ++strPtr;
- if (strPtr < streams->getLength()) {
- streams->get(strPtr, &curStr);
- curStr.streamReset();
- }
- }
- return c;
-}
-
-int Lexer::lookChar() {
- if (curStr.isNone()) {
- return EOF;
- }
- return curStr.streamLookChar();
-}
-
-Object *Lexer::getObj(Object *obj) {
- char *p;
- int c, c2;
- GBool comment, neg, done;
- int numParen;
- int xi;
- double xf, scale;
- GString *s;
- int n, m;
-
- // skip whitespace and comments
- comment = gFalse;
- while (1) {
- if ((c = getChar()) == EOF) {
- return obj->initEOF();
- }
- if (comment) {
- if (c == '\r' || c == '\n')
- comment = gFalse;
- } else if (c == '%') {
- comment = gTrue;
- } else if (specialChars[c] != 1) {
- break;
- }
- }
-
- // start reading token
- switch (c) {
-
- // number
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- case '-': case '.':
- neg = gFalse;
- xi = 0;
- if (c == '-') {
- neg = gTrue;
- } else if (c == '.') {
- goto doReal;
- } else {
- xi = c - '0';
- }
- while (1) {
- c = lookChar();
- if (isdigit(c)) {
- getChar();
- xi = xi * 10 + (c - '0');
- } else if (c == '.') {
- getChar();
- goto doReal;
- } else {
- break;
- }
- }
- if (neg)
- xi = -xi;
- obj->initInt(xi);
- break;
- doReal:
- xf = xi;
- scale = 0.1;
- while (1) {
- c = lookChar();
- if (c == '-') {
- // ignore minus signs in the middle of numbers to match
- // Adobe's behavior
- error(getPos(), "Badly formatted number");
- getChar();
- continue;
- }
- if (!isdigit(c)) {
- break;
- }
- getChar();
- xf = xf + scale * (c - '0');
- scale *= 0.1;
- }
- if (neg)
- xf = -xf;
- obj->initReal(xf);
- break;
-
- // string
- case '(':
- p = tokBuf;
- n = 0;
- numParen = 1;
- done = gFalse;
- s = NULL;
- do {
- c2 = EOF;
- switch (c = getChar()) {
-
- case EOF:
-#if 0
- // This breaks some PDF files, e.g., ones from Photoshop.
- case '\r':
- case '\n':
-#endif
- error(getPos(), "Unterminated string");
- done = gTrue;
- break;
-
- case '(':
- ++numParen;
- c2 = c;
- break;
-
- case ')':
- if (--numParen == 0) {
- done = gTrue;
- } else {
- c2 = c;
- }
- break;
-
- case '\\':
- switch (c = getChar()) {
- case 'n':
- c2 = '\n';
- break;
- case 'r':
- c2 = '\r';
- break;
- case 't':
- c2 = '\t';
- break;
- case 'b':
- c2 = '\b';
- break;
- case 'f':
- c2 = '\f';
- break;
- case '\\':
- case '(':
- case ')':
- c2 = c;
- break;
- case '0': case '1': case '2': case '3':
- case '4': case '5': case '6': case '7':
- c2 = c - '0';
- c = lookChar();
- if (c >= '0' && c <= '7') {
- getChar();
- c2 = (c2 << 3) + (c - '0');
- c = lookChar();
- if (c >= '0' && c <= '7') {
- getChar();
- c2 = (c2 << 3) + (c - '0');
- }
- }
- break;
- case '\r':
- c = lookChar();
- if (c == '\n') {
- getChar();
- }
- break;
- case '\n':
- break;
- case EOF:
- error(getPos(), "Unterminated string");
- done = gTrue;
- break;
- default:
- c2 = c;
- break;
- }
- break;
-
- default:
- c2 = c;
- break;
- }
-
- if (c2 != EOF) {
- if (n == tokBufSize) {
- if (!s)
- s = new GString(tokBuf, tokBufSize);
- else
- s->append(tokBuf, tokBufSize);
- p = tokBuf;
- n = 0;
- }
- *p++ = (char)c2;
- ++n;
- }
- } while (!done);
- if (!s)
- s = new GString(tokBuf, n);
- else
- s->append(tokBuf, n);
- obj->initString(s);
- break;
-
- // name
- case '/':
- p = tokBuf;
- n = 0;
- while ((c = lookChar()) != EOF && !specialChars[c]) {
- getChar();
- if (c == '#') {
- c2 = lookChar();
- if (c2 >= '0' && c2 <= '9') {
- c = c2 - '0';
- } else if (c2 >= 'A' && c2 <= 'F') {
- c = c2 - 'A' + 10;
- } else if (c2 >= 'a' && c2 <= 'f') {
- c = c2 - 'a' + 10;
- } else {
- goto notEscChar;
- }
- getChar();
- c <<= 4;
- c2 = getChar();
- if (c2 >= '0' && c2 <= '9') {
- c += c2 - '0';
- } else if (c2 >= 'A' && c2 <= 'F') {
- c += c2 - 'A' + 10;
- } else if (c2 >= 'a' && c2 <= 'f') {
- c += c2 - 'a' + 10;
- } else {
- illegalChars++;
- //error(getPos(), "Illegal digit in hex char in name");
- }
- }
- notEscChar:
- if (++n == tokBufSize) {
- error(getPos(), "Name token too long");
- break;
- }
- *p++ = c;
- }
- *p = '\0';
- obj->initName(tokBuf);
- break;
-
- // array punctuation
- case '[':
- case ']':
- tokBuf[0] = c;
- tokBuf[1] = '\0';
- obj->initCmd(tokBuf);
- break;
-
- // hex string or dict punctuation
- case '<':
- c = lookChar();
-
- // dict punctuation
- if (c == '<') {
- getChar();
- tokBuf[0] = tokBuf[1] = '<';
- tokBuf[2] = '\0';
- obj->initCmd(tokBuf);
-
- // hex string
- } else {
- p = tokBuf;
- m = n = 0;
- c2 = 0;
- s = NULL;
- while (1) {
- c = getChar();
- if (c == '>') {
- break;
- } else if (c == EOF) {
- error(getPos(), "Unterminated hex string");
- break;
- } else if (specialChars[c] != 1) {
- c2 = c2 << 4;
- if (c >= '0' && c <= '9')
- c2 += c - '0';
- else if (c >= 'A' && c <= 'F')
- c2 += c - 'A' + 10;
- else if (c >= 'a' && c <= 'f')
- c2 += c - 'a' + 10;
- else {
- illegalChars++;
- //error(getPos(), "Illegal character <%02x> in hex string", c);
- }
- if (++m == 2) {
- if (n == tokBufSize) {
- if (!s)
- s = new GString(tokBuf, tokBufSize);
- else
- s->append(tokBuf, tokBufSize);
- p = tokBuf;
- n = 0;
- }
- *p++ = (char)c2;
- ++n;
- c2 = 0;
- m = 0;
- }
- }
- }
- if (!s)
- s = new GString(tokBuf, n);
- else
- s->append(tokBuf, n);
- if (m == 1)
- s->append((char)(c2 << 4));
- obj->initString(s);
- }
- break;
-
- // dict punctuation
- case '>':
- c = lookChar();
- if (c == '>') {
- getChar();
- tokBuf[0] = tokBuf[1] = '>';
- tokBuf[2] = '\0';
- obj->initCmd(tokBuf);
- } else {
- illegalChars++;
- //error(getPos(), "Illegal character '>'");
- obj->initError();
- }
- break;
-
- // error
- case ')':
- case '{':
- case '}':
- //error(getPos(), "Illegal character '%c'", c);
- illegalChars++;
- obj->initError();
- break;
-
- // command
- default:
- p = tokBuf;
- *p++ = c;
- n = 1;
- while ((c = lookChar()) != EOF && !specialChars[c]) {
- getChar();
- if (++n == tokBufSize) {
- error(getPos(), "Command token too long");
- break;
- }
- *p++ = c;
- }
- *p = '\0';
- if (tokBuf[0] == 't' && !strcmp(tokBuf, "true")) {
- obj->initBool(gTrue);
- } else if (tokBuf[0] == 'f' && !strcmp(tokBuf, "false")) {
- obj->initBool(gFalse);
- } else if (tokBuf[0] == 'n' && !strcmp(tokBuf, "null")) {
- obj->initNull();
- } else {
- obj->initCmd(tokBuf);
- }
- break;
- }
- return obj;
-}
-
-void Lexer::skipToNextLine() {
- int c;
-
- while (1) {
- c = getChar();
- if (c == EOF || c == '\n') {
- return;
- }
- if (c == '\r') {
- if ((c = lookChar()) == '\n') {
- getChar();
- }
- return;
- }
- }
-}
-
-GBool Lexer::isSpace(int c) {
- return c >= 0 && c <= 0xff && specialChars[c] == 1;
-}
+++ /dev/null
-//========================================================================
-//
-// Lexer.h
-//
-// Copyright 1996-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#ifndef LEXER_H
-#define LEXER_H
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma interface
-#endif
-
-#include "Object.h"
-#include "Stream.h"
-
-class XRef;
-
-#define tokBufSize 128 // size of token buffer
-
-//------------------------------------------------------------------------
-// Lexer
-//------------------------------------------------------------------------
-
-class Lexer {
-public:
-
- // Construct a lexer for a single stream. Deletes the stream when
- // lexer is deleted.
- Lexer(XRef *xref, Stream *str);
-
- // Construct a lexer for a stream or array of streams (assumes obj
- // is either a stream or array of streams).
- Lexer(XRef *xref, Object *obj);
-
- // Destructor.
- ~Lexer();
-
- // Get the next object from the input stream.
- Object *getObj(Object *obj);
-
- // Skip to the beginning of the next line in the input stream.
- void skipToNextLine();
-
- // Skip over one character.
- void skipChar() { getChar(); }
-
- // Get stream.
- Stream *getStream()
- { return curStr.isNone() ? (Stream *)NULL : curStr.getStream(); }
-
- // Get current position in file. This is only used for error
- // messages, so it returns an int instead of a Guint.
- int getPos()
- { return curStr.isNone() ? -1 : (int)curStr.streamGetPos(); }
-
- // Set position in file.
- void setPos(Guint pos, int dir = 0)
- { if (!curStr.isNone()) curStr.streamSetPos(pos, dir); }
-
- // Returns true if <c> is a whitespace character.
- static GBool isSpace(int c);
-
-private:
-
- int getChar();
- int lookChar();
-
- Array *streams; // array of input streams
- int strPtr; // index of current stream
- Object curStr; // current stream
- GBool freeArray; // should lexer free the streams array?
- char tokBuf[tokBufSize]; // temporary token buffer
-};
-
-#endif
+++ /dev/null
-//========================================================================
-//
-// Link.cc
-//
-// Copyright 1996-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma implementation
-#endif
-
-#include <stddef.h>
-#include <string.h>
-#include "gmem.h"
-#include "GString.h"
-#include "Error.h"
-#include "Object.h"
-#include "Array.h"
-#include "Dict.h"
-#include "Link.h"
-
-//------------------------------------------------------------------------
-// LinkAction
-//------------------------------------------------------------------------
-
-LinkAction *LinkAction::parseDest(Object *obj) {
- LinkAction *action;
-
- action = new LinkGoTo(obj);
- if (!action->isOk()) {
- delete action;
- return NULL;
- }
- return action;
-}
-
-LinkAction *LinkAction::parseAction(Object *obj, GString *baseURI) {
- LinkAction *action;
- Object obj2, obj3, obj4;
-
- if (!obj->isDict()) {
- error(-1, "Bad annotation action");
- return NULL;
- }
-
- obj->dictLookup("S", &obj2);
-
- // GoTo action
- if (obj2.isName("GoTo")) {
- obj->dictLookup("D", &obj3);
- action = new LinkGoTo(&obj3);
- obj3.free();
-
- // GoToR action
- } else if (obj2.isName("GoToR")) {
- obj->dictLookup("F", &obj3);
- obj->dictLookup("D", &obj4);
- action = new LinkGoToR(&obj3, &obj4);
- obj3.free();
- obj4.free();
-
- // Launch action
- } else if (obj2.isName("Launch")) {
- action = new LinkLaunch(obj);
-
- // URI action
- } else if (obj2.isName("URI")) {
- obj->dictLookup("URI", &obj3);
- action = new LinkURI(&obj3, baseURI);
- obj3.free();
-
- // Named action
- } else if (obj2.isName("Named")) {
- obj->dictLookup("N", &obj3);
- action = new LinkNamed(&obj3);
- obj3.free();
-
- // Movie action
- } else if (obj2.isName("Movie")) {
- obj->dictLookupNF("Annot", &obj3);
- obj->dictLookup("T", &obj4);
- action = new LinkMovie(&obj3, &obj4);
- obj3.free();
- obj4.free();
-
- // unknown action
- } else if (obj2.isName()) {
- action = new LinkUnknown(obj2.getName());
-
- // action is missing or wrong type
- } else {
- error(-1, "Bad annotation action");
- action = NULL;
- }
-
- obj2.free();
-
- if (action && !action->isOk()) {
- delete action;
- return NULL;
- }
- return action;
-}
-
-GString *LinkAction::getFileSpecName(Object *fileSpecObj) {
- GString *name;
- Object obj1;
-
- name = NULL;
-
- // string
- if (fileSpecObj->isString()) {
- name = fileSpecObj->getString()->copy();
-
- // dictionary
- } else if (fileSpecObj->isDict()) {
-#ifdef WIN32
- if (!fileSpecObj->dictLookup("DOS", &obj1)->isString()) {
-#else
- if (!fileSpecObj->dictLookup("Unix", &obj1)->isString()) {
-#endif
- obj1.free();
- fileSpecObj->dictLookup("F", &obj1);
- }
- if (obj1.isString()) {
- name = obj1.getString()->copy();
- } else {
- error(-1, "Illegal file spec in link");
- }
- obj1.free();
-
- // error
- } else {
- error(-1, "Illegal file spec in link");
- }
-
- // system-dependent path manipulation
- if (name) {
-#ifdef WIN32
- int i, j;
-
- // "//...." --> "\...."
- // "/x/...." --> "x:\...."
- // "/server/share/...." --> "\\server\share\...."
- // convert escaped slashes to slashes and unescaped slashes to backslashes
- i = 0;
- if (name->getChar(0) == '/') {
- if (name->getLength() >= 2 && name->getChar(1) == '/') {
- name->del(0);
- i = 0;
- } else if (name->getLength() >= 2 &&
- ((name->getChar(1) >= 'a' && name->getChar(1) <= 'z') ||
- (name->getChar(1) >= 'A' && name->getChar(1) <= 'Z')) &&
- (name->getLength() == 2 || name->getChar(2) == '/')) {
- name->setChar(0, name->getChar(1));
- name->setChar(1, ':');
- i = 2;
- } else {
- for (j = 2; j < name->getLength(); ++j) {
- if (name->getChar(j-1) != '\\' &&
- name->getChar(j) == '/') {
- break;
- }
- }
- if (j < name->getLength()) {
- name->setChar(0, '\\');
- name->insert(0, '\\');
- i = 2;
- }
- }
- }
- for (; i < name->getLength(); ++i) {
- if (name->getChar(i) == '/') {
- name->setChar(i, '\\');
- } else if (name->getChar(i) == '\\' &&
- i+1 < name->getLength() &&
- name->getChar(i+1) == '/') {
- name->del(i);
- }
- }
-#else
- // no manipulation needed for Unix
-#endif
- }
-
- return name;
-}
-
-//------------------------------------------------------------------------
-// LinkDest
-//------------------------------------------------------------------------
-
-LinkDest::LinkDest(Array *a) {
- Object obj1, obj2;
-
- // initialize fields
- left = bottom = right = top = zoom = 0;
- ok = gFalse;
-
- // get page
- if (a->getLength() < 2) {
- error(-1, "Annotation destination array is too short");
- return;
- }
- a->getNF(0, &obj1);
- if (obj1.isInt()) {
- pageNum = obj1.getInt() + 1;
- pageIsRef = gFalse;
- } else if (obj1.isRef()) {
- pageRef.num = obj1.getRefNum();
- pageRef.gen = obj1.getRefGen();
- pageIsRef = gTrue;
- } else {
- error(-1, "Bad annotation destination");
- goto err2;
- }
- obj1.free();
-
- // get destination type
- a->get(1, &obj1);
-
- // XYZ link
- if (obj1.isName("XYZ")) {
- kind = destXYZ;
- if (a->getLength() < 3) {
- changeLeft = gFalse;
- } else {
- a->get(2, &obj2);
- if (obj2.isNull()) {
- changeLeft = gFalse;
- } else if (obj2.isNum()) {
- changeLeft = gTrue;
- left = obj2.getNum();
- } else {
- error(-1, "Bad annotation destination position");
- goto err1;
- }
- obj2.free();
- }
- if (a->getLength() < 4) {
- changeTop = gFalse;
- } else {
- a->get(3, &obj2);
- if (obj2.isNull()) {
- changeTop = gFalse;
- } else if (obj2.isNum()) {
- changeTop = gTrue;
- top = obj2.getNum();
- } else {
- error(-1, "Bad annotation destination position");
- goto err1;
- }
- obj2.free();
- }
- if (a->getLength() < 5) {
- changeZoom = gFalse;
- } else {
- a->get(4, &obj2);
- if (obj2.isNull()) {
- changeZoom = gFalse;
- } else if (obj2.isNum()) {
- changeZoom = gTrue;
- zoom = obj2.getNum();
- } else {
- error(-1, "Bad annotation destination position");
- goto err1;
- }
- obj2.free();
- }
-
- // Fit link
- } else if (obj1.isName("Fit")) {
- if (a->getLength() < 2) {
- error(-1, "Annotation destination array is too short");
- goto err2;
- }
- kind = destFit;
-
- // FitH link
- } else if (obj1.isName("FitH")) {
- if (a->getLength() < 3) {
- error(-1, "Annotation destination array is too short");
- goto err2;
- }
- kind = destFitH;
- if (!a->get(2, &obj2)->isNum()) {
- error(-1, "Bad annotation destination position");
- goto err1;
- }
- top = obj2.getNum();
- obj2.free();
-
- // FitV link
- } else if (obj1.isName("FitV")) {
- if (a->getLength() < 3) {
- error(-1, "Annotation destination array is too short");
- goto err2;
- }
- kind = destFitV;
- if (!a->get(2, &obj2)->isNum()) {
- error(-1, "Bad annotation destination position");
- goto err1;
- }
- left = obj2.getNum();
- obj2.free();
-
- // FitR link
- } else if (obj1.isName("FitR")) {
- if (a->getLength() < 6) {
- error(-1, "Annotation destination array is too short");
- goto err2;
- }
- kind = destFitR;
- if (!a->get(2, &obj2)->isNum()) {
- error(-1, "Bad annotation destination position");
- goto err1;
- }
- left = obj2.getNum();
- obj2.free();
- if (!a->get(3, &obj2)->isNum()) {
- error(-1, "Bad annotation destination position");
- goto err1;
- }
- bottom = obj2.getNum();
- obj2.free();
- if (!a->get(4, &obj2)->isNum()) {
- error(-1, "Bad annotation destination position");
- goto err1;
- }
- right = obj2.getNum();
- obj2.free();
- if (!a->get(5, &obj2)->isNum()) {
- error(-1, "Bad annotation destination position");
- goto err1;
- }
- top = obj2.getNum();
- obj2.free();
-
- // FitB link
- } else if (obj1.isName("FitB")) {
- if (a->getLength() < 2) {
- error(-1, "Annotation destination array is too short");
- goto err2;
- }
- kind = destFitB;
-
- // FitBH link
- } else if (obj1.isName("FitBH")) {
- if (a->getLength() < 3) {
- error(-1, "Annotation destination array is too short");
- goto err2;
- }
- kind = destFitBH;
- if (!a->get(2, &obj2)->isNum()) {
- error(-1, "Bad annotation destination position");
- goto err1;
- }
- top = obj2.getNum();
- obj2.free();
-
- // FitBV link
- } else if (obj1.isName("FitBV")) {
- if (a->getLength() < 3) {
- error(-1, "Annotation destination array is too short");
- goto err2;
- }
- kind = destFitBV;
- if (!a->get(2, &obj2)->isNum()) {
- error(-1, "Bad annotation destination position");
- goto err1;
- }
- left = obj2.getNum();
- obj2.free();
-
- // unknown link kind
- } else {
- error(-1, "Unknown annotation destination type");
- goto err2;
- }
-
- obj1.free();
- ok = gTrue;
- return;
-
- err1:
- obj2.free();
- err2:
- obj1.free();
-}
-
-LinkDest::LinkDest(LinkDest *dest) {
- kind = dest->kind;
- pageIsRef = dest->pageIsRef;
- if (pageIsRef)
- pageRef = dest->pageRef;
- else
- pageNum = dest->pageNum;
- left = dest->left;
- bottom = dest->bottom;
- right = dest->right;
- top = dest->top;
- zoom = dest->zoom;
- changeLeft = dest->changeLeft;
- changeTop = dest->changeTop;
- changeZoom = dest->changeZoom;
- ok = gTrue;
-}
-
-//------------------------------------------------------------------------
-// LinkGoTo
-//------------------------------------------------------------------------
-
-LinkGoTo::LinkGoTo(Object *destObj) {
- dest = NULL;
- namedDest = NULL;
-
- // named destination
- if (destObj->isName()) {
- namedDest = new GString(destObj->getName());
- } else if (destObj->isString()) {
- namedDest = destObj->getString()->copy();
-
- // destination dictionary
- } else if (destObj->isArray()) {
- dest = new LinkDest(destObj->getArray());
- if (!dest->isOk()) {
- delete dest;
- dest = NULL;
- }
- // error
- } else {
- error(-1, "Illegal annotation destination %d", destObj->getType());
- }
-}
-
-LinkGoTo::~LinkGoTo() {
- if (dest)
- delete dest;
- if (namedDest)
- delete namedDest;
-}
-
-//------------------------------------------------------------------------
-// LinkGoToR
-//------------------------------------------------------------------------
-
-LinkGoToR::LinkGoToR(Object *fileSpecObj, Object *destObj) {
- dest = NULL;
- namedDest = NULL;
-
- // get file name
- fileName = getFileSpecName(fileSpecObj);
-
- // named destination
- if (destObj->isName()) {
- namedDest = new GString(destObj->getName());
- } else if (destObj->isString()) {
- namedDest = destObj->getString()->copy();
-
- // destination dictionary
- } else if (destObj->isArray()) {
- dest = new LinkDest(destObj->getArray());
- if (!dest->isOk()) {
- delete dest;
- dest = NULL;
- }
- // error
- } else {
- error(-1, "Illegal annotation destination %d", destObj->getType());
- }
-}
-
-LinkGoToR::~LinkGoToR() {
- if (fileName)
- delete fileName;
- if (dest)
- delete dest;
- if (namedDest)
- delete namedDest;
-}
-
-
-//------------------------------------------------------------------------
-// LinkLaunch
-//------------------------------------------------------------------------
-
-LinkLaunch::LinkLaunch(Object *actionObj) {
- Object obj1, obj2;
-
- fileName = NULL;
- params = NULL;
-
- if (actionObj->isDict()) {
- if (!actionObj->dictLookup("F", &obj1)->isNull()) {
- fileName = getFileSpecName(&obj1);
- } else {
- obj1.free();
-#ifdef WIN32
- if (actionObj->dictLookup("Win", &obj1)->isDict()) {
- obj1.dictLookup("F", &obj2);
- fileName = getFileSpecName(&obj2);
- obj2.free();
- if (obj1.dictLookup("P", &obj2)->isString()) {
- params = obj2.getString()->copy();
- }
- obj2.free();
- } else {
- error(-1, "Bad launch-type link action");
- }
-#else
- //~ This hasn't been defined by Adobe yet, so assume it looks
- //~ just like the Win dictionary until they say otherwise.
- if (actionObj->dictLookup("Unix", &obj1)->isDict()) {
- obj1.dictLookup("F", &obj2);
- fileName = getFileSpecName(&obj2);
- obj2.free();
- if (obj1.dictLookup("P", &obj2)->isString()) {
- params = obj2.getString()->copy();
- }
- obj2.free();
- } else {
- error(-1, "Bad launch-type link action");
- }
-#endif
- }
- obj1.free();
- }
-}
-
-LinkLaunch::~LinkLaunch() {
- if (fileName)
- delete fileName;
- if (params)
- delete params;
-}
-
-//------------------------------------------------------------------------
-// LinkURI
-//------------------------------------------------------------------------
-
-LinkURI::LinkURI(Object *uriObj, GString *baseURI) {
- GString *uri2;
- int n;
- char c;
-
- uri = NULL;
- if (uriObj->isString()) {
- uri2 = uriObj->getString()->copy();
- if (baseURI && baseURI->getLength() > 0) {
- n = strcspn(uri2->getCString(), "/:");
- if (n == uri2->getLength() || uri2->getChar(n) == '/') {
- uri = baseURI->copy();
- c = uri->getChar(uri->getLength() - 1);
- if (c == '/' || c == '?') {
- if (uri2->getChar(0) == '/') {
- uri2->del(0);
- }
- } else {
- if (uri2->getChar(0) != '/') {
- uri->append('/');
- }
- }
- uri->append(uri2);
- delete uri2;
- } else {
- uri = uri2;
- }
- } else {
- uri = uri2;
- }
- } else {
- error(-1, "Illegal URI-type link");
- }
-}
-
-LinkURI::~LinkURI() {
- if (uri)
- delete uri;
-}
-
-//------------------------------------------------------------------------
-// LinkNamed
-//------------------------------------------------------------------------
-
-LinkNamed::LinkNamed(Object *nameObj) {
- name = NULL;
- if (nameObj->isName()) {
- name = new GString(nameObj->getName());
- }
-}
-
-LinkNamed::~LinkNamed() {
- if (name) {
- delete name;
- }
-}
-
-//------------------------------------------------------------------------
-// LinkMovie
-//------------------------------------------------------------------------
-
-LinkMovie::LinkMovie(Object *annotObj, Object *titleObj) {
- annotRef.num = -1;
- title = NULL;
- if (annotObj->isRef()) {
- annotRef = annotObj->getRef();
- } else if (titleObj->isString()) {
- title = titleObj->getString()->copy();
- } else {
- error(-1, "Movie action is missing both the Annot and T keys");
- }
-}
-
-LinkMovie::~LinkMovie() {
- if (title) {
- delete title;
- }
-}
-
-//------------------------------------------------------------------------
-// LinkUnknown
-//------------------------------------------------------------------------
-
-LinkUnknown::LinkUnknown(char *actionA) {
- action = new GString(actionA);
-}
-
-LinkUnknown::~LinkUnknown() {
- delete action;
-}
-
-//------------------------------------------------------------------------
-// LinkBorderStyle
-//------------------------------------------------------------------------
-
-LinkBorderStyle::LinkBorderStyle(LinkBorderType typeA, double widthA,
- double *dashA, int dashLengthA,
- double rA, double gA, double bA) {
- type = typeA;
- width = widthA;
- dash = dashA;
- dashLength = dashLengthA;
- r = rA;
- g = gA;
- b = bA;
-}
-
-LinkBorderStyle::~LinkBorderStyle() {
- if (dash) {
- gfree(dash);
- }
-}
-
-//------------------------------------------------------------------------
-// Link
-//------------------------------------------------------------------------
-
-Link::Link(Dict *dict, GString *baseURI) {
- Object obj1, obj2, obj3;
- LinkBorderType borderType;
- double borderWidth;
- double *borderDash;
- int borderDashLength;
- double borderR, borderG, borderB;
- double t;
- int i;
-
- borderStyle = NULL;
- action = NULL;
- ok = gFalse;
-
- // get rectangle
- if (!dict->lookup("Rect", &obj1)->isArray()) {
- error(-1, "Annotation rectangle is wrong type");
- goto err2;
- }
- if (!obj1.arrayGet(0, &obj2)->isNum()) {
- error(-1, "Bad annotation rectangle");
- goto err1;
- }
- x1 = obj2.getNum();
- obj2.free();
- if (!obj1.arrayGet(1, &obj2)->isNum()) {
- error(-1, "Bad annotation rectangle");
- goto err1;
- }
- y1 = obj2.getNum();
- obj2.free();
- if (!obj1.arrayGet(2, &obj2)->isNum()) {
- error(-1, "Bad annotation rectangle");
- goto err1;
- }
- x2 = obj2.getNum();
- obj2.free();
- if (!obj1.arrayGet(3, &obj2)->isNum()) {
- error(-1, "Bad annotation rectangle");
- goto err1;
- }
- y2 = obj2.getNum();
- obj2.free();
- obj1.free();
- if (x1 > x2) {
- t = x1;
- x1 = x2;
- x2 = t;
- }
- if (y1 > y2) {
- t = y1;
- y1 = y2;
- y2 = t;
- }
-
- // get the border style info
- borderType = linkBorderSolid;
- borderWidth = 1;
- borderDash = NULL;
- borderDashLength = 0;
- borderR = 0;
- borderG = 0;
- borderB = 1;
- if (dict->lookup("BS", &obj1)->isDict()) {
- if (obj1.dictLookup("S", &obj2)->isName()) {
- if (obj2.isName("S")) {
- borderType = linkBorderSolid;
- } else if (obj2.isName("D")) {
- borderType = linkBorderDashed;
- } else if (obj2.isName("B")) {
- borderType = linkBorderEmbossed;
- } else if (obj2.isName("I")) {
- borderType = linkBorderEngraved;
- } else if (obj2.isName("U")) {
- borderType = linkBorderUnderlined;
- }
- }
- obj2.free();
- if (obj1.dictLookup("W", &obj2)->isNum()) {
- borderWidth = obj2.getNum();
- }
- obj2.free();
- if (obj1.dictLookup("D", &obj2)->isArray()) {
- borderDashLength = obj2.arrayGetLength();
- borderDash = (double *)gmallocn(borderDashLength, sizeof(double));
- for (i = 0; i < borderDashLength; ++i) {
- if (obj2.arrayGet(i, &obj3)->isNum()) {
- borderDash[i] = obj3.getNum();
- } else {
- borderDash[i] = 1;
- }
- obj3.free();
- }
- }
- obj2.free();
- } else {
- obj1.free();
- if (dict->lookup("Border", &obj1)->isArray()) {
- if (obj1.arrayGetLength() >= 3) {
- if (obj1.arrayGet(2, &obj2)->isNum()) {
- borderWidth = obj2.getNum();
- }
- obj2.free();
- if (obj1.arrayGetLength() >= 4) {
- if (obj1.arrayGet(3, &obj2)->isArray()) {
- borderType = linkBorderDashed;
- borderDashLength = obj2.arrayGetLength();
- borderDash = (double *)gmallocn(borderDashLength, sizeof(double));
- for (i = 0; i < borderDashLength; ++i) {
- if (obj2.arrayGet(i, &obj3)->isNum()) {
- borderDash[i] = obj3.getNum();
- } else {
- borderDash[i] = 1;
- }
- obj3.free();
- }
- } else {
- // Adobe draws no border at all if the last element is of
- // the wrong type.
- borderWidth = 0;
- }
- obj2.free();
- }
- }
- }
- }
- obj1.free();
- if (dict->lookup("C", &obj1)->isArray() && obj1.arrayGetLength() == 3) {
- if (obj1.arrayGet(0, &obj2)->isNum()) {
- borderR = obj2.getNum();
- }
- obj1.free();
- if (obj1.arrayGet(1, &obj2)->isNum()) {
- borderG = obj2.getNum();
- }
- obj1.free();
- if (obj1.arrayGet(2, &obj2)->isNum()) {
- borderB = obj2.getNum();
- }
- obj1.free();
- }
- obj1.free();
- borderStyle = new LinkBorderStyle(borderType, borderWidth,
- borderDash, borderDashLength,
- borderR, borderG, borderB);
-
- // look for destination
- if (!dict->lookup("Dest", &obj1)->isNull()) {
- action = LinkAction::parseDest(&obj1);
-
- // look for action
- } else {
- obj1.free();
- if (dict->lookup("A", &obj1)->isDict()) {
- action = LinkAction::parseAction(&obj1, baseURI);
- }
- }
- obj1.free();
-
- // check for bad action
- if (action) {
- ok = gTrue;
- }
-
- return;
-
- err1:
- obj2.free();
- err2:
- obj1.free();
-}
-
-Link::~Link() {
- if (borderStyle) {
- delete borderStyle;
- }
- if (action) {
- delete action;
- }
-}
-
-//------------------------------------------------------------------------
-// Links
-//------------------------------------------------------------------------
-
-Links::Links(Object *annots, GString *baseURI) {
- Link *link;
- Object obj1, obj2;
- int size;
- int i;
-
- links = NULL;
- size = 0;
- numLinks = 0;
-
- if (annots->isArray()) {
- for (i = 0; i < annots->arrayGetLength(); ++i) {
- if (annots->arrayGet(i, &obj1)->isDict()) {
- if (obj1.dictLookup("Subtype", &obj2)->isName("Link")) {
- link = new Link(obj1.getDict(), baseURI);
- if (link->isOk()) {
- if (numLinks >= size) {
- size += 16;
- links = (Link **)greallocn(links, size, sizeof(Link *));
- }
- links[numLinks++] = link;
- } else {
- delete link;
- }
- }
- obj2.free();
- }
- obj1.free();
- }
- }
-}
-
-Links::~Links() {
- int i;
-
- for (i = 0; i < numLinks; ++i)
- delete links[i];
- gfree(links);
-}
-
-LinkAction *Links::find(double x, double y) {
- int i;
-
- for (i = numLinks - 1; i >= 0; --i) {
- if (links[i]->inRect(x, y)) {
- return links[i]->getAction();
- }
- }
- return NULL;
-}
-
-GBool Links::onLink(double x, double y) {
- int i;
-
- for (i = 0; i < numLinks; ++i) {
- if (links[i]->inRect(x, y))
- return gTrue;
- }
- return gFalse;
-}
+++ /dev/null
-//========================================================================
-//
-// Link.h
-//
-// Copyright 1996-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#ifndef LINK_H
-#define LINK_H
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma interface
-#endif
-
-#include "Object.h"
-
-class GString;
-class Array;
-class Dict;
-
-//------------------------------------------------------------------------
-// LinkAction
-//------------------------------------------------------------------------
-
-enum LinkActionKind {
- actionGoTo, // go to destination
- actionGoToR, // go to destination in new file
- actionLaunch, // launch app (or open document)
- actionURI, // URI
- actionNamed, // named action
- actionMovie, // movie action
- actionUnknown // anything else
-};
-
-class LinkAction {
-public:
-
- // Destructor.
- virtual ~LinkAction() {}
-
- // Was the LinkAction created successfully?
- virtual GBool isOk() = 0;
-
- // Check link action type.
- virtual LinkActionKind getKind() = 0;
-
- // Parse a destination (old-style action) name, string, or array.
- static LinkAction *parseDest(Object *obj);
-
- // Parse an action dictionary.
- static LinkAction *parseAction(Object *obj, GString *baseURI = NULL);
-
- // Extract a file name from a file specification (string or
- // dictionary).
- static GString *getFileSpecName(Object *fileSpecObj);
-};
-
-//------------------------------------------------------------------------
-// LinkDest
-//------------------------------------------------------------------------
-
-enum LinkDestKind {
- destXYZ,
- destFit,
- destFitH,
- destFitV,
- destFitR,
- destFitB,
- destFitBH,
- destFitBV
-};
-
-class LinkDest {
-public:
-
- // Build a LinkDest from the array.
- LinkDest(Array *a);
-
- // Copy a LinkDest.
- LinkDest *copy() { return new LinkDest(this); }
-
- // Was the LinkDest created successfully?
- GBool isOk() { return ok; }
-
- // Accessors.
- LinkDestKind getKind() { return kind; }
- GBool isPageRef() { return pageIsRef; }
- int getPageNum() { return pageNum; }
- Ref getPageRef() { return pageRef; }
- double getLeft() { return left; }
- double getBottom() { return bottom; }
- double getRight() { return right; }
- double getTop() { return top; }
- double getZoom() { return zoom; }
- GBool getChangeLeft() { return changeLeft; }
- GBool getChangeTop() { return changeTop; }
- GBool getChangeZoom() { return changeZoom; }
-
-private:
-
- LinkDestKind kind; // destination type
- GBool pageIsRef; // is the page a reference or number?
- union {
- Ref pageRef; // reference to page
- int pageNum; // one-relative page number
- };
- double left, bottom; // position
- double right, top;
- double zoom; // zoom factor
- GBool changeLeft, changeTop; // for destXYZ links, which position
- GBool changeZoom; // components to change
- GBool ok; // set if created successfully
-
- LinkDest(LinkDest *dest);
-};
-
-//------------------------------------------------------------------------
-// LinkGoTo
-//------------------------------------------------------------------------
-
-class LinkGoTo: public LinkAction {
-public:
-
- // Build a LinkGoTo from a destination (dictionary, name, or string).
- LinkGoTo(Object *destObj);
-
- // Destructor.
- virtual ~LinkGoTo();
-
- // Was the LinkGoTo created successfully?
- virtual GBool isOk() { return dest || namedDest; }
-
- // Accessors.
- virtual LinkActionKind getKind() { return actionGoTo; }
- LinkDest *getDest() { return dest; }
- GString *getNamedDest() { return namedDest; }
-
-private:
-
- LinkDest *dest; // regular destination (NULL for remote
- // link with bad destination)
- GString *namedDest; // named destination (only one of dest and
- // and namedDest may be non-NULL)
-};
-
-//------------------------------------------------------------------------
-// LinkGoToR
-//------------------------------------------------------------------------
-
-class LinkGoToR: public LinkAction {
-public:
-
- // Build a LinkGoToR from a file spec (dictionary) and destination
- // (dictionary, name, or string).
- LinkGoToR(Object *fileSpecObj, Object *destObj);
-
- // Destructor.
- virtual ~LinkGoToR();
-
- // Was the LinkGoToR created successfully?
- virtual GBool isOk() { return fileName && (dest || namedDest); }
-
- // Accessors.
- virtual LinkActionKind getKind() { return actionGoToR; }
- GString *getFileName() { return fileName; }
- LinkDest *getDest() { return dest; }
- GString *getNamedDest() { return namedDest; }
-
-private:
-
- GString *fileName; // file name
- LinkDest *dest; // regular destination (NULL for remote
- // link with bad destination)
- GString *namedDest; // named destination (only one of dest and
- // and namedDest may be non-NULL)
-};
-
-//------------------------------------------------------------------------
-// LinkLaunch
-//------------------------------------------------------------------------
-
-class LinkLaunch: public LinkAction {
-public:
-
- // Build a LinkLaunch from an action dictionary.
- LinkLaunch(Object *actionObj);
-
- // Destructor.
- virtual ~LinkLaunch();
-
- // Was the LinkLaunch created successfully?
- virtual GBool isOk() { return fileName != NULL; }
-
- // Accessors.
- virtual LinkActionKind getKind() { return actionLaunch; }
- GString *getFileName() { return fileName; }
- GString *getParams() { return params; }
-
-private:
-
- GString *fileName; // file name
- GString *params; // parameters
-};
-
-//------------------------------------------------------------------------
-// LinkURI
-//------------------------------------------------------------------------
-
-class LinkURI: public LinkAction {
-public:
-
- // Build a LinkURI given the URI (string) and base URI.
- LinkURI(Object *uriObj, GString *baseURI);
-
- // Destructor.
- virtual ~LinkURI();
-
- // Was the LinkURI created successfully?
- virtual GBool isOk() { return uri != NULL; }
-
- // Accessors.
- virtual LinkActionKind getKind() { return actionURI; }
- GString *getURI() { return uri; }
-
-private:
-
- GString *uri; // the URI
-};
-
-//------------------------------------------------------------------------
-// LinkNamed
-//------------------------------------------------------------------------
-
-class LinkNamed: public LinkAction {
-public:
-
- // Build a LinkNamed given the action name.
- LinkNamed(Object *nameObj);
-
- virtual ~LinkNamed();
-
- virtual GBool isOk() { return name != NULL; }
-
- virtual LinkActionKind getKind() { return actionNamed; }
- GString *getName() { return name; }
-
-private:
-
- GString *name;
-};
-
-//------------------------------------------------------------------------
-// LinkMovie
-//------------------------------------------------------------------------
-
-class LinkMovie: public LinkAction {
-public:
-
- LinkMovie(Object *annotObj, Object *titleObj);
-
- virtual ~LinkMovie();
-
- virtual GBool isOk() { return annotRef.num >= 0 || title != NULL; }
-
- virtual LinkActionKind getKind() { return actionMovie; }
- GBool hasAnnotRef() { return annotRef.num >= 0; }
- Ref *getAnnotRef() { return &annotRef; }
- GString *getTitle() { return title; }
-
-private:
-
- Ref annotRef;
- GString *title;
-};
-
-//------------------------------------------------------------------------
-// LinkUnknown
-//------------------------------------------------------------------------
-
-class LinkUnknown: public LinkAction {
-public:
-
- // Build a LinkUnknown with the specified action type.
- LinkUnknown(char *actionA);
-
- // Destructor.
- virtual ~LinkUnknown();
-
- // Was the LinkUnknown create successfully?
- virtual GBool isOk() { return action != NULL; }
-
- // Accessors.
- virtual LinkActionKind getKind() { return actionUnknown; }
- GString *getAction() { return action; }
-
-private:
-
- GString *action; // action subtype
-};
-
-//------------------------------------------------------------------------
-// LinkBorderStyle
-//------------------------------------------------------------------------
-
-enum LinkBorderType {
- linkBorderSolid,
- linkBorderDashed,
- linkBorderEmbossed,
- linkBorderEngraved,
- linkBorderUnderlined
-};
-
-class LinkBorderStyle {
-public:
-
- LinkBorderStyle(LinkBorderType typeA, double widthA,
- double *dashA, int dashLengthA,
- double rA, double gA, double bA);
- ~LinkBorderStyle();
-
- LinkBorderType getType() { return type; }
- double getWidth() { return width; }
- void getDash(double **dashA, int *dashLengthA)
- { *dashA = dash; *dashLengthA = dashLength; }
- void getColor(double *rA, double *gA, double *bA)
- { *rA = r; *gA = g; *bA = b; }
-
-private:
-
- LinkBorderType type;
- double width;
- double *dash;
- int dashLength;
- double r, g, b;
-};
-
-//------------------------------------------------------------------------
-// Link
-//------------------------------------------------------------------------
-
-class Link {
-public:
-
- // Construct a link, given its dictionary.
- Link(Dict *dict, GString *baseURI);
-
- // Destructor.
- ~Link();
-
- // Was the link created successfully?
- GBool isOk() { return ok; }
-
- // Check if point is inside the link rectangle.
- GBool inRect(double x, double y)
- { return x1 <= x && x <= x2 && y1 <= y && y <= y2; }
-
- // Get action.
- LinkAction *getAction() { return action; }
-
- // Get the link rectangle.
- void getRect(double *xa1, double *ya1, double *xa2, double *ya2)
- { *xa1 = x1; *ya1 = y1; *xa2 = x2; *ya2 = y2; }
-
- // Get the border style info.
- LinkBorderStyle *getBorderStyle() { return borderStyle; }
-
-private:
-
- double x1, y1; // lower left corner
- double x2, y2; // upper right corner
- LinkBorderStyle *borderStyle; // border style
- LinkAction *action; // action
- GBool ok; // is link valid?
-};
-
-//------------------------------------------------------------------------
-// Links
-//------------------------------------------------------------------------
-
-class Links {
-public:
-
- // Extract links from array of annotations.
- Links(Object *annots, GString *baseURI);
-
- // Destructor.
- ~Links();
-
- // Iterate through list of links.
- int getNumLinks() { return numLinks; }
- Link *getLink(int i) { return links[i]; }
-
- // If point <x>,<y> is in a link, return the associated action;
- // else return NULL.
- LinkAction *find(double x, double y);
-
- // Return true if <x>,<y> is in a link.
- GBool onLink(double x, double y);
-
-private:
-
- Link **links;
- int numLinks;
-};
-
-#endif
+++ /dev/null
-top_builddir = ../..
-srcdir = @srcdir@
-top_srcdir = @top_srcdir@
-include ../../Makefile.common
-
-all: libpdf$(A)
-
-libpdf_objects = GHash.$(O) GList.$(O) GString.$(O) gmem.$(O) gfile.$(O) \
- FoFiTrueType.$(O) FoFiType1.$(O) FoFiType1C.$(O) FoFiBase.$(O) FoFiEncodings.$(O) \
- OutputDev.$(O) PDFDoc.$(O) Error.$(O) Stream.$(O) Object.$(O) \
- Decrypt.$(O) Array.$(O) XRef.$(O) Dict.$(O) Parser.$(O) \
- Lexer.$(O) Outline.$(O) PDFDocEncoding.$(O) Catalog.$(O) \
- Link.$(O) GlobalParams.$(O) JBIG2Stream.$(O) Page.$(O) JPXStream.$(O) \
- JArithmeticDecoder.$(O) Gfx.$(O) GfxFont.$(O) CMap.$(O) CharCodeToUnicode.$(O) \
- PSTokenizer.$(O) FontEncodingTables.$(O) BuiltinFont.$(O) BuiltinFontTables.$(O) \
- GfxState.$(O) Function.$(O) Annot.$(O) NameToCharCode.$(O) UnicodeMap.$(O) cmyk.$(O) \
- SecurityHandler.$(O)
-
-cmyk.$(O): cmyk.cc
- $(CC) -I./ cmyk.cc -o $@
-UnicodeMap.$(O): UnicodeMap.cc
- $(CC) -I./ UnicodeMap.cc -o $@
-NameToCharCode.$(O): NameToCharCode.cc
- $(CC) -I./ NameToCharCode.cc -o $@
-Annot.$(O): Annot.cc
- $(CC) -I./ Annot.cc -o $@
-Function.$(O): Function.cc
- $(CC) -I./ Function.cc -o $@
-BuiltinFontTables.$(O): BuiltinFontTables.cc
- $(CC) -I./ BuiltinFontTables.cc -o $@
-BuiltinFont.$(O): BuiltinFont.cc
- $(CC) -I./ BuiltinFont.cc -o $@
-FontEncodingTables.$(O): FontEncodingTables.cc
- $(CC) -I./ FontEncodingTables.cc -o $@
-PSTokenizer.$(O): PSTokenizer.cc
- $(CC) -I./ PSTokenizer.cc -o $@
-CharCodeToUnicode.$(O): CharCodeToUnicode.cc
- $(CC) -I./ CharCodeToUnicode.cc -o $@
-CMap.$(O): CMap.cc
- $(CC) -I./ CMap.cc -o $@
-GfxFont.$(O): GfxFont.cc
- $(CC) -I./ GfxFont.cc -o $@
-Gfx.$(O): Gfx.cc
- $(CC) -I./ Gfx.cc -o $@
-GfxState.$(O): GfxState.cc
- $(CC) -I./ GfxState.cc -o $@
-JArithmeticDecoder.$(O): JArithmeticDecoder.cc
- $(CC) -I./ JArithmeticDecoder.cc -o $@
-JPXStream.$(O): JPXStream.cc
- $(CC) -I./ JPXStream.cc -o $@
-GlobalParams.$(O): GlobalParams.cc GlobalParams.h
- $(CC) -I./ GlobalParams.cc -o $@
-JBIG2Stream.$(O): JBIG2Stream.cc
- $(CC) -I./ JBIG2Stream.cc -o $@
-Page.$(O): Page.cc
- $(CC) -I./ Page.cc -o $@
-Link.$(O): Link.cc
- $(CC) -I./ Link.cc -o $@
-Catalog.$(O): Catalog.cc
- $(CC) -I./ Catalog.cc -o $@
-PDFDocEncoding.$(O): PDFDocEncoding.cc
- $(CC) -I./ PDFDocEncoding.cc -o $@
-Outline.$(O): Outline.cc
- $(CC) -I./ Outline.cc -o $@
-Lexer.$(O): Lexer.cc
- $(CC) -I./ Lexer.cc -o $@
-Parser.$(O): Parser.cc
- $(CC) -I./ Parser.cc -o $@
-XRef.$(O): XRef.cc
- $(CC) -I./ XRef.cc -o $@
-Array.$(O): Array.cc
- $(CC) -I./ Array.cc -o $@
-Dict.$(O): Dict.cc
- $(CC) -I./ Dict.cc -o $@
-Decrypt.$(O): Decrypt.cc
- $(CC) -I./ Decrypt.cc -o $@
-Object.$(O): Object.cc
- $(CC) -I./ Object.cc -o $@
-Error.$(O): Error.cc aconf.h
- $(CC) -I./ Error.cc -o $@
-Stream.$(O): Stream.cc
- $(CC) -I./ Stream.cc -o $@
-PDFDoc.$(O): PDFDoc.cc
- $(CC) -I./ PDFDoc.cc -o $@
-SecurityHandler.$(O): SecurityHandler.cc SecurityHandler.h
- $(CC) -I./ SecurityHandler.cc -o $@
-OutputDev.$(O): OutputDev.cc GfxState.h Stream.h Object.h OutputDev.h gtypes.h CharTypes.h
- $(CC) -I./ OutputDev.cc -o $@
-FoFiBase.$(O): FoFiBase.cc
- $(CC) -I./ FoFiBase.cc -o $@
-FoFiTrueType.$(O): FoFiTrueType.cc FoFiBase.h
- $(CC) -I./ FoFiTrueType.cc -o $@
-FoFiEncodings.$(O): FoFiEncodings.cc FoFiEncodings.h
- $(CC) -I./ FoFiEncodings.cc -o $@
-FoFiType1C.$(O): FoFiType1C.cc FoFiBase.h
- $(CC) -I./ FoFiType1C.cc -o $@
-FoFiType1.$(O): FoFiType1.cc FoFiBase.h
- $(CC) -I./ FoFiType1.cc -o $@
-GList.$(O): GList.cc
- $(CC) -I./ GList.cc -o $@
-GString.$(O): GString.cc
- $(CC) -I./ GString.cc -o $@
-GHash.$(O): GHash.cc
- $(CC) -I./ GHash.cc -o $@
-gfile.$(O): gfile.cc
- $(CC) -I./ gfile.cc -o $@
-gmem.$(O): gmem.c
- $(C) -I./ gmem.c -o $@
-
-libpdf$(A): $(libpdf_objects)
- $(AR) r libpdf$(A) $(libpdf_objects)
- $(RANLIB) libpdf$(A)
-
-install:
-uninstall:
-
-clean:
- rm -f *.o *.obj *.lo *.a *.lib *.la gmon.out
-
+++ /dev/null
-//========================================================================
-//
-// NameToCharCode.cc
-//
-// Copyright 2001-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma implementation
-#endif
-
-#include <string.h>
-#include "gmem.h"
-#include "NameToCharCode.h"
-
-//------------------------------------------------------------------------
-
-struct NameToCharCodeEntry {
- char *name;
- CharCode c;
-};
-
-//------------------------------------------------------------------------
-
-NameToCharCode::NameToCharCode() {
- int i;
-
- size = 31;
- len = 0;
- tab = (NameToCharCodeEntry *)gmallocn(size, sizeof(NameToCharCodeEntry));
- for (i = 0; i < size; ++i) {
- tab[i].name = NULL;
- }
-}
-
-NameToCharCode::~NameToCharCode() {
- int i;
-
- for (i = 0; i < size; ++i) {
- if (tab[i].name) {
- gfree(tab[i].name);
- }
- }
- gfree(tab);
-}
-
-void NameToCharCode::add(char *name, CharCode c) {
- NameToCharCodeEntry *oldTab;
- int h, i, oldSize;
-
- // expand the table if necessary
- if (len >= size / 2) {
- oldSize = size;
- oldTab = tab;
- size = 2*size + 1;
- tab = (NameToCharCodeEntry *)gmallocn(size, sizeof(NameToCharCodeEntry));
- for (h = 0; h < size; ++h) {
- tab[h].name = NULL;
- }
- for (i = 0; i < oldSize; ++i) {
- if (oldTab[i].name) {
- h = hash(oldTab[i].name);
- while (tab[h].name) {
- if (++h == size) {
- h = 0;
- }
- }
- tab[h] = oldTab[i];
- }
- }
- gfree(oldTab);
- }
-
- // add the new name
- h = hash(name);
- while (tab[h].name && strcmp(tab[h].name, name)) {
- if (++h == size) {
- h = 0;
- }
- }
- if (!tab[h].name) {
- tab[h].name = copyString(name);
- }
- tab[h].c = c;
-
- ++len;
-}
-
-CharCode NameToCharCode::lookup(char *name) {
- int h;
-
- h = hash(name);
- while (tab[h].name) {
- if (!strcmp(tab[h].name, name)) {
- return tab[h].c;
- }
- if (++h == size) {
- h = 0;
- }
- }
- return 0;
-}
-
-int NameToCharCode::hash(char *name) {
- char *p;
- unsigned int h;
-
- h = 0;
- for (p = name; *p; ++p) {
- h = 17 * h + (int)(*p & 0xff);
- }
- return (int)(h % size);
-}
+++ /dev/null
-//========================================================================
-//
-// NameToCharCode.h
-//
-// Copyright 2001-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#ifndef NAMETOCHARCODE_H
-#define NAMETOCHARCODE_H
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma interface
-#endif
-
-#include "CharTypes.h"
-
-struct NameToCharCodeEntry;
-
-//------------------------------------------------------------------------
-
-class NameToCharCode {
-public:
-
- NameToCharCode();
- ~NameToCharCode();
-
- void add(char *name, CharCode c);
- CharCode lookup(char *name);
-
-private:
-
- int hash(char *name);
-
- NameToCharCodeEntry *tab;
- int size;
- int len;
-};
-
-#endif
+++ /dev/null
-//========================================================================
-//
-// NameToUnicodeTable.h
-//
-// Copyright 2001-2004 Glyph & Cog, LLC
-//
-//========================================================================
-
-static struct {
- Unicode u;
- char *name;
-} nameToUnicodeTab[] = {
- {0x0021, "!"},
- {0x0023, "#"},
- {0x0024, "$"},
- {0x0025, "%"},
- {0x0026, "&"},
- {0x0027, "'"},
- {0x0028, "("},
- {0x0029, ")"},
- {0x002a, "*"},
- {0x002b, "+"},
- {0x002c, ","},
- {0x002d, "-"},
- {0x002e, "."},
- {0x002f, "/"},
- {0x0030, "0"},
- {0x0031, "1"},
- {0x0032, "2"},
- {0x0033, "3"},
- {0x0034, "4"},
- {0x0035, "5"},
- {0x0036, "6"},
- {0x0037, "7"},
- {0x0038, "8"},
- {0x0039, "9"},
- {0x003a, ":"},
- {0x003b, ";"},
- {0x003c, "<"},
- {0x003d, "="},
- {0x003e, ">"},
- {0x003f, "?"},
- {0x0040, "@"},
- {0x0041, "A"},
- {0x00c6, "AE"},
- {0x01fc, "AEacute"},
- {0xf7e6, "AEsmall"},
- {0x00c1, "Aacute"},
- {0xf7e1, "Aacutesmall"},
- {0x0102, "Abreve"},
- {0x00c2, "Acircumflex"},
- {0xf7e2, "Acircumflexsmall"},
- {0xf6c9, "Acute"},
- {0xf7b4, "Acutesmall"},
- {0x00c4, "Adieresis"},
- {0xf7e4, "Adieresissmall"},
- {0x00c0, "Agrave"},
- {0xf7e0, "Agravesmall"},
- {0x0391, "Alpha"},
- {0x0386, "Alphatonos"},
- {0x0100, "Amacron"},
- {0x0104, "Aogonek"},
- {0x00c5, "Aring"},
- {0x01fa, "Aringacute"},
- {0xf7e5, "Aringsmall"},
- {0xf761, "Asmall"},
- {0x00c3, "Atilde"},
- {0xf7e3, "Atildesmall"},
- {0x0042, "B"},
- {0x0392, "Beta"},
- {0xf6f4, "Brevesmall"},
- {0xf762, "Bsmall"},
- {0x0043, "C"},
- {0x0106, "Cacute"},
- {0xf6ca, "Caron"},
- {0xf6f5, "Caronsmall"},
- {0x010c, "Ccaron"},
- {0x00c7, "Ccedilla"},
- {0xf7e7, "Ccedillasmall"},
- {0x0108, "Ccircumflex"},
- {0x010a, "Cdotaccent"},
- {0xf7b8, "Cedillasmall"},
- {0x03a7, "Chi"},
- {0xf6f6, "Circumflexsmall"},
- {0xf763, "Csmall"},
- {0x0044, "D"},
- {0x010e, "Dcaron"},
- {0x0110, "Dcroat"},
- {0x2206, "Delta"},
- {0xf6cb, "Dieresis"},
- {0xf6cc, "DieresisAcute"},
- {0xf6cd, "DieresisGrave"},
- {0xf7a8, "Dieresissmall"},
- {0xf6f7, "Dotaccentsmall"},
- {0xf764, "Dsmall"},
- {0x0045, "E"},
- {0x00c9, "Eacute"},
- {0xf7e9, "Eacutesmall"},
- {0x0114, "Ebreve"},
- {0x011a, "Ecaron"},
- {0x00ca, "Ecircumflex"},
- {0xf7ea, "Ecircumflexsmall"},
- {0x00cb, "Edieresis"},
- {0xf7eb, "Edieresissmall"},
- {0x0116, "Edotaccent"},
- {0x00c8, "Egrave"},
- {0xf7e8, "Egravesmall"},
- {0x0112, "Emacron"},
- {0x014a, "Eng"},
- {0x0118, "Eogonek"},
- {0x0395, "Epsilon"},
- {0x0388, "Epsilontonos"},
- {0xf765, "Esmall"},
- {0x0397, "Eta"},
- {0x0389, "Etatonos"},
- {0x00d0, "Eth"},
- {0xf7f0, "Ethsmall"},
- {0x20ac, "Euro"},
- {0x0046, "F"},
- {0xf766, "Fsmall"},
- {0x0047, "G"},
- {0x0393, "Gamma"},
- {0x011e, "Gbreve"},
- {0x01e6, "Gcaron"},
- {0x011c, "Gcircumflex"},
- {0x0122, "Gcommaaccent"},
- {0x0120, "Gdotaccent"},
- {0xf6ce, "Grave"},
- {0xf760, "Gravesmall"},
- {0xf767, "Gsmall"},
- {0x0048, "H"},
- {0x25cf, "H18533"},
- {0x25aa, "H18543"},
- {0x25ab, "H18551"},
- {0x25a1, "H22073"},
- {0x0126, "Hbar"},
- {0x0124, "Hcircumflex"},
- {0xf768, "Hsmall"},
- {0xf6cf, "Hungarumlaut"},
- {0xf6f8, "Hungarumlautsmall"},
- {0x0049, "I"},
- {0x0132, "IJ"},
- {0x00cd, "Iacute"},
- {0xf7ed, "Iacutesmall"},
- {0x012c, "Ibreve"},
- {0x00ce, "Icircumflex"},
- {0xf7ee, "Icircumflexsmall"},
- {0x00cf, "Idieresis"},
- {0xf7ef, "Idieresissmall"},
- {0x0130, "Idotaccent"},
- {0x2111, "Ifraktur"},
- {0x00cc, "Igrave"},
- {0xf7ec, "Igravesmall"},
- {0x012a, "Imacron"},
- {0x012e, "Iogonek"},
- {0x0399, "Iota"},
- {0x03aa, "Iotadieresis"},
- {0x038a, "Iotatonos"},
- {0xf769, "Ismall"},
- {0x0128, "Itilde"},
- {0x004a, "J"},
- {0x0134, "Jcircumflex"},
- {0xf76a, "Jsmall"},
- {0x004b, "K"},
- {0x039a, "Kappa"},
- {0x0136, "Kcommaaccent"},
- {0xf76b, "Ksmall"},
- {0x004c, "L"},
- {0xf6bf, "LL"},
- {0x0139, "Lacute"},
- {0x039b, "Lambda"},
- {0x013d, "Lcaron"},
- {0x013b, "Lcommaaccent"},
- {0x013f, "Ldot"},
- {0x0141, "Lslash"},
- {0xf6f9, "Lslashsmall"},
- {0xf76c, "Lsmall"},
- {0x004d, "M"},
- {0xf6d0, "Macron"},
- {0xf7af, "Macronsmall"},
- {0xf76d, "Msmall"},
- {0x039c, "Mu"},
- {0x004e, "N"},
- {0x0143, "Nacute"},
- {0x0147, "Ncaron"},
- {0x0145, "Ncommaaccent"},
- {0xf76e, "Nsmall"},
- {0x00d1, "Ntilde"},
- {0xf7f1, "Ntildesmall"},
- {0x039d, "Nu"},
- {0x004f, "O"},
- {0x0152, "OE"},
- {0xf6fa, "OEsmall"},
- {0x00d3, "Oacute"},
- {0xf7f3, "Oacutesmall"},
- {0x014e, "Obreve"},
- {0x00d4, "Ocircumflex"},
- {0xf7f4, "Ocircumflexsmall"},
- {0x00d6, "Odieresis"},
- {0xf7f6, "Odieresissmall"},
- {0xf6fb, "Ogoneksmall"},
- {0x00d2, "Ograve"},
- {0xf7f2, "Ogravesmall"},
- {0x01a0, "Ohorn"},
- {0x0150, "Ohungarumlaut"},
- {0x014c, "Omacron"},
- {0x2126, "Omega"},
- {0x038f, "Omegatonos"},
- {0x039f, "Omicron"},
- {0x038c, "Omicrontonos"},
- {0x00d8, "Oslash"},
- {0x01fe, "Oslashacute"},
- {0xf7f8, "Oslashsmall"},
- {0xf76f, "Osmall"},
- {0x00d5, "Otilde"},
- {0xf7f5, "Otildesmall"},
- {0x0050, "P"},
- {0x03a6, "Phi"},
- {0x03a0, "Pi"},
- {0x03a8, "Psi"},
- {0xf770, "Psmall"},
- {0x0051, "Q"},
- {0xf771, "Qsmall"},
- {0x0052, "R"},
- {0x0154, "Racute"},
- {0x0158, "Rcaron"},
- {0x0156, "Rcommaaccent"},
- {0x211c, "Rfraktur"},
- {0x03a1, "Rho"},
- {0xf6fc, "Ringsmall"},
- {0xf772, "Rsmall"},
- {0x0053, "S"},
- {0x250c, "SF010000"},
- {0x2514, "SF020000"},
- {0x2510, "SF030000"},
- {0x2518, "SF040000"},
- {0x253c, "SF050000"},
- {0x252c, "SF060000"},
- {0x2534, "SF070000"},
- {0x251c, "SF080000"},
- {0x2524, "SF090000"},
- {0x2500, "SF100000"},
- {0x2502, "SF110000"},
- {0x2561, "SF190000"},
- {0x2562, "SF200000"},
- {0x2556, "SF210000"},
- {0x2555, "SF220000"},
- {0x2563, "SF230000"},
- {0x2551, "SF240000"},
- {0x2557, "SF250000"},
- {0x255d, "SF260000"},
- {0x255c, "SF270000"},
- {0x255b, "SF280000"},
- {0x255e, "SF360000"},
- {0x255f, "SF370000"},
- {0x255a, "SF380000"},
- {0x2554, "SF390000"},
- {0x2569, "SF400000"},
- {0x2566, "SF410000"},
- {0x2560, "SF420000"},
- {0x2550, "SF430000"},
- {0x256c, "SF440000"},
- {0x2567, "SF450000"},
- {0x2568, "SF460000"},
- {0x2564, "SF470000"},
- {0x2565, "SF480000"},
- {0x2559, "SF490000"},
- {0x2558, "SF500000"},
- {0x2552, "SF510000"},
- {0x2553, "SF520000"},
- {0x256b, "SF530000"},
- {0x256a, "SF540000"},
- {0x015a, "Sacute"},
- {0x0160, "Scaron"},
- {0xf6fd, "Scaronsmall"},
- {0x015e, "Scedilla"},
- {0x015c, "Scircumflex"},
- {0x0218, "Scommaaccent"},
- {0x03a3, "Sigma"},
- {0xf773, "Ssmall"},
- {0x0054, "T"},
- {0x03a4, "Tau"},
- {0x0166, "Tbar"},
- {0x0164, "Tcaron"},
- {0x0162, "Tcommaaccent"},
- {0x0398, "Theta"},
- {0x00de, "Thorn"},
- {0xf7fe, "Thornsmall"},
- {0xf6fe, "Tildesmall"},
- {0xf774, "Tsmall"},
- {0x0055, "U"},
- {0x00da, "Uacute"},
- {0xf7fa, "Uacutesmall"},
- {0x016c, "Ubreve"},
- {0x00db, "Ucircumflex"},
- {0xf7fb, "Ucircumflexsmall"},
- {0x00dc, "Udieresis"},
- {0xf7fc, "Udieresissmall"},
- {0x00d9, "Ugrave"},
- {0xf7f9, "Ugravesmall"},
- {0x01af, "Uhorn"},
- {0x0170, "Uhungarumlaut"},
- {0x016a, "Umacron"},
- {0x0172, "Uogonek"},
- {0x03a5, "Upsilon"},
- {0x03d2, "Upsilon1"},
- {0x03ab, "Upsilondieresis"},
- {0x038e, "Upsilontonos"},
- {0x016e, "Uring"},
- {0xf775, "Usmall"},
- {0x0168, "Utilde"},
- {0x0056, "V"},
- {0xf776, "Vsmall"},
- {0x0057, "W"},
- {0x1e82, "Wacute"},
- {0x0174, "Wcircumflex"},
- {0x1e84, "Wdieresis"},
- {0x1e80, "Wgrave"},
- {0xf777, "Wsmall"},
- {0x0058, "X"},
- {0x039e, "Xi"},
- {0xf778, "Xsmall"},
- {0x0059, "Y"},
- {0x00dd, "Yacute"},
- {0xf7fd, "Yacutesmall"},
- {0x0176, "Ycircumflex"},
- {0x0178, "Ydieresis"},
- {0xf7ff, "Ydieresissmall"},
- {0x1ef2, "Ygrave"},
- {0xf779, "Ysmall"},
- {0x005a, "Z"},
- {0x0179, "Zacute"},
- {0x017d, "Zcaron"},
- {0xf6ff, "Zcaronsmall"},
- {0x017b, "Zdotaccent"},
- {0x0396, "Zeta"},
- {0xf77a, "Zsmall"},
- {0x0022, "\""},
- {0x005c, "\\"},
- {0x005d, "]"},
- {0x005e, "^"},
- {0x005f, "_"},
- {0x0060, "`"},
- {0x0061, "a"},
- {0x00e1, "aacute"},
- {0x0103, "abreve"},
- {0x00e2, "acircumflex"},
- {0x00b4, "acute"},
- {0x0301, "acutecomb"},
- {0x00e4, "adieresis"},
- {0x00e6, "ae"},
- {0x01fd, "aeacute"},
- {0x2015, "afii00208"},
- {0x0410, "afii10017"},
- {0x0411, "afii10018"},
- {0x0412, "afii10019"},
- {0x0413, "afii10020"},
- {0x0414, "afii10021"},
- {0x0415, "afii10022"},
- {0x0401, "afii10023"},
- {0x0416, "afii10024"},
- {0x0417, "afii10025"},
- {0x0418, "afii10026"},
- {0x0419, "afii10027"},
- {0x041a, "afii10028"},
- {0x041b, "afii10029"},
- {0x041c, "afii10030"},
- {0x041d, "afii10031"},
- {0x041e, "afii10032"},
- {0x041f, "afii10033"},
- {0x0420, "afii10034"},
- {0x0421, "afii10035"},
- {0x0422, "afii10036"},
- {0x0423, "afii10037"},
- {0x0424, "afii10038"},
- {0x0425, "afii10039"},
- {0x0426, "afii10040"},
- {0x0427, "afii10041"},
- {0x0428, "afii10042"},
- {0x0429, "afii10043"},
- {0x042a, "afii10044"},
- {0x042b, "afii10045"},
- {0x042c, "afii10046"},
- {0x042d, "afii10047"},
- {0x042e, "afii10048"},
- {0x042f, "afii10049"},
- {0x0490, "afii10050"},
- {0x0402, "afii10051"},
- {0x0403, "afii10052"},
- {0x0404, "afii10053"},
- {0x0405, "afii10054"},
- {0x0406, "afii10055"},
- {0x0407, "afii10056"},
- {0x0408, "afii10057"},
- {0x0409, "afii10058"},
- {0x040a, "afii10059"},
- {0x040b, "afii10060"},
- {0x040c, "afii10061"},
- {0x040e, "afii10062"},
- {0xf6c4, "afii10063"},
- {0xf6c5, "afii10064"},
- {0x0430, "afii10065"},
- {0x0431, "afii10066"},
- {0x0432, "afii10067"},
- {0x0433, "afii10068"},
- {0x0434, "afii10069"},
- {0x0435, "afii10070"},
- {0x0451, "afii10071"},
- {0x0436, "afii10072"},
- {0x0437, "afii10073"},
- {0x0438, "afii10074"},
- {0x0439, "afii10075"},
- {0x043a, "afii10076"},
- {0x043b, "afii10077"},
- {0x043c, "afii10078"},
- {0x043d, "afii10079"},
- {0x043e, "afii10080"},
- {0x043f, "afii10081"},
- {0x0440, "afii10082"},
- {0x0441, "afii10083"},
- {0x0442, "afii10084"},
- {0x0443, "afii10085"},
- {0x0444, "afii10086"},
- {0x0445, "afii10087"},
- {0x0446, "afii10088"},
- {0x0447, "afii10089"},
- {0x0448, "afii10090"},
- {0x0449, "afii10091"},
- {0x044a, "afii10092"},
- {0x044b, "afii10093"},
- {0x044c, "afii10094"},
- {0x044d, "afii10095"},
- {0x044e, "afii10096"},
- {0x044f, "afii10097"},
- {0x0491, "afii10098"},
- {0x0452, "afii10099"},
- {0x0453, "afii10100"},
- {0x0454, "afii10101"},
- {0x0455, "afii10102"},
- {0x0456, "afii10103"},
- {0x0457, "afii10104"},
- {0x0458, "afii10105"},
- {0x0459, "afii10106"},
- {0x045a, "afii10107"},
- {0x045b, "afii10108"},
- {0x045c, "afii10109"},
- {0x045e, "afii10110"},
- {0x040f, "afii10145"},
- {0x0462, "afii10146"},
- {0x0472, "afii10147"},
- {0x0474, "afii10148"},
- {0xf6c6, "afii10192"},
- {0x045f, "afii10193"},
- {0x0463, "afii10194"},
- {0x0473, "afii10195"},
- {0x0475, "afii10196"},
- {0xf6c7, "afii10831"},
- {0xf6c8, "afii10832"},
- {0x04d9, "afii10846"},
- {0x200e, "afii299"},
- {0x200f, "afii300"},
- {0x200d, "afii301"},
- {0x066a, "afii57381"},
- {0x060c, "afii57388"},
- {0x0660, "afii57392"},
- {0x0661, "afii57393"},
- {0x0662, "afii57394"},
- {0x0663, "afii57395"},
- {0x0664, "afii57396"},
- {0x0665, "afii57397"},
- {0x0666, "afii57398"},
- {0x0667, "afii57399"},
- {0x0668, "afii57400"},
- {0x0669, "afii57401"},
- {0x061b, "afii57403"},
- {0x061f, "afii57407"},
- {0x0621, "afii57409"},
- {0x0622, "afii57410"},
- {0x0623, "afii57411"},
- {0x0624, "afii57412"},
- {0x0625, "afii57413"},
- {0x0626, "afii57414"},
- {0x0627, "afii57415"},
- {0x0628, "afii57416"},
- {0x0629, "afii57417"},
- {0x062a, "afii57418"},
- {0x062b, "afii57419"},
- {0x062c, "afii57420"},
- {0x062d, "afii57421"},
- {0x062e, "afii57422"},
- {0x062f, "afii57423"},
- {0x0630, "afii57424"},
- {0x0631, "afii57425"},
- {0x0632, "afii57426"},
- {0x0633, "afii57427"},
- {0x0634, "afii57428"},
- {0x0635, "afii57429"},
- {0x0636, "afii57430"},
- {0x0637, "afii57431"},
- {0x0638, "afii57432"},
- {0x0639, "afii57433"},
- {0x063a, "afii57434"},
- {0x0640, "afii57440"},
- {0x0641, "afii57441"},
- {0x0642, "afii57442"},
- {0x0643, "afii57443"},
- {0x0644, "afii57444"},
- {0x0645, "afii57445"},
- {0x0646, "afii57446"},
- {0x0648, "afii57448"},
- {0x0649, "afii57449"},
- {0x064a, "afii57450"},
- {0x064b, "afii57451"},
- {0x064c, "afii57452"},
- {0x064d, "afii57453"},
- {0x064e, "afii57454"},
- {0x064f, "afii57455"},
- {0x0650, "afii57456"},
- {0x0651, "afii57457"},
- {0x0652, "afii57458"},
- {0x0647, "afii57470"},
- {0x06a4, "afii57505"},
- {0x067e, "afii57506"},
- {0x0686, "afii57507"},
- {0x0698, "afii57508"},
- {0x06af, "afii57509"},
- {0x0679, "afii57511"},
- {0x0688, "afii57512"},
- {0x0691, "afii57513"},
- {0x06ba, "afii57514"},
- {0x06d2, "afii57519"},
- {0x06d5, "afii57534"},
- {0x20aa, "afii57636"},
- {0x05be, "afii57645"},
- {0x05c3, "afii57658"},
- {0x05d0, "afii57664"},
- {0x05d1, "afii57665"},
- {0x05d2, "afii57666"},
- {0x05d3, "afii57667"},
- {0x05d4, "afii57668"},
- {0x05d5, "afii57669"},
- {0x05d6, "afii57670"},
- {0x05d7, "afii57671"},
- {0x05d8, "afii57672"},
- {0x05d9, "afii57673"},
- {0x05da, "afii57674"},
- {0x05db, "afii57675"},
- {0x05dc, "afii57676"},
- {0x05dd, "afii57677"},
- {0x05de, "afii57678"},
- {0x05df, "afii57679"},
- {0x05e0, "afii57680"},
- {0x05e1, "afii57681"},
- {0x05e2, "afii57682"},
- {0x05e3, "afii57683"},
- {0x05e4, "afii57684"},
- {0x05e5, "afii57685"},
- {0x05e6, "afii57686"},
- {0x05e7, "afii57687"},
- {0x05e8, "afii57688"},
- {0x05e9, "afii57689"},
- {0x05ea, "afii57690"},
- {0xfb2a, "afii57694"},
- {0xfb2b, "afii57695"},
- {0xfb4b, "afii57700"},
- {0xfb1f, "afii57705"},
- {0x05f0, "afii57716"},
- {0x05f1, "afii57717"},
- {0x05f2, "afii57718"},
- {0xfb35, "afii57723"},
- {0x05b4, "afii57793"},
- {0x05b5, "afii57794"},
- {0x05b6, "afii57795"},
- {0x05bb, "afii57796"},
- {0x05b8, "afii57797"},
- {0x05b7, "afii57798"},
- {0x05b0, "afii57799"},
- {0x05b2, "afii57800"},
- {0x05b1, "afii57801"},
- {0x05b3, "afii57802"},
- {0x05c2, "afii57803"},
- {0x05c1, "afii57804"},
- {0x05b9, "afii57806"},
- {0x05bc, "afii57807"},
- {0x05bd, "afii57839"},
- {0x05bf, "afii57841"},
- {0x05c0, "afii57842"},
- {0x02bc, "afii57929"},
- {0x2105, "afii61248"},
- {0x2113, "afii61289"},
- {0x2116, "afii61352"},
- {0x202c, "afii61573"},
- {0x202d, "afii61574"},
- {0x202e, "afii61575"},
- {0x200c, "afii61664"},
- {0x066d, "afii63167"},
- {0x02bd, "afii64937"},
- {0x00e0, "agrave"},
- {0x2135, "aleph"},
- {0x03b1, "alpha"},
- {0x03ac, "alphatonos"},
- {0x0101, "amacron"},
- {0x0026, "ampersand"},
- {0xf726, "ampersandsmall"},
- {0x2220, "angle"},
- {0x2329, "angleleft"},
- {0x232a, "angleright"},
- {0x0387, "anoteleia"},
- {0x0105, "aogonek"},
- {0x2248, "approxequal"},
- {0x00e5, "aring"},
- {0x01fb, "aringacute"},
- {0x2194, "arrowboth"},
- {0x21d4, "arrowdblboth"},
- {0x21d3, "arrowdbldown"},
- {0x21d0, "arrowdblleft"},
- {0x21d2, "arrowdblright"},
- {0x21d1, "arrowdblup"},
- {0x2193, "arrowdown"},
- {0xf8e7, "arrowhorizex"},
- {0x2190, "arrowleft"},
- {0x2192, "arrowright"},
- {0x2191, "arrowup"},
- {0x2195, "arrowupdn"},
- {0x21a8, "arrowupdnbse"},
- {0xf8e6, "arrowvertex"},
- {0x005e, "asciicircum"},
- {0x007e, "asciitilde"},
- {0x002a, "asterisk"},
- {0x2217, "asteriskmath"},
- {0xf6e9, "asuperior"},
- {0x0040, "at"},
- {0x00e3, "atilde"},
- {0x0062, "b"},
- {0x005c, "backslash"},
- {0x007c, "bar"},
- {0x03b2, "beta"},
- {0x2588, "block"},
- {0xf8f4, "braceex"},
- {0x007b, "braceleft"},
- {0xf8f3, "braceleftbt"},
- {0xf8f2, "braceleftmid"},
- {0xf8f1, "bracelefttp"},
- {0x007d, "braceright"},
- {0xf8fe, "bracerightbt"},
- {0xf8fd, "bracerightmid"},
- {0xf8fc, "bracerighttp"},
- {0x005b, "bracketleft"},
- {0xf8f0, "bracketleftbt"},
- {0xf8ef, "bracketleftex"},
- {0xf8ee, "bracketlefttp"},
- {0x005d, "bracketright"},
- {0xf8fb, "bracketrightbt"},
- {0xf8fa, "bracketrightex"},
- {0xf8f9, "bracketrighttp"},
- {0x02d8, "breve"},
- {0x00a6, "brokenbar"},
- {0xf6ea, "bsuperior"},
- {0x2022, "bullet"},
- {0x0063, "c"},
- {0x0107, "cacute"},
- {0x02c7, "caron"},
- {0x21b5, "carriagereturn"},
- {0x010d, "ccaron"},
- {0x00e7, "ccedilla"},
- {0x0109, "ccircumflex"},
- {0x010b, "cdotaccent"},
- {0x00b8, "cedilla"},
- {0x00a2, "cent"},
- {0xf6df, "centinferior"},
- {0xf7a2, "centoldstyle"},
- {0xf6e0, "centsuperior"},
- {0x03c7, "chi"},
- {0x25cb, "circle"},
- {0x2297, "circlemultiply"},
- {0x2295, "circleplus"},
- {0x02c6, "circumflex"},
- {0x2663, "club"},
- {0x003a, "colon"},
- {0x20a1, "colonmonetary"},
- {0x002c, "comma"},
- {0xf6c3, "commaaccent"},
- {0xf6e1, "commainferior"},
- {0xf6e2, "commasuperior"},
- {0x2245, "congruent"},
- {0x00a9, "copyright"},
- {0x00a9, "copyrightsans"},
- {0x00a9, "copyrightserif"},
- {0x00a4, "currency"},
- {0xf6d1, "cyrBreve"},
- {0xf6d2, "cyrFlex"},
- {0xf6d4, "cyrbreve"},
- {0xf6d5, "cyrflex"},
- {0x0064, "d"},
- {0x2020, "dagger"},
- {0x2021, "daggerdbl"},
- {0xf6d3, "dblGrave"},
- {0xf6d6, "dblgrave"},
- {0x010f, "dcaron"},
- {0x0111, "dcroat"},
- {0x00b0, "degree"},
- {0x03b4, "delta"},
- {0x2666, "diamond"},
- {0x00a8, "dieresis"},
- {0xf6d7, "dieresisacute"},
- {0xf6d8, "dieresisgrave"},
- {0x0385, "dieresistonos"},
- {0x00f7, "divide"},
- {0x2593, "dkshade"},
- {0x2584, "dnblock"},
- {0x0024, "dollar"},
- {0xf6e3, "dollarinferior"},
- {0xf724, "dollaroldstyle"},
- {0xf6e4, "dollarsuperior"},
- {0x20ab, "dong"},
- {0x02d9, "dotaccent"},
- {0x0323, "dotbelowcomb"},
- {0x0131, "dotlessi"},
- {0xf6be, "dotlessj"},
- {0x22c5, "dotmath"},
- {0xf6eb, "dsuperior"},
- {0x0065, "e"},
- {0x00e9, "eacute"},
- {0x0115, "ebreve"},
- {0x011b, "ecaron"},
- {0x00ea, "ecircumflex"},
- {0x00eb, "edieresis"},
- {0x0117, "edotaccent"},
- {0x00e8, "egrave"},
- {0x0038, "eight"},
- {0x2088, "eightinferior"},
- {0xf738, "eightoldstyle"},
- {0x2078, "eightsuperior"},
- {0x2208, "element"},
- {0x2026, "ellipsis"},
- {0x0113, "emacron"},
- {0x2014, "emdash"},
- {0x2205, "emptyset"},
- {0x2013, "endash"},
- {0x014b, "eng"},
- {0x0119, "eogonek"},
- {0x03b5, "epsilon"},
- {0x03ad, "epsilontonos"},
- {0x003d, "equal"},
- {0x2261, "equivalence"},
- {0x212e, "estimated"},
- {0xf6ec, "esuperior"},
- {0x03b7, "eta"},
- {0x03ae, "etatonos"},
- {0x00f0, "eth"},
- {0x0021, "exclam"},
- {0x203c, "exclamdbl"},
- {0x00a1, "exclamdown"},
- {0xf7a1, "exclamdownsmall"},
- {0x0021, "exclamleft"},
- {0xf721, "exclamsmall"},
- {0x2203, "existential"},
- {0x0066, "f"},
- {0x2640, "female"},
- {0xfb00, "ff"},
- {0xfb03, "ffi"},
- {0xfb04, "ffl"},
- {0xfb01, "fi"},
- {0x2012, "figuredash"},
- {0x25a0, "filledbox"},
- {0x25ac, "filledrect"},
- {0x0035, "five"},
- {0x215d, "fiveeighths"},
- {0x2085, "fiveinferior"},
- {0xf735, "fiveoldstyle"},
- {0x2075, "fivesuperior"},
- {0xfb02, "fl"},
- {0x0192, "florin"},
- {0x0034, "four"},
- {0x2084, "fourinferior"},
- {0xf734, "fouroldstyle"},
- {0x2074, "foursuperior"},
- {0x2044, "fraction"},
- {0x20a3, "franc"},
- {0x0067, "g"},
- {0x03b3, "gamma"},
- {0x011f, "gbreve"},
- {0x01e7, "gcaron"},
- {0x011d, "gcircumflex"},
- {0x0123, "gcommaaccent"},
- {0x0121, "gdotaccent"},
- {0x00df, "germandbls"},
- {0x2207, "gradient"},
- {0x0060, "grave"},
- {0x0300, "gravecomb"},
- {0x003e, "greater"},
- {0x2265, "greaterequal"},
- {0x00ab, "guillemotleft"},
- {0x00bb, "guillemotright"},
- {0x2039, "guilsinglleft"},
- {0x203a, "guilsinglright"},
- {0x0068, "h"},
- {0x0127, "hbar"},
- {0x0125, "hcircumflex"},
- {0x2665, "heart"},
- {0x0309, "hookabovecomb"},
- {0x2302, "house"},
- {0x02dd, "hungarumlaut"},
- {0x002d, "hyphen"},
- {0xf6e5, "hypheninferior"},
- {0xf6e6, "hyphensuperior"},
- {0x0069, "i"},
- {0x00ed, "iacute"},
- {0x012d, "ibreve"},
- {0x00ee, "icircumflex"},
- {0x00ef, "idieresis"},
- {0x00ec, "igrave"},
- {0x0133, "ij"},
- {0x012b, "imacron"},
- {0x221e, "infinity"},
- {0x222b, "integral"},
- {0x2321, "integralbt"},
- {0xf8f5, "integralex"},
- {0x2320, "integraltp"},
- {0x2229, "intersection"},
- {0x25d8, "invbullet"},
- {0x25d9, "invcircle"},
- {0x263b, "invsmileface"},
- {0x012f, "iogonek"},
- {0x03b9, "iota"},
- {0x03ca, "iotadieresis"},
- {0x0390, "iotadieresistonos"},
- {0x03af, "iotatonos"},
- {0xf6ed, "isuperior"},
- {0x0129, "itilde"},
- {0x006a, "j"},
- {0x0135, "jcircumflex"},
- {0x006b, "k"},
- {0x03ba, "kappa"},
- {0x0137, "kcommaaccent"},
- {0x0138, "kgreenlandic"},
- {0x006c, "l"},
- {0x013a, "lacute"},
- {0x03bb, "lambda"},
- {0x013e, "lcaron"},
- {0x013c, "lcommaaccent"},
- {0x0140, "ldot"},
- {0x003c, "less"},
- {0x2264, "lessequal"},
- {0x258c, "lfblock"},
- {0x20a4, "lira"},
- {0xf6c0, "ll"},
- {0x2227, "logicaland"},
- {0x00ac, "logicalnot"},
- {0x2228, "logicalor"},
- {0x017f, "longs"},
- {0x25ca, "lozenge"},
- {0x0142, "lslash"},
- {0xf6ee, "lsuperior"},
- {0x2591, "ltshade"},
- {0x006d, "m"},
- {0x00af, "macron"},
- {0x2642, "male"},
- {0x2212, "minus"},
- {0x2032, "minute"},
- {0xf6ef, "msuperior"},
- {0x00b5, "mu"},
- {0x00d7, "multiply"},
- {0x266a, "musicalnote"},
- {0x266b, "musicalnotedbl"},
- {0x006e, "n"},
- {0x0144, "nacute"},
- {0x0149, "napostrophe"},
- {0x00a0, "nbspace"},
- {0x0148, "ncaron"},
- {0x0146, "ncommaaccent"},
- {0x0039, "nine"},
- {0x2089, "nineinferior"},
- {0xf739, "nineoldstyle"},
- {0x2079, "ninesuperior"},
- {0x00a0, "nonbreakingspace"},
- {0x2209, "notelement"},
- {0x2260, "notequal"},
- {0x2284, "notsubset"},
- {0x207f, "nsuperior"},
- {0x00f1, "ntilde"},
- {0x03bd, "nu"},
- {0x0023, "numbersign"},
- {0x006f, "o"},
- {0x00f3, "oacute"},
- {0x014f, "obreve"},
- {0x00f4, "ocircumflex"},
- {0x00f6, "odieresis"},
- {0x0153, "oe"},
- {0x02db, "ogonek"},
- {0x00f2, "ograve"},
- {0x01a1, "ohorn"},
- {0x0151, "ohungarumlaut"},
- {0x014d, "omacron"},
- {0x03c9, "omega"},
- {0x03d6, "omega1"},
- {0x03ce, "omegatonos"},
- {0x03bf, "omicron"},
- {0x03cc, "omicrontonos"},
- {0x0031, "one"},
- {0x2024, "onedotenleader"},
- {0x215b, "oneeighth"},
- {0xf6dc, "onefitted"},
- {0x00bd, "onehalf"},
- {0x2081, "oneinferior"},
- {0xf731, "oneoldstyle"},
- {0x00bc, "onequarter"},
- {0x00b9, "onesuperior"},
- {0x2153, "onethird"},
- {0x25e6, "openbullet"},
- {0x00aa, "ordfeminine"},
- {0x00ba, "ordmasculine"},
- {0x221f, "orthogonal"},
- {0x00f8, "oslash"},
- {0x01ff, "oslashacute"},
- {0xf6f0, "osuperior"},
- {0x00f5, "otilde"},
- {0x0070, "p"},
- {0x00b6, "paragraph"},
- {0x0028, "parenleft"},
- {0xf8ed, "parenleftbt"},
- {0xf8ec, "parenleftex"},
- {0x208d, "parenleftinferior"},
- {0x207d, "parenleftsuperior"},
- {0xf8eb, "parenlefttp"},
- {0x0029, "parenright"},
- {0xf8f8, "parenrightbt"},
- {0xf8f7, "parenrightex"},
- {0x208e, "parenrightinferior"},
- {0x207e, "parenrightsuperior"},
- {0xf8f6, "parenrighttp"},
- {0x2202, "partialdiff"},
- {0x0025, "percent"},
- {0x002e, "period"},
- {0x00b7, "periodcentered"},
- {0xf6e7, "periodinferior"},
- {0xf6e8, "periodsuperior"},
- {0x22a5, "perpendicular"},
- {0x2030, "perthousand"},
- {0x20a7, "peseta"},
- {0x03c6, "phi"},
- {0x03d5, "phi1"},
- {0x03c0, "pi"},
- {0x002b, "plus"},
- {0x00b1, "plusminus"},
- {0x211e, "prescription"},
- {0x220f, "product"},
- {0x2282, "propersubset"},
- {0x2283, "propersuperset"},
- {0x221d, "proportional"},
- {0x03c8, "psi"},
- {0x0071, "q"},
- {0x003f, "question"},
- {0x00bf, "questiondown"},
- {0xf7bf, "questiondownsmall"},
- {0xf73f, "questionsmall"},
- {0x0022, "quotedbl"},
- {0x201e, "quotedblbase"},
- {0x201c, "quotedblleft"},
- {0x201d, "quotedblright"},
- {0x2018, "quoteleft"},
- {0x201b, "quotereversed"},
- {0x2019, "quoteright"},
- {0x201a, "quotesinglbase"},
- {0x0027, "quotesingle"},
- {0x0072, "r"},
- {0x0155, "racute"},
- {0x221a, "radical"},
- {0xf8e5, "radicalex"},
- {0x0159, "rcaron"},
- {0x0157, "rcommaaccent"},
- {0x2286, "reflexsubset"},
- {0x2287, "reflexsuperset"},
- {0x00ae, "registered"},
- {0x00ae, "registersans"},
- {0x00ae, "registerserif"},
- {0x2310, "revlogicalnot"},
- {0x03c1, "rho"},
- {0x02da, "ring"},
- {0xf6f1, "rsuperior"},
- {0x2590, "rtblock"},
- {0xf6dd, "rupiah"},
- {0x0073, "s"},
- {0x015b, "sacute"},
- {0x0161, "scaron"},
- {0x015f, "scedilla"},
- {0x015d, "scircumflex"},
- {0x0219, "scommaaccent"},
- {0x2033, "second"},
- {0x00a7, "section"},
- {0x003b, "semicolon"},
- {0x0037, "seven"},
- {0x215e, "seveneighths"},
- {0x2087, "seveninferior"},
- {0xf737, "sevenoldstyle"},
- {0x2077, "sevensuperior"},
- {0x2592, "shade"},
- {0x03c3, "sigma"},
- {0x03c2, "sigma1"},
- {0x223c, "similar"},
- {0x0036, "six"},
- {0x2086, "sixinferior"},
- {0xf736, "sixoldstyle"},
- {0x2076, "sixsuperior"},
- {0x002f, "slash"},
- {0x263a, "smileface"},
- {0x0020, "space"},
- {0x2660, "spade"},
- {0xf6f2, "ssuperior"},
- {0x00a3, "sterling"},
- {0x220b, "suchthat"},
- {0x2211, "summation"},
- {0x263c, "sun"},
- {0x0074, "t"},
- {0x03c4, "tau"},
- {0x0167, "tbar"},
- {0x0165, "tcaron"},
- {0x0163, "tcommaaccent"},
- {0x2234, "therefore"},
- {0x03b8, "theta"},
- {0x03d1, "theta1"},
- {0x00fe, "thorn"},
- {0x0033, "three"},
- {0x215c, "threeeighths"},
- {0x2083, "threeinferior"},
- {0xf733, "threeoldstyle"},
- {0x00be, "threequarters"},
- {0xf6de, "threequartersemdash"},
- {0x00b3, "threesuperior"},
- {0x02dc, "tilde"},
- {0x0303, "tildecomb"},
- {0x0384, "tonos"},
- {0x2122, "trademark"},
- {0x2122, "trademarksans"},
- {0x2122, "trademarkserif"},
- {0x25bc, "triagdn"},
- {0x25c4, "triaglf"},
- {0x25ba, "triagrt"},
- {0x25b2, "triagup"},
- {0xf6f3, "tsuperior"},
- {0x0032, "two"},
- {0x2025, "twodotenleader"},
- {0x2082, "twoinferior"},
- {0xf732, "twooldstyle"},
- {0x00b2, "twosuperior"},
- {0x2154, "twothirds"},
- {0x0075, "u"},
- {0x00fa, "uacute"},
- {0x016d, "ubreve"},
- {0x00fb, "ucircumflex"},
- {0x00fc, "udieresis"},
- {0x00f9, "ugrave"},
- {0x01b0, "uhorn"},
- {0x0171, "uhungarumlaut"},
- {0x016b, "umacron"},
- {0x005f, "underscore"},
- {0x2017, "underscoredbl"},
- {0x222a, "union"},
- {0x2200, "universal"},
- {0x0173, "uogonek"},
- {0x2580, "upblock"},
- {0x03c5, "upsilon"},
- {0x03cb, "upsilondieresis"},
- {0x03b0, "upsilondieresistonos"},
- {0x03cd, "upsilontonos"},
- {0x016f, "uring"},
- {0x0169, "utilde"},
- {0x0076, "v"},
- {0x0077, "w"},
- {0x1e83, "wacute"},
- {0x0175, "wcircumflex"},
- {0x1e85, "wdieresis"},
- {0x2118, "weierstrass"},
- {0x1e81, "wgrave"},
- {0x0078, "x"},
- {0x03be, "xi"},
- {0x0079, "y"},
- {0x00fd, "yacute"},
- {0x0177, "ycircumflex"},
- {0x00ff, "ydieresis"},
- {0x00a5, "yen"},
- {0x1ef3, "ygrave"},
- {0x007a, "z"},
- {0x017a, "zacute"},
- {0x017e, "zcaron"},
- {0x017c, "zdotaccent"},
- {0x0030, "zero"},
- {0x2080, "zeroinferior"},
- {0xf730, "zerooldstyle"},
- {0x2070, "zerosuperior"},
- {0x03b6, "zeta"},
- {0x007b, "{"},
- {0x007c, "|"},
- {0x007d, "}"},
- {0x007e, "~"},
- { 0, NULL }
-};
+++ /dev/null
-//========================================================================
-//
-// Object.cc
-//
-// Copyright 1996-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma implementation
-#endif
-
-#include <stddef.h>
-#include "Object.h"
-#include "Array.h"
-#include "Dict.h"
-#include "Error.h"
-#include "Stream.h"
-#include "XRef.h"
-
-//------------------------------------------------------------------------
-// Object
-//------------------------------------------------------------------------
-
-char *objTypeNames[numObjTypes] = {
- "boolean",
- "integer",
- "real",
- "string",
- "name",
- "null",
- "array",
- "dictionary",
- "stream",
- "ref",
- "cmd",
- "error",
- "eof",
- "none"
-};
-
-#ifdef DEBUG_MEM
-int Object::numAlloc[numObjTypes] =
- {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
-#endif
-
-Object *Object::initArray(XRef *xref) {
- initObj(objArray);
- array = new Array(xref);
- return this;
-}
-
-Object *Object::initDict(XRef *xref) {
- initObj(objDict);
- dict = new Dict(xref);
- return this;
-}
-
-Object *Object::initDict(Dict *dictA) {
- initObj(objDict);
- dict = dictA;
- dict->incRef();
- return this;
-}
-
-Object *Object::initStream(Stream *streamA) {
- initObj(objStream);
- stream = streamA;
- return this;
-}
-
-Object *Object::copy(Object *obj) {
- *obj = *this;
- switch (type) {
- case objString:
- obj->string = string->copy();
- break;
- case objName:
- obj->name = copyString(name);
- break;
- case objArray:
- array->incRef();
- break;
- case objDict:
- dict->incRef();
- break;
- case objStream:
- stream->incRef();
- break;
- case objCmd:
- obj->cmd = copyString(cmd);
- break;
- default:
- break;
- }
-#ifdef DEBUG_MEM
- ++numAlloc[type];
-#endif
- return obj;
-}
-
-Object *Object::fetch(XRef *xref, Object *obj) {
- return (type == objRef && xref) ?
- xref->fetch(ref.num, ref.gen, obj) : copy(obj);
-}
-
-void Object::free() {
- switch (type) {
- case objString:
- delete string;
- break;
- case objName:
- gfree(name);
- break;
- case objArray:
- if (!array->decRef()) {
- delete array;
- }
- break;
- case objDict:
- if (!dict->decRef()) {
- delete dict;
- }
- break;
- case objStream:
- if (!stream->decRef()) {
- delete stream;
- }
- break;
- case objCmd:
- gfree(cmd);
- break;
- default:
- break;
- }
-#ifdef DEBUG_MEM
- --numAlloc[type];
-#endif
- type = objNone;
-}
-
-char *Object::getTypeName() {
- return objTypeNames[type];
-}
-
-void Object::print(FILE *f) {
- Object obj;
- int i;
-
- switch (type) {
- case objBool:
- fprintf(f, "%s", booln ? "true" : "false");
- break;
- case objInt:
- fprintf(f, "%d", intg);
- break;
- case objReal:
- fprintf(f, "%g", real);
- break;
- case objString:
- fprintf(f, "(");
- fwrite(string->getCString(), 1, string->getLength(), f);
- fprintf(f, ")");
- break;
- case objName:
- fprintf(f, "/%s", name);
- break;
- case objNull:
- fprintf(f, "null");
- break;
- case objArray:
- fprintf(f, "[");
- for (i = 0; i < arrayGetLength(); ++i) {
- if (i > 0)
- fprintf(f, " ");
- arrayGetNF(i, &obj);
- obj.print(f);
- obj.free();
- }
- fprintf(f, "]");
- break;
- case objDict:
- fprintf(f, "<<");
- for (i = 0; i < dictGetLength(); ++i) {
- fprintf(f, " /%s ", dictGetKey(i));
- dictGetValNF(i, &obj);
- obj.print(f);
- obj.free();
- }
- fprintf(f, " >>");
- break;
- case objStream:
- fprintf(f, "<stream>");
- break;
- case objRef:
- fprintf(f, "%d %d R", ref.num, ref.gen);
- break;
- case objCmd:
- fprintf(f, "%s", cmd);
- break;
- case objError:
- fprintf(f, "<error>");
- break;
- case objEOF:
- fprintf(f, "<EOF>");
- break;
- case objNone:
- fprintf(f, "<none>");
- break;
- }
-}
-
-void Object::memCheck(FILE *f) {
-#ifdef DEBUG_MEM
- int i;
- int t;
-
- t = 0;
- for (i = 0; i < numObjTypes; ++i)
- t += numAlloc[i];
- if (t > 0) {
- fprintf(f, "Allocated objects:\n");
- for (i = 0; i < numObjTypes; ++i) {
- if (numAlloc[i] > 0)
- fprintf(f, " %-20s: %6d\n", objTypeNames[i], numAlloc[i]);
- }
- }
-#endif
-}
+++ /dev/null
-//========================================================================
-//
-// Object.h
-//
-// Copyright 1996-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#ifndef OBJECT_H
-#define OBJECT_H
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma interface
-#endif
-
-#include <stdio.h>
-#include <string.h>
-#include "gtypes.h"
-#include "gmem.h"
-#include "GString.h"
-
-class XRef;
-class Array;
-class Dict;
-class Stream;
-
-//------------------------------------------------------------------------
-// Ref
-//------------------------------------------------------------------------
-
-struct Ref {
- int num; // object number
- int gen; // generation number
-};
-
-//------------------------------------------------------------------------
-// object types
-//------------------------------------------------------------------------
-
-enum ObjType {
- // simple objects
- objBool, // boolean
- objInt, // integer
- objReal, // real
- objString, // string
- objName, // name
- objNull, // null
-
- // complex objects
- objArray, // array
- objDict, // dictionary
- objStream, // stream
- objRef, // indirect reference
-
- // special objects
- objCmd, // command name
- objError, // error return from Lexer
- objEOF, // end of file return from Lexer
- objNone // uninitialized object
-};
-
-#define numObjTypes 14 // total number of object types
-
-//------------------------------------------------------------------------
-// Object
-//------------------------------------------------------------------------
-
-#ifdef DEBUG_MEM
-#define initObj(t) ++numAlloc[type = t]
-#else
-#define initObj(t) type = t
-#endif
-
-class Object {
-public:
-
- // Default constructor.
- Object():
- type(objNone) {}
-
- // Initialize an object.
- Object *initBool(GBool boolnA)
- { initObj(objBool); booln = boolnA; return this; }
- Object *initInt(int intgA)
- { initObj(objInt); intg = intgA; return this; }
- Object *initReal(double realA)
- { initObj(objReal); real = realA; return this; }
- Object *initString(GString *stringA)
- { initObj(objString); string = stringA; return this; }
- Object *initName(char *nameA)
- { initObj(objName); name = copyString(nameA); return this; }
- Object *initNull()
- { initObj(objNull); return this; }
- Object *initArray(XRef *xref);
- Object *initDict(XRef *xref);
- Object *initDict(Dict *dictA);
- Object *initStream(Stream *streamA);
- Object *initRef(int numA, int genA)
- { initObj(objRef); ref.num = numA; ref.gen = genA; return this; }
- Object *initCmd(char *cmdA)
- { initObj(objCmd); cmd = copyString(cmdA); return this; }
- Object *initError()
- { initObj(objError); return this; }
- Object *initEOF()
- { initObj(objEOF); return this; }
-
- // Copy an object.
- Object *copy(Object *obj);
-
- // If object is a Ref, fetch and return the referenced object.
- // Otherwise, return a copy of the object.
- Object *fetch(XRef *xref, Object *obj);
-
- // Free object contents.
- void free();
-
- // Type checking.
- ObjType getType() { return type; }
- GBool isBool() { return type == objBool; }
- GBool isInt() { return type == objInt; }
- GBool isReal() { return type == objReal; }
- GBool isNum() { return type == objInt || type == objReal; }
- GBool isString() { return type == objString; }
- GBool isName() { return type == objName; }
- GBool isNull() { return type == objNull; }
- GBool isArray() { return type == objArray; }
- GBool isDict() { return type == objDict; }
- GBool isStream() { return type == objStream; }
- GBool isRef() { return type == objRef; }
- GBool isCmd() { return type == objCmd; }
- GBool isError() { return type == objError; }
- GBool isEOF() { return type == objEOF; }
- GBool isNone() { return type == objNone; }
-
- // Special type checking.
- GBool isName(char *nameA)
- { return type == objName && !strcmp(name, nameA); }
- GBool isDict(char *dictType);
- GBool isStream(char *dictType);
- GBool isCmd(char *cmdA)
- { return type == objCmd && !strcmp(cmd, cmdA); }
-
- // Accessors. NB: these assume object is of correct type.
- GBool getBool() { return booln; }
- int getInt() { return intg; }
- double getReal() { return real; }
- double getNum() { return type == objInt ? (double)intg : real; }
- GString *getString() { return string; }
- char *getName() { return name; }
- Array *getArray() { return array; }
- Dict *getDict() { return dict; }
- Stream *getStream() { return stream; }
- Ref getRef() { return ref; }
- int getRefNum() { return ref.num; }
- int getRefGen() { return ref.gen; }
- char *getCmd() { return cmd; }
-
- // Array accessors.
- int arrayGetLength();
- void arrayAdd(Object *elem);
- Object *arrayGet(int i, Object *obj);
- Object *arrayGetNF(int i, Object *obj);
-
- // Dict accessors.
- int dictGetLength();
- void dictAdd(char *key, Object *val);
- GBool dictIs(char *dictType);
- Object *dictLookup(char *key, Object *obj);
- Object *dictLookupNF(char *key, Object *obj);
- char *dictGetKey(int i);
- Object *dictGetVal(int i, Object *obj);
- Object *dictGetValNF(int i, Object *obj);
-
- // Stream accessors.
- GBool streamIs(char *dictType);
- void streamReset();
- void streamClose();
- int streamGetChar();
- int streamLookChar();
- char *streamGetLine(char *buf, int size);
- Guint streamGetPos();
- void streamSetPos(Guint pos, int dir = 0);
- Dict *streamGetDict();
-
- // Output.
- char *getTypeName();
- void print(FILE *f = stdout);
-
- // Memory testing.
- static void memCheck(FILE *f);
-
-private:
-
- ObjType type; // object type
- union { // value for each type:
- GBool booln; // boolean
- int intg; // integer
- double real; // real
- GString *string; // string
- char *name; // name
- Array *array; // array
- Dict *dict; // dictionary
- Stream *stream; // stream
- Ref ref; // indirect reference
- char *cmd; // command
- };
-
-#ifdef DEBUG_MEM
- static int // number of each type of object
- numAlloc[numObjTypes]; // currently allocated
-#endif
-};
-
-//------------------------------------------------------------------------
-// Array accessors.
-//------------------------------------------------------------------------
-
-#include "Array.h"
-
-inline int Object::arrayGetLength()
- { return array->getLength(); }
-
-inline void Object::arrayAdd(Object *elem)
- { array->add(elem); }
-
-inline Object *Object::arrayGet(int i, Object *obj)
- { return array->get(i, obj); }
-
-inline Object *Object::arrayGetNF(int i, Object *obj)
- { return array->getNF(i, obj); }
-
-//------------------------------------------------------------------------
-// Dict accessors.
-//------------------------------------------------------------------------
-
-#include "Dict.h"
-
-inline int Object::dictGetLength()
- { return dict->getLength(); }
-
-inline void Object::dictAdd(char *key, Object *val)
- { dict->add(key, val); }
-
-inline GBool Object::dictIs(char *dictType)
- { return dict->is(dictType); }
-
-inline GBool Object::isDict(char *dictType)
- { return type == objDict && dictIs(dictType); }
-
-inline Object *Object::dictLookup(char *key, Object *obj)
- { return dict->lookup(key, obj); }
-
-inline Object *Object::dictLookupNF(char *key, Object *obj)
- { return dict->lookupNF(key, obj); }
-
-inline char *Object::dictGetKey(int i)
- { return dict->getKey(i); }
-
-inline Object *Object::dictGetVal(int i, Object *obj)
- { return dict->getVal(i, obj); }
-
-inline Object *Object::dictGetValNF(int i, Object *obj)
- { return dict->getValNF(i, obj); }
-
-//------------------------------------------------------------------------
-// Stream accessors.
-//------------------------------------------------------------------------
-
-#include "Stream.h"
-
-inline GBool Object::streamIs(char *dictType)
- { return stream->getDict()->is(dictType); }
-
-inline GBool Object::isStream(char *dictType)
- { return type == objStream && streamIs(dictType); }
-
-inline void Object::streamReset()
- { stream->reset(); }
-
-inline void Object::streamClose()
- { stream->close(); }
-
-inline int Object::streamGetChar()
- { return stream->getChar(); }
-
-inline int Object::streamLookChar()
- { return stream->lookChar(); }
-
-inline char *Object::streamGetLine(char *buf, int size)
- { return stream->getLine(buf, size); }
-
-inline Guint Object::streamGetPos()
- { return stream->getPos(); }
-
-inline void Object::streamSetPos(Guint pos, int dir)
- { stream->setPos(pos, dir); }
-
-inline Dict *Object::streamGetDict()
- { return stream->getDict(); }
-
-#endif
+++ /dev/null
-//========================================================================
-//
-// Outline.cc
-//
-// Copyright 2002-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma implementation
-#endif
-
-#include "gmem.h"
-#include "GString.h"
-#include "GList.h"
-#include "Link.h"
-#include "PDFDocEncoding.h"
-#include "Outline.h"
-
-//------------------------------------------------------------------------
-
-Outline::Outline(Object *outlineObj, XRef *xref) {
- Object first, last;
-
- items = NULL;
- if (!outlineObj->isDict()) {
- return;
- }
- items = OutlineItem::readItemList(outlineObj->dictLookupNF("First", &first),
- outlineObj->dictLookupNF("Last", &last),
- xref);
- first.free();
- last.free();
-}
-
-Outline::~Outline() {
- if (items) {
- deleteGList(items, OutlineItem);
- }
-}
-
-//------------------------------------------------------------------------
-
-OutlineItem::OutlineItem(Dict *dict, XRef *xrefA) {
- Object obj1;
- GString *s;
- int i;
-
- xref = xrefA;
- title = NULL;
- action = NULL;
- kids = NULL;
-
- if (dict->lookup("Title", &obj1)->isString()) {
- s = obj1.getString();
- if ((s->getChar(0) & 0xff) == 0xfe &&
- (s->getChar(1) & 0xff) == 0xff) {
- titleLen = (s->getLength() - 2) / 2;
- title = (Unicode *)gmallocn(titleLen, sizeof(Unicode));
- for (i = 0; i < titleLen; ++i) {
- title[i] = ((s->getChar(2 + 2*i) & 0xff) << 8) |
- (s->getChar(3 + 2*i) & 0xff);
- }
- } else {
- titleLen = s->getLength();
- title = (Unicode *)gmallocn(titleLen, sizeof(Unicode));
- for (i = 0; i < titleLen; ++i) {
- title[i] = pdfDocEncoding[s->getChar(i) & 0xff];
- }
- }
- } else {
- titleLen = 0;
- }
- obj1.free();
-
- if (!dict->lookup("Dest", &obj1)->isNull()) {
- action = LinkAction::parseDest(&obj1);
- } else {
- obj1.free();
- if (!dict->lookup("A", &obj1)->isNull()) {
- action = LinkAction::parseAction(&obj1);
- }
- }
- obj1.free();
-
- dict->lookupNF("First", &firstRef);
- dict->lookupNF("Last", &lastRef);
- dict->lookupNF("Next", &nextRef);
-
- startsOpen = gFalse;
- if (dict->lookup("Count", &obj1)->isInt()) {
- if (obj1.getInt() > 0) {
- startsOpen = gTrue;
- }
- }
- obj1.free();
-}
-
-OutlineItem::~OutlineItem() {
- close();
- if (title) {
- gfree(title);
- }
- if (action) {
- delete action;
- }
- firstRef.free();
- lastRef.free();
- nextRef.free();
-}
-
-GList *OutlineItem::readItemList(Object *firstItemRef, Object *lastItemRef,
- XRef *xrefA) {
- GList *items;
- OutlineItem *item;
- Object obj;
- Object *p;
-
- items = new GList();
- p = firstItemRef;
- while (p->isRef()) {
- if (!p->fetch(xrefA, &obj)->isDict()) {
- obj.free();
- break;
- }
- item = new OutlineItem(obj.getDict(), xrefA);
- obj.free();
- items->append(item);
- if (p->getRef().num == lastItemRef->getRef().num &&
- p->getRef().gen == lastItemRef->getRef().gen) {
- break;
- }
- p = &item->nextRef;
- }
- return items;
-}
-
-void OutlineItem::open() {
- if (!kids) {
- kids = readItemList(&firstRef, &lastRef, xref);
- }
-}
-
-void OutlineItem::close() {
- if (kids) {
- deleteGList(kids, OutlineItem);
- kids = NULL;
- }
-}
+++ /dev/null
-//========================================================================
-//
-// Outline.h
-//
-// Copyright 2002-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#ifndef OUTLINE_H
-#define OUTLINE_H
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma interface
-#endif
-
-#include "Object.h"
-#include "CharTypes.h"
-
-class GString;
-class GList;
-class XRef;
-class LinkAction;
-
-//------------------------------------------------------------------------
-
-class Outline {
-public:
-
- Outline(Object *outlineObj, XRef *xref);
- ~Outline();
-
- GList *getItems() { return items; }
-
-private:
-
- GList *items; // NULL if document has no outline
- // [OutlineItem]
-};
-
-//------------------------------------------------------------------------
-
-class OutlineItem {
-public:
-
- OutlineItem(Dict *dict, XRef *xrefA);
- ~OutlineItem();
-
- static GList *readItemList(Object *firstItemRef, Object *lastItemRef,
- XRef *xrefA);
-
- void open();
- void close();
-
- Unicode *getTitle() { return title; }
- int getTitleLength() { return titleLen; }
- LinkAction *getAction() { return action; }
- GBool isOpen() { return startsOpen; }
- GBool hasKids() { return firstRef.isRef(); }
- GList *getKids() { return kids; }
-
-private:
-
- XRef *xref;
- Unicode *title;
- int titleLen;
- LinkAction *action;
- Object firstRef;
- Object lastRef;
- Object nextRef;
- GBool startsOpen;
- GList *kids; // NULL unless this item is open [OutlineItem]
-};
-
-#endif
+++ /dev/null
-//========================================================================
-//
-// OutputDev.cc
-//
-// Copyright 1996-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma implementation
-#endif
-
-#include <stddef.h>
-#include "Object.h"
-#include "Stream.h"
-#include "GfxState.h"
-#include "OutputDev.h"
-
-//------------------------------------------------------------------------
-// OutputDev
-//------------------------------------------------------------------------
-
-void OutputDev::setDefaultCTM(double *ctm) {
- int i;
- double det;
-
- for (i = 0; i < 6; ++i) {
- defCTM[i] = ctm[i];
- }
- det = 1 / (defCTM[0] * defCTM[3] - defCTM[1] * defCTM[2]);
- defICTM[0] = defCTM[3] * det;
- defICTM[1] = -defCTM[1] * det;
- defICTM[2] = -defCTM[2] * det;
- defICTM[3] = defCTM[0] * det;
- defICTM[4] = (defCTM[2] * defCTM[5] - defCTM[3] * defCTM[4]) * det;
- defICTM[5] = (defCTM[1] * defCTM[4] - defCTM[0] * defCTM[5]) * det;
-}
-
-void OutputDev::cvtDevToUser(double dx, double dy, double *ux, double *uy) {
- *ux = defICTM[0] * dx + defICTM[2] * dy + defICTM[4];
- *uy = defICTM[1] * dx + defICTM[3] * dy + defICTM[5];
-}
-
-void OutputDev::cvtUserToDev(double ux, double uy, int *dx, int *dy) {
- *dx = (int)(defCTM[0] * ux + defCTM[2] * uy + defCTM[4] + 0.5);
- *dy = (int)(defCTM[1] * ux + defCTM[3] * uy + defCTM[5] + 0.5);
-}
-
-void OutputDev::updateAll(GfxState *state) {
- updateLineDash(state);
- updateFlatness(state);
- updateLineJoin(state);
- updateLineCap(state);
- updateMiterLimit(state);
- updateLineWidth(state);
- updateFillColorSpace(state);
- updateFillColor(state);
- updateStrokeColorSpace(state);
- updateStrokeColor(state);
- updateBlendMode(state);
- updateFillOpacity(state);
- updateStrokeOpacity(state);
- updateFillOverprint(state);
- updateStrokeOverprint(state);
- updateFont(state);
-}
-
-GBool OutputDev::beginType3Char(GfxState *state, double x, double y,
- double dx, double dy,
- CharCode code, Unicode *u, int uLen) {
- return gFalse;
-}
-
-void OutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str,
- int width, int height, GBool invert,
- GBool inlineImg) {
- int i, j;
-
- if (inlineImg) {
- str->reset();
- j = height * ((width + 7) / 8);
- for (i = 0; i < j; ++i)
- str->getChar();
- str->close();
- }
-}
-
-void OutputDev::drawImage(GfxState *state, Object *ref, Stream *str,
- int width, int height, GfxImageColorMap *colorMap,
- int *maskColors, GBool inlineImg) {
- int i, j;
-
- if (inlineImg) {
- str->reset();
- j = height * ((width * colorMap->getNumPixelComps() *
- colorMap->getBits() + 7) / 8);
- for (i = 0; i < j; ++i)
- str->getChar();
- str->close();
- }
-}
-
-void OutputDev::drawMaskedImage(GfxState *state, Object *ref, Stream *str,
- int width, int height,
- GfxImageColorMap *colorMap,
- Stream *maskStr,
- int maskWidth, int maskHeight,
- GBool maskInvert) {
- drawImage(state, ref, str, width, height, colorMap, NULL, gFalse);
-}
-
-void OutputDev::drawSoftMaskedImage(GfxState *state, Object *ref, Stream *str,
- int width, int height,
- GfxImageColorMap *colorMap,
- Stream *maskStr,
- int maskWidth, int maskHeight,
- GfxImageColorMap *maskColorMap) {
- drawImage(state, ref, str, width, height, colorMap, NULL, gFalse);
-}
-
-#if OPI_SUPPORT
-void OutputDev::opiBegin(GfxState *state, Dict *opiDict) {
-}
-
-void OutputDev::opiEnd(GfxState *state, Dict *opiDict) {
-}
-#endif
+++ /dev/null
-//========================================================================
-//
-// OutputDev.h
-//
-// Copyright 1996-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#ifndef OUTPUTDEV_H
-#define OUTPUTDEV_H
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma interface
-#endif
-
-#include "gtypes.h"
-#include "CharTypes.h"
-
-class GString;
-class GfxState;
-class GfxColorSpace;
-class GfxImageColorMap;
-class GfxFunctionShading;
-class GfxAxialShading;
-class GfxRadialShading;
-class Stream;
-class Link;
-class Catalog;
-
-//------------------------------------------------------------------------
-// OutputDev
-//------------------------------------------------------------------------
-
-class OutputDev {
-public:
-
- // Constructor.
- OutputDev() {}
-
- // Destructor.
- virtual ~OutputDev() {}
-
- //----- get info about output device
-
- // Does this device use upside-down coordinates?
- // (Upside-down means (0,0) is the top left corner of the page.)
- virtual GBool upsideDown() = 0;
-
- // Does this device use drawChar() or drawString()?
- virtual GBool useDrawChar() = 0;
-
- // Does this device use tilingPatternFill()? If this returns false,
- // tiling pattern fills will be reduced to a series of other drawing
- // operations.
- virtual GBool useTilingPatternFill() { return gFalse; }
-
- // Does this device use functionShadedFill(), axialShadedFill(), and
- // radialShadedFill()? If this returns false, these shaded fills
- // will be reduced to a series of other drawing operations.
- virtual GBool useShadedFills() { return gFalse; }
-
- // Does this device use beginType3Char/endType3Char? Otherwise,
- // text in Type 3 fonts will be drawn with drawChar/drawString.
- virtual GBool interpretType3Chars() = 0;
-
- // Does this device need non-text content?
- virtual GBool needNonText() { return gTrue; }
-
- //----- initialization and control
-
- // Set default transform matrix.
- virtual void setDefaultCTM(double *ctm);
-
- // Start a page.
- virtual void startPage(int pageNum, GfxState *state, double x1,double y1,double x2,double y2) {}
-
- // End a page.
- virtual void endPage() {}
-
- // Dump page contents to display.
- virtual void dump() {}
-
- //----- coordinate conversion
-
- // Convert between device and user coordinates.
- virtual void cvtDevToUser(double dx, double dy, double *ux, double *uy);
- virtual void cvtUserToDev(double ux, double uy, int *dx, int *dy);
-
- double *getDefCTM() { return defCTM; }
- double *getDefICTM() { return defICTM; }
-
- //----- link borders
- virtual void drawLink(Link *link, Catalog *catalog) {}
-
- //----- save/restore graphics state
- virtual void saveState(GfxState *state) {}
- virtual void restoreState(GfxState *state) {}
-
- //----- update graphics state
- virtual void updateAll(GfxState *state);
- virtual void updateCTM(GfxState *state, double m11, double m12,
- double m21, double m22, double m31, double m32) {}
- virtual void updateLineDash(GfxState *state) {}
- virtual void updateFlatness(GfxState *state) {}
- virtual void updateLineJoin(GfxState *state) {}
- virtual void updateLineCap(GfxState *state) {}
- virtual void updateMiterLimit(GfxState *state) {}
- virtual void updateLineWidth(GfxState *state) {}
- virtual void updateFillColorSpace(GfxState *state) {}
- virtual void updateStrokeColorSpace(GfxState *state) {}
- virtual void updateFillColor(GfxState *state) {}
- virtual void updateStrokeColor(GfxState *state) {}
- virtual void updateBlendMode(GfxState *state) {}
- virtual void updateFillOpacity(GfxState *state) {}
- virtual void updateStrokeOpacity(GfxState *state) {}
- virtual void updateFillOverprint(GfxState *state) {}
- virtual void updateStrokeOverprint(GfxState *state) {}
-
- //----- update text state
- virtual void updateFont(GfxState *state) {}
- virtual void updateTextMat(GfxState *state) {}
- virtual void updateCharSpace(GfxState *state) {}
- virtual void updateRender(GfxState *state) {}
- virtual void updateRise(GfxState *state) {}
- virtual void updateWordSpace(GfxState *state) {}
- virtual void updateHorizScaling(GfxState *state) {}
- virtual void updateTextPos(GfxState *state) {}
- virtual void updateTextShift(GfxState *state, double shift) {}
-
- //----- path painting
- virtual void stroke(GfxState *state) {}
- virtual void fill(GfxState *state) {}
- virtual void eoFill(GfxState *state) {}
- virtual void tilingPatternFill(GfxState *state, Object *str,
- int paintType, Dict *resDict,
- double *mat, double *bbox,
- int x0, int y0, int x1, int y1,
- double xStep, double yStep) {}
- virtual void functionShadedFill(GfxState *state,
- GfxFunctionShading *shading) {}
- virtual void axialShadedFill(GfxState *state, GfxAxialShading *shading) {}
- virtual void radialShadedFill(GfxState *state, GfxRadialShading *shading) {}
-
- //----- path clipping
- virtual void clip(GfxState *state) {}
- virtual void eoClip(GfxState *state) {}
-
- //----- text drawing
- virtual void beginStringOp(GfxState *state) {}
- virtual void endStringOp(GfxState *state) {}
- virtual void beginString(GfxState *state, GString *s) {}
- virtual void endString(GfxState *state) {}
- virtual void drawChar(GfxState *state, double x, double y,
- double dx, double dy,
- double originX, double originY,
- CharCode code, int nBytes, Unicode *u, int uLen) {}
- virtual void drawString(GfxState *state, GString *s) {}
- virtual GBool beginType3Char(GfxState *state, double x, double y,
- double dx, double dy,
- CharCode code, Unicode *u, int uLen);
- virtual void endType3Char(GfxState *state) {}
- virtual void endTextObject(GfxState *state) {}
-
- //----- image drawing
- virtual void drawImageMask(GfxState *state, Object *ref, Stream *str,
- int width, int height, GBool invert,
- GBool inlineImg);
- virtual void drawImage(GfxState *state, Object *ref, Stream *str,
- int width, int height, GfxImageColorMap *colorMap,
- int *maskColors, GBool inlineImg);
- virtual void drawMaskedImage(GfxState *state, Object *ref, Stream *str,
- int width, int height,
- GfxImageColorMap *colorMap,
- Stream *maskStr, int maskWidth, int maskHeight,
- GBool maskInvert);
- virtual void drawSoftMaskedImage(GfxState *state, Object *ref, Stream *str,
- int width, int height,
- GfxImageColorMap *colorMap,
- Stream *maskStr,
- int maskWidth, int maskHeight,
- GfxImageColorMap *maskColorMap);
-
-#if OPI_SUPPORT
- //----- OPI functions
- virtual void opiBegin(GfxState *state, Dict *opiDict);
- virtual void opiEnd(GfxState *state, Dict *opiDict);
-#endif
-
- //----- Type 3 font operators
- virtual void type3D0(GfxState *state, double wx, double wy) {}
- virtual void type3D1(GfxState *state, double wx, double wy,
- double llx, double lly, double urx, double ury) {}
-
- //----- PostScript XObjects
- virtual void psXObject(Stream *psStream, Stream *level1Stream) {}
-
-private:
-
- double defCTM[6]; // default coordinate transform matrix
- double defICTM[6]; // inverse of default CTM
-};
-
-#endif
+++ /dev/null
-//========================================================================
-//
-// PDFDoc.cc
-//
-// Copyright 1996-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma implementation
-#endif
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stddef.h>
-#include <string.h>
-#ifdef WIN32
-# include <windows.h>
-#endif
-#include "GString.h"
-#include "config.h"
-#include "GlobalParams.h"
-#include "Page.h"
-#include "Catalog.h"
-#include "Stream.h"
-#include "XRef.h"
-#include "Link.h"
-#include "OutputDev.h"
-#include "Error.h"
-#include "ErrorCodes.h"
-#include "Lexer.h"
-#include "Parser.h"
-#include "SecurityHandler.h"
-#ifndef DISABLE_OUTLINE
-#include "Outline.h"
-#endif
-#include "PDFDoc.h"
-
-//------------------------------------------------------------------------
-
-#define headerSearchSize 1024 // read this many bytes at beginning of
- // file to look for '%PDF'
-
-//------------------------------------------------------------------------
-// PDFDoc
-//------------------------------------------------------------------------
-
-PDFDoc::PDFDoc(GString *fileNameA, GString *ownerPassword,
- GString *userPassword, void *guiDataA) {
- Object obj;
- GString *fileName1, *fileName2;
-
- ok = gFalse;
- errCode = errNone;
-
- guiData = guiDataA;
-
- file = NULL;
- str = NULL;
- xref = NULL;
- catalog = NULL;
- links = NULL;
-#ifndef DISABLE_OUTLINE
- outline = NULL;
-#endif
-
- fileName = fileNameA;
- fileName1 = fileName;
-
-
- // try to open file
- fileName2 = NULL;
-#ifdef VMS
- if (!(file = fopen(fileName1->getCString(), "rb", "ctx=stm"))) {
- error(-1, "Couldn't open file '%s'", fileName1->getCString());
- errCode = errOpenFile;
- return;
- }
-#else
- if (!(file = fopen(fileName1->getCString(), "rb"))) {
- fileName2 = fileName->copy();
- fileName2->lowerCase();
- if (!(file = fopen(fileName2->getCString(), "rb"))) {
- fileName2->upperCase();
- if (!(file = fopen(fileName2->getCString(), "rb"))) {
- error(-1, "Couldn't open file '%s'", fileName->getCString());
- delete fileName2;
- errCode = errOpenFile;
- return;
- }
- }
- delete fileName2;
- }
-#endif
-
- // create stream
- obj.initNull();
- str = new FileStream(file, 0, gFalse, 0, &obj);
-
- ok = setup(ownerPassword, userPassword);
-}
-
-#ifdef WIN32
-PDFDoc::PDFDoc(wchar_t *fileNameA, int fileNameLen, GString *ownerPassword,
- GString *userPassword, void *guiDataA) {
- OSVERSIONINFO version;
- wchar_t fileName2[_MAX_PATH + 1];
- Object obj;
- int i;
-
- ok = gFalse;
- errCode = errNone;
-
- guiData = guiDataA;
-
- file = NULL;
- str = NULL;
- xref = NULL;
- catalog = NULL;
- links = NULL;
-#ifndef DISABLE_OUTLINE
- outline = NULL;
-#endif
-
- //~ file name should be stored in Unicode (?)
- fileName = new GString();
- for (i = 0; i < fileNameLen; ++i) {
- fileName->append((char)fileNameA[i]);
- }
-
- // zero-terminate the file name string
- for (i = 0; i < fileNameLen && i < _MAX_PATH; ++i) {
- fileName2[i] = fileNameA[i];
- }
- fileName2[i] = 0;
-
- // try to open file
- // NB: _wfopen is only available in NT
- version.dwOSVersionInfoSize = sizeof(version);
- GetVersionEx(&version);
- if (version.dwPlatformId == VER_PLATFORM_WIN32_NT) {
- file = _wfopen(fileName2, L"rb");
- } else {
- file = fopen(fileName->getCString(), "rb");
- }
- if (!file) {
- error(-1, "Couldn't open file '%s'", fileName->getCString());
- errCode = errOpenFile;
- return;
- }
-
- // create stream
- obj.initNull();
- str = new FileStream(file, 0, gFalse, 0, &obj);
-
- ok = setup(ownerPassword, userPassword);
-}
-#endif
-
-PDFDoc::PDFDoc(BaseStream *strA, GString *ownerPassword,
- GString *userPassword, void *guiDataA) {
- ok = gFalse;
- errCode = errNone;
- guiData = guiDataA;
- fileName = NULL;
- file = NULL;
- str = strA;
- xref = NULL;
- catalog = NULL;
- links = NULL;
-#ifndef DISABLE_OUTLINE
- outline = NULL;
-#endif
- ok = setup(ownerPassword, userPassword);
-}
-
-GBool PDFDoc::setup(GString *ownerPassword, GString *userPassword) {
- str->reset();
-
- // check header
- checkHeader();
-
- // read xref table
- xref = new XRef(str);
- if (!xref->isOk()) {
- error(-1, "Couldn't read xref table");
- errCode = xref->getErrorCode();
- return gFalse;
- }
-
- // check for encryption
- if (!checkEncryption(ownerPassword, userPassword)) {
- errCode = errEncrypted;
- return gFalse;
- }
-
- // read catalog
- catalog = new Catalog(xref);
- if (!catalog->isOk()) {
- error(-1, "Couldn't read page catalog");
- errCode = errBadCatalog;
- return gFalse;
- }
-
-#ifndef DISABLE_OUTLINE
- // read outline
- outline = new Outline(catalog->getOutline(), xref);
-#endif
-
- // done
- return gTrue;
-}
-
-PDFDoc::~PDFDoc() {
-#ifndef DISABLE_OUTLINE
- if (outline) {
- delete outline;
- }
-#endif
- if (catalog) {
- delete catalog;
- }
- if (xref) {
- delete xref;
- }
- if (str) {
- delete str;
- }
- if (file) {
- fclose(file);
- }
- if (fileName) {
- delete fileName;
- }
- if (links) {
- delete links;
- }
-}
-
-// Check for a PDF header on this stream. Skip past some garbage
-// if necessary.
-void PDFDoc::checkHeader() {
- char hdrBuf[headerSearchSize+1];
- char *p;
- int i;
-
- pdfVersion = 0;
- for (i = 0; i < headerSearchSize; ++i) {
- hdrBuf[i] = str->getChar();
- }
- hdrBuf[headerSearchSize] = '\0';
- for (i = 0; i < headerSearchSize - 5; ++i) {
- if (!strncmp(&hdrBuf[i], "%PDF-", 5)) {
- break;
- }
- }
- if (i >= headerSearchSize - 5) {
- error(-1, "May not be a PDF file (continuing anyway)");
- return;
- }
- str->moveStart(i);
- if (!(p = strtok(&hdrBuf[i+5], " \t\n\r"))) {
- error(-1, "May not be a PDF file (continuing anyway)");
- return;
- }
- pdfVersion = atof(p);
- if (!(hdrBuf[i+5] >= '0' && hdrBuf[i+5] <= '9') ||
- pdfVersion > supportedPDFVersionNum + 0.0001) {
- error(-1, "PDF version %s -- xpdf supports version %s"
- " (continuing anyway)", p, supportedPDFVersionStr);
- }
-}
-
-GBool PDFDoc::checkEncryption(GString *ownerPassword, GString *userPassword) {
- Object encrypt;
- GBool encrypted;
- SecurityHandler *secHdlr;
- GBool ret;
-
- xref->getTrailerDict()->dictLookup("Encrypt", &encrypt);
- if ((encrypted = encrypt.isDict())) {
- if ((secHdlr = SecurityHandler::make(this, &encrypt))) {
- if (secHdlr->checkEncryption(ownerPassword, userPassword)) {
- // authorization succeeded
- xref->setEncryption(secHdlr->getPermissionFlags(),
- secHdlr->getOwnerPasswordOk(),
- secHdlr->getFileKey(),
- secHdlr->getFileKeyLength(),
- secHdlr->getEncVersion());
- ret = gTrue;
- } else {
- // authorization failed
- ret = gFalse;
- }
- delete secHdlr;
- } else {
- // couldn't find the matching security handler
- ret = gFalse;
- }
- } else {
- // document is not encrypted
- ret = gTrue;
- }
- encrypt.free();
- return ret;
-}
-
-void PDFDoc::displayPage(OutputDev *out, int page, double hDPI, double vDPI,
- int rotate, GBool useMediaBox, GBool crop,
- GBool doLinks,
- GBool (*abortCheckCbk)(void *data),
- void *abortCheckCbkData) {
- Page *p;
-
- if (globalParams->getPrintCommands()) {
- printf("***** page %d *****\n", page);
- }
- p = catalog->getPage(page);
- if (doLinks) {
- if (links) {
- delete links;
- }
- getLinks(p);
- p->display(out, hDPI, vDPI, rotate, useMediaBox, crop, links, catalog,
- abortCheckCbk, abortCheckCbkData);
- } else {
- p->display(out, hDPI, vDPI, rotate, useMediaBox, crop, NULL, catalog,
- abortCheckCbk, abortCheckCbkData);
- }
-}
-
-void PDFDoc::displayPages(OutputDev *out, int firstPage, int lastPage,
- double hDPI, double vDPI, int rotate,
- GBool useMediaBox, GBool crop, GBool doLinks,
- GBool (*abortCheckCbk)(void *data),
- void *abortCheckCbkData) {
- int page;
-
- for (page = firstPage; page <= lastPage; ++page) {
- displayPage(out, page, hDPI, vDPI, rotate, useMediaBox, crop, doLinks,
- abortCheckCbk, abortCheckCbkData);
- }
-}
-
-void PDFDoc::displayPageSlice(OutputDev *out, int page,
- double hDPI, double vDPI, int rotate,
- GBool useMediaBox, GBool crop, GBool doLinks,
- int sliceX, int sliceY, int sliceW, int sliceH,
- GBool (*abortCheckCbk)(void *data),
- void *abortCheckCbkData) {
- Page *p;
-
- p = catalog->getPage(page);
- if (doLinks) {
- if (links) {
- delete links;
- }
- getLinks(p);
- p->displaySlice(out, hDPI, vDPI, rotate, useMediaBox, crop,
- sliceX, sliceY, sliceW, sliceH,
- links, catalog, abortCheckCbk, abortCheckCbkData);
- } else {
- p->displaySlice(out, hDPI, vDPI, rotate, useMediaBox, crop,
- sliceX, sliceY, sliceW, sliceH,
- NULL, catalog, abortCheckCbk, abortCheckCbkData);
- }
-}
-
-Links *PDFDoc::takeLinks() {
- Links *ret;
-
- ret = links;
- links = NULL;
- return ret;
-}
-
-GBool PDFDoc::isLinearized() {
- Parser *parser;
- Object obj1, obj2, obj3, obj4, obj5;
- GBool lin;
-
- lin = gFalse;
- obj1.initNull();
- parser = new Parser(xref,
- new Lexer(xref,
- str->makeSubStream(str->getStart(), gFalse, 0, &obj1)));
- parser->getObj(&obj1);
- parser->getObj(&obj2);
- parser->getObj(&obj3);
- parser->getObj(&obj4);
- if (obj1.isInt() && obj2.isInt() && obj3.isCmd("obj") &&
- obj4.isDict()) {
- obj4.dictLookup("Linearized", &obj5);
- if (obj5.isNum() && obj5.getNum() > 0) {
- lin = gTrue;
- }
- obj5.free();
- }
- obj4.free();
- obj3.free();
- obj2.free();
- obj1.free();
- delete parser;
- return lin;
-}
-
-GBool PDFDoc::saveAs(GString *name) {
- FILE *f;
- int c;
-
- if (!(f = fopen(name->getCString(), "wb"))) {
- error(-1, "Couldn't open file '%s'", name->getCString());
- return gFalse;
- }
- str->reset();
- while ((c = str->getChar()) != EOF) {
- fputc(c, f);
- }
- str->close();
- fclose(f);
- return gTrue;
-}
-
-void PDFDoc::getLinks(Page *page) {
- Object obj;
-
- links = new Links(page->getAnnots(&obj), catalog->getBaseURI());
- obj.free();
-}
+++ /dev/null
-//========================================================================
-//
-// PDFDoc.h
-//
-// Copyright 1996-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#ifndef PDFDOC_H
-#define PDFDOC_H
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma interface
-#endif
-
-#include <stdio.h>
-#include "XRef.h"
-#include "Catalog.h"
-#include "Page.h"
-
-class GString;
-class BaseStream;
-class OutputDev;
-class Links;
-class LinkAction;
-class LinkDest;
-class Outline;
-
-//------------------------------------------------------------------------
-// PDFDoc
-//------------------------------------------------------------------------
-
-class PDFDoc {
-public:
-
- PDFDoc(GString *fileNameA, GString *ownerPassword = NULL,
- GString *userPassword = NULL, void *guiDataA = NULL);
-#ifdef WIN32
- PDFDoc(wchar_t *fileNameA, int fileNameLen, GString *ownerPassword = NULL,
- GString *userPassword = NULL, void *guiDataA = NULL);
-#endif
- PDFDoc(BaseStream *strA, GString *ownerPassword = NULL,
- GString *userPassword = NULL, void *guiDataA = NULL);
- ~PDFDoc();
-
- // Was PDF document successfully opened?
- GBool isOk() { return ok; }
-
- // Get the error code (if isOk() returns false).
- int getErrorCode() { return errCode; }
-
- // Get file name.
- GString *getFileName() { return fileName; }
-
- // Get the xref table.
- XRef *getXRef() { return xref; }
-
- // Get catalog.
- Catalog *getCatalog() { return catalog; }
-
- // Get base stream.
- BaseStream *getBaseStream() { return str; }
-
- // Get page parameters.
- double getPageMediaWidth(int page)
- { return catalog->getPage(page)->getMediaWidth(); }
- double getPageMediaHeight(int page)
- { return catalog->getPage(page)->getMediaHeight(); }
- double getPageCropWidth(int page)
- { return catalog->getPage(page)->getCropWidth(); }
- double getPageCropHeight(int page)
- { return catalog->getPage(page)->getCropHeight(); }
- int getPageRotate(int page)
- { return catalog->getPage(page)->getRotate(); }
-
- // Get number of pages.
- int getNumPages() { return catalog->getNumPages(); }
-
- // Return the contents of the metadata stream, or NULL if there is
- // no metadata.
- GString *readMetadata() { return catalog->readMetadata(); }
-
- // Return the structure tree root object.
- Object *getStructTreeRoot() { return catalog->getStructTreeRoot(); }
-
- // Display a page.
- void displayPage(OutputDev *out, int page, double hDPI, double vDPI,
- int rotate, GBool useMediaBox, GBool crop,
- GBool doLinks,
- GBool (*abortCheckCbk)(void *data) = NULL,
- void *abortCheckCbkData = NULL);
-
- // Display a range of pages.
- void displayPages(OutputDev *out, int firstPage, int lastPage,
- double hDPI, double vDPI, int rotate,
- GBool useMediaBox, GBool crop, GBool doLinks,
- GBool (*abortCheckCbk)(void *data) = NULL,
- void *abortCheckCbkData = NULL);
-
- // Display part of a page.
- void displayPageSlice(OutputDev *out, int page,
- double hDPI, double vDPI, int rotate,
- GBool useMediaBox, GBool crop, GBool doLinks,
- int sliceX, int sliceY, int sliceW, int sliceH,
- GBool (*abortCheckCbk)(void *data) = NULL,
- void *abortCheckCbkData = NULL);
-
- // Find a page, given its object ID. Returns page number, or 0 if
- // not found.
- int findPage(int num, int gen) { return catalog->findPage(num, gen); }
-
- // Returns the links for the current page, transferring ownership to
- // the caller.
- Links *takeLinks();
-
- // Find a named destination. Returns the link destination, or
- // NULL if <name> is not a destination.
- LinkDest *findDest(GString *name)
- { return catalog->findDest(name); }
-
-#ifndef DISABLE_OUTLINE
- // Return the outline object.
- Outline *getOutline() { return outline; }
-#endif
-
- // Is the file encrypted?
- GBool isEncrypted() { return xref->isEncrypted(); }
-
- // Check various permissions.
- GBool okToPrint(GBool ignoreOwnerPW = gFalse)
- { return xref->okToPrint(ignoreOwnerPW); }
- GBool okToChange(GBool ignoreOwnerPW = gFalse)
- { return xref->okToChange(ignoreOwnerPW); }
- GBool okToCopy(GBool ignoreOwnerPW = gFalse)
- { return xref->okToCopy(ignoreOwnerPW); }
- GBool okToAddNotes(GBool ignoreOwnerPW = gFalse)
- { return xref->okToAddNotes(ignoreOwnerPW); }
-
- // Is this document linearized?
- GBool isLinearized();
-
- // Return the document's Info dictionary (if any).
- Object *getDocInfo(Object *obj) { return xref->getDocInfo(obj); }
- Object *getDocInfoNF(Object *obj) { return xref->getDocInfoNF(obj); }
-
- // Return the PDF version specified by the file.
- double getPDFVersion() { return pdfVersion; }
-
- // Save this file with another name.
- GBool saveAs(GString *name);
-
- // Return a pointer to the GUI (XPDFCore or WinPDFCore object).
- void *getGUIData() { return guiData; }
-
-
-private:
-
- GBool setup(GString *ownerPassword, GString *userPassword);
- void checkHeader();
- GBool checkEncryption(GString *ownerPassword, GString *userPassword);
- void getLinks(Page *page);
-
- GString *fileName;
- FILE *file;
- BaseStream *str;
- void *guiData;
- double pdfVersion;
- XRef *xref;
- Catalog *catalog;
- Links *links;
-#ifndef DISABLE_OUTLINE
- Outline *outline;
-#endif
-
-
- GBool ok;
- int errCode;
-};
-
-#endif
+++ /dev/null
-//========================================================================
-//
-// PDFDocEncoding.h
-//
-// Copyright 2002-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#include "PDFDocEncoding.h"
-
-Unicode pdfDocEncoding[256] = {
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 00
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 10
- 0x02d8, 0x02c7, 0x02c6, 0x02d9, 0x02dd, 0x02db, 0x02da, 0x02dc,
- 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, // 20
- 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
- 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, // 30
- 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
- 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, // 40
- 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
- 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, // 50
- 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
- 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, // 60
- 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
- 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, // 70
- 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x0000,
- 0x2022, 0x2020, 0x2021, 0x2026, 0x2014, 0x2013, 0x0192, 0x2044, // 80
- 0x2039, 0x203a, 0x2212, 0x2030, 0x201e, 0x201c, 0x201d, 0x2018,
- 0x2019, 0x201a, 0x2122, 0xfb01, 0xfb02, 0x0141, 0x0152, 0x0160, // 90
- 0x0178, 0x017d, 0x0131, 0x0142, 0x0153, 0x0161, 0x017e, 0x0000,
- 0x20ac, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7, // a0
- 0x00a8, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x0000, 0x00ae, 0x00af,
- 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7, // b0
- 0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf,
- 0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7, // c0
- 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf,
- 0x00d0, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7, // d0
- 0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x00df,
- 0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7, // e0
- 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef,
- 0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7, // f0
- 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe, 0x00ff
-};
+++ /dev/null
-//========================================================================
-//
-// PDFDocEncoding.h
-//
-// Copyright 2002-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#ifndef PDFDOCENCODING_H
-#define PDFDOCENCODING_H
-
-#include "CharTypes.h"
-
-extern Unicode pdfDocEncoding[256];
-
-#endif
+++ /dev/null
-//========================================================================
-//
-// PSTokenizer.cc
-//
-// Copyright 2002-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma implementation
-#endif
-
-#include <stdio.h>
-#include <stdlib.h>
-#include "PSTokenizer.h"
-
-//------------------------------------------------------------------------
-
-// A '1' in this array means the character is white space. A '1' or
-// '2' means the character ends a name or command.
-static char specialChars[256] = {
- 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, // 0x
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1x
- 1, 0, 0, 0, 0, 2, 0, 0, 2, 2, 0, 0, 0, 0, 0, 2, // 2x
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, // 3x
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 4x
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0, // 5x
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 6x
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0, // 7x
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8x
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9x
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // ax
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // bx
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // cx
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // dx
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // ex
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // fx
-};
-
-//------------------------------------------------------------------------
-
-PSTokenizer::PSTokenizer(int (*getCharFuncA)(void *), void *dataA) {
- getCharFunc = getCharFuncA;
- data = dataA;
- charBuf = -1;
-}
-
-PSTokenizer::~PSTokenizer() {
-}
-
-GBool PSTokenizer::getToken(char *buf, int size, int *length) {
- GBool comment, backslash;
- int c;
- int i;
-
- // skip whitespace and comments
- comment = gFalse;
- while (1) {
- if ((c = getChar()) == EOF) {
- buf[0] = '\0';
- *length = 0;
- return gFalse;
- }
- if (comment) {
- if (c == '\x0a' || c == '\x0d') {
- comment = gFalse;
- }
- } else if (c == '%') {
- comment = gTrue;
- } else if (specialChars[c] != 1) {
- break;
- }
- }
-
- // read a token
- i = 0;
- buf[i++] = c;
- if (c == '(') {
- backslash = gFalse;
- while ((c = lookChar()) != EOF) {
- if (i < size - 1) {
- buf[i++] = c;
- }
- getChar();
- if (c == '\\') {
- backslash = gTrue;
- } else if (!backslash && c == ')') {
- break;
- } else {
- backslash = gFalse;
- }
- }
- } else if (c == '<') {
- while ((c = lookChar()) != EOF) {
- getChar();
- if (i < size - 1) {
- buf[i++] = c;
- }
- if (c == '>') {
- break;
- }
- }
- } else if (c != '[' && c != ']') {
- while ((c = lookChar()) != EOF && !specialChars[c]) {
- getChar();
- if (i < size - 1) {
- buf[i++] = c;
- }
- }
- }
- buf[i] = '\0';
- *length = i;
-
- return gTrue;
-}
-
-int PSTokenizer::lookChar() {
- if (charBuf < 0) {
- charBuf = (*getCharFunc)(data);
- }
- return charBuf;
-}
-
-int PSTokenizer::getChar() {
- int c;
-
- if (charBuf < 0) {
- charBuf = (*getCharFunc)(data);
- }
- c = charBuf;
- charBuf = -1;
- return c;
-}
+++ /dev/null
-//========================================================================
-//
-// PSTokenizer.h
-//
-// Copyright 2002-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#ifndef PSTOKENIZER_H
-#define PSTOKENIZER_H
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma interface
-#endif
-
-#include "gtypes.h"
-
-//------------------------------------------------------------------------
-
-class PSTokenizer {
-public:
-
- PSTokenizer(int (*getCharFuncA)(void *), void *dataA);
- ~PSTokenizer();
-
- // Get the next PostScript token. Returns false at end-of-stream.
- GBool getToken(char *buf, int size, int *length);
-
-private:
-
- int lookChar();
- int getChar();
-
- int (*getCharFunc)(void *);
- void *data;
- int charBuf;
-};
-
-#endif
+++ /dev/null
-//========================================================================
-//
-// Page.cc
-//
-// Copyright 1996-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma implementation
-#endif
-
-#include <stddef.h>
-#include "GlobalParams.h"
-#include "Object.h"
-#include "Array.h"
-#include "Dict.h"
-#include "XRef.h"
-#include "Link.h"
-#include "OutputDev.h"
-#ifndef PDF_PARSER_ONLY
-#include "Gfx.h"
-#include "GfxState.h"
-#include "Annot.h"
-#endif
-#include "Error.h"
-#include "Page.h"
-
-//------------------------------------------------------------------------
-// PageAttrs
-//------------------------------------------------------------------------
-
-PageAttrs::PageAttrs(PageAttrs *attrs, Dict *dict) {
- Object obj1;
-
- // get old/default values
- if (attrs) {
- mediaBox = attrs->mediaBox;
- cropBox = attrs->cropBox;
- haveCropBox = attrs->haveCropBox;
- rotate = attrs->rotate;
- attrs->resources.copy(&resources);
- } else {
- // set default MediaBox to 8.5" x 11" -- this shouldn't be necessary
- // but some (non-compliant) PDF files don't specify a MediaBox
- mediaBox.x1 = 0;
- mediaBox.y1 = 0;
- mediaBox.x2 = 612;
- mediaBox.y2 = 792;
- cropBox.x1 = cropBox.y1 = cropBox.x2 = cropBox.y2 = 0;
- haveCropBox = gFalse;
- rotate = 0;
- resources.initNull();
- }
-
- // media box
- readBox(dict, "MediaBox", &mediaBox);
-
- // crop box
- if (readBox(dict, "CropBox", &cropBox)) {
- haveCropBox = gTrue;
- }
- if (!haveCropBox) {
- cropBox = mediaBox;
- }
-
- // other boxes
- bleedBox = cropBox;
- readBox(dict, "BleedBox", &bleedBox);
- trimBox = cropBox;
- readBox(dict, "TrimBox", &trimBox);
- artBox = cropBox;
- readBox(dict, "ArtBox", &artBox);
-
- // rotate
- dict->lookup("Rotate", &obj1);
- if (obj1.isInt()) {
- rotate = obj1.getInt();
- }
- obj1.free();
- while (rotate < 0) {
- rotate += 360;
- }
- while (rotate >= 360) {
- rotate -= 360;
- }
-
- // misc attributes
- dict->lookup("LastModified", &lastModified);
- dict->lookup("BoxColorInfo", &boxColorInfo);
- dict->lookup("Group", &group);
- dict->lookup("Metadata", &metadata);
- dict->lookup("PieceInfo", &pieceInfo);
- dict->lookup("SeparationInfo", &separationInfo);
-
- // resource dictionary
- dict->lookup("Resources", &obj1);
- if (obj1.isDict()) {
- resources.free();
- obj1.copy(&resources);
- }
- obj1.free();
-}
-
-PageAttrs::~PageAttrs() {
- lastModified.free();
- boxColorInfo.free();
- group.free();
- metadata.free();
- pieceInfo.free();
- separationInfo.free();
- resources.free();
-}
-
-GBool PageAttrs::readBox(Dict *dict, char *key, PDFRectangle *box) {
- PDFRectangle tmp;
- double t;
- Object obj1, obj2;
- GBool ok;
-
- dict->lookup(key, &obj1);
- if (obj1.isArray() && obj1.arrayGetLength() == 4) {
- ok = gTrue;
- obj1.arrayGet(0, &obj2);
- if (obj2.isNum()) {
- tmp.x1 = obj2.getNum();
- } else {
- ok = gFalse;
- }
- obj2.free();
- obj1.arrayGet(1, &obj2);
- if (obj2.isNum()) {
- tmp.y1 = obj2.getNum();
- } else {
- ok = gFalse;
- }
- obj2.free();
- obj1.arrayGet(2, &obj2);
- if (obj2.isNum()) {
- tmp.x2 = obj2.getNum();
- } else {
- ok = gFalse;
- }
- obj2.free();
- obj1.arrayGet(3, &obj2);
- if (obj2.isNum()) {
- tmp.y2 = obj2.getNum();
- } else {
- ok = gFalse;
- }
- obj2.free();
- if (ok) {
- if (tmp.x1 > tmp.x2) {
- t = tmp.x1; tmp.x1 = tmp.x2; tmp.x2 = t;
- }
- if (tmp.y1 > tmp.y2) {
- t = tmp.y1; tmp.y1 = tmp.y2; tmp.y2 = t;
- }
- *box = tmp;
- }
- } else {
- ok = gFalse;
- }
- obj1.free();
- return ok;
-}
-
-//------------------------------------------------------------------------
-// Page
-//------------------------------------------------------------------------
-
-Page::Page(XRef *xrefA, int numA, Dict *pageDict, PageAttrs *attrsA) {
- ok = gTrue;
- xref = xrefA;
- num = numA;
-
- // get attributes
- attrs = attrsA;
-
- // annotations
- pageDict->lookupNF("Annots", &annots);
- if (!(annots.isRef() || annots.isArray() || annots.isNull())) {
- error(-1, "Page annotations object (page %d) is wrong type (%s)",
- num, annots.getTypeName());
- annots.free();
- goto err2;
- }
-
- // contents
- pageDict->lookupNF("Contents", &contents);
- if (!(contents.isRef() || contents.isArray() ||
- contents.isNull())) {
- error(-1, "Page contents object (page %d) is wrong type (%s)",
- num, contents.getTypeName());
- contents.free();
- goto err1;
- }
-
- return;
-
- err2:
- annots.initNull();
- err1:
- contents.initNull();
- ok = gFalse;
-}
-
-Page::~Page() {
- delete attrs;
- annots.free();
- contents.free();
-}
-
-void Page::display(OutputDev *out, double hDPI, double vDPI,
- int rotate, GBool useMediaBox, GBool crop,
- Links *links, Catalog *catalog,
- GBool (*abortCheckCbk)(void *data),
- void *abortCheckCbkData) {
- displaySlice(out, hDPI, vDPI, rotate, useMediaBox, crop,
- -1, -1, -1, -1, links, catalog,
- abortCheckCbk, abortCheckCbkData);
-}
-
-void Page::displaySlice(OutputDev *out, double hDPI, double vDPI,
- int rotate, GBool useMediaBox, GBool crop,
- int sliceX, int sliceY, int sliceW, int sliceH,
- Links *links, Catalog *catalog,
- GBool (*abortCheckCbk)(void *data),
- void *abortCheckCbkData) {
-#ifndef PDF_PARSER_ONLY
- PDFRectangle *mediaBox, *cropBox, *baseBox;
- PDFRectangle box;
- Gfx *gfx;
- Object obj;
- Link *link;
- Annots *annotList;
- double kx, ky;
- int i;
-
- rotate += getRotate();
- if (rotate >= 360) {
- rotate -= 360;
- } else if (rotate < 0) {
- rotate += 360;
- }
-
- mediaBox = getMediaBox();
- cropBox = getCropBox();
- if (sliceW >= 0 && sliceH >= 0) {
- baseBox = useMediaBox ? mediaBox : cropBox;
- kx = 72.0 / hDPI;
- ky = 72.0 / vDPI;
- if (rotate == 90) {
- if (out->upsideDown()) {
- box.x1 = baseBox->x1 + ky * sliceY;
- box.x2 = baseBox->x1 + ky * (sliceY + sliceH);
- } else {
- box.x1 = baseBox->x2 - ky * (sliceY + sliceH);
- box.x2 = baseBox->x2 - ky * sliceY;
- }
- box.y1 = baseBox->y1 + kx * sliceX;
- box.y2 = baseBox->y1 + kx * (sliceX + sliceW);
- } else if (rotate == 180) {
- box.x1 = baseBox->x2 - kx * (sliceX + sliceW);
- box.x2 = baseBox->x2 - kx * sliceX;
- if (out->upsideDown()) {
- box.y1 = baseBox->y1 + ky * sliceY;
- box.y2 = baseBox->y1 + ky * (sliceY + sliceH);
- } else {
- box.y1 = baseBox->y2 - ky * (sliceY + sliceH);
- box.y2 = baseBox->y2 - ky * sliceY;
- }
- } else if (rotate == 270) {
- if (out->upsideDown()) {
- box.x1 = baseBox->x2 - ky * (sliceY + sliceH);
- box.x2 = baseBox->x2 - ky * sliceY;
- } else {
- box.x1 = baseBox->x1 + ky * sliceY;
- box.x2 = baseBox->x1 + ky * (sliceY + sliceH);
- }
- box.y1 = baseBox->y2 - kx * (sliceX + sliceW);
- box.y2 = baseBox->y2 - kx * sliceX;
- } else {
- box.x1 = baseBox->x1 + kx * sliceX;
- box.x2 = baseBox->x1 + kx * (sliceX + sliceW);
- if (out->upsideDown()) {
- box.y1 = baseBox->y2 - ky * (sliceY + sliceH);
- box.y2 = baseBox->y2 - ky * sliceY;
- } else {
- box.y1 = baseBox->y1 + ky * sliceY;
- box.y2 = baseBox->y1 + ky * (sliceY + sliceH);
- }
- }
- } else if (useMediaBox) {
- box = *mediaBox;
- } else {
- box = *cropBox;
- crop = gFalse;
- }
-
- if (globalParams->getPrintCommands()) {
- printf("***** MediaBox = ll:%g,%g ur:%g,%g\n",
- mediaBox->x1, mediaBox->y1, mediaBox->x2, mediaBox->y2);
- printf("***** CropBox = ll:%g,%g ur:%g,%g\n",
- cropBox->x1, cropBox->y1, cropBox->x2, cropBox->y2);
- printf("***** Rotate = %d\n", attrs->getRotate());
- }
-
- gfx = new Gfx(xref, out, num, attrs->getResourceDict(),
- hDPI, vDPI, &box, crop ? cropBox : (PDFRectangle *)NULL,
- rotate, abortCheckCbk, abortCheckCbkData);
- contents.fetch(xref, &obj);
- if (!obj.isNull()) {
- gfx->saveState();
- gfx->display(&obj);
- gfx->restoreState();
- }
- obj.free();
-
- // draw links
- if (links) {
- gfx->saveState();
- for (i = 0; i < links->getNumLinks(); ++i) {
- link = links->getLink(i);
- out->drawLink(link, catalog);
- }
- gfx->restoreState();
- out->dump();
- }
-
- // draw non-link annotations
- annotList = new Annots(xref, catalog, annots.fetch(xref, &obj));
- obj.free();
- if (annotList->getNumAnnots() > 0) {
- if (globalParams->getPrintCommands()) {
- printf("***** Annotations\n");
- }
- for (i = 0; i < annotList->getNumAnnots(); ++i) {
- annotList->getAnnot(i)->draw(gfx);
- }
- out->dump();
- }
- delete annotList;
-
- delete gfx;
-#endif
-}
-
-void Page::getDefaultCTM(double *ctm, double hDPI, double vDPI,
- int rotate, GBool upsideDown) {
- GfxState *state;
- int i;
-
- rotate += getRotate();
- if (rotate >= 360) {
- rotate -= 360;
- } else if (rotate < 0) {
- rotate += 360;
- }
- state = new GfxState(hDPI, vDPI, getMediaBox(), rotate, upsideDown);
- for (i = 0; i < 6; ++i) {
- ctm[i] = state->getCTM()[i];
- }
- delete state;
-}
+++ /dev/null
-//========================================================================
-//
-// Page.h
-//
-// Copyright 1996-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#ifndef PAGE_H
-#define PAGE_H
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma interface
-#endif
-
-#include "Object.h"
-
-class Dict;
-class XRef;
-class OutputDev;
-class Links;
-class Catalog;
-
-//------------------------------------------------------------------------
-
-class PDFRectangle {
-public:
- double x1, y1, x2, y2;
-
- PDFRectangle() { x1 = y1 = x2 = y2 = 0; }
- PDFRectangle(double x1A, double y1A, double x2A, double y2A)
- { x1 = x1A; y1 = y1A; x2 = x2A; y2 = y2A; }
- GBool isValid() { return x1 != 0 || y1 != 0 || x2 != 0 || y2 != 0; }
-};
-
-//------------------------------------------------------------------------
-// PageAttrs
-//------------------------------------------------------------------------
-
-class PageAttrs {
-public:
-
- // Construct a new PageAttrs object by merging a dictionary
- // (of type Pages or Page) into another PageAttrs object. If
- // <attrs> is NULL, uses defaults.
- PageAttrs(PageAttrs *attrs, Dict *dict);
-
- // Destructor.
- ~PageAttrs();
-
- // Accessors.
- PDFRectangle *getMediaBox() { return &mediaBox; }
- PDFRectangle *getCropBox() { return &cropBox; }
- GBool isCropped() { return haveCropBox; }
- PDFRectangle *getBleedBox() { return &bleedBox; }
- PDFRectangle *getTrimBox() { return &trimBox; }
- PDFRectangle *getArtBox() { return &artBox; }
- int getRotate() { return rotate; }
- GString *getLastModified()
- { return lastModified.isString()
- ? lastModified.getString() : (GString *)NULL; }
- Dict *getBoxColorInfo()
- { return boxColorInfo.isDict() ? boxColorInfo.getDict() : (Dict *)NULL; }
- Dict *getGroup()
- { return group.isDict() ? group.getDict() : (Dict *)NULL; }
- Stream *getMetadata()
- { return metadata.isStream() ? metadata.getStream() : (Stream *)NULL; }
- Dict *getPieceInfo()
- { return pieceInfo.isDict() ? pieceInfo.getDict() : (Dict *)NULL; }
- Dict *getSeparationInfo()
- { return separationInfo.isDict()
- ? separationInfo.getDict() : (Dict *)NULL; }
- Dict *getResourceDict()
- { return resources.isDict() ? resources.getDict() : (Dict *)NULL; }
-
-private:
-
- GBool readBox(Dict *dict, char *key, PDFRectangle *box);
-
- PDFRectangle mediaBox;
- PDFRectangle cropBox;
- GBool haveCropBox;
- PDFRectangle bleedBox;
- PDFRectangle trimBox;
- PDFRectangle artBox;
- int rotate;
- Object lastModified;
- Object boxColorInfo;
- Object group;
- Object metadata;
- Object pieceInfo;
- Object separationInfo;
- Object resources;
-};
-
-//------------------------------------------------------------------------
-// Page
-//------------------------------------------------------------------------
-
-class Page {
-public:
-
- // Constructor.
- Page(XRef *xrefA, int numA, Dict *pageDict, PageAttrs *attrsA);
-
- // Destructor.
- ~Page();
-
- // Is page valid?
- GBool isOk() { return ok; }
-
- // Get page parameters.
- PDFRectangle *getMediaBox() { return attrs->getMediaBox(); }
- PDFRectangle *getCropBox() { return attrs->getCropBox(); }
- GBool isCropped() { return attrs->isCropped(); }
- double getMediaWidth()
- { return attrs->getMediaBox()->x2 - attrs->getMediaBox()->x1; }
- double getMediaHeight()
- { return attrs->getMediaBox()->y2 - attrs->getMediaBox()->y1; }
- double getCropWidth()
- { return attrs->getCropBox()->x2 - attrs->getCropBox()->x1; }
- double getCropHeight()
- { return attrs->getCropBox()->y2 - attrs->getCropBox()->y1; }
- PDFRectangle *getBleedBox() { return attrs->getBleedBox(); }
- PDFRectangle *getTrimBox() { return attrs->getTrimBox(); }
- PDFRectangle *getArtBox() { return attrs->getArtBox(); }
- int getRotate() { return attrs->getRotate(); }
- GString *getLastModified() { return attrs->getLastModified(); }
- Dict *getBoxColorInfo() { return attrs->getBoxColorInfo(); }
- Dict *getGroup() { return attrs->getGroup(); }
- Stream *getMetadata() { return attrs->getMetadata(); }
- Dict *getPieceInfo() { return attrs->getPieceInfo(); }
- Dict *getSeparationInfo() { return attrs->getSeparationInfo(); }
-
- // Get resource dictionary.
- Dict *getResourceDict() { return attrs->getResourceDict(); }
-
- // Get annotations array.
- Object *getAnnots(Object *obj) { return annots.fetch(xref, obj); }
-
- // Get contents.
- Object *getContents(Object *obj) { return contents.fetch(xref, obj); }
-
- // Display a page.
- void display(OutputDev *out, double hDPI, double vDPI,
- int rotate, GBool useMediaBox, GBool crop,
- Links *links, Catalog *catalog,
- GBool (*abortCheckCbk)(void *data) = NULL,
- void *abortCheckCbkData = NULL);
-
- // Display part of a page.
- void displaySlice(OutputDev *out, double hDPI, double vDPI,
- int rotate, GBool useMediaBox, GBool crop,
- int sliceX, int sliceY, int sliceW, int sliceH,
- Links *links, Catalog *catalog,
- GBool (*abortCheckCbk)(void *data) = NULL,
- void *abortCheckCbkData = NULL);
-
- // Get the page's default CTM.
- void getDefaultCTM(double *ctm, double hDPI, double vDPI,
- int rotate, GBool upsideDown);
-
-private:
-
- XRef *xref; // the xref table for this PDF file
- int num; // page number
- PageAttrs *attrs; // page attributes
- Object annots; // annotations array
- Object contents; // page contents
- GBool ok; // true if page is valid
-};
-
-#endif
+++ /dev/null
-//========================================================================
-//
-// Parser.cc
-//
-// Copyright 1996-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma implementation
-#endif
-
-#include <stddef.h>
-#include "Object.h"
-#include "Array.h"
-#include "Dict.h"
-#include "Parser.h"
-#include "XRef.h"
-#include "Error.h"
-#include "Decrypt.h"
-
-Parser::Parser(XRef *xrefA, Lexer *lexerA) {
- xref = xrefA;
- lexer = lexerA;
- inlineImg = 0;
- lexer->getObj(&buf1);
- lexer->getObj(&buf2);
-}
-
-Parser::~Parser() {
- buf1.free();
- buf2.free();
- delete lexer;
-}
-
-Object *Parser::getObj(Object *obj,
- Guchar *fileKey, int keyLength,
- int objNum, int objGen) {
- char *key;
- Stream *str;
- Object obj2;
- int num;
- Decrypt *decrypt;
- GString *s;
- char *p;
- int i;
-
- // refill buffer after inline image data
- if (inlineImg == 2) {
- buf1.free();
- buf2.free();
- lexer->getObj(&buf1);
- lexer->getObj(&buf2);
- inlineImg = 0;
- }
-
- // array
- if (buf1.isCmd("[")) {
- shift();
- obj->initArray(xref);
- while (!buf1.isCmd("]") && !buf1.isEOF())
- obj->arrayAdd(getObj(&obj2, fileKey, keyLength, objNum, objGen));
- if (buf1.isEOF())
- error(getPos(), "End of file inside array");
- shift();
-
- // dictionary or stream
- } else if (buf1.isCmd("<<")) {
- shift();
- obj->initDict(xref);
- while (!buf1.isCmd(">>") && !buf1.isEOF()) {
- if (!buf1.isName()) {
- error(getPos(), "Dictionary key must be a name object");
- shift();
- } else {
- key = copyString(buf1.getName());
- shift();
- if (buf1.isEOF() || buf1.isError()) {
- gfree(key);
- break;
- }
- obj->dictAdd(key, getObj(&obj2, fileKey, keyLength, objNum, objGen));
- }
- }
- if (buf1.isEOF())
- error(getPos(), "End of file inside dictionary");
- if (buf2.isCmd("stream")) {
- if ((str = makeStream(obj))) {
- obj->initStream(str);
- if (fileKey) {
- str->getBaseStream()->doDecryption(fileKey, keyLength,
- objNum, objGen);
- }
- } else {
- obj->free();
- obj->initError();
- }
- } else {
- shift();
- }
-
- // indirect reference or integer
- } else if (buf1.isInt()) {
- num = buf1.getInt();
- shift();
- if (buf1.isInt() && buf2.isCmd("R")) {
- obj->initRef(num, buf1.getInt());
- shift();
- shift();
- } else {
- obj->initInt(num);
- }
-
- // string
- } else if (buf1.isString() && fileKey) {
- buf1.copy(obj);
- s = obj->getString();
- decrypt = new Decrypt(fileKey, keyLength, objNum, objGen);
- for (i = 0, p = obj->getString()->getCString();
- i < s->getLength();
- ++i, ++p) {
- *p = decrypt->decryptByte(*p);
- }
- delete decrypt;
- shift();
-
- // simple object
- } else {
- buf1.copy(obj);
- shift();
- }
-
- return obj;
-}
-
-Stream *Parser::makeStream(Object *dict) {
- Object obj;
- BaseStream *baseStr;
- Stream *str;
- Guint pos, endPos, length;
-
- // get stream start position
- lexer->skipToNextLine();
- pos = lexer->getPos();
-
- // get length
- dict->dictLookup("Length", &obj);
- if (obj.isInt()) {
- length = (Guint)obj.getInt();
- obj.free();
- } else {
- error(getPos(), "Bad 'Length' attribute in stream");
- obj.free();
- return NULL;
- }
-
- // check for length in damaged file
- if (xref && xref->getStreamEnd(pos, &endPos)) {
- length = endPos - pos;
- }
-
- // in badly damaged PDF files, we can run off the end of the input
- // stream immediately after the "stream" token
- if (!lexer->getStream()) {
- return NULL;
- }
- baseStr = lexer->getStream()->getBaseStream();
-
- // skip over stream data
- lexer->setPos(pos + length);
-
- // refill token buffers and check for 'endstream'
- shift(); // kill '>>'
- shift(); // kill 'stream'
- if (buf1.isCmd("endstream")) {
- shift();
- } else {
- error(getPos(), "Missing 'endstream'");
- // kludge for broken PDF files: just add 5k to the length, and
- // hope its enough
- length += 5000;
- }
-
- // make base stream
- str = baseStr->makeSubStream(pos, gTrue, length, dict);
-
- // get filters
- str = str->addFilters(dict);
-
- return str;
-}
-
-void Parser::shift() {
- if (inlineImg > 0) {
- if (inlineImg < 2) {
- ++inlineImg;
- } else {
- // in a damaged content stream, if 'ID' shows up in the middle
- // of a dictionary, we need to reset
- inlineImg = 0;
- }
- } else if (buf2.isCmd("ID")) {
- lexer->skipChar(); // skip char after 'ID' command
- inlineImg = 1;
- }
- buf1.free();
- buf1 = buf2;
- if (inlineImg > 0) // don't buffer inline image data
- buf2.initNull();
- else
- lexer->getObj(&buf2);
-}
+++ /dev/null
-//========================================================================
-//
-// Parser.h
-//
-// Copyright 1996-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#ifndef PARSER_H
-#define PARSER_H
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma interface
-#endif
-
-#include "Lexer.h"
-
-//------------------------------------------------------------------------
-// Parser
-//------------------------------------------------------------------------
-
-class Parser {
-public:
-
- // Constructor.
- Parser(XRef *xrefA, Lexer *lexerA);
-
- // Destructor.
- ~Parser();
-
- // Get the next object from the input stream.
- Object *getObj(Object *obj,
- Guchar *fileKey = NULL, int keyLength = 0,
- int objNum = 0, int objGen = 0);
-
- // Get stream.
- Stream *getStream() { return lexer->getStream(); }
-
- // Get current position in file.
- int getPos() { return lexer->getPos(); }
-
-private:
-
- XRef *xref; // the xref table for this PDF file
- Lexer *lexer; // input stream
- Object buf1, buf2; // next two tokens
- int inlineImg; // set when inline image data is encountered
-
- Stream *makeStream(Object *dict);
- void shift();
-};
-
-#endif
-
+++ /dev/null
-//========================================================================
-//
-// SecurityHandler.cc
-//
-// Copyright 2004 Glyph & Cog, LLC
-//
-//========================================================================
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma implementation
-#endif
-
-#include "GString.h"
-#include "PDFDoc.h"
-#include "Decrypt.h"
-#include "Error.h"
-#include "GlobalParams.h"
-#if HAVE_XPDFCORE
-# include "XPDFCore.h"
-#elif HAVE_WINPDFCORE
-# include "WinPDFCore.h"
-#endif
-#ifdef ENABLE_PLUGINS
-# include "XpdfPluginAPI.h"
-#endif
-#include "SecurityHandler.h"
-
-//------------------------------------------------------------------------
-// SecurityHandler
-//------------------------------------------------------------------------
-
-SecurityHandler *SecurityHandler::make(PDFDoc *docA, Object *encryptDictA) {
- Object filterObj;
- SecurityHandler *secHdlr;
- XpdfSecurityHandler *xsh;
-
- encryptDictA->dictLookup("Filter", &filterObj);
- if (filterObj.isName("Standard")) {
- secHdlr = new StandardSecurityHandler(docA, encryptDictA);
- } else if (filterObj.isName()) {
-#ifdef ENABLE_PLUGINS
- if ((xsh = globalParams->getSecurityHandler(filterObj.getName()))) {
- secHdlr = new ExternalSecurityHandler(docA, encryptDictA, xsh);
- } else {
-#endif
- error(-1, "Couldn't find the '%s' security handler",
- filterObj.getName());
- secHdlr = NULL;
-#ifdef ENABLE_PLUGINS
- }
-#endif
- } else {
- error(-1, "Missing or invalid 'Filter' entry in encryption dictionary");
- secHdlr = NULL;
- }
- filterObj.free();
- return secHdlr;
-}
-
-SecurityHandler::SecurityHandler(PDFDoc *docA) {
- doc = docA;
-}
-
-SecurityHandler::~SecurityHandler() {
-}
-
-GBool SecurityHandler::checkEncryption(GString *ownerPassword,
- GString *userPassword) {
- void *authData;
- GBool ok;
- int i;
-
- if (ownerPassword || userPassword) {
- authData = makeAuthData(ownerPassword, userPassword);
- } else {
- authData = NULL;
- }
- ok = authorize(authData);
- if (authData) {
- freeAuthData(authData);
- }
- for (i = 0; !ok && i < 3; ++i) {
- if (!(authData = getAuthData())) {
- break;
- }
- ok = authorize(authData);
- if (authData) {
- freeAuthData(authData);
- }
- }
- if (!ok) {
- error(-1, "Incorrect password");
- }
- return ok;
-}
-
-//------------------------------------------------------------------------
-// StandardSecurityHandler
-//------------------------------------------------------------------------
-
-class StandardAuthData {
-public:
-
- StandardAuthData(GString *ownerPasswordA, GString *userPasswordA) {
- ownerPassword = ownerPasswordA;
- userPassword = userPasswordA;
- }
-
- ~StandardAuthData() {
- if (ownerPassword) {
- delete ownerPassword;
- }
- if (userPassword) {
- delete userPassword;
- }
- }
-
- GString *ownerPassword;
- GString *userPassword;
-};
-
-StandardSecurityHandler::StandardSecurityHandler(PDFDoc *docA,
- Object *encryptDictA):
- SecurityHandler(docA)
-{
- Object versionObj, revisionObj, lengthObj;
- Object ownerKeyObj, userKeyObj, permObj, fileIDObj;
- Object fileIDObj1;
- Object cryptFiltersObj, streamFilterObj, stringFilterObj;
- Object cryptFilterObj, cfmObj, cfLengthObj;
- Object encryptMetadataObj;
-
- ok = gFalse;
- fileID = NULL;
- ownerKey = NULL;
- userKey = NULL;
-
- encryptDictA->dictLookup("V", &versionObj);
- encryptDictA->dictLookup("R", &revisionObj);
- encryptDictA->dictLookup("Length", &lengthObj);
- encryptDictA->dictLookup("O", &ownerKeyObj);
- encryptDictA->dictLookup("U", &userKeyObj);
- encryptDictA->dictLookup("P", &permObj);
- doc->getXRef()->getTrailerDict()->dictLookup("ID", &fileIDObj);
- if (versionObj.isInt() &&
- revisionObj.isInt() &&
- ownerKeyObj.isString() && ownerKeyObj.getString()->getLength() == 32 &&
- userKeyObj.isString() && userKeyObj.getString()->getLength() == 32 &&
- permObj.isInt()) {
- encVersion = versionObj.getInt();
- encRevision = revisionObj.getInt();
- // revision 2 forces a 40-bit key - some buggy PDF generators
- // set the Length value incorrectly
- if (encRevision == 2 || !lengthObj.isInt()) {
- fileKeyLength = 5;
- } else {
- fileKeyLength = lengthObj.getInt() / 8;
- }
- encryptMetadata = gTrue;
- //~ this currently only handles a subset of crypt filter functionality
- if (encVersion == 4 && encRevision == 4) {
- encryptDictA->dictLookup("CF", &cryptFiltersObj);
- encryptDictA->dictLookup("StmF", &streamFilterObj);
- encryptDictA->dictLookup("StrF", &stringFilterObj);
- if (cryptFiltersObj.isDict() &&
- streamFilterObj.isName() &&
- stringFilterObj.isName() &&
- !strcmp(streamFilterObj.getName(), stringFilterObj.getName())) {
- if (cryptFiltersObj.dictLookup(streamFilterObj.getName(),
- &cryptFilterObj)->isDict()) {
- if (cryptFilterObj.dictLookup("CFM", &cfmObj)->isName("V2")) {
- encVersion = 2;
- encRevision = 3;
- if (cryptFilterObj.dictLookup("Length", &cfLengthObj)->isInt()) {
- //~ according to the spec, this should be cfLengthObj / 8
- fileKeyLength = cfLengthObj.getInt();
- }
- cfLengthObj.free();
- }
- cfmObj.free();
- }
- cryptFilterObj.free();
- }
- stringFilterObj.free();
- streamFilterObj.free();
- cryptFiltersObj.free();
- if (encryptDictA->dictLookup("EncryptMetadata",
- &encryptMetadataObj)->isBool()) {
- encryptMetadata = encryptMetadataObj.getBool();
- }
- encryptMetadataObj.free();
- }
- permFlags = permObj.getInt();
- ownerKey = ownerKeyObj.getString()->copy();
- userKey = userKeyObj.getString()->copy();
- if (encVersion >= 1 && encVersion <= 2 &&
- encRevision >= 2 && encRevision <= 3) {
- if (fileIDObj.isArray()) {
- if (fileIDObj.arrayGet(0, &fileIDObj1)->isString()) {
- fileID = fileIDObj1.getString()->copy();
- } else {
- fileID = new GString();
- }
- fileIDObj1.free();
- } else {
- fileID = new GString();
- }
- ok = gTrue;
- } else {
- error(-1, "Unsupported version/revision (%d/%d) of Standard security handler",
- encVersion, encRevision);
- }
- } else {
- error(-1, "Weird encryption info");
- }
- if (fileKeyLength > 16) {
- fileKeyLength = 16;
- }
- fileIDObj.free();
- permObj.free();
- userKeyObj.free();
- ownerKeyObj.free();
- lengthObj.free();
- revisionObj.free();
- versionObj.free();
-}
-
-StandardSecurityHandler::~StandardSecurityHandler() {
- if (fileID) {
- delete fileID;
- }
- if (ownerKey) {
- delete ownerKey;
- }
- if (userKey) {
- delete userKey;
- }
-}
-
-void *StandardSecurityHandler::makeAuthData(GString *ownerPassword,
- GString *userPassword) {
- return new StandardAuthData(ownerPassword ? ownerPassword->copy()
- : (GString *)NULL,
- userPassword ? userPassword->copy()
- : (GString *)NULL);
-}
-
-void *StandardSecurityHandler::getAuthData() {
-#if HAVE_XPDFCORE
- XPDFCore *core;
- GString *password;
-
- if (!(core = (XPDFCore *)doc->getGUIData()) ||
- !(password = core->getPassword())) {
- return NULL;
- }
- return new StandardAuthData(password, password->copy());
-#elif HAVE_WINPDFCORE
- WinPDFCore *core;
- GString *password;
-
- if (!(core = (WinPDFCore *)doc->getGUIData()) ||
- !(password = core->getPassword())) {
- return NULL;
- }
- return new StandardAuthData(password, password->copy());
-#else
- return NULL;
-#endif
-}
-
-void StandardSecurityHandler::freeAuthData(void *authData) {
- delete (StandardAuthData *)authData;
-}
-
-GBool StandardSecurityHandler::authorize(void *authData) {
- GString *ownerPassword, *userPassword;
-
- if (!ok) {
- return gFalse;
- }
- if (authData) {
- ownerPassword = ((StandardAuthData *)authData)->ownerPassword;
- userPassword = ((StandardAuthData *)authData)->userPassword;
- } else {
- ownerPassword = NULL;
- userPassword = NULL;
- }
- if (!Decrypt::makeFileKey(encVersion, encRevision, fileKeyLength,
- ownerKey, userKey, permFlags, fileID,
- ownerPassword, userPassword, fileKey,
- encryptMetadata, &ownerPasswordOk)) {
- return gFalse;
- }
- return gTrue;
-}
-
-#ifdef ENABLE_PLUGINS
-
-//------------------------------------------------------------------------
-// ExternalSecurityHandler
-//------------------------------------------------------------------------
-
-ExternalSecurityHandler::ExternalSecurityHandler(PDFDoc *docA,
- Object *encryptDictA,
- XpdfSecurityHandler *xshA):
- SecurityHandler(docA)
-{
- encryptDictA->copy(&encryptDict);
- xsh = xshA;
- ok = gFalse;
-
- if (!(*xsh->newDoc)(xsh->handlerData, (XpdfDoc)docA,
- (XpdfObject)encryptDictA, &docData)) {
- return;
- }
-
- ok = gTrue;
-}
-
-ExternalSecurityHandler::~ExternalSecurityHandler() {
- (*xsh->freeDoc)(xsh->handlerData, docData);
- encryptDict.free();
-}
-
-void *ExternalSecurityHandler::makeAuthData(GString *ownerPassword,
- GString *userPassword) {
- char *opw, *upw;
- void *authData;
-
- opw = ownerPassword ? ownerPassword->getCString() : (char *)NULL;
- upw = userPassword ? userPassword->getCString() : (char *)NULL;
- if (!(*xsh->makeAuthData)(xsh->handlerData, docData, opw, upw, &authData)) {
- return NULL;
- }
- return authData;
-}
-
-void *ExternalSecurityHandler::getAuthData() {
- void *authData;
-
- if (!(*xsh->getAuthData)(xsh->handlerData, docData, &authData)) {
- return NULL;
- }
- return authData;
-}
-
-void ExternalSecurityHandler::freeAuthData(void *authData) {
- (*xsh->freeAuthData)(xsh->handlerData, docData, authData);
-}
-
-GBool ExternalSecurityHandler::authorize(void *authData) {
- char *key;
- int length;
-
- if (!ok) {
- return gFalse;
- }
- permFlags = (*xsh->authorize)(xsh->handlerData, docData, authData);
- if (!(permFlags & xpdfPermissionOpen)) {
- return gFalse;
- }
- if (!(*xsh->getKey)(xsh->handlerData, docData, &key, &length, &encVersion)) {
- return gFalse;
- }
- if ((fileKeyLength = length) > 16) {
- fileKeyLength = 16;
- }
- memcpy(fileKey, key, fileKeyLength);
- (*xsh->freeKey)(xsh->handlerData, docData, key, length);
- return gTrue;
-}
-
-#endif // ENABLE_PLUGINS
+++ /dev/null
-//========================================================================
-//
-// SecurityHandler.h
-//
-// Copyright 2004 Glyph & Cog, LLC
-//
-//========================================================================
-
-#ifndef SECURITYHANDLER_H
-#define SECURITYHANDLER_H
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma interface
-#endif
-
-#include "gtypes.h"
-#include "Object.h"
-
-class GString;
-class PDFDoc;
-struct XpdfSecurityHandler;
-
-//------------------------------------------------------------------------
-// SecurityHandler
-//------------------------------------------------------------------------
-
-class SecurityHandler {
-public:
-
- static SecurityHandler *make(PDFDoc *docA, Object *encryptDictA);
-
- SecurityHandler(PDFDoc *docA);
- virtual ~SecurityHandler();
-
- // Check the document's encryption. If the document is encrypted,
- // this will first try <ownerPassword> and <userPassword> (in
- // "batch" mode), and if those fail, it will attempt to request a
- // password from the user. This is the high-level function that
- // calls the lower level functions for the specific security handler
- // (requesting a password three times, etc.). Returns true if the
- // document can be opened (if it's unencrypted, or if a correct
- // password is obtained); false otherwise (encrypted and no correct
- // password).
- GBool checkEncryption(GString *ownerPassword,
- GString *userPassword);
-
- // Create authorization data for the specified owner and user
- // passwords. If the security handler doesn't support "batch" mode,
- // this function should return NULL.
- virtual void *makeAuthData(GString *ownerPassword,
- GString *userPassword) = 0;
-
- // Construct authorization data, typically by prompting the user for
- // a password. Returns an authorization data object, or NULL to
- // cancel.
- virtual void *getAuthData() = 0;
-
- // Free the authorization data returned by makeAuthData or
- // getAuthData.
- virtual void freeAuthData(void *authData) = 0;
-
- // Attempt to authorize the document, using the supplied
- // authorization data (which may be NULL). Returns true if
- // successful (i.e., if at least the right to open the document was
- // granted).
- virtual GBool authorize(void *authData) = 0;
-
- // Return the various authorization parameters. These are only
- // valid after authorize has returned true.
- virtual int getPermissionFlags() = 0;
- virtual GBool getOwnerPasswordOk() = 0;
- virtual Guchar *getFileKey() = 0;
- virtual int getFileKeyLength() = 0;
- virtual int getEncVersion() = 0;
-
-protected:
-
- PDFDoc *doc;
-};
-
-//------------------------------------------------------------------------
-// StandardSecurityHandler
-//------------------------------------------------------------------------
-
-class StandardSecurityHandler: public SecurityHandler {
-public:
-
- StandardSecurityHandler(PDFDoc *docA, Object *encryptDictA);
- virtual ~StandardSecurityHandler();
-
- virtual void *makeAuthData(GString *ownerPassword,
- GString *userPassword);
- virtual void *getAuthData();
- virtual void freeAuthData(void *authData);
- virtual GBool authorize(void *authData);
- virtual int getPermissionFlags() { return permFlags; }
- virtual GBool getOwnerPasswordOk() { return ownerPasswordOk; }
- virtual Guchar *getFileKey() { return fileKey; }
- virtual int getFileKeyLength() { return fileKeyLength; }
- virtual int getEncVersion() { return encVersion; }
-
-private:
-
- int permFlags;
- GBool ownerPasswordOk;
- Guchar fileKey[16];
- int fileKeyLength;
- int encVersion;
- int encRevision;
- GBool encryptMetadata;
-
- GString *ownerKey, *userKey;
- GString *fileID;
- GBool ok;
-};
-
-#ifdef ENABLE_PLUGINS
-//------------------------------------------------------------------------
-// ExternalSecurityHandler
-//------------------------------------------------------------------------
-
-class ExternalSecurityHandler: public SecurityHandler {
-public:
-
- ExternalSecurityHandler(PDFDoc *docA, Object *encryptDictA,
- XpdfSecurityHandler *xshA);
- virtual ~ExternalSecurityHandler();
-
- virtual void *makeAuthData(GString *ownerPassword,
- GString *userPassword);
- virtual void *getAuthData();
- virtual void freeAuthData(void *authData);
- virtual GBool authorize(void *authData);
- virtual int getPermissionFlags() { return permFlags; }
- virtual GBool getOwnerPasswordOk() { return gFalse; }
- virtual Guchar *getFileKey() { return fileKey; }
- virtual int getFileKeyLength() { return fileKeyLength; }
- virtual int getEncVersion() { return encVersion; }
-
-private:
-
- Object encryptDict;
- XpdfSecurityHandler *xsh;
- void *docData;
- int permFlags;
- Guchar fileKey[16];
- int fileKeyLength;
- int encVersion;
- GBool ok;
-};
-#endif // ENABLE_PLUGINS
-
-#endif
+++ /dev/null
-//========================================================================
-//
-// Stream-CCITT.h
-//
-// Tables for CCITT Fax decoding.
-//
-// Copyright 1996-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-struct CCITTCode {
- short bits;
- short n;
-};
-
-#define ccittEOL -2
-
-//------------------------------------------------------------------------
-// 2D codes
-//------------------------------------------------------------------------
-
-#define twoDimPass 0
-#define twoDimHoriz 1
-#define twoDimVert0 2
-#define twoDimVertR1 3
-#define twoDimVertL1 4
-#define twoDimVertR2 5
-#define twoDimVertL2 6
-#define twoDimVertR3 7
-#define twoDimVertL3 8
-
-// 1-7 bit codes
-static CCITTCode twoDimTab1[128] = {
- {-1, -1}, {-1, -1}, // 000000x
- {7, twoDimVertL3}, // 0000010
- {7, twoDimVertR3}, // 0000011
- {6, twoDimVertL2}, {6, twoDimVertL2}, // 000010x
- {6, twoDimVertR2}, {6, twoDimVertR2}, // 000011x
- {4, twoDimPass}, {4, twoDimPass}, // 0001xxx
- {4, twoDimPass}, {4, twoDimPass},
- {4, twoDimPass}, {4, twoDimPass},
- {4, twoDimPass}, {4, twoDimPass},
- {3, twoDimHoriz}, {3, twoDimHoriz}, // 001xxxx
- {3, twoDimHoriz}, {3, twoDimHoriz},
- {3, twoDimHoriz}, {3, twoDimHoriz},
- {3, twoDimHoriz}, {3, twoDimHoriz},
- {3, twoDimHoriz}, {3, twoDimHoriz},
- {3, twoDimHoriz}, {3, twoDimHoriz},
- {3, twoDimHoriz}, {3, twoDimHoriz},
- {3, twoDimHoriz}, {3, twoDimHoriz},
- {3, twoDimVertL1}, {3, twoDimVertL1}, // 010xxxx
- {3, twoDimVertL1}, {3, twoDimVertL1},
- {3, twoDimVertL1}, {3, twoDimVertL1},
- {3, twoDimVertL1}, {3, twoDimVertL1},
- {3, twoDimVertL1}, {3, twoDimVertL1},
- {3, twoDimVertL1}, {3, twoDimVertL1},
- {3, twoDimVertL1}, {3, twoDimVertL1},
- {3, twoDimVertL1}, {3, twoDimVertL1},
- {3, twoDimVertR1}, {3, twoDimVertR1}, // 011xxxx
- {3, twoDimVertR1}, {3, twoDimVertR1},
- {3, twoDimVertR1}, {3, twoDimVertR1},
- {3, twoDimVertR1}, {3, twoDimVertR1},
- {3, twoDimVertR1}, {3, twoDimVertR1},
- {3, twoDimVertR1}, {3, twoDimVertR1},
- {3, twoDimVertR1}, {3, twoDimVertR1},
- {3, twoDimVertR1}, {3, twoDimVertR1},
- {1, twoDimVert0}, {1, twoDimVert0}, // 1xxxxxx
- {1, twoDimVert0}, {1, twoDimVert0},
- {1, twoDimVert0}, {1, twoDimVert0},
- {1, twoDimVert0}, {1, twoDimVert0},
- {1, twoDimVert0}, {1, twoDimVert0},
- {1, twoDimVert0}, {1, twoDimVert0},
- {1, twoDimVert0}, {1, twoDimVert0},
- {1, twoDimVert0}, {1, twoDimVert0},
- {1, twoDimVert0}, {1, twoDimVert0},
- {1, twoDimVert0}, {1, twoDimVert0},
- {1, twoDimVert0}, {1, twoDimVert0},
- {1, twoDimVert0}, {1, twoDimVert0},
- {1, twoDimVert0}, {1, twoDimVert0},
- {1, twoDimVert0}, {1, twoDimVert0},
- {1, twoDimVert0}, {1, twoDimVert0},
- {1, twoDimVert0}, {1, twoDimVert0},
- {1, twoDimVert0}, {1, twoDimVert0},
- {1, twoDimVert0}, {1, twoDimVert0},
- {1, twoDimVert0}, {1, twoDimVert0},
- {1, twoDimVert0}, {1, twoDimVert0},
- {1, twoDimVert0}, {1, twoDimVert0},
- {1, twoDimVert0}, {1, twoDimVert0},
- {1, twoDimVert0}, {1, twoDimVert0},
- {1, twoDimVert0}, {1, twoDimVert0},
- {1, twoDimVert0}, {1, twoDimVert0},
- {1, twoDimVert0}, {1, twoDimVert0},
- {1, twoDimVert0}, {1, twoDimVert0},
- {1, twoDimVert0}, {1, twoDimVert0},
- {1, twoDimVert0}, {1, twoDimVert0},
- {1, twoDimVert0}, {1, twoDimVert0},
- {1, twoDimVert0}, {1, twoDimVert0},
- {1, twoDimVert0}, {1, twoDimVert0}
-};
-
-//------------------------------------------------------------------------
-// white run lengths
-//------------------------------------------------------------------------
-
-// 11-12 bit codes (upper 7 bits are 0)
-static CCITTCode whiteTab1[32] = {
- {-1, -1}, // 00000
- {12, ccittEOL}, // 00001
- {-1, -1}, {-1, -1}, // 0001x
- {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}, // 001xx
- {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}, // 010xx
- {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}, // 011xx
- {11, 1792}, {11, 1792}, // 1000x
- {12, 1984}, // 10010
- {12, 2048}, // 10011
- {12, 2112}, // 10100
- {12, 2176}, // 10101
- {12, 2240}, // 10110
- {12, 2304}, // 10111
- {11, 1856}, {11, 1856}, // 1100x
- {11, 1920}, {11, 1920}, // 1101x
- {12, 2368}, // 11100
- {12, 2432}, // 11101
- {12, 2496}, // 11110
- {12, 2560} // 11111
-};
-
-// 1-9 bit codes
-static CCITTCode whiteTab2[512] = {
- {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}, // 0000000xx
- {8, 29}, {8, 29}, // 00000010x
- {8, 30}, {8, 30}, // 00000011x
- {8, 45}, {8, 45}, // 00000100x
- {8, 46}, {8, 46}, // 00000101x
- {7, 22}, {7, 22}, {7, 22}, {7, 22}, // 0000011xx
- {7, 23}, {7, 23}, {7, 23}, {7, 23}, // 0000100xx
- {8, 47}, {8, 47}, // 00001010x
- {8, 48}, {8, 48}, // 00001011x
- {6, 13}, {6, 13}, {6, 13}, {6, 13}, // 000011xxx
- {6, 13}, {6, 13}, {6, 13}, {6, 13},
- {7, 20}, {7, 20}, {7, 20}, {7, 20}, // 0001000xx
- {8, 33}, {8, 33}, // 00010010x
- {8, 34}, {8, 34}, // 00010011x
- {8, 35}, {8, 35}, // 00010100x
- {8, 36}, {8, 36}, // 00010101x
- {8, 37}, {8, 37}, // 00010110x
- {8, 38}, {8, 38}, // 00010111x
- {7, 19}, {7, 19}, {7, 19}, {7, 19}, // 0001100xx
- {8, 31}, {8, 31}, // 00011010x
- {8, 32}, {8, 32}, // 00011011x
- {6, 1}, {6, 1}, {6, 1}, {6, 1}, // 000111xxx
- {6, 1}, {6, 1}, {6, 1}, {6, 1},
- {6, 12}, {6, 12}, {6, 12}, {6, 12}, // 001000xxx
- {6, 12}, {6, 12}, {6, 12}, {6, 12},
- {8, 53}, {8, 53}, // 00100100x
- {8, 54}, {8, 54}, // 00100101x
- {7, 26}, {7, 26}, {7, 26}, {7, 26}, // 0010011xx
- {8, 39}, {8, 39}, // 00101000x
- {8, 40}, {8, 40}, // 00101001x
- {8, 41}, {8, 41}, // 00101010x
- {8, 42}, {8, 42}, // 00101011x
- {8, 43}, {8, 43}, // 00101100x
- {8, 44}, {8, 44}, // 00101101x
- {7, 21}, {7, 21}, {7, 21}, {7, 21}, // 0010111xx
- {7, 28}, {7, 28}, {7, 28}, {7, 28}, // 0011000xx
- {8, 61}, {8, 61}, // 00110010x
- {8, 62}, {8, 62}, // 00110011x
- {8, 63}, {8, 63}, // 00110100x
- {8, 0}, {8, 0}, // 00110101x
- {8, 320}, {8, 320}, // 00110110x
- {8, 384}, {8, 384}, // 00110111x
- {5, 10}, {5, 10}, {5, 10}, {5, 10}, // 00111xxxx
- {5, 10}, {5, 10}, {5, 10}, {5, 10},
- {5, 10}, {5, 10}, {5, 10}, {5, 10},
- {5, 10}, {5, 10}, {5, 10}, {5, 10},
- {5, 11}, {5, 11}, {5, 11}, {5, 11}, // 01000xxxx
- {5, 11}, {5, 11}, {5, 11}, {5, 11},
- {5, 11}, {5, 11}, {5, 11}, {5, 11},
- {5, 11}, {5, 11}, {5, 11}, {5, 11},
- {7, 27}, {7, 27}, {7, 27}, {7, 27}, // 0100100xx
- {8, 59}, {8, 59}, // 01001010x
- {8, 60}, {8, 60}, // 01001011x
- {9, 1472}, // 010011000
- {9, 1536}, // 010011001
- {9, 1600}, // 010011010
- {9, 1728}, // 010011011
- {7, 18}, {7, 18}, {7, 18}, {7, 18}, // 0100111xx
- {7, 24}, {7, 24}, {7, 24}, {7, 24}, // 0101000xx
- {8, 49}, {8, 49}, // 01010010x
- {8, 50}, {8, 50}, // 01010011x
- {8, 51}, {8, 51}, // 01010100x
- {8, 52}, {8, 52}, // 01010101x
- {7, 25}, {7, 25}, {7, 25}, {7, 25}, // 0101011xx
- {8, 55}, {8, 55}, // 01011000x
- {8, 56}, {8, 56}, // 01011001x
- {8, 57}, {8, 57}, // 01011010x
- {8, 58}, {8, 58}, // 01011011x
- {6, 192}, {6, 192}, {6, 192}, {6, 192}, // 010111xxx
- {6, 192}, {6, 192}, {6, 192}, {6, 192},
- {6, 1664}, {6, 1664}, {6, 1664}, {6, 1664}, // 011000xxx
- {6, 1664}, {6, 1664}, {6, 1664}, {6, 1664},
- {8, 448}, {8, 448}, // 01100100x
- {8, 512}, {8, 512}, // 01100101x
- {9, 704}, // 011001100
- {9, 768}, // 011001101
- {8, 640}, {8, 640}, // 01100111x
- {8, 576}, {8, 576}, // 01101000x
- {9, 832}, // 011010010
- {9, 896}, // 011010011
- {9, 960}, // 011010100
- {9, 1024}, // 011010101
- {9, 1088}, // 011010110
- {9, 1152}, // 011010111
- {9, 1216}, // 011011000
- {9, 1280}, // 011011001
- {9, 1344}, // 011011010
- {9, 1408}, // 011011011
- {7, 256}, {7, 256}, {7, 256}, {7, 256}, // 0110111xx
- {4, 2}, {4, 2}, {4, 2}, {4, 2}, // 0111xxxxx
- {4, 2}, {4, 2}, {4, 2}, {4, 2},
- {4, 2}, {4, 2}, {4, 2}, {4, 2},
- {4, 2}, {4, 2}, {4, 2}, {4, 2},
- {4, 2}, {4, 2}, {4, 2}, {4, 2},
- {4, 2}, {4, 2}, {4, 2}, {4, 2},
- {4, 2}, {4, 2}, {4, 2}, {4, 2},
- {4, 2}, {4, 2}, {4, 2}, {4, 2},
- {4, 3}, {4, 3}, {4, 3}, {4, 3}, // 1000xxxxx
- {4, 3}, {4, 3}, {4, 3}, {4, 3},
- {4, 3}, {4, 3}, {4, 3}, {4, 3},
- {4, 3}, {4, 3}, {4, 3}, {4, 3},
- {4, 3}, {4, 3}, {4, 3}, {4, 3},
- {4, 3}, {4, 3}, {4, 3}, {4, 3},
- {4, 3}, {4, 3}, {4, 3}, {4, 3},
- {4, 3}, {4, 3}, {4, 3}, {4, 3},
- {5, 128}, {5, 128}, {5, 128}, {5, 128}, // 10010xxxx
- {5, 128}, {5, 128}, {5, 128}, {5, 128},
- {5, 128}, {5, 128}, {5, 128}, {5, 128},
- {5, 128}, {5, 128}, {5, 128}, {5, 128},
- {5, 8}, {5, 8}, {5, 8}, {5, 8}, // 10011xxxx
- {5, 8}, {5, 8}, {5, 8}, {5, 8},
- {5, 8}, {5, 8}, {5, 8}, {5, 8},
- {5, 8}, {5, 8}, {5, 8}, {5, 8},
- {5, 9}, {5, 9}, {5, 9}, {5, 9}, // 10100xxxx
- {5, 9}, {5, 9}, {5, 9}, {5, 9},
- {5, 9}, {5, 9}, {5, 9}, {5, 9},
- {5, 9}, {5, 9}, {5, 9}, {5, 9},
- {6, 16}, {6, 16}, {6, 16}, {6, 16}, // 101010xxx
- {6, 16}, {6, 16}, {6, 16}, {6, 16},
- {6, 17}, {6, 17}, {6, 17}, {6, 17}, // 101011xxx
- {6, 17}, {6, 17}, {6, 17}, {6, 17},
- {4, 4}, {4, 4}, {4, 4}, {4, 4}, // 1011xxxxx
- {4, 4}, {4, 4}, {4, 4}, {4, 4},
- {4, 4}, {4, 4}, {4, 4}, {4, 4},
- {4, 4}, {4, 4}, {4, 4}, {4, 4},
- {4, 4}, {4, 4}, {4, 4}, {4, 4},
- {4, 4}, {4, 4}, {4, 4}, {4, 4},
- {4, 4}, {4, 4}, {4, 4}, {4, 4},
- {4, 4}, {4, 4}, {4, 4}, {4, 4},
- {4, 5}, {4, 5}, {4, 5}, {4, 5}, // 1100xxxxx
- {4, 5}, {4, 5}, {4, 5}, {4, 5},
- {4, 5}, {4, 5}, {4, 5}, {4, 5},
- {4, 5}, {4, 5}, {4, 5}, {4, 5},
- {4, 5}, {4, 5}, {4, 5}, {4, 5},
- {4, 5}, {4, 5}, {4, 5}, {4, 5},
- {4, 5}, {4, 5}, {4, 5}, {4, 5},
- {4, 5}, {4, 5}, {4, 5}, {4, 5},
- {6, 14}, {6, 14}, {6, 14}, {6, 14}, // 110100xxx
- {6, 14}, {6, 14}, {6, 14}, {6, 14},
- {6, 15}, {6, 15}, {6, 15}, {6, 15}, // 110101xxx
- {6, 15}, {6, 15}, {6, 15}, {6, 15},
- {5, 64}, {5, 64}, {5, 64}, {5, 64}, // 11011xxxx
- {5, 64}, {5, 64}, {5, 64}, {5, 64},
- {5, 64}, {5, 64}, {5, 64}, {5, 64},
- {5, 64}, {5, 64}, {5, 64}, {5, 64},
- {4, 6}, {4, 6}, {4, 6}, {4, 6}, // 1110xxxxx
- {4, 6}, {4, 6}, {4, 6}, {4, 6},
- {4, 6}, {4, 6}, {4, 6}, {4, 6},
- {4, 6}, {4, 6}, {4, 6}, {4, 6},
- {4, 6}, {4, 6}, {4, 6}, {4, 6},
- {4, 6}, {4, 6}, {4, 6}, {4, 6},
- {4, 6}, {4, 6}, {4, 6}, {4, 6},
- {4, 6}, {4, 6}, {4, 6}, {4, 6},
- {4, 7}, {4, 7}, {4, 7}, {4, 7}, // 1111xxxxx
- {4, 7}, {4, 7}, {4, 7}, {4, 7},
- {4, 7}, {4, 7}, {4, 7}, {4, 7},
- {4, 7}, {4, 7}, {4, 7}, {4, 7},
- {4, 7}, {4, 7}, {4, 7}, {4, 7},
- {4, 7}, {4, 7}, {4, 7}, {4, 7},
- {4, 7}, {4, 7}, {4, 7}, {4, 7},
- {4, 7}, {4, 7}, {4, 7}, {4, 7}
-};
-
-//------------------------------------------------------------------------
-// black run lengths
-//------------------------------------------------------------------------
-
-// 10-13 bit codes (upper 6 bits are 0)
-static CCITTCode blackTab1[128] = {
- {-1, -1}, {-1, -1}, // 000000000000x
- {12, ccittEOL}, {12, ccittEOL}, // 000000000001x
- {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}, // 00000000001xx
- {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}, // 00000000010xx
- {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}, // 00000000011xx
- {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}, // 00000000100xx
- {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}, // 00000000101xx
- {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}, // 00000000110xx
- {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}, // 00000000111xx
- {11, 1792}, {11, 1792}, {11, 1792}, {11, 1792}, // 00000001000xx
- {12, 1984}, {12, 1984}, // 000000010010x
- {12, 2048}, {12, 2048}, // 000000010011x
- {12, 2112}, {12, 2112}, // 000000010100x
- {12, 2176}, {12, 2176}, // 000000010101x
- {12, 2240}, {12, 2240}, // 000000010110x
- {12, 2304}, {12, 2304}, // 000000010111x
- {11, 1856}, {11, 1856}, {11, 1856}, {11, 1856}, // 00000001100xx
- {11, 1920}, {11, 1920}, {11, 1920}, {11, 1920}, // 00000001101xx
- {12, 2368}, {12, 2368}, // 000000011100x
- {12, 2432}, {12, 2432}, // 000000011101x
- {12, 2496}, {12, 2496}, // 000000011110x
- {12, 2560}, {12, 2560}, // 000000011111x
- {10, 18}, {10, 18}, {10, 18}, {10, 18}, // 0000001000xxx
- {10, 18}, {10, 18}, {10, 18}, {10, 18},
- {12, 52}, {12, 52}, // 000000100100x
- {13, 640}, // 0000001001010
- {13, 704}, // 0000001001011
- {13, 768}, // 0000001001100
- {13, 832}, // 0000001001101
- {12, 55}, {12, 55}, // 000000100111x
- {12, 56}, {12, 56}, // 000000101000x
- {13, 1280}, // 0000001010010
- {13, 1344}, // 0000001010011
- {13, 1408}, // 0000001010100
- {13, 1472}, // 0000001010101
- {12, 59}, {12, 59}, // 000000101011x
- {12, 60}, {12, 60}, // 000000101100x
- {13, 1536}, // 0000001011010
- {13, 1600}, // 0000001011011
- {11, 24}, {11, 24}, {11, 24}, {11, 24}, // 00000010111xx
- {11, 25}, {11, 25}, {11, 25}, {11, 25}, // 00000011000xx
- {13, 1664}, // 0000001100100
- {13, 1728}, // 0000001100101
- {12, 320}, {12, 320}, // 000000110011x
- {12, 384}, {12, 384}, // 000000110100x
- {12, 448}, {12, 448}, // 000000110101x
- {13, 512}, // 0000001101100
- {13, 576}, // 0000001101101
- {12, 53}, {12, 53}, // 000000110111x
- {12, 54}, {12, 54}, // 000000111000x
- {13, 896}, // 0000001110010
- {13, 960}, // 0000001110011
- {13, 1024}, // 0000001110100
- {13, 1088}, // 0000001110101
- {13, 1152}, // 0000001110110
- {13, 1216}, // 0000001110111
- {10, 64}, {10, 64}, {10, 64}, {10, 64}, // 0000001111xxx
- {10, 64}, {10, 64}, {10, 64}, {10, 64}
-};
-
-// 7-12 bit codes (upper 4 bits are 0)
-static CCITTCode blackTab2[192] = {
- {8, 13}, {8, 13}, {8, 13}, {8, 13}, // 00000100xxxx
- {8, 13}, {8, 13}, {8, 13}, {8, 13},
- {8, 13}, {8, 13}, {8, 13}, {8, 13},
- {8, 13}, {8, 13}, {8, 13}, {8, 13},
- {11, 23}, {11, 23}, // 00000101000x
- {12, 50}, // 000001010010
- {12, 51}, // 000001010011
- {12, 44}, // 000001010100
- {12, 45}, // 000001010101
- {12, 46}, // 000001010110
- {12, 47}, // 000001010111
- {12, 57}, // 000001011000
- {12, 58}, // 000001011001
- {12, 61}, // 000001011010
- {12, 256}, // 000001011011
- {10, 16}, {10, 16}, {10, 16}, {10, 16}, // 0000010111xx
- {10, 17}, {10, 17}, {10, 17}, {10, 17}, // 0000011000xx
- {12, 48}, // 000001100100
- {12, 49}, // 000001100101
- {12, 62}, // 000001100110
- {12, 63}, // 000001100111
- {12, 30}, // 000001101000
- {12, 31}, // 000001101001
- {12, 32}, // 000001101010
- {12, 33}, // 000001101011
- {12, 40}, // 000001101100
- {12, 41}, // 000001101101
- {11, 22}, {11, 22}, // 00000110111x
- {8, 14}, {8, 14}, {8, 14}, {8, 14}, // 00000111xxxx
- {8, 14}, {8, 14}, {8, 14}, {8, 14},
- {8, 14}, {8, 14}, {8, 14}, {8, 14},
- {8, 14}, {8, 14}, {8, 14}, {8, 14},
- {7, 10}, {7, 10}, {7, 10}, {7, 10}, // 0000100xxxxx
- {7, 10}, {7, 10}, {7, 10}, {7, 10},
- {7, 10}, {7, 10}, {7, 10}, {7, 10},
- {7, 10}, {7, 10}, {7, 10}, {7, 10},
- {7, 10}, {7, 10}, {7, 10}, {7, 10},
- {7, 10}, {7, 10}, {7, 10}, {7, 10},
- {7, 10}, {7, 10}, {7, 10}, {7, 10},
- {7, 10}, {7, 10}, {7, 10}, {7, 10},
- {7, 11}, {7, 11}, {7, 11}, {7, 11}, // 0000101xxxxx
- {7, 11}, {7, 11}, {7, 11}, {7, 11},
- {7, 11}, {7, 11}, {7, 11}, {7, 11},
- {7, 11}, {7, 11}, {7, 11}, {7, 11},
- {7, 11}, {7, 11}, {7, 11}, {7, 11},
- {7, 11}, {7, 11}, {7, 11}, {7, 11},
- {7, 11}, {7, 11}, {7, 11}, {7, 11},
- {7, 11}, {7, 11}, {7, 11}, {7, 11},
- {9, 15}, {9, 15}, {9, 15}, {9, 15}, // 000011000xxx
- {9, 15}, {9, 15}, {9, 15}, {9, 15},
- {12, 128}, // 000011001000
- {12, 192}, // 000011001001
- {12, 26}, // 000011001010
- {12, 27}, // 000011001011
- {12, 28}, // 000011001100
- {12, 29}, // 000011001101
- {11, 19}, {11, 19}, // 00001100111x
- {11, 20}, {11, 20}, // 00001101000x
- {12, 34}, // 000011010010
- {12, 35}, // 000011010011
- {12, 36}, // 000011010100
- {12, 37}, // 000011010101
- {12, 38}, // 000011010110
- {12, 39}, // 000011010111
- {11, 21}, {11, 21}, // 00001101100x
- {12, 42}, // 000011011010
- {12, 43}, // 000011011011
- {10, 0}, {10, 0}, {10, 0}, {10, 0}, // 0000110111xx
- {7, 12}, {7, 12}, {7, 12}, {7, 12}, // 0000111xxxxx
- {7, 12}, {7, 12}, {7, 12}, {7, 12},
- {7, 12}, {7, 12}, {7, 12}, {7, 12},
- {7, 12}, {7, 12}, {7, 12}, {7, 12},
- {7, 12}, {7, 12}, {7, 12}, {7, 12},
- {7, 12}, {7, 12}, {7, 12}, {7, 12},
- {7, 12}, {7, 12}, {7, 12}, {7, 12},
- {7, 12}, {7, 12}, {7, 12}, {7, 12}
-};
-
-// 2-6 bit codes
-static CCITTCode blackTab3[64] = {
- {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}, // 0000xx
- {6, 9}, // 000100
- {6, 8}, // 000101
- {5, 7}, {5, 7}, // 00011x
- {4, 6}, {4, 6}, {4, 6}, {4, 6}, // 0010xx
- {4, 5}, {4, 5}, {4, 5}, {4, 5}, // 0011xx
- {3, 1}, {3, 1}, {3, 1}, {3, 1}, // 010xxx
- {3, 1}, {3, 1}, {3, 1}, {3, 1},
- {3, 4}, {3, 4}, {3, 4}, {3, 4}, // 011xxx
- {3, 4}, {3, 4}, {3, 4}, {3, 4},
- {2, 3}, {2, 3}, {2, 3}, {2, 3}, // 10xxxx
- {2, 3}, {2, 3}, {2, 3}, {2, 3},
- {2, 3}, {2, 3}, {2, 3}, {2, 3},
- {2, 3}, {2, 3}, {2, 3}, {2, 3},
- {2, 2}, {2, 2}, {2, 2}, {2, 2}, // 11xxxx
- {2, 2}, {2, 2}, {2, 2}, {2, 2},
- {2, 2}, {2, 2}, {2, 2}, {2, 2},
- {2, 2}, {2, 2}, {2, 2}, {2, 2}
-};
+++ /dev/null
-//========================================================================
-//
-// Stream.cc
-//
-// Copyright 1996-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma implementation
-#endif
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stddef.h>
-#ifndef WIN32
-#include <unistd.h>
-#endif
-#include <string.h>
-#include <ctype.h>
-#include "gmem.h"
-#include "gfile.h"
-#include "config.h"
-#include "Error.h"
-#include "Object.h"
-#include "Lexer.h"
-#include "Decrypt.h"
-#include "GfxState.h"
-#include "Stream.h"
-#include "JBIG2Stream.h"
-#include "JPXStream.h"
-#include "Stream-CCITT.h"
-
-#ifdef __DJGPP__
-static GBool setDJSYSFLAGS = gFalse;
-#endif
-
-#ifdef VMS
-#ifdef __GNUC__
-#define SEEK_SET 0
-#define SEEK_CUR 1
-#define SEEK_END 2
-#endif
-#endif
-
-//------------------------------------------------------------------------
-// Stream (base class)
-//------------------------------------------------------------------------
-
-Stream::Stream() {
- ref = 1;
-}
-
-Stream::~Stream() {
-}
-
-void Stream::close() {
-}
-
-int Stream::getRawChar() {
- error(-1, "Internal: called getRawChar() on non-predictor stream");
- return EOF;
-}
-
-char *Stream::getLine(char *buf, int size) {
- int i;
- int c;
-
- if (lookChar() == EOF)
- return NULL;
- for (i = 0; i < size - 1; ++i) {
- c = getChar();
- if (c == EOF || c == '\n')
- break;
- if (c == '\r') {
- if ((c = lookChar()) == '\n')
- getChar();
- break;
- }
- buf[i] = c;
- }
- buf[i] = '\0';
- return buf;
-}
-
-GString *Stream::getPSFilter(int psLevel, char *indent) {
- return new GString();
-}
-
-Stream *Stream::addFilters(Object *dict) {
- Object obj, obj2;
- Object params, params2;
- Stream *str;
- int i;
-
- str = this;
- dict->dictLookup("Filter", &obj);
- if (obj.isNull()) {
- obj.free();
- dict->dictLookup("F", &obj);
- }
- dict->dictLookup("DecodeParms", ¶ms);
- if (params.isNull()) {
- params.free();
- dict->dictLookup("DP", ¶ms);
- }
- if (obj.isName()) {
- str = makeFilter(obj.getName(), str, ¶ms);
- } else if (obj.isArray()) {
- for (i = 0; i < obj.arrayGetLength(); ++i) {
- obj.arrayGet(i, &obj2);
- if (params.isArray())
- params.arrayGet(i, ¶ms2);
- else
- params2.initNull();
- if (obj2.isName()) {
- str = makeFilter(obj2.getName(), str, ¶ms2);
- } else {
- error(getPos(), "Bad filter name");
- str = new EOFStream(str);
- }
- obj2.free();
- params2.free();
- }
- } else if (!obj.isNull()) {
- error(getPos(), "Bad 'Filter' attribute in stream");
- }
- obj.free();
- params.free();
-
- return str;
-}
-
-Stream *Stream::makeFilter(char *name, Stream *str, Object *params) {
- int pred; // parameters
- int colors;
- int bits;
- int early;
- int encoding;
- GBool endOfLine, byteAlign, endOfBlock, black;
- int columns, rows;
- Object globals, obj;
-
- if (!strcmp(name, "ASCIIHexDecode") || !strcmp(name, "AHx")) {
- str = new ASCIIHexStream(str);
- } else if (!strcmp(name, "ASCII85Decode") || !strcmp(name, "A85")) {
- str = new ASCII85Stream(str);
- } else if (!strcmp(name, "LZWDecode") || !strcmp(name, "LZW")) {
- pred = 1;
- columns = 1;
- colors = 1;
- bits = 8;
- early = 1;
- if (params->isDict()) {
- params->dictLookup("Predictor", &obj);
- if (obj.isInt())
- pred = obj.getInt();
- obj.free();
- params->dictLookup("Columns", &obj);
- if (obj.isInt())
- columns = obj.getInt();
- obj.free();
- params->dictLookup("Colors", &obj);
- if (obj.isInt())
- colors = obj.getInt();
- obj.free();
- params->dictLookup("BitsPerComponent", &obj);
- if (obj.isInt())
- bits = obj.getInt();
- obj.free();
- params->dictLookup("EarlyChange", &obj);
- if (obj.isInt())
- early = obj.getInt();
- obj.free();
- }
- str = new LZWStream(str, pred, columns, colors, bits, early);
- } else if (!strcmp(name, "RunLengthDecode") || !strcmp(name, "RL")) {
- str = new RunLengthStream(str);
- } else if (!strcmp(name, "CCITTFaxDecode") || !strcmp(name, "CCF")) {
- encoding = 0;
- endOfLine = gFalse;
- byteAlign = gFalse;
- columns = 1728;
- rows = 0;
- endOfBlock = gTrue;
- black = gFalse;
- if (params->isDict()) {
- params->dictLookup("K", &obj);
- if (obj.isInt()) {
- encoding = obj.getInt();
- }
- obj.free();
- params->dictLookup("EndOfLine", &obj);
- if (obj.isBool()) {
- endOfLine = obj.getBool();
- }
- obj.free();
- params->dictLookup("EncodedByteAlign", &obj);
- if (obj.isBool()) {
- byteAlign = obj.getBool();
- }
- obj.free();
- params->dictLookup("Columns", &obj);
- if (obj.isInt()) {
- columns = obj.getInt();
- }
- obj.free();
- params->dictLookup("Rows", &obj);
- if (obj.isInt()) {
- rows = obj.getInt();
- }
- obj.free();
- params->dictLookup("EndOfBlock", &obj);
- if (obj.isBool()) {
- endOfBlock = obj.getBool();
- }
- obj.free();
- params->dictLookup("BlackIs1", &obj);
- if (obj.isBool()) {
- black = obj.getBool();
- }
- obj.free();
- }
- str = new CCITTFaxStream(str, encoding, endOfLine, byteAlign,
- columns, rows, endOfBlock, black);
- } else if (!strcmp(name, "DCTDecode") || !strcmp(name, "DCT")) {
- str = new DCTStream(str);
- } else if (!strcmp(name, "FlateDecode") || !strcmp(name, "Fl")) {
- pred = 1;
- columns = 1;
- colors = 1;
- bits = 8;
- if (params->isDict()) {
- params->dictLookup("Predictor", &obj);
- if (obj.isInt())
- pred = obj.getInt();
- obj.free();
- params->dictLookup("Columns", &obj);
- if (obj.isInt())
- columns = obj.getInt();
- obj.free();
- params->dictLookup("Colors", &obj);
- if (obj.isInt())
- colors = obj.getInt();
- obj.free();
- params->dictLookup("BitsPerComponent", &obj);
- if (obj.isInt())
- bits = obj.getInt();
- obj.free();
- }
- str = new FlateStream(str, pred, columns, colors, bits);
- } else if (!strcmp(name, "JBIG2Decode")) {
- if (params->isDict()) {
- params->dictLookup("JBIG2Globals", &globals);
- }
- str = new JBIG2Stream(str, &globals);
- globals.free();
- } else if (!strcmp(name, "JPXDecode")) {
- str = new JPXStream(str);
- } else {
- error(getPos(), "Unknown filter '%s'", name);
- str = new EOFStream(str);
- }
- return str;
-}
-
-//------------------------------------------------------------------------
-// BaseStream
-//------------------------------------------------------------------------
-
-BaseStream::BaseStream(Object *dictA) {
- dict = *dictA;
- decrypt = NULL;
-}
-
-BaseStream::~BaseStream() {
- dict.free();
- if (decrypt)
- delete decrypt;
-}
-
-void BaseStream::doDecryption(Guchar *fileKey, int keyLength,
- int objNum, int objGen) {
- decrypt = new Decrypt(fileKey, keyLength, objNum, objGen);
-}
-
-//------------------------------------------------------------------------
-// FilterStream
-//------------------------------------------------------------------------
-
-FilterStream::FilterStream(Stream *strA) {
- str = strA;
-}
-
-FilterStream::~FilterStream() {
-}
-
-void FilterStream::close() {
- str->close();
-}
-
-void FilterStream::setPos(Guint pos, int dir) {
- error(-1, "Internal: called setPos() on FilterStream");
-}
-
-//------------------------------------------------------------------------
-// ImageStream
-//------------------------------------------------------------------------
-
-ImageStream::ImageStream(Stream *strA, int widthA, int nCompsA, int nBitsA) {
- int imgLineSize;
-
- str = strA;
- width = widthA;
- nComps = nCompsA;
- nBits = nBitsA;
-
- nVals = width * nComps;
- if (nBits == 1) {
- imgLineSize = (nVals + 7) & ~7;
- } else {
- imgLineSize = nVals;
- }
- imgLine = (Guchar *)gmallocn(imgLineSize, sizeof(Guchar));
- imgIdx = nVals;
-}
-
-ImageStream::~ImageStream() {
- gfree(imgLine);
-}
-
-void ImageStream::reset() {
- str->reset();
-}
-
-GBool ImageStream::getPixel(Guchar *pix) {
- int i;
-
- if (imgIdx >= nVals) {
- getLine();
- imgIdx = 0;
- }
- for (i = 0; i < nComps; ++i) {
- pix[i] = imgLine[imgIdx++];
- }
- return gTrue;
-}
-
-Guchar *ImageStream::getLine() {
- Gulong buf, bitMask;
- int bits;
- int c;
- int i;
-
- if (nBits == 1) {
- for (i = 0; i < nVals; i += 8) {
- c = str->getChar();
- imgLine[i+0] = (Guchar)((c >> 7) & 1);
- imgLine[i+1] = (Guchar)((c >> 6) & 1);
- imgLine[i+2] = (Guchar)((c >> 5) & 1);
- imgLine[i+3] = (Guchar)((c >> 4) & 1);
- imgLine[i+4] = (Guchar)((c >> 3) & 1);
- imgLine[i+5] = (Guchar)((c >> 2) & 1);
- imgLine[i+6] = (Guchar)((c >> 1) & 1);
- imgLine[i+7] = (Guchar)(c & 1);
- }
- } else if (nBits == 8) {
- for (i = 0; i < nVals; ++i) {
- imgLine[i] = str->getChar();
- }
- } else {
- bitMask = (1 << nBits) - 1;
- buf = 0;
- bits = 0;
- for (i = 0; i < nVals; ++i) {
- if (bits < nBits) {
- buf = (buf << 8) | (str->getChar() & 0xff);
- bits += 8;
- }
- imgLine[i] = (Guchar)((buf >> (bits - nBits)) & bitMask);
- bits -= nBits;
- }
- }
- return imgLine;
-}
-
-void ImageStream::skipLine() {
- int n, i;
-
- n = (nVals * nBits + 7) >> 3;
- for (i = 0; i < n; ++i) {
- str->getChar();
- }
-}
-
-//------------------------------------------------------------------------
-// StreamPredictor
-//------------------------------------------------------------------------
-
-StreamPredictor::StreamPredictor(Stream *strA, int predictorA,
- int widthA, int nCompsA, int nBitsA) {
- int totalBits;
-
- str = strA;
- predictor = predictorA;
- width = widthA;
- nComps = nCompsA;
- nBits = nBitsA;
- predLine = NULL;
- ok = gFalse;
-
- nVals = width * nComps;
- totalBits = nVals * nBits;
- if (totalBits == 0 ||
- (totalBits / nBits) / nComps != width ||
- totalBits + 7 < 0) {
- return;
- }
- pixBytes = (nComps * nBits + 7) >> 3;
- rowBytes = ((totalBits + 7) >> 3) + pixBytes;
- if (rowBytes < 0) {
- return;
- }
- predLine = (Guchar *)gmalloc(rowBytes);
- memset(predLine, 0, rowBytes);
- predIdx = rowBytes;
-
- ok = gTrue;
-}
-
-StreamPredictor::~StreamPredictor() {
- gfree(predLine);
-}
-
-int StreamPredictor::lookChar() {
- if (predIdx >= rowBytes) {
- if (!getNextLine()) {
- return EOF;
- }
- }
- return predLine[predIdx];
-}
-
-int StreamPredictor::getChar() {
- if (predIdx >= rowBytes) {
- if (!getNextLine()) {
- return EOF;
- }
- }
- return predLine[predIdx++];
-}
-
-GBool StreamPredictor::getNextLine() {
- int curPred;
- Guchar upLeftBuf[gfxColorMaxComps * 2 + 1];
- int left, up, upLeft, p, pa, pb, pc;
- int c;
- Gulong inBuf, outBuf, bitMask;
- int inBits, outBits;
- int i, j, k, kk;
-
- // get PNG optimum predictor number
- if (predictor >= 10) {
- if ((curPred = str->getRawChar()) == EOF) {
- return gFalse;
- }
- curPred += 10;
- } else {
- curPred = predictor;
- }
-
- // read the raw line, apply PNG (byte) predictor
- memset(upLeftBuf, 0, pixBytes + 1);
- for (i = pixBytes; i < rowBytes; ++i) {
- for (j = pixBytes; j > 0; --j) {
- upLeftBuf[j] = upLeftBuf[j-1];
- }
- upLeftBuf[0] = predLine[i];
- if ((c = str->getRawChar()) == EOF) {
- if (i > pixBytes) {
- // this ought to return false, but some (broken) PDF files
- // contain truncated image data, and Adobe apparently reads the
- // last partial line
- break;
- }
- return gFalse;
- }
- switch (curPred) {
- case 11: // PNG sub
- predLine[i] = predLine[i - pixBytes] + (Guchar)c;
- break;
- case 12: // PNG up
- predLine[i] = predLine[i] + (Guchar)c;
- break;
- case 13: // PNG average
- predLine[i] = ((predLine[i - pixBytes] + predLine[i]) >> 1) +
- (Guchar)c;
- break;
- case 14: // PNG Paeth
- left = predLine[i - pixBytes];
- up = predLine[i];
- upLeft = upLeftBuf[pixBytes];
- p = left + up - upLeft;
- if ((pa = p - left) < 0)
- pa = -pa;
- if ((pb = p - up) < 0)
- pb = -pb;
- if ((pc = p - upLeft) < 0)
- pc = -pc;
- if (pa <= pb && pa <= pc)
- predLine[i] = left + (Guchar)c;
- else if (pb <= pc)
- predLine[i] = up + (Guchar)c;
- else
- predLine[i] = upLeft + (Guchar)c;
- break;
- case 10: // PNG none
- default: // no predictor or TIFF predictor
- predLine[i] = (Guchar)c;
- break;
- }
- }
-
- // apply TIFF (component) predictor
- if (predictor == 2) {
- if (nBits == 1) {
- inBuf = predLine[pixBytes - 1];
- for (i = pixBytes; i < rowBytes; i += 8) {
- // 1-bit add is just xor
- inBuf = (inBuf << 8) | predLine[i];
- predLine[i] ^= inBuf >> nComps;
- }
- } else if (nBits == 8) {
- for (i = pixBytes; i < rowBytes; ++i) {
- predLine[i] += predLine[i - nComps];
- }
- } else {
- memset(upLeftBuf, 0, nComps + 1);
- bitMask = (1 << nBits) - 1;
- inBuf = outBuf = 0;
- inBits = outBits = 0;
- j = k = pixBytes;
- for (i = 0; i < width; ++i) {
- for (kk = 0; kk < nComps; ++kk) {
- if (inBits < nBits) {
- inBuf = (inBuf << 8) | (predLine[j++] & 0xff);
- inBits += 8;
- }
- upLeftBuf[kk] = (upLeftBuf[kk] +
- (inBuf >> (inBits - nBits))) & bitMask;
- inBits -= nBits;
- outBuf = (outBuf << nBits) | upLeftBuf[kk];
- outBits += nBits;
- if (outBits >= 8) {
- predLine[k++] = (Guchar)(outBuf >> (outBits - 8));
- outBits -= 8;
- }
- }
- }
- if (outBits > 0) {
- predLine[k++] = (Guchar)((outBuf << (8 - outBits)) +
- (inBuf & ((1 << (8 - outBits)) - 1)));
- }
- }
- }
-
- // reset to start of line
- predIdx = pixBytes;
-
- return gTrue;
-}
-
-//------------------------------------------------------------------------
-// FileStream
-//------------------------------------------------------------------------
-
-FileStream::FileStream(FILE *fA, Guint startA, GBool limitedA,
- Guint lengthA, Object *dictA):
- BaseStream(dictA) {
- f = fA;
- start = startA;
- limited = limitedA;
- length = lengthA;
- bufPtr = bufEnd = buf;
- bufPos = start;
- savePos = 0;
- saved = gFalse;
-}
-
-FileStream::~FileStream() {
- close();
-}
-
-Stream *FileStream::makeSubStream(Guint startA, GBool limitedA,
- Guint lengthA, Object *dictA) {
- return new FileStream(f, startA, limitedA, lengthA, dictA);
-}
-
-void FileStream::reset() {
-#if HAVE_FSEEKO
- savePos = (Guint)ftello(f);
- fseeko(f, start, SEEK_SET);
-#elif HAVE_FSEEK64
- savePos = (Guint)ftell64(f);
- fseek64(f, start, SEEK_SET);
-#else
- savePos = (Guint)ftell(f);
- fseek(f, start, SEEK_SET);
-#endif
- saved = gTrue;
- bufPtr = bufEnd = buf;
- bufPos = start;
- if (decrypt)
- decrypt->reset();
-}
-
-void FileStream::close() {
- if (saved) {
-#if HAVE_FSEEKO
- fseeko(f, savePos, SEEK_SET);
-#elif HAVE_FSEEK64
- fseek64(f, savePos, SEEK_SET);
-#else
- fseek(f, savePos, SEEK_SET);
-#endif
- saved = gFalse;
- }
-}
-
-GBool FileStream::fillBuf() {
- int n;
- char *p;
-
- bufPos += bufEnd - buf;
- bufPtr = bufEnd = buf;
- if (limited && bufPos >= start + length) {
- return gFalse;
- }
- if (limited && bufPos + fileStreamBufSize > start + length) {
- n = start + length - bufPos;
- } else {
- n = fileStreamBufSize;
- }
- n = fread(buf, 1, n, f);
- bufEnd = buf + n;
- if (bufPtr >= bufEnd) {
- return gFalse;
- }
- if (decrypt) {
- for (p = buf; p < bufEnd; ++p) {
- *p = (char)decrypt->decryptByte((Guchar)*p);
- }
- }
- return gTrue;
-}
-
-void FileStream::setPos(Guint pos, int dir) {
- Guint size;
-
- if (dir >= 0) {
-#if HAVE_FSEEKO
- fseeko(f, pos, SEEK_SET);
-#elif HAVE_FSEEK64
- fseek64(f, pos, SEEK_SET);
-#else
- fseek(f, pos, SEEK_SET);
-#endif
- bufPos = pos;
- } else {
-#if HAVE_FSEEKO
- fseeko(f, 0, SEEK_END);
- size = (Guint)ftello(f);
-#elif HAVE_FSEEK64
- fseek64(f, 0, SEEK_END);
- size = (Guint)ftell64(f);
-#else
- fseek(f, 0, SEEK_END);
- size = (Guint)ftell(f);
-#endif
- if (pos > size)
- pos = (Guint)size;
-#ifdef __CYGWIN32__
- //~ work around a bug in cygwin's implementation of fseek
- rewind(f);
-#endif
-#if HAVE_FSEEKO
- fseeko(f, -(int)pos, SEEK_END);
- bufPos = (Guint)ftello(f);
-#elif HAVE_FSEEK64
- fseek64(f, -(int)pos, SEEK_END);
- bufPos = (Guint)ftell64(f);
-#else
- fseek(f, -(int)pos, SEEK_END);
- bufPos = (Guint)ftell(f);
-#endif
- }
- bufPtr = bufEnd = buf;
-}
-
-void FileStream::moveStart(int delta) {
- start += delta;
- bufPtr = bufEnd = buf;
- bufPos = start;
-}
-
-//------------------------------------------------------------------------
-// MemStream
-//------------------------------------------------------------------------
-
-MemStream::MemStream(char *bufA, Guint startA, Guint lengthA, Object *dictA):
- BaseStream(dictA) {
- buf = bufA;
- start = startA;
- length = lengthA;
- bufEnd = buf + start + length;
- bufPtr = buf + start;
- needFree = gFalse;
-}
-
-MemStream::~MemStream() {
- if (needFree) {
- gfree(buf);
- }
-}
-
-Stream *MemStream::makeSubStream(Guint startA, GBool limited,
- Guint lengthA, Object *dictA) {
- MemStream *subStr;
- Guint newLength;
-
- if (!limited || startA + lengthA > start + length) {
- newLength = start + length - startA;
- } else {
- newLength = lengthA;
- }
- subStr = new MemStream(buf, startA, newLength, dictA);
- return subStr;
-}
-
-void MemStream::reset() {
- bufPtr = buf + start;
- if (decrypt) {
- decrypt->reset();
- }
-}
-
-void MemStream::close() {
-}
-
-void MemStream::setPos(Guint pos, int dir) {
- Guint i;
-
- if (dir >= 0) {
- i = pos;
- } else {
- i = start + length - pos;
- }
- if (i < start) {
- i = start;
- } else if (i > start + length) {
- i = start + length;
- }
- bufPtr = buf + i;
-}
-
-void MemStream::moveStart(int delta) {
- start += delta;
- length -= delta;
- bufPtr = buf + start;
-}
-
-void MemStream::doDecryption(Guchar *fileKey, int keyLength,
- int objNum, int objGen) {
- char *newBuf;
- char *p, *q;
-
- this->BaseStream::doDecryption(fileKey, keyLength, objNum, objGen);
- if (decrypt) {
- newBuf = (char *)gmalloc(length);
- for (p = buf + start, q = newBuf; p < bufEnd; ++p, ++q) {
- *q = (char)decrypt->decryptByte((Guchar)*p);
- }
- bufEnd = newBuf + length;
- bufPtr = newBuf + (bufPtr - (buf + start));
- start = 0;
- buf = newBuf;
- needFree = gTrue;
- }
-}
-
-//------------------------------------------------------------------------
-// EmbedStream
-//------------------------------------------------------------------------
-
-EmbedStream::EmbedStream(Stream *strA, Object *dictA,
- GBool limitedA, Guint lengthA):
- BaseStream(dictA) {
- str = strA;
- limited = limitedA;
- length = lengthA;
-}
-
-EmbedStream::~EmbedStream() {
-}
-
-Stream *EmbedStream::makeSubStream(Guint start, GBool limitedA,
- Guint lengthA, Object *dictA) {
- error(-1, "Internal: called makeSubStream() on EmbedStream");
- return NULL;
-}
-
-int EmbedStream::getChar() {
- if (limited && !length) {
- return EOF;
- }
- --length;
- return str->getChar();
-}
-
-int EmbedStream::lookChar() {
- if (limited && !length) {
- return EOF;
- }
- return str->lookChar();
-}
-
-void EmbedStream::setPos(Guint pos, int dir) {
- error(-1, "Internal: called setPos() on EmbedStream");
-}
-
-Guint EmbedStream::getStart() {
- error(-1, "Internal: called getStart() on EmbedStream");
- return 0;
-}
-
-void EmbedStream::moveStart(int delta) {
- error(-1, "Internal: called moveStart() on EmbedStream");
-}
-
-//------------------------------------------------------------------------
-// ASCIIHexStream
-//------------------------------------------------------------------------
-
-ASCIIHexStream::ASCIIHexStream(Stream *strA):
- FilterStream(strA) {
- buf = EOF;
- eof = gFalse;
-}
-
-ASCIIHexStream::~ASCIIHexStream() {
- delete str;
-}
-
-void ASCIIHexStream::reset() {
- str->reset();
- buf = EOF;
- eof = gFalse;
-}
-
-int ASCIIHexStream::lookChar() {
- int c1, c2, x;
-
- if (buf != EOF)
- return buf;
- if (eof) {
- buf = EOF;
- return EOF;
- }
- do {
- c1 = str->getChar();
- } while (isspace(c1));
- if (c1 == '>') {
- eof = gTrue;
- buf = EOF;
- return buf;
- }
- do {
- c2 = str->getChar();
- } while (isspace(c2));
- if (c2 == '>') {
- eof = gTrue;
- c2 = '0';
- }
- if (c1 >= '0' && c1 <= '9') {
- x = (c1 - '0') << 4;
- } else if (c1 >= 'A' && c1 <= 'F') {
- x = (c1 - 'A' + 10) << 4;
- } else if (c1 >= 'a' && c1 <= 'f') {
- x = (c1 - 'a' + 10) << 4;
- } else if (c1 == EOF) {
- eof = gTrue;
- x = 0;
- } else {
- error(getPos(), "Illegal character <%02x> in ASCIIHex stream", c1);
- x = 0;
- }
- if (c2 >= '0' && c2 <= '9') {
- x += c2 - '0';
- } else if (c2 >= 'A' && c2 <= 'F') {
- x += c2 - 'A' + 10;
- } else if (c2 >= 'a' && c2 <= 'f') {
- x += c2 - 'a' + 10;
- } else if (c2 == EOF) {
- eof = gTrue;
- x = 0;
- } else {
- error(getPos(), "Illegal character <%02x> in ASCIIHex stream", c2);
- }
- buf = x & 0xff;
- return buf;
-}
-
-GString *ASCIIHexStream::getPSFilter(int psLevel, char *indent) {
- GString *s;
-
- if (psLevel < 2) {
- return NULL;
- }
- if (!(s = str->getPSFilter(psLevel, indent))) {
- return NULL;
- }
- s->append(indent)->append("/ASCIIHexDecode filter\n");
- return s;
-}
-
-GBool ASCIIHexStream::isBinary(GBool last) {
- return str->isBinary(gFalse);
-}
-
-//------------------------------------------------------------------------
-// ASCII85Stream
-//------------------------------------------------------------------------
-
-ASCII85Stream::ASCII85Stream(Stream *strA):
- FilterStream(strA) {
- index = n = 0;
- eof = gFalse;
-}
-
-ASCII85Stream::~ASCII85Stream() {
- delete str;
-}
-
-void ASCII85Stream::reset() {
- str->reset();
- index = n = 0;
- eof = gFalse;
-}
-
-int ASCII85Stream::lookChar() {
- int k;
- Gulong t;
-
- if (index >= n) {
- if (eof)
- return EOF;
- index = 0;
- do {
- c[0] = str->getChar();
- } while (Lexer::isSpace(c[0]));
- if (c[0] == '~' || c[0] == EOF) {
- eof = gTrue;
- n = 0;
- return EOF;
- } else if (c[0] == 'z') {
- b[0] = b[1] = b[2] = b[3] = 0;
- n = 4;
- } else {
- for (k = 1; k < 5; ++k) {
- do {
- c[k] = str->getChar();
- } while (Lexer::isSpace(c[k]));
- if (c[k] == '~' || c[k] == EOF)
- break;
- }
- n = k - 1;
- if (k < 5 && (c[k] == '~' || c[k] == EOF)) {
- for (++k; k < 5; ++k)
- c[k] = 0x21 + 84;
- eof = gTrue;
- }
- t = 0;
- for (k = 0; k < 5; ++k)
- t = t * 85 + (c[k] - 0x21);
- for (k = 3; k >= 0; --k) {
- b[k] = (int)(t & 0xff);
- t >>= 8;
- }
- }
- }
- return b[index];
-}
-
-GString *ASCII85Stream::getPSFilter(int psLevel, char *indent) {
- GString *s;
-
- if (psLevel < 2) {
- return NULL;
- }
- if (!(s = str->getPSFilter(psLevel, indent))) {
- return NULL;
- }
- s->append(indent)->append("/ASCII85Decode filter\n");
- return s;
-}
-
-GBool ASCII85Stream::isBinary(GBool last) {
- return str->isBinary(gFalse);
-}
-
-//------------------------------------------------------------------------
-// LZWStream
-//------------------------------------------------------------------------
-
-LZWStream::LZWStream(Stream *strA, int predictor, int columns, int colors,
- int bits, int earlyA):
- FilterStream(strA) {
- if (predictor != 1) {
- pred = new StreamPredictor(this, predictor, columns, colors, bits);
- if (!pred->isOk()) {
- delete pred;
- pred = NULL;
- }
- } else {
- pred = NULL;
- }
- early = earlyA;
- eof = gFalse;
- inputBits = 0;
- clearTable();
-}
-
-LZWStream::~LZWStream() {
- if (pred) {
- delete pred;
- }
- delete str;
-}
-
-int LZWStream::getChar() {
- if (pred) {
- return pred->getChar();
- }
- if (eof) {
- return EOF;
- }
- if (seqIndex >= seqLength) {
- if (!processNextCode()) {
- return EOF;
- }
- }
- return seqBuf[seqIndex++];
-}
-
-int LZWStream::lookChar() {
- if (pred) {
- return pred->lookChar();
- }
- if (eof) {
- return EOF;
- }
- if (seqIndex >= seqLength) {
- if (!processNextCode()) {
- return EOF;
- }
- }
- return seqBuf[seqIndex];
-}
-
-int LZWStream::getRawChar() {
- if (eof) {
- return EOF;
- }
- if (seqIndex >= seqLength) {
- if (!processNextCode()) {
- return EOF;
- }
- }
- return seqBuf[seqIndex++];
-}
-
-void LZWStream::reset() {
- str->reset();
- eof = gFalse;
- inputBits = 0;
- clearTable();
-}
-
-GBool LZWStream::processNextCode() {
- int code;
- int nextLength;
- int i, j;
-
- // check for EOF
- if (eof) {
- return gFalse;
- }
-
- // check for eod and clear-table codes
- start:
- code = getCode();
- if (code == EOF || code == 257) {
- eof = gTrue;
- return gFalse;
- }
- if (code == 256) {
- clearTable();
- goto start;
- }
- if (nextCode >= 4097) {
- error(getPos(), "Bad LZW stream - expected clear-table code");
- clearTable();
- }
-
- // process the next code
- nextLength = seqLength + 1;
- if (code < 256) {
- seqBuf[0] = code;
- seqLength = 1;
- } else if (code < nextCode) {
- seqLength = table[code].length;
- for (i = seqLength - 1, j = code; i > 0; --i) {
- seqBuf[i] = table[j].tail;
- j = table[j].head;
- }
- seqBuf[0] = j;
- } else if (code == nextCode) {
- seqBuf[seqLength] = newChar;
- ++seqLength;
- } else {
- error(getPos(), "Bad LZW stream - unexpected code");
- eof = gTrue;
- return gFalse;
- }
- newChar = seqBuf[0];
- if (first) {
- first = gFalse;
- } else {
- table[nextCode].length = nextLength;
- table[nextCode].head = prevCode;
- table[nextCode].tail = newChar;
- ++nextCode;
- if (nextCode + early == 512)
- nextBits = 10;
- else if (nextCode + early == 1024)
- nextBits = 11;
- else if (nextCode + early == 2048)
- nextBits = 12;
- }
- prevCode = code;
-
- // reset buffer
- seqIndex = 0;
-
- return gTrue;
-}
-
-void LZWStream::clearTable() {
- nextCode = 258;
- nextBits = 9;
- seqIndex = seqLength = 0;
- first = gTrue;
-}
-
-int LZWStream::getCode() {
- int c;
- int code;
-
- while (inputBits < nextBits) {
- if ((c = str->getChar()) == EOF)
- return EOF;
- inputBuf = (inputBuf << 8) | (c & 0xff);
- inputBits += 8;
- }
- code = (inputBuf >> (inputBits - nextBits)) & ((1 << nextBits) - 1);
- inputBits -= nextBits;
- return code;
-}
-
-GString *LZWStream::getPSFilter(int psLevel, char *indent) {
- GString *s;
-
- if (psLevel < 2 || pred) {
- return NULL;
- }
- if (!(s = str->getPSFilter(psLevel, indent))) {
- return NULL;
- }
- s->append(indent)->append("<< ");
- if (!early) {
- s->append("/EarlyChange 0 ");
- }
- s->append(">> /LZWDecode filter\n");
- return s;
-}
-
-GBool LZWStream::isBinary(GBool last) {
- return str->isBinary(gTrue);
-}
-
-//------------------------------------------------------------------------
-// RunLengthStream
-//------------------------------------------------------------------------
-
-RunLengthStream::RunLengthStream(Stream *strA):
- FilterStream(strA) {
- bufPtr = bufEnd = buf;
- eof = gFalse;
-}
-
-RunLengthStream::~RunLengthStream() {
- delete str;
-}
-
-void RunLengthStream::reset() {
- str->reset();
- bufPtr = bufEnd = buf;
- eof = gFalse;
-}
-
-GString *RunLengthStream::getPSFilter(int psLevel, char *indent) {
- GString *s;
-
- if (psLevel < 2) {
- return NULL;
- }
- if (!(s = str->getPSFilter(psLevel, indent))) {
- return NULL;
- }
- s->append(indent)->append("/RunLengthDecode filter\n");
- return s;
-}
-
-GBool RunLengthStream::isBinary(GBool last) {
- return str->isBinary(gTrue);
-}
-
-GBool RunLengthStream::fillBuf() {
- int c;
- int n, i;
-
- if (eof)
- return gFalse;
- c = str->getChar();
- if (c == 0x80 || c == EOF) {
- eof = gTrue;
- return gFalse;
- }
- if (c < 0x80) {
- n = c + 1;
- for (i = 0; i < n; ++i)
- buf[i] = (char)str->getChar();
- } else {
- n = 0x101 - c;
- c = str->getChar();
- for (i = 0; i < n; ++i)
- buf[i] = (char)c;
- }
- bufPtr = buf;
- bufEnd = buf + n;
- return gTrue;
-}
-
-//------------------------------------------------------------------------
-// CCITTFaxStream
-//------------------------------------------------------------------------
-
-CCITTFaxStream::CCITTFaxStream(Stream *strA, int encodingA, GBool endOfLineA,
- GBool byteAlignA, int columnsA, int rowsA,
- GBool endOfBlockA, GBool blackA):
- FilterStream(strA) {
- encoding = encodingA;
- endOfLine = endOfLineA;
- byteAlign = byteAlignA;
- columns = columnsA;
- if (columns < 1) {
- columns = 1;
- }
- rows = rowsA;
- endOfBlock = endOfBlockA;
- black = blackA;
- refLine = (short *)gmallocn(columns + 4, sizeof(short));
- codingLine = (short *)gmallocn(columns + 3, sizeof(short));
-
- eof = gFalse;
- row = 0;
- nextLine2D = encoding < 0;
- inputBits = 0;
- codingLine[0] = 0;
- codingLine[1] = refLine[2] = columns;
- a0 = 1;
-
- buf = EOF;
-}
-
-CCITTFaxStream::~CCITTFaxStream() {
- delete str;
- gfree(refLine);
- gfree(codingLine);
-}
-
-void CCITTFaxStream::reset() {
- short code1;
-
- str->reset();
- eof = gFalse;
- row = 0;
- nextLine2D = encoding < 0;
- inputBits = 0;
- codingLine[0] = 0;
- codingLine[1] = refLine[2] = columns;
- a0 = 1;
- buf = EOF;
-
- // skip any initial zero bits and end-of-line marker, and get the 2D
- // encoding tag
- while ((code1 = lookBits(12)) == 0) {
- eatBits(1);
- }
- if (code1 == 0x001) {
- eatBits(12);
- }
- if (encoding > 0) {
- nextLine2D = !lookBits(1);
- eatBits(1);
- }
-}
-
-int CCITTFaxStream::lookChar() {
- short code1, code2, code3;
- int a0New;
- GBool err, gotEOL;
- int ret;
- int bits, i;
-
- // if at eof just return EOF
- if (eof && codingLine[a0] >= columns) {
- return EOF;
- }
-
- // read the next row
- err = gFalse;
- if (codingLine[a0] >= columns) {
-
- // 2-D encoding
- if (nextLine2D) {
- for (i = 0; codingLine[i] < columns; ++i)
- refLine[i] = codingLine[i];
- refLine[i] = refLine[i + 1] = columns;
- b1 = 1;
- a0New = codingLine[a0 = 0] = 0;
- do {
- code1 = getTwoDimCode();
- switch (code1) {
- case twoDimPass:
- if (refLine[b1] < columns) {
- a0New = refLine[b1 + 1];
- b1 += 2;
- }
- break;
- case twoDimHoriz:
- if ((a0 & 1) == 0) {
- code1 = code2 = 0;
- do {
- code1 += code3 = getWhiteCode();
- } while (code3 >= 64);
- do {
- code2 += code3 = getBlackCode();
- } while (code3 >= 64);
- } else {
- code1 = code2 = 0;
- do {
- code1 += code3 = getBlackCode();
- } while (code3 >= 64);
- do {
- code2 += code3 = getWhiteCode();
- } while (code3 >= 64);
- }
- if (code1 > 0 || code2 > 0) {
- codingLine[a0 + 1] = a0New + code1;
- ++a0;
- a0New = codingLine[a0 + 1] = codingLine[a0] + code2;
- ++a0;
- while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
- b1 += 2;
- }
- break;
- case twoDimVert0:
- a0New = codingLine[++a0] = refLine[b1];
- if (refLine[b1] < columns) {
- ++b1;
- while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
- b1 += 2;
- }
- break;
- case twoDimVertR1:
- a0New = codingLine[++a0] = refLine[b1] + 1;
- if (refLine[b1] < columns) {
- ++b1;
- while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
- b1 += 2;
- }
- break;
- case twoDimVertL1:
- if (a0 == 0 || refLine[b1] - 1 > a0New) {
- a0New = codingLine[++a0] = refLine[b1] - 1;
- --b1;
- while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
- b1 += 2;
- }
- break;
- case twoDimVertR2:
- a0New = codingLine[++a0] = refLine[b1] + 2;
- if (refLine[b1] < columns) {
- ++b1;
- while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
- b1 += 2;
- }
- break;
- case twoDimVertL2:
- if (a0 == 0 || refLine[b1] - 2 > a0New) {
- a0New = codingLine[++a0] = refLine[b1] - 2;
- --b1;
- while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
- b1 += 2;
- }
- break;
- case twoDimVertR3:
- a0New = codingLine[++a0] = refLine[b1] + 3;
- if (refLine[b1] < columns) {
- ++b1;
- while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
- b1 += 2;
- }
- break;
- case twoDimVertL3:
- if (a0 == 0 || refLine[b1] - 3 > a0New) {
- a0New = codingLine[++a0] = refLine[b1] - 3;
- --b1;
- while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
- b1 += 2;
- }
- break;
- case EOF:
- eof = gTrue;
- codingLine[a0 = 0] = columns;
- return EOF;
- default:
- error(getPos(), "Bad 2D code %04x in CCITTFax stream", code1);
- err = gTrue;
- break;
- }
- } while (codingLine[a0] < columns);
-
- // 1-D encoding
- } else {
- codingLine[a0 = 0] = 0;
- while (1) {
- code1 = 0;
- do {
- code1 += code3 = getWhiteCode();
- } while (code3 >= 64);
- codingLine[a0+1] = codingLine[a0] + code1;
- ++a0;
- if (codingLine[a0] >= columns)
- break;
- code2 = 0;
- do {
- code2 += code3 = getBlackCode();
- } while (code3 >= 64);
- codingLine[a0+1] = codingLine[a0] + code2;
- ++a0;
- if (codingLine[a0] >= columns)
- break;
- }
- }
-
- if (codingLine[a0] != columns) {
- error(getPos(), "CCITTFax row is wrong length (%d)", codingLine[a0]);
- // force the row to be the correct length
- while (codingLine[a0] > columns) {
- --a0;
- }
- codingLine[++a0] = columns;
- err = gTrue;
- }
-
- // byte-align the row
- if (byteAlign) {
- inputBits &= ~7;
- }
-
- // check for end-of-line marker, skipping over any extra zero bits
- gotEOL = gFalse;
- if (!endOfBlock && row == rows - 1) {
- eof = gTrue;
- } else {
- code1 = lookBits(12);
- while (code1 == 0) {
- eatBits(1);
- code1 = lookBits(12);
- }
- if (code1 == 0x001) {
- eatBits(12);
- gotEOL = gTrue;
- } else if (code1 == EOF) {
- eof = gTrue;
- }
- }
-
- // get 2D encoding tag
- if (!eof && encoding > 0) {
- nextLine2D = !lookBits(1);
- eatBits(1);
- }
-
- // check for end-of-block marker
- if (endOfBlock && gotEOL) {
- code1 = lookBits(12);
- if (code1 == 0x001) {
- eatBits(12);
- if (encoding > 0) {
- lookBits(1);
- eatBits(1);
- }
- if (encoding >= 0) {
- for (i = 0; i < 4; ++i) {
- code1 = lookBits(12);
- if (code1 != 0x001) {
- error(getPos(), "Bad RTC code in CCITTFax stream");
- }
- eatBits(12);
- if (encoding > 0) {
- lookBits(1);
- eatBits(1);
- }
- }
- }
- eof = gTrue;
- }
-
- // look for an end-of-line marker after an error -- we only do
- // this if we know the stream contains end-of-line markers because
- // the "just plow on" technique tends to work better otherwise
- } else if (err && endOfLine) {
- do {
- if (code1 == EOF) {
- eof = gTrue;
- return EOF;
- }
- eatBits(1);
- code1 = lookBits(13);
- } while ((code1 >> 1) != 0x001);
- eatBits(12);
- if (encoding > 0) {
- eatBits(1);
- nextLine2D = !(code1 & 1);
- }
- }
-
- a0 = 0;
- outputBits = codingLine[1] - codingLine[0];
- if (outputBits == 0) {
- a0 = 1;
- outputBits = codingLine[2] - codingLine[1];
- }
-
- ++row;
- }
-
- // get a byte
- if (outputBits >= 8) {
- ret = ((a0 & 1) == 0) ? 0xff : 0x00;
- if ((outputBits -= 8) == 0) {
- ++a0;
- if (codingLine[a0] < columns) {
- outputBits = codingLine[a0 + 1] - codingLine[a0];
- }
- }
- } else {
- bits = 8;
- ret = 0;
- do {
- if (outputBits > bits) {
- i = bits;
- bits = 0;
- if ((a0 & 1) == 0) {
- ret |= 0xff >> (8 - i);
- }
- outputBits -= i;
- } else {
- i = outputBits;
- bits -= outputBits;
- if ((a0 & 1) == 0) {
- ret |= (0xff >> (8 - i)) << bits;
- }
- outputBits = 0;
- ++a0;
- if (codingLine[a0] < columns) {
- outputBits = codingLine[a0 + 1] - codingLine[a0];
- }
- }
- } while (bits > 0 && codingLine[a0] < columns);
- }
- buf = black ? (ret ^ 0xff) : ret;
- return buf;
-}
-
-short CCITTFaxStream::getTwoDimCode() {
- short code;
- CCITTCode *p;
- int n;
-
- code = 0; // make gcc happy
- if (endOfBlock) {
- code = lookBits(7);
- p = &twoDimTab1[code];
- if (p->bits > 0) {
- eatBits(p->bits);
- return p->n;
- }
- } else {
- for (n = 1; n <= 7; ++n) {
- code = lookBits(n);
- if (n < 7) {
- code <<= 7 - n;
- }
- p = &twoDimTab1[code];
- if (p->bits == n) {
- eatBits(n);
- return p->n;
- }
- }
- }
- error(getPos(), "Bad two dim code (%04x) in CCITTFax stream", code);
- return EOF;
-}
-
-short CCITTFaxStream::getWhiteCode() {
- short code;
- CCITTCode *p;
- int n;
-
- code = 0; // make gcc happy
- if (endOfBlock) {
- code = lookBits(12);
- if ((code >> 5) == 0) {
- p = &whiteTab1[code];
- } else {
- p = &whiteTab2[code >> 3];
- }
- if (p->bits > 0) {
- eatBits(p->bits);
- return p->n;
- }
- } else {
- for (n = 1; n <= 9; ++n) {
- code = lookBits(n);
- if (n < 9) {
- code <<= 9 - n;
- }
- p = &whiteTab2[code];
- if (p->bits == n) {
- eatBits(n);
- return p->n;
- }
- }
- for (n = 11; n <= 12; ++n) {
- code = lookBits(n);
- if (n < 12) {
- code <<= 12 - n;
- }
- p = &whiteTab1[code];
- if (p->bits == n) {
- eatBits(n);
- return p->n;
- }
- }
- }
- error(getPos(), "Bad white code (%04x) in CCITTFax stream", code);
- // eat a bit and return a positive number so that the caller doesn't
- // go into an infinite loop
- eatBits(1);
- return 1;
-}
-
-short CCITTFaxStream::getBlackCode() {
- short code;
- CCITTCode *p;
- int n;
-
- code = 0; // make gcc happy
- if (endOfBlock) {
- code = lookBits(13);
- if ((code >> 7) == 0) {
- p = &blackTab1[code];
- } else if ((code >> 9) == 0) {
- p = &blackTab2[(code >> 1) - 64];
- } else {
- p = &blackTab3[code >> 7];
- }
- if (p->bits > 0) {
- eatBits(p->bits);
- return p->n;
- }
- } else {
- for (n = 2; n <= 6; ++n) {
- code = lookBits(n);
- if (n < 6) {
- code <<= 6 - n;
- }
- p = &blackTab3[code];
- if (p->bits == n) {
- eatBits(n);
- return p->n;
- }
- }
- for (n = 7; n <= 12; ++n) {
- code = lookBits(n);
- if (n < 12) {
- code <<= 12 - n;
- }
- if (code >= 64) {
- p = &blackTab2[code - 64];
- if (p->bits == n) {
- eatBits(n);
- return p->n;
- }
- }
- }
- for (n = 10; n <= 13; ++n) {
- code = lookBits(n);
- if (n < 13) {
- code <<= 13 - n;
- }
- p = &blackTab1[code];
- if (p->bits == n) {
- eatBits(n);
- return p->n;
- }
- }
- }
- error(getPos(), "Bad black code (%04x) in CCITTFax stream", code);
- // eat a bit and return a positive number so that the caller doesn't
- // go into an infinite loop
- eatBits(1);
- return 1;
-}
-
-short CCITTFaxStream::lookBits(int n) {
- int c;
-
- while (inputBits < n) {
- if ((c = str->getChar()) == EOF) {
- if (inputBits == 0) {
- return EOF;
- }
- // near the end of the stream, the caller may ask for more bits
- // than are available, but there may still be a valid code in
- // however many bits are available -- we need to return correct
- // data in this case
- return (inputBuf << (n - inputBits)) & (0xffff >> (16 - n));
- }
- inputBuf = (inputBuf << 8) + c;
- inputBits += 8;
- }
- return (inputBuf >> (inputBits - n)) & (0xffff >> (16 - n));
-}
-
-GString *CCITTFaxStream::getPSFilter(int psLevel, char *indent) {
- GString *s;
- char s1[50];
-
- if (psLevel < 2) {
- return NULL;
- }
- if (!(s = str->getPSFilter(psLevel, indent))) {
- return NULL;
- }
- s->append(indent)->append("<< ");
- if (encoding != 0) {
- sprintf(s1, "/K %d ", encoding);
- s->append(s1);
- }
- if (endOfLine) {
- s->append("/EndOfLine true ");
- }
- if (byteAlign) {
- s->append("/EncodedByteAlign true ");
- }
- sprintf(s1, "/Columns %d ", columns);
- s->append(s1);
- if (rows != 0) {
- sprintf(s1, "/Rows %d ", rows);
- s->append(s1);
- }
- if (!endOfBlock) {
- s->append("/EndOfBlock false ");
- }
- if (black) {
- s->append("/BlackIs1 true ");
- }
- s->append(">> /CCITTFaxDecode filter\n");
- return s;
-}
-
-GBool CCITTFaxStream::isBinary(GBool last) {
- return str->isBinary(gTrue);
-}
-
-//------------------------------------------------------------------------
-// DCTStream
-//------------------------------------------------------------------------
-
-// IDCT constants (20.12 fixed point format)
-#define dctCos1 4017 // cos(pi/16)
-#define dctSin1 799 // sin(pi/16)
-#define dctCos3 3406 // cos(3*pi/16)
-#define dctSin3 2276 // sin(3*pi/16)
-#define dctCos6 1567 // cos(6*pi/16)
-#define dctSin6 3784 // sin(6*pi/16)
-#define dctSqrt2 5793 // sqrt(2)
-#define dctSqrt1d2 2896 // sqrt(2) / 2
-
-// color conversion parameters (16.16 fixed point format)
-#define dctCrToR 91881 // 1.4020
-#define dctCbToG -22553 // -0.3441363
-#define dctCrToG -46802 // -0.71413636
-#define dctCbToB 116130 // 1.772
-
-// clip [-256,511] --> [0,255]
-#define dctClipOffset 256
-static Guchar dctClip[768];
-static int dctClipInit = 0;
-
-// zig zag decode map
-static int dctZigZag[64] = {
- 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
-};
-
-DCTStream::DCTStream(Stream *strA):
- FilterStream(strA) {
- int i, j;
-
- progressive = interleaved = gFalse;
- width = height = 0;
- mcuWidth = mcuHeight = 0;
- numComps = 0;
- comp = 0;
- x = y = dy = 0;
- for (i = 0; i < 4; ++i) {
- for (j = 0; j < 32; ++j) {
- rowBuf[i][j] = NULL;
- }
- frameBuf[i] = NULL;
- }
-
- if (!dctClipInit) {
- for (i = -256; i < 0; ++i)
- dctClip[dctClipOffset + i] = 0;
- for (i = 0; i < 256; ++i)
- dctClip[dctClipOffset + i] = i;
- for (i = 256; i < 512; ++i)
- dctClip[dctClipOffset + i] = 255;
- dctClipInit = 1;
- }
-}
-
-DCTStream::~DCTStream() {
- int i, j;
-
- delete str;
- if (progressive || !interleaved) {
- for (i = 0; i < numComps; ++i) {
- gfree(frameBuf[i]);
- }
- } else {
- for (i = 0; i < numComps; ++i) {
- for (j = 0; j < mcuHeight; ++j) {
- gfree(rowBuf[i][j]);
- }
- }
- }
-}
-
-void DCTStream::reset() {
- int i, j;
-
- str->reset();
-
- progressive = interleaved = gFalse;
- width = height = 0;
- numComps = 0;
- numQuantTables = 0;
- numDCHuffTables = 0;
- numACHuffTables = 0;
- colorXform = 0;
- gotJFIFMarker = gFalse;
- gotAdobeMarker = gFalse;
- restartInterval = 0;
-
- if (!readHeader()) {
- y = height;
- return;
- }
-
- // compute MCU size
- if (numComps == 1) {
- compInfo[0].hSample = compInfo[0].vSample = 1;
- }
- mcuWidth = compInfo[0].hSample;
- mcuHeight = compInfo[0].vSample;
- for (i = 1; i < numComps; ++i) {
- if (compInfo[i].hSample > mcuWidth) {
- mcuWidth = compInfo[i].hSample;
- }
- if (compInfo[i].vSample > mcuHeight) {
- mcuHeight = compInfo[i].vSample;
- }
- }
- mcuWidth *= 8;
- mcuHeight *= 8;
-
- // figure out color transform
- if (!gotAdobeMarker && numComps == 3) {
- if (gotJFIFMarker) {
- colorXform = 1;
- } else if (compInfo[0].id == 82 && compInfo[1].id == 71 &&
- compInfo[2].id == 66) { // ASCII "RGB"
- colorXform = 0;
- } else {
- colorXform = 1;
- }
- }
-
- if (progressive || !interleaved) {
-
- // allocate a buffer for the whole image
- bufWidth = ((width + mcuWidth - 1) / mcuWidth) * mcuWidth;
- bufHeight = ((height + mcuHeight - 1) / mcuHeight) * mcuHeight;
- for (i = 0; i < numComps; ++i) {
- frameBuf[i] = (int *)gmallocn(bufWidth * bufHeight, sizeof(int));
- memset(frameBuf[i], 0, bufWidth * bufHeight * sizeof(int));
- }
-
- // read the image data
- do {
- restartMarker = 0xd0;
- restart();
- readScan();
- } while (readHeader());
-
- // decode
- decodeImage();
-
- // initialize counters
- comp = 0;
- x = 0;
- y = 0;
-
- } else {
-
- // allocate a buffer for one row of MCUs
- bufWidth = ((width + mcuWidth - 1) / mcuWidth) * mcuWidth;
- for (i = 0; i < numComps; ++i) {
- for (j = 0; j < mcuHeight; ++j) {
- rowBuf[i][j] = (Guchar *)gmallocn(bufWidth, sizeof(Guchar));
- }
- }
-
- // initialize counters
- comp = 0;
- x = 0;
- y = 0;
- dy = mcuHeight;
-
- restartMarker = 0xd0;
- restart();
- }
-}
-
-int DCTStream::getChar() {
- int c;
-
- if (y >= height) {
- return EOF;
- }
- if (progressive || !interleaved) {
- c = frameBuf[comp][y * bufWidth + x];
- if (++comp == numComps) {
- comp = 0;
- if (++x == width) {
- x = 0;
- ++y;
- }
- }
- } else {
- if (dy >= mcuHeight) {
- if (!readMCURow()) {
- y = height;
- return EOF;
- }
- comp = 0;
- x = 0;
- dy = 0;
- }
- c = rowBuf[comp][dy][x];
- if (++comp == numComps) {
- comp = 0;
- if (++x == width) {
- x = 0;
- ++y;
- ++dy;
- if (y == height) {
- readTrailer();
- }
- }
- }
- }
- return c;
-}
-
-int DCTStream::lookChar() {
- if (y >= height) {
- return EOF;
- }
- if (progressive || !interleaved) {
- return frameBuf[comp][y * bufWidth + x];
- } else {
- if (dy >= mcuHeight) {
- if (!readMCURow()) {
- y = height;
- return EOF;
- }
- comp = 0;
- x = 0;
- dy = 0;
- }
- return rowBuf[comp][dy][x];
- }
-}
-
-void DCTStream::restart() {
- int i;
-
- inputBits = 0;
- restartCtr = restartInterval;
- for (i = 0; i < numComps; ++i) {
- compInfo[i].prevDC = 0;
- }
- eobRun = 0;
-}
-
-// Read one row of MCUs from a sequential JPEG stream.
-GBool DCTStream::readMCURow() {
- int data1[64];
- Guchar data2[64];
- Guchar *p1, *p2;
- int pY, pCb, pCr, pR, pG, pB;
- int h, v, horiz, vert, hSub, vSub;
- int x1, x2, y2, x3, y3, x4, y4, x5, y5, cc, i;
- int c;
-
- for (x1 = 0; x1 < width; x1 += mcuWidth) {
-
- // deal with restart marker
- if (restartInterval > 0 && restartCtr == 0) {
- c = readMarker();
- if (c != restartMarker) {
- error(getPos(), "Bad DCT data: incorrect restart marker");
- return gFalse;
- }
- if (++restartMarker == 0xd8)
- restartMarker = 0xd0;
- restart();
- }
-
- // read one MCU
- for (cc = 0; cc < numComps; ++cc) {
- h = compInfo[cc].hSample;
- v = compInfo[cc].vSample;
- horiz = mcuWidth / h;
- vert = mcuHeight / v;
- hSub = horiz / 8;
- vSub = vert / 8;
- for (y2 = 0; y2 < mcuHeight; y2 += vert) {
- for (x2 = 0; x2 < mcuWidth; x2 += horiz) {
- if (!readDataUnit(&dcHuffTables[scanInfo.dcHuffTable[cc]],
- &acHuffTables[scanInfo.acHuffTable[cc]],
- &compInfo[cc].prevDC,
- data1)) {
- return gFalse;
- }
- transformDataUnit(quantTables[compInfo[cc].quantTable],
- data1, data2);
- if (hSub == 1 && vSub == 1) {
- for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
- p1 = &rowBuf[cc][y2+y3][x1+x2];
- p1[0] = data2[i];
- p1[1] = data2[i+1];
- p1[2] = data2[i+2];
- p1[3] = data2[i+3];
- p1[4] = data2[i+4];
- p1[5] = data2[i+5];
- p1[6] = data2[i+6];
- p1[7] = data2[i+7];
- }
- } else if (hSub == 2 && vSub == 2) {
- for (y3 = 0, i = 0; y3 < 16; y3 += 2, i += 8) {
- p1 = &rowBuf[cc][y2+y3][x1+x2];
- p2 = &rowBuf[cc][y2+y3+1][x1+x2];
- p1[0] = p1[1] = p2[0] = p2[1] = data2[i];
- p1[2] = p1[3] = p2[2] = p2[3] = data2[i+1];
- p1[4] = p1[5] = p2[4] = p2[5] = data2[i+2];
- p1[6] = p1[7] = p2[6] = p2[7] = data2[i+3];
- p1[8] = p1[9] = p2[8] = p2[9] = data2[i+4];
- p1[10] = p1[11] = p2[10] = p2[11] = data2[i+5];
- p1[12] = p1[13] = p2[12] = p2[13] = data2[i+6];
- p1[14] = p1[15] = p2[14] = p2[15] = data2[i+7];
- }
- } else {
- i = 0;
- for (y3 = 0, y4 = 0; y3 < 8; ++y3, y4 += vSub) {
- for (x3 = 0, x4 = 0; x3 < 8; ++x3, x4 += hSub) {
- for (y5 = 0; y5 < vSub; ++y5)
- for (x5 = 0; x5 < hSub; ++x5)
- rowBuf[cc][y2+y4+y5][x1+x2+x4+x5] = data2[i];
- ++i;
- }
- }
- }
- }
- }
- }
- --restartCtr;
-
- // color space conversion
- if (colorXform) {
- // convert YCbCr to RGB
- if (numComps == 3) {
- for (y2 = 0; y2 < mcuHeight; ++y2) {
- for (x2 = 0; x2 < mcuWidth; ++x2) {
- pY = rowBuf[0][y2][x1+x2];
- pCb = rowBuf[1][y2][x1+x2] - 128;
- pCr = rowBuf[2][y2][x1+x2] - 128;
- pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16;
- rowBuf[0][y2][x1+x2] = dctClip[dctClipOffset + pR];
- pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr + 32768) >> 16;
- rowBuf[1][y2][x1+x2] = dctClip[dctClipOffset + pG];
- pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16;
- rowBuf[2][y2][x1+x2] = dctClip[dctClipOffset + pB];
- }
- }
- // convert YCbCrK to CMYK (K is passed through unchanged)
- } else if (numComps == 4) {
- for (y2 = 0; y2 < mcuHeight; ++y2) {
- for (x2 = 0; x2 < mcuWidth; ++x2) {
- pY = rowBuf[0][y2][x1+x2];
- pCb = rowBuf[1][y2][x1+x2] - 128;
- pCr = rowBuf[2][y2][x1+x2] - 128;
- pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16;
- rowBuf[0][y2][x1+x2] = 255 - dctClip[dctClipOffset + pR];
- pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr + 32768) >> 16;
- rowBuf[1][y2][x1+x2] = 255 - dctClip[dctClipOffset + pG];
- pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16;
- rowBuf[2][y2][x1+x2] = 255 - dctClip[dctClipOffset + pB];
- }
- }
- }
- }
- }
- return gTrue;
-}
-
-// Read one scan from a progressive or non-interleaved JPEG stream.
-void DCTStream::readScan() {
- int data[64];
- int x1, y1, dx1, dy1, x2, y2, y3, cc, i;
- int h, v, horiz, vert, vSub;
- int *p1;
- int c;
-
- if (scanInfo.numComps == 1) {
- for (cc = 0; cc < numComps; ++cc) {
- if (scanInfo.comp[cc]) {
- break;
- }
- }
- dx1 = mcuWidth / compInfo[cc].hSample;
- dy1 = mcuHeight / compInfo[cc].vSample;
- } else {
- dx1 = mcuWidth;
- dy1 = mcuHeight;
- }
-
- for (y1 = 0; y1 < height; y1 += dy1) {
- for (x1 = 0; x1 < width; x1 += dx1) {
-
- // deal with restart marker
- if (restartInterval > 0 && restartCtr == 0) {
- c = readMarker();
- if (c != restartMarker) {
- error(getPos(), "Bad DCT data: incorrect restart marker");
- return;
- }
- if (++restartMarker == 0xd8) {
- restartMarker = 0xd0;
- }
- restart();
- }
-
- // read one MCU
- for (cc = 0; cc < numComps; ++cc) {
- if (!scanInfo.comp[cc]) {
- continue;
- }
-
- h = compInfo[cc].hSample;
- v = compInfo[cc].vSample;
- horiz = mcuWidth / h;
- vert = mcuHeight / v;
- vSub = vert / 8;
- for (y2 = 0; y2 < dy1; y2 += vert) {
- for (x2 = 0; x2 < dx1; x2 += horiz) {
-
- // pull out the current values
- p1 = &frameBuf[cc][(y1+y2) * bufWidth + (x1+x2)];
- for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
- data[i] = p1[0];
- data[i+1] = p1[1];
- data[i+2] = p1[2];
- data[i+3] = p1[3];
- data[i+4] = p1[4];
- data[i+5] = p1[5];
- data[i+6] = p1[6];
- data[i+7] = p1[7];
- p1 += bufWidth * vSub;
- }
-
- // read one data unit
- if (progressive) {
- if (!readProgressiveDataUnit(
- &dcHuffTables[scanInfo.dcHuffTable[cc]],
- &acHuffTables[scanInfo.acHuffTable[cc]],
- &compInfo[cc].prevDC,
- data)) {
- return;
- }
- } else {
- if (!readDataUnit(&dcHuffTables[scanInfo.dcHuffTable[cc]],
- &acHuffTables[scanInfo.acHuffTable[cc]],
- &compInfo[cc].prevDC,
- data)) {
- return;
- }
- }
-
- // add the data unit into frameBuf
- p1 = &frameBuf[cc][(y1+y2) * bufWidth + (x1+x2)];
- for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
- p1[0] = data[i];
- p1[1] = data[i+1];
- p1[2] = data[i+2];
- p1[3] = data[i+3];
- p1[4] = data[i+4];
- p1[5] = data[i+5];
- p1[6] = data[i+6];
- p1[7] = data[i+7];
- p1 += bufWidth * vSub;
- }
- }
- }
- }
- --restartCtr;
- }
- }
-}
-
-// Read one data unit from a sequential JPEG stream.
-GBool DCTStream::readDataUnit(DCTHuffTable *dcHuffTable,
- DCTHuffTable *acHuffTable,
- int *prevDC, int data[64]) {
- int run, size, amp;
- int c;
- int i, j;
-
- if ((size = readHuffSym(dcHuffTable)) == 9999) {
- return gFalse;
- }
- if (size > 0) {
- if ((amp = readAmp(size)) == 9999) {
- return gFalse;
- }
- } else {
- amp = 0;
- }
- data[0] = *prevDC += amp;
- for (i = 1; i < 64; ++i) {
- data[i] = 0;
- }
- i = 1;
- while (i < 64) {
- run = 0;
- while ((c = readHuffSym(acHuffTable)) == 0xf0 && run < 0x30) {
- run += 0x10;
- }
- if (c == 9999) {
- return gFalse;
- }
- if (c == 0x00) {
- break;
- } else {
- run += (c >> 4) & 0x0f;
- size = c & 0x0f;
- amp = readAmp(size);
- if (amp == 9999) {
- return gFalse;
- }
- i += run;
- if (i < 64) {
- j = dctZigZag[i++];
- data[j] = amp;
- }
- }
- }
- return gTrue;
-}
-
-// Read one data unit from a sequential JPEG stream.
-GBool DCTStream::readProgressiveDataUnit(DCTHuffTable *dcHuffTable,
- DCTHuffTable *acHuffTable,
- int *prevDC, int data[64]) {
- int run, size, amp, bit, c;
- int i, j, k;
-
- // get the DC coefficient
- i = scanInfo.firstCoeff;
- if (i == 0) {
- if (scanInfo.ah == 0) {
- if ((size = readHuffSym(dcHuffTable)) == 9999) {
- return gFalse;
- }
- if (size > 0) {
- if ((amp = readAmp(size)) == 9999) {
- return gFalse;
- }
- } else {
- amp = 0;
- }
- data[0] += (*prevDC += amp) << scanInfo.al;
- } else {
- if ((bit = readBit()) == 9999) {
- return gFalse;
- }
- data[0] += bit << scanInfo.al;
- }
- ++i;
- }
- if (scanInfo.lastCoeff == 0) {
- return gTrue;
- }
-
- // check for an EOB run
- if (eobRun > 0) {
- while (i <= scanInfo.lastCoeff) {
- j = dctZigZag[i++];
- if (data[j] != 0) {
- if ((bit = readBit()) == EOF) {
- return gFalse;
- }
- if (bit) {
- data[j] += 1 << scanInfo.al;
- }
- }
- }
- --eobRun;
- return gTrue;
- }
-
- // read the AC coefficients
- while (i <= scanInfo.lastCoeff) {
- if ((c = readHuffSym(acHuffTable)) == 9999) {
- return gFalse;
- }
-
- // ZRL
- if (c == 0xf0) {
- k = 0;
- while (k < 16) {
- j = dctZigZag[i++];
- if (data[j] == 0) {
- ++k;
- } else {
- if ((bit = readBit()) == EOF) {
- return gFalse;
- }
- if (bit) {
- data[j] += 1 << scanInfo.al;
- }
- }
- }
-
- // EOB run
- } else if ((c & 0x0f) == 0x00) {
- j = c >> 4;
- eobRun = 0;
- for (k = 0; k < j; ++k) {
- if ((bit = readBit()) == EOF) {
- return gFalse;
- }
- eobRun = (eobRun << 1) | bit;
- }
- eobRun += 1 << j;
- while (i <= scanInfo.lastCoeff) {
- j = dctZigZag[i++];
- if (data[j] != 0) {
- if ((bit = readBit()) == EOF) {
- return gFalse;
- }
- if (bit) {
- data[j] += 1 << scanInfo.al;
- }
- }
- }
- --eobRun;
- break;
-
- // zero run and one AC coefficient
- } else {
- run = (c >> 4) & 0x0f;
- size = c & 0x0f;
- if ((amp = readAmp(size)) == 9999) {
- return gFalse;
- }
- k = 0;
- do {
- j = dctZigZag[i++];
- while (data[j] != 0) {
- if ((bit = readBit()) == EOF) {
- return gFalse;
- }
- if (bit) {
- data[j] += 1 << scanInfo.al;
- }
- j = dctZigZag[i++];
- }
- ++k;
- } while (k <= run);
- data[j] = amp << scanInfo.al;
- }
- }
-
- return gTrue;
-}
-
-// Decode a progressive JPEG image.
-void DCTStream::decodeImage() {
- int dataIn[64];
- Guchar dataOut[64];
- Gushort *quantTable;
- int pY, pCb, pCr, pR, pG, pB;
- int x1, y1, x2, y2, x3, y3, x4, y4, x5, y5, cc, i;
- int h, v, horiz, vert, hSub, vSub;
- int *p0, *p1, *p2;
-
- for (y1 = 0; y1 < bufHeight; y1 += mcuHeight) {
- for (x1 = 0; x1 < bufWidth; x1 += mcuWidth) {
- for (cc = 0; cc < numComps; ++cc) {
- quantTable = quantTables[compInfo[cc].quantTable];
- h = compInfo[cc].hSample;
- v = compInfo[cc].vSample;
- horiz = mcuWidth / h;
- vert = mcuHeight / v;
- hSub = horiz / 8;
- vSub = vert / 8;
- for (y2 = 0; y2 < mcuHeight; y2 += vert) {
- for (x2 = 0; x2 < mcuWidth; x2 += horiz) {
-
- // pull out the coded data unit
- p1 = &frameBuf[cc][(y1+y2) * bufWidth + (x1+x2)];
- for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
- dataIn[i] = p1[0];
- dataIn[i+1] = p1[1];
- dataIn[i+2] = p1[2];
- dataIn[i+3] = p1[3];
- dataIn[i+4] = p1[4];
- dataIn[i+5] = p1[5];
- dataIn[i+6] = p1[6];
- dataIn[i+7] = p1[7];
- p1 += bufWidth * vSub;
- }
-
- // transform
- transformDataUnit(quantTable, dataIn, dataOut);
-
- // store back into frameBuf, doing replication for
- // subsampled components
- p1 = &frameBuf[cc][(y1+y2) * bufWidth + (x1+x2)];
- if (hSub == 1 && vSub == 1) {
- for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
- p1[0] = dataOut[i] & 0xff;
- p1[1] = dataOut[i+1] & 0xff;
- p1[2] = dataOut[i+2] & 0xff;
- p1[3] = dataOut[i+3] & 0xff;
- p1[4] = dataOut[i+4] & 0xff;
- p1[5] = dataOut[i+5] & 0xff;
- p1[6] = dataOut[i+6] & 0xff;
- p1[7] = dataOut[i+7] & 0xff;
- p1 += bufWidth;
- }
- } else if (hSub == 2 && vSub == 2) {
- p2 = p1 + bufWidth;
- for (y3 = 0, i = 0; y3 < 16; y3 += 2, i += 8) {
- p1[0] = p1[1] = p2[0] = p2[1] = dataOut[i] & 0xff;
- p1[2] = p1[3] = p2[2] = p2[3] = dataOut[i+1] & 0xff;
- p1[4] = p1[5] = p2[4] = p2[5] = dataOut[i+2] & 0xff;
- p1[6] = p1[7] = p2[6] = p2[7] = dataOut[i+3] & 0xff;
- p1[8] = p1[9] = p2[8] = p2[9] = dataOut[i+4] & 0xff;
- p1[10] = p1[11] = p2[10] = p2[11] = dataOut[i+5] & 0xff;
- p1[12] = p1[13] = p2[12] = p2[13] = dataOut[i+6] & 0xff;
- p1[14] = p1[15] = p2[14] = p2[15] = dataOut[i+7] & 0xff;
- p1 += bufWidth * 2;
- p2 += bufWidth * 2;
- }
- } else {
- i = 0;
- for (y3 = 0, y4 = 0; y3 < 8; ++y3, y4 += vSub) {
- for (x3 = 0, x4 = 0; x3 < 8; ++x3, x4 += hSub) {
- p2 = p1 + x4;
- for (y5 = 0; y5 < vSub; ++y5) {
- for (x5 = 0; x5 < hSub; ++x5) {
- p2[x5] = dataOut[i] & 0xff;
- }
- p2 += bufWidth;
- }
- ++i;
- }
- p1 += bufWidth * vSub;
- }
- }
- }
- }
- }
-
- // color space conversion
- if (colorXform) {
- // convert YCbCr to RGB
- if (numComps == 3) {
- for (y2 = 0; y2 < mcuHeight; ++y2) {
- p0 = &frameBuf[0][(y1+y2) * bufWidth + x1];
- p1 = &frameBuf[1][(y1+y2) * bufWidth + x1];
- p2 = &frameBuf[2][(y1+y2) * bufWidth + x1];
- for (x2 = 0; x2 < mcuWidth; ++x2) {
- pY = *p0;
- pCb = *p1 - 128;
- pCr = *p2 - 128;
- pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16;
- *p0++ = dctClip[dctClipOffset + pR];
- pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr +
- 32768) >> 16;
- *p1++ = dctClip[dctClipOffset + pG];
- pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16;
- *p2++ = dctClip[dctClipOffset + pB];
- }
- }
- // convert YCbCrK to CMYK (K is passed through unchanged)
- } else if (numComps == 4) {
- for (y2 = 0; y2 < mcuHeight; ++y2) {
- p0 = &frameBuf[0][(y1+y2) * bufWidth + x1];
- p1 = &frameBuf[1][(y1+y2) * bufWidth + x1];
- p2 = &frameBuf[2][(y1+y2) * bufWidth + x1];
- for (x2 = 0; x2 < mcuWidth; ++x2) {
- pY = *p0;
- pCb = *p1 - 128;
- pCr = *p2 - 128;
- pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16;
- *p0++ = 255 - dctClip[dctClipOffset + pR];
- pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr +
- 32768) >> 16;
- *p1++ = 255 - dctClip[dctClipOffset + pG];
- pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16;
- *p2++ = 255 - dctClip[dctClipOffset + pB];
- }
- }
- }
- }
- }
- }
-}
-
-// Transform one data unit -- this performs the dequantization and
-// IDCT steps. This IDCT algorithm is taken from:
-// Christoph Loeffler, Adriaan Ligtenberg, George S. Moschytz,
-// "Practical Fast 1-D DCT Algorithms with 11 Multiplications",
-// IEEE Intl. Conf. on Acoustics, Speech & Signal Processing, 1989,
-// 988-991.
-// The stage numbers mentioned in the comments refer to Figure 1 in this
-// paper.
-void DCTStream::transformDataUnit(Gushort *quantTable,
- int dataIn[64], Guchar dataOut[64]) {
- int v0, v1, v2, v3, v4, v5, v6, v7, t;
- int *p;
- int i;
-
- // dequant
- for (i = 0; i < 64; ++i) {
- dataIn[i] *= quantTable[i];
- }
-
- // inverse DCT on rows
- for (i = 0; i < 64; i += 8) {
- p = dataIn + i;
-
- // check for all-zero AC coefficients
- if (p[1] == 0 && p[2] == 0 && p[3] == 0 &&
- p[4] == 0 && p[5] == 0 && p[6] == 0 && p[7] == 0) {
- t = (dctSqrt2 * p[0] + 512) >> 10;
- p[0] = t;
- p[1] = t;
- p[2] = t;
- p[3] = t;
- p[4] = t;
- p[5] = t;
- p[6] = t;
- p[7] = t;
- continue;
- }
-
- // stage 4
- v0 = (dctSqrt2 * p[0] + 128) >> 8;
- v1 = (dctSqrt2 * p[4] + 128) >> 8;
- v2 = p[2];
- v3 = p[6];
- v4 = (dctSqrt1d2 * (p[1] - p[7]) + 128) >> 8;
- v7 = (dctSqrt1d2 * (p[1] + p[7]) + 128) >> 8;
- v5 = p[3] << 4;
- v6 = p[5] << 4;
-
- // stage 3
- t = (v0 - v1+ 1) >> 1;
- v0 = (v0 + v1 + 1) >> 1;
- v1 = t;
- t = (v2 * dctSin6 + v3 * dctCos6 + 128) >> 8;
- v2 = (v2 * dctCos6 - v3 * dctSin6 + 128) >> 8;
- v3 = t;
- t = (v4 - v6 + 1) >> 1;
- v4 = (v4 + v6 + 1) >> 1;
- v6 = t;
- t = (v7 + v5 + 1) >> 1;
- v5 = (v7 - v5 + 1) >> 1;
- v7 = t;
-
- // stage 2
- t = (v0 - v3 + 1) >> 1;
- v0 = (v0 + v3 + 1) >> 1;
- v3 = t;
- t = (v1 - v2 + 1) >> 1;
- v1 = (v1 + v2 + 1) >> 1;
- v2 = t;
- t = (v4 * dctSin3 + v7 * dctCos3 + 2048) >> 12;
- v4 = (v4 * dctCos3 - v7 * dctSin3 + 2048) >> 12;
- v7 = t;
- t = (v5 * dctSin1 + v6 * dctCos1 + 2048) >> 12;
- v5 = (v5 * dctCos1 - v6 * dctSin1 + 2048) >> 12;
- v6 = t;
-
- // stage 1
- p[0] = v0 + v7;
- p[7] = v0 - v7;
- p[1] = v1 + v6;
- p[6] = v1 - v6;
- p[2] = v2 + v5;
- p[5] = v2 - v5;
- p[3] = v3 + v4;
- p[4] = v3 - v4;
- }
-
- // inverse DCT on columns
- for (i = 0; i < 8; ++i) {
- p = dataIn + i;
-
- // check for all-zero AC coefficients
- if (p[1*8] == 0 && p[2*8] == 0 && p[3*8] == 0 &&
- p[4*8] == 0 && p[5*8] == 0 && p[6*8] == 0 && p[7*8] == 0) {
- t = (dctSqrt2 * dataIn[i+0] + 8192) >> 14;
- p[0*8] = t;
- p[1*8] = t;
- p[2*8] = t;
- p[3*8] = t;
- p[4*8] = t;
- p[5*8] = t;
- p[6*8] = t;
- p[7*8] = t;
- continue;
- }
-
- // stage 4
- v0 = (dctSqrt2 * p[0*8] + 2048) >> 12;
- v1 = (dctSqrt2 * p[4*8] + 2048) >> 12;
- v2 = p[2*8];
- v3 = p[6*8];
- v4 = (dctSqrt1d2 * (p[1*8] - p[7*8]) + 2048) >> 12;
- v7 = (dctSqrt1d2 * (p[1*8] + p[7*8]) + 2048) >> 12;
- v5 = p[3*8];
- v6 = p[5*8];
-
- // stage 3
- t = (v0 - v1 + 1) >> 1;
- v0 = (v0 + v1 + 1) >> 1;
- v1 = t;
- t = (v2 * dctSin6 + v3 * dctCos6 + 2048) >> 12;
- v2 = (v2 * dctCos6 - v3 * dctSin6 + 2048) >> 12;
- v3 = t;
- t = (v4 - v6 + 1) >> 1;
- v4 = (v4 + v6 + 1) >> 1;
- v6 = t;
- t = (v7 + v5 + 1) >> 1;
- v5 = (v7 - v5 + 1) >> 1;
- v7 = t;
-
- // stage 2
- t = (v0 - v3 + 1) >> 1;
- v0 = (v0 + v3 + 1) >> 1;
- v3 = t;
- t = (v1 - v2 + 1) >> 1;
- v1 = (v1 + v2 + 1) >> 1;
- v2 = t;
- t = (v4 * dctSin3 + v7 * dctCos3 + 2048) >> 12;
- v4 = (v4 * dctCos3 - v7 * dctSin3 + 2048) >> 12;
- v7 = t;
- t = (v5 * dctSin1 + v6 * dctCos1 + 2048) >> 12;
- v5 = (v5 * dctCos1 - v6 * dctSin1 + 2048) >> 12;
- v6 = t;
-
- // stage 1
- p[0*8] = v0 + v7;
- p[7*8] = v0 - v7;
- p[1*8] = v1 + v6;
- p[6*8] = v1 - v6;
- p[2*8] = v2 + v5;
- p[5*8] = v2 - v5;
- p[3*8] = v3 + v4;
- p[4*8] = v3 - v4;
- }
-
- // convert to 8-bit integers
- for (i = 0; i < 64; ++i) {
- dataOut[i] = dctClip[dctClipOffset + 128 + ((dataIn[i] + 8) >> 4)];
- }
-}
-
-int DCTStream::readHuffSym(DCTHuffTable *table) {
- Gushort code;
- int bit;
- int codeBits;
-
- code = 0;
- codeBits = 0;
- do {
- // add a bit to the code
- if ((bit = readBit()) == EOF)
- return 9999;
- code = (code << 1) + bit;
- ++codeBits;
-
- // look up code
- if (code - table->firstCode[codeBits] < table->numCodes[codeBits]) {
- code -= table->firstCode[codeBits];
- return table->sym[table->firstSym[codeBits] + code];
- }
- } while (codeBits < 16);
-
- error(getPos(), "Bad Huffman code in DCT stream");
- return 9999;
-}
-
-int DCTStream::readAmp(int size) {
- int amp, bit;
- int bits;
-
- amp = 0;
- for (bits = 0; bits < size; ++bits) {
- if ((bit = readBit()) == EOF)
- return 9999;
- amp = (amp << 1) + bit;
- }
- if (amp < (1 << (size - 1)))
- amp -= (1 << size) - 1;
- return amp;
-}
-
-int DCTStream::readBit() {
- int bit;
- int c, c2;
-
- if (inputBits == 0) {
- if ((c = str->getChar()) == EOF)
- return EOF;
- if (c == 0xff) {
- do {
- c2 = str->getChar();
- } while (c2 == 0xff);
- if (c2 != 0x00) {
- error(getPos(), "Bad DCT data: missing 00 after ff");
- return EOF;
- }
- }
- inputBuf = c;
- inputBits = 8;
- }
- bit = (inputBuf >> (inputBits - 1)) & 1;
- --inputBits;
- return bit;
-}
-
-GBool DCTStream::readHeader() {
- GBool doScan;
- int n;
- int c = 0;
- int i;
-
- // read headers
- doScan = gFalse;
- while (!doScan) {
- c = readMarker();
- switch (c) {
- case 0xc0: // SOF0 (sequential)
- case 0xc1: // SOF1 (extended sequential)
- if (!readBaselineSOF()) {
- return gFalse;
- }
- break;
- case 0xc2: // SOF2 (progressive)
- if (!readProgressiveSOF()) {
- return gFalse;
- }
- break;
- case 0xc4: // DHT
- if (!readHuffmanTables()) {
- return gFalse;
- }
- break;
- case 0xd8: // SOI
- break;
- case 0xd9: // EOI
- return gFalse;
- case 0xda: // SOS
- if (!readScanInfo()) {
- return gFalse;
- }
- doScan = gTrue;
- break;
- case 0xdb: // DQT
- if (!readQuantTables()) {
- return gFalse;
- }
- break;
- case 0xdd: // DRI
- if (!readRestartInterval()) {
- return gFalse;
- }
- break;
- case 0xe0: // APP0
- if (!readJFIFMarker()) {
- return gFalse;
- }
- break;
- case 0xee: // APP14
- if (!readAdobeMarker()) {
- return gFalse;
- }
- break;
- case EOF:
- error(getPos(), "Bad DCT header");
- return gFalse;
- default:
- // skip APPn / COM / etc.
- if (c >= 0xe0) {
- n = read16() - 2;
- for (i = 0; i < n; ++i) {
- str->getChar();
- }
- } else {
- error(getPos(), "Unknown DCT marker <%02x>", c);
- return gFalse;
- }
- break;
- }
- }
-
- return gTrue;
-}
-
-GBool DCTStream::readBaselineSOF() {
- int length;
- int prec;
- int i;
- int c;
-
- length = read16();
- prec = str->getChar();
- height = read16();
- width = read16();
- numComps = str->getChar();
- if (numComps <= 0 || numComps > 4) {
- error(getPos(), "Bad number of components in DCT stream", prec);
- return gFalse;
- }
- if (numComps <= 0 || numComps > 4) {
- error(getPos(), "Bad number of components in DCT stream", prec);
- return gFalse;
- }
- if (prec != 8) {
- error(getPos(), "Bad DCT precision %d", prec);
- return gFalse;
- }
- for (i = 0; i < numComps; ++i) {
- compInfo[i].id = str->getChar();
- c = str->getChar();
- compInfo[i].hSample = (c >> 4) & 0x0f;
- compInfo[i].vSample = c & 0x0f;
- compInfo[i].quantTable = str->getChar();
- }
- progressive = gFalse;
- return gTrue;
-}
-
-GBool DCTStream::readProgressiveSOF() {
- int length;
- int prec;
- int i;
- int c;
-
- length = read16();
- prec = str->getChar();
- height = read16();
- width = read16();
- numComps = str->getChar();
- if (prec != 8) {
- error(getPos(), "Bad DCT precision %d", prec);
- return gFalse;
- }
- for (i = 0; i < numComps; ++i) {
- compInfo[i].id = str->getChar();
- c = str->getChar();
- compInfo[i].hSample = (c >> 4) & 0x0f;
- compInfo[i].vSample = c & 0x0f;
- compInfo[i].quantTable = str->getChar();
- }
- progressive = gTrue;
- return gTrue;
-}
-
-GBool DCTStream::readScanInfo() {
- int length;
- int id, c;
- int i, j;
-
- length = read16() - 2;
- scanInfo.numComps = str->getChar();
- --length;
- if (length != 2 * scanInfo.numComps + 3) {
- error(getPos(), "Bad DCT scan info block");
- return gFalse;
- }
- interleaved = scanInfo.numComps == numComps;
- for (j = 0; j < numComps; ++j) {
- scanInfo.comp[j] = gFalse;
- }
- for (i = 0; i < scanInfo.numComps; ++i) {
- id = str->getChar();
- // some (broken) DCT streams reuse ID numbers, but at least they
- // keep the components in order, so we check compInfo[i] first to
- // work around the problem
- if (id == compInfo[i].id) {
- j = i;
- } else {
- for (j = 0; j < numComps; ++j) {
- if (id == compInfo[j].id) {
- break;
- }
- }
- if (j == numComps) {
- error(getPos(), "Bad DCT component ID in scan info block");
- return gFalse;
- }
- }
- scanInfo.comp[j] = gTrue;
- c = str->getChar();
- scanInfo.dcHuffTable[j] = (c >> 4) & 0x0f;
- scanInfo.acHuffTable[j] = c & 0x0f;
- }
- scanInfo.firstCoeff = str->getChar();
- scanInfo.lastCoeff = str->getChar();
- c = str->getChar();
- scanInfo.ah = (c >> 4) & 0x0f;
- scanInfo.al = c & 0x0f;
- return gTrue;
-}
-
-GBool DCTStream::readQuantTables() {
- int length, prec, i, index;
-
- length = read16() - 2;
- while (length > 0) {
- index = str->getChar();
- prec = (index >> 4) & 0x0f;
- index &= 0x0f;
- if (prec > 1 || index >= 4) {
- error(getPos(), "Bad DCT quantization table");
- return gFalse;
- }
- if (index == numQuantTables) {
- numQuantTables = index + 1;
- }
- for (i = 0; i < 64; ++i) {
- if (prec) {
- quantTables[index][dctZigZag[i]] = read16();
- } else {
- quantTables[index][dctZigZag[i]] = str->getChar();
- }
- }
- if (prec) {
- length -= 129;
- } else {
- length -= 65;
- }
- }
- return gTrue;
-}
-
-GBool DCTStream::readHuffmanTables() {
- DCTHuffTable *tbl;
- int length;
- int index;
- Gushort code;
- Guchar sym;
- int i;
- int c;
-
- length = read16() - 2;
- while (length > 0) {
- index = str->getChar();
- --length;
- if ((index & 0x0f) >= 4) {
- error(getPos(), "Bad DCT Huffman table");
- return gFalse;
- }
- if (index & 0x10) {
- index &= 0x0f;
- if (index >= numACHuffTables)
- numACHuffTables = index+1;
- tbl = &acHuffTables[index];
- } else {
- if (index >= numDCHuffTables)
- numDCHuffTables = index+1;
- tbl = &dcHuffTables[index];
- }
- sym = 0;
- code = 0;
- for (i = 1; i <= 16; ++i) {
- c = str->getChar();
- tbl->firstSym[i] = sym;
- tbl->firstCode[i] = code;
- tbl->numCodes[i] = c;
- sym += c;
- code = (code + c) << 1;
- }
- length -= 16;
- for (i = 0; i < sym; ++i)
- tbl->sym[i] = str->getChar();
- length -= sym;
- }
- return gTrue;
-}
-
-GBool DCTStream::readRestartInterval() {
- int length;
-
- length = read16();
- if (length != 4) {
- error(getPos(), "Bad DCT restart interval");
- return gFalse;
- }
- restartInterval = read16();
- return gTrue;
-}
-
-GBool DCTStream::readJFIFMarker() {
- int length, i;
- char buf[5];
- int c;
-
- length = read16();
- length -= 2;
- if (length >= 5) {
- for (i = 0; i < 5; ++i) {
- if ((c = str->getChar()) == EOF) {
- error(getPos(), "Bad DCT APP0 marker");
- return gFalse;
- }
- buf[i] = c;
- }
- length -= 5;
- if (!memcmp(buf, "JFIF\0", 5)) {
- gotJFIFMarker = gTrue;
- }
- }
- while (length > 0) {
- if (str->getChar() == EOF) {
- error(getPos(), "Bad DCT APP0 marker");
- return gFalse;
- }
- --length;
- }
- return gTrue;
-}
-
-GBool DCTStream::readAdobeMarker() {
- int length, i;
- char buf[12];
- int c;
-
- length = read16();
- if (length < 14) {
- goto err;
- }
- for (i = 0; i < 12; ++i) {
- if ((c = str->getChar()) == EOF) {
- goto err;
- }
- buf[i] = c;
- }
- if (strncmp(buf, "Adobe", 5)) {
- goto err;
- }
- colorXform = buf[11];
- gotAdobeMarker = gTrue;
- for (i = 14; i < length; ++i) {
- if (str->getChar() == EOF) {
- goto err;
- }
- }
- return gTrue;
-
- err:
- error(getPos(), "Bad DCT Adobe APP14 marker");
- return gFalse;
-}
-
-GBool DCTStream::readTrailer() {
- int c;
-
- c = readMarker();
- if (c != 0xd9) { // EOI
- error(getPos(), "Bad DCT trailer");
- return gFalse;
- }
- return gTrue;
-}
-
-int DCTStream::readMarker() {
- int c;
-
- do {
- do {
- c = str->getChar();
- } while (c != 0xff && c != EOF);
- do {
- c = str->getChar();
- } while (c == 0xff);
- } while (c == 0x00);
- return c;
-}
-
-int DCTStream::read16() {
- int c1, c2;
-
- if ((c1 = str->getChar()) == EOF)
- return EOF;
- if ((c2 = str->getChar()) == EOF)
- return EOF;
- return (c1 << 8) + c2;
-}
-
-GString *DCTStream::getPSFilter(int psLevel, char *indent) {
- GString *s;
-
- if (psLevel < 2) {
- return NULL;
- }
- if (!(s = str->getPSFilter(psLevel, indent))) {
- return NULL;
- }
- s->append(indent)->append("<< >> /DCTDecode filter\n");
- return s;
-}
-
-GBool DCTStream::isBinary(GBool last) {
- return str->isBinary(gTrue);
-}
-
-//------------------------------------------------------------------------
-// FlateStream
-//------------------------------------------------------------------------
-
-int FlateStream::codeLenCodeMap[flateMaxCodeLenCodes] = {
- 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
-};
-
-FlateDecode FlateStream::lengthDecode[flateMaxLitCodes-257] = {
- {0, 3},
- {0, 4},
- {0, 5},
- {0, 6},
- {0, 7},
- {0, 8},
- {0, 9},
- {0, 10},
- {1, 11},
- {1, 13},
- {1, 15},
- {1, 17},
- {2, 19},
- {2, 23},
- {2, 27},
- {2, 31},
- {3, 35},
- {3, 43},
- {3, 51},
- {3, 59},
- {4, 67},
- {4, 83},
- {4, 99},
- {4, 115},
- {5, 131},
- {5, 163},
- {5, 195},
- {5, 227},
- {0, 258},
- {0, 258},
- {0, 258}
-};
-
-FlateDecode FlateStream::distDecode[flateMaxDistCodes] = {
- { 0, 1},
- { 0, 2},
- { 0, 3},
- { 0, 4},
- { 1, 5},
- { 1, 7},
- { 2, 9},
- { 2, 13},
- { 3, 17},
- { 3, 25},
- { 4, 33},
- { 4, 49},
- { 5, 65},
- { 5, 97},
- { 6, 129},
- { 6, 193},
- { 7, 257},
- { 7, 385},
- { 8, 513},
- { 8, 769},
- { 9, 1025},
- { 9, 1537},
- {10, 2049},
- {10, 3073},
- {11, 4097},
- {11, 6145},
- {12, 8193},
- {12, 12289},
- {13, 16385},
- {13, 24577}
-};
-
-static FlateCode flateFixedLitCodeTabCodes[512] = {
- {7, 0x0100},
- {8, 0x0050},
- {8, 0x0010},
- {8, 0x0118},
- {7, 0x0110},
- {8, 0x0070},
- {8, 0x0030},
- {9, 0x00c0},
- {7, 0x0108},
- {8, 0x0060},
- {8, 0x0020},
- {9, 0x00a0},
- {8, 0x0000},
- {8, 0x0080},
- {8, 0x0040},
- {9, 0x00e0},
- {7, 0x0104},
- {8, 0x0058},
- {8, 0x0018},
- {9, 0x0090},
- {7, 0x0114},
- {8, 0x0078},
- {8, 0x0038},
- {9, 0x00d0},
- {7, 0x010c},
- {8, 0x0068},
- {8, 0x0028},
- {9, 0x00b0},
- {8, 0x0008},
- {8, 0x0088},
- {8, 0x0048},
- {9, 0x00f0},
- {7, 0x0102},
- {8, 0x0054},
- {8, 0x0014},
- {8, 0x011c},
- {7, 0x0112},
- {8, 0x0074},
- {8, 0x0034},
- {9, 0x00c8},
- {7, 0x010a},
- {8, 0x0064},
- {8, 0x0024},
- {9, 0x00a8},
- {8, 0x0004},
- {8, 0x0084},
- {8, 0x0044},
- {9, 0x00e8},
- {7, 0x0106},
- {8, 0x005c},
- {8, 0x001c},
- {9, 0x0098},
- {7, 0x0116},
- {8, 0x007c},
- {8, 0x003c},
- {9, 0x00d8},
- {7, 0x010e},
- {8, 0x006c},
- {8, 0x002c},
- {9, 0x00b8},
- {8, 0x000c},
- {8, 0x008c},
- {8, 0x004c},
- {9, 0x00f8},
- {7, 0x0101},
- {8, 0x0052},
- {8, 0x0012},
- {8, 0x011a},
- {7, 0x0111},
- {8, 0x0072},
- {8, 0x0032},
- {9, 0x00c4},
- {7, 0x0109},
- {8, 0x0062},
- {8, 0x0022},
- {9, 0x00a4},
- {8, 0x0002},
- {8, 0x0082},
- {8, 0x0042},
- {9, 0x00e4},
- {7, 0x0105},
- {8, 0x005a},
- {8, 0x001a},
- {9, 0x0094},
- {7, 0x0115},
- {8, 0x007a},
- {8, 0x003a},
- {9, 0x00d4},
- {7, 0x010d},
- {8, 0x006a},
- {8, 0x002a},
- {9, 0x00b4},
- {8, 0x000a},
- {8, 0x008a},
- {8, 0x004a},
- {9, 0x00f4},
- {7, 0x0103},
- {8, 0x0056},
- {8, 0x0016},
- {8, 0x011e},
- {7, 0x0113},
- {8, 0x0076},
- {8, 0x0036},
- {9, 0x00cc},
- {7, 0x010b},
- {8, 0x0066},
- {8, 0x0026},
- {9, 0x00ac},
- {8, 0x0006},
- {8, 0x0086},
- {8, 0x0046},
- {9, 0x00ec},
- {7, 0x0107},
- {8, 0x005e},
- {8, 0x001e},
- {9, 0x009c},
- {7, 0x0117},
- {8, 0x007e},
- {8, 0x003e},
- {9, 0x00dc},
- {7, 0x010f},
- {8, 0x006e},
- {8, 0x002e},
- {9, 0x00bc},
- {8, 0x000e},
- {8, 0x008e},
- {8, 0x004e},
- {9, 0x00fc},
- {7, 0x0100},
- {8, 0x0051},
- {8, 0x0011},
- {8, 0x0119},
- {7, 0x0110},
- {8, 0x0071},
- {8, 0x0031},
- {9, 0x00c2},
- {7, 0x0108},
- {8, 0x0061},
- {8, 0x0021},
- {9, 0x00a2},
- {8, 0x0001},
- {8, 0x0081},
- {8, 0x0041},
- {9, 0x00e2},
- {7, 0x0104},
- {8, 0x0059},
- {8, 0x0019},
- {9, 0x0092},
- {7, 0x0114},
- {8, 0x0079},
- {8, 0x0039},
- {9, 0x00d2},
- {7, 0x010c},
- {8, 0x0069},
- {8, 0x0029},
- {9, 0x00b2},
- {8, 0x0009},
- {8, 0x0089},
- {8, 0x0049},
- {9, 0x00f2},
- {7, 0x0102},
- {8, 0x0055},
- {8, 0x0015},
- {8, 0x011d},
- {7, 0x0112},
- {8, 0x0075},
- {8, 0x0035},
- {9, 0x00ca},
- {7, 0x010a},
- {8, 0x0065},
- {8, 0x0025},
- {9, 0x00aa},
- {8, 0x0005},
- {8, 0x0085},
- {8, 0x0045},
- {9, 0x00ea},
- {7, 0x0106},
- {8, 0x005d},
- {8, 0x001d},
- {9, 0x009a},
- {7, 0x0116},
- {8, 0x007d},
- {8, 0x003d},
- {9, 0x00da},
- {7, 0x010e},
- {8, 0x006d},
- {8, 0x002d},
- {9, 0x00ba},
- {8, 0x000d},
- {8, 0x008d},
- {8, 0x004d},
- {9, 0x00fa},
- {7, 0x0101},
- {8, 0x0053},
- {8, 0x0013},
- {8, 0x011b},
- {7, 0x0111},
- {8, 0x0073},
- {8, 0x0033},
- {9, 0x00c6},
- {7, 0x0109},
- {8, 0x0063},
- {8, 0x0023},
- {9, 0x00a6},
- {8, 0x0003},
- {8, 0x0083},
- {8, 0x0043},
- {9, 0x00e6},
- {7, 0x0105},
- {8, 0x005b},
- {8, 0x001b},
- {9, 0x0096},
- {7, 0x0115},
- {8, 0x007b},
- {8, 0x003b},
- {9, 0x00d6},
- {7, 0x010d},
- {8, 0x006b},
- {8, 0x002b},
- {9, 0x00b6},
- {8, 0x000b},
- {8, 0x008b},
- {8, 0x004b},
- {9, 0x00f6},
- {7, 0x0103},
- {8, 0x0057},
- {8, 0x0017},
- {8, 0x011f},
- {7, 0x0113},
- {8, 0x0077},
- {8, 0x0037},
- {9, 0x00ce},
- {7, 0x010b},
- {8, 0x0067},
- {8, 0x0027},
- {9, 0x00ae},
- {8, 0x0007},
- {8, 0x0087},
- {8, 0x0047},
- {9, 0x00ee},
- {7, 0x0107},
- {8, 0x005f},
- {8, 0x001f},
- {9, 0x009e},
- {7, 0x0117},
- {8, 0x007f},
- {8, 0x003f},
- {9, 0x00de},
- {7, 0x010f},
- {8, 0x006f},
- {8, 0x002f},
- {9, 0x00be},
- {8, 0x000f},
- {8, 0x008f},
- {8, 0x004f},
- {9, 0x00fe},
- {7, 0x0100},
- {8, 0x0050},
- {8, 0x0010},
- {8, 0x0118},
- {7, 0x0110},
- {8, 0x0070},
- {8, 0x0030},
- {9, 0x00c1},
- {7, 0x0108},
- {8, 0x0060},
- {8, 0x0020},
- {9, 0x00a1},
- {8, 0x0000},
- {8, 0x0080},
- {8, 0x0040},
- {9, 0x00e1},
- {7, 0x0104},
- {8, 0x0058},
- {8, 0x0018},
- {9, 0x0091},
- {7, 0x0114},
- {8, 0x0078},
- {8, 0x0038},
- {9, 0x00d1},
- {7, 0x010c},
- {8, 0x0068},
- {8, 0x0028},
- {9, 0x00b1},
- {8, 0x0008},
- {8, 0x0088},
- {8, 0x0048},
- {9, 0x00f1},
- {7, 0x0102},
- {8, 0x0054},
- {8, 0x0014},
- {8, 0x011c},
- {7, 0x0112},
- {8, 0x0074},
- {8, 0x0034},
- {9, 0x00c9},
- {7, 0x010a},
- {8, 0x0064},
- {8, 0x0024},
- {9, 0x00a9},
- {8, 0x0004},
- {8, 0x0084},
- {8, 0x0044},
- {9, 0x00e9},
- {7, 0x0106},
- {8, 0x005c},
- {8, 0x001c},
- {9, 0x0099},
- {7, 0x0116},
- {8, 0x007c},
- {8, 0x003c},
- {9, 0x00d9},
- {7, 0x010e},
- {8, 0x006c},
- {8, 0x002c},
- {9, 0x00b9},
- {8, 0x000c},
- {8, 0x008c},
- {8, 0x004c},
- {9, 0x00f9},
- {7, 0x0101},
- {8, 0x0052},
- {8, 0x0012},
- {8, 0x011a},
- {7, 0x0111},
- {8, 0x0072},
- {8, 0x0032},
- {9, 0x00c5},
- {7, 0x0109},
- {8, 0x0062},
- {8, 0x0022},
- {9, 0x00a5},
- {8, 0x0002},
- {8, 0x0082},
- {8, 0x0042},
- {9, 0x00e5},
- {7, 0x0105},
- {8, 0x005a},
- {8, 0x001a},
- {9, 0x0095},
- {7, 0x0115},
- {8, 0x007a},
- {8, 0x003a},
- {9, 0x00d5},
- {7, 0x010d},
- {8, 0x006a},
- {8, 0x002a},
- {9, 0x00b5},
- {8, 0x000a},
- {8, 0x008a},
- {8, 0x004a},
- {9, 0x00f5},
- {7, 0x0103},
- {8, 0x0056},
- {8, 0x0016},
- {8, 0x011e},
- {7, 0x0113},
- {8, 0x0076},
- {8, 0x0036},
- {9, 0x00cd},
- {7, 0x010b},
- {8, 0x0066},
- {8, 0x0026},
- {9, 0x00ad},
- {8, 0x0006},
- {8, 0x0086},
- {8, 0x0046},
- {9, 0x00ed},
- {7, 0x0107},
- {8, 0x005e},
- {8, 0x001e},
- {9, 0x009d},
- {7, 0x0117},
- {8, 0x007e},
- {8, 0x003e},
- {9, 0x00dd},
- {7, 0x010f},
- {8, 0x006e},
- {8, 0x002e},
- {9, 0x00bd},
- {8, 0x000e},
- {8, 0x008e},
- {8, 0x004e},
- {9, 0x00fd},
- {7, 0x0100},
- {8, 0x0051},
- {8, 0x0011},
- {8, 0x0119},
- {7, 0x0110},
- {8, 0x0071},
- {8, 0x0031},
- {9, 0x00c3},
- {7, 0x0108},
- {8, 0x0061},
- {8, 0x0021},
- {9, 0x00a3},
- {8, 0x0001},
- {8, 0x0081},
- {8, 0x0041},
- {9, 0x00e3},
- {7, 0x0104},
- {8, 0x0059},
- {8, 0x0019},
- {9, 0x0093},
- {7, 0x0114},
- {8, 0x0079},
- {8, 0x0039},
- {9, 0x00d3},
- {7, 0x010c},
- {8, 0x0069},
- {8, 0x0029},
- {9, 0x00b3},
- {8, 0x0009},
- {8, 0x0089},
- {8, 0x0049},
- {9, 0x00f3},
- {7, 0x0102},
- {8, 0x0055},
- {8, 0x0015},
- {8, 0x011d},
- {7, 0x0112},
- {8, 0x0075},
- {8, 0x0035},
- {9, 0x00cb},
- {7, 0x010a},
- {8, 0x0065},
- {8, 0x0025},
- {9, 0x00ab},
- {8, 0x0005},
- {8, 0x0085},
- {8, 0x0045},
- {9, 0x00eb},
- {7, 0x0106},
- {8, 0x005d},
- {8, 0x001d},
- {9, 0x009b},
- {7, 0x0116},
- {8, 0x007d},
- {8, 0x003d},
- {9, 0x00db},
- {7, 0x010e},
- {8, 0x006d},
- {8, 0x002d},
- {9, 0x00bb},
- {8, 0x000d},
- {8, 0x008d},
- {8, 0x004d},
- {9, 0x00fb},
- {7, 0x0101},
- {8, 0x0053},
- {8, 0x0013},
- {8, 0x011b},
- {7, 0x0111},
- {8, 0x0073},
- {8, 0x0033},
- {9, 0x00c7},
- {7, 0x0109},
- {8, 0x0063},
- {8, 0x0023},
- {9, 0x00a7},
- {8, 0x0003},
- {8, 0x0083},
- {8, 0x0043},
- {9, 0x00e7},
- {7, 0x0105},
- {8, 0x005b},
- {8, 0x001b},
- {9, 0x0097},
- {7, 0x0115},
- {8, 0x007b},
- {8, 0x003b},
- {9, 0x00d7},
- {7, 0x010d},
- {8, 0x006b},
- {8, 0x002b},
- {9, 0x00b7},
- {8, 0x000b},
- {8, 0x008b},
- {8, 0x004b},
- {9, 0x00f7},
- {7, 0x0103},
- {8, 0x0057},
- {8, 0x0017},
- {8, 0x011f},
- {7, 0x0113},
- {8, 0x0077},
- {8, 0x0037},
- {9, 0x00cf},
- {7, 0x010b},
- {8, 0x0067},
- {8, 0x0027},
- {9, 0x00af},
- {8, 0x0007},
- {8, 0x0087},
- {8, 0x0047},
- {9, 0x00ef},
- {7, 0x0107},
- {8, 0x005f},
- {8, 0x001f},
- {9, 0x009f},
- {7, 0x0117},
- {8, 0x007f},
- {8, 0x003f},
- {9, 0x00df},
- {7, 0x010f},
- {8, 0x006f},
- {8, 0x002f},
- {9, 0x00bf},
- {8, 0x000f},
- {8, 0x008f},
- {8, 0x004f},
- {9, 0x00ff}
-};
-
-FlateHuffmanTab FlateStream::fixedLitCodeTab = {
- flateFixedLitCodeTabCodes, 9
-};
-
-static FlateCode flateFixedDistCodeTabCodes[32] = {
- {5, 0x0000},
- {5, 0x0010},
- {5, 0x0008},
- {5, 0x0018},
- {5, 0x0004},
- {5, 0x0014},
- {5, 0x000c},
- {5, 0x001c},
- {5, 0x0002},
- {5, 0x0012},
- {5, 0x000a},
- {5, 0x001a},
- {5, 0x0006},
- {5, 0x0016},
- {5, 0x000e},
- {0, 0x0000},
- {5, 0x0001},
- {5, 0x0011},
- {5, 0x0009},
- {5, 0x0019},
- {5, 0x0005},
- {5, 0x0015},
- {5, 0x000d},
- {5, 0x001d},
- {5, 0x0003},
- {5, 0x0013},
- {5, 0x000b},
- {5, 0x001b},
- {5, 0x0007},
- {5, 0x0017},
- {5, 0x000f},
- {0, 0x0000}
-};
-
-FlateHuffmanTab FlateStream::fixedDistCodeTab = {
- flateFixedDistCodeTabCodes, 5
-};
-
-FlateStream::FlateStream(Stream *strA, int predictor, int columns,
- int colors, int bits):
- FilterStream(strA) {
- if (predictor != 1) {
- pred = new StreamPredictor(this, predictor, columns, colors, bits);
- if (!pred->isOk()) {
- delete pred;
- pred = NULL;
- }
- } else {
- pred = NULL;
- }
- litCodeTab.codes = NULL;
- distCodeTab.codes = NULL;
-}
-
-FlateStream::~FlateStream() {
- if (litCodeTab.codes != fixedLitCodeTab.codes) {
- gfree(litCodeTab.codes);
- }
- if (distCodeTab.codes != fixedDistCodeTab.codes) {
- gfree(distCodeTab.codes);
- }
- if (pred) {
- delete pred;
- }
- delete str;
-}
-
-void FlateStream::reset() {
- int cmf, flg;
-
- index = 0;
- remain = 0;
- codeBuf = 0;
- codeSize = 0;
- compressedBlock = gFalse;
- endOfBlock = gTrue;
- eof = gTrue;
-
- str->reset();
-
- // read header
- //~ need to look at window size?
- endOfBlock = eof = gTrue;
- cmf = str->getChar();
- flg = str->getChar();
- if (cmf == EOF || flg == EOF)
- return;
- if ((cmf & 0x0f) != 0x08) {
- error(getPos(), "Unknown compression method in flate stream");
- return;
- }
- if ((((cmf << 8) + flg) % 31) != 0) {
- error(getPos(), "Bad FCHECK in flate stream");
- return;
- }
- if (flg & 0x20) {
- error(getPos(), "FDICT bit set in flate stream");
- return;
- }
-
- eof = gFalse;
-}
-
-int FlateStream::getChar() {
- int c;
-
- if (pred) {
- return pred->getChar();
- }
- while (remain == 0) {
- if (endOfBlock && eof)
- return EOF;
- readSome();
- }
- c = buf[index];
- index = (index + 1) & flateMask;
- --remain;
- return c;
-}
-
-int FlateStream::lookChar() {
- int c;
-
- if (pred) {
- return pred->lookChar();
- }
- while (remain == 0) {
- if (endOfBlock && eof)
- return EOF;
- readSome();
- }
- c = buf[index];
- return c;
-}
-
-int FlateStream::getRawChar() {
- int c;
-
- while (remain == 0) {
- if (endOfBlock && eof)
- return EOF;
- readSome();
- }
- c = buf[index];
- index = (index + 1) & flateMask;
- --remain;
- return c;
-}
-
-GString *FlateStream::getPSFilter(int psLevel, char *indent) {
- GString *s;
-
- if (psLevel < 3 || pred) {
- return NULL;
- }
- if (!(s = str->getPSFilter(psLevel, indent))) {
- return NULL;
- }
- s->append(indent)->append("<< >> /FlateDecode filter\n");
- return s;
-}
-
-GBool FlateStream::isBinary(GBool last) {
- return str->isBinary(gTrue);
-}
-
-void FlateStream::readSome() {
- int code1, code2;
- int len, dist;
- int i, j, k;
- int c;
-
- if (endOfBlock) {
- if (!startBlock())
- return;
- }
-
- if (compressedBlock) {
- if ((code1 = getHuffmanCodeWord(&litCodeTab)) == EOF)
- goto err;
- if (code1 < 256) {
- buf[index] = code1;
- remain = 1;
- } else if (code1 == 256) {
- endOfBlock = gTrue;
- remain = 0;
- } else {
- code1 -= 257;
- code2 = lengthDecode[code1].bits;
- if (code2 > 0 && (code2 = getCodeWord(code2)) == EOF)
- goto err;
- len = lengthDecode[code1].first + code2;
- if ((code1 = getHuffmanCodeWord(&distCodeTab)) == EOF)
- goto err;
- code2 = distDecode[code1].bits;
- if (code2 > 0 && (code2 = getCodeWord(code2)) == EOF)
- goto err;
- dist = distDecode[code1].first + code2;
- i = index;
- j = (index - dist) & flateMask;
- for (k = 0; k < len; ++k) {
- buf[i] = buf[j];
- i = (i + 1) & flateMask;
- j = (j + 1) & flateMask;
- }
- remain = len;
- }
-
- } else {
- len = (blockLen < flateWindow) ? blockLen : flateWindow;
- for (i = 0, j = index; i < len; ++i, j = (j + 1) & flateMask) {
- if ((c = str->getChar()) == EOF) {
- endOfBlock = eof = gTrue;
- break;
- }
- buf[j] = c & 0xff;
- }
- remain = i;
- blockLen -= len;
- if (blockLen == 0)
- endOfBlock = gTrue;
- }
-
- return;
-
-err:
- error(getPos(), "Unexpected end of file in flate stream");
- endOfBlock = eof = gTrue;
- remain = 0;
-}
-
-GBool FlateStream::startBlock() {
- int blockHdr;
- int c;
- int check;
-
- // free the code tables from the previous block
- if (litCodeTab.codes != fixedLitCodeTab.codes) {
- gfree(litCodeTab.codes);
- }
- litCodeTab.codes = NULL;
- if (distCodeTab.codes != fixedDistCodeTab.codes) {
- gfree(distCodeTab.codes);
- }
- distCodeTab.codes = NULL;
-
- // read block header
- blockHdr = getCodeWord(3);
- if (blockHdr & 1)
- eof = gTrue;
- blockHdr >>= 1;
-
- // uncompressed block
- if (blockHdr == 0) {
- compressedBlock = gFalse;
- if ((c = str->getChar()) == EOF)
- goto err;
- blockLen = c & 0xff;
- if ((c = str->getChar()) == EOF)
- goto err;
- blockLen |= (c & 0xff) << 8;
- if ((c = str->getChar()) == EOF)
- goto err;
- check = c & 0xff;
- if ((c = str->getChar()) == EOF)
- goto err;
- check |= (c & 0xff) << 8;
- if (check != (~blockLen & 0xffff))
- error(getPos(), "Bad uncompressed block length in flate stream");
- codeBuf = 0;
- codeSize = 0;
-
- // compressed block with fixed codes
- } else if (blockHdr == 1) {
- compressedBlock = gTrue;
- loadFixedCodes();
-
- // compressed block with dynamic codes
- } else if (blockHdr == 2) {
- compressedBlock = gTrue;
- if (!readDynamicCodes()) {
- goto err;
- }
-
- // unknown block type
- } else {
- goto err;
- }
-
- endOfBlock = gFalse;
- return gTrue;
-
-err:
- error(getPos(), "Bad block header in flate stream");
- endOfBlock = eof = gTrue;
- return gFalse;
-}
-
-void FlateStream::loadFixedCodes() {
- litCodeTab.codes = fixedLitCodeTab.codes;
- litCodeTab.maxLen = fixedLitCodeTab.maxLen;
- distCodeTab.codes = fixedDistCodeTab.codes;
- distCodeTab.maxLen = fixedDistCodeTab.maxLen;
-}
-
-GBool FlateStream::readDynamicCodes() {
- int numCodeLenCodes;
- int numLitCodes;
- int numDistCodes;
- int codeLenCodeLengths[flateMaxCodeLenCodes];
- FlateHuffmanTab codeLenCodeTab;
- int len, repeat, code;
- int i;
-
- codeLenCodeTab.codes = NULL;
-
- // read lengths
- if ((numLitCodes = getCodeWord(5)) == EOF) {
- goto err;
- }
- numLitCodes += 257;
- if ((numDistCodes = getCodeWord(5)) == EOF) {
- goto err;
- }
- numDistCodes += 1;
- if ((numCodeLenCodes = getCodeWord(4)) == EOF) {
- goto err;
- }
- numCodeLenCodes += 4;
- if (numLitCodes > flateMaxLitCodes ||
- numDistCodes > flateMaxDistCodes ||
- numCodeLenCodes > flateMaxCodeLenCodes) {
- goto err;
- }
-
- // build the code length code table
- for (i = 0; i < flateMaxCodeLenCodes; ++i) {
- codeLenCodeLengths[i] = 0;
- }
- for (i = 0; i < numCodeLenCodes; ++i) {
- if ((codeLenCodeLengths[codeLenCodeMap[i]] = getCodeWord(3)) == -1) {
- goto err;
- }
- }
- compHuffmanCodes(codeLenCodeLengths, flateMaxCodeLenCodes, &codeLenCodeTab);
-
- // build the literal and distance code tables
- len = 0;
- repeat = 0;
- i = 0;
- while (i < numLitCodes + numDistCodes) {
- if ((code = getHuffmanCodeWord(&codeLenCodeTab)) == EOF) {
- goto err;
- }
- if (code == 16) {
- if ((repeat = getCodeWord(2)) == EOF) {
- goto err;
- }
- repeat += 3;
- if (i + repeat > numLitCodes + numDistCodes) {
- goto err;
- }
- for (; repeat > 0; --repeat) {
- codeLengths[i++] = len;
- }
- } else if (code == 17) {
- if ((repeat = getCodeWord(3)) == EOF) {
- goto err;
- }
- repeat += 3;
- if (i + repeat > numLitCodes + numDistCodes) {
- goto err;
- }
- len = 0;
- for (; repeat > 0; --repeat) {
- codeLengths[i++] = 0;
- }
- } else if (code == 18) {
- if ((repeat = getCodeWord(7)) == EOF) {
- goto err;
- }
- repeat += 11;
- if (i + repeat > numLitCodes + numDistCodes) {
- goto err;
- }
- len = 0;
- for (; repeat > 0; --repeat) {
- codeLengths[i++] = 0;
- }
- } else {
- codeLengths[i++] = len = code;
- }
- }
- compHuffmanCodes(codeLengths, numLitCodes, &litCodeTab);
- compHuffmanCodes(codeLengths + numLitCodes, numDistCodes, &distCodeTab);
-
- gfree(codeLenCodeTab.codes);
- return gTrue;
-
-err:
- error(getPos(), "Bad dynamic code table in flate stream");
- gfree(codeLenCodeTab.codes);
- return gFalse;
-}
-
-// Convert an array <lengths> of <n> lengths, in value order, into a
-// Huffman code lookup table.
-void FlateStream::compHuffmanCodes(int *lengths, int n, FlateHuffmanTab *tab) {
- int tabSize, len, code, code2, skip, val, i, t;
-
- // find max code length
- tab->maxLen = 0;
- for (val = 0; val < n; ++val) {
- if (lengths[val] > tab->maxLen) {
- tab->maxLen = lengths[val];
- }
- }
-
- // allocate the table
- tabSize = 1 << tab->maxLen;
- tab->codes = (FlateCode *)gmallocn(tabSize, sizeof(FlateCode));
-
- // clear the table
- for (i = 0; i < tabSize; ++i) {
- tab->codes[i].len = 0;
- tab->codes[i].val = 0;
- }
-
- // build the table
- for (len = 1, code = 0, skip = 2;
- len <= tab->maxLen;
- ++len, code <<= 1, skip <<= 1) {
- for (val = 0; val < n; ++val) {
- if (lengths[val] == len) {
-
- // bit-reverse the code
- code2 = 0;
- t = code;
- for (i = 0; i < len; ++i) {
- code2 = (code2 << 1) | (t & 1);
- t >>= 1;
- }
-
- // fill in the table entries
- for (i = code2; i < tabSize; i += skip) {
- tab->codes[i].len = (Gushort)len;
- tab->codes[i].val = (Gushort)val;
- }
-
- ++code;
- }
- }
- }
-}
-
-int FlateStream::getHuffmanCodeWord(FlateHuffmanTab *tab) {
- FlateCode *code;
- int c;
-
- while (codeSize < tab->maxLen) {
- if ((c = str->getChar()) == EOF) {
- break;
- }
- codeBuf |= (c & 0xff) << codeSize;
- codeSize += 8;
- }
- code = &tab->codes[codeBuf & ((1 << tab->maxLen) - 1)];
- if (codeSize == 0 || codeSize < code->len || code->len == 0) {
- return EOF;
- }
- codeBuf >>= code->len;
- codeSize -= code->len;
- return (int)code->val;
-}
-
-int FlateStream::getCodeWord(int bits) {
- int c;
-
- while (codeSize < bits) {
- if ((c = str->getChar()) == EOF)
- return EOF;
- codeBuf |= (c & 0xff) << codeSize;
- codeSize += 8;
- }
- c = codeBuf & ((1 << bits) - 1);
- codeBuf >>= bits;
- codeSize -= bits;
- return c;
-}
-
-//------------------------------------------------------------------------
-// EOFStream
-//------------------------------------------------------------------------
-
-EOFStream::EOFStream(Stream *strA):
- FilterStream(strA) {
-}
-
-EOFStream::~EOFStream() {
- delete str;
-}
-
-//------------------------------------------------------------------------
-// FixedLengthEncoder
-//------------------------------------------------------------------------
-
-FixedLengthEncoder::FixedLengthEncoder(Stream *strA, int lengthA):
- FilterStream(strA) {
- length = lengthA;
- count = 0;
-}
-
-FixedLengthEncoder::~FixedLengthEncoder() {
- if (str->isEncoder())
- delete str;
-}
-
-void FixedLengthEncoder::reset() {
- str->reset();
- count = 0;
-}
-
-int FixedLengthEncoder::getChar() {
- if (length >= 0 && count >= length)
- return EOF;
- ++count;
- return str->getChar();
-}
-
-int FixedLengthEncoder::lookChar() {
- if (length >= 0 && count >= length)
- return EOF;
- return str->getChar();
-}
-
-GBool FixedLengthEncoder::isBinary(GBool last) {
- return str->isBinary(gTrue);
-}
-
-//------------------------------------------------------------------------
-// ASCIIHexEncoder
-//------------------------------------------------------------------------
-
-ASCIIHexEncoder::ASCIIHexEncoder(Stream *strA):
- FilterStream(strA) {
- bufPtr = bufEnd = buf;
- lineLen = 0;
- eof = gFalse;
-}
-
-ASCIIHexEncoder::~ASCIIHexEncoder() {
- if (str->isEncoder()) {
- delete str;
- }
-}
-
-void ASCIIHexEncoder::reset() {
- str->reset();
- bufPtr = bufEnd = buf;
- lineLen = 0;
- eof = gFalse;
-}
-
-GBool ASCIIHexEncoder::fillBuf() {
- static char *hex = "0123456789abcdef";
- int c;
-
- if (eof) {
- return gFalse;
- }
- bufPtr = bufEnd = buf;
- if ((c = str->getChar()) == EOF) {
- *bufEnd++ = '>';
- eof = gTrue;
- } else {
- if (lineLen >= 64) {
- *bufEnd++ = '\n';
- lineLen = 0;
- }
- *bufEnd++ = hex[(c >> 4) & 0x0f];
- *bufEnd++ = hex[c & 0x0f];
- lineLen += 2;
- }
- return gTrue;
-}
-
-//------------------------------------------------------------------------
-// ASCII85Encoder
-//------------------------------------------------------------------------
-
-ASCII85Encoder::ASCII85Encoder(Stream *strA):
- FilterStream(strA) {
- bufPtr = bufEnd = buf;
- lineLen = 0;
- eof = gFalse;
-}
-
-ASCII85Encoder::~ASCII85Encoder() {
- if (str->isEncoder())
- delete str;
-}
-
-void ASCII85Encoder::reset() {
- str->reset();
- bufPtr = bufEnd = buf;
- lineLen = 0;
- eof = gFalse;
-}
-
-GBool ASCII85Encoder::fillBuf() {
- Gulong t;
- char buf1[5];
- int c;
- int n, i;
-
- if (eof)
- return gFalse;
- t = 0;
- for (n = 0; n < 4; ++n) {
- if ((c = str->getChar()) == EOF)
- break;
- t = (t << 8) + c;
- }
- bufPtr = bufEnd = buf;
- if (n > 0) {
- if (n == 4 && t == 0) {
- *bufEnd++ = 'z';
- if (++lineLen == 65) {
- *bufEnd++ = '\n';
- lineLen = 0;
- }
- } else {
- if (n < 4)
- t <<= 8 * (4 - n);
- for (i = 4; i >= 0; --i) {
- buf1[i] = (char)(t % 85 + 0x21);
- t /= 85;
- }
- for (i = 0; i <= n; ++i) {
- *bufEnd++ = buf1[i];
- if (++lineLen == 65) {
- *bufEnd++ = '\n';
- lineLen = 0;
- }
- }
- }
- }
- if (n < 4) {
- *bufEnd++ = '~';
- *bufEnd++ = '>';
- eof = gTrue;
- }
- return bufPtr < bufEnd;
-}
-
-//------------------------------------------------------------------------
-// RunLengthEncoder
-//------------------------------------------------------------------------
-
-RunLengthEncoder::RunLengthEncoder(Stream *strA):
- FilterStream(strA) {
- bufPtr = bufEnd = nextEnd = buf;
- eof = gFalse;
-}
-
-RunLengthEncoder::~RunLengthEncoder() {
- if (str->isEncoder())
- delete str;
-}
-
-void RunLengthEncoder::reset() {
- str->reset();
- bufPtr = bufEnd = nextEnd = buf;
- eof = gFalse;
-}
-
-//
-// When fillBuf finishes, buf[] looks like this:
-// +-----+--------------+-----------------+--
-// + tag | ... data ... | next 0, 1, or 2 |
-// +-----+--------------+-----------------+--
-// ^ ^ ^
-// bufPtr bufEnd nextEnd
-//
-GBool RunLengthEncoder::fillBuf() {
- int c, c1, c2;
- int n;
-
- // already hit EOF?
- if (eof)
- return gFalse;
-
- // grab two bytes
- if (nextEnd < bufEnd + 1) {
- if ((c1 = str->getChar()) == EOF) {
- eof = gTrue;
- return gFalse;
- }
- } else {
- c1 = bufEnd[0] & 0xff;
- }
- if (nextEnd < bufEnd + 2) {
- if ((c2 = str->getChar()) == EOF) {
- eof = gTrue;
- buf[0] = 0;
- buf[1] = c1;
- bufPtr = buf;
- bufEnd = &buf[2];
- return gTrue;
- }
- } else {
- c2 = bufEnd[1] & 0xff;
- }
-
- // check for repeat
- c = 0; // make gcc happy
- if (c1 == c2) {
- n = 2;
- while (n < 128 && (c = str->getChar()) == c1)
- ++n;
- buf[0] = (char)(257 - n);
- buf[1] = c1;
- bufEnd = &buf[2];
- if (c == EOF) {
- eof = gTrue;
- } else if (n < 128) {
- buf[2] = c;
- nextEnd = &buf[3];
- } else {
- nextEnd = bufEnd;
- }
-
- // get up to 128 chars
- } else {
- buf[1] = c1;
- buf[2] = c2;
- n = 2;
- while (n < 128) {
- if ((c = str->getChar()) == EOF) {
- eof = gTrue;
- break;
- }
- ++n;
- buf[n] = c;
- if (buf[n] == buf[n-1])
- break;
- }
- if (buf[n] == buf[n-1]) {
- buf[0] = (char)(n-2-1);
- bufEnd = &buf[n-1];
- nextEnd = &buf[n+1];
- } else {
- buf[0] = (char)(n-1);
- bufEnd = nextEnd = &buf[n+1];
- }
- }
- bufPtr = buf;
- return gTrue;
-}
+++ /dev/null
-//========================================================================
-//
-// Stream.h
-//
-// Copyright 1996-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#ifndef STREAM_H
-#define STREAM_H
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma interface
-#endif
-
-#include <stdio.h>
-#include "gtypes.h"
-#include "Object.h"
-
-class Decrypt;
-class BaseStream;
-
-//------------------------------------------------------------------------
-
-enum StreamKind {
- strFile,
- strASCIIHex,
- strASCII85,
- strLZW,
- strRunLength,
- strCCITTFax,
- strDCT,
- strFlate,
- strJBIG2,
- strJPX,
- strWeird // internal-use stream types
-};
-
-enum StreamColorSpaceMode {
- streamCSNone,
- streamCSDeviceGray,
- streamCSDeviceRGB,
- streamCSDeviceCMYK
-};
-
-//------------------------------------------------------------------------
-// Stream (base class)
-//------------------------------------------------------------------------
-
-class Stream {
-public:
-
- // Constructor.
- Stream();
-
- // Destructor.
- virtual ~Stream();
-
- // Reference counting.
- int incRef() { return ++ref; }
- int decRef() { return --ref; }
-
- // Get kind of stream.
- virtual StreamKind getKind() = 0;
-
- // Reset stream to beginning.
- virtual void reset() = 0;
-
- // Close down the stream.
- virtual void close();
-
- // Get next char from stream.
- virtual int getChar() = 0;
-
- // Peek at next char in stream.
- virtual int lookChar() = 0;
-
- // Get next char from stream without using the predictor.
- // This is only used by StreamPredictor.
- virtual int getRawChar();
-
- // Get next line from stream.
- virtual char *getLine(char *buf, int size);
-
- // Get current position in file.
- virtual int getPos() = 0;
-
- // Go to a position in the stream. If <dir> is negative, the
- // position is from the end of the file; otherwise the position is
- // from the start of the file.
- virtual void setPos(Guint pos, int dir = 0) = 0;
-
- // Get PostScript command for the filter(s).
- virtual GString *getPSFilter(int psLevel, char *indent);
-
- // Does this stream type potentially contain non-printable chars?
- virtual GBool isBinary(GBool last = gTrue) = 0;
-
- // Get the BaseStream of this stream.
- virtual BaseStream *getBaseStream() = 0;
-
- // Get the dictionary associated with this stream.
- virtual Dict *getDict() = 0;
-
- // Is this an encoding filter?
- virtual GBool isEncoder() { return gFalse; }
-
- // Get image parameters which are defined by the stream contents.
- virtual void getImageParams(int *bitsPerComponent,
- StreamColorSpaceMode *csMode) {}
-
- // Add filters to this stream according to the parameters in <dict>.
- // Returns the new stream.
- Stream *addFilters(Object *dict);
-
-private:
-
- Stream *makeFilter(char *name, Stream *str, Object *params);
-
- int ref; // reference count
-};
-
-//------------------------------------------------------------------------
-// BaseStream
-//
-// This is the base class for all streams that read directly from a file.
-//------------------------------------------------------------------------
-
-class BaseStream: public Stream {
-public:
-
- BaseStream(Object *dictA);
- virtual ~BaseStream();
- virtual Stream *makeSubStream(Guint start, GBool limited,
- Guint length, Object *dict) = 0;
- virtual void setPos(Guint pos, int dir = 0) = 0;
- virtual GBool isBinary(GBool last = gTrue) { return last; }
- virtual BaseStream *getBaseStream() { return this; }
- virtual Dict *getDict() { return dict.getDict(); }
-
- // Get/set position of first byte of stream within the file.
- virtual Guint getStart() = 0;
- virtual void moveStart(int delta) = 0;
-
- // Set decryption for this stream.
- virtual void doDecryption(Guchar *fileKey, int keyLength,
- int objNum, int objGen);
-
-protected:
-
- Decrypt *decrypt;
-
-private:
-
- Object dict;
-};
-
-//------------------------------------------------------------------------
-// FilterStream
-//
-// This is the base class for all streams that filter another stream.
-//------------------------------------------------------------------------
-
-class FilterStream: public Stream {
-public:
-
- FilterStream(Stream *strA);
- virtual ~FilterStream();
- virtual void close();
- virtual int getPos() { return str->getPos(); }
- virtual void setPos(Guint pos, int dir = 0);
- virtual BaseStream *getBaseStream() { return str->getBaseStream(); }
- virtual Dict *getDict() { return str->getDict(); }
-
-protected:
-
- Stream *str;
-};
-
-//------------------------------------------------------------------------
-// ImageStream
-//------------------------------------------------------------------------
-
-class ImageStream {
-public:
-
- // Create an image stream object for an image with the specified
- // parameters. Note that these are the actual image parameters,
- // which may be different from the predictor parameters.
- ImageStream(Stream *strA, int widthA, int nCompsA, int nBitsA);
-
- ~ImageStream();
-
- // Reset the stream.
- void reset();
-
- // Gets the next pixel from the stream. <pix> should be able to hold
- // at least nComps elements. Returns false at end of file.
- GBool getPixel(Guchar *pix);
-
- // Returns a pointer to the next line of pixels. Returns NULL at
- // end of file.
- Guchar *getLine();
-
- // Skip an entire line from the image.
- void skipLine();
-
-private:
-
- Stream *str; // base stream
- int width; // pixels per line
- int nComps; // components per pixel
- int nBits; // bits per component
- int nVals; // components per line
- Guchar *imgLine; // line buffer
- int imgIdx; // current index in imgLine
-};
-
-//------------------------------------------------------------------------
-// StreamPredictor
-//------------------------------------------------------------------------
-
-class StreamPredictor {
-public:
-
- // Create a predictor object. Note that the parameters are for the
- // predictor, and may not match the actual image parameters.
- StreamPredictor(Stream *strA, int predictorA,
- int widthA, int nCompsA, int nBitsA);
-
- ~StreamPredictor();
-
- GBool isOk() { return ok; }
-
- int lookChar();
- int getChar();
-
-private:
-
- GBool getNextLine();
-
- Stream *str; // base stream
- int predictor; // predictor
- int width; // pixels per line
- int nComps; // components per pixel
- int nBits; // bits per component
- int nVals; // components per line
- int pixBytes; // bytes per pixel
- int rowBytes; // bytes per line
- Guchar *predLine; // line buffer
- int predIdx; // current index in predLine
- GBool ok;
-};
-
-//------------------------------------------------------------------------
-// FileStream
-//------------------------------------------------------------------------
-
-#define fileStreamBufSize 256
-
-class FileStream: public BaseStream {
-public:
-
- FileStream(FILE *fA, Guint startA, GBool limitedA,
- Guint lengthA, Object *dictA);
- virtual ~FileStream();
- virtual Stream *makeSubStream(Guint startA, GBool limitedA,
- Guint lengthA, Object *dictA);
- virtual StreamKind getKind() { return strFile; }
- virtual void reset();
- virtual void close();
- virtual int getChar()
- { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); }
- virtual int lookChar()
- { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); }
- virtual int getPos() { return bufPos + (bufPtr - buf); }
- virtual void setPos(Guint pos, int dir = 0);
- virtual Guint getStart() { return start; }
- virtual void moveStart(int delta);
-
-private:
-
- GBool fillBuf();
-
- FILE *f;
- Guint start;
- GBool limited;
- Guint length;
- char buf[fileStreamBufSize];
- char *bufPtr;
- char *bufEnd;
- Guint bufPos;
- int savePos;
- GBool saved;
-};
-
-//------------------------------------------------------------------------
-// MemStream
-//------------------------------------------------------------------------
-
-class MemStream: public BaseStream {
-public:
-
- MemStream(char *bufA, Guint startA, Guint lengthA, Object *dictA);
- virtual ~MemStream();
- virtual Stream *makeSubStream(Guint start, GBool limited,
- Guint lengthA, Object *dictA);
- virtual StreamKind getKind() { return strWeird; }
- virtual void reset();
- virtual void close();
- virtual int getChar()
- { return (bufPtr < bufEnd) ? (*bufPtr++ & 0xff) : EOF; }
- virtual int lookChar()
- { return (bufPtr < bufEnd) ? (*bufPtr & 0xff) : EOF; }
- virtual int getPos() { return (int)(bufPtr - buf); }
- virtual void setPos(Guint pos, int dir = 0);
- virtual Guint getStart() { return start; }
- virtual void moveStart(int delta);
- virtual void doDecryption(Guchar *fileKey, int keyLength,
- int objNum, int objGen);
-
-private:
-
- char *buf;
- Guint start;
- Guint length;
- char *bufEnd;
- char *bufPtr;
- GBool needFree;
-};
-
-//------------------------------------------------------------------------
-// EmbedStream
-//
-// This is a special stream type used for embedded streams (inline
-// images). It reads directly from the base stream -- after the
-// EmbedStream is deleted, reads from the base stream will proceed where
-// the BaseStream left off. Note that this is very different behavior
-// that creating a new FileStream (using makeSubStream).
-//------------------------------------------------------------------------
-
-class EmbedStream: public BaseStream {
-public:
-
- EmbedStream(Stream *strA, Object *dictA, GBool limitedA, Guint lengthA);
- virtual ~EmbedStream();
- virtual Stream *makeSubStream(Guint start, GBool limitedA,
- Guint lengthA, Object *dictA);
- virtual StreamKind getKind() { return str->getKind(); }
- virtual void reset() {}
- virtual int getChar();
- virtual int lookChar();
- virtual int getPos() { return str->getPos(); }
- virtual void setPos(Guint pos, int dir = 0);
- virtual Guint getStart();
- virtual void moveStart(int delta);
-
-private:
-
- Stream *str;
- GBool limited;
- Guint length;
-};
-
-//------------------------------------------------------------------------
-// ASCIIHexStream
-//------------------------------------------------------------------------
-
-class ASCIIHexStream: public FilterStream {
-public:
-
- ASCIIHexStream(Stream *strA);
- virtual ~ASCIIHexStream();
- virtual StreamKind getKind() { return strASCIIHex; }
- virtual void reset();
- virtual int getChar()
- { int c = lookChar(); buf = EOF; return c; }
- virtual int lookChar();
- virtual GString *getPSFilter(int psLevel, char *indent);
- virtual GBool isBinary(GBool last = gTrue);
-
-private:
-
- int buf;
- GBool eof;
-};
-
-//------------------------------------------------------------------------
-// ASCII85Stream
-//------------------------------------------------------------------------
-
-class ASCII85Stream: public FilterStream {
-public:
-
- ASCII85Stream(Stream *strA);
- virtual ~ASCII85Stream();
- virtual StreamKind getKind() { return strASCII85; }
- virtual void reset();
- virtual int getChar()
- { int ch = lookChar(); ++index; return ch; }
- virtual int lookChar();
- virtual GString *getPSFilter(int psLevel, char *indent);
- virtual GBool isBinary(GBool last = gTrue);
-
-private:
-
- int c[5];
- int b[4];
- int index, n;
- GBool eof;
-};
-
-//------------------------------------------------------------------------
-// LZWStream
-//------------------------------------------------------------------------
-
-class LZWStream: public FilterStream {
-public:
-
- LZWStream(Stream *strA, int predictor, int columns, int colors,
- int bits, int earlyA);
- virtual ~LZWStream();
- virtual StreamKind getKind() { return strLZW; }
- virtual void reset();
- virtual int getChar();
- virtual int lookChar();
- virtual int getRawChar();
- virtual GString *getPSFilter(int psLevel, char *indent);
- virtual GBool isBinary(GBool last = gTrue);
-
-private:
-
- StreamPredictor *pred; // predictor
- int early; // early parameter
- GBool eof; // true if at eof
- int inputBuf; // input buffer
- int inputBits; // number of bits in input buffer
- struct { // decoding table
- int length;
- int head;
- Guchar tail;
- } table[4097];
- int nextCode; // next code to be used
- int nextBits; // number of bits in next code word
- int prevCode; // previous code used in stream
- int newChar; // next char to be added to table
- Guchar seqBuf[4097]; // buffer for current sequence
- int seqLength; // length of current sequence
- int seqIndex; // index into current sequence
- GBool first; // first code after a table clear
-
- GBool processNextCode();
- void clearTable();
- int getCode();
-};
-
-//------------------------------------------------------------------------
-// RunLengthStream
-//------------------------------------------------------------------------
-
-class RunLengthStream: public FilterStream {
-public:
-
- RunLengthStream(Stream *strA);
- virtual ~RunLengthStream();
- virtual StreamKind getKind() { return strRunLength; }
- virtual void reset();
- virtual int getChar()
- { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); }
- virtual int lookChar()
- { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); }
- virtual GString *getPSFilter(int psLevel, char *indent);
- virtual GBool isBinary(GBool last = gTrue);
-
-private:
-
- char buf[128]; // buffer
- char *bufPtr; // next char to read
- char *bufEnd; // end of buffer
- GBool eof;
-
- GBool fillBuf();
-};
-
-//------------------------------------------------------------------------
-// CCITTFaxStream
-//------------------------------------------------------------------------
-
-struct CCITTCodeTable;
-
-class CCITTFaxStream: public FilterStream {
-public:
-
- CCITTFaxStream(Stream *strA, int encodingA, GBool endOfLineA,
- GBool byteAlignA, int columnsA, int rowsA,
- GBool endOfBlockA, GBool blackA);
- virtual ~CCITTFaxStream();
- virtual StreamKind getKind() { return strCCITTFax; }
- virtual void reset();
- virtual int getChar()
- { int c = lookChar(); buf = EOF; return c; }
- virtual int lookChar();
- virtual GString *getPSFilter(int psLevel, char *indent);
- virtual GBool isBinary(GBool last = gTrue);
-
-private:
-
- int encoding; // 'K' parameter
- GBool endOfLine; // 'EndOfLine' parameter
- GBool byteAlign; // 'EncodedByteAlign' parameter
- int columns; // 'Columns' parameter
- int rows; // 'Rows' parameter
- GBool endOfBlock; // 'EndOfBlock' parameter
- GBool black; // 'BlackIs1' parameter
- GBool eof; // true if at eof
- GBool nextLine2D; // true if next line uses 2D encoding
- int row; // current row
- int inputBuf; // input buffer
- int inputBits; // number of bits in input buffer
- short *refLine; // reference line changing elements
- int b1; // index into refLine
- short *codingLine; // coding line changing elements
- int a0; // index into codingLine
- int outputBits; // remaining ouput bits
- int buf; // character buffer
-
- short getTwoDimCode();
- short getWhiteCode();
- short getBlackCode();
- short lookBits(int n);
- void eatBits(int n) { inputBits -= n; }
-};
-
-//------------------------------------------------------------------------
-// DCTStream
-//------------------------------------------------------------------------
-
-// DCT component info
-struct DCTCompInfo {
- int id; // component ID
- int hSample, vSample; // horiz/vert sampling resolutions
- int quantTable; // quantization table number
- int prevDC; // DC coefficient accumulator
-};
-
-struct DCTScanInfo {
- GBool comp[4]; // comp[i] is set if component i is
- // included in this scan
- int numComps; // number of components in the scan
- int dcHuffTable[4]; // DC Huffman table numbers
- int acHuffTable[4]; // AC Huffman table numbers
- int firstCoeff, lastCoeff; // first and last DCT coefficient
- int ah, al; // successive approximation parameters
-};
-
-// DCT Huffman decoding table
-struct DCTHuffTable {
- Guchar firstSym[17]; // first symbol for this bit length
- Gushort firstCode[17]; // first code for this bit length
- Gushort numCodes[17]; // number of codes of this bit length
- Guchar sym[256]; // symbols
-};
-
-class DCTStream: public FilterStream {
-public:
-
- DCTStream(Stream *strA);
- virtual ~DCTStream();
- virtual StreamKind getKind() { return strDCT; }
- virtual void reset();
- virtual int getChar();
- virtual int lookChar();
- virtual GString *getPSFilter(int psLevel, char *indent);
- virtual GBool isBinary(GBool last = gTrue);
- Stream *getRawStream() { return str; }
-
-private:
-
- GBool progressive; // set if in progressive mode
- GBool interleaved; // set if in interleaved mode
- int width, height; // image size
- int mcuWidth, mcuHeight; // size of min coding unit, in data units
- int bufWidth, bufHeight; // frameBuf size
- DCTCompInfo compInfo[4]; // info for each component
- DCTScanInfo scanInfo; // info for the current scan
- int numComps; // number of components in image
- int colorXform; // need YCbCr-to-RGB transform?
- GBool gotJFIFMarker; // set if APP0 JFIF marker was present
- GBool gotAdobeMarker; // set if APP14 Adobe marker was present
- int restartInterval; // restart interval, in MCUs
- Gushort quantTables[4][64]; // quantization tables
- int numQuantTables; // number of quantization tables
- DCTHuffTable dcHuffTables[4]; // DC Huffman tables
- DCTHuffTable acHuffTables[4]; // AC Huffman tables
- int numDCHuffTables; // number of DC Huffman tables
- int numACHuffTables; // number of AC Huffman tables
- Guchar *rowBuf[4][32]; // buffer for one MCU (non-progressive mode)
- int *frameBuf[4]; // buffer for frame (progressive mode)
- int comp, x, y, dy; // current position within image/MCU
- int restartCtr; // MCUs left until restart
- int restartMarker; // next restart marker
- int eobRun; // number of EOBs left in the current run
- int inputBuf; // input buffer for variable length codes
- int inputBits; // number of valid bits in input buffer
-
- void restart();
- GBool readMCURow();
- void readScan();
- GBool readDataUnit(DCTHuffTable *dcHuffTable,
- DCTHuffTable *acHuffTable,
- int *prevDC, int data[64]);
- GBool readProgressiveDataUnit(DCTHuffTable *dcHuffTable,
- DCTHuffTable *acHuffTable,
- int *prevDC, int data[64]);
- void decodeImage();
- void transformDataUnit(Gushort *quantTable,
- int dataIn[64], Guchar dataOut[64]);
- int readHuffSym(DCTHuffTable *table);
- int readAmp(int size);
- int readBit();
- GBool readHeader();
- GBool readBaselineSOF();
- GBool readProgressiveSOF();
- GBool readScanInfo();
- GBool readQuantTables();
- GBool readHuffmanTables();
- GBool readRestartInterval();
- GBool readJFIFMarker();
- GBool readAdobeMarker();
- GBool readTrailer();
- int readMarker();
- int read16();
-};
-
-//------------------------------------------------------------------------
-// FlateStream
-//------------------------------------------------------------------------
-
-#define flateWindow 32768 // buffer size
-#define flateMask (flateWindow-1)
-#define flateMaxHuffman 15 // max Huffman code length
-#define flateMaxCodeLenCodes 19 // max # code length codes
-#define flateMaxLitCodes 288 // max # literal codes
-#define flateMaxDistCodes 30 // max # distance codes
-
-// Huffman code table entry
-struct FlateCode {
- Gushort len; // code length, in bits
- Gushort val; // value represented by this code
-};
-
-struct FlateHuffmanTab {
- FlateCode *codes;
- int maxLen;
-};
-
-// Decoding info for length and distance code words
-struct FlateDecode {
- int bits; // # extra bits
- int first; // first length/distance
-};
-
-class FlateStream: public FilterStream {
-public:
-
- FlateStream(Stream *strA, int predictor, int columns,
- int colors, int bits);
- virtual ~FlateStream();
- virtual StreamKind getKind() { return strFlate; }
- virtual void reset();
- virtual int getChar();
- virtual int lookChar();
- virtual int getRawChar();
- virtual GString *getPSFilter(int psLevel, char *indent);
- virtual GBool isBinary(GBool last = gTrue);
-
-private:
-
- StreamPredictor *pred; // predictor
- Guchar buf[flateWindow]; // output data buffer
- int index; // current index into output buffer
- int remain; // number valid bytes in output buffer
- int codeBuf; // input buffer
- int codeSize; // number of bits in input buffer
- int // literal and distance code lengths
- codeLengths[flateMaxLitCodes + flateMaxDistCodes];
- FlateHuffmanTab litCodeTab; // literal code table
- FlateHuffmanTab distCodeTab; // distance code table
- GBool compressedBlock; // set if reading a compressed block
- int blockLen; // remaining length of uncompressed block
- GBool endOfBlock; // set when end of block is reached
- GBool eof; // set when end of stream is reached
-
- static int // code length code reordering
- codeLenCodeMap[flateMaxCodeLenCodes];
- static FlateDecode // length decoding info
- lengthDecode[flateMaxLitCodes-257];
- static FlateDecode // distance decoding info
- distDecode[flateMaxDistCodes];
- static FlateHuffmanTab // fixed literal code table
- fixedLitCodeTab;
- static FlateHuffmanTab // fixed distance code table
- fixedDistCodeTab;
-
- void readSome();
- GBool startBlock();
- void loadFixedCodes();
- GBool readDynamicCodes();
- void compHuffmanCodes(int *lengths, int n, FlateHuffmanTab *tab);
- int getHuffmanCodeWord(FlateHuffmanTab *tab);
- int getCodeWord(int bits);
-};
-
-//------------------------------------------------------------------------
-// EOFStream
-//------------------------------------------------------------------------
-
-class EOFStream: public FilterStream {
-public:
-
- EOFStream(Stream *strA);
- virtual ~EOFStream();
- virtual StreamKind getKind() { return strWeird; }
- virtual void reset() {}
- virtual int getChar() { return EOF; }
- virtual int lookChar() { return EOF; }
- virtual GString *getPSFilter(int psLevel, char *indent) { return NULL; }
- virtual GBool isBinary(GBool last = gTrue) { return gFalse; }
-};
-
-//------------------------------------------------------------------------
-// FixedLengthEncoder
-//------------------------------------------------------------------------
-
-class FixedLengthEncoder: public FilterStream {
-public:
-
- FixedLengthEncoder(Stream *strA, int lengthA);
- ~FixedLengthEncoder();
- virtual StreamKind getKind() { return strWeird; }
- virtual void reset();
- virtual int getChar();
- virtual int lookChar();
- virtual GString *getPSFilter(int psLevel, char *indent) { return NULL; }
- virtual GBool isBinary(GBool last = gTrue);
- virtual GBool isEncoder() { return gTrue; }
-
-private:
-
- int length;
- int count;
-};
-
-//------------------------------------------------------------------------
-// ASCIIHexEncoder
-//------------------------------------------------------------------------
-
-class ASCIIHexEncoder: public FilterStream {
-public:
-
- ASCIIHexEncoder(Stream *strA);
- virtual ~ASCIIHexEncoder();
- virtual StreamKind getKind() { return strWeird; }
- virtual void reset();
- virtual int getChar()
- { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); }
- virtual int lookChar()
- { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); }
- virtual GString *getPSFilter(int psLevel, char *indent) { return NULL; }
- virtual GBool isBinary(GBool last = gTrue) { return gFalse; }
- virtual GBool isEncoder() { return gTrue; }
-
-private:
-
- char buf[4];
- char *bufPtr;
- char *bufEnd;
- int lineLen;
- GBool eof;
-
- GBool fillBuf();
-};
-
-//------------------------------------------------------------------------
-// ASCII85Encoder
-//------------------------------------------------------------------------
-
-class ASCII85Encoder: public FilterStream {
-public:
-
- ASCII85Encoder(Stream *strA);
- virtual ~ASCII85Encoder();
- virtual StreamKind getKind() { return strWeird; }
- virtual void reset();
- virtual int getChar()
- { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); }
- virtual int lookChar()
- { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); }
- virtual GString *getPSFilter(int psLevel, char *indent) { return NULL; }
- virtual GBool isBinary(GBool last = gTrue) { return gFalse; }
- virtual GBool isEncoder() { return gTrue; }
-
-private:
-
- char buf[8];
- char *bufPtr;
- char *bufEnd;
- int lineLen;
- GBool eof;
-
- GBool fillBuf();
-};
-
-//------------------------------------------------------------------------
-// RunLengthEncoder
-//------------------------------------------------------------------------
-
-class RunLengthEncoder: public FilterStream {
-public:
-
- RunLengthEncoder(Stream *strA);
- virtual ~RunLengthEncoder();
- virtual StreamKind getKind() { return strWeird; }
- virtual void reset();
- virtual int getChar()
- { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); }
- virtual int lookChar()
- { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); }
- virtual GString *getPSFilter(int psLevel, char *indent) { return NULL; }
- virtual GBool isBinary(GBool last = gTrue) { return gTrue; }
- virtual GBool isEncoder() { return gTrue; }
-
-private:
-
- char buf[131];
- char *bufPtr;
- char *bufEnd;
- char *nextEnd;
- GBool eof;
-
- GBool fillBuf();
-};
-
-#endif
+++ /dev/null
-//========================================================================
-//
-// UTF8.h
-//
-// Copyright 2001-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-static int mapUTF8(Unicode u, char *buf, int bufSize) {
- if (u <= 0x0000007f) {
- if (bufSize < 1) {
- return 0;
- }
- buf[0] = (char)u;
- return 1;
- } else if (u <= 0x000007ff) {
- if (bufSize < 2) {
- return 0;
- }
- buf[0] = (char)(0xc0 + (u >> 6));
- buf[1] = (char)(0x80 + (u & 0x3f));
- return 2;
- } else if (u <= 0x0000ffff) {
- if (bufSize < 3) {
- return 0;
- }
- buf[0] = (char)(0xe0 + (u >> 12));
- buf[1] = (char)(0x80 + ((u >> 6) & 0x3f));
- buf[2] = (char)(0x80 + (u & 0x3f));
- return 3;
- } else if (u <= 0x0010ffff) {
- if (bufSize < 4) {
- return 0;
- }
- buf[0] = (char)(0xf0 + (u >> 18));
- buf[1] = (char)(0x80 + ((u >> 12) & 0x3f));
- buf[2] = (char)(0x80 + ((u >> 6) & 0x3f));
- buf[3] = (char)(0x80 + (u & 0x3f));
- return 4;
- } else {
- return 0;
- }
-}
-
-static int mapUCS2(Unicode u, char *buf, int bufSize) {
- if (u <= 0xffff) {
- if (bufSize < 2) {
- return 0;
- }
- buf[0] = (char)((u >> 8) & 0xff);
- buf[1] = (char)(u & 0xff);
- return 2;
- } else {
- return 0;
- }
-}
+++ /dev/null
-//========================================================================
-//
-// UnicodeMap.cc
-//
-// Copyright 2001-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma implementation
-#endif
-
-#include <stdio.h>
-#include <string.h>
-#include "gmem.h"
-#include "gfile.h"
-#include "GString.h"
-#include "GList.h"
-#include "Error.h"
-#include "GlobalParams.h"
-#include "UnicodeMap.h"
-
-//------------------------------------------------------------------------
-
-#define maxExtCode 16
-
-struct UnicodeMapExt {
- Unicode u; // Unicode char
- char code[maxExtCode];
- Guint nBytes;
-};
-
-//------------------------------------------------------------------------
-
-UnicodeMap *UnicodeMap::parse(GString *encodingNameA) {
- FILE *f;
- UnicodeMap *map;
- UnicodeMapRange *range;
- UnicodeMapExt *eMap;
- int size, eMapsSize;
- char buf[256];
- int line, nBytes, i, x;
- char *tok1, *tok2, *tok3;
-
- if (!(f = globalParams->getUnicodeMapFile(encodingNameA))) {
- error(-1, "Couldn't find unicodeMap file for the '%s' encoding",
- encodingNameA->getCString());
- return NULL;
- }
-
- map = new UnicodeMap(encodingNameA->copy());
-
- size = 8;
- map->ranges = (UnicodeMapRange *)gmallocn(size, sizeof(UnicodeMapRange));
- eMapsSize = 0;
-
- line = 1;
- while (getLine(buf, sizeof(buf), f)) {
- if ((tok1 = strtok(buf, " \t\r\n")) &&
- (tok2 = strtok(NULL, " \t\r\n"))) {
- if (!(tok3 = strtok(NULL, " \t\r\n"))) {
- tok3 = tok2;
- tok2 = tok1;
- }
- nBytes = strlen(tok3) / 2;
- if (nBytes <= 4) {
- if (map->len == size) {
- size *= 2;
- map->ranges = (UnicodeMapRange *)
- greallocn(map->ranges, size, sizeof(UnicodeMapRange));
- }
- range = &map->ranges[map->len];
- sscanf(tok1, "%x", &range->start);
- sscanf(tok2, "%x", &range->end);
- sscanf(tok3, "%x", &range->code);
- range->nBytes = nBytes;
- ++map->len;
- } else if (tok2 == tok1) {
- if (map->eMapsLen == eMapsSize) {
- eMapsSize += 16;
- map->eMaps = (UnicodeMapExt *)
- greallocn(map->eMaps, eMapsSize, sizeof(UnicodeMapExt));
- }
- eMap = &map->eMaps[map->eMapsLen];
- sscanf(tok1, "%x", &eMap->u);
- for (i = 0; i < nBytes; ++i) {
- sscanf(tok3 + i*2, "%2x", &x);
- eMap->code[i] = (char)x;
- }
- eMap->nBytes = nBytes;
- ++map->eMapsLen;
- } else {
- error(-1, "Bad line (%d) in unicodeMap file for the '%s' encoding",
- line, encodingNameA->getCString());
- }
- } else {
- error(-1, "Bad line (%d) in unicodeMap file for the '%s' encoding",
- line, encodingNameA->getCString());
- }
- ++line;
- }
-
- fclose(f);
-
- return map;
-}
-
-UnicodeMap::UnicodeMap(GString *encodingNameA) {
- encodingName = encodingNameA;
- unicodeOut = gFalse;
- kind = unicodeMapUser;
- ranges = NULL;
- len = 0;
- eMaps = NULL;
- eMapsLen = 0;
- refCnt = 1;
-#if MULTITHREADED
- gInitMutex(&mutex);
-#endif
-}
-
-UnicodeMap::UnicodeMap(char *encodingNameA, GBool unicodeOutA,
- UnicodeMapRange *rangesA, int lenA) {
- encodingName = new GString(encodingNameA);
- unicodeOut = unicodeOutA;
- kind = unicodeMapResident;
- ranges = rangesA;
- len = lenA;
- eMaps = NULL;
- eMapsLen = 0;
- refCnt = 1;
-#if MULTITHREADED
- gInitMutex(&mutex);
-#endif
-}
-
-UnicodeMap::UnicodeMap(char *encodingNameA, GBool unicodeOutA,
- UnicodeMapFunc funcA) {
- encodingName = new GString(encodingNameA);
- unicodeOut = unicodeOutA;
- kind = unicodeMapFunc;
- func = funcA;
- eMaps = NULL;
- eMapsLen = 0;
- refCnt = 1;
-#if MULTITHREADED
- gInitMutex(&mutex);
-#endif
-}
-
-UnicodeMap::~UnicodeMap() {
- delete encodingName;
- if (kind == unicodeMapUser && ranges) {
- gfree(ranges);
- }
- if (eMaps) {
- gfree(eMaps);
- }
-#if MULTITHREADED
- gDestroyMutex(&mutex);
-#endif
-}
-
-void UnicodeMap::incRefCnt() {
-#if MULTITHREADED
- gLockMutex(&mutex);
-#endif
- ++refCnt;
-#if MULTITHREADED
- gUnlockMutex(&mutex);
-#endif
-}
-
-void UnicodeMap::decRefCnt() {
- GBool done;
-
-#if MULTITHREADED
- gLockMutex(&mutex);
-#endif
- done = --refCnt == 0;
-#if MULTITHREADED
- gUnlockMutex(&mutex);
-#endif
- if (done) {
- delete this;
- }
-}
-
-GBool UnicodeMap::match(GString *encodingNameA) {
- return !encodingName->cmp(encodingNameA);
-}
-
-int UnicodeMap::mapUnicode(Unicode u, char *buf, int bufSize) {
- int a, b, m, n, i, j;
- Guint code;
-
- if (kind == unicodeMapFunc) {
- return (*func)(u, buf, bufSize);
- }
-
- a = 0;
- b = len;
- if (u >= ranges[a].start) {
- // invariant: ranges[a].start <= u < ranges[b].start
- while (b - a > 1) {
- m = (a + b) / 2;
- if (u >= ranges[m].start) {
- a = m;
- } else if (u < ranges[m].start) {
- b = m;
- }
- }
- if (u <= ranges[a].end) {
- n = ranges[a].nBytes;
- if (n > bufSize) {
- return 0;
- }
- code = ranges[a].code + (u - ranges[a].start);
- for (i = n - 1; i >= 0; --i) {
- buf[i] = (char)(code & 0xff);
- code >>= 8;
- }
- return n;
- }
- }
-
- for (i = 0; i < eMapsLen; ++i) {
- if (eMaps[i].u == u) {
- n = eMaps[i].nBytes;
- for (j = 0; j < n; ++j) {
- buf[j] = eMaps[i].code[j];
- }
- return n;
- }
- }
-
- return 0;
-}
-
-//------------------------------------------------------------------------
-
-UnicodeMapCache::UnicodeMapCache() {
- int i;
-
- for (i = 0; i < unicodeMapCacheSize; ++i) {
- cache[i] = NULL;
- }
-}
-
-UnicodeMapCache::~UnicodeMapCache() {
- int i;
-
- for (i = 0; i < unicodeMapCacheSize; ++i) {
- if (cache[i]) {
- cache[i]->decRefCnt();
- }
- }
-}
-
-UnicodeMap *UnicodeMapCache::getUnicodeMap(GString *encodingName) {
- UnicodeMap *map;
- int i, j;
-
- if (cache[0] && cache[0]->match(encodingName)) {
- cache[0]->incRefCnt();
- return cache[0];
- }
- for (i = 1; i < unicodeMapCacheSize; ++i) {
- if (cache[i] && cache[i]->match(encodingName)) {
- map = cache[i];
- for (j = i; j >= 1; --j) {
- cache[j] = cache[j - 1];
- }
- cache[0] = map;
- map->incRefCnt();
- return map;
- }
- }
- if ((map = UnicodeMap::parse(encodingName))) {
- if (cache[unicodeMapCacheSize - 1]) {
- cache[unicodeMapCacheSize - 1]->decRefCnt();
- }
- for (j = unicodeMapCacheSize - 1; j >= 1; --j) {
- cache[j] = cache[j - 1];
- }
- cache[0] = map;
- map->incRefCnt();
- return map;
- }
- return NULL;
-}
+++ /dev/null
-//========================================================================
-//
-// UnicodeMap.h
-//
-// Mapping from Unicode to an encoding.
-//
-// Copyright 2001-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#ifndef UNICODEMAP_H
-#define UNICODEMAP_H
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma interface
-#endif
-
-#include "gtypes.h"
-#include "CharTypes.h"
-
-#if MULTITHREADED
-#include "GMutex.h"
-#endif
-
-class GString;
-
-//------------------------------------------------------------------------
-
-enum UnicodeMapKind {
- unicodeMapUser, // read from a file
- unicodeMapResident, // static list of ranges
- unicodeMapFunc // function pointer
-};
-
-typedef int (*UnicodeMapFunc)(Unicode u, char *buf, int bufSize);
-
-struct UnicodeMapRange {
- Unicode start, end; // range of Unicode chars
- Guint code, nBytes; // first output code
-};
-
-struct UnicodeMapExt;
-
-//------------------------------------------------------------------------
-
-class UnicodeMap {
-public:
-
- // Create the UnicodeMap specified by <encodingName>. Sets the
- // initial reference count to 1. Returns NULL on failure.
- static UnicodeMap *parse(GString *encodingNameA);
-
- // Create a resident UnicodeMap.
- UnicodeMap(char *encodingNameA, GBool unicodeOutA,
- UnicodeMapRange *rangesA, int lenA);
-
- // Create a resident UnicodeMap that uses a function instead of a
- // list of ranges.
- UnicodeMap(char *encodingNameA, GBool unicodeOutA,
- UnicodeMapFunc funcA);
-
- ~UnicodeMap();
-
- void incRefCnt();
- void decRefCnt();
-
- GString *getEncodingName() { return encodingName; }
-
- GBool isUnicode() { return unicodeOut; }
-
- // Return true if this UnicodeMap matches the specified
- // <encodingNameA>.
- GBool match(GString *encodingNameA);
-
- // Map Unicode to the target encoding. Fills in <buf> with the
- // output and returns the number of bytes used. Output will be
- // truncated at <bufSize> bytes. No string terminator is written.
- // Returns 0 if no mapping is found.
- int mapUnicode(Unicode u, char *buf, int bufSize);
-
-private:
-
- UnicodeMap(GString *encodingNameA);
-
- GString *encodingName;
- UnicodeMapKind kind;
- GBool unicodeOut;
- union {
- UnicodeMapRange *ranges; // (user, resident)
- UnicodeMapFunc func; // (func)
- };
- int len; // (user, resident)
- UnicodeMapExt *eMaps; // (user)
- int eMapsLen; // (user)
- int refCnt;
-#if MULTITHREADED
- GMutex mutex;
-#endif
-};
-
-//------------------------------------------------------------------------
-
-#define unicodeMapCacheSize 4
-
-class UnicodeMapCache {
-public:
-
- UnicodeMapCache();
- ~UnicodeMapCache();
-
- // Get the UnicodeMap for <encodingName>. Increments its reference
- // count; there will be one reference for the cache plus one for the
- // caller of this function. Returns NULL on failure.
- UnicodeMap *getUnicodeMap(GString *encodingName);
-
-private:
-
- UnicodeMap *cache[unicodeMapCacheSize];
-};
-
-#endif
+++ /dev/null
-//========================================================================
-//
-// UnicodeMapTables.h
-//
-// Copyright 2001-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-static UnicodeMapRange latin1UnicodeMapRanges[] = {
- { 0x000a, 0x000a, 0x0a, 1 },
- { 0x000c, 0x000d, 0x0c, 1 },
- { 0x0020, 0x007e, 0x20, 1 },
- { 0x00a0, 0x00a0, 0x20, 1 },
- { 0x00a1, 0x00ac, 0xa1, 1 },
- { 0x00ae, 0x00ff, 0xae, 1 },
- { 0x010c, 0x010c, 0x43, 1 },
- { 0x010d, 0x010d, 0x63, 1 },
- { 0x0131, 0x0131, 0x69, 1 },
- { 0x0141, 0x0141, 0x4c, 1 },
- { 0x0142, 0x0142, 0x6c, 1 },
- { 0x0152, 0x0152, 0x4f45, 2 },
- { 0x0153, 0x0153, 0x6f65, 2 },
- { 0x0160, 0x0160, 0x53, 1 },
- { 0x0161, 0x0161, 0x73, 1 },
- { 0x0178, 0x0178, 0x59, 1 },
- { 0x017d, 0x017d, 0x5a, 1 },
- { 0x017e, 0x017e, 0x7a, 1 },
- { 0x02c6, 0x02c6, 0x5e, 1 },
- { 0x02da, 0x02da, 0xb0, 1 },
- { 0x02dc, 0x02dc, 0x7e, 1 },
- { 0x2013, 0x2013, 0xad, 1 },
- { 0x2014, 0x2014, 0x2d2d, 2 },
- { 0x2018, 0x2018, 0x60, 1 },
- { 0x2019, 0x2019, 0x27, 1 },
- { 0x201a, 0x201a, 0x2c, 1 },
- { 0x201c, 0x201c, 0x22, 1 },
- { 0x201d, 0x201d, 0x22, 1 },
- { 0x201e, 0x201e, 0x2c2c, 2 },
- { 0x2022, 0x2022, 0xb7, 1 },
- { 0x2026, 0x2026, 0x2e2e2e, 3 },
- { 0x2039, 0x2039, 0x3c, 1 },
- { 0x203a, 0x203a, 0x3e, 1 },
- { 0x2044, 0x2044, 0x2f, 1 },
- { 0x2122, 0x2122, 0x544d, 2 },
- { 0x2212, 0x2212, 0x2d, 1 },
- { 0xf6f9, 0xf6f9, 0x4c, 1 },
- { 0xf6fa, 0xf6fa, 0x4f45, 2 },
- { 0xf6fc, 0xf6fc, 0xb0, 1 },
- { 0xf6fd, 0xf6fd, 0x53, 1 },
- { 0xf6fe, 0xf6fe, 0x7e, 1 },
- { 0xf6ff, 0xf6ff, 0x5a, 1 },
- { 0xf721, 0xf721, 0x21, 1 },
- { 0xf724, 0xf724, 0x24, 1 },
- { 0xf726, 0xf726, 0x26, 1 },
- { 0xf730, 0xf739, 0x30, 1 },
- { 0xf73f, 0xf73f, 0x3f, 1 },
- { 0xf761, 0xf77a, 0x41, 1 },
- { 0xf7a1, 0xf7a2, 0xa1, 1 },
- { 0xf7bf, 0xf7bf, 0xbf, 1 },
- { 0xf7e0, 0xf7f6, 0xc0, 1 },
- { 0xf7f8, 0xf7fe, 0xd8, 1 },
- { 0xf7ff, 0xf7ff, 0x59, 1 },
- { 0xfb00, 0xfb00, 0x6666, 2 },
- { 0xfb01, 0xfb01, 0x6669, 2 },
- { 0xfb02, 0xfb02, 0x666c, 2 },
- { 0xfb03, 0xfb03, 0x666669, 3 },
- { 0xfb04, 0xfb04, 0x66666c, 3 }
-};
-#define latin1UnicodeMapLen (sizeof(latin1UnicodeMapRanges) / sizeof(UnicodeMapRange))
-
-static UnicodeMapRange ascii7UnicodeMapRanges[] = {
- { 0x000a, 0x000a, 0x0a, 1 },
- { 0x000c, 0x000d, 0x0c, 1 },
- { 0x0020, 0x005f, 0x20, 1 },
- { 0x0061, 0x007e, 0x61, 1 },
- { 0x00a6, 0x00a6, 0x7c, 1 },
- { 0x00a9, 0x00a9, 0x286329, 3 },
- { 0x00ae, 0x00ae, 0x285229, 3 },
- { 0x00b7, 0x00b7, 0x2a, 1 },
- { 0x00bc, 0x00bc, 0x312f34, 3 },
- { 0x00bd, 0x00bd, 0x312f32, 3 },
- { 0x00be, 0x00be, 0x332f34, 3 },
- { 0x00c0, 0x00c0, 0x41, 1 },
- { 0x00c1, 0x00c1, 0x41, 1 },
- { 0x00c2, 0x00c2, 0x41, 1 },
- { 0x00c3, 0x00c3, 0x41, 1 },
- { 0x00c4, 0x00c4, 0x41, 1 },
- { 0x00c5, 0x00c5, 0x41, 1 },
- { 0x00c6, 0x00c6, 0x4145, 2 },
- { 0x00c7, 0x00c7, 0x43, 1 },
- { 0x00c8, 0x00c8, 0x45, 1 },
- { 0x00c9, 0x00c9, 0x45, 1 },
- { 0x00ca, 0x00ca, 0x45, 1 },
- { 0x00cb, 0x00cb, 0x45, 1 },
- { 0x00cc, 0x00cc, 0x49, 1 },
- { 0x00cd, 0x00cd, 0x49, 1 },
- { 0x00ce, 0x00ce, 0x49, 1 },
- { 0x00cf, 0x00cf, 0x49, 1 },
- { 0x00d1, 0x00d2, 0x4e, 1 },
- { 0x00d3, 0x00d3, 0x4f, 1 },
- { 0x00d4, 0x00d4, 0x4f, 1 },
- { 0x00d5, 0x00d5, 0x4f, 1 },
- { 0x00d6, 0x00d6, 0x4f, 1 },
- { 0x00d7, 0x00d7, 0x78, 1 },
- { 0x00d8, 0x00d8, 0x4f, 1 },
- { 0x00d9, 0x00d9, 0x55, 1 },
- { 0x00da, 0x00da, 0x55, 1 },
- { 0x00db, 0x00db, 0x55, 1 },
- { 0x00dc, 0x00dc, 0x55, 1 },
- { 0x00dd, 0x00dd, 0x59, 1 },
- { 0x00e0, 0x00e0, 0x61, 1 },
- { 0x00e1, 0x00e1, 0x61, 1 },
- { 0x00e2, 0x00e2, 0x61, 1 },
- { 0x00e3, 0x00e3, 0x61, 1 },
- { 0x00e4, 0x00e4, 0x61, 1 },
- { 0x00e5, 0x00e5, 0x61, 1 },
- { 0x00e6, 0x00e6, 0x6165, 2 },
- { 0x00e7, 0x00e7, 0x63, 1 },
- { 0x00e8, 0x00e8, 0x65, 1 },
- { 0x00e9, 0x00e9, 0x65, 1 },
- { 0x00ea, 0x00ea, 0x65, 1 },
- { 0x00eb, 0x00eb, 0x65, 1 },
- { 0x00ec, 0x00ec, 0x69, 1 },
- { 0x00ed, 0x00ed, 0x69, 1 },
- { 0x00ee, 0x00ee, 0x69, 1 },
- { 0x00ef, 0x00ef, 0x69, 1 },
- { 0x00f1, 0x00f2, 0x6e, 1 },
- { 0x00f3, 0x00f3, 0x6f, 1 },
- { 0x00f4, 0x00f4, 0x6f, 1 },
- { 0x00f5, 0x00f5, 0x6f, 1 },
- { 0x00f6, 0x00f6, 0x6f, 1 },
- { 0x00f7, 0x00f7, 0x2f, 1 },
- { 0x00f8, 0x00f8, 0x6f, 1 },
- { 0x00f9, 0x00f9, 0x75, 1 },
- { 0x00fa, 0x00fa, 0x75, 1 },
- { 0x00fb, 0x00fb, 0x75, 1 },
- { 0x00fc, 0x00fc, 0x75, 1 },
- { 0x00fd, 0x00fd, 0x79, 1 },
- { 0x00ff, 0x00ff, 0x79, 1 },
- { 0x0131, 0x0131, 0x69, 1 },
- { 0x0141, 0x0141, 0x4c, 1 },
- { 0x0152, 0x0152, 0x4f45, 2 },
- { 0x0153, 0x0153, 0x6f65, 2 },
- { 0x0160, 0x0160, 0x53, 1 },
- { 0x0178, 0x0178, 0x59, 1 },
- { 0x017d, 0x017d, 0x5a, 1 },
- { 0x2013, 0x2013, 0x2d, 1 },
- { 0x2014, 0x2014, 0x2d2d, 2 },
- { 0x2018, 0x2018, 0x60, 1 },
- { 0x2019, 0x2019, 0x27, 1 },
- { 0x201c, 0x201c, 0x22, 1 },
- { 0x201d, 0x201d, 0x22, 1 },
- { 0x2022, 0x2022, 0x2a, 1 },
- { 0x2026, 0x2026, 0x2e2e2e, 3 },
- { 0x2122, 0x2122, 0x544d, 2 },
- { 0x2212, 0x2212, 0x2d, 1 },
- { 0xf6f9, 0xf6f9, 0x4c, 1 },
- { 0xf6fa, 0xf6fa, 0x4f45, 2 },
- { 0xf6fd, 0xf6fd, 0x53, 1 },
- { 0xf6fe, 0xf6fe, 0x7e, 1 },
- { 0xf6ff, 0xf6ff, 0x5a, 1 },
- { 0xf721, 0xf721, 0x21, 1 },
- { 0xf724, 0xf724, 0x24, 1 },
- { 0xf726, 0xf726, 0x26, 1 },
- { 0xf730, 0xf739, 0x30, 1 },
- { 0xf73f, 0xf73f, 0x3f, 1 },
- { 0xf761, 0xf77a, 0x41, 1 },
- { 0xf7e0, 0xf7e0, 0x41, 1 },
- { 0xf7e1, 0xf7e1, 0x41, 1 },
- { 0xf7e2, 0xf7e2, 0x41, 1 },
- { 0xf7e3, 0xf7e3, 0x41, 1 },
- { 0xf7e4, 0xf7e4, 0x41, 1 },
- { 0xf7e5, 0xf7e5, 0x41, 1 },
- { 0xf7e6, 0xf7e6, 0x4145, 2 },
- { 0xf7e7, 0xf7e7, 0x43, 1 },
- { 0xf7e8, 0xf7e8, 0x45, 1 },
- { 0xf7e9, 0xf7e9, 0x45, 1 },
- { 0xf7ea, 0xf7ea, 0x45, 1 },
- { 0xf7eb, 0xf7eb, 0x45, 1 },
- { 0xf7ec, 0xf7ec, 0x49, 1 },
- { 0xf7ed, 0xf7ed, 0x49, 1 },
- { 0xf7ee, 0xf7ee, 0x49, 1 },
- { 0xf7ef, 0xf7ef, 0x49, 1 },
- { 0xf7f1, 0xf7f2, 0x4e, 1 },
- { 0xf7f3, 0xf7f3, 0x4f, 1 },
- { 0xf7f4, 0xf7f4, 0x4f, 1 },
- { 0xf7f5, 0xf7f5, 0x4f, 1 },
- { 0xf7f6, 0xf7f6, 0x4f, 1 },
- { 0xf7f8, 0xf7f8, 0x4f, 1 },
- { 0xf7f9, 0xf7f9, 0x55, 1 },
- { 0xf7fa, 0xf7fa, 0x55, 1 },
- { 0xf7fb, 0xf7fb, 0x55, 1 },
- { 0xf7fc, 0xf7fc, 0x55, 1 },
- { 0xf7fd, 0xf7fd, 0x59, 1 },
- { 0xf7ff, 0xf7ff, 0x59, 1 },
- { 0xfb00, 0xfb00, 0x6666, 2 },
- { 0xfb01, 0xfb01, 0x6669, 2 },
- { 0xfb02, 0xfb02, 0x666c, 2 },
- { 0xfb03, 0xfb03, 0x666669, 3 },
- { 0xfb04, 0xfb04, 0x66666c, 3 }
-};
-#define ascii7UnicodeMapLen (sizeof(ascii7UnicodeMapRanges) / sizeof(UnicodeMapRange))
-
-static UnicodeMapRange symbolUnicodeMapRanges[] = {
- { 0x0020, 0x0021, 0x20, 1 },
- { 0x0023, 0x0023, 0x23, 1 },
- { 0x0025, 0x0026, 0x25, 1 },
- { 0x0028, 0x0029, 0x28, 1 },
- { 0x002b, 0x002c, 0x2b, 1 },
- { 0x002e, 0x003f, 0x2e, 1 },
- { 0x005b, 0x005b, 0x5b, 1 },
- { 0x005d, 0x005d, 0x5d, 1 },
- { 0x005f, 0x005f, 0x5f, 1 },
- { 0x007b, 0x007d, 0x7b, 1 },
- { 0x00ac, 0x00ac, 0xd8, 1 },
- { 0x00b0, 0x00b1, 0xb0, 1 },
- { 0x00b5, 0x00b5, 0x6d, 1 },
- { 0x00d7, 0x00d7, 0xb4, 1 },
- { 0x00f7, 0x00f7, 0xb8, 1 },
- { 0x0192, 0x0192, 0xa6, 1 },
- { 0x0391, 0x0392, 0x41, 1 },
- { 0x0393, 0x0393, 0x47, 1 },
- { 0x0395, 0x0395, 0x45, 1 },
- { 0x0396, 0x0396, 0x5a, 1 },
- { 0x0397, 0x0397, 0x48, 1 },
- { 0x0398, 0x0398, 0x51, 1 },
- { 0x0399, 0x0399, 0x49, 1 },
- { 0x039a, 0x039d, 0x4b, 1 },
- { 0x039e, 0x039e, 0x58, 1 },
- { 0x039f, 0x03a0, 0x4f, 1 },
- { 0x03a1, 0x03a1, 0x52, 1 },
- { 0x03a3, 0x03a5, 0x53, 1 },
- { 0x03a6, 0x03a6, 0x46, 1 },
- { 0x03a7, 0x03a7, 0x43, 1 },
- { 0x03a8, 0x03a8, 0x59, 1 },
- { 0x03b1, 0x03b2, 0x61, 1 },
- { 0x03b3, 0x03b3, 0x67, 1 },
- { 0x03b4, 0x03b5, 0x64, 1 },
- { 0x03b6, 0x03b6, 0x7a, 1 },
- { 0x03b7, 0x03b7, 0x68, 1 },
- { 0x03b8, 0x03b8, 0x71, 1 },
- { 0x03b9, 0x03b9, 0x69, 1 },
- { 0x03ba, 0x03bb, 0x6b, 1 },
- { 0x03bd, 0x03bd, 0x6e, 1 },
- { 0x03be, 0x03be, 0x78, 1 },
- { 0x03bf, 0x03c0, 0x6f, 1 },
- { 0x03c1, 0x03c1, 0x72, 1 },
- { 0x03c2, 0x03c2, 0x56, 1 },
- { 0x03c3, 0x03c5, 0x73, 1 },
- { 0x03c6, 0x03c6, 0x66, 1 },
- { 0x03c7, 0x03c7, 0x63, 1 },
- { 0x03c8, 0x03c8, 0x79, 1 },
- { 0x03c9, 0x03c9, 0x77, 1 },
- { 0x03d1, 0x03d1, 0x4a, 1 },
- { 0x03d2, 0x03d2, 0xa1, 1 },
- { 0x03d5, 0x03d5, 0x6a, 1 },
- { 0x03d6, 0x03d6, 0x76, 1 },
- { 0x2022, 0x2022, 0xb7, 1 },
- { 0x2026, 0x2026, 0xbc, 1 },
- { 0x2032, 0x2032, 0xa2, 1 },
- { 0x2033, 0x2033, 0xb2, 1 },
- { 0x2044, 0x2044, 0xa4, 1 },
- { 0x2111, 0x2111, 0xc1, 1 },
- { 0x2118, 0x2118, 0xc3, 1 },
- { 0x211c, 0x211c, 0xc2, 1 },
- { 0x2126, 0x2126, 0x57, 1 },
- { 0x2135, 0x2135, 0xc0, 1 },
- { 0x2190, 0x2193, 0xac, 1 },
- { 0x2194, 0x2194, 0xab, 1 },
- { 0x21b5, 0x21b5, 0xbf, 1 },
- { 0x21d0, 0x21d3, 0xdc, 1 },
- { 0x21d4, 0x21d4, 0xdb, 1 },
- { 0x2200, 0x2200, 0x22, 1 },
- { 0x2202, 0x2202, 0xb6, 1 },
- { 0x2203, 0x2203, 0x24, 1 },
- { 0x2205, 0x2205, 0xc6, 1 },
- { 0x2206, 0x2206, 0x44, 1 },
- { 0x2207, 0x2207, 0xd1, 1 },
- { 0x2208, 0x2209, 0xce, 1 },
- { 0x220b, 0x220b, 0x27, 1 },
- { 0x220f, 0x220f, 0xd5, 1 },
- { 0x2211, 0x2211, 0xe5, 1 },
- { 0x2212, 0x2212, 0x2d, 1 },
- { 0x2217, 0x2217, 0x2a, 1 },
- { 0x221a, 0x221a, 0xd6, 1 },
- { 0x221d, 0x221d, 0xb5, 1 },
- { 0x221e, 0x221e, 0xa5, 1 },
- { 0x2220, 0x2220, 0xd0, 1 },
- { 0x2227, 0x2228, 0xd9, 1 },
- { 0x2229, 0x222a, 0xc7, 1 },
- { 0x222b, 0x222b, 0xf2, 1 },
- { 0x2234, 0x2234, 0x5c, 1 },
- { 0x223c, 0x223c, 0x7e, 1 },
- { 0x2245, 0x2245, 0x40, 1 },
- { 0x2248, 0x2248, 0xbb, 1 },
- { 0x2260, 0x2261, 0xb9, 1 },
- { 0x2264, 0x2264, 0xa3, 1 },
- { 0x2265, 0x2265, 0xb3, 1 },
- { 0x2282, 0x2282, 0xcc, 1 },
- { 0x2283, 0x2283, 0xc9, 1 },
- { 0x2284, 0x2284, 0xcb, 1 },
- { 0x2286, 0x2286, 0xcd, 1 },
- { 0x2287, 0x2287, 0xca, 1 },
- { 0x2295, 0x2295, 0xc5, 1 },
- { 0x2297, 0x2297, 0xc4, 1 },
- { 0x22a5, 0x22a5, 0x5e, 1 },
- { 0x22c5, 0x22c5, 0xd7, 1 },
- { 0x2320, 0x2320, 0xf3, 1 },
- { 0x2321, 0x2321, 0xf5, 1 },
- { 0x2329, 0x2329, 0xe1, 1 },
- { 0x232a, 0x232a, 0xf1, 1 },
- { 0x25ca, 0x25ca, 0xe0, 1 },
- { 0x2660, 0x2660, 0xaa, 1 },
- { 0x2663, 0x2663, 0xa7, 1 },
- { 0x2665, 0x2665, 0xa9, 1 },
- { 0x2666, 0x2666, 0xa8, 1 },
- { 0xf6d9, 0xf6d9, 0xd3, 1 },
- { 0xf6da, 0xf6da, 0xd2, 1 },
- { 0xf6db, 0xf6db, 0xd4, 1 },
- { 0xf8e5, 0xf8e5, 0x60, 1 },
- { 0xf8e6, 0xf8e7, 0xbd, 1 },
- { 0xf8e8, 0xf8ea, 0xe2, 1 },
- { 0xf8eb, 0xf8f4, 0xe6, 1 },
- { 0xf8f5, 0xf8f5, 0xf4, 1 },
- { 0xf8f6, 0xf8fe, 0xf6, 1 }
-};
-#define symbolUnicodeMapLen (sizeof(symbolUnicodeMapRanges) / sizeof(UnicodeMapRange))
-
-static UnicodeMapRange zapfDingbatsUnicodeMapRanges[] = {
- { 0x0020, 0x0020, 0x20, 1 },
- { 0x2192, 0x2192, 0xd5, 1 },
- { 0x2194, 0x2195, 0xd6, 1 },
- { 0x2460, 0x2469, 0xac, 1 },
- { 0x25a0, 0x25a0, 0x6e, 1 },
- { 0x25b2, 0x25b2, 0x73, 1 },
- { 0x25bc, 0x25bc, 0x74, 1 },
- { 0x25c6, 0x25c6, 0x75, 1 },
- { 0x25cf, 0x25cf, 0x6c, 1 },
- { 0x25d7, 0x25d7, 0x77, 1 },
- { 0x2605, 0x2605, 0x48, 1 },
- { 0x260e, 0x260e, 0x25, 1 },
- { 0x261b, 0x261b, 0x2a, 1 },
- { 0x261e, 0x261e, 0x2b, 1 },
- { 0x2660, 0x2660, 0xab, 1 },
- { 0x2663, 0x2663, 0xa8, 1 },
- { 0x2665, 0x2665, 0xaa, 1 },
- { 0x2666, 0x2666, 0xa9, 1 },
- { 0x2701, 0x2704, 0x21, 1 },
- { 0x2706, 0x2709, 0x26, 1 },
- { 0x270c, 0x2727, 0x2c, 1 },
- { 0x2729, 0x274b, 0x49, 1 },
- { 0x274d, 0x274d, 0x6d, 1 },
- { 0x274f, 0x2752, 0x6f, 1 },
- { 0x2756, 0x2756, 0x76, 1 },
- { 0x2758, 0x275e, 0x78, 1 },
- { 0x2761, 0x2767, 0xa1, 1 },
- { 0x2776, 0x2794, 0xb6, 1 },
- { 0x2798, 0x27af, 0xd8, 1 },
- { 0x27b1, 0x27be, 0xf1, 1 }
-};
-#define zapfDingbatsUnicodeMapLen (sizeof(zapfDingbatsUnicodeMapRanges) / sizeof(UnicodeMapRange))
+++ /dev/null
-//========================================================================
-//
-// XRef.cc
-//
-// Copyright 1996-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma implementation
-#endif
-
-#include <stdlib.h>
-#include <stddef.h>
-#include <string.h>
-#include <ctype.h>
-#include "gmem.h"
-#include "Object.h"
-#include "Stream.h"
-#include "Lexer.h"
-#include "Parser.h"
-#include "Dict.h"
-#include "Error.h"
-#include "ErrorCodes.h"
-#include "XRef.h"
-
-//------------------------------------------------------------------------
-
-#define xrefSearchSize 1024 // read this many bytes at end of file
- // to look for 'startxref'
-
-//------------------------------------------------------------------------
-// Permission bits
-//------------------------------------------------------------------------
-
-#define permPrint (1<<2)
-#define permChange (1<<3)
-#define permCopy (1<<4)
-#define permNotes (1<<5)
-#define defPermFlags 0xfffc
-
-//------------------------------------------------------------------------
-// ObjectStream
-//------------------------------------------------------------------------
-
-class ObjectStream {
-public:
-
- // Create an object stream, using object number <objStrNum>,
- // generation 0.
- ObjectStream(XRef *xref, int objStrNumA);
-
- ~ObjectStream();
-
- // Return the object number of this object stream.
- int getObjStrNum() { return objStrNum; }
-
- // Get the <objIdx>th object from this stream, which should be
- // object number <objNum>, generation 0.
- Object *getObject(int objIdx, int objNum, Object *obj);
-
-private:
-
- int objStrNum; // object number of the object stream
- int nObjects; // number of objects in the stream
- Object *objs; // the objects (length = nObjects)
- int *objNums; // the object numbers (length = nObjects)
-};
-
-ObjectStream::ObjectStream(XRef *xref, int objStrNumA) {
- Stream *str;
- Parser *parser;
- int *offsets;
- Object objStr, obj1, obj2;
- int first, i;
-
- objStrNum = objStrNumA;
- nObjects = 0;
- objs = NULL;
- objNums = NULL;
-
- if (!xref->fetch(objStrNum, 0, &objStr)->isStream()) {
- goto err1;
- }
-
- if (!objStr.streamGetDict()->lookup("N", &obj1)->isInt()) {
- obj1.free();
- goto err1;
- }
- nObjects = obj1.getInt();
- obj1.free();
- if (nObjects <= 0) {
- goto err1;
- }
-
- if (!objStr.streamGetDict()->lookup("First", &obj1)->isInt()) {
- obj1.free();
- goto err1;
- }
- first = obj1.getInt();
- obj1.free();
- if (first < 0) {
- goto err1;
- }
-
- objs = new Object[nObjects];
- objNums = (int *)gmallocn(nObjects, sizeof(int));
- offsets = (int *)gmallocn(nObjects, sizeof(int));
-
- // parse the header: object numbers and offsets
- objStr.streamReset();
- obj1.initNull();
- str = new EmbedStream(objStr.getStream(), &obj1, gTrue, first);
- parser = new Parser(xref, new Lexer(xref, str));
- for (i = 0; i < nObjects; ++i) {
- parser->getObj(&obj1);
- parser->getObj(&obj2);
- if (!obj1.isInt() || !obj2.isInt()) {
- obj1.free();
- obj2.free();
- delete parser;
- gfree(offsets);
- goto err1;
- }
- objNums[i] = obj1.getInt();
- offsets[i] = obj2.getInt();
- obj1.free();
- obj2.free();
- if (objNums[i] < 0 || offsets[i] < 0 ||
- (i > 0 && offsets[i] < offsets[i-1])) {
- delete parser;
- gfree(offsets);
- goto err1;
- }
- }
- while (str->getChar() != EOF) ;
- delete parser;
-
- // skip to the first object - this shouldn't be necessary because
- // the First key is supposed to be equal to offsets[0], but just in
- // case...
- for (i = first; i < offsets[0]; ++i) {
- objStr.getStream()->getChar();
- }
-
- // parse the objects
- for (i = 0; i < nObjects; ++i) {
- obj1.initNull();
- if (i == nObjects - 1) {
- str = new EmbedStream(objStr.getStream(), &obj1, gFalse, 0);
- } else {
- str = new EmbedStream(objStr.getStream(), &obj1, gTrue,
- offsets[i+1] - offsets[i]);
- }
- parser = new Parser(xref, new Lexer(xref, str));
- parser->getObj(&objs[i]);
- while (str->getChar() != EOF) ;
- delete parser;
- }
-
- gfree(offsets);
-
- err1:
- objStr.free();
- return;
-}
-
-ObjectStream::~ObjectStream() {
- int i;
-
- if (objs) {
- for (i = 0; i < nObjects; ++i) {
- objs[i].free();
- }
- delete[] objs;
- }
- gfree(objNums);
-}
-
-Object *ObjectStream::getObject(int objIdx, int objNum, Object *obj) {
- if (objIdx < 0 || objIdx >= nObjects || objNum != objNums[objIdx]) {
- return obj->initNull();
- }
- return objs[objIdx].copy(obj);
-}
-
-//------------------------------------------------------------------------
-// XRef
-//------------------------------------------------------------------------
-
-XRef::XRef(BaseStream *strA) {
- Guint pos;
- Object obj;
-
- ok = gTrue;
- errCode = errNone;
- size = 0;
- entries = NULL;
- streamEnds = NULL;
- streamEndsLen = 0;
- objStr = NULL;
-
- encrypted = gFalse;
- permFlags = defPermFlags;
- ownerPasswordOk = gFalse;
-
- // read the trailer
- str = strA;
- start = str->getStart();
- pos = getStartXref();
-
- // if there was a problem with the 'startxref' position, try to
- // reconstruct the xref table
- if (pos == 0) {
- if (!(ok = constructXRef())) {
- errCode = errDamaged;
- return;
- }
-
- // read the xref table
- } else {
- while (readXRef(&pos)) ;
-
- // if there was a problem with the xref table,
- // try to reconstruct it
- if (!ok) {
- if (!(ok = constructXRef())) {
- errCode = errDamaged;
- return;
- }
- }
- }
-
- // get the root dictionary (catalog) object
- trailerDict.dictLookupNF("Root", &obj);
- if (obj.isRef()) {
- rootNum = obj.getRefNum();
- rootGen = obj.getRefGen();
- obj.free();
- } else {
- obj.free();
- if (!(ok = constructXRef())) {
- errCode = errDamaged;
- return;
- }
- }
-
- // now set the trailer dictionary's xref pointer so we can fetch
- // indirect objects from it
- trailerDict.getDict()->setXRef(this);
-}
-
-XRef::~XRef() {
- gfree(entries);
- trailerDict.free();
- if (streamEnds) {
- gfree(streamEnds);
- }
- if (objStr) {
- delete objStr;
- }
-}
-
-// Read the 'startxref' position.
-Guint XRef::getStartXref() {
- char buf[xrefSearchSize+1];
- char *p;
- int c, n, i;
-
- // read last xrefSearchSize bytes
- str->setPos(xrefSearchSize, -1);
- for (n = 0; n < xrefSearchSize; ++n) {
- if ((c = str->getChar()) == EOF) {
- break;
- }
- buf[n] = c;
- }
- buf[n] = '\0';
-
- // find startxref
- for (i = n - 9; i >= 0; --i) {
- if (!strncmp(&buf[i], "startxref", 9)) {
- break;
- }
- }
- if (i < 0) {
- return 0;
- }
- for (p = &buf[i+9]; isspace(*p); ++p) ;
- lastXRefPos = strToUnsigned(p);
-
- return lastXRefPos;
-}
-
-// Read one xref table section. Also reads the associated trailer
-// dictionary, and returns the prev pointer (if any).
-GBool XRef::readXRef(Guint *pos) {
- Parser *parser;
- Object obj;
- GBool more;
-
- // start up a parser, parse one token
- obj.initNull();
- parser = new Parser(NULL,
- new Lexer(NULL,
- str->makeSubStream(start + *pos, gFalse, 0, &obj)));
- parser->getObj(&obj);
-
- // parse an old-style xref table
- if (obj.isCmd("xref")) {
- obj.free();
- more = readXRefTable(parser, pos);
-
- // parse an xref stream
- } else if (obj.isInt()) {
- obj.free();
- if (!parser->getObj(&obj)->isInt()) {
- goto err1;
- }
- obj.free();
- if (!parser->getObj(&obj)->isCmd("obj")) {
- goto err1;
- }
- obj.free();
- if (!parser->getObj(&obj)->isStream()) {
- goto err1;
- }
- more = readXRefStream(obj.getStream(), pos);
- obj.free();
-
- } else {
- goto err1;
- }
-
- delete parser;
- return more;
-
- err1:
- obj.free();
- delete parser;
- ok = gFalse;
- return gFalse;
-}
-
-GBool XRef::readXRefTable(Parser *parser, Guint *pos) {
- XRefEntry entry;
- GBool more;
- Object obj, obj2;
- Guint pos2;
- int first, n, newSize, i;
-
- while (1) {
- parser->getObj(&obj);
- if (obj.isCmd("trailer")) {
- obj.free();
- break;
- }
- if (!obj.isInt()) {
- goto err1;
- }
- first = obj.getInt();
- obj.free();
- if (!parser->getObj(&obj)->isInt()) {
- goto err1;
- }
- n = obj.getInt();
- obj.free();
- if (first < 0 || n < 0 || first + n < 0) {
- goto err1;
- }
- if (first + n > size) {
- for (newSize = size ? 2 * size : 1024;
- first + n > newSize && newSize > 0;
- newSize <<= 1) ;
- if (newSize < 0) {
- goto err1;
- }
- entries = (XRefEntry *)greallocn(entries, newSize, sizeof(XRefEntry));
- for (i = size; i < newSize; ++i) {
- entries[i].offset = 0xffffffff;
- entries[i].type = xrefEntryFree;
- }
- size = newSize;
- }
- for (i = first; i < first + n; ++i) {
- if (!parser->getObj(&obj)->isInt()) {
- goto err1;
- }
- entry.offset = (Guint)obj.getInt();
- obj.free();
- if (!parser->getObj(&obj)->isInt()) {
- goto err1;
- }
- entry.gen = obj.getInt();
- obj.free();
- parser->getObj(&obj);
- if (obj.isCmd("n")) {
- entry.type = xrefEntryUncompressed;
- } else if (obj.isCmd("f")) {
- entry.type = xrefEntryFree;
- } else {
- goto err1;
- }
- obj.free();
- if (entries[i].offset == 0xffffffff) {
- entries[i] = entry;
- // PDF files of patents from the IBM Intellectual Property
- // Network have a bug: the xref table claims to start at 1
- // instead of 0.
- if (i == 1 && first == 1 &&
- entries[1].offset == 0 && entries[1].gen == 65535 &&
- entries[1].type == xrefEntryFree) {
- i = first = 0;
- entries[0] = entries[1];
- entries[1].offset = 0xffffffff;
- }
- }
- }
- }
-
- // read the trailer dictionary
- if (!parser->getObj(&obj)->isDict()) {
- goto err1;
- }
-
- // get the 'Prev' pointer
- obj.getDict()->lookupNF("Prev", &obj2);
- if (obj2.isInt()) {
- *pos = (Guint)obj2.getInt();
- more = gTrue;
- } else if (obj2.isRef()) {
- // certain buggy PDF generators generate "/Prev NNN 0 R" instead
- // of "/Prev NNN"
- *pos = (Guint)obj2.getRefNum();
- more = gTrue;
- } else {
- more = gFalse;
- }
- obj2.free();
-
- // save the first trailer dictionary
- if (trailerDict.isNone()) {
- obj.copy(&trailerDict);
- }
-
- // check for an 'XRefStm' key
- if (obj.getDict()->lookup("XRefStm", &obj2)->isInt()) {
- pos2 = (Guint)obj2.getInt();
- readXRef(&pos2);
- if (!ok) {
- obj2.free();
- goto err1;
- }
- }
- obj2.free();
-
- obj.free();
- return more;
-
- err1:
- obj.free();
- ok = gFalse;
- return gFalse;
-}
-
-GBool XRef::readXRefStream(Stream *xrefStr, Guint *pos) {
- Dict *dict;
- int w[3];
- GBool more;
- Object obj, obj2, idx;
- int newSize, first, n, i;
-
- dict = xrefStr->getDict();
-
- if (!dict->lookupNF("Size", &obj)->isInt()) {
- goto err1;
- }
- newSize = obj.getInt();
- obj.free();
- if (newSize < 0) {
- goto err1;
- }
- if (newSize > size) {
- entries = (XRefEntry *)greallocn(entries, newSize, sizeof(XRefEntry));
- for (i = size; i < newSize; ++i) {
- entries[i].offset = 0xffffffff;
- entries[i].type = xrefEntryFree;
- }
- size = newSize;
- }
-
- if (!dict->lookupNF("W", &obj)->isArray() ||
- obj.arrayGetLength() < 3) {
- goto err1;
- }
- for (i = 0; i < 3; ++i) {
- if (!obj.arrayGet(i, &obj2)->isInt()) {
- obj2.free();
- goto err1;
- }
- w[i] = obj2.getInt();
- obj2.free();
- if (w[i] < 0 || w[i] > 4) {
- goto err1;
- }
- }
- obj.free();
-
- xrefStr->reset();
- dict->lookupNF("Index", &idx);
- if (idx.isArray()) {
- for (i = 0; i+1 < idx.arrayGetLength(); i += 2) {
- if (!idx.arrayGet(i, &obj)->isInt()) {
- idx.free();
- goto err1;
- }
- first = obj.getInt();
- obj.free();
- if (!idx.arrayGet(i+1, &obj)->isInt()) {
- idx.free();
- goto err1;
- }
- n = obj.getInt();
- obj.free();
- if (first < 0 || n < 0 ||
- !readXRefStreamSection(xrefStr, w, first, n)) {
- idx.free();
- goto err0;
- }
- }
- } else {
- if (!readXRefStreamSection(xrefStr, w, 0, newSize)) {
- idx.free();
- goto err0;
- }
- }
- idx.free();
-
- dict->lookupNF("Prev", &obj);
- if (obj.isInt()) {
- *pos = (Guint)obj.getInt();
- more = gTrue;
- } else {
- more = gFalse;
- }
- obj.free();
- if (trailerDict.isNone()) {
- trailerDict.initDict(dict);
- }
-
- return more;
-
- err1:
- obj.free();
- err0:
- ok = gFalse;
- return gFalse;
-}
-
-GBool XRef::readXRefStreamSection(Stream *xrefStr, int *w, int first, int n) {
- Guint offset;
- int type, gen, c, newSize, i, j;
-
- if (first + n < 0) {
- return gFalse;
- }
- if (first + n > size) {
- for (newSize = size ? 2 * size : 1024;
- first + n > newSize && newSize > 0;
- newSize <<= 1) ;
- if (newSize < 0) {
- return gFalse;
- }
- entries = (XRefEntry *)greallocn(entries, newSize, sizeof(XRefEntry));
- for (i = size; i < newSize; ++i) {
- entries[i].offset = 0xffffffff;
- entries[i].type = xrefEntryFree;
- }
- size = newSize;
- }
- for (i = first; i < first + n; ++i) {
- if (w[0] == 0) {
- type = 1;
- } else {
- for (type = 0, j = 0; j < w[0]; ++j) {
- if ((c = xrefStr->getChar()) == EOF) {
- return gFalse;
- }
- type = (type << 8) + c;
- }
- }
- for (offset = 0, j = 0; j < w[1]; ++j) {
- if ((c = xrefStr->getChar()) == EOF) {
- return gFalse;
- }
- offset = (offset << 8) + c;
- }
- for (gen = 0, j = 0; j < w[2]; ++j) {
- if ((c = xrefStr->getChar()) == EOF) {
- return gFalse;
- }
- gen = (gen << 8) + c;
- }
- if (entries[i].offset == 0xffffffff) {
- switch (type) {
- case 0:
- entries[i].offset = offset;
- entries[i].gen = gen;
- entries[i].type = xrefEntryFree;
- break;
- case 1:
- entries[i].offset = offset;
- entries[i].gen = gen;
- entries[i].type = xrefEntryUncompressed;
- break;
- case 2:
- entries[i].offset = offset;
- entries[i].gen = gen;
- entries[i].type = xrefEntryCompressed;
- break;
- default:
- return gFalse;
- }
- }
- }
-
- return gTrue;
-}
-
-// Attempt to construct an xref table for a damaged file.
-GBool XRef::constructXRef() {
- Parser *parser;
- Object newTrailerDict, obj;
- char buf[256];
- Guint pos;
- int num, gen;
- int newSize;
- int streamEndsSize;
- char *p;
- int i;
- GBool gotRoot;
-
- gfree(entries);
- size = 0;
- entries = NULL;
-
- error(0, "PDF file is damaged - attempting to reconstruct xref table...");
- gotRoot = gFalse;
- streamEndsLen = streamEndsSize = 0;
-
- str->reset();
- while (1) {
- pos = str->getPos();
- if (!str->getLine(buf, 256)) {
- break;
- }
- p = buf;
-
- // got trailer dictionary
- if (!strncmp(p, "trailer", 7)) {
- obj.initNull();
- parser = new Parser(NULL,
- new Lexer(NULL,
- str->makeSubStream(pos + 7, gFalse, 0, &obj)));
- parser->getObj(&newTrailerDict);
- if (newTrailerDict.isDict()) {
- newTrailerDict.dictLookupNF("Root", &obj);
- if (obj.isRef()) {
- rootNum = obj.getRefNum();
- rootGen = obj.getRefGen();
- if (!trailerDict.isNone()) {
- trailerDict.free();
- }
- newTrailerDict.copy(&trailerDict);
- gotRoot = gTrue;
- }
- obj.free();
- }
- newTrailerDict.free();
- delete parser;
-
- // look for object
- } else if (isdigit(*p)) {
- num = atoi(p);
- if (num > 0) {
- do {
- ++p;
- } while (*p && isdigit(*p));
- if (isspace(*p)) {
- do {
- ++p;
- } while (*p && isspace(*p));
- if (isdigit(*p)) {
- gen = atoi(p);
- do {
- ++p;
- } while (*p && isdigit(*p));
- if (isspace(*p)) {
- do {
- ++p;
- } while (*p && isspace(*p));
- if (!strncmp(p, "obj", 3)) {
- if (num >= size) {
- newSize = (num + 1 + 255) & ~255;
- if (newSize < 0) {
- error(-1, "Bad object number");
- return gFalse;
- }
- entries = (XRefEntry *)
- greallocn(entries, newSize, sizeof(XRefEntry));
- for (i = size; i < newSize; ++i) {
- entries[i].offset = 0xffffffff;
- entries[i].type = xrefEntryFree;
- }
- size = newSize;
- }
- if (entries[num].type == xrefEntryFree ||
- gen >= entries[num].gen) {
- entries[num].offset = pos - start;
- entries[num].gen = gen;
- entries[num].type = xrefEntryUncompressed;
- }
- }
- }
- }
- }
- }
-
- } else if (!strncmp(p, "endstream", 9)) {
- if (streamEndsLen == streamEndsSize) {
- streamEndsSize += 64;
- streamEnds = (Guint *)greallocn(streamEnds,
- streamEndsSize, sizeof(int));
- }
- streamEnds[streamEndsLen++] = pos;
- }
- }
-
- if (gotRoot)
- return gTrue;
-
- error(-1, "Couldn't find trailer dictionary");
- return gFalse;
-}
-
-void XRef::setEncryption(int permFlagsA, GBool ownerPasswordOkA,
- Guchar *fileKeyA, int keyLengthA, int encVersionA) {
- int i;
-
- encrypted = gTrue;
- permFlags = permFlagsA;
- ownerPasswordOk = ownerPasswordOkA;
- if (keyLengthA <= 16) {
- keyLength = keyLengthA;
- } else {
- keyLength = 16;
- }
- for (i = 0; i < keyLength; ++i) {
- fileKey[i] = fileKeyA[i];
- }
- encVersion = encVersionA;
-}
-
-GBool XRef::okToPrint(GBool ignoreOwnerPW) {
- return (!ignoreOwnerPW && ownerPasswordOk) || (permFlags & permPrint);
-}
-
-GBool XRef::okToChange(GBool ignoreOwnerPW) {
- return (!ignoreOwnerPW && ownerPasswordOk) || (permFlags & permChange);
-}
-
-GBool XRef::okToCopy(GBool ignoreOwnerPW) {
- return (!ignoreOwnerPW && ownerPasswordOk) || (permFlags & permCopy);
-}
-
-GBool XRef::okToAddNotes(GBool ignoreOwnerPW) {
- return (!ignoreOwnerPW && ownerPasswordOk) || (permFlags & permNotes);
-}
-
-Object *XRef::fetch(int num, int gen, Object *obj) {
- XRefEntry *e;
- Parser *parser;
- Object obj1, obj2, obj3;
-
- // check for bogus ref - this can happen in corrupted PDF files
- if (num < 0 || num >= size) {
- goto err;
- }
-
- e = &entries[num];
- switch (e->type) {
-
- case xrefEntryUncompressed:
- if (e->gen != gen) {
- goto err;
- }
- obj1.initNull();
- parser = new Parser(this,
- new Lexer(this,
- str->makeSubStream(start + e->offset, gFalse, 0, &obj1)));
- parser->getObj(&obj1);
- parser->getObj(&obj2);
- parser->getObj(&obj3);
- if (!obj1.isInt() || obj1.getInt() != num ||
- !obj2.isInt() || obj2.getInt() != gen ||
- !obj3.isCmd("obj")) {
- obj1.free();
- obj2.free();
- obj3.free();
- delete parser;
- goto err;
- }
- parser->getObj(obj, encrypted ? fileKey : (Guchar *)NULL, keyLength,
- num, gen);
- obj1.free();
- obj2.free();
- obj3.free();
- delete parser;
- break;
-
- case xrefEntryCompressed:
- if (gen != 0) {
- goto err;
- }
- if (!objStr || objStr->getObjStrNum() != (int)e->offset) {
- if (objStr) {
- delete objStr;
- }
- objStr = new ObjectStream(this, e->offset);
- }
- objStr->getObject(e->gen, num, obj);
- break;
-
- default:
- goto err;
- }
-
- return obj;
-
- err:
- return obj->initNull();
-}
-
-Object *XRef::getDocInfo(Object *obj) {
- return trailerDict.dictLookup("Info", obj);
-}
-
-// Added for the pdftex project.
-Object *XRef::getDocInfoNF(Object *obj) {
- return trailerDict.dictLookupNF("Info", obj);
-}
-
-GBool XRef::getStreamEnd(Guint streamStart, Guint *streamEnd) {
- int a, b, m;
-
- if (streamEndsLen == 0 ||
- streamStart > streamEnds[streamEndsLen - 1]) {
- return gFalse;
- }
-
- a = -1;
- b = streamEndsLen - 1;
- // invariant: streamEnds[a] < streamStart <= streamEnds[b]
- while (b - a > 1) {
- m = (a + b) / 2;
- if (streamStart <= streamEnds[m]) {
- b = m;
- } else {
- a = m;
- }
- }
- *streamEnd = streamEnds[b];
- return gTrue;
-}
-
-Guint XRef::strToUnsigned(char *s) {
- Guint x;
- char *p;
- int i;
-
- x = 0;
- for (p = s, i = 0; *p && isdigit(*p) && i < 10; ++p, ++i) {
- x = 10 * x + (*p - '0');
- }
- return x;
-}
+++ /dev/null
-//========================================================================
-//
-// XRef.h
-//
-// Copyright 1996-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#ifndef XREF_H
-#define XREF_H
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma interface
-#endif
-
-#include "gtypes.h"
-#include "Object.h"
-
-class Dict;
-class Stream;
-class Parser;
-class ObjectStream;
-
-//------------------------------------------------------------------------
-// XRef
-//------------------------------------------------------------------------
-
-enum XRefEntryType {
- xrefEntryFree,
- xrefEntryUncompressed,
- xrefEntryCompressed
-};
-
-struct XRefEntry {
- Guint offset;
- int gen;
- XRefEntryType type;
-};
-
-class XRef {
-public:
-
- // Constructor. Read xref table from stream.
- XRef(BaseStream *strA);
-
- // Destructor.
- ~XRef();
-
- // Is xref table valid?
- GBool isOk() { return ok; }
-
- // Get the error code (if isOk() returns false).
- int getErrorCode() { return errCode; }
-
- // Set the encryption parameters.
- void setEncryption(int permFlagsA, GBool ownerPasswordOkA,
- Guchar *fileKeyA, int keyLengthA, int encVersionA);
-
- // Is the file encrypted?
- GBool isEncrypted() { return encrypted; }
-
- // Check various permissions.
- GBool okToPrint(GBool ignoreOwnerPW = gFalse);
- GBool okToChange(GBool ignoreOwnerPW = gFalse);
- GBool okToCopy(GBool ignoreOwnerPW = gFalse);
- GBool okToAddNotes(GBool ignoreOwnerPW = gFalse);
-
- // Get catalog object.
- Object *getCatalog(Object *obj) { return fetch(rootNum, rootGen, obj); }
-
- // Fetch an indirect reference.
- Object *fetch(int num, int gen, Object *obj);
-
- // Return the document's Info dictionary (if any).
- Object *getDocInfo(Object *obj);
- Object *getDocInfoNF(Object *obj);
-
- // Return the number of objects in the xref table.
- int getNumObjects() { return size; }
-
- // Return the offset of the last xref table.
- Guint getLastXRefPos() { return lastXRefPos; }
-
- // Return the catalog object reference.
- int getRootNum() { return rootNum; }
- int getRootGen() { return rootGen; }
-
- // Get end position for a stream in a damaged file.
- // Returns false if unknown or file is not damaged.
- GBool getStreamEnd(Guint streamStart, Guint *streamEnd);
-
- // Direct access.
- int getSize() { return size; }
- XRefEntry *getEntry(int i) { return &entries[i]; }
- Object *getTrailerDict() { return &trailerDict; }
-
-private:
-
- BaseStream *str; // input stream
- Guint start; // offset in file (to allow for garbage
- // at beginning of file)
- XRefEntry *entries; // xref entries
- int size; // size of <entries> array
- int rootNum, rootGen; // catalog dict
- GBool ok; // true if xref table is valid
- int errCode; // error code (if <ok> is false)
- Object trailerDict; // trailer dictionary
- Guint lastXRefPos; // offset of last xref table
- Guint *streamEnds; // 'endstream' positions - only used in
- // damaged files
- int streamEndsLen; // number of valid entries in streamEnds
- ObjectStream *objStr; // cached object stream
- GBool encrypted; // true if file is encrypted
- int permFlags; // permission bits
- GBool ownerPasswordOk; // true if owner password is correct
- Guchar fileKey[16]; // file decryption key
- int keyLength; // length of key, in bytes
- int encVersion; // encryption algorithm
-
- Guint getStartXref();
- GBool readXRef(Guint *pos);
- GBool readXRefTable(Parser *parser, Guint *pos);
- GBool readXRefStreamSection(Stream *xrefStr, int *w, int first, int n);
- GBool readXRefStream(Stream *xrefStr, Guint *pos);
- GBool constructXRef();
- Guint strToUnsigned(char *s);
-};
-
-#endif
+++ /dev/null
-/* aconf.h. Generated by configure. */
-/*
- * aconf.h
- *
- * Copyright 2002 Glyph & Cog, LLC
- */
-
-#ifndef ACONF_H
-#define ACONF_H
-#include "../../config.h"
-
-#define HAVE_STRINGS_H 1
-
-// todo:
-//
-// HAVE_STRINGS_H
-// HAVE_BSTRING_H
-// HAVE_SYS_SELECT_H
-// SELECT_TAKES_INT
-// HAVE_FSEEK64
-// HAVE_MKSTEMPS
-// HAVE_FSEEKO 1
-
-#endif
+++ /dev/null
-#include <stdio.h>
-#include <stdlib.h>
-#include <math.h>
-#include "GfxState.h"
-static struct _rgb {unsigned char r,g,b;}
-cmyk2rgb[8*16*16*8] = {
-{255,255,255},{222,223,225},{191,192,195},{162,164,167},{133,135,138},{106,107,110},{73,74,75},{34,30,31},{255,254,241},{223,222,212},{192,191,184},{163,163,157},{134,134,129},{107,106,103},{74,73,70},{33,29,27},{255,253,227},{223,221,199},{192,191,174},{163,163,147},{135,134,121},{107,106,96},{74,73,65},{33,29,23},{255,252,214},{224,220,188},{193,190,164},{164,162,140},{135,133,115},{107,105,90},{74,72,61},{32,28,19},
-{255,251,201},{225,220,177},{193,190,154},{164,162,132},{135,133,108},{107,105,85},{74,72,56},{32,28,15},{255,250,187},{226,219,165},{194,189,144},{164,161,122},{135,132,100},{107,104,79},{74,72,52},{31,28,9},{255,249,173},{227,219,154},{195,189,134},{164,160,113},{135,132,92},{107,104,72},{74,72,47},{31,28,5},{255,248,160},{226,218,142},{195,188,123},{165,159,104},{135,131,85},{107,103,65},{74,71,41},{30,27,2},
-{255,247,147},{227,216,130},{196,187,112},{165,158,95},{135,131,77},{107,103,59},{74,71,35},{29,26,0},{255,246,133},{228,215,117},{197,186,101},{165,157,86},{135,130,69},{107,103,52},{74,70,29},{28,26,0},{255,245,117},{228,214,103},{196,186,90},{165,157,76},{135,130,60},{107,103,44},{74,70,21},{27,26,0},{255,244,100},{227,214,89},{195,185,78},{165,157,65},{135,129,50},{107,102,35},{73,70,12},{26,26,0},
-{255,244,78},{227,213,72},{195,184,62},{165,156,51},{135,129,38},{107,102,22},{73,70,6},{25,26,0},{255,243,54},{228,212,52},{196,183,44},{165,155,36},{135,128,24},{107,101,7},{72,69,1},{24,25,0},{255,242,27},{228,212,27},{196,183,22},{165,155,18},{135,128,12},{107,101,3},{72,69,0},{24,25,0},{255,241,0},{227,212,0},{195,182,0},{165,154,0},{136,127,0},{107,100,0},{72,69,0},{24,25,0},
-{253,241,246},{220,210,216},{190,182,189},{161,154,161},{133,127,133},{106,101,105},{74,69,72},{34,26,28},{254,240,232},{221,209,204},{191,181,178},{162,154,152},{133,127,125},{106,100,99},{74,68,67},{33,25,24},{254,239,219},{222,209,193},{191,181,168},{162,154,143},{134,127,117},{106,100,92},{74,68,62},{33,25,20},{254,238,207},{222,208,182},{192,180,159},{163,153,135},{134,126,111},{106,99,87},{74,67,58},{32,24,16},
-{254,237,194},{223,207,172},{192,179,149},{163,153,127},{134,126,104},{106,99,82},{74,67,53},{32,24,11},{255,236,181},{224,206,160},{193,178,140},{163,152,118},{134,125,97},{106,98,76},{73,67,49},{31,24,6},{255,235,168},{225,206,149},{193,178,130},{163,151,110},{134,124,89},{106,98,69},{73,67,44},{31,23,2},{255,234,155},{225,205,137},{194,177,119},{164,150,101},{134,124,82},{106,97,62},{73,66,38},{30,23,1},
-{255,233,143},{225,204,126},{194,176,108},{164,149,92},{134,124,74},{106,97,56},{73,66,32},{29,22,0},{255,232,129},{226,203,114},{195,176,98},{164,148,83},{134,123,66},{106,97,49},{73,65,26},{28,22,0},{255,231,114},{226,202,100},{194,176,88},{164,148,73},{134,123,57},{106,97,41},{73,65,19},{27,22,0},{255,230,98},{226,202,86},{194,175,76},{164,148,63},{134,122,48},{106,96,32},{72,65,10},{26,22,0},
-{255,230,77},{226,201,70},{194,174,61},{164,147,49},{134,122,36},{106,96,20},{72,65,5},{26,22,0},{255,229,56},{226,200,53},{194,173,45},{164,146,35},{134,121,22},{106,95,6},{72,64,0},{25,21,0},{255,229,28},{226,200,28},{194,173,23},{164,146,17},{134,121,11},{106,95,2},{72,64,0},{25,21,0},{255,228,0},{226,200,1},{194,172,2},{164,146,0},{135,120,0},{106,94,0},{72,64,0},{24,21,0},
-{252,226,237},{219,197,207},{189,172,182},{161,145,155},{133,119,128},{106,94,101},{75,63,70},{34,21,26},{253,225,224},{220,197,196},{190,171,172},{162,145,146},{133,119,121},{105,93,95},{74,62,65},{33,20,22},{254,224,211},{221,197,186},{191,171,162},{162,145,138},{133,119,114},{105,93,89},{74,62,59},{33,20,16},{254,223,199},{221,196,176},{192,170,153},{162,144,130},{133,118,108},{105,92,84},{74,61,55},{32,20,12},
-{254,222,187},{221,195,166},{192,169,144},{162,144,122},{133,118,101},{105,92,79},{74,61,51},{32,20,8},{255,221,175},{223,194,154},{192,168,135},{163,143,115},{133,117,94},{105,91,73},{73,61,46},{31,19,3},{255,220,162},{224,194,144},{192,168,126},{163,142,107},{133,116,86},{105,91,67},{73,61,41},{31,18,0},{255,219,150},{224,193,133},{193,167,115},{163,141,98},{134,116,79},{106,91,60},{73,60,36},{30,18,0},
-{255,219,138},{224,192,122},{193,166,105},{163,141,89},{134,116,72},{106,91,54},{73,60,30},{29,18,0},{255,218,126},{224,191,111},{193,166,96},{163,140,81},{134,115,64},{106,90,47},{73,60,24},{28,17,0},{255,218,111},{225,191,98},{193,166,86},{163,140,71},{134,115,55},{106,90,39},{73,60,17},{27,17,0},{255,217,96},{226,190,84},{194,165,75},{164,140,61},{134,114,46},{106,89,30},{72,59,8},{26,17,0},
-{255,217,77},{226,190,69},{194,165,60},{164,139,48},{134,114,34},{106,89,18},{72,59,4},{26,17,0},{255,216,57},{225,189,53},{193,164,45},{163,138,34},{133,113,21},{105,88,6},{72,59,0},{25,17,0},{255,216,30},{225,189,28},{193,164,24},{163,138,17},{133,113,10},{105,88,2},{72,59,0},{25,17,0},{255,215,1},{226,188,3},{194,163,3},{163,138,0},{134,113,0},{106,88,0},{72,59,0},{24,16,0},
-{250,214,229},{217,186,201},{188,162,176},{160,137,151},{133,112,124},{105,88,97},{74,59,66},{34,15,22},{251,212,217},{218,185,190},{189,161,167},{161,137,142},{133,112,117},{105,87,91},{73,58,61},{34,15,18},{252,211,204},{219,185,180},{190,161,158},{161,137,134},{133,112,110},{105,87,85},{73,58,56},{34,15,12},{252,211,193},{220,184,170},{190,160,149},{161,136,126},{132,111,104},{105,86,81},{73,57,52},{33,15,8},
-{253,210,181},{220,184,161},{190,160,140},{161,135,118},{132,111,97},{105,86,75},{73,57,48},{32,15,4},{253,209,169},{221,183,150},{191,159,131},{162,135,111},{132,110,90},{104,85,69},{73,57,44},{32,14,2},{253,208,158},{221,183,140},{191,159,122},{162,135,103},{132,110,83},{104,85,63},{73,57,39},{32,14,0},{254,207,146},{222,182,129},{191,158,112},{162,134,95},{133,109,76},{105,85,57},{73,56,33},{31,14,0},
-{254,207,134},{222,182,118},{191,157,103},{162,134,87},{133,109,70},{105,85,51},{73,56,27},{30,14,0},{254,206,122},{223,181,108},{191,157,94},{162,133,79},{133,108,62},{105,84,45},{73,56,22},{29,13,0},{254,206,108},{223,181,96},{191,156,83},{162,133,69},{133,108,53},{105,84,37},{73,56,15},{28,13,0},{254,205,94},{223,180,83},{192,155,72},{162,132,59},{133,108,44},{105,84,28},{72,55,6},{27,13,0},
-{254,205,76},{223,180,68},{192,155,58},{162,132,46},{133,108,33},{105,84,17},{72,55,3},{27,13,0},{255,204,58},{223,179,53},{191,155,44},{162,131,33},{133,107,20},{105,84,5},{72,55,0},{26,13,0},{255,204,34},{223,179,30},{191,155,25},{162,131,18},{133,107,10},{105,84,2},{72,55,0},{26,13,0},{254,203,9},{224,178,7},{192,154,5},{162,130,1},{133,106,0},{105,83,0},{72,55,0},{25,12,0},
-{249,201,221},{216,175,194},{188,151,170},{160,129,146},{133,105,120},{105,81,94},{74,54,63},{34,10,19},{250,199,209},{217,174,183},{189,150,161},{161,129,137},{133,105,113},{105,81,88},{73,53,58},{34,10,14},{250,198,197},{218,174,173},{189,150,152},{161,129,129},{133,105,106},{105,81,82},{73,53,53},{34,10,8},{251,198,186},{219,173,164},{189,150,144},{160,128,122},{132,104,100},{105,81,78},{73,52,49},{33,10,5},
-{252,198,175},{220,173,156},{189,150,135},{160,127,114},{132,103,94},{105,81,72},{73,52,45},{32,10,2},{252,197,164},{219,172,146},{190,149,126},{161,127,107},{132,103,87},{104,80,66},{73,52,41},{32,9,1},{252,196,153},{219,172,136},{191,149,118},{161,127,99},{132,103,80},{104,80,60},{73,52,36},{32,9,0},{252,195,142},{220,171,125},{190,148,109},{161,126,92},{132,102,73},{104,80,54},{73,52,30},{31,9,0},
-{252,195,130},{221,171,115},{190,148,100},{161,126,84},{132,102,67},{104,80,48},{73,52,24},{30,9,0},{253,194,118},{221,170,105},{190,147,91},{162,125,76},{133,101,60},{105,79,42},{73,51,19},{29,9,0},{253,194,105},{221,170,93},{190,147,80},{162,125,66},{133,101,51},{105,79,35},{73,51,13},{28,9,0},{253,193,91},{221,169,81},{191,146,69},{161,124,56},{132,101,43},{104,79,27},{72,51,5},{27,8,0},
-{253,193,76},{221,169,68},{191,146,57},{161,124,45},{132,101,32},{104,79,17},{72,51,2},{27,8,0},{254,192,59},{222,168,53},{190,146,44},{162,123,33},{133,100,20},{105,78,5},{72,51,0},{26,9,0},{254,192,38},{222,168,32},{190,146,25},{162,123,18},{133,100,10},{105,78,2},{72,51,0},{26,9,0},{253,191,16},{222,167,12},{190,145,7},{161,122,2},{133,99,0},{105,78,0},{72,51,0},{26,8,0},
-{247,187,214},{215,164,187},{187,141,164},{159,120,140},{132,98,115},{104,75,90},{73,48,60},{34,4,15},{248,185,202},{216,163,177},{188,140,155},{159,119,132},{132,98,108},{104,75,84},{73,47,55},{34,4,10},{249,184,190},{217,162,167},{188,140,146},{159,119,124},{132,98,101},{104,75,78},{73,47,51},{34,4,6},{250,184,179},{218,161,158},{188,140,138},{159,119,117},{131,97,96},{105,75,74},{74,47,47},{33,4,3},
-{250,184,169},{218,161,150},{188,140,130},{159,118,110},{131,96,90},{105,75,70},{74,47,43},{33,4,1},{250,183,158},{218,160,140},{189,139,122},{160,118,103},{131,96,84},{104,74,64},{73,47,39},{32,3,0},{250,183,147},{218,160,130},{189,139,114},{160,118,95},{131,96,77},{104,74,58},{73,47,34},{32,3,0},{250,182,136},{219,159,121},{189,138,105},{160,117,88},{132,95,70},{104,74,52},{72,46,28},{31,3,0},
-{250,181,126},{220,159,111},{189,138,96},{160,117,80},{132,95,64},{104,74,46},{72,46,22},{29,3,0},{251,180,114},{219,159,101},{189,137,87},{161,116,73},{132,94,57},{104,73,40},{73,46,17},{28,3,0},{251,180,102},{219,159,91},{189,137,78},{161,116,64},{132,94,49},{104,73,33},{73,46,11},{28,3,0},{251,179,89},{219,158,79},{189,136,67},{160,115,54},{131,94,41},{104,73,25},{72,46,4},{28,3,0},
-{251,179,75},{219,158,66},{189,136,55},{160,115,44},{131,94,30},{104,73,15},{72,46,1},{28,3,0},{252,179,60},{220,157,52},{189,136,43},{160,114,32},{132,93,18},{104,72,4},{72,46,0},{27,3,0},{252,179,41},{220,157,34},{189,136,26},{160,114,17},{132,93,9},{104,72,2},{72,46,0},{27,3,0},{251,178,22},{220,156,16},{189,135,9},{160,114,2},{132,93,0},{104,72,0},{71,46,0},{27,3,0},
-{246,173,206},{214,152,181},{186,131,158},{158,111,135},{131,90,110},{104,69,86},{73,42,57},{34,0,11},{247,172,194},{215,152,171},{187,130,149},{158,110,127},{131,90,104},{104,69,81},{73,42,52},{34,0,7},{247,171,182},{215,151,161},{187,130,140},{158,110,119},{131,90,97},{104,69,75},{73,42,48},{34,0,3},{248,170,173},{216,150,152},{187,130,133},{159,110,112},{131,89,93},{105,69,71},{74,42,44},{33,0,2},
-{248,170,163},{216,150,144},{187,130,125},{159,110,106},{131,89,87},{105,69,67},{74,42,40},{33,0,0},{248,170,153},{217,149,135},{187,129,118},{159,109,99},{131,88,81},{104,68,61},{73,42,36},{32,0,0},{248,170,142},{217,149,126},{187,129,110},{159,109,92},{131,88,74},{104,68,56},{73,42,31},{32,0,0},{248,169,132},{217,148,117},{188,128,101},{160,108,85},{132,88,67},{104,68,50},{72,41,25},{31,0,0},
-{249,169,122},{218,148,107},{188,128,93},{160,108,77},{132,88,61},{104,68,44},{72,41,20},{29,0,0},{250,168,111},{217,148,98},{188,127,84},{160,107,70},{132,87,54},{104,67,38},{73,41,15},{28,0,0},{250,168,99},{217,148,88},{188,127,75},{160,107,61},{132,87,47},{104,67,31},{73,41,9},{28,0,0},{249,167,87},{217,147,77},{188,126,65},{160,106,52},{131,87,39},{104,67,23},{72,41,4},{28,0,0},
-{249,167,73},{217,147,64},{188,126,53},{160,106,42},{131,87,28},{104,67,14},{72,41,1},{28,0,0},{250,166,59},{218,146,51},{188,126,42},{159,106,31},{131,86,17},{103,66,4},{72,41,0},{27,0,0},{250,166,43},{218,146,35},{188,126,27},{159,106,17},{131,86,9},{103,66,2},{72,41,0},{27,0,0},{249,165,27},{218,145,19},{188,125,11},{159,106,3},{132,86,0},{104,66,0},{71,41,0},{27,0,0},
-{245,160,198},{213,140,174},{185,121,152},{157,102,130},{130,83,106},{104,62,83},{73,37,54},{34,0,8},{246,159,187},{214,140,164},{186,120,143},{157,101,122},{131,82,100},{104,62,78},{73,37,49},{34,0,4},{246,159,175},{214,140,155},{186,120,135},{157,101,114},{131,82,94},{104,62,72},{73,37,46},{34,0,1},{247,158,166},{215,139,147},{186,120,128},{158,101,108},{130,82,89},{104,62,68},{73,37,42},{33,0,1},
-{247,158,158},{215,139,139},{186,120,121},{158,101,102},{130,82,84},{104,62,64},{73,37,38},{33,0,0},{246,157,148},{216,138,130},{186,119,114},{158,100,95},{131,81,78},{103,61,58},{72,37,33},{32,0,0},{246,157,138},{216,138,122},{186,119,106},{158,100,88},{131,81,71},{103,61,53},{72,37,28},{32,0,0},{247,157,129},{216,137,113},{187,118,98},{159,99,81},{131,81,65},{103,61,48},{71,36,23},{31,0,0},
-{248,157,119},{216,137,104},{187,118,90},{159,99,74},{131,81,59},{103,61,42},{71,36,18},{30,0,0},{249,156,108},{216,137,95},{187,118,82},{159,99,67},{131,80,52},{103,61,35},{72,36,12},{29,0,0},{249,156,97},{216,137,85},{187,118,73},{159,99,60},{131,80,44},{103,61,28},{72,36,8},{29,0,0},{248,155,85},{216,136,75},{187,117,63},{159,99,51},{131,80,37},{103,61,21},{72,36,3},{28,0,0},
-{248,155,72},{216,136,63},{187,117,52},{159,99,41},{131,80,27},{103,61,13},{72,36,1},{28,0,0},{248,154,58},{217,135,50},{187,117,41},{158,98,30},{130,79,16},{103,60,3},{71,36,0},{27,0,0},{248,154,43},{217,135,36},{187,117,28},{158,98,18},{130,79,8},{103,60,1},{71,36,0},{27,0,0},{248,153,28},{216,134,22},{187,116,15},{158,98,5},{131,79,0},{103,60,0},{71,36,0},{26,0,0},
-{243,147,190},{212,128,168},{184,111,146},{157,93,124},{130,75,102},{104,56,79},{73,30,51},{34,0,4},{244,147,179},{213,128,158},{185,110,138},{157,93,118},{131,74,96},{104,56,74},{73,31,47},{34,0,2},{244,147,169},{213,128,149},{185,110,130},{157,93,110},{131,74,90},{104,56,69},{73,31,43},{34,0,0},{245,146,160},{214,127,141},{185,110,124},{157,93,104},{130,75,85},{104,56,65},{73,31,39},{33,0,0},
-{245,146,152},{214,127,133},{185,110,117},{157,93,98},{130,75,80},{104,56,60},{73,31,35},{33,0,0},{244,145,142},{214,127,125},{184,109,110},{156,92,91},{130,74,74},{103,55,55},{72,31,31},{32,0,0},{244,144,133},{214,127,117},{184,109,102},{156,92,84},{130,74,68},{103,55,50},{72,31,26},{31,0,0},{245,145,124},{215,126,109},{185,108,94},{157,91,77},{130,73,62},{102,55,45},{71,30,21},{31,0,0},
-{246,145,115},{215,126,100},{185,108,86},{157,91,71},{130,73,56},{102,55,40},{71,30,16},{30,0,0},{247,144,105},{214,125,92},{185,108,79},{157,91,65},{130,73,50},{103,55,33},{72,31,10},{29,0,0},{247,144,94},{214,125,83},{185,108,71},{157,91,58},{130,73,42},{103,55,26},{72,31,6},{29,0,0},{246,143,83},{214,125,73},{185,108,61},{157,91,49},{130,73,35},{103,55,19},{72,31,2},{28,0,0},
-{246,143,70},{214,125,61},{185,108,50},{157,91,39},{130,73,25},{103,55,11},{72,31,1},{28,0,0},{246,142,57},{215,124,49},{185,107,40},{157,90,28},{130,73,14},{103,54,3},{71,30,0},{27,0,0},{246,142,44},{215,124,37},{185,107,29},{157,90,18},{130,73,7},{103,54,1},{71,30,0},{27,0,0},{246,141,30},{215,124,24},{185,107,18},{157,90,6},{130,72,0},{103,54,0},{71,30,0},{26,0,0},
-{242,135,182},{211,116,161},{183,101,140},{156,84,119},{130,67,98},{103,49,75},{72,23,48},{35,0,1},{243,134,172},{212,116,151},{184,101,133},{156,84,113},{130,67,92},{103,49,71},{72,24,44},{34,0,1},{243,134,162},{212,116,142},{184,101,125},{156,84,106},{130,67,86},{103,49,66},{72,24,40},{33,0,0},{244,134,154},{213,116,135},{184,101,119},{156,84,100},{130,67,81},{103,49,62},{72,24,36},{32,0,0},
-{244,134,146},{213,116,128},{184,101,112},{156,84,94},{130,67,76},{103,49,57},{72,24,32},{32,0,0},{243,133,137},{213,116,120},{183,100,105},{155,83,88},{129,67,70},{102,49,52},{71,24,28},{31,0,0},{243,132,128},{213,116,112},{183,100,97},{155,83,81},{129,67,65},{102,49,47},{71,24,23},{30,0,0},{244,132,119},{214,115,105},{184,99,90},{156,83,74},{129,66,59},{103,48,42},{72,24,19},{30,0,0},
-{245,132,110},{214,115,96},{184,99,83},{156,83,68},{129,66,53},{103,48,37},{72,24,14},{30,0,0},{245,132,101},{213,114,89},{184,99,76},{156,83,62},{130,66,48},{102,48,32},{71,25,7},{29,0,0},{245,132,91},{213,114,80},{184,99,68},{156,83,55},{130,66,41},{102,48,25},{71,25,4},{29,0,0},{245,131,81},{213,115,70},{184,99,59},{156,82,47},{129,66,34},{102,48,18},{71,25,1},{28,0,0},
-{245,131,69},{213,115,60},{184,99,49},{156,82,38},{129,66,24},{102,48,10},{71,25,1},{28,0,0},{245,130,56},{214,114,48},{184,98,39},{156,82,27},{129,66,13},{102,48,3},{71,25,0},{28,0,0},{245,130,45},{214,114,37},{184,98,29},{156,82,17},{129,66,6},{102,48,1},{71,25,0},{28,0,0},{245,130,32},{214,114,25},{184,98,19},{156,81,6},{129,65,0},{102,48,0},{70,25,0},{27,0,0},
-{242,121,175},{211,104,154},{183,90,135},{156,74,114},{129,58,93},{103,41,72},{72,14,45},{33,0,0},{242,120,165},{211,104,145},{183,90,128},{156,74,108},{130,58,88},{103,41,68},{72,15,41},{32,0,0},{242,120,156},{211,104,137},{183,90,120},{156,74,102},{130,58,82},{103,41,63},{72,15,37},{31,0,0},{242,120,148},{212,104,130},{184,90,114},{156,74,96},{129,58,78},{103,42,59},{72,15,33},{31,0,0},
-{242,120,140},{212,104,123},{184,90,107},{156,74,90},{129,58,73},{103,42,54},{72,15,29},{31,0,0},{242,119,132},{212,104,115},{183,90,101},{155,74,85},{129,58,67},{102,42,49},{71,16,25},{30,0,0},{242,119,123},{212,104,107},{183,90,93},{155,74,78},{129,58,62},{102,42,44},{71,16,20},{29,0,0},{243,119,115},{213,103,100},{183,89,86},{155,74,71},{129,58,56},{102,41,39},{71,16,16},{29,0,0},
-{243,119,106},{213,103,93},{183,88,80},{156,74,65},{129,58,50},{102,41,34},{71,16,11},{29,0,0},{243,118,97},{212,103,86},{184,89,73},{156,74,59},{129,58,45},{102,41,29},{71,17,5},{28,0,0},{243,118,88},{212,103,77},{184,89,65},{156,74,52},{129,58,39},{102,41,23},{71,17,3},{28,0,0},{244,118,78},{212,103,67},{184,89,57},{155,73,45},{129,58,32},{102,41,16},{71,17,1},{27,0,0},
-{244,118,67},{212,103,58},{184,89,47},{155,73,36},{129,58,22},{102,41,9},{71,17,1},{27,0,0},{243,117,55},{212,103,47},{183,88,38},{155,73,27},{129,58,12},{102,41,3},{71,18,0},{27,0,0},{243,117,44},{212,103,37},{183,88,29},{155,73,17},{129,58,6},{102,41,1},{71,18,0},{27,0,0},{244,117,33},{213,103,25},{184,88,19},{156,73,7},{129,57,0},{102,42,0},{70,18,0},{27,0,0},
-{241,106,169},{210,92,148},{182,78,129},{155,64,109},{128,48,89},{103,32,69},{72,5,42},{31,0,0},{241,106,159},{210,92,139},{182,78,122},{155,64,103},{129,49,84},{103,32,64},{72,5,38},{30,0,0},{241,106,150},{210,92,131},{182,78,114},{155,64,97},{129,49,78},{103,32,59},{72,5,35},{29,0,0},{241,106,142},{211,92,125},{183,78,108},{155,64,91},{128,49,74},{103,33,55},{72,5,31},{29,0,0},
-{241,106,134},{211,92,118},{183,78,103},{155,64,86},{128,49,69},{103,33,51},{72,5,27},{29,0,0},{241,105,126},{211,92,111},{182,79,97},{155,64,81},{128,48,64},{102,33,47},{71,6,23},{28,0,0},{241,105,118},{211,92,103},{182,79,90},{155,64,76},{128,48,59},{102,33,42},{71,6,18},{27,0,0},{241,105,111},{211,91,96},{182,78,83},{154,64,69},{128,49,54},{101,33,37},{70,6,13},{27,0,0},
-{241,105,103},{211,91,89},{182,78,77},{155,64,63},{128,49,48},{101,33,32},{70,7,8},{27,0,0},{242,104,94},{211,91,82},{183,79,70},{156,64,57},{128,49,43},{102,33,27},{71,8,3},{26,0,0},{242,104,85},{211,91,74},{183,79,63},{155,64,50},{128,49,37},{102,33,21},{71,8,2},{26,0,0},{242,105,75},{210,91,65},{183,79,55},{154,64,43},{128,49,30},{101,34,14},{70,8,1},{26,0,0},
-{242,104,65},{210,91,56},{183,79,46},{154,64,34},{128,49,20},{101,34,7},{70,8,1},{26,0,0},{242,103,53},{211,91,45},{182,78,37},{154,64,26},{128,49,10},{102,34,2},{70,9,0},{26,0,0},{242,103,43},{211,91,36},{182,78,28},{154,64,17},{128,49,5},{102,34,1},{70,9,0},{26,0,0},{243,103,33},{211,91,26},{183,78,19},{155,64,8},{128,50,0},{101,35,0},{70,10,0},{26,0,0},
-{239,89,161},{209,76,141},{181,64,123},{155,51,104},{128,36,85},{103,20,65},{72,2,39},{28,0,0},{240,88,152},{210,77,134},{182,64,117},{155,51,98},{129,37,80},{103,20,61},{72,2,35},{27,0,0},{240,88,143},{210,77,126},{182,64,109},{155,51,92},{129,37,74},{103,20,56},{72,2,32},{27,0,0},{241,88,136},{210,77,120},{182,64,103},{155,51,87},{128,37,70},{102,21,52},{72,2,28},{27,0,0},
-{241,89,129},{210,77,113},{182,64,98},{155,51,83},{128,37,66},{102,21,48},{72,2,24},{27,0,0},{241,89,121},{210,77,106},{182,65,92},{154,52,77},{128,37,61},{102,21,44},{71,2,20},{26,0,0},{241,89,114},{210,77,99},{182,65,86},{154,52,72},{128,38,56},{102,21,39},{71,2,15},{26,0,0},{240,89,107},{210,77,92},{182,65,80},{154,52,66},{128,38,51},{101,22,34},{70,2,10},{25,0,0},
-{240,89,99},{210,77,86},{182,65,74},{155,53,60},{128,39,45},{101,22,29},{70,3,6},{25,0,0},{241,89,91},{210,77,79},{182,66,67},{155,53,54},{128,39,40},{102,22,24},{71,4,3},{25,0,0},{241,89,82},{210,77,71},{182,66,60},{154,53,47},{128,39,34},{102,22,18},{71,4,2},{25,0,0},{241,89,72},{210,77,62},{182,66,53},{154,53,41},{128,39,27},{101,23,11},{70,4,1},{25,0,0},
-{241,89,62},{210,77,54},{182,66,44},{154,53,33},{128,39,19},{101,23,6},{70,4,1},{25,0,0},{241,88,52},{211,77,44},{182,65,36},{154,53,25},{127,39,10},{102,24,2},{70,5,0},{25,0,0},{241,88,43},{211,77,36},{182,65,28},{154,54,17},{127,39,5},{102,24,1},{70,5,0},{25,0,0},{242,88,33},{210,78,27},{182,66,20},{154,54,9},{127,41,0},{101,25,0},{70,5,0},{25,0,0},
-{237,71,154},{208,59,134},{180,50,117},{154,38,100},{128,22,81},{102,6,61},{72,0,36},{25,0,0},{238,70,145},{209,60,128},{181,49,111},{154,38,94},{128,23,76},{102,7,57},{72,0,32},{25,0,0},{239,69,137},{209,61,121},{181,49,105},{154,38,88},{128,24,70},{102,7,53},{72,0,29},{25,0,0},{240,70,130},{208,61,115},{181,50,99},{154,39,83},{128,25,66},{101,7,49},{71,0,25},{25,0,0},
-{240,71,123},{208,61,108},{181,50,94},{154,39,79},{128,25,62},{101,7,45},{71,0,21},{25,0,0},{240,72,117},{209,62,102},{181,51,88},{153,39,73},{127,25,57},{101,8,40},{71,0,17},{24,0,0},{240,72,110},{209,62,95},{181,51,82},{153,39,68},{127,26,52},{101,9,35},{71,0,12},{24,0,0},{239,72,103},{209,63,88},{181,52,76},{154,40,62},{127,26,47},{101,10,31},{70,0,8},{23,0,0},
-{239,72,95},{209,63,82},{181,52,70},{154,41,56},{127,27,42},{101,10,26},{70,0,5},{23,0,0},{239,73,88},{209,62,75},{180,52,64},{153,41,51},{127,28,37},{102,10,21},{71,0,3},{23,0,0},{239,73,79},{209,62,68},{180,52,57},{153,41,45},{127,28,31},{102,10,15},{71,0,1},{23,0,0},{239,72,69},{209,63,60},{181,53,50},{154,41,39},{127,28,25},{101,11,8},{70,1,0},{23,0,0},
-{239,72,60},{209,63,52},{181,53,42},{154,41,31},{127,28,17},{101,11,4},{70,1,0},{23,0,0},{239,73,51},{210,63,43},{181,53,35},{154,41,24},{126,28,9},{101,12,1},{69,1,0},{23,0,0},{239,73,43},{210,63,35},{181,53,28},{154,42,17},{126,29,5},{101,13,1},{69,1,0},{23,0,0},{240,73,34},{209,64,28},{181,54,21},{153,43,10},{126,31,1},{101,14,0},{70,1,0},{23,0,0},
-{237,37,147},{207,30,128},{180,26,112},{154,19,95},{128,11,77},{102,2,58},{72,0,33},{23,0,0},{238,36,139},{208,31,122},{181,25,106},{154,19,89},{128,11,72},{102,3,54},{72,0,29},{23,0,0},{238,36,131},{208,31,115},{181,25,99},{154,19,83},{128,12,67},{102,3,50},{72,0,26},{23,0,0},{239,37,124},{207,32,109},{181,26,94},{154,20,79},{128,12,63},{101,3,46},{71,0,22},{23,0,0},
-{239,38,117},{207,32,103},{181,26,90},{154,20,75},{128,12,59},{101,3,42},{71,0,18},{23,0,0},{238,42,111},{208,34,97},{180,26,84},{153,20,70},{127,13,54},{101,3,37},{71,0,14},{22,0,0},{238,45,104},{208,35,92},{180,27,78},{153,20,64},{127,13,49},{101,4,33},{71,0,10},{22,0,0},{238,44,97},{208,37,85},{180,28,73},{153,20,59},{127,13,44},{101,4,29},{70,0,7},{22,0,0},
-{239,45,91},{208,38,79},{180,29,67},{153,21,54},{127,14,40},{101,4,24},{70,0,4},{22,0,0},{238,47,84},{208,37,72},{180,28,61},{153,21,49},{127,14,35},{101,5,19},{71,0,3},{22,0,0},{238,48,76},{208,38,66},{180,29,55},{153,22,43},{127,14,29},{101,5,13},{71,0,1},{22,0,0},{238,49,68},{208,40,59},{180,31,48},{153,22,37},{127,14,23},{101,5,7},{70,1,0},{22,0,0},
-{238,49,59},{208,41,51},{180,32,41},{153,23,30},{127,14,16},{101,5,3},{70,1,0},{22,0,0},{239,50,50},{209,42,43},{180,33,34},{154,24,23},{126,14,8},{101,6,1},{69,1,0},{22,0,0},{239,50,43},{209,42,35},{180,33,28},{154,24,17},{126,15,5},{101,6,1},{69,1,0},{22,0,0},{239,51,34},{208,42,28},{181,34,21},{153,25,10},{126,16,1},{101,7,0},{70,1,0},{23,0,0},
-{237,0,140},{206,0,122},{179,0,108},{153,0,91},{128,0,73},{102,0,54},{71,0,30},{20,0,0},{237,0,133},{207,0,116},{180,0,101},{153,0,85},{127,0,68},{102,0,50},{71,0,26},{20,0,0},{237,0,125},{207,0,110},{180,0,94},{153,0,79},{127,0,63},{102,0,46},{71,0,23},{20,0,0},{237,1,119},{206,1,104},{180,0,90},{153,0,75},{127,0,59},{102,0,42},{71,0,19},{20,0,0},
-{237,3,112},{206,2,99},{180,0,86},{153,0,71},{127,0,55},{102,0,38},{71,0,15},{20,0,0},{236,11,106},{206,4,93},{179,0,80},{152,0,66},{126,0,51},{101,0,34},{70,0,11},{20,0,0},{236,16,99},{206,7,88},{179,1,75},{152,0,61},{126,0,46},{101,0,30},{70,0,8},{20,0,0},{237,15,92},{206,10,81},{179,3,69},{152,0,56},{126,0,41},{100,0,26},{69,0,5},{20,0,0},
-{238,16,86},{206,12,75},{179,4,63},{152,0,51},{126,0,37},{100,0,22},{69,0,3},{20,0,0},{237,19,80},{207,11,69},{180,3,58},{153,0,46},{126,0,33},{100,0,17},{70,0,2},{20,0,0},{237,22,73},{207,13,63},{180,5,52},{153,1,41},{126,0,27},{100,0,11},{70,0,1},{20,0,0},{237,24,66},{207,16,57},{179,8,46},{152,2,35},{126,0,21},{100,0,5},{69,0,0},{20,0,0},
-{237,25,58},{207,19,50},{179,11,40},{152,3,29},{126,0,14},{100,0,2},{69,0,0},{20,0,0},{238,25,49},{207,21,43},{179,13,33},{153,5,22},{127,0,7},{100,0,0},{69,0,0},{20,0,0},{238,26,42},{207,21,36},{179,13,27},{153,5,16},{127,0,4},{100,0,0},{69,0,0},{21,0,0},{238,28,35},{207,20,29},{180,13,22},{152,5,10},{126,0,1},{100,0,0},{69,0,0},{22,0,0},
-{215,240,252},{188,210,222},{162,182,193},{136,154,165},{113,128,136},{88,101,108},{59,69,76},{22,27,32},{217,238,238},{189,209,210},{163,181,183},{137,154,156},{114,127,129},{89,100,102},{59,69,71},{20,26,28},{218,237,224},{189,209,198},{163,181,173},{138,154,147},{114,127,121},{89,100,96},{59,69,65},{19,26,24},{219,236,212},{191,208,188},{164,180,164},{139,153,139},{114,126,114},{89,99,90},{59,68,61},{19,26,20},
-{219,236,200},{192,207,177},{165,180,154},{139,153,131},{114,126,107},{89,99,85},{59,68,56},{19,26,17},{221,235,187},{193,206,165},{166,179,144},{140,152,122},{115,125,100},{90,98,79},{59,67,51},{18,25,11},{222,234,174},{194,206,154},{167,179,134},{141,151,114},{115,125,93},{90,98,73},{59,67,46},{17,25,6},{223,233,160},{195,205,143},{168,178,124},{141,150,105},{116,124,86},{90,97,66},{60,66,41},{16,25,2},
-{224,232,147},{195,204,131},{168,177,114},{141,150,96},{116,124,78},{90,97,60},{60,66,35},{15,25,0},{225,231,135},{196,203,119},{168,176,104},{142,149,87},{116,123,71},{90,96,53},{59,66,30},{14,24,0},{225,231,120},{196,202,106},{168,176,92},{142,149,77},{116,123,62},{90,96,46},{59,66,23},{13,24,0},{226,230,105},{196,201,93},{169,175,81},{142,148,67},{116,122,53},{91,96,38},{60,65,15},{12,24,0},
-{226,230,87},{197,201,77},{169,175,67},{142,148,55},{116,122,42},{91,96,27},{60,65,8},{11,24,0},{226,229,68},{198,200,60},{170,174,53},{143,147,43},{117,121,31},{91,95,16},{60,65,2},{10,24,0},{227,229,46},{198,200,41},{170,174,35},{143,147,26},{117,121,17},{91,95,8},{60,65,1},{10,24,0},{228,229,22},{198,200,21},{170,173,17},{143,146,9},{116,120,2},{90,95,0},{59,64,0},{9,23,0},
-{214,226,243},{187,198,215},{162,172,187},{137,146,159},{113,121,132},{88,95,104},{60,64,73},{23,22,29},{216,225,230},{189,197,203},{163,171,177},{138,145,151},{114,120,125},{89,94,98},{60,64,68},{21,21,25},{217,225,217},{190,197,192},{164,171,168},{139,145,142},{114,120,117},{89,94,92},{60,64,62},{20,21,21},{218,224,205},{191,196,182},{165,170,159},{140,144,135},{115,119,110},{90,93,87},{60,63,58},{20,21,17},
-{218,223,193},{191,195,171},{165,170,149},{140,144,127},{115,119,103},{90,93,82},{60,63,53},{20,21,13},{220,222,181},{193,194,160},{165,169,140},{140,143,118},{114,118,96},{89,92,76},{60,63,49},{19,21,7},{221,222,168},{194,194,149},{166,169,130},{140,143,110},{114,118,90},{89,92,70},{60,63,44},{18,21,3},{221,221,155},{194,193,138},{167,168,120},{141,142,102},{115,117,83},{89,91,63},{60,62,39},{17,21,1},
-{222,220,143},{194,193,127},{167,167,110},{141,141,93},{115,117,75},{89,91,57},{60,62,33},{16,21,0},{223,219,131},{195,192,115},{167,166,101},{141,140,84},{115,116,68},{90,91,50},{60,61,27},{15,20,0},{224,218,117},{196,191,103},{167,166,89},{141,140,74},{115,116,59},{90,91,43},{60,61,21},{14,20,0},{224,218,103},{196,190,90},{168,165,78},{141,140,64},{115,115,51},{90,90,35},{60,61,13},{13,20,0},
-{224,217,86},{196,190,76},{168,165,65},{141,140,53},{115,115,40},{90,90,25},{60,61,7},{12,20,0},{225,216,68},{197,189,60},{169,164,52},{142,139,41},{116,114,29},{91,90,14},{60,61,2},{10,20,0},{225,216,48},{197,189,42},{169,164,35},{142,139,26},{116,114,16},{91,90,6},{60,61,1},{10,20,0},{226,216,27},{197,189,24},{169,164,19},{142,139,11},{116,114,3},{90,89,0},{59,60,0},{10,19,0},
-{214,213,235},{187,187,207},{162,163,180},{137,138,153},{113,113,127},{88,88,101},{61,59,70},{23,17,26},{216,212,222},{189,186,196},{163,162,171},{139,137,145},{114,112,121},{89,87,95},{61,58,65},{22,16,22},{217,211,209},{190,186,185},{164,162,162},{139,137,137},{114,112,114},{89,87,89},{61,58,60},{21,16,18},{218,211,197},{191,185,175},{165,161,153},{140,136,130},{115,112,107},{90,87,84},{61,58,56},{20,16,14},
-{218,211,186},{191,184,164},{165,161,144},{140,136,122},{115,112,100},{90,87,79},{61,58,51},{20,16,10},{219,210,174},{192,183,154},{165,160,135},{140,135,114},{114,111,93},{89,86,73},{61,57,47},{19,16,4},{220,209,162},{193,183,144},{165,160,126},{140,135,106},{114,110,87},{89,86,67},{61,57,42},{19,16,1},{220,208,151},{193,182,133},{166,159,117},{140,134,99},{114,109,80},{89,85,61},{60,57,37},{18,16,0},
-{221,207,139},{193,182,123},{166,158,107},{140,133,90},{114,109,73},{89,85,55},{60,57,31},{17,16,0},{222,206,127},{194,181,112},{167,157,98},{141,132,81},{115,108,65},{90,85,48},{60,57,25},{16,15,0},{223,206,114},{195,181,100},{167,157,87},{141,132,72},{115,108,57},{90,85,41},{60,57,19},{15,15,0},{223,206,101},{196,180,88},{167,156,77},{141,132,62},{115,108,49},{90,84,33},{60,56,12},{14,15,0},
-{223,205,85},{196,180,75},{167,156,64},{141,132,52},{115,108,39},{90,84,23},{60,56,6},{13,15,0},{224,204,68},{196,179,60},{168,155,51},{142,131,40},{116,107,28},{91,84,12},{60,56,2},{11,15,0},{224,204,49},{196,179,43},{168,155,35},{142,131,26},{116,107,16},{91,84,5},{60,56,1},{11,15,0},{225,204,31},{196,178,26},{168,155,20},{142,131,12},{116,107,3},{90,83,0},{59,56,0},{11,15,0},
-{213,201,227},{187,177,200},{162,153,175},{138,130,149},{114,106,123},{89,83,97},{61,55,67},{24,11,24},{215,200,215},{188,176,190},{163,153,165},{138,129,141},{114,106,117},{89,83,92},{61,54,62},{23,11,20},{216,199,202},{189,176,179},{163,153,156},{138,129,133},{114,106,110},{89,83,86},{61,54,57},{23,11,15},{217,199,191},{190,175,169},{164,152,148},{139,129,126},{114,105,103},{89,83,81},{61,54,53},{22,11,10},
-{217,199,181},{190,174,160},{164,152,140},{139,129,118},{114,105,97},{89,83,76},{61,54,49},{22,11,6},{218,198,170},{191,173,150},{164,151,131},{140,128,110},{115,105,91},{90,82,70},{60,53,45},{21,11,2},{219,197,158},{192,173,140},{164,151,122},{140,128,102},{115,104,84},{90,82,65},{60,53,40},{20,11,0},{219,196,147},{192,172,129},{165,150,113},{140,127,95},{115,103,77},{90,81,59},{61,53,35},{19,11,0},
-{220,195,135},{192,172,119},{165,149,103},{140,126,87},{115,103,71},{90,81,53},{61,53,29},{18,11,0},{221,194,124},{193,171,109},{166,148,94},{141,125,79},{115,102,63},{90,81,46},{61,53,23},{17,11,0},{221,194,112},{193,171,98},{166,148,85},{141,125,70},{115,102,56},{90,81,39},{61,53,17},{15,11,0},{222,194,98},{194,170,86},{166,147,75},{140,125,60},{115,102,47},{90,80,32},{60,52,10},{14,11,0},
-{222,194,83},{194,170,73},{166,147,62},{140,125,50},{115,102,37},{90,80,21},{60,52,5},{14,11,0},{223,193,67},{195,169,59},{167,146,50},{141,124,39},{115,101,26},{90,80,10},{60,52,1},{13,11,0},{223,193,50},{195,169,44},{167,146,36},{141,124,26},{115,101,15},{90,80,4},{60,52,0},{12,11,0},{224,192,35},{195,169,28},{167,146,22},{141,124,13},{115,101,4},{90,79,0},{60,52,0},{12,11,0},
-{213,189,219},{187,166,193},{162,144,169},{138,122,144},{114,99,119},{89,78,94},{61,51,64},{24,6,21},{214,188,207},{188,165,183},{163,144,160},{138,121,137},{114,99,113},{89,78,89},{61,50,59},{24,6,17},{215,187,195},{189,165,173},{163,144,151},{138,121,129},{114,99,106},{89,78,83},{61,50,54},{24,6,12},{216,187,185},{190,164,164},{164,143,143},{139,121,122},{114,98,100},{89,77,78},{61,50,50},{23,6,7},
-{217,187,175},{190,164,155},{164,143,135},{139,121,114},{114,98,94},{89,77,73},{61,50,46},{22,6,3},{218,186,165},{191,163,145},{164,142,126},{140,120,107},{115,98,88},{90,77,67},{60,49,42},{21,6,1},{219,185,154},{191,163,135},{164,142,118},{140,120,99},{115,98,81},{90,77,62},{60,49,37},{21,6,0},{219,184,143},{191,162,125},{165,141,109},{140,119,92},{115,97,74},{90,76,56},{61,49,32},{20,6,0},
-{219,184,132},{191,162,115},{165,141,100},{140,119,84},{115,97,68},{90,76,50},{61,49,26},{18,6,0},{220,183,121},{192,161,106},{166,140,91},{141,118,76},{115,96,61},{90,76,44},{61,49,21},{17,6,0},{220,183,109},{192,161,95},{166,140,82},{141,118,68},{115,96,54},{90,76,37},{61,49,14},{15,6,0},{221,183,95},{193,160,84},{166,139,72},{140,117,59},{115,96,45},{90,75,30},{60,48,8},{14,7,0},
-{222,183,82},{193,160,71},{166,139,61},{140,117,49},{115,96,35},{90,75,20},{60,48,4},{14,7,0},{223,182,67},{194,159,59},{167,138,49},{141,116,38},{115,95,25},{90,75,9},{60,48,0},{14,7,0},{223,182,51},{194,159,44},{167,138,37},{141,116,26},{115,95,15},{90,75,4},{60,48,0},{13,7,0},{223,181,36},{194,159,30},{167,137,24},{141,116,14},{115,95,4},{90,75,0},{60,48,0},{12,6,0},
-{212,176,210},{186,154,186},{162,134,162},{138,113,139},{114,92,115},{90,72,90},{62,45,60},{25,3,17},{213,175,200},{187,154,176},{163,134,154},{139,113,132},{114,92,109},{89,72,85},{61,45,56},{24,2,13},{214,175,189},{188,154,166},{163,134,145},{139,113,124},{114,92,102},{89,72,79},{61,45,51},{24,2,8},{215,175,179},{189,153,158},{163,133,138},{139,112,117},{114,91,96},{90,71,75},{61,44,47},{23,2,4},
-{216,175,169},{189,153,149},{164,133,131},{139,112,110},{114,91,90},{90,71,70},{61,44,43},{23,2,1},{217,174,159},{190,153,140},{164,133,122},{139,112,103},{114,91,84},{89,71,64},{61,44,39},{22,2,0},{217,173,148},{190,153,131},{164,133,114},{139,112,96},{114,91,78},{89,71,59},{61,44,35},{21,2,0},{218,172,137},{190,152,121},{164,132,105},{140,111,89},{114,90,71},{90,70,54},{61,44,30},{20,2,0},
-{219,172,127},{190,152,111},{165,132,97},{140,111,82},{114,90,65},{90,70,48},{61,44,24},{18,2,0},{220,171,117},{191,151,102},{166,131,89},{140,110,74},{114,90,59},{90,70,42},{60,44,19},{17,2,0},{220,171,105},{191,151,93},{166,131,80},{140,110,66},{114,90,52},{90,70,35},{60,44,12},{16,2,0},{220,171,93},{192,150,82},{165,130,70},{140,109,57},{114,89,43},{89,69,28},{60,44,6},{15,3,0},
-{220,171,80},{192,150,69},{165,130,59},{140,109,47},{114,89,34},{89,69,18},{60,44,3},{15,3,0},{221,170,66},{193,149,57},{166,129,47},{140,109,36},{114,89,24},{89,69,8},{60,44,0},{15,3,0},{221,170,51},{193,149,44},{166,129,36},{140,109,26},{114,89,14},{89,69,3},{60,44,0},{14,3,0},{221,169,37},{193,149,31},{166,128,24},{140,108,14},{114,89,4},{89,69,0},{59,43,0},{13,2,0},
-{212,164,202},{186,143,179},{162,124,156},{138,105,134},{114,86,110},{90,66,86},{62,40,57},{25,0,14},{213,163,192},{187,143,169},{163,124,148},{139,105,127},{114,85,104},{90,66,81},{61,40,53},{24,0,9},{214,163,182},{187,143,160},{163,124,140},{139,105,119},{114,85,98},{90,66,76},{61,40,48},{24,0,5},{215,162,173},{188,142,152},{163,124,133},{139,104,112},{114,85,92},{90,65,72},{61,39,44},{23,0,2},
-{216,162,163},{188,142,144},{164,124,126},{139,104,106},{114,85,87},{90,65,67},{61,39,40},{23,0,0},{216,162,153},{189,142,135},{164,123,117},{139,104,100},{114,84,81},{89,65,61},{61,39,36},{22,0,0},{216,161,142},{189,142,126},{164,123,109},{139,104,93},{114,84,75},{89,65,56},{61,39,32},{21,0,0},{217,161,132},{190,141,117},{164,122,102},{140,103,86},{114,84,68},{90,64,51},{61,39,27},{20,0,0},
-{218,160,122},{190,141,108},{165,122,94},{140,103,79},{114,84,62},{90,64,45},{61,39,21},{18,0,0},{219,159,113},{191,140,99},{166,122,86},{140,102,72},{114,83,56},{90,64,39},{60,39,16},{17,0,0},{219,159,102},{191,140,90},{166,122,77},{140,102,64},{114,83,49},{90,64,32},{60,39,10},{17,0,0},{219,159,91},{191,139,80},{165,121,67},{140,101,55},{114,83,41},{89,63,25},{60,39,5},{16,0,0},
-{219,159,78},{191,139,67},{165,121,57},{140,101,45},{114,83,32},{89,63,16},{60,39,2},{16,0,0},{220,159,66},{192,138,56},{166,120,46},{140,101,35},{114,83,23},{89,63,7},{60,39,0},{15,0,0},{220,159,51},{192,138,44},{166,120,36},{140,101,26},{114,83,14},{89,63,3},{60,39,0},{14,0,0},{220,158,37},{192,138,32},{165,120,24},{140,100,14},{114,83,4},{89,63,0},{59,38,0},{13,0,0},
-{212,152,195},{185,132,173},{161,115,150},{137,98,128},{113,79,106},{90,59,83},{62,34,54},{23,0,10},{213,151,185},{186,132,163},{162,115,143},{138,97,122},{114,78,100},{90,59,78},{62,34,50},{23,0,6},{214,151,175},{186,132,154},{162,115,135},{138,97,114},{114,78,94},{90,59,73},{62,34,46},{23,0,2},{214,150,166},{187,131,147},{163,115,128},{138,97,108},{114,78,89},{90,59,69},{61,34,42},{22,0,1},
-{215,150,158},{187,131,139},{163,115,121},{138,97,102},{114,78,84},{90,59,64},{61,34,38},{21,0,0},{215,150,148},{188,131,130},{163,114,113},{138,96,96},{114,77,78},{90,59,58},{61,34,34},{20,0,0},{215,150,138},{188,131,122},{163,114,105},{138,96,89},{114,77,72},{90,59,53},{61,34,29},{20,0,0},{216,149,128},{189,130,113},{164,113,98},{139,96,82},{114,77,65},{90,58,48},{61,34,24},{19,0,0},
-{217,149,118},{189,130,104},{164,113,90},{139,96,76},{114,77,59},{90,58,42},{61,34,19},{18,0,0},{218,148,109},{190,130,96},{165,113,83},{139,95,69},{113,76,53},{90,58,37},{61,34,13},{17,0,0},{218,148,99},{190,130,87},{165,113,74},{139,95,61},{113,76,47},{90,58,31},{61,34,8},{17,0,0},{218,148,88},{190,129,77},{164,112,65},{139,94,53},{113,76,40},{89,58,24},{60,34,4},{16,0,0},
-{218,148,76},{190,129,66},{164,112,55},{139,94,44},{113,76,31},{89,58,15},{60,34,1},{15,0,0},{219,147,64},{191,128,55},{165,111,45},{139,94,34},{114,76,22},{90,58,6},{60,34,0},{14,0,0},{219,147,52},{191,128,44},{165,111,35},{139,94,25},{114,76,13},{90,58,2},{60,34,0},{14,0,0},{219,147,38},{191,128,33},{165,111,25},{139,93,13},{113,76,3},{89,58,0},{59,34,0},{14,0,0},
-{212,140,189},{185,122,167},{161,106,144},{137,90,123},{113,72,102},{90,53,79},{62,27,52},{22,0,6},{213,139,179},{186,122,157},{162,105,137},{138,89,117},{114,71,96},{90,53,74},{62,28,48},{22,0,3},{214,139,169},{186,122,148},{162,105,130},{138,89,110},{114,71,90},{90,53,69},{62,28,44},{22,0,0},{214,138,160},{187,121,141},{163,105,123},{138,89,104},{114,71,85},{90,53,65},{61,28,40},{21,0,0},
-{214,138,152},{187,121,133},{163,105,116},{138,89,98},{114,71,80},{90,53,61},{61,28,36},{20,0,0},{215,138,143},{187,121,126},{163,105,109},{138,88,92},{114,71,74},{90,53,56},{61,29,32},{19,0,0},{215,138,134},{187,121,118},{163,105,101},{138,88,85},{114,71,68},{90,53,51},{61,29,27},{19,0,0},{215,137,124},{188,120,109},{163,104,94},{138,88,79},{114,71,63},{90,52,46},{61,28,22},{18,0,0},
-{215,137,114},{188,120,100},{163,104,87},{138,88,73},{114,71,57},{90,52,40},{61,28,17},{17,0,0},{216,136,105},{189,120,93},{163,104,80},{138,87,66},{113,70,51},{90,52,35},{61,28,11},{16,0,0},{216,136,96},{189,120,84},{163,104,72},{138,87,58},{113,70,45},{90,52,29},{61,28,6},{16,0,0},{217,136,86},{188,119,75},{164,103,63},{138,87,51},{113,70,38},{89,52,22},{60,28,3},{15,0,0},
-{217,136,74},{188,119,64},{164,103,53},{138,87,42},{113,70,29},{89,52,13},{60,28,1},{14,0,0},{217,135,62},{189,118,53},{164,103,43},{139,87,32},{114,70,20},{90,52,5},{60,28,0},{13,0,0},{217,135,52},{189,118,44},{164,103,35},{139,87,24},{114,70,11},{90,52,2},{60,28,0},{13,0,0},{218,135,40},{189,118,34},{164,103,25},{139,86,14},{113,70,3},{89,52,0},{59,29,0},{13,0,0},
-{211,127,182},{185,111,160},{161,97,139},{136,81,118},{113,64,98},{90,46,76},{61,20,49},{21,0,3},{212,127,172},{186,111,151},{162,96,132},{137,81,112},{113,64,92},{90,46,71},{62,21,45},{20,0,2},{213,127,162},{186,111,143},{162,96,125},{137,81,106},{113,64,86},{90,46,66},{62,21,41},{19,0,0},{214,126,153},{186,111,136},{162,96,119},{138,81,100},{113,64,81},{90,46,62},{61,21,37},{18,0,0},
-{214,126,145},{186,111,128},{162,96,112},{138,81,94},{113,64,76},{90,46,58},{61,21,33},{18,0,0},{214,126,138},{186,111,121},{163,96,105},{138,81,88},{113,64,70},{90,46,53},{61,22,29},{17,0,0},{214,126,130},{186,111,113},{163,96,98},{138,81,82},{113,64,65},{90,46,48},{61,22,25},{16,0,0},{214,125,120},{187,110,105},{163,95,91},{138,80,76},{113,64,60},{89,46,43},{61,22,20},{16,0,0},
-{214,125,111},{187,110,97},{163,95,85},{138,80,70},{113,64,54},{89,46,37},{61,22,15},{15,0,0},{215,125,102},{188,110,90},{162,95,78},{137,80,63},{113,63,48},{89,46,32},{61,23,9},{14,0,0},{215,125,93},{188,110,81},{162,95,70},{137,80,56},{113,63,42},{89,46,26},{61,23,5},{13,0,0},{216,125,83},{187,109,72},{163,94,61},{138,80,49},{113,63,36},{89,46,20},{60,22,3},{12,0,0},
-{216,125,73},{187,109,63},{163,94,52},{138,80,41},{113,63,27},{89,46,12},{60,22,1},{12,0,0},{216,124,61},{188,109,52},{163,95,42},{138,79,31},{113,63,19},{89,46,4},{59,23,0},{12,0,0},{216,124,51},{188,109,43},{163,95,34},{138,79,23},{113,63,10},{89,46,2},{59,23,0},{12,0,0},{217,124,41},{188,109,33},{163,94,25},{138,79,15},{113,63,3},{89,45,0},{59,23,0},{12,0,0},
-{211,114,174},{184,100,153},{161,87,134},{136,72,113},{113,55,93},{90,39,73},{61,13,46},{19,0,1},{212,114,165},{185,100,145},{162,87,127},{137,72,107},{113,56,88},{90,39,68},{62,13,42},{17,0,1},{212,114,156},{186,100,137},{162,87,120},{137,72,101},{113,56,83},{90,39,63},{62,13,38},{16,0,0},{213,114,148},{186,100,131},{162,87,114},{138,72,96},{113,56,78},{90,39,59},{61,14,34},{15,0,0},
-{213,114,140},{186,100,123},{162,87,107},{138,72,91},{113,56,73},{90,39,55},{61,14,30},{15,0,0},{213,114,133},{186,100,116},{163,86,101},{138,72,85},{113,56,67},{90,39,50},{61,14,26},{14,0,0},{213,114,125},{186,100,108},{163,86,95},{138,72,79},{113,56,62},{90,39,45},{61,14,22},{14,0,0},{214,114,116},{186,100,101},{163,86,88},{138,71,73},{113,56,57},{89,39,40},{61,14,17},{13,0,0},
-{214,114,107},{186,100,94},{163,86,82},{138,71,67},{113,56,51},{89,39,35},{61,14,12},{12,0,0},{214,114,99},{187,100,87},{162,86,75},{137,71,60},{113,56,46},{89,39,30},{61,15,7},{12,0,0},{214,114,90},{187,100,79},{162,86,67},{137,71,54},{113,56,40},{89,39,24},{61,16,4},{11,0,0},{215,114,80},{187,99,70},{163,85,59},{138,71,47},{113,56,34},{89,39,18},{60,15,2},{10,0,0},
-{215,114,71},{187,99,61},{163,85,50},{138,71,39},{113,56,25},{89,39,10},{60,15,1},{10,0,0},{215,113,60},{188,99,51},{163,86,41},{137,71,30},{113,55,17},{89,40,4},{59,16,0},{10,0,0},{215,113,51},{188,99,43},{163,86,33},{137,71,22},{113,55,9},{89,40,2},{59,16,0},{10,0,0},{215,113,41},{188,99,33},{163,85,25},{138,71,15},{113,55,3},{89,39,0},{59,16,0},{10,0,0},
-{210,102,167},{183,89,147},{161,76,128},{136,62,109},{112,46,89},{90,30,69},{62,5,43},{15,0,0},{211,101,158},{184,89,139},{162,76,121},{137,62,103},{113,47,84},{90,30,65},{62,5,39},{14,0,0},{211,101,150},{185,89,131},{162,76,114},{137,62,97},{113,47,79},{90,30,60},{62,5,36},{14,0,0},{212,102,142},{185,89,125},{162,77,109},{137,62,92},{112,47,75},{90,31,56},{61,5,32},{13,0,0},
-{212,102,135},{185,89,118},{162,77,103},{137,62,87},{112,47,70},{90,31,52},{61,5,28},{13,0,0},{212,102,127},{186,89,111},{162,76,97},{137,62,81},{112,47,65},{90,31,48},{61,5,24},{12,0,0},{212,102,119},{186,89,104},{162,76,91},{137,62,76},{112,47,60},{90,31,43},{61,5,20},{12,0,0},{213,102,111},{186,89,97},{162,76,84},{137,62,70},{112,48,54},{90,32,38},{61,5,15},{11,0,0},
-{213,102,103},{186,89,91},{162,76,78},{137,62,64},{112,48,49},{89,32,33},{61,5,10},{10,0,0},{213,101,95},{186,90,84},{162,76,71},{137,62,58},{112,48,44},{88,32,28},{60,6,5},{10,0,0},{213,101,87},{186,90,77},{162,76,64},{137,62,52},{112,48,38},{88,32,22},{60,7,3},{10,0,0},{214,102,78},{186,89,68},{162,75,57},{137,62,45},{112,48,32},{88,32,16},{59,8,1},{9,0,0},
-{214,102,69},{186,89,59},{162,75,48},{137,62,37},{112,48,23},{88,32,9},{59,8,1},{9,0,0},{214,101,58},{187,89,49},{162,76,39},{136,62,29},{112,48,15},{89,33,3},{59,8,0},{9,0,0},{214,101,50},{187,89,41},{162,76,32},{136,62,21},{112,48,8},{89,33,1},{59,8,0},{9,0,0},{214,101,41},{188,89,34},{162,75,25},{137,62,14},{112,48,3},{88,33,0},{59,9,0},{9,0,0},
-{209,86,160},{183,74,141},{161,63,123},{136,49,104},{112,34,85},{90,18,65},{62,2,40},{11,0,0},{210,86,152},{184,75,134},{162,63,116},{137,50,98},{113,35,80},{90,19,61},{62,2,36},{11,0,0},{211,86,144},{185,75,126},{162,63,109},{137,50,93},{113,36,75},{90,19,57},{62,2,33},{11,0,0},{212,87,137},{185,75,120},{161,64,104},{137,51,88},{112,36,71},{90,19,53},{61,2,29},{10,0,0},
-{212,87,130},{185,75,113},{161,64,99},{137,51,83},{112,36,67},{90,19,49},{61,2,25},{10,0,0},{212,87,122},{186,75,107},{162,63,93},{137,51,78},{112,37,62},{90,20,45},{61,2,21},{10,0,0},{212,87,114},{186,76,100},{162,63,87},{137,51,73},{112,37,57},{90,20,40},{61,2,17},{10,0,0},{212,87,107},{186,76,94},{162,64,81},{137,51,67},{112,38,51},{90,21,35},{61,2,12},{9,0,0},
-{212,87,100},{186,76,88},{162,64,75},{137,51,61},{112,38,46},{89,21,30},{61,2,8},{8,0,0},{212,87,92},{186,76,81},{161,64,68},{137,52,55},{112,38,41},{88,22,25},{60,3,4},{8,0,0},{212,87,84},{186,76,74},{161,64,61},{137,52,49},{112,38,35},{88,22,19},{60,3,3},{8,0,0},{213,88,75},{186,76,65},{162,64,54},{137,52,42},{112,38,29},{88,22,13},{59,4,1},{7,0,0},
-{213,88,67},{186,76,57},{162,64,46},{137,52,35},{112,38,22},{88,22,8},{59,4,1},{7,0,0},{213,87,57},{187,76,48},{162,65,38},{136,52,28},{112,39,14},{89,23,3},{59,4,0},{6,0,0},{213,87,50},{187,76,41},{162,65,32},{136,52,20},{112,39,8},{89,23,1},{59,4,0},{6,0,0},{213,87,41},{187,76,34},{162,64,25},{137,52,14},{112,39,3},{88,23,0},{59,5,0},{6,0,0},
-{208,69,153},{183,59,135},{160,49,118},{137,36,99},{113,22,81},{90,6,61},{61,0,36},{8,0,0},{209,70,146},{184,60,128},{161,50,112},{137,37,94},{112,23,76},{90,7,57},{61,0,33},{8,0,0},{210,70,138},{185,60,121},{161,50,105},{137,38,89},{112,24,71},{90,7,53},{61,0,30},{8,0,0},{211,71,131},{185,60,115},{160,50,100},{137,39,84},{113,24,67},{90,7,49},{61,0,26},{7,0,0},
-{211,71,124},{185,60,109},{160,50,95},{137,39,79},{113,24,63},{90,7,45},{61,0,22},{6,0,0},{212,72,117},{185,61,103},{161,51,89},{136,39,74},{112,25,58},{89,8,41},{60,0,18},{6,0,0},{212,72,110},{185,62,96},{161,51,83},{136,39,69},{112,25,53},{89,8,36},{60,0,14},{6,0,0},{211,72,103},{185,63,90},{161,52,77},{136,39,63},{112,26,48},{89,9,32},{60,0,9},{6,0,0},
-{211,72,96},{185,63,84},{161,52,71},{136,39,57},{112,26,43},{89,9,28},{60,0,6},{6,0,0},{211,73,89},{185,62,77},{160,52,64},{136,40,52},{112,27,38},{88,10,23},{59,1,3},{6,0,0},{211,73,81},{185,62,70},{160,52,58},{136,40,46},{112,27,32},{88,10,17},{59,1,2},{6,0,0},{212,73,73},{186,63,63},{161,52,52},{136,41,40},{112,28,26},{88,11,11},{59,1,1},{6,0,0},
-{212,73,65},{186,63,55},{161,52,44},{136,41,34},{112,28,20},{88,12,6},{59,1,1},{5,0,0},{212,73,56},{186,63,47},{161,53,37},{136,41,27},{112,29,13},{88,13,2},{58,1,0},{4,0,0},{212,73,49},{186,63,40},{161,53,31},{136,41,19},{112,29,8},{88,13,1},{58,1,0},{4,0,0},{212,73,42},{186,64,34},{161,52,25},{136,42,13},{112,29,3},{88,13,0},{58,1,0},{4,0,0},
-{208,43,146},{183,32,129},{160,25,112},{137,18,94},{113,11,77},{90,2,59},{61,0,34},{6,0,0},{209,45,139},{184,34,122},{161,26,106},{137,19,89},{112,11,72},{90,3,55},{61,0,31},{6,0,0},{210,46,131},{185,35,115},{161,26,100},{137,19,84},{112,12,68},{90,3,51},{61,0,28},{6,0,0},{210,47,125},{185,37,110},{160,26,95},{136,20,80},{113,12,64},{90,3,47},{61,0,24},{5,0,0},
-{210,48,118},{185,38,104},{160,27,90},{136,20,76},{113,12,60},{90,3,43},{61,0,20},{5,0,0},{211,49,112},{185,40,98},{161,29,85},{136,20,71},{112,13,55},{89,3,39},{60,0,16},{5,0,0},{211,50,105},{185,41,92},{161,30,80},{136,20,66},{112,13,50},{89,3,34},{60,0,12},{5,0,0},{211,50,99},{184,42,87},{161,31,74},{136,21,60},{112,13,46},{89,4,30},{60,0,8},{5,0,0},
-{211,51,93},{184,42,81},{161,32,68},{136,21,55},{112,13,41},{89,4,26},{60,0,6},{5,0,0},{211,52,86},{185,42,74},{160,33,62},{136,22,50},{112,14,36},{88,5,21},{59,1,3},{5,0,0},{211,52,79},{185,43,67},{160,34,56},{136,23,44},{112,14,31},{88,5,15},{59,1,2},{5,0,0},{212,53,71},{185,44,61},{161,35,50},{136,24,38},{112,14,25},{88,5,9},{59,1,1},{5,0,0},
-{212,53,63},{185,44,53},{161,35,43},{136,24,32},{112,14,19},{88,6,5},{59,1,1},{4,0,0},{212,53,55},{185,45,46},{161,36,37},{136,25,26},{111,15,12},{88,6,2},{58,1,0},{4,0,0},{212,53,49},{185,45,39},{161,36,30},{136,25,19},{111,15,7},{88,6,1},{58,1,0},{4,0,0},{212,53,42},{186,45,33},{161,37,25},{136,26,13},{112,15,3},{88,6,0},{58,1,0},{4,0,0},
-{207,15,140},{184,3,123},{159,0,106},{136,0,90},{112,0,73},{90,0,56},{61,0,31},{3,0,0},{208,17,133},{185,5,117},{160,1,101},{136,0,85},{112,0,69},{89,0,52},{61,0,28},{3,0,0},{209,19,125},{185,7,110},{160,1,95},{136,0,80},{112,0,64},{89,0,48},{61,0,25},{3,0,0},{209,21,119},{185,11,105},{160,2,91},{135,0,76},{112,0,60},{89,0,44},{60,0,21},{3,0,0},
-{209,22,113},{185,14,100},{160,4,86},{135,0,72},{112,0,56},{89,0,40},{60,0,18},{3,0,0},{210,24,107},{184,17,94},{160,6,81},{135,0,67},{112,0,52},{89,0,36},{60,0,13},{3,0,0},{210,26,101},{184,19,88},{160,8,76},{135,0,62},{112,0,47},{89,0,31},{60,0,9},{3,0,0},{210,27,95},{183,20,83},{160,10,71},{135,1,57},{112,0,43},{89,0,27},{60,0,7},{3,0,0},
-{210,29,89},{183,21,77},{160,12,65},{135,2,52},{112,0,39},{89,0,23},{60,0,5},{3,0,0},{210,30,82},{184,22,70},{160,14,60},{135,3,47},{111,0,34},{88,0,18},{59,0,3},{3,0,0},{210,31,76},{184,23,64},{160,16,54},{135,4,42},{111,0,29},{88,0,13},{59,0,1},{3,0,0},{211,31,69},{184,25,58},{160,18,48},{135,6,36},{111,0,23},{88,0,7},{58,0,0},{3,0,0},
-{211,32,61},{184,26,51},{160,18,42},{135,7,30},{111,0,17},{88,0,4},{58,0,0},{3,0,0},{211,33,54},{184,27,44},{160,19,36},{135,9,24},{111,1,10},{88,0,1},{58,0,0},{3,0,0},{211,33,48},{184,27,38},{160,20,30},{135,9,18},{111,1,6},{88,0,1},{58,0,0},{3,0,0},{211,34,42},{185,27,32},{160,21,24},{135,10,13},{111,1,2},{88,0,0},{58,0,0},{3,0,0},
-{175,226,249},{153,198,220},{132,173,192},{112,147,164},{91,121,135},{71,96,107},{45,65,75},{7,24,33},{177,225,236},{155,197,208},{134,172,181},{113,146,155},{92,120,128},{71,95,102},{45,64,70},{6,23,29},{179,224,223},{156,196,197},{135,172,171},{115,146,146},{93,120,121},{71,95,96},{45,64,65},{6,23,25},{181,223,211},{158,196,187},{137,171,162},{116,145,139},{94,120,114},{72,95,90},{45,64,61},{5,23,21},
-{182,223,199},{160,196,176},{138,170,154},{116,144,131},{94,120,107},{72,95,85},{45,64,56},{5,23,18},{183,222,187},{161,195,165},{139,169,144},{117,144,122},{95,119,101},{72,94,79},{45,63,52},{4,22,13},{184,221,174},{162,194,154},{139,169,134},{118,144,114},{95,119,94},{72,94,73},{45,63,47},{4,22,8},{185,220,161},{163,193,143},{140,168,124},{118,143,105},{96,118,86},{73,93,66},{46,62,42},{4,22,3},
-{187,219,149},{163,192,131},{141,167,114},{118,142,96},{96,118,79},{73,93,60},{46,62,37},{3,22,0},{189,218,137},{164,191,120},{142,166,105},{119,141,88},{96,117,72},{74,92,54},{45,62,31},{2,22,0},{190,218,123},{164,191,109},{142,166,94},{119,141,79},{96,117,64},{74,92,47},{45,62,25},{1,22,0},{191,217,109},{165,190,97},{143,166,84},{119,140,70},{96,116,55},{74,91,40},{45,61,19},{0,22,0},
-{191,217,93},{166,190,82},{143,165,71},{119,140,59},{96,116,45},{74,91,31},{45,61,11},{0,22,0},{192,216,77},{168,189,68},{144,164,57},{120,139,47},{97,115,35},{74,91,21},{46,61,3},{0,22,0},{193,216,62},{168,189,54},{144,164,45},{120,139,36},{97,115,24},{74,91,12},{46,61,1},{0,22,0},{194,216,46},{168,189,39},{144,164,33},{120,139,24},{97,114,13},{75,90,3},{45,60,0},{0,22,0},
-{176,213,240},{154,187,212},{134,163,186},{113,139,158},{92,115,131},{72,90,104},{46,60,72},{8,19,30},{178,212,228},{156,186,201},{136,163,176},{115,138,150},{93,114,124},{72,89,98},{46,60,67},{7,18,26},{179,212,216},{158,186,190},{137,163,166},{116,138,141},{94,114,117},{72,89,92},{46,60,62},{7,18,22},{182,211,204},{160,185,181},{138,162,157},{117,137,134},{95,113,110},{73,89,87},{46,59,58},{6,18,18},
-{183,210,193},{161,185,170},{139,161,149},{117,137,127},{95,113,103},{74,89,82},{46,59,54},{6,18,14},{185,209,181},{162,184,160},{140,160,139},{118,136,118},{96,112,97},{73,88,76},{46,59,49},{6,17,10},{186,209,169},{162,183,149},{140,160,130},{118,136,110},{96,112,90},{73,88,70},{46,59,44},{6,17,5},{186,208,156},{163,182,138},{141,159,120},{119,135,102},{96,111,83},{74,87,63},{47,58,39},{5,18,2},
-{187,207,144},{163,182,127},{141,158,111},{119,135,93},{96,111,76},{74,87,57},{47,58,34},{4,18,0},{188,206,133},{164,181,117},{142,157,102},{119,134,85},{96,110,69},{74,87,51},{46,58,29},{4,17,0},{189,206,120},{165,181,106},{142,157,92},{119,134,76},{96,110,61},{74,87,45},{46,58,23},{2,17,0},{191,205,107},{166,180,94},{142,157,82},{119,133,67},{97,110,53},{75,86,38},{46,57,17},{1,18,0},
-{191,205,91},{167,180,80},{143,156,69},{119,133,57},{97,110,44},{75,86,29},{46,57,9},{1,18,0},{192,204,76},{168,180,66},{144,155,56},{120,132,45},{97,109,34},{75,86,19},{46,57,2},{0,17,0},{193,204,61},{168,180,52},{144,155,44},{120,132,35},{97,109,23},{75,86,10},{46,57,1},{0,17,0},{194,204,47},{167,179,40},{144,155,32},{120,132,24},{97,109,12},{75,85,2},{46,56,0},{0,17,0},
-{177,201,232},{155,177,204},{135,154,179},{114,131,152},{93,107,127},{72,84,101},{47,55,70},{9,13,27},{179,200,220},{157,177,193},{137,154,169},{116,130,144},{94,107,120},{73,83,95},{47,55,65},{8,13,23},{180,200,208},{159,177,183},{138,154,160},{117,130,136},{95,107,113},{73,83,89},{47,55,60},{8,13,19},{182,199,197},{160,176,174},{139,153,151},{117,129,129},{96,106,107},{74,83,84},{47,54,56},{7,13,15},
-{183,198,186},{161,175,164},{139,152,143},{117,129,122},{96,106,100},{74,83,79},{47,54,52},{7,13,11},{185,197,175},{162,174,154},{140,151,134},{118,128,115},{96,105,94},{74,82,73},{48,54,47},{6,12,7},{186,197,163},{162,174,144},{140,151,126},{118,128,107},{96,105,87},{74,82,67},{48,54,42},{6,12,3},{186,196,151},{163,173,134},{141,150,117},{119,127,99},{96,104,80},{75,81,61},{47,53,37},{6,13,1},
-{187,196,140},{163,173,124},{141,150,108},{119,127,91},{96,104,73},{75,81,55},{47,53,32},{5,13,0},{188,195,129},{164,172,114},{142,149,99},{119,126,83},{96,103,66},{74,81,49},{47,53,27},{4,12,0},{189,195,118},{165,172,103},{142,149,90},{119,126,74},{96,103,59},{74,81,43},{47,53,21},{3,12,0},{191,194,105},{166,171,92},{143,148,80},{119,125,65},{97,103,52},{75,80,36},{47,53,15},{1,13,0},
-{191,194,90},{167,171,79},{143,148,68},{119,125,56},{97,103,43},{75,80,27},{47,53,8},{1,13,0},{192,193,76},{168,170,65},{144,147,56},{120,125,44},{97,102,33},{75,80,17},{47,53,2},{0,12,0},{192,193,61},{168,170,52},{144,147,44},{120,125,34},{97,102,23},{75,80,9},{47,53,1},{0,12,0},{193,193,48},{167,169,40},{144,146,31},{120,124,24},{98,102,12},{75,79,2},{46,53,0},{0,13,0},
-{178,189,224},{156,168,198},{136,145,173},{115,124,148},{95,101,123},{74,79,97},{48,51,67},{10,7,24},{180,188,213},{158,167,188},{137,145,164},{116,123,140},{96,101,116},{74,79,91},{48,51,62},{9,7,20},{181,188,201},{160,167,178},{138,145,156},{116,123,132},{96,101,109},{74,79,85},{48,51,57},{9,7,16},{182,188,191},{161,166,169},{139,144,147},{117,122,125},{96,100,103},{75,79,81},{48,50,53},{9,8,12},
-{183,188,180},{161,166,160},{140,144,139},{118,122,118},{96,100,96},{75,79,76},{48,50,49},{9,8,7},{185,187,170},{162,165,150},{140,143,130},{118,122,111},{96,99,90},{75,78,70},{48,50,45},{8,8,4},{186,187,159},{162,165,140},{140,143,122},{118,122,103},{96,99,84},{75,78,64},{48,50,40},{7,8,1},{187,186,147},{163,164,130},{141,142,113},{119,121,96},{97,99,77},{75,77,59},{48,49,35},{6,9,0},
-{187,185,136},{163,164,120},{141,142,104},{119,121,88},{97,99,71},{75,77,53},{48,49,30},{6,9,0},{188,184,125},{164,163,110},{142,141,95},{120,120,80},{97,98,64},{75,77,47},{48,49,25},{4,8,0},{189,184,114},{165,163,100},{142,141,86},{120,120,72},{97,98,57},{75,77,41},{48,49,19},{3,8,0},{190,184,102},{166,162,90},{143,140,77},{120,119,63},{98,98,50},{75,76,34},{48,49,13},{1,9,0},
-{190,184,88},{166,162,77},{143,140,66},{120,119,54},{98,98,41},{75,76,25},{48,49,7},{1,9,0},{191,183,74},{167,161,64},{144,139,54},{120,119,43},{98,97,31},{75,76,15},{47,49,2},{1,8,0},{191,183,60},{167,161,52},{144,139,43},{120,119,33},{98,97,21},{75,76,8},{47,49,1},{1,8,0},{192,182,48},{168,160,40},{144,139,32},{121,118,24},{98,97,11},{76,75,2},{47,49,0},{0,9,0},
-{178,178,216},{157,158,192},{136,137,168},{115,116,143},{95,95,119},{75,74,94},{49,47,64},{11,2,21},{180,177,205},{159,157,182},{137,136,159},{116,116,136},{96,95,112},{74,74,88},{49,46,59},{10,3,17},{182,177,194},{160,157,172},{138,136,151},{116,116,128},{96,95,105},{74,74,82},{49,46,54},{10,3,13},{183,177,184},{161,156,164},{140,136,143},{117,115,121},{96,94,99},{75,73,78},{49,46,50},{9,3,9},
-{184,177,175},{162,156,155},{141,136,135},{118,115,114},{96,94,93},{75,73,73},{49,46,46},{9,3,4},{186,176,165},{162,155,145},{140,135,126},{119,114,107},{97,93,87},{75,73,67},{48,46,42},{9,3,2},{187,176,154},{162,155,135},{140,135,118},{119,114,100},{97,93,81},{75,73,61},{48,46,37},{8,3,0},{187,175,143},{163,154,126},{141,134,109},{119,114,93},{97,93,74},{75,72,56},{49,45,32},{7,4,0},
-{187,175,132},{163,154,116},{141,134,101},{119,114,85},{97,93,68},{75,72,50},{49,45,28},{6,4,0},{188,174,122},{164,153,107},{142,133,92},{120,113,78},{98,92,61},{75,72,45},{48,45,23},{4,4,0},{188,174,111},{165,153,97},{142,133,83},{120,113,69},{98,92,55},{75,72,39},{48,45,17},{3,4,0},{189,173,99},{166,153,87},{143,133,74},{120,112,61},{98,92,48},{75,72,32},{48,45,10},{1,4,0},
-{190,173,86},{166,153,75},{143,133,64},{120,112,52},{98,92,39},{75,72,24},{48,45,6},{1,4,0},{191,173,73},{166,152,63},{144,132,53},{120,111,42},{98,91,30},{75,71,14},{47,45,2},{1,4,0},{191,173,60},{167,152,52},{144,132,43},{120,111,33},{98,91,20},{75,71,8},{47,45,1},{1,4,0},{191,172,48},{168,152,41},{144,131,32},{121,111,23},{98,91,11},{76,71,2},{47,45,0},{0,5,0},
-{180,166,209},{158,147,185},{137,128,162},{116,109,138},{96,88,114},{76,68,90},{50,41,61},{12,1,19},{181,166,198},{160,147,175},{138,127,153},{117,108,131},{96,88,108},{75,68,84},{50,41,57},{11,1,14},{182,166,188},{161,147,166},{139,127,145},{118,108,124},{96,88,101},{75,68,79},{50,41,52},{11,1,9},{183,165,178},{162,146,158},{140,127,138},{118,108,117},{97,87,96},{76,67,75},{50,41,48},{10,2,5},
-{184,165,169},{162,146,149},{141,127,130},{119,108,110},{97,87,90},{76,67,70},{50,41,44},{10,2,2},{185,164,159},{163,145,140},{141,126,122},{120,107,103},{97,87,84},{75,67,64},{49,41,40},{10,2,1},{186,164,148},{163,145,131},{141,126,114},{120,107,96},{97,87,78},{75,67,59},{49,41,35},{8,2,0},{186,164,139},{163,144,122},{141,126,106},{119,107,89},{97,86,72},{76,66,54},{49,41,30},{7,2,0},
-{187,164,128},{164,144,113},{142,126,98},{119,107,83},{97,86,66},{76,66,48},{49,41,26},{6,2,0},{188,163,119},{165,143,104},{143,125,90},{120,106,76},{98,86,59},{76,66,43},{49,41,21},{5,2,0},{188,163,108},{165,143,95},{143,125,81},{120,106,67},{98,86,53},{76,66,37},{49,41,15},{4,2,0},{189,162,97},{165,143,85},{142,124,72},{121,105,59},{98,85,46},{76,66,30},{48,41,8},{3,2,0},
-{189,162,84},{166,143,73},{142,124,62},{121,105,50},{98,85,38},{76,66,22},{48,41,4},{3,2,0},{190,162,72},{166,142,61},{143,123,51},{120,104,40},{98,85,29},{76,65,13},{48,41,1},{3,2,0},{190,162,60},{167,142,51},{143,123,42},{120,104,31},{98,85,19},{76,65,7},{48,41,1},{2,2,0},{190,161,48},{167,142,41},{143,123,32},{121,104,22},{98,85,10},{76,65,1},{48,41,0},{1,2,0},
-{180,155,201},{159,137,179},{137,120,156},{117,101,133},{96,82,110},{76,62,86},{50,36,58},{11,0,16},{181,154,191},{160,136,169},{138,119,148},{118,100,126},{97,81,104},{76,62,81},{50,36,54},{11,0,11},{182,154,182},{161,136,160},{139,119,140},{119,100,119},{97,81,98},{76,62,76},{50,36,49},{11,0,6},{183,154,172},{162,136,152},{140,118,133},{119,100,113},{97,81,93},{76,61,72},{50,36,45},{11,0,2},
-{184,154,163},{162,136,144},{141,118,125},{119,100,106},{97,81,87},{76,61,67},{50,36,41},{10,0,0},{185,153,153},{163,135,135},{141,118,117},{120,99,100},{97,80,81},{75,61,61},{50,36,37},{9,0,0},{185,153,143},{163,135,127},{141,118,110},{120,99,93},{97,80,75},{75,61,56},{50,36,32},{7,0,0},{186,153,134},{163,135,118},{141,118,103},{119,99,86},{97,80,69},{76,61,51},{49,36,28},{6,0,0},
-{187,153,124},{164,135,109},{142,118,95},{119,99,80},{97,80,63},{76,61,46},{49,36,24},{5,0,0},{188,152,115},{165,134,101},{143,117,87},{120,98,73},{98,79,57},{76,60,41},{49,36,19},{4,0,0},{188,152,105},{165,134,92},{143,117,79},{120,98,65},{98,79,51},{76,60,34},{49,36,13},{4,0,0},{189,151,95},{165,134,82},{142,116,70},{121,97,57},{98,79,44},{76,60,28},{48,36,6},{4,0,0},
-{189,151,82},{165,134,71},{142,116,60},{121,97,48},{98,79,36},{76,60,20},{48,36,3},{4,0,0},{190,151,70},{166,133,60},{143,115,50},{120,97,39},{98,79,27},{76,59,11},{48,36,1},{3,0,0},{190,151,60},{166,133,50},{143,115,41},{120,97,30},{98,79,18},{76,59,7},{48,36,1},{3,0,0},{190,150,48},{167,133,41},{143,115,32},{121,96,22},{98,79,9},{76,59,1},{48,36,0},{2,0,0},
-{181,144,194},{159,127,173},{138,111,151},{118,94,128},{97,75,106},{76,56,83},{51,30,55},{9,0,12},{182,143,184},{160,127,163},{139,110,143},{119,93,121},{98,74,100},{76,55,78},{50,31,51},{10,0,7},{183,143,175},{161,127,154},{139,110,135},{119,93,114},{98,74,94},{76,55,73},{50,31,46},{10,0,3},{184,143,166},{162,127,147},{140,110,128},{119,93,108},{98,74,89},{76,55,69},{50,31,42},{8,0,1},
-{184,143,158},{162,127,139},{140,110,120},{119,93,102},{98,74,84},{76,55,64},{50,31,38},{7,0,0},{185,142,148},{163,126,130},{141,109,113},{120,92,96},{98,73,78},{76,56,59},{50,31,34},{6,0,0},{185,142,139},{163,126,122},{141,109,106},{120,92,90},{98,73,72},{76,56,54},{50,31,30},{6,0,0},{186,142,130},{164,125,113},{141,109,99},{120,92,83},{98,73,66},{76,55,49},{50,31,26},{5,0,0},
-{186,142,120},{164,125,105},{141,109,91},{120,92,77},{98,73,60},{76,55,43},{50,31,21},{4,0,0},{187,141,111},{164,125,98},{142,108,84},{119,91,70},{98,72,54},{76,55,38},{50,31,16},{4,0,0},{188,141,102},{165,125,89},{142,108,76},{119,91,62},{98,72,48},{76,55,32},{50,31,10},{4,0,0},{189,141,92},{165,124,80},{142,107,68},{120,90,55},{98,72,42},{76,55,26},{49,31,4},{3,0,0},
-{189,141,80},{165,124,70},{142,107,59},{120,90,47},{98,72,35},{76,55,19},{49,31,2},{3,0,0},{189,141,68},{165,124,59},{142,107,49},{120,90,38},{98,72,26},{77,54,10},{49,31,0},{2,0,0},{189,141,59},{165,124,49},{142,107,40},{120,90,29},{98,72,17},{77,54,6},{49,31,0},{2,0,0},{190,141,49},{166,124,41},{143,107,31},{120,89,21},{98,72,8},{76,54,1},{48,31,0},{1,0,0},
-{181,133,187},{159,117,167},{138,102,145},{118,86,124},{98,68,102},{76,50,79},{51,23,52},{7,0,8},{182,133,178},{160,117,157},{139,101,137},{119,85,117},{98,68,96},{76,49,74},{50,24,48},{7,0,4},{183,133,169},{161,117,148},{139,101,130},{119,85,110},{98,68,90},{76,49,69},{50,25,44},{7,0,1},{184,133,160},{162,117,141},{140,101,123},{119,85,104},{98,68,85},{77,49,65},{50,25,40},{6,0,0},
-{184,133,152},{163,117,134},{140,101,116},{119,85,98},{98,68,80},{77,49,61},{50,25,36},{6,0,0},{185,132,143},{163,116,126},{141,101,109},{120,84,92},{98,67,74},{77,50,57},{50,25,32},{5,0,0},{186,132,135},{163,116,118},{141,101,102},{120,84,86},{98,67,69},{77,50,52},{50,25,28},{4,0,0},{186,132,126},{164,115,109},{141,100,95},{120,84,80},{98,67,64},{77,49,47},{50,25,24},{4,0,0},
-{186,132,116},{164,115,101},{141,100,88},{120,84,74},{98,67,58},{77,49,41},{50,25,19},{3,0,0},{187,131,107},{164,115,94},{141,100,81},{119,84,67},{98,66,52},{76,49,36},{50,26,14},{2,0,0},{188,131,98},{164,115,86},{141,100,74},{119,84,60},{98,66,46},{76,49,30},{50,26,8},{2,0,0},{188,131,89},{165,114,78},{142,99,66},{120,83,53},{98,66,40},{76,49,24},{49,26,3},{2,0,0},
-{188,131,78},{165,114,68},{142,99,57},{120,83,45},{98,66,33},{76,49,17},{49,26,1},{1,0,0},{189,131,66},{165,114,57},{142,99,47},{120,83,36},{98,66,24},{77,49,8},{49,27,0},{1,0,0},{189,131,57},{165,114,49},{142,99,39},{120,83,28},{98,66,15},{77,49,4},{49,27,0},{1,0,0},{189,131,49},{166,114,40},{143,99,31},{120,83,20},{98,66,7},{76,49,1},{48,27,0},{1,0,0},
-{182,122,180},{160,107,160},{138,93,139},{118,77,119},{98,61,98},{77,43,76},{51,16,49},{5,0,4},{183,122,171},{161,107,151},{139,92,132},{119,77,113},{98,61,92},{77,43,71},{51,17,45},{5,0,2},{184,122,162},{162,107,143},{140,92,125},{119,77,106},{98,61,86},{77,43,66},{51,18,42},{5,0,0},{185,122,154},{162,107,136},{140,92,119},{119,77,100},{98,61,81},{77,43,62},{50,18,38},{4,0,0},
-{185,122,146},{162,107,129},{140,92,112},{119,77,94},{98,61,76},{77,43,58},{50,18,34},{4,0,0},{185,122,138},{163,107,122},{141,92,105},{119,77,88},{98,60,71},{77,44,54},{51,19,30},{3,0,0},{185,122,130},{163,107,114},{141,92,98},{119,77,83},{98,60,66},{77,44,49},{51,19,26},{3,0,0},{186,121,121},{163,106,105},{142,91,91},{119,77,77},{98,60,61},{77,43,44},{50,20,22},{2,0,0},
-{186,121,112},{163,106,98},{142,91,85},{119,77,71},{98,60,56},{77,43,40},{50,20,17},{1,0,0},{187,121,104},{164,106,91},{142,91,78},{119,77,64},{98,60,51},{77,43,35},{50,21,12},{1,0,0},{187,121,95},{164,106,83},{142,91,71},{119,77,58},{98,60,45},{77,43,29},{50,21,7},{1,0,0},{187,121,86},{164,105,75},{142,91,64},{119,76,52},{98,60,39},{77,43,23},{49,21,3},{1,0,0},
-{187,121,76},{164,105,66},{142,91,56},{119,76,44},{98,60,31},{77,43,15},{49,21,1},{1,0,0},{188,120,65},{165,105,56},{142,91,46},{120,76,35},{98,59,23},{76,43,7},{48,21,0},{0,0,0},{188,120,56},{165,105,48},{142,91,38},{120,76,27},{98,59,14},{76,43,3},{48,21,0},{0,0,0},{188,120,48},{165,105,39},{143,90,30},{120,76,20},{98,59,6},{76,43,0},{48,22,0},{0,0,0},
-{182,110,173},{160,96,153},{139,83,134},{118,68,114},{98,53,94},{77,36,73},{51,10,46},{3,0,2},{183,110,164},{161,96,145},{140,83,127},{119,69,108},{98,53,89},{77,36,68},{51,11,42},{3,0,1},{184,110,156},{162,96,137},{140,83,120},{119,69,101},{98,53,83},{77,36,63},{51,11,39},{3,0,0},{185,110,149},{162,96,131},{141,83,114},{119,69,96},{98,53,78},{77,36,59},{50,12,35},{2,0,0},
-{185,110,141},{162,96,124},{141,83,107},{119,69,91},{98,53,73},{77,36,55},{50,12,31},{2,0,0},{185,110,133},{163,97,117},{141,83,101},{119,68,85},{98,53,68},{77,37,51},{51,12,27},{1,0,0},{185,110,125},{163,97,109},{141,83,95},{119,68,80},{98,53,63},{77,37,46},{51,12,23},{1,0,0},{186,110,117},{163,96,102},{142,82,88},{119,69,74},{98,53,58},{77,37,41},{50,13,19},{1,0,0},
-{186,110,109},{163,96,95},{142,82,82},{119,69,68},{98,53,53},{77,37,37},{50,13,14},{1,0,0},{187,110,101},{164,96,88},{142,82,75},{119,68,61},{98,53,48},{77,37,32},{50,14,10},{1,0,0},{187,110,92},{164,96,80},{142,82,69},{119,68,55},{98,53,42},{77,37,27},{50,14,5},{1,0,0},{187,110,84},{164,96,73},{142,82,62},{119,68,49},{98,53,36},{77,37,21},{49,15,3},{0,0,0},
-{187,110,74},{164,96,64},{142,82,54},{119,68,42},{98,53,29},{77,37,13},{49,15,1},{0,0,0},{188,109,64},{165,96,55},{142,82,45},{120,68,34},{98,53,21},{76,37,6},{48,15,0},{0,0,0},{188,109,55},{165,96,47},{142,82,37},{120,68,26},{98,53,13},{76,37,3},{48,15,0},{0,0,0},{188,109,47},{165,95,39},{143,82,30},{120,68,19},{98,53,6},{76,37,0},{48,16,0},{0,0,0},
-{182,98,167},{160,86,147},{139,73,128},{119,59,109},{98,44,90},{77,27,70},{51,4,44},{1,0,0},{183,98,158},{161,86,139},{140,73,122},{120,60,103},{98,44,85},{78,28,65},{51,5,40},{1,0,0},{183,98,150},{162,86,131},{141,73,115},{120,60,97},{98,44,79},{78,28,61},{51,5,37},{1,0,0},{184,98,143},{162,86,125},{141,73,109},{120,60,93},{98,45,75},{77,29,57},{50,5,33},{1,0,0},
-{185,98,136},{162,86,118},{141,73,103},{120,60,88},{98,45,70},{77,29,53},{50,5,29},{1,0,0},{185,98,128},{163,87,112},{141,73,97},{120,59,82},{98,46,65},{77,30,49},{50,5,25},{0,0,0},{185,98,120},{163,87,105},{141,73,91},{120,59,76},{98,46,60},{77,30,44},{50,5,21},{0,0,0},{186,98,113},{163,86,98},{141,73,85},{120,60,71},{98,46,55},{77,30,39},{50,6,16},{0,0,0},
-{186,98,105},{163,86,92},{141,73,79},{120,60,65},{98,46,51},{77,30,35},{50,6,12},{0,0,0},{186,98,98},{163,86,85},{141,73,73},{120,59,59},{98,46,46},{76,30,30},{49,7,8},{0,0,0},{186,98,90},{163,86,78},{141,73,67},{120,59,53},{98,46,40},{76,30,25},{49,7,4},{0,0,0},{187,98,81},{163,86,71},{141,73,60},{119,60,47},{98,46,34},{76,31,19},{48,8,2},{0,0,0},
-{187,98,72},{163,86,62},{141,73,52},{119,60,40},{98,46,27},{76,31,11},{48,8,1},{0,0,0},{187,98,62},{164,86,53},{142,73,43},{119,60,33},{98,46,19},{76,31,5},{48,9,0},{0,0,0},{187,98,54},{164,86,45},{142,73,36},{119,60,25},{98,46,12},{76,31,2},{48,9,0},{0,0,0},{188,98,47},{165,85,38},{143,73,29},{120,60,18},{98,47,6},{76,31,0},{47,10,0},{0,0,0},
-{182,84,161},{160,73,141},{139,61,123},{119,48,104},{98,33,86},{77,17,66},{51,2,41},{1,0,0},{183,84,152},{161,73,134},{140,62,117},{120,49,99},{98,34,81},{78,18,62},{51,2,37},{1,0,0},{183,84,144},{162,73,126},{141,62,110},{120,49,93},{98,34,75},{78,18,58},{51,2,34},{1,0,0},{184,84,138},{162,73,120},{141,62,105},{120,49,89},{98,35,71},{77,19,54},{50,2,30},{0,0,0},
-{185,84,131},{162,73,114},{141,62,99},{120,49,84},{98,35,67},{77,19,50},{50,2,26},{0,0,0},{185,85,123},{163,74,108},{141,63,93},{120,50,79},{98,36,62},{77,19,46},{50,2,22},{0,0,0},{185,85,116},{163,74,101},{141,63,88},{120,50,73},{98,36,57},{77,19,41},{50,2,18},{0,0,0},{186,85,109},{163,75,95},{141,63,82},{120,50,68},{98,36,52},{77,20,36},{50,2,13},{0,0,0},
-{186,85,102},{163,75,89},{141,63,76},{120,50,62},{98,36,48},{77,20,32},{50,2,9},{0,0,0},{186,85,95},{163,74,82},{141,63,70},{120,50,56},{98,37,43},{76,20,27},{49,3,6},{0,0,0},{186,85,87},{163,74,75},{141,63,64},{120,50,50},{98,37,37},{76,21,22},{49,3,3},{0,0,0},{187,85,79},{163,74,68},{141,63,57},{119,51,44},{98,38,31},{76,21,16},{48,4,2},{0,0,0},
-{187,85,71},{163,74,60},{141,63,50},{119,51,38},{98,38,25},{76,21,10},{48,4,1},{0,0,0},{187,85,61},{164,75,52},{142,63,42},{119,51,32},{98,38,18},{76,22,4},{48,5,0},{0,0,0},{187,85,54},{164,75,45},{142,63,36},{119,51,24},{98,38,12},{76,22,2},{48,5,0},{0,0,0},{188,85,47},{165,74,38},{143,63,29},{120,51,18},{98,38,6},{76,23,0},{47,5,0},{0,0,0},
-{182,69,154},{160,59,136},{140,48,118},{119,36,100},{98,21,82},{78,5,62},{51,0,38},{0,0,0},{183,70,146},{161,60,129},{141,49,112},{120,37,95},{98,22,77},{78,6,58},{50,0,34},{0,0,0},{184,70,138},{162,60,121},{141,49,106},{120,37,89},{98,22,71},{78,6,54},{50,0,31},{0,0,0},{185,71,132},{162,60,115},{140,50,101},{120,38,85},{99,23,67},{78,7,50},{50,0,27},{0,0,0},
-{185,71,125},{162,60,110},{140,50,95},{120,38,80},{99,23,63},{78,7,46},{50,0,24},{0,0,0},{185,72,119},{162,61,104},{140,51,89},{120,38,75},{98,24,59},{77,7,42},{50,0,20},{0,0,0},{185,72,112},{162,62,97},{140,51,84},{120,38,70},{98,25,54},{77,7,38},{50,0,15},{0,0,0},{185,72,105},{162,63,91},{140,51,78},{119,39,64},{98,26,49},{77,8,33},{50,0,10},{0,0,0},
-{185,72,98},{162,63,85},{140,51,72},{119,39,59},{98,26,45},{77,9,29},{50,0,7},{0,0,0},{186,73,91},{163,62,79},{141,51,67},{119,40,54},{98,27,40},{77,10,25},{50,1,4},{0,0,0},{186,73,84},{163,62,73},{141,51,61},{119,40,48},{98,27,35},{77,10,20},{50,1,2},{0,0,0},{186,73,77},{163,63,66},{141,51,55},{120,41,42},{98,28,29},{76,11,14},{49,1,1},{0,0,0},
-{186,73,69},{163,63,58},{141,51,48},{120,41,36},{98,28,23},{76,11,9},{49,1,1},{0,0,0},{187,72,60},{163,63,51},{141,52,41},{120,41,30},{98,29,17},{76,12,4},{48,1,0},{0,0,0},{187,72,53},{163,63,44},{141,52,35},{120,41,23},{98,29,10},{76,12,2},{48,1,0},{0,0,0},{187,72,46},{164,63,38},{142,52,29},{119,41,17},{98,29,4},{76,13,0},{48,1,0},{0,0,0},
-{182,49,147},{160,37,130},{140,26,113},{119,18,95},{98,10,77},{78,2,59},{51,0,35},{0,0,0},{183,50,140},{161,39,123},{141,28,107},{120,19,90},{98,11,73},{78,3,55},{50,0,32},{0,0,0},{184,50,132},{162,40,116},{141,29,101},{120,19,85},{98,11,69},{78,3,52},{50,0,29},{0,0,0},{185,51,126},{162,41,110},{140,30,96},{120,20,81},{99,12,65},{78,3,48},{50,0,25},{0,0,0},
-{185,52,120},{162,42,105},{140,31,91},{120,21,77},{99,12,61},{78,3,44},{50,0,21},{0,0,0},{185,53,114},{162,44,99},{140,33,86},{120,22,72},{98,12,56},{77,3,40},{50,0,17},{0,0,0},{185,54,108},{162,45,94},{140,34,81},{120,22,67},{98,13,52},{77,3,36},{50,0,13},{0,0,0},{185,54,101},{162,45,88},{140,34,75},{119,23,61},{98,13,47},{77,4,31},{50,0,9},{0,0,0},
-{185,55,94},{162,45,82},{140,35,70},{119,24,57},{98,13,43},{77,4,27},{50,0,6},{0,0,0},{186,55,87},{163,46,76},{141,36,65},{119,25,52},{98,14,38},{77,5,23},{50,1,4},{0,0,0},{186,55,81},{163,46,70},{141,37,59},{119,25,47},{98,14,33},{77,5,18},{50,1,2},{0,0,0},{186,56,75},{163,47,64},{141,37,53},{120,26,41},{98,15,28},{76,5,12},{49,1,1},{0,0,0},
-{186,56,67},{163,47,57},{141,38,47},{120,27,35},{98,15,22},{76,5,8},{49,1,1},{0,0,0},{187,56,59},{163,47,50},{141,38,40},{120,28,29},{98,16,16},{76,6,3},{48,1,0},{0,0,0},{187,56,53},{163,47,43},{141,38,34},{120,28,23},{98,16,10},{76,6,2},{48,1,0},{0,0,0},{187,56,46},{164,48,37},{142,39,29},{119,28,17},{98,16,4},{76,6,0},{48,1,0},{0,0,0},
-{183,28,141},{161,16,124},{140,3,108},{119,0,91},{99,0,73},{78,0,56},{50,0,32},{0,0,0},{184,29,134},{162,18,118},{140,6,102},{120,0,86},{99,0,69},{78,0,52},{50,0,29},{0,0,0},{184,29,127},{162,19,111},{140,8,96},{120,1,81},{99,0,66},{78,0,49},{50,0,26},{0,0,0},{185,31,121},{162,21,106},{141,9,92},{120,2,77},{99,0,62},{78,0,45},{50,0,22},{0,0,0},
-{185,32,116},{162,23,101},{141,11,87},{120,2,73},{99,0,58},{78,0,41},{50,0,19},{0,0,0},{185,34,110},{162,25,95},{140,14,82},{120,3,68},{99,0,53},{78,0,37},{49,0,14},{0,0,0},{185,35,104},{162,26,90},{140,16,77},{120,4,63},{99,0,49},{78,0,33},{49,0,10},{0,0,0},{185,35,97},{162,27,84},{140,17,72},{119,5,58},{99,0,45},{77,0,29},{49,0,7},{0,0,0},
-{185,36,91},{162,28,78},{140,19,67},{119,6,54},{99,0,41},{77,0,25},{49,0,5},{0,0,0},{185,37,84},{162,29,73},{140,20,62},{119,7,50},{98,1,36},{77,0,21},{49,0,4},{0,0,0},{185,38,78},{162,30,67},{140,21,56},{119,9,45},{98,1,31},{77,0,15},{49,0,2},{0,0,0},{185,39,72},{163,31,61},{140,22,50},{119,10,39},{98,1,26},{76,0,9},{48,0,0},{0,0,0},
-{185,39,65},{163,31,55},{140,23,45},{119,11,33},{98,2,20},{76,0,6},{48,0,0},{0,0,0},{186,38,58},{163,31,48},{141,24,39},{119,13,27},{98,3,14},{76,0,2},{47,0,0},{0,0,0},{186,38,52},{163,32,42},{141,24,33},{119,13,22},{98,3,9},{76,0,1},{47,0,0},{0,0,0},{186,39,46},{163,33,36},{141,25,28},{119,14,17},{98,3,4},{76,0,0},{47,0,0},{0,0,0},
-{132,213,247},{116,187,218},{101,164,190},{84,139,162},{67,114,135},{49,90,107},{25,61,75},{0,21,33},{135,212,234},{119,186,206},{103,163,180},{86,138,153},{69,114,128},{50,89,101},{25,61,70},{0,21,29},{138,212,221},{122,186,195},{105,163,171},{88,138,145},{70,114,120},{52,89,95},{25,61,65},{0,21,26},{141,211,209},{124,185,186},{107,162,162},{90,137,138},{72,113,114},{53,89,90},{26,60,61},{0,21,22},
-{144,210,198},{126,185,175},{109,162,153},{90,137,131},{72,113,107},{53,89,85},{26,60,57},{0,21,18},{145,209,187},{128,184,165},{109,161,144},{91,136,122},{73,112,101},{53,88,79},{27,60,52},{0,20,14},{147,209,174},{129,184,154},{110,161,134},{92,136,114},{73,112,94},{53,88,73},{27,60,47},{0,20,9},{148,208,162},{129,183,143},{112,160,125},{93,135,105},{74,111,87},{54,87,66},{28,60,42},{0,21,4},
-{150,207,150},{130,182,132},{113,159,115},{94,135,97},{75,111,80},{55,87,60},{28,60,37},{0,21,1},{152,206,138},{132,181,122},{114,158,105},{94,134,89},{75,111,73},{56,87,55},{28,59,32},{0,20,0},{154,206,126},{134,181,111},{114,158,95},{94,134,81},{75,111,65},{56,87,49},{28,59,26},{0,20,0},{155,206,112},{135,180,99},{115,157,85},{95,133,72},{76,110,57},{56,86,42},{29,59,20},{0,20,0},
-{155,206,99},{136,180,86},{116,157,74},{96,133,62},{76,110,48},{56,86,33},{29,59,13},{0,20,0},{157,205,84},{137,180,74},{117,156,62},{97,132,51},{77,109,39},{57,86,25},{29,58,4},{0,20,0},{158,205,71},{137,180,62},{117,156,52},{97,132,42},{77,109,30},{57,86,16},{29,58,2},{0,20,0},{160,204,58},{139,180,51},{118,156,42},{97,132,33},{77,108,22},{57,86,7},{29,58,0},{0,20,0},
-{136,202,239},{120,178,211},{104,155,184},{87,132,157},{69,108,131},{52,85,104},{28,57,72},{0,16,30},{138,201,226},{122,177,200},{106,154,174},{89,131,149},{71,108,124},{53,84,98},{28,56,67},{0,16,26},{141,200,214},{124,177,189},{108,154,165},{90,131,140},{72,108,116},{53,84,91},{28,56,62},{0,16,23},{144,199,203},{126,176,180},{110,153,156},{91,130,133},{73,107,110},{54,84,87},{29,56,58},{0,16,19},
-{146,199,192},{128,176,170},{111,153,148},{92,130,126},{74,107,103},{55,84,82},{29,56,54},{0,16,15},{148,198,181},{129,175,160},{112,152,139},{93,129,118},{75,106,97},{55,83,76},{30,56,50},{0,15,11},{149,198,169},{130,174,149},{113,152,130},{94,129,110},{75,106,90},{55,83,70},{30,56,45},{0,15,6},{150,197,157},{131,173,138},{114,151,121},{95,128,102},{76,106,83},{56,83,64},{30,56,40},{0,16,2},
-{152,196,145},{132,173,128},{114,150,112},{95,128,94},{76,106,77},{56,83,58},{30,56,35},{0,16,0},{154,195,134},{134,172,118},{115,149,102},{96,127,86},{76,105,70},{57,82,52},{30,55,30},{0,15,0},{155,195,123},{135,172,108},{115,149,93},{96,127,78},{76,105,62},{57,82,46},{30,55,24},{0,15,0},{157,195,110},{136,171,96},{116,148,83},{97,126,69},{77,104,55},{58,82,40},{30,55,18},{0,15,0},
-{157,195,96},{137,171,84},{117,148,72},{97,126,60},{77,104,46},{58,82,31},{30,55,11},{0,15,0},{158,194,83},{138,171,72},{118,147,60},{98,125,50},{78,103,37},{58,81,23},{30,54,3},{0,15,0},{159,194,70},{139,171,61},{118,147,51},{98,125,41},{78,103,29},{58,81,15},{30,54,1},{0,15,0},{160,193,58},{140,170,50},{118,147,41},{98,125,32},{78,103,21},{58,81,6},{30,54,0},{0,15,0},
-{139,190,231},{122,168,203},{106,146,177},{88,124,152},{71,102,126},{53,79,101},{30,52,70},{0,11,28},{142,189,218},{124,168,192},{108,145,168},{90,123,143},{73,101,119},{54,79,95},{31,52,65},{0,10,24},{144,189,206},{126,168,182},{109,145,159},{92,123,135},{74,101,112},{55,79,88},{31,52,60},{0,10,21},{146,188,196},{128,167,173},{111,144,150},{93,122,128},{75,100,106},{56,78,84},{31,51,56},{0,10,17},
-{148,188,185},{129,167,164},{113,144,142},{94,122,121},{76,100,100},{57,78,79},{31,51,52},{0,10,13},{150,187,174},{131,166,154},{114,143,134},{95,121,115},{76,100,94},{56,78,73},{32,52,48},{0,10,8},{151,187,163},{132,165,144},{114,143,126},{95,121,107},{76,100,87},{56,78,67},{32,52,43},{0,10,4},{152,186,152},{133,164,134},{115,142,117},{96,120,99},{77,99,80},{57,78,62},{31,51,38},{0,10,1},
-{153,186,141},{134,164,124},{115,142,109},{96,120,91},{77,99,74},{57,78,56},{31,51,33},{0,10,0},{154,185,131},{135,163,115},{116,141,100},{97,119,84},{77,98,67},{58,77,50},{32,51,28},{0,9,0},{155,185,120},{136,163,105},{116,141,91},{97,119,76},{77,98,60},{58,77,44},{32,51,22},{0,9,0},{157,184,108},{137,162,94},{117,140,81},{98,119,67},{78,98,53},{58,77,38},{32,51,16},{0,10,0},
-{158,184,95},{138,162,82},{118,140,71},{98,119,58},{78,98,45},{58,77,30},{32,51,9},{0,10,0},{159,183,82},{139,162,70},{119,139,59},{99,118,49},{78,97,36},{58,76,21},{32,51,3},{0,9,0},{159,183,70},{139,162,60},{119,139,50},{99,118,40},{78,97,28},{58,76,13},{32,51,1},{0,9,0},{160,183,58},{140,161,49},{119,139,40},{99,118,32},{79,97,20},{59,76,5},{32,50,0},{0,9,0},
-{142,180,223},{124,159,197},{109,138,173},{91,118,148},{74,96,122},{55,75,97},{33,48,66},{1,5,25},{145,179,211},{127,158,187},{110,137,164},{93,117,139},{75,95,115},{56,75,91},{33,48,62},{0,5,21},{147,179,200},{129,158,177},{111,137,155},{93,117,131},{75,95,108},{56,75,85},{33,48,58},{0,5,17},{148,178,190},{130,158,168},{113,137,146},{95,116,124},{76,95,102},{57,74,81},{33,47,54},{0,5,13},
-{149,178,179},{131,158,160},{114,137,138},{95,116,117},{77,95,97},{58,74,76},{33,47,50},{0,5,9},{151,178,169},{132,157,150},{115,136,130},{96,115,111},{77,94,91},{58,74,70},{34,48,45},{0,5,4},{152,178,159},{133,156,140},{115,136,122},{96,115,103},{77,94,84},{58,74,64},{34,48,40},{0,5,2},{153,177,148},{134,155,130},{116,135,113},{97,114,96},{78,94,77},{59,73,59},{33,47,36},{0,6,0},
-{154,176,137},{135,155,120},{116,135,105},{98,114,89},{78,94,71},{59,73,54},{33,47,31},{0,6,0},{155,175,127},{136,154,111},{117,134,96},{99,114,82},{79,93,65},{59,73,48},{33,47,26},{0,5,0},{156,175,116},{137,154,102},{117,134,88},{99,114,74},{79,93,58},{59,73,42},{33,47,20},{0,5,0},{158,175,105},{138,153,92},{118,133,79},{99,113,65},{79,93,51},{60,73,36},{33,47,14},{0,5,0},
-{159,175,92},{138,153,80},{119,133,69},{99,113,56},{79,93,43},{60,73,28},{33,47,8},{0,5,0},{160,174,80},{139,153,69},{119,132,57},{99,112,47},{79,92,35},{60,72,19},{33,47,3},{0,5,0},{160,174,68},{140,153,59},{119,132,49},{99,112,39},{79,92,27},{60,72,12},{33,47,1},{0,5,0},{160,173,58},{141,152,48},{120,132,41},{100,112,31},{80,92,19},{60,72,4},{33,46,0},{0,5,0},
-{144,169,215},{127,150,190},{110,130,167},{94,110,143},{75,90,118},{57,70,93},{34,44,63},{1,1,22},{146,168,204},{129,149,181},{112,130,159},{95,110,135},{76,90,111},{58,70,88},{34,44,59},{0,1,18},{148,168,193},{131,149,172},{113,130,150},{95,110,127},{76,90,104},{58,70,82},{34,44,55},{0,1,14},{150,168,184},{132,148,163},{114,129,142},{96,109,120},{77,89,99},{59,69,78},{35,43,51},{0,1,10},
-{151,168,174},{133,148,155},{115,129,134},{97,109,113},{77,89,94},{59,69,73},{35,43,47},{0,1,6},{153,167,164},{134,148,145},{115,128,126},{97,109,107},{78,89,88},{59,69,67},{35,44,42},{0,1,2},{153,167,154},{134,147,136},{116,128,118},{98,109,100},{78,89,81},{59,69,61},{35,44,37},{0,1,0},{154,166,143},{135,147,127},{117,127,110},{98,108,93},{79,89,74},{59,68,56},{35,43,33},{0,2,0},
-{155,166,133},{136,147,117},{117,127,102},{98,108,86},{79,89,68},{59,68,51},{35,43,29},{0,2,0},{156,165,124},{137,146,108},{118,127,93},{99,107,79},{80,88,62},{60,68,46},{35,43,24},{0,2,0},{156,165,113},{138,146,99},{118,127,85},{99,107,71},{80,88,56},{60,68,40},{35,43,18},{0,2,0},{158,164,102},{139,145,89},{119,126,76},{99,107,63},{80,88,49},{60,68,34},{34,43,12},{0,2,0},
-{159,164,89},{139,145,78},{119,126,67},{99,107,55},{80,88,42},{60,68,26},{34,43,8},{0,2,0},{160,164,78},{140,144,67},{119,125,56},{99,106,46},{80,87,34},{60,67,18},{34,43,3},{0,2,0},{160,164,68},{141,144,58},{119,125,48},{99,106,38},{80,87,26},{60,67,11},{34,43,1},{0,2,0},{161,163,57},{142,144,48},{120,125,40},{100,105,30},{80,87,18},{61,67,4},{34,42,0},{0,2,0},
-{146,158,208},{129,140,184},{112,122,161},{95,103,137},{77,84,114},{59,64,89},{36,38,61},{1,0,20},{148,158,197},{131,139,175},{114,121,153},{96,103,130},{78,84,107},{59,64,84},{36,39,57},{1,1,15},{150,158,187},{132,139,166},{115,121,144},{97,103,123},{78,84,101},{59,64,79},{36,39,52},{1,1,10},{151,158,178},{134,138,157},{116,121,137},{97,102,116},{79,83,96},{60,64,75},{36,38,48},{1,1,6},
-{152,158,168},{135,138,149},{116,121,130},{98,102,110},{79,83,91},{60,64,70},{36,38,44},{1,1,3},{154,157,159},{136,138,139},{117,120,122},{99,102,103},{79,83,85},{60,63,65},{36,39,40},{1,1,1},{154,157,149},{136,138,131},{117,120,114},{99,102,96},{79,83,79},{60,63,59},{36,39,35},{0,1,0},{155,156,139},{137,137,122},{118,120,106},{99,101,89},{80,83,72},{60,63,54},{36,39,31},{0,1,0},
-{156,156,129},{137,137,113},{118,120,98},{99,101,83},{80,83,66},{60,63,49},{36,39,27},{0,1,0},{157,155,120},{138,136,105},{118,119,91},{99,100,76},{80,82,60},{61,63,44},{36,39,22},{0,1,0},{158,155,110},{138,136,96},{118,119,83},{99,100,69},{80,82,54},{61,63,38},{36,39,16},{0,1,0},{159,154,100},{139,136,87},{119,118,74},{100,100,61},{81,82,47},{61,63,32},{36,39,10},{0,1,0},
-{160,154,87},{140,136,76},{119,118,65},{100,100,53},{81,82,40},{61,63,24},{36,39,6},{0,1,0},{161,154,76},{141,135,66},{120,117,55},{100,99,44},{81,81,32},{61,62,16},{35,39,2},{0,1,0},{161,154,67},{141,135,57},{120,117,47},{100,99,37},{81,81,24},{61,62,10},{35,39,1},{0,1,0},{161,153,56},{141,135,48},{121,117,39},{100,99,29},{81,81,16},{61,62,3},{35,38,0},{0,1,0},
-{148,147,200},{131,130,178},{113,114,155},{96,95,132},{78,78,110},{59,59,86},{37,33,58},{1,0,17},{150,147,190},{133,130,169},{115,113,147},{97,95,125},{79,78,104},{60,58,81},{37,34,54},{1,0,12},{152,147,181},{134,130,160},{116,113,139},{98,95,118},{79,78,98},{61,58,76},{37,34,49},{1,0,7},{153,147,172},{135,129,151},{117,112,132},{98,95,112},{80,77,93},{61,58,72},{37,33,45},{1,0,3},
-{154,147,163},{135,129,143},{117,112,125},{98,95,107},{80,77,88},{61,58,67},{37,33,41},{1,0,1},{155,146,154},{136,129,134},{118,112,118},{99,94,100},{80,77,82},{61,58,62},{37,34,37},{1,0,0},{155,146,144},{137,129,126},{118,112,111},{99,94,93},{80,77,76},{61,58,57},{37,34,33},{0,0,0},{156,145,135},{137,129,118},{119,112,103},{99,94,86},{80,77,70},{61,58,52},{36,34,29},{0,0,0},
-{157,145,125},{137,129,110},{119,112,95},{99,94,80},{80,77,64},{61,58,47},{36,34,25},{0,0,0},{158,144,116},{138,128,102},{119,111,88},{99,94,73},{80,76,58},{62,58,41},{36,34,20},{0,0,0},{158,144,107},{138,128,93},{119,111,80},{99,94,66},{80,76,52},{62,58,35},{36,34,14},{0,0,0},{159,144,97},{139,127,84},{120,110,72},{100,93,59},{81,76,45},{62,58,29},{36,34,8},{0,0,0},
-{160,144,85},{140,127,74},{120,110,63},{100,93,51},{81,76,38},{62,58,22},{36,34,4},{0,0,0},{161,144,74},{141,127,64},{121,109,53},{101,93,42},{82,75,30},{62,57,15},{36,34,1},{0,0,0},{161,144,66},{141,127,56},{121,109,46},{101,93,35},{82,75,22},{62,57,9},{36,34,1},{0,0,0},{161,144,56},{141,126,48},{121,109,38},{101,93,28},{82,75,15},{62,57,3},{35,34,0},{0,0,0},
-{150,137,193},{132,121,172},{114,106,150},{97,88,128},{79,71,106},{60,53,83},{38,28,55},{0,0,13},{152,137,183},{134,121,163},{116,105,142},{98,88,121},{80,71,100},{61,53,78},{38,28,51},{1,0,8},{153,137,174},{135,121,154},{117,105,134},{99,88,114},{80,71,94},{62,53,73},{38,28,47},{1,0,4},{154,137,166},{136,120,146},{118,105,127},{99,88,108},{81,71,90},{62,53,69},{38,28,43},{1,0,2},
-{155,137,158},{136,120,138},{118,105,120},{99,88,103},{81,71,85},{62,53,64},{38,28,39},{1,0,0},{156,136,149},{137,120,130},{119,104,114},{100,87,97},{81,70,79},{62,53,59},{38,29,35},{0,0,0},{156,136,139},{137,120,122},{119,104,107},{100,87,90},{81,70,73},{62,53,54},{38,29,31},{0,0,0},{157,136,130},{138,120,114},{120,104,99},{100,87,83},{81,70,67},{62,53,49},{37,29,26},{0,0,0},
-{158,136,121},{138,120,106},{120,104,92},{100,87,77},{81,70,61},{62,53,44},{37,29,22},{0,0,0},{159,135,112},{138,119,98},{120,103,85},{100,87,70},{81,70,55},{62,53,39},{37,29,17},{0,0,0},{159,135,103},{139,119,90},{120,103,77},{100,87,64},{81,70,49},{62,53,33},{37,29,11},{0,0,0},{160,135,94},{140,119,82},{121,103,70},{101,86,57},{82,70,43},{62,53,27},{37,29,5},{0,0,0},
-{161,135,83},{140,119,72},{121,103,61},{101,86,49},{82,70,37},{62,53,21},{37,29,3},{0,0,0},{161,135,73},{141,118,62},{121,102,52},{101,86,41},{82,69,29},{63,52,14},{36,30,1},{0,0,0},{161,135,65},{141,118,54},{121,102,45},{101,86,34},{82,69,21},{63,52,8},{36,30,1},{0,0,0},{162,135,56},{142,118,47},{121,102,37},{101,86,27},{82,69,14},{63,52,2},{36,30,0},{0,0,0},
-{152,127,187},{134,111,166},{116,97,145},{99,82,124},{80,65,102},{62,47,79},{39,21,53},{0,0,9},{153,127,177},{135,111,157},{117,97,138},{100,82,117},{81,65,96},{62,47,74},{38,22,49},{0,0,5},{154,127,168},{136,111,148},{118,97,130},{100,82,110},{81,65,90},{62,47,70},{38,22,45},{0,0,1},{155,127,160},{137,111,141},{119,97,123},{100,82,104},{82,65,86},{63,47,66},{38,23,41},{0,0,1},
-{156,127,152},{137,111,134},{119,97,116},{100,82,99},{82,65,81},{63,47,62},{38,23,37},{0,0,0},{157,126,144},{138,111,126},{119,96,110},{101,81,93},{82,64,75},{63,47,57},{38,23,33},{0,0,0},{158,126,135},{138,111,118},{119,96,103},{101,81,87},{82,64,69},{63,47,52},{38,23,29},{0,0,0},{158,126,126},{139,110,110},{120,96,95},{101,81,80},{82,64,64},{63,47,47},{38,24,24},{0,0,0},
-{158,126,117},{139,110,102},{120,96,89},{101,81,74},{82,64,58},{63,47,42},{38,24,20},{0,0,0},{159,125,109},{139,110,95},{120,96,82},{101,81,68},{82,64,53},{62,47,37},{38,25,15},{0,0,0},{159,125,100},{140,110,88},{120,96,75},{101,81,62},{82,64,47},{62,47,31},{38,25,9},{0,0,0},{160,125,91},{140,110,80},{121,96,68},{101,80,55},{82,64,41},{62,47,25},{38,25,4},{0,0,0},
-{161,125,81},{140,110,70},{121,96,59},{101,80,47},{82,64,35},{62,47,19},{38,25,2},{0,0,0},{161,125,71},{141,109,60},{121,95,50},{101,80,39},{82,63,27},{63,47,12},{37,26,1},{0,0,0},{161,125,63},{141,109,52},{121,95,43},{101,80,32},{82,63,19},{63,47,6},{37,26,1},{0,0,0},{162,125,55},{142,109,46},{121,95,36},{101,80,26},{82,63,13},{63,47,2},{36,26,0},{0,0,0},
-{153,117,180},{135,103,159},{117,89,140},{100,75,119},{81,58,98},{63,40,76},{39,14,50},{0,0,5},{154,117,171},{136,103,151},{118,89,133},{101,75,113},{82,58,92},{63,41,71},{39,15,46},{0,0,3},{156,117,162},{137,103,143},{119,89,125},{101,75,106},{82,58,86},{63,41,67},{39,16,42},{0,0,0},{157,117,154},{138,103,136},{119,89,119},{101,75,100},{82,58,82},{63,41,63},{39,17,38},{0,0,0},
-{157,117,146},{138,103,129},{119,89,112},{101,75,95},{82,58,77},{63,41,59},{39,17,35},{0,0,0},{158,116,139},{139,103,122},{120,89,106},{101,74,89},{83,57,71},{64,41,54},{39,18,31},{0,0,0},{158,116,131},{139,103,114},{120,89,99},{101,74,84},{83,57,66},{64,41,49},{39,18,27},{0,0,0},{159,116,122},{139,102,106},{121,88,92},{101,74,78},{82,58,61},{63,41,45},{39,19,23},{0,0,0},
-{159,116,113},{139,102,99},{121,88,86},{101,74,72},{82,58,57},{63,41,41},{39,19,18},{0,0,0},{159,116,106},{140,102,92},{121,88,79},{101,74,65},{82,58,52},{63,42,36},{39,20,13},{0,0,0},{159,116,98},{140,102,85},{121,88,73},{101,74,59},{82,58,46},{63,42,30},{39,20,8},{0,0,0},{160,116,89},{141,102,77},{121,88,66},{101,73,53},{82,57,40},{63,42,24},{38,20,4},{0,0,0},
-{161,116,79},{141,102,69},{121,88,58},{101,73,46},{82,57,33},{63,42,17},{38,20,2},{0,0,0},{162,115,70},{141,101,59},{121,88,49},{102,73,38},{83,57,26},{63,42,10},{37,21,0},{0,0,0},{162,115,62},{141,101,51},{121,88,42},{102,73,31},{83,57,18},{63,42,5},{37,21,0},{0,0,0},{161,115,54},{142,101,45},{122,88,35},{102,73,25},{83,57,12},{63,42,2},{37,21,0},{0,0,0},
-{154,106,173},{135,93,153},{118,80,134},{100,66,114},{82,51,94},{63,33,73},{40,9,47},{0,0,3},{155,106,164},{137,94,145},{119,80,128},{101,67,108},{83,51,89},{63,34,68},{40,10,43},{0,0,1},{156,106,156},{138,94,138},{119,80,120},{101,67,101},{83,51,83},{63,34,64},{40,10,39},{0,0,0},{157,106,149},{138,94,131},{120,80,114},{102,66,97},{83,51,79},{63,34,60},{40,11,35},{0,0,0},
-{158,106,141},{139,94,124},{120,80,108},{102,66,92},{83,51,74},{63,34,56},{40,11,32},{0,0,0},{158,106,134},{139,94,117},{120,80,102},{102,66,86},{83,51,68},{64,35,52},{40,12,28},{0,0,0},{158,106,126},{139,94,110},{120,80,96},{102,66,81},{83,51,63},{64,35,47},{40,12,24},{0,0,0},{159,106,118},{139,93,103},{121,80,89},{101,66,75},{82,51,58},{63,35,42},{39,13,20},{0,0,0},
-{159,106,110},{139,93,96},{121,80,83},{101,66,69},{82,51,54},{63,35,38},{39,13,16},{0,0,0},{159,106,103},{140,93,89},{121,80,76},{102,66,62},{83,52,49},{63,36,34},{39,14,11},{0,0,0},{159,106,95},{140,93,82},{121,80,70},{102,66,57},{83,52,44},{63,36,28},{39,14,7},{0,0,0},{160,106,86},{141,93,74},{121,80,63},{101,66,51},{82,51,38},{63,36,22},{38,14,3},{0,0,0},
-{161,106,77},{141,93,66},{121,80,56},{101,66,44},{82,51,31},{63,36,15},{38,14,1},{0,0,0},{162,106,68},{141,92,58},{121,80,47},{102,66,37},{83,51,24},{63,36,8},{37,15,0},{0,0,0},{162,106,60},{141,92,50},{121,80,40},{102,66,30},{83,51,17},{63,36,5},{37,15,0},{0,0,0},{161,105,53},{142,92,44},{122,80,35},{102,66,24},{83,51,11},{63,36,2},{37,15,0},{0,0,0},
-{155,96,167},{136,83,147},{119,71,128},{101,57,109},{83,42,90},{64,25,70},{41,3,45},{0,0,1},{156,95,158},{138,84,139},{120,71,122},{102,58,103},{84,43,85},{64,26,65},{40,4,41},{0,0,0},{157,95,150},{139,84,132},{120,71,115},{102,58,97},{84,43,79},{64,27,61},{40,4,37},{0,0,0},{158,95,143},{139,84,126},{121,71,110},{103,58,93},{84,43,75},{64,27,57},{40,5,33},{0,0,0},
-{159,95,136},{139,84,119},{121,71,104},{103,58,88},{84,43,71},{64,27,54},{40,5,30},{0,0,0},{159,96,129},{140,84,113},{121,71,98},{103,58,82},{84,44,66},{64,28,50},{40,5,26},{0,0,0},{159,96,121},{140,84,106},{121,71,92},{103,58,77},{84,44,61},{64,28,45},{40,5,22},{0,0,0},{160,96,114},{140,84,99},{121,71,86},{102,58,72},{83,44,56},{64,29,40},{40,6,18},{0,0,0},
-{160,96,107},{140,84,93},{121,71,80},{102,58,66},{83,44,52},{64,29,36},{40,6,14},{0,0,0},{160,96,100},{140,83,86},{121,72,74},{103,58,60},{84,45,47},{64,29,32},{39,7,9},{0,0,0},{160,96,92},{140,83,79},{121,72,68},{103,58,55},{84,45,42},{64,29,26},{39,7,5},{0,0,0},{161,95,83},{141,83,72},{121,71,61},{102,58,49},{83,45,36},{63,30,20},{39,8,3},{0,0,0},
-{161,95,75},{141,83,64},{121,71,54},{102,58,42},{83,45,29},{63,30,14},{39,8,1},{0,0,0},{161,96,66},{142,83,56},{122,71,46},{102,58,35},{83,45,22},{63,30,7},{38,8,0},{0,0,0},{161,96,59},{142,83,49},{122,71,39},{102,58,29},{83,45,15},{63,30,4},{38,8,0},{0,0,0},{162,95,52},{142,83,43},{123,71,34},{103,58,23},{84,45,9},{63,30,1},{37,9,0},{0,0,0},
-{155,83,161},{137,72,141},{119,60,123},{101,47,105},{83,32,86},{64,16,67},{41,1,42},{0,0,0},{157,83,153},{138,72,134},{120,61,117},{102,48,99},{84,33,81},{64,16,62},{40,2,38},{0,0,0},{157,83,145},{139,72,127},{120,61,110},{102,48,93},{84,33,76},{64,17,58},{40,2,34},{0,0,0},{158,83,138},{140,72,121},{121,61,106},{103,48,89},{84,34,72},{64,17,54},{40,2,30},{0,0,0},
-{159,83,131},{140,72,115},{121,61,100},{103,48,84},{84,34,68},{64,17,51},{40,2,27},{0,0,0},{159,84,124},{140,73,109},{121,61,94},{103,49,79},{84,35,63},{64,18,47},{40,2,23},{0,0,0},{159,84,117},{140,73,102},{121,61,88},{103,49,74},{84,35,58},{64,18,42},{40,2,19},{0,0,0},{160,84,110},{140,73,96},{121,62,83},{103,49,69},{84,36,53},{64,19,37},{40,2,15},{0,0,0},
-{160,84,103},{140,73,90},{121,62,77},{103,49,63},{84,36,49},{64,19,33},{40,3,11},{0,0,0},{160,84,96},{140,73,83},{121,62,71},{103,49,57},{84,36,44},{64,19,29},{39,4,7},{0,0,0},{160,84,89},{141,73,76},{121,62,65},{103,49,52},{84,36,39},{64,20,24},{39,4,4},{0,0,0},{161,84,81},{141,73,70},{121,62,58},{102,50,46},{83,37,33},{63,21,18},{39,4,2},{0,0,0},
-{161,84,73},{141,73,62},{121,62,51},{102,50,40},{83,37,27},{63,21,13},{39,4,1},{0,0,0},{161,84,65},{142,73,55},{122,62,45},{102,50,34},{83,37,21},{63,21,6},{38,4,0},{0,0,0},{161,84,58},{142,73,48},{122,62,38},{102,50,28},{83,37,14},{63,21,3},{38,4,0},{0,0,0},{162,84,52},{143,73,42},{123,62,33},{103,50,22},{84,37,8},{63,22,1},{37,5,0},{0,0,0},
-{156,70,154},{138,60,136},{120,48,118},{102,35,101},{84,20,82},{65,5,63},{41,0,39},{0,0,0},{158,70,147},{139,60,129},{121,49,112},{103,36,95},{84,22,77},{65,6,59},{40,0,35},{0,0,0},{159,70,139},{140,60,122},{121,49,106},{103,37,89},{84,23,72},{65,6,55},{40,0,32},{0,0,0},{160,71,132},{140,60,116},{122,49,102},{104,38,85},{85,23,68},{65,6,51},{40,0,28},{0,0,0},
-{160,71,126},{140,60,111},{122,49,96},{104,38,80},{85,23,64},{65,6,47},{40,0,25},{0,0,0},{160,72,120},{140,61,105},{121,50,90},{103,39,75},{84,24,60},{65,7,43},{40,0,21},{0,0,0},{160,72,113},{140,61,98},{121,50,84},{103,39,70},{84,25,55},{65,7,39},{40,0,17},{0,0,0},{160,72,106},{140,62,92},{122,50,79},{103,39,65},{84,26,50},{65,8,35},{40,0,12},{0,0,0},
-{160,72,99},{140,62,86},{122,50,74},{103,39,60},{84,27,46},{65,9,31},{40,0,8},{0,0,0},{161,72,92},{141,62,80},{122,51,68},{103,40,55},{84,27,42},{64,9,27},{40,0,5},{0,0,0},{161,72,86},{141,62,74},{122,51,62},{103,40,50},{84,27,37},{64,10,22},{40,0,3},{0,0,0},{161,72,79},{142,62,68},{122,51,56},{103,40,44},{84,28,31},{64,11,16},{39,1,1},{0,0,0},
-{161,72,71},{142,62,60},{122,51,49},{103,40,38},{84,28,25},{64,11,11},{39,1,1},{0,0,0},{162,72,63},{142,62,53},{122,51,43},{103,41,32},{84,28,19},{64,12,5},{38,1,0},{0,0,0},{162,72,57},{142,62,47},{122,51,37},{103,41,26},{84,28,13},{64,12,2},{38,1,0},{0,0,0},{162,72,51},{143,62,41},{122,52,32},{102,41,21},{83,29,7},{63,13,0},{38,1,0},{0,0,0},
-{157,53,148},{138,42,130},{121,29,113},{102,18,96},{84,10,78},{65,2,60},{40,0,36},{0,0,0},{158,53,141},{139,43,124},{121,31,107},{103,20,91},{84,11,74},{65,3,56},{40,0,33},{0,0,0},{159,53,133},{140,43,117},{121,32,101},{103,20,86},{84,12,69},{65,3,52},{40,0,30},{0,0,0},{160,53,127},{140,44,111},{122,33,97},{104,21,82},{85,12,65},{65,3,48},{40,0,26},{0,0,0},
-{160,54,121},{140,44,106},{122,34,92},{104,22,77},{85,12,61},{65,3,45},{40,0,22},{0,0,0},{160,55,115},{140,45,101},{122,35,87},{103,23,73},{84,12,57},{65,3,41},{40,0,18},{0,0,0},{160,56,109},{140,46,95},{122,36,82},{103,24,68},{84,13,53},{65,3,37},{40,0,15},{0,0,0},{160,56,102},{140,47,89},{122,36,77},{103,25,63},{84,13,48},{65,4,33},{40,0,11},{0,0,0},
-{160,56,96},{140,47,83},{122,37,72},{103,26,58},{84,14,44},{65,4,29},{40,0,7},{0,0,0},{161,57,89},{141,47,78},{122,37,66},{103,27,53},{84,15,40},{64,4,25},{40,0,5},{0,0,0},{161,57,83},{141,47,72},{122,38,60},{103,27,48},{84,15,35},{64,5,20},{40,0,3},{0,0,0},{161,57,77},{142,48,66},{122,39,54},{103,27,42},{84,16,29},{64,5,14},{39,1,1},{0,0,0},
-{161,57,69},{142,49,59},{122,39,48},{103,28,37},{84,16,24},{64,5,9},{39,1,1},{0,0,0},{162,58,62},{142,49,52},{122,40,42},{103,29,31},{84,16,18},{64,6,4},{38,1,0},{0,0,0},{162,58,56},{142,49,46},{122,40,36},{103,29,25},{84,16,12},{64,6,2},{38,1,0},{0,0,0},{162,58,50},{143,49,41},{122,40,31},{102,29,20},{83,17,6},{63,6,0},{38,1,0},{0,0,0},
-{158,35,142},{139,25,125},{122,10,108},{103,1,91},{85,0,74},{65,0,57},{39,0,33},{0,0,0},{159,35,135},{140,26,119},{122,13,103},{103,2,87},{85,0,70},{65,0,53},{39,0,30},{0,0,0},{160,35,128},{140,27,112},{122,15,97},{103,3,82},{85,0,66},{65,0,50},{39,0,27},{0,0,0},{160,37,122},{141,28,107},{122,17,93},{103,5,78},{85,0,62},{65,0,46},{39,0,23},{0,0,0},
-{160,38,117},{141,28,102},{122,18,88},{103,6,74},{85,0,58},{65,0,42},{39,0,19},{0,0,0},{160,39,111},{140,30,97},{122,19,84},{103,7,70},{85,0,54},{65,0,38},{39,0,15},{0,0,0},{160,40,105},{140,31,92},{122,21,79},{103,9,65},{85,0,50},{65,0,34},{39,0,12},{0,0,0},{160,41,98},{141,32,86},{122,22,74},{104,10,60},{85,1,46},{65,0,30},{39,0,9},{0,0,0},
-{160,41,92},{141,32,80},{122,23,69},{104,12,56},{85,1,42},{65,0,26},{39,0,6},{0,0,0},{161,42,86},{141,33,75},{122,24,64},{103,13,51},{84,2,38},{64,0,22},{38,0,4},{0,0,0},{161,42,80},{141,33,69},{122,25,58},{103,14,46},{84,2,33},{64,0,17},{38,0,2},{0,0,0},{161,43,74},{142,34,63},{122,26,52},{103,15,40},{84,3,27},{64,0,11},{37,0,1},{0,0,0},
-{161,43,67},{142,35,57},{122,27,47},{103,16,35},{84,3,22},{64,0,7},{37,0,1},{0,0,0},{162,44,61},{142,36,51},{122,28,41},{103,17,30},{84,4,16},{64,0,3},{37,0,0},{0,0,0},{162,44,55},{142,36,45},{122,28,35},{103,17,24},{84,4,11},{64,0,2},{37,0,0},{0,0,0},{163,44,49},{142,37,40},{123,28,30},{103,17,19},{84,4,5},{64,0,0},{36,0,0},{0,0,0},
-{76,202,245},{68,178,216},{56,155,188},{45,132,161},{32,108,134},{17,86,107},{5,58,75},{0,19,34},{82,201,232},{74,177,204},{62,154,178},{50,132,152},{35,108,127},{19,85,101},{5,57,70},{0,18,30},{89,200,219},{80,176,193},{67,154,169},{54,132,144},{38,108,119},{20,85,94},{5,57,65},{0,18,27},{94,199,207},{82,176,184},{70,153,160},{56,131,137},{41,108,113},{22,85,90},{6,57,61},{0,18,23},
-{98,199,196},{85,176,174},{72,153,152},{59,131,129},{43,108,107},{24,85,85},{6,57,57},{0,18,20},{100,198,185},{88,175,164},{74,152,142},{61,130,122},{44,107,101},{25,84,79},{7,57,53},{0,18,14},{102,197,173},{90,174,153},{76,152,134},{62,130,114},{45,107,94},{27,84,74},{8,57,48},{0,18,10},{104,197,162},{91,173,143},{78,151,125},{63,129,106},{47,106,87},{29,83,67},{8,56,44},{0,18,6},
-{107,196,151},{93,173,133},{80,150,116},{65,129,98},{48,106,80},{30,83,61},{8,56,39},{0,18,3},{109,195,139},{96,172,123},{81,149,107},{66,128,91},{49,105,73},{31,83,56},{9,56,34},{0,17,1},{111,195,128},{98,172,112},{82,149,97},{67,128,83},{49,105,66},{31,83,50},{9,56,28},{0,17,0},{113,194,115},{99,171,101},{84,149,87},{68,127,74},{51,105,59},{33,82,43},{9,56,22},{0,17,0},
-{115,194,102},{100,171,90},{85,149,77},{68,127,64},{52,105,51},{33,82,36},{9,56,15},{0,17,0},{118,194,89},{101,170,78},{86,148,66},{69,126,55},{53,104,43},{34,82,29},{10,56,8},{0,17,0},{119,194,77},{102,170,68},{87,148,58},{69,126,47},{53,104,35},{34,82,21},{10,56,4},{0,17,0},{121,193,66},{104,170,57},{88,148,48},{70,126,39},{53,104,28},{34,82,13},{9,55,1},{0,16,0},
-{85,191,237},{76,168,209},{64,147,182},{52,125,156},{38,103,129},{23,81,103},{7,53,72},{0,13,31},{91,190,224},{81,167,198},{68,146,172},{55,125,148},{41,103,123},{24,80,97},{8,53,67},{0,13,27},{96,190,212},{85,167,187},{72,146,164},{59,125,140},{43,103,115},{26,80,91},{8,53,63},{0,13,24},{100,189,201},{88,167,178},{75,145,155},{61,124,133},{45,102,109},{27,80,87},{9,53,59},{0,12,20},
-{103,188,190},{90,167,168},{77,145,147},{63,124,125},{46,102,103},{29,80,82},{9,53,55},{0,12,17},{105,187,179},{92,166,159},{79,144,138},{64,123,118},{48,101,97},{30,79,76},{10,53,50},{0,12,11},{107,187,168},{94,165,148},{80,144,130},{65,123,110},{49,101,91},{31,79,71},{10,53,45},{0,12,7},{109,186,158},{95,164,139},{82,143,121},{66,122,103},{50,101,84},{33,79,65},{10,52,41},{0,12,4},
-{112,186,147},{97,164,129},{83,143,112},{68,122,95},{51,101,77},{34,79,59},{10,52,37},{0,12,1},{114,185,136},{99,163,119},{84,142,104},{69,121,88},{52,100,71},{35,78,54},{11,52,32},{0,11,0},{115,185,125},{101,163,109},{85,142,95},{70,121,80},{53,100,64},{35,78,48},{11,52,26},{0,11,0},{117,184,112},{103,162,99},{87,142,85},{71,120,71},{54,99,57},{36,78,41},{11,52,20},{0,11,0},
-{119,184,100},{104,162,88},{88,142,75},{71,120,62},{54,99,49},{36,78,34},{11,52,13},{0,11,0},{121,183,87},{105,161,76},{89,141,64},{72,120,53},{55,99,41},{36,77,27},{11,52,6},{0,11,0},{122,183,76},{105,161,66},{89,141,56},{72,120,46},{55,99,33},{36,77,19},{11,52,3},{0,11,0},{123,183,65},{107,161,56},{90,141,48},{73,119,38},{56,99,26},{37,77,11},{11,51,1},{0,11,0},
-{94,180,229},{84,159,201},{72,139,175},{59,118,150},{44,97,125},{28,75,100},{10,49,69},{0,7,29},{99,179,216},{87,158,191},{75,138,166},{61,117,143},{46,97,119},{30,75,94},{10,49,65},{0,7,25},{103,179,205},{91,158,181},{77,138,158},{63,117,135},{48,97,112},{31,75,88},{10,49,61},{0,7,22},{106,178,194},{93,158,171},{79,137,150},{65,116,129},{49,96,106},{33,74,84},{11,49,57},{0,6,18},
-{109,178,183},{94,158,163},{81,137,142},{66,116,121},{50,96,100},{34,74,79},{11,49,53},{0,6,15},{111,177,173},{96,157,153},{83,136,134},{67,115,114},{51,95,94},{34,74,73},{11,49,48},{0,6,9},{113,177,163},{97,157,144},{84,136,126},{68,115,107},{52,95,88},{35,74,68},{11,49,43},{0,6,5},{114,176,153},{99,156,135},{85,135,117},{69,115,100},{53,95,81},{36,74,63},{11,48,39},{0,6,2},
-{116,176,143},{101,155,125},{86,135,109},{71,115,93},{54,95,75},{36,74,57},{11,48,35},{0,6,0},{117,175,133},{102,155,116},{87,134,101},{72,114,86},{54,94,69},{37,73,52},{11,49,30},{0,5,0},{118,175,122},{104,155,107},{88,134,93},{72,114,78},{55,94,62},{37,73,46},{11,49,24},{0,5,0},{120,174,110},{105,154,97},{89,134,83},{73,113,69},{56,93,55},{38,73,40},{11,49,18},{0,5,0},
-{122,174,98},{106,154,86},{90,134,74},{73,113,61},{56,93,47},{38,73,32},{11,49,11},{0,5,0},{123,174,86},{107,153,74},{91,133,63},{74,113,52},{56,93,40},{39,72,25},{11,48,4},{0,5,0},{124,174,75},{107,153,65},{91,133,55},{74,113,45},{57,93,32},{39,72,17},{11,48,2},{0,5,0},{125,173,65},{108,153,56},{92,133,48},{75,113,38},{58,93,25},{40,72,9},{11,48,1},{0,5,0},
-{100,170,221},{89,151,195},{76,132,171},{63,112,146},{48,92,121},{32,71,96},{12,45,66},{0,3,27},{104,170,209},{92,150,185},{79,131,162},{65,111,139},{50,91,115},{33,71,90},{12,45,62},{0,3,23},{107,170,198},{95,150,175},{81,131,154},{66,111,131},{51,91,108},{34,71,85},{12,45,58},{0,3,18},{110,169,188},{97,150,167},{82,130,146},{68,110,125},{52,91,103},{36,70,81},{13,45,54},{0,3,14},
-{112,169,179},{98,150,159},{84,130,138},{69,110,117},{53,91,97},{37,70,77},{13,45,50},{0,3,11},{114,168,169},{99,149,149},{86,129,130},{71,109,110},{54,90,91},{37,70,71},{13,45,46},{0,3,6},{116,168,159},{101,149,140},{87,129,122},{71,109,103},{55,90,85},{38,70,65},{13,45,41},{0,3,3},{117,167,149},{102,148,131},{88,128,114},{72,109,96},{56,90,78},{39,69,60},{13,44,37},{0,3,1},
-{118,167,139},{103,148,121},{88,128,106},{73,109,90},{57,90,72},{40,69,55},{13,44,33},{0,3,0},{119,166,129},{104,147,112},{89,128,98},{74,108,83},{57,89,67},{40,69,50},{14,45,28},{0,2,0},{121,166,118},{106,147,103},{90,128,90},{74,108,75},{57,89,60},{40,69,44},{14,45,22},{0,2,0},{122,165,107},{107,146,94},{91,127,81},{75,107,67},{58,89,53},{41,69,38},{14,45,16},{0,2,0},
-{124,165,96},{107,146,84},{92,127,72},{75,107,59},{58,89,45},{41,69,30},{14,45,10},{0,2,0},{126,165,84},{108,146,73},{93,126,61},{75,107,50},{58,88,38},{41,68,23},{15,44,4},{0,2,0},{126,165,73},{109,146,64},{93,126,53},{76,107,43},{59,88,31},{41,68,15},{15,44,2},{0,2,0},{127,164,64},{110,146,55},{94,126,46},{76,107,36},{60,88,24},{41,68,8},{14,44,1},{0,2,0},
-{106,160,213},{94,143,189},{80,124,166},{67,105,142},{52,86,117},{36,66,92},{13,41,63},{0,0,24},{109,160,202},{96,142,179},{83,124,157},{69,105,135},{54,86,111},{37,66,87},{13,41,59},{0,0,20},{111,160,191},{98,142,170},{84,124,149},{71,105,127},{54,86,104},{38,66,82},{13,41,55},{0,0,15},{113,160,182},{100,142,162},{86,123,142},{72,104,121},{55,85,100},{39,65,78},{14,41,51},{0,0,11},
-{115,160,174},{101,142,154},{87,123,134},{72,104,114},{56,85,94},{40,65,74},{15,41,47},{0,0,7},{117,159,164},{103,141,145},{88,122,126},{73,103,107},{57,85,88},{41,65,68},{15,41,43},{0,0,4},{119,159,154},{103,141,136},{89,122,118},{74,103,100},{58,85,82},{41,65,62},{15,41,38},{0,0,1},{120,158,144},{104,140,127},{90,121,111},{75,103,93},{59,85,75},{41,64,57},{15,40,34},{0,0,0},
-{122,158,134},{105,140,118},{91,121,103},{75,103,87},{59,85,69},{42,64,52},{16,40,30},{0,0,0},{123,157,125},{106,139,109},{92,121,95},{76,102,80},{59,84,64},{42,65,47},{17,41,26},{0,0,0},{123,157,115},{108,139,100},{92,121,87},{76,102,72},{59,84,58},{42,65,41},{17,41,20},{0,0,0},{124,157,104},{109,138,91},{93,120,78},{77,102,65},{60,84,51},{42,64,35},{16,41,14},{0,0,0},
-{126,157,93},{109,138,81},{93,120,69},{77,102,57},{60,84,44},{42,64,28},{16,41,9},{0,0,0},{128,157,81},{110,138,71},{94,119,60},{77,101,49},{60,83,37},{43,64,22},{17,40,3},{0,0,0},{128,157,72},{111,138,63},{94,119,52},{77,101,42},{60,83,30},{43,64,14},{17,40,2},{0,0,0},{129,156,63},{112,138,54},{95,119,45},{78,101,35},{60,83,23},{43,64,7},{16,40,1},{0,0,0},
-{110,150,206},{97,134,183},{84,117,160},{71,98,137},{55,80,113},{39,60,89},{16,35,61},{0,0,21},{113,150,195},{99,133,173},{86,116,151},{72,98,130},{56,80,107},{41,60,84},{17,35,57},{0,0,17},{115,150,185},{101,133,164},{87,116,143},{73,98,122},{57,80,100},{41,60,79},{18,35,53},{0,0,12},{117,150,176},{103,132,156},{89,116,136},{74,97,116},{58,79,96},{42,60,75},{19,36,49},{0,0,8},
-{119,150,168},{104,132,148},{90,116,129},{75,97,110},{58,79,90},{42,60,70},{19,36,45},{0,0,4},{121,150,158},{105,132,140},{91,115,122},{75,97,103},{59,79,84},{42,60,66},{19,36,41},{0,0,2},{121,150,149},{106,132,132},{92,115,114},{75,97,97},{59,79,79},{42,60,60},{19,36,36},{0,0,0},{122,149,140},{107,131,123},{92,114,107},{76,97,90},{60,79,73},{43,60,55},{19,36,32},{0,0,0},
-{124,149,130},{107,131,114},{92,114,99},{77,97,84},{61,79,67},{43,60,50},{19,36,28},{0,0,0},{125,148,121},{108,130,106},{93,113,92},{77,96,77},{61,78,61},{44,60,45},{20,36,24},{0,0,0},{126,148,112},{109,130,98},{94,113,85},{78,96,70},{61,78,55},{44,60,39},{20,36,18},{0,0,0},{127,147,102},{110,129,89},{95,113,76},{79,96,63},{61,78,49},{44,60,33},{19,36,12},{0,0,0},
-{128,147,90},{111,129,79},{95,113,67},{79,96,55},{61,78,42},{44,60,26},{19,36,8},{0,0,0},{129,147,79},{112,129,69},{96,112,58},{79,95,47},{62,77,35},{44,60,20},{20,36,3},{0,0,0},{129,147,71},{112,129,61},{96,112,51},{79,95,40},{62,77,28},{44,60,13},{20,36,1},{0,0,0},{130,147,62},{113,129,52},{97,112,44},{80,95,34},{62,77,21},{44,59,6},{19,36,0},{0,0,0},
-{114,140,199},{100,124,177},{87,109,154},{74,91,132},{58,74,109},{42,55,86},{19,30,58},{0,0,18},{117,140,189},{102,124,167},{89,108,146},{75,91,125},{59,74,103},{43,55,81},{20,30,54},{0,0,14},{119,140,179},{104,124,158},{91,108,138},{75,91,118},{60,74,97},{43,55,76},{20,30,50},{0,0,9},{120,140,170},{106,124,151},{92,108,131},{76,91,112},{61,73,92},{44,55,72},{21,31,46},{0,0,5},
-{121,140,162},{106,124,143},{92,108,124},{77,91,106},{61,73,87},{44,55,67},{21,31,42},{0,0,2},{123,140,153},{107,123,135},{93,107,118},{78,90,100},{61,73,81},{44,55,63},{21,31,38},{0,0,1},{124,140,144},{108,123,127},{94,107,110},{78,90,94},{61,73,76},{44,55,58},{21,31,34},{0,0,0},{124,139,135},{109,123,119},{95,107,103},{79,90,87},{62,73,70},{45,55,53},{22,31,30},{0,0,0},
-{126,139,127},{110,123,111},{95,107,96},{79,90,81},{62,73,64},{45,55,48},{22,31,26},{0,0,0},{127,139,118},{111,122,103},{95,106,89},{79,90,74},{62,72,58},{45,55,43},{22,32,22},{0,0,0},{128,139,109},{111,122,95},{95,106,82},{79,90,68},{62,72,52},{45,55,37},{22,32,16},{0,0,0},{129,138,99},{112,121,86},{96,106,74},{80,89,61},{63,72,46},{45,55,31},{22,31,10},{0,0,0},
-{129,138,88},{113,121,77},{96,106,65},{80,89,53},{63,72,40},{45,55,24},{22,31,6},{0,0,0},{130,138,77},{114,121,67},{97,105,57},{81,89,45},{63,72,33},{45,55,18},{22,32,3},{0,0,0},{130,138,70},{114,121,59},{97,105,50},{81,89,39},{63,72,26},{45,55,11},{22,32,1},{0,0,0},{131,138,62},{114,121,52},{97,105,43},{81,89,33},{63,71,19},{45,54,5},{21,32,0},{0,0,0},
-{117,131,192},{104,115,170},{89,101,149},{75,84,127},{59,67,105},{43,50,83},{22,25,55},{0,0,15},{119,131,182},{105,115,161},{91,101,141},{76,84,120},{60,67,100},{44,50,78},{22,25,51},{0,0,10},{121,131,173},{107,115,153},{92,101,133},{77,84,114},{61,67,94},{45,50,73},{22,25,47},{0,0,6},{122,131,165},{108,115,146},{93,101,127},{78,84,108},{62,67,89},{45,50,69},{23,26,43},{0,0,3},
-{123,131,157},{109,115,138},{94,101,120},{79,84,103},{62,67,84},{45,50,64},{23,26,40},{0,0,1},{124,131,148},{110,115,130},{95,100,114},{79,83,97},{63,67,78},{46,50,60},{23,26,36},{0,0,0},{125,131,139},{110,115,122},{95,100,107},{79,83,91},{63,67,73},{46,50,55},{23,26,32},{0,0,0},{126,130,131},{111,114,115},{96,100,100},{80,83,84},{63,67,67},{46,50,51},{24,26,28},{0,0,0},
-{127,130,123},{111,114,108},{96,100,93},{80,83,78},{63,67,62},{46,50,46},{24,26,24},{0,0,0},{128,130,114},{112,114,100},{96,99,86},{80,83,72},{63,67,57},{46,50,41},{24,27,19},{0,0,0},{129,130,105},{112,114,92},{96,99,79},{80,83,66},{63,67,51},{46,50,35},{24,27,13},{0,0,0},{130,129,96},{113,113,84},{97,99,72},{81,83,59},{64,67,45},{46,50,29},{24,27,7},{0,0,0},
-{130,129,86},{114,113,75},{97,99,64},{81,83,51},{64,67,39},{46,50,23},{24,27,5},{0,0,0},{131,129,76},{115,113,66},{98,98,56},{82,83,44},{64,67,32},{46,50,17},{23,28,2},{0,0,0},{131,129,69},{115,113,58},{98,98,49},{82,83,38},{64,67,25},{46,50,10},{23,28,1},{0,0,0},{132,129,61},{115,113,51},{98,98,42},{82,82,32},{64,66,18},{46,49,4},{22,28,0},{0,0,0},
-{120,121,186},{106,107,164},{92,93,143},{77,78,122},{61,61,101},{45,44,80},{24,19,53},{0,0,11},{122,121,176},{108,107,156},{93,93,137},{78,78,116},{62,61,96},{46,44,75},{24,20,49},{0,0,7},{123,121,167},{109,107,148},{94,93,129},{79,78,110},{63,61,90},{47,44,70},{24,20,45},{0,0,3},{124,121,159},{110,107,141},{95,93,123},{80,78,104},{64,61,86},{47,44,66},{25,21,41},{0,0,1},
-{125,121,152},{111,107,133},{96,93,116},{81,78,99},{64,61,81},{47,44,62},{25,21,38},{0,0,0},{126,121,143},{112,107,126},{96,93,110},{81,77,93},{64,61,76},{48,44,57},{25,21,34},{0,0,0},{127,121,135},{112,107,118},{96,93,103},{81,77,87},{64,61,70},{48,44,53},{25,21,30},{0,0,0},{128,121,127},{113,106,111},{97,92,96},{81,77,82},{64,61,65},{47,45,49},{26,22,26},{0,0,0},
-{128,121,119},{113,106,104},{97,92,90},{81,77,76},{64,61,60},{47,45,44},{26,22,22},{0,0,0},{129,121,111},{114,106,97},{98,92,83},{81,77,70},{65,61,55},{47,45,39},{26,23,17},{0,0,0},{130,121,102},{114,106,89},{98,92,77},{81,77,64},{65,61,49},{47,45,33},{26,23,11},{0,0,0},{131,120,93},{114,106,82},{99,92,70},{82,77,57},{65,61,43},{48,45,27},{26,23,6},{0,0,0},
-{131,120,84},{115,106,73},{99,92,62},{82,77,49},{65,61,37},{48,45,21},{26,23,4},{0,0,0},{132,120,74},{116,105,64},{99,91,54},{82,77,42},{65,61,30},{48,45,15},{25,24,2},{0,0,0},{132,120,67},{116,105,56},{100,91,47},{82,77,36},{65,61,23},{48,45,9},{25,24,1},{0,0,0},{133,120,59},{116,105,49},{100,91,40},{83,76,30},{65,61,17},{47,45,4},{24,24,0},{0,0,0},
-{122,112,179},{109,99,159},{93,85,138},{80,71,118},{63,55,98},{46,38,77},{25,12,50},{0,0,7},{124,112,170},{110,99,151},{95,85,132},{81,71,112},{64,55,93},{47,39,72},{25,13,46},{0,0,4},{126,112,161},{111,99,143},{96,85,125},{81,71,106},{65,55,87},{48,39,67},{25,13,43},{0,0,1},{127,112,154},{112,99,136},{97,85,119},{82,71,100},{65,55,83},{48,39,63},{26,14,39},{0,0,0},
-{127,112,147},{112,99,129},{97,85,113},{82,71,95},{65,55,78},{48,39,59},{26,14,35},{0,0,0},{128,112,139},{113,99,122},{97,86,107},{82,71,89},{65,55,73},{49,39,55},{26,15,31},{0,0,0},{129,112,131},{113,99,114},{97,86,100},{82,71,84},{65,55,68},{49,39,51},{26,15,28},{0,0,0},{129,112,123},{114,98,107},{98,85,93},{82,70,79},{65,55,63},{48,39,46},{27,16,24},{0,0,0},
-{129,112,115},{114,98,101},{98,85,87},{82,70,73},{65,55,59},{48,39,42},{27,17,20},{0,0,0},{130,112,108},{115,98,94},{99,85,80},{82,70,67},{66,56,54},{48,40,38},{27,18,15},{0,0,0},{131,112,100},{115,98,86},{99,85,74},{82,70,61},{66,56,48},{48,40,32},{27,18,10},{0,0,0},{132,111,91},{115,98,79},{100,85,68},{83,70,55},{66,55,42},{49,40,26},{27,19,5},{0,0,0},
-{132,111,82},{116,98,71},{100,85,60},{83,70,48},{66,55,35},{49,40,20},{27,19,3},{0,0,0},{133,111,73},{117,98,63},{100,84,52},{83,70,41},{66,55,29},{49,40,14},{26,19,1},{0,0,0},{133,111,66},{117,98,55},{101,84,46},{83,70,35},{66,55,22},{49,40,8},{26,19,1},{0,0,0},{134,111,58},{117,97,48},{101,84,39},{84,70,29},{66,55,16},{48,40,3},{25,19,0},{0,0,0},
-{125,102,173},{110,90,153},{95,77,133},{81,63,114},{65,48,94},{48,31,74},{26,7,47},{0,0,4},{126,102,164},{111,90,146},{97,77,127},{82,63,108},{66,48,89},{49,32,69},{27,8,43},{0,0,2},{127,102,156},{112,90,138},{98,77,120},{83,63,102},{66,48,84},{49,32,64},{27,8,40},{0,0,0},{128,102,149},{113,90,131},{98,77,114},{83,63,97},{66,48,80},{49,32,60},{28,9,36},{0,0,0},
-{129,102,142},{113,90,124},{98,77,109},{83,63,92},{66,48,75},{49,32,56},{28,9,33},{0,0,0},{130,103,134},{114,90,118},{99,78,103},{83,64,86},{66,49,70},{49,33,52},{28,10,29},{0,0,0},{130,103,126},{114,90,111},{99,78,97},{83,64,81},{66,49,65},{49,33,48},{28,10,26},{0,0,0},{130,102,119},{114,90,104},{99,77,90},{83,64,76},{66,49,60},{49,33,44},{28,11,22},{0,0,0},
-{131,102,112},{114,90,98},{99,77,84},{83,64,70},{66,49,56},{49,33,40},{28,11,18},{0,0,0},{132,103,105},{115,90,91},{100,77,78},{84,64,64},{67,50,51},{49,34,35},{27,12,13},{0,0,0},{133,103,97},{115,90,84},{100,77,72},{84,64,59},{67,50,46},{49,34,30},{27,12,8},{0,0,0},{134,102,88},{116,90,76},{100,77,65},{83,64,53},{66,49,40},{49,34,24},{27,13,5},{0,0,0},
-{134,102,80},{116,90,68},{100,77,58},{83,64,46},{66,49,33},{49,34,18},{27,13,3},{0,0,0},{134,102,71},{117,90,61},{101,77,50},{84,63,40},{67,49,27},{49,34,12},{26,13,1},{0,0,0},{134,102,64},{117,90,54},{101,77,44},{84,63,34},{67,49,21},{49,34,7},{26,13,1},{0,0,0},{135,102,57},{118,89,48},{102,77,38},{84,64,28},{67,49,15},{49,34,3},{25,13,0},{0,0,0},
-{127,92,167},{112,81,147},{97,69,128},{83,55,109},{66,40,90},{50,23,70},{28,3,45},{0,0,1},{128,92,158},{113,81,140},{99,69,122},{84,56,104},{67,41,85},{50,24,66},{29,3,41},{0,0,0},{129,92,150},{114,81,133},{100,69,116},{84,56,98},{68,41,80},{50,25,62},{29,3,38},{0,0,0},{130,92,143},{115,81,127},{100,69,110},{84,56,94},{68,41,76},{50,25,58},{29,3,34},{0,0,0},
-{131,92,136},{115,81,120},{100,69,105},{84,56,89},{68,41,72},{50,25,54},{29,3,31},{0,0,0},{132,93,129},{116,81,114},{100,69,99},{85,56,84},{68,42,68},{50,26,50},{29,4,27},{0,0,0},{132,93,122},{116,81,108},{100,69,94},{85,56,79},{68,42,63},{50,26,46},{29,4,24},{0,0,0},{132,93,115},{116,81,101},{101,69,88},{84,56,74},{67,42,58},{50,27,42},{29,4,20},{0,0,0},
-{133,93,109},{116,81,95},{101,69,82},{84,56,68},{67,42,54},{50,27,38},{29,4,16},{0,0,0},{133,93,102},{116,81,88},{101,70,76},{85,56,62},{68,43,49},{50,27,33},{28,5,11},{0,0,0},{134,93,94},{116,81,81},{101,70,70},{85,56,57},{68,43,44},{50,27,28},{28,5,6},{0,0,0},{135,92,86},{117,81,74},{101,69,63},{84,56,51},{67,43,38},{50,28,22},{28,6,4},{0,0,0},
-{135,92,78},{117,81,66},{101,69,56},{84,56,44},{67,43,31},{50,28,16},{28,6,2},{0,0,0},{135,92,69},{118,81,59},{102,69,48},{84,56,38},{67,43,25},{50,28,10},{27,6,1},{0,0,0},{135,92,62},{118,81,53},{102,69,42},{84,56,32},{67,43,19},{50,28,6},{27,6,1},{0,0,0},{136,92,56},{118,81,47},{103,69,37},{85,56,27},{68,43,13},{50,28,3},{26,7,0},{0,0,0},
-{129,81,161},{113,70,142},{99,58,124},{83,45,105},{67,30,87},{51,14,67},{29,1,42},{0,0,0},{131,81,153},{114,70,135},{100,59,118},{84,46,100},{68,31,82},{51,14,63},{29,1,38},{0,0,0},{131,81,145},{115,70,128},{100,59,112},{84,46,95},{68,32,77},{51,15,59},{29,1,35},{0,0,0},{132,81,138},{116,70,122},{101,59,106},{85,46,91},{68,32,73},{51,16,55},{29,1,31},{0,0,0},
-{132,81,132},{116,70,116},{101,59,101},{85,46,86},{68,32,69},{51,16,51},{29,1,28},{0,0,0},{133,82,125},{116,71,110},{101,59,95},{85,47,81},{68,33,65},{51,17,47},{29,1,25},{0,0,0},{133,82,118},{116,71,104},{101,59,90},{85,47,76},{68,34,60},{51,18,43},{29,1,21},{0,0,0},{134,82,111},{116,71,98},{101,60,85},{85,48,71},{68,34,55},{51,18,39},{29,2,17},{0,0,0},
-{134,82,105},{116,71,92},{101,60,79},{85,48,65},{68,34,51},{51,18,35},{29,2,13},{0,0,0},{134,82,98},{117,71,85},{101,60,73},{85,48,59},{68,35,46},{50,19,31},{28,2,9},{0,0,0},{134,82,91},{117,71,78},{101,60,67},{85,48,54},{68,35,41},{50,19,26},{28,2,6},{0,0,0},{135,82,83},{117,71,72},{101,60,60},{84,48,48},{67,35,35},{50,20,20},{28,3,4},{0,0,0},
-{135,82,75},{117,71,64},{101,60,53},{84,48,43},{67,35,30},{50,20,15},{28,3,2},{0,0,0},{135,82,68},{118,71,57},{102,60,47},{85,48,37},{67,36,24},{50,20,8},{27,3,1},{0,0,0},{135,82,61},{118,71,51},{102,60,41},{85,48,31},{67,36,18},{50,20,5},{27,3,1},{0,0,0},{136,82,55},{119,71,46},{103,61,36},{85,48,26},{68,36,12},{50,21,3},{26,3,0},{0,0,0},
-{130,69,155},{115,58,137},{100,48,120},{85,35,101},{68,20,83},{52,4,64},{28,0,40},{0,0,0},{132,69,148},{116,59,131},{101,48,114},{85,36,96},{68,21,78},{52,5,60},{28,0,36},{0,0,0},{133,69,140},{117,59,124},{101,48,108},{85,36,91},{68,22,73},{52,5,56},{28,0,33},{0,0,0},{134,69,134},{117,59,118},{102,49,102},{86,37,87},{69,23,69},{52,6,52},{28,0,29},{0,0,0},
-{134,69,127},{117,59,112},{102,49,97},{86,37,82},{69,23,65},{52,6,48},{28,0,26},{0,0,0},{134,70,121},{117,60,106},{102,49,91},{85,38,77},{68,24,61},{52,8,44},{28,0,22},{0,0,0},{134,71,114},{117,60,100},{102,49,86},{85,38,72},{68,25,56},{52,8,41},{28,0,18},{0,0,0},{134,71,107},{117,61,94},{102,50,81},{86,39,67},{69,26,52},{52,9,37},{28,1,13},{0,0,0},
-{134,71,101},{117,61,88},{102,50,75},{86,39,62},{69,26,48},{52,10,33},{28,1,10},{0,0,0},{135,71,94},{118,61,82},{102,50,70},{85,39,57},{68,27,44},{51,11,29},{28,1,7},{0,0,0},{135,71,88},{118,61,76},{102,50,64},{85,39,52},{68,27,39},{51,11,24},{28,1,5},{0,0,0},{135,71,81},{118,61,70},{102,51,58},{85,40,46},{68,28,33},{51,12,18},{27,1,3},{0,0,0},
-{135,71,73},{118,61,62},{102,51,51},{85,40,41},{68,28,28},{51,12,13},{27,1,1},{0,0,0},{136,72,66},{119,62,55},{103,51,45},{86,41,35},{68,29,23},{51,13,7},{26,1,0},{0,0,0},{136,72,60},{119,62,49},{103,51,40},{86,41,30},{68,29,17},{51,13,4},{26,1,0},{0,0,0},{137,71,54},{120,62,44},{103,52,35},{86,41,25},{68,29,11},{51,14,2},{26,1,0},{0,0,0},
-{131,55,149},{116,45,131},{101,33,115},{86,20,97},{69,10,80},{52,2,62},{27,0,38},{0,0,0},{133,55,142},{117,45,125},{102,34,109},{86,22,93},{69,11,75},{53,2,58},{27,0,34},{0,0,0},{134,55,135},{118,45,119},{102,35,103},{86,22,88},{69,11,71},{53,2,54},{27,0,31},{0,0,0},{134,55,129},{118,46,113},{103,35,99},{86,23,84},{69,12,67},{52,3,50},{27,0,27},{0,0,0},
-{134,56,123},{118,46,108},{103,36,94},{86,24,79},{69,12,63},{52,3,46},{27,0,24},{0,0,0},{135,57,117},{118,47,102},{103,37,88},{86,25,75},{69,13,59},{52,4,42},{28,0,20},{0,0,0},{135,58,111},{118,48,97},{103,37,83},{86,26,70},{69,14,54},{52,4,39},{28,0,16},{0,0,0},{135,58,104},{118,49,91},{102,38,78},{86,27,65},{69,15,50},{52,5,35},{27,1,12},{0,0,0},
-{135,58,98},{118,49,85},{102,39,73},{86,28,60},{69,15,46},{52,5,31},{27,1,9},{0,0,0},{135,59,91},{118,49,80},{103,39,68},{85,28,55},{68,16,42},{52,5,27},{27,1,6},{0,0,0},{135,59,85},{118,49,74},{103,40,62},{85,28,50},{68,16,37},{52,5,22},{27,1,4},{0,0,0},{136,59,79},{119,50,68},{103,41,56},{85,29,44},{68,17,31},{51,6,16},{26,1,2},{0,0,0},
-{136,59,72},{119,50,61},{103,41,50},{85,30,39},{68,17,26},{51,6,11},{26,1,1},{0,0,0},{137,60,65},{119,51,54},{104,41,44},{86,31,34},{68,18,21},{51,6,6},{25,1,0},{0,0,0},{137,60,59},{119,51,48},{104,41,39},{86,31,29},{68,18,15},{51,6,4},{25,1,0},{0,0,0},{137,60,53},{120,51,43},{104,42,34},{86,31,24},{68,18,10},{51,7,2},{25,1,0},{0,0,0},
-{133,40,144},{117,30,126},{102,17,110},{87,4,93},{70,0,76},{53,0,59},{25,0,35},{0,0,0},{134,40,137},{118,31,120},{103,19,105},{87,6,89},{70,0,72},{53,0,55},{26,0,31},{0,0,0},{135,40,130},{119,31,114},{103,20,99},{87,7,84},{70,0,68},{53,0,52},{26,0,28},{0,0,0},{136,41,124},{119,32,109},{103,21,95},{87,9,80},{70,1,64},{53,0,48},{26,0,24},{0,0,0},
-{136,42,119},{119,32,104},{103,22,90},{87,10,76},{70,1,60},{53,0,44},{26,0,21},{0,0,0},{136,43,113},{119,34,98},{104,23,85},{87,11,72},{70,2,56},{53,0,40},{27,0,17},{0,0,0},{136,44,107},{119,35,93},{104,24,80},{87,13,67},{70,2,52},{53,0,36},{27,0,13},{0,0,0},{136,45,100},{120,36,88},{103,25,75},{87,14,62},{70,3,48},{53,0,32},{26,0,10},{0,0,0},
-{136,45,94},{120,36,82},{103,26,71},{87,15,58},{70,3,44},{53,0,28},{26,0,7},{0,0,0},{136,46,88},{119,37,77},{104,27,66},{86,16,53},{69,4,40},{52,0,24},{26,0,5},{0,0,0},{136,46,82},{119,37,71},{104,28,60},{86,16,48},{69,4,35},{52,0,19},{26,0,3},{0,0,0},{137,47,76},{120,37,65},{104,29,54},{86,17,42},{69,5,29},{52,0,13},{25,0,1},{0,0,0},
-{137,47,70},{120,38,59},{104,29,49},{86,18,37},{69,5,24},{52,0,9},{25,0,1},{0,0,0},{138,47,63},{120,39,53},{104,30,43},{87,19,32},{69,6,19},{51,0,5},{24,0,0},{0,0,0},{138,47,57},{120,39,47},{104,30,38},{87,19,27},{69,6,13},{51,0,3},{24,0,0},{0,0,0},{137,47,52},{120,40,42},{105,31,33},{87,20,22},{69,6,8},{51,0,1},{23,0,0},{0,0,0},
-{15,192,243},{14,169,214},{11,147,187},{8,126,160},{5,103,133},{1,81,106},{0,55,75},{0,16,34},{18,191,230},{16,168,202},{13,146,177},{10,125,151},{6,103,126},{1,81,100},{0,54,70},{0,15,31},{20,190,218},{18,167,191},{15,146,168},{12,125,143},{7,103,119},{2,81,94},{0,54,65},{0,14,28},{22,189,206},{19,167,182},{16,145,159},{12,124,136},{8,102,113},{2,81,90},{0,54,61},{0,14,24},
-{23,189,195},{20,167,173},{17,145,150},{13,124,129},{9,102,106},{3,81,85},{0,54,57},{0,14,21},{24,188,183},{21,166,163},{17,144,141},{14,123,121},{9,102,100},{4,80,79},{0,54,53},{0,14,15},{24,187,172},{22,165,153},{18,144,133},{15,123,113},{10,102,94},{4,80,74},{0,54,48},{0,14,11},{25,187,162},{22,164,144},{19,143,125},{15,122,106},{10,101,87},{5,80,68},{1,54,44},{0,13,7},
-{30,186,152},{27,164,134},{22,143,117},{15,122,99},{11,101,81},{6,80,62},{1,54,40},{0,12,4},{40,185,140},{37,163,124},{27,142,108},{16,121,92},{11,101,74},{6,80,57},{1,54,35},{0,12,1},{49,185,129},{44,163,113},{32,142,99},{18,121,84},{11,101,67},{6,80,51},{1,54,29},{0,12,0},{57,184,117},{48,163,103},{38,142,89},{22,120,76},{12,100,60},{7,79,44},{1,54,23},{0,11,0},
-{62,184,104},{52,163,92},{40,142,80},{24,120,67},{12,100,52},{7,79,37},{1,54,16},{0,11,0},{66,184,92},{55,162,82},{41,141,70},{25,120,58},{12,99,45},{7,78,31},{1,54,10},{0,11,0},{69,184,83},{57,162,73},{43,141,62},{27,120,51},{13,99,39},{7,78,24},{1,54,6},{0,11,0},{71,183,73},{60,162,64},{45,141,54},{29,119,44},{15,99,33},{7,78,18},{1,53,2},{0,11,0},
-{19,181,235},{17,160,207},{14,140,181},{11,119,155},{7,97,128},{3,76,102},{0,51,72},{0,9,31},{21,180,223},{19,159,196},{15,139,171},{12,118,147},{8,98,122},{3,76,97},{0,50,67},{0,8,28},{23,180,211},{21,159,186},{18,139,163},{13,118,139},{9,98,115},{4,76,91},{0,50,63},{0,7,25},{30,179,200},{25,158,177},{21,138,154},{15,117,132},{10,97,109},{4,76,87},{1,50,59},{0,7,21},
-{37,179,189},{30,158,168},{24,138,146},{16,117,125},{10,97,103},{5,76,82},{1,50,55},{0,7,18},{40,178,178},{33,157,158},{28,137,137},{19,116,117},{11,96,97},{6,75,76},{1,50,51},{0,7,13},{42,177,167},{36,157,149},{30,137,129},{21,116,110},{13,96,91},{6,75,71},{1,50,46},{0,7,8},{45,177,158},{38,156,140},{31,136,121},{23,116,103},{13,96,84},{7,75,65},{1,50,42},{0,7,4},
-{49,176,148},{42,156,130},{34,136,113},{25,116,96},{14,96,78},{7,75,60},{1,50,38},{0,6,2},{56,175,137},{48,155,120},{38,135,105},{26,115,89},{15,95,71},{7,75,54},{1,50,33},{0,6,0},{61,175,126},{53,155,110},{42,135,96},{29,115,81},{16,95,65},{7,75,49},{1,50,27},{0,6,0},{66,174,114},{57,154,100},{46,135,87},{31,114,73},{17,95,58},{9,74,42},{1,50,21},{0,6,0},
-{70,174,102},{60,154,90},{48,135,78},{33,114,65},{18,95,50},{9,74,35},{1,50,14},{0,6,0},{74,174,90},{63,154,79},{50,134,68},{34,114,56},{20,94,43},{10,74,29},{1,50,8},{0,6,0},{76,174,81},{64,154,71},{50,134,60},{35,114,49},{20,94,37},{10,74,22},{1,50,5},{0,6,0},{77,174,71},{66,154,62},{53,134,53},{37,113,43},{22,94,31},{10,74,16},{1,49,2},{0,6,0},
-{23,171,227},{21,151,200},{18,132,174},{14,111,149},{10,91,124},{5,71,99},{1,46,69},{0,2,29},{26,170,215},{23,151,189},{19,131,165},{15,111,142},{10,92,118},{6,71,94},{1,46,65},{0,2,25},{29,170,204},{25,151,180},{21,131,157},{16,111,134},{11,92,112},{6,71,88},{1,46,61},{0,2,22},{40,169,193},{33,150,171},{26,131,149},{18,111,128},{12,91,106},{7,70,84},{1,46,57},{0,1,18},
-{50,169,182},{41,150,162},{31,131,142},{20,111,121},{12,91,100},{7,70,80},{1,46,53},{0,1,15},{55,168,172},{45,149,153},{37,130,134},{24,110,114},{13,90,94},{7,70,74},{1,46,49},{0,1,11},{59,168,162},{49,149,145},{42,130,126},{27,110,107},{15,90,88},{8,70,68},{1,46,44},{0,1,6},{62,168,153},{53,148,136},{43,129,118},{31,109,100},{16,90,82},{8,70,63},{1,46,40},{0,1,2},
-{66,167,143},{56,148,126},{46,129,110},{34,109,93},{18,90,76},{8,70,58},{1,46,36},{0,1,0},{70,166,134},{59,147,117},{49,128,102},{36,108,86},{19,89,69},{8,70,52},{1,46,31},{0,1,0},{73,166,123},{63,147,107},{52,128,94},{38,108,79},{20,89,63},{8,70,47},{1,46,25},{0,1,0},{75,165,112},{65,146,98},{53,127,85},{40,108,71},{22,89,57},{9,70,41},{1,46,19},{0,1,0},
-{78,165,101},{68,146,88},{55,127,76},{41,108,63},{24,89,49},{10,70,34},{1,46,13},{0,1,0},{82,165,89},{70,146,77},{57,127,67},{42,107,55},{27,88,42},{11,70,28},{1,46,7},{0,1,0},{83,165,80},{71,146,69},{58,127,59},{43,107,48},{28,88,36},{11,70,21},{1,46,4},{0,1,0},{84,165,70},{72,146,61},{59,127,52},{45,107,42},{29,88,30},{12,69,15},{1,46,2},{0,1,0},
-{36,162,220},{32,144,194},{28,125,170},{19,105,145},{11,87,120},{6,67,95},{1,42,66},{0,1,27},{42,161,208},{37,143,184},{31,124,161},{23,105,138},{13,87,114},{7,67,90},{1,42,62},{0,1,23},{48,161,198},{41,143,175},{34,124,153},{25,105,130},{15,87,108},{7,67,85},{1,42,58},{0,1,18},{55,161,188},{46,143,166},{38,124,145},{28,105,124},{17,87,102},{9,66,81},{1,42,54},{0,1,14},
-{61,161,178},{51,143,158},{42,124,138},{30,105,117},{18,87,97},{9,66,76},{1,42,50},{0,1,11},{65,160,168},{55,142,149},{45,123,130},{33,104,110},{19,86,91},{10,66,71},{1,42,46},{0,1,7},{68,160,158},{57,142,141},{48,123,122},{36,104,104},{21,86,85},{10,66,66},{1,42,42},{0,1,4},{70,159,149},{61,141,132},{50,122,114},{38,104,97},{23,86,79},{10,66,61},{1,42,38},{0,1,1},
-{74,159,139},{63,141,122},{52,122,106},{40,104,91},{25,86,73},{11,66,56},{1,42,34},{0,1,0},{76,158,130},{65,140,113},{55,121,99},{41,103,84},{25,85,67},{11,66,50},{2,42,29},{0,0,0},{79,158,119},{68,140,104},{57,121,91},{43,103,76},{26,85,61},{11,66,45},{2,42,23},{0,0,0},{81,158,109},{69,139,95},{58,121,83},{45,103,69},{28,85,55},{12,66,39},{2,42,17},{0,0,0},
-{83,158,98},{71,139,86},{59,121,74},{45,103,61},{29,85,47},{12,66,32},{2,42,11},{0,0,0},{85,157,86},{74,139,75},{61,120,65},{46,102,53},{31,84,40},{13,66,26},{2,42,5},{0,0,0},{86,157,78},{74,139,67},{61,120,57},{47,102,46},{31,84,34},{13,66,19},{2,42,3},{0,0,0},{87,157,69},{75,139,60},{63,120,50},{48,102,40},{32,84,29},{14,65,14},{2,42,1},{0,0,0},
-{49,153,212},{43,136,188},{37,118,165},{25,99,141},{15,82,117},{9,63,92},{1,38,63},{0,0,24},{57,153,201},{50,135,179},{42,117,156},{31,99,134},{18,82,111},{9,62,87},{1,38,59},{0,0,20},{64,153,191},{55,135,170},{45,117,148},{35,99,126},{20,82,104},{9,62,82},{1,38,55},{0,0,15},{67,153,182},{58,135,161},{49,117,141},{38,99,120},{23,82,99},{10,62,78},{1,38,51},{0,0,11},
-{71,153,173},{61,135,153},{51,117,134},{40,99,113},{25,82,94},{11,62,73},{2,38,47},{0,0,7},{73,152,163},{63,134,145},{53,116,126},{41,99,107},{26,81,88},{12,62,68},{2,38,43},{0,0,4},{76,152,154},{66,134,137},{55,116,118},{42,99,101},{28,81,82},{12,62,63},{2,38,39},{0,0,2},{79,151,145},{67,133,128},{56,115,111},{44,98,94},{29,81,76},{13,62,58},{2,38,35},{0,0,1},
-{81,151,135},{70,133,119},{58,115,103},{46,98,88},{30,81,70},{14,62,53},{2,38,31},{0,0,0},{82,150,126},{71,132,110},{60,115,96},{46,98,81},{31,80,64},{14,62,48},{3,38,26},{0,0,0},{84,150,116},{73,132,101},{61,115,88},{47,98,73},{32,80,58},{14,62,42},{3,38,21},{0,0,0},{86,150,106},{74,131,92},{62,114,80},{49,97,66},{34,80,52},{15,62,36},{3,38,15},{0,0,0},
-{88,150,95},{76,131,83},{63,114,71},{50,97,58},{34,80,45},{15,62,30},{3,38,10},{0,0,0},{90,149,84},{78,132,74},{65,114,62},{51,97,51},{35,79,39},{16,62,24},{3,38,4},{0,0,0},{90,149,76},{78,132,66},{65,114,56},{51,97,45},{35,79,33},{16,62,18},{3,38,2},{0,0,0},{91,149,68},{79,131,59},{66,113,49},{52,97,39},{36,79,27},{17,61,12},{3,38,1},{0,0,0},
-{62,143,205},{54,127,182},{47,111,159},{35,93,136},{23,76,113},{11,57,89},{2,33,61},{0,0,21},{67,143,194},{59,126,173},{50,110,151},{39,93,129},{26,76,107},{12,57,84},{3,33,57},{0,0,17},{72,143,185},{63,126,164},{53,110,143},{42,93,122},{28,76,100},{13,57,79},{3,33,53},{0,0,12},{75,143,176},{66,126,156},{56,110,136},{44,93,116},{30,76,95},{14,58,75},{4,33,49},{0,0,8},
-{78,143,167},{67,126,148},{57,110,129},{45,93,109},{30,76,90},{15,58,70},{4,33,45},{0,0,5},{80,143,157},{69,125,139},{59,109,122},{46,93,103},{32,75,84},{16,58,66},{4,34,41},{0,0,2},{82,143,149},{72,125,131},{60,109,114},{47,93,97},{33,75,79},{17,58,61},{4,34,37},{0,0,1},{84,142,140},{73,124,123},{61,108,107},{49,92,91},{34,75,74},{18,58,56},{4,34,33},{0,0,0},
-{85,142,131},{75,124,115},{62,108,100},{50,92,85},{35,75,68},{19,58,51},{4,34,29},{0,0,0},{87,141,122},{76,124,107},{64,108,93},{51,92,78},{36,74,62},{19,57,46},{4,34,24},{0,0,0},{89,141,113},{77,124,99},{65,108,85},{52,92,71},{37,74,56},{19,57,40},{4,34,19},{0,0,0},{91,141,103},{78,123,90},{66,107,78},{53,91,64},{38,74,50},{20,57,34},{4,34,13},{0,0,0},
-{92,141,93},{79,123,81},{67,107,69},{53,91,56},{38,74,43},{20,57,28},{4,34,8},{0,0,0},{94,140,82},{81,123,72},{69,107,60},{54,91,49},{39,74,37},{21,57,22},{5,34,3},{0,0,0},{94,140,74},{81,123,64},{69,107,54},{55,91,43},{39,74,31},{21,57,16},{5,34,2},{0,0,0},{95,140,67},{82,123,57},{70,107,48},{56,91,38},{39,74,25},{21,57,10},{4,34,1},{0,0,0},
-{73,134,198},{63,118,176},{54,103,154},{44,87,131},{30,70,109},{14,52,86},{3,28,58},{0,0,18},{76,134,188},{66,118,167},{57,103,146},{46,87,124},{33,70,103},{16,52,81},{4,28,54},{0,0,14},{79,134,179},{70,118,158},{60,103,138},{48,87,117},{35,70,97},{18,52,76},{4,28,50},{0,0,9},{81,134,170},{72,118,151},{61,102,131},{49,87,112},{36,70,92},{19,53,72},{5,28,46},{0,0,5},
-{83,134,161},{73,118,143},{62,102,124},{50,87,106},{36,70,87},{19,53,67},{5,28,42},{0,0,2},{86,134,152},{75,117,135},{64,102,118},{51,87,100},{37,70,81},{20,53,63},{5,29,38},{0,0,1},{88,134,144},{76,117,127},{64,102,111},{52,87,94},{38,70,76},{21,53,58},{5,29,34},{0,0,0},{89,133,136},{77,116,119},{65,102,104},{53,86,88},{39,70,71},{22,53,53},{5,29,30},{0,0,0},
-{91,133,128},{79,116,111},{67,102,97},{53,86,82},{39,70,65},{23,53,49},{5,29,26},{0,0,0},{92,133,119},{80,116,104},{68,101,90},{54,86,75},{39,69,59},{23,52,44},{6,30,22},{0,0,0},{94,133,110},{80,116,96},{69,101,82},{55,86,69},{40,69,53},{23,52,38},{6,30,17},{0,0,0},{95,132,100},{81,115,87},{70,101,75},{56,85,62},{41,69,47},{23,52,32},{5,30,11},{0,0,0},
-{95,132,90},{82,115,79},{70,101,67},{56,85,54},{41,69,41},{23,52,26},{5,30,7},{0,0,0},{97,131,80},{84,115,70},{71,101,59},{57,85,47},{42,69,35},{24,52,20},{6,30,3},{0,0,0},{97,131,73},{84,115,62},{72,101,52},{57,85,41},{42,69,29},{24,52,14},{6,30,2},{0,0,0},{98,132,66},{85,115,55},{73,101,46},{58,85,36},{43,69,24},{24,52,8},{6,30,1},{0,0,0},
-{79,125,192},{69,111,169},{59,96,149},{48,81,127},{35,65,105},{19,47,83},{5,23,55},{0,0,15},{82,125,182},{72,110,161},{62,96,141},{50,81,120},{37,65,99},{21,47,78},{5,23,51},{0,0,11},{85,125,173},{74,110,153},{64,96,133},{51,81,113},{38,65,93},{23,47,73},{6,23,48},{0,0,6},{87,125,165},{76,110,146},{66,95,127},{52,81,108},{39,65,89},{23,48,69},{7,24,44},{0,0,3},
-{89,125,156},{77,110,138},{67,95,120},{53,81,103},{40,65,84},{23,48,64},{7,24,40},{0,0,1},{90,125,148},{79,110,131},{68,95,114},{54,81,97},{41,65,78},{24,48,60},{7,24,36},{0,0,0},{92,125,140},{79,110,123},{68,95,108},{54,81,91},{41,65,73},{25,48,55},{7,24,32},{0,0,0},{93,124,132},{80,109,116},{69,95,101},{55,80,85},{42,65,68},{26,48,51},{7,25,28},{0,0,0},
-{94,124,124},{82,109,108},{69,95,94},{56,80,79},{42,65,62},{26,48,47},{7,25,24},{0,0,0},{95,124,115},{83,109,101},{70,94,87},{56,80,73},{42,64,57},{26,47,42},{7,26,20},{0,0,0},{96,124,107},{84,109,93},{71,94,80},{57,80,67},{43,64,52},{26,47,37},{7,26,15},{0,0,0},{97,124,97},{85,108,85},{72,94,73},{58,80,60},{44,64,46},{27,47,31},{7,26,9},{0,0,0},
-{98,124,88},{85,108,77},{73,94,65},{58,80,53},{44,64,40},{27,47,25},{7,26,6},{0,0,0},{99,123,79},{87,108,68},{73,94,58},{59,80,46},{44,64,34},{27,47,19},{7,26,2},{0,0,0},{99,123,72},{87,108,61},{74,94,51},{59,80,40},{44,64,28},{27,47,13},{7,26,1},{0,0,0},{100,123,65},{87,108,54},{74,94,45},{60,80,35},{44,64,23},{27,47,7},{7,26,0},{0,0,0},
-{86,117,186},{75,103,164},{64,90,144},{52,75,123},{39,59,101},{23,42,80},{7,17,53},{0,0,12},{88,117,176},{77,103,156},{66,89,137},{54,75,116},{41,59,95},{25,42,75},{8,18,49},{0,0,8},{89,117,167},{78,103,148},{68,89,129},{55,75,109},{42,59,90},{27,42,70},{8,18,46},{0,0,3},{91,117,160},{79,103,141},{69,89,123},{56,75,104},{43,59,86},{28,42,66},{8,19,42},{0,0,1},
-{93,117,152},{80,103,134},{69,89,116},{57,75,99},{43,59,81},{28,42,62},{8,19,38},{0,0,0},{94,117,144},{82,103,127},{70,89,110},{57,75,93},{44,59,75},{29,42,58},{8,19,34},{0,0,0},{95,117,136},{83,103,119},{71,89,104},{57,75,87},{44,59,70},{29,42,53},{8,19,30},{0,0,0},{96,116,128},{84,103,112},{72,89,97},{58,74,82},{45,59,65},{29,42,49},{8,20,26},{0,0,0},
-{97,116,120},{85,103,105},{72,89,91},{58,74,76},{45,59,60},{29,42,45},{8,20,22},{0,0,0},{98,116,112},{86,102,98},{73,88,84},{59,74,71},{45,59,55},{29,43,40},{9,21,18},{0,0,0},{99,116,104},{86,102,90},{74,88,78},{59,74,65},{45,59,50},{29,43,35},{8,21,13},{0,0,0},{100,116,95},{87,102,83},{75,88,71},{60,74,58},{46,59,44},{29,43,29},{8,22,7},{0,0,0},
-{100,116,86},{88,102,75},{75,88,63},{60,74,51},{46,59,38},{29,43,23},{8,22,4},{0,0,0},{101,115,77},{89,102,66},{75,88,56},{61,74,44},{46,59,32},{29,43,17},{8,22,2},{0,0,0},{101,115,70},{89,102,59},{76,88,49},{61,74,38},{46,59,26},{29,43,11},{8,22,1},{0,0,0},{102,115,63},{89,101,52},{76,88,43},{62,74,33},{46,59,21},{30,43,5},{8,22,0},{0,0,0},
-{90,108,179},{79,96,159},{67,83,139},{56,68,118},{43,52,97},{27,36,77},{8,10,50},{0,0,8},{92,108,170},{81,96,152},{70,82,132},{57,68,112},{44,53,92},{28,37,72},{9,11,46},{0,0,5},{93,108,162},{83,96,144},{71,82,124},{58,68,105},{45,53,87},{29,37,68},{9,11,43},{0,0,1},{95,108,155},{84,96,137},{72,82,119},{59,68,101},{45,53,83},{30,37,64},{9,12,39},{0,0,0},
-{96,108,147},{84,96,129},{72,82,113},{59,68,96},{45,53,78},{31,37,60},{10,12,36},{0,0,0},{97,108,139},{85,96,123},{73,82,107},{60,68,90},{46,53,72},{31,37,55},{10,13,32},{0,0,0},{97,108,131},{85,96,115},{73,82,100},{60,68,84},{46,53,67},{31,37,51},{10,13,28},{0,0,0},{98,108,124},{86,96,108},{74,82,93},{61,67,79},{46,53,63},{31,37,47},{10,14,24},{0,0,0},
-{100,108,116},{87,96,101},{74,82,87},{61,67,73},{46,53,59},{31,37,43},{11,15,20},{0,0,0},{101,108,109},{87,95,95},{75,82,81},{61,68,68},{47,54,54},{31,38,38},{11,16,16},{0,0,0},{101,108,101},{88,95,87},{75,82,75},{61,68,62},{47,54,49},{31,38,33},{11,16,11},{0,0,0},{102,108,92},{89,95,80},{76,82,69},{62,68,56},{47,53,43},{31,38,27},{10,17,6},{0,0,0},
-{102,108,84},{89,95,72},{76,82,61},{62,68,50},{47,53,37},{31,38,22},{10,17,3},{0,0,0},{103,107,75},{90,95,65},{77,81,54},{63,68,43},{47,54,31},{32,38,16},{10,17,1},{0,0,0},{103,107,68},{90,95,58},{77,81,48},{63,68,37},{47,54,25},{32,38,10},{10,17,1},{0,0,0},{104,107,62},{91,94,51},{77,81,42},{63,67,32},{47,54,20},{31,38,4},{9,17,0},{0,0,0},
-{94,99,173},{83,88,153},{71,75,134},{59,61,114},{45,46,94},{31,29,74},{8,5,48},{0,0,5},{95,99,164},{84,88,146},{73,75,127},{61,61,108},{46,46,89},{31,30,69},{9,6,44},{0,0,3},{96,99,156},{86,88,139},{74,75,120},{61,61,102},{47,47,84},{31,30,65},{10,7,41},{0,0,0},{98,99,150},{87,88,132},{74,75,114},{62,61,98},{48,47,80},{32,31,61},{11,7,37},{0,0,0},
-{99,99,142},{87,88,124},{74,75,109},{62,61,93},{48,47,75},{33,31,57},{11,7,33},{0,0,0},{100,100,134},{88,88,118},{75,75,103},{62,62,87},{48,47,70},{33,31,53},{12,8,30},{0,0,0},{100,100,127},{88,88,112},{75,75,97},{62,62,81},{48,47,65},{33,31,48},{12,8,26},{0,0,0},{101,100,120},{89,88,105},{76,75,91},{63,61,76},{48,47,60},{33,31,44},{12,9,22},{0,0,0},
-{103,100,113},{89,88,98},{76,75,85},{63,61,71},{48,47,56},{33,31,40},{12,9,18},{0,0,0},{104,99,106},{90,87,92},{76,75,79},{63,62,65},{49,48,52},{33,32,36},{12,10,13},{0,0,0},{104,99,98},{90,87,85},{77,75,73},{63,62,60},{49,48,47},{33,32,31},{12,10,9},{0,0,0},{105,99,90},{91,87,78},{78,75,67},{64,62,54},{48,47,41},{33,32,25},{11,11,6},{0,0,0},
-{105,99,82},{91,87,70},{78,75,59},{64,62,48},{48,47,35},{33,32,20},{11,11,3},{0,0,0},{105,99,73},{92,87,63},{79,75,52},{64,62,42},{49,48,29},{33,32,14},{11,11,1},{0,0,0},{105,99,66},{92,87,56},{79,75,46},{64,62,36},{49,48,23},{33,32,8},{11,11,1},{0,0,0},{106,99,60},{93,87,51},{79,75,41},{64,61,30},{49,48,18},{33,32,4},{11,11,0},{0,0,0},
-{97,90,167},{86,79,147},{74,67,128},{62,53,110},{48,38,90},{33,21,70},{10,3,46},{0,0,2},{99,90,158},{87,79,140},{75,67,122},{63,54,105},{49,39,86},{33,22,66},{11,3,42},{0,0,1},{100,90,150},{88,79,133},{76,67,116},{63,54,99},{49,40,81},{33,23,63},{11,3,39},{0,0,0},{101,90,144},{89,79,127},{77,67,110},{64,54,94},{50,40,77},{34,24,59},{12,3,35},{0,0,0},
-{102,90,137},{90,79,120},{77,67,105},{64,54,89},{50,40,72},{34,24,55},{12,3,31},{0,0,0},{102,91,130},{90,79,114},{77,67,99},{64,54,84},{50,41,68},{34,25,51},{13,4,28},{0,0,0},{102,91,123},{90,79,108},{77,67,94},{64,54,79},{50,41,63},{34,25,46},{13,4,24},{0,0,0},{103,91,116},{91,79,102},{78,67,89},{65,55,74},{50,41,58},{34,25,42},{13,5,20},{0,0,0},
-{105,91,110},{91,79,96},{78,67,83},{65,55,69},{50,41,54},{34,25,38},{13,5,16},{0,0,0},{105,90,103},{92,79,90},{78,68,77},{65,55,63},{51,42,50},{34,26,34},{13,5,11},{0,0,0},{106,90,95},{92,79,83},{79,68,71},{65,55,58},{51,42,45},{34,26,29},{13,5,7},{0,0,0},{107,90,88},{93,79,76},{80,67,65},{65,55,52},{50,41,39},{34,26,23},{12,6,5},{0,0,0},
-{107,90,80},{93,79,68},{80,67,57},{65,55,46},{50,41,33},{34,26,18},{12,6,3},{0,0,0},{107,90,71},{94,79,61},{81,68,50},{66,55,40},{51,42,27},{35,26,12},{12,6,1},{0,0,0},{107,90,65},{94,79,55},{81,68,45},{66,55,34},{51,42,22},{35,26,7},{12,6,1},{0,0,0},{108,90,59},{94,79,50},{81,68,40},{66,55,29},{51,42,17},{34,27,4},{12,6,0},{0,0,0},
-{101,79,161},{89,69,142},{77,57,124},{64,44,106},{50,29,87},{35,13,67},{10,1,43},{0,0,1},{102,80,153},{90,69,135},{78,57,118},{65,45,101},{51,30,82},{35,14,63},{11,1,39},{0,0,0},{103,80,145},{91,69,129},{79,57,112},{65,45,95},{51,31,78},{35,14,60},{11,1,36},{0,0,0},{104,80,139},{91,69,123},{80,58,107},{66,46,91},{51,32,74},{36,15,56},{12,1,32},{0,0,0},
-{104,80,133},{92,69,116},{80,58,102},{66,46,86},{51,32,69},{36,15,52},{12,1,28},{0,0,0},{105,81,126},{92,69,110},{80,58,96},{65,46,81},{51,32,65},{35,16,48},{13,2,25},{0,0,0},{105,81,119},{92,69,104},{80,58,90},{65,46,76},{51,33,60},{35,17,43},{13,2,21},{0,0,0},{106,81,112},{93,70,99},{80,58,85},{66,47,71},{52,33,55},{35,17,39},{13,3,17},{0,0,0},
-{106,81,106},{93,70,93},{80,58,80},{66,47,66},{52,33,51},{35,17,35},{13,3,13},{0,0,0},{107,81,99},{93,70,87},{81,59,74},{66,47,60},{51,34,47},{36,18,31},{13,3,9},{0,0,0},{107,81,92},{93,70,80},{81,59,68},{66,47,55},{51,34,42},{36,18,26},{13,3,6},{0,0,0},{108,80,85},{94,70,73},{81,59,62},{66,47,49},{51,34,37},{36,19,21},{13,3,4},{0,0,0},
-{108,80,77},{94,70,66},{81,59,55},{66,47,44},{51,34,32},{36,19,16},{13,3,2},{0,0,0},{108,81,70},{95,70,59},{82,59,49},{67,47,39},{51,35,26},{36,19,10},{13,3,1},{0,0,0},{108,81,64},{95,70,53},{82,59,44},{67,47,33},{51,35,21},{36,19,7},{13,3,1},{0,0,0},{109,80,58},{96,70,48},{82,60,39},{67,47,28},{51,35,16},{35,20,4},{12,3,0},{0,0,0},
-{104,68,156},{91,58,137},{80,48,120},{66,35,102},{52,20,83},{37,4,64},{10,0,40},{0,0,0},{105,68,149},{92,59,131},{81,48,114},{67,36,97},{53,21,78},{37,5,60},{11,0,36},{0,0,0},{106,68,141},{93,59,125},{81,48,108},{68,36,91},{53,22,74},{37,5,57},{11,0,33},{0,0,0},{107,69,135},{94,59,119},{82,49,103},{68,37,87},{53,23,70},{38,6,53},{12,0,29},{0,0,0},
-{107,69,129},{94,59,112},{82,49,98},{68,37,82},{53,23,66},{38,6,49},{12,0,26},{0,0,0},{107,70,122},{95,60,106},{82,49,92},{67,38,77},{53,24,61},{37,7,45},{12,0,23},{0,0,0},{107,70,115},{95,60,100},{82,49,86},{67,38,72},{53,24,57},{37,8,41},{12,0,19},{0,0,0},{108,70,108},{95,61,95},{82,49,81},{67,39,67},{53,25,53},{37,9,37},{12,1,14},{0,0,0},
-{108,70,102},{95,61,89},{82,49,76},{67,39,63},{53,26,49},{37,10,33},{13,1,10},{0,0,0},{109,70,95},{95,61,83},{82,50,71},{68,39,58},{52,26,45},{37,10,29},{14,1,7},{0,0,0},{109,70,89},{95,61,77},{82,50,65},{68,39,53},{52,26,40},{37,10,24},{14,1,5},{0,0,0},{109,71,82},{96,61,71},{82,50,59},{68,39,47},{53,27,35},{37,11,19},{13,1,3},{0,0,0},
-{109,71,75},{96,61,64},{82,50,53},{68,39,42},{53,27,30},{37,11,14},{13,1,1},{0,0,0},{110,71,68},{97,61,57},{83,51,47},{69,40,37},{52,28,25},{37,12,9},{13,1,0},{0,0,0},{110,71,62},{97,61,51},{83,51,42},{69,40,32},{52,28,19},{37,12,6},{13,1,0},{0,0,0},{111,71,56},{97,61,46},{83,51,37},{69,40,27},{52,29,14},{37,13,3},{12,1,0},{0,0,0},
-{106,56,150},{93,46,132},{81,35,116},{68,22,98},{53,10,80},{38,2,62},{10,0,38},{0,0,0},{107,56,143},{94,47,126},{82,36,110},{69,23,93},{54,11,76},{38,2,58},{11,0,34},{0,0,0},{108,56,136},{95,47,120},{82,36,104},{69,23,88},{54,12,72},{38,2,55},{11,0,31},{0,0,0},{109,57,130},{96,47,114},{83,37,100},{69,25,84},{54,13,68},{38,3,51},{11,0,27},{0,0,0},
-{109,57,124},{96,47,109},{83,37,95},{69,25,80},{54,13,64},{38,3,47},{11,0,24},{0,0,0},{109,58,118},{96,49,103},{83,38,89},{68,26,75},{54,14,59},{38,3,43},{12,0,21},{0,0,0},{109,59,112},{96,49,98},{83,38,84},{68,27,70},{54,14,55},{38,4,39},{12,0,17},{0,0,0},{109,59,105},{96,50,92},{82,39,79},{68,28,65},{54,15,51},{38,4,35},{13,1,12},{0,0,0},
-{109,60,99},{96,50,86},{82,40,74},{68,29,61},{54,16,47},{38,5,31},{13,1,9},{0,0,0},{110,60,93},{96,51,81},{83,40,69},{68,29,56},{53,16,43},{38,5,28},{13,1,6},{0,0,0},{110,60,87},{96,51,75},{83,41,63},{68,29,51},{53,16,38},{38,5,23},{13,1,4},{0,0,0},{110,61,80},{97,51,69},{83,41,57},{68,30,46},{53,17,33},{38,6,17},{13,1,2},{0,0,0},
-{110,61,73},{97,51,63},{83,41,52},{68,30,41},{53,18,28},{38,6,13},{13,1,1},{0,0,0},{111,61,67},{98,51,56},{84,42,46},{69,31,36},{53,19,23},{37,6,8},{13,1,0},{0,0,0},{111,61,61},{98,51,50},{84,42,41},{69,31,31},{53,19,18},{37,6,5},{13,1,0},{0,0,0},{112,61,55},{98,51,45},{84,42,36},{69,31,26},{53,19,13},{37,7,3},{12,1,0},{0,0,0},
-{108,44,145},{96,33,127},{82,22,111},{70,8,95},{55,0,77},{39,0,60},{9,0,36},{0,0,0},{109,43,138},{97,34,121},{83,23,106},{70,9,90},{55,1,73},{39,0,56},{10,0,32},{0,0,0},{110,43,131},{97,34,115},{84,24,100},{70,10,85},{55,1,69},{39,0,52},{10,0,29},{0,0,0},{111,44,125},{98,35,110},{84,25,96},{70,12,81},{55,2,65},{39,0,48},{11,0,25},{0,0,0},
-{111,45,120},{98,35,105},{84,26,91},{70,13,77},{55,2,61},{39,0,45},{12,0,22},{0,0,0},{111,46,114},{98,37,99},{84,27,86},{70,15,72},{55,3,57},{39,0,41},{13,0,18},{0,0,0},{111,47,108},{98,38,94},{84,27,81},{70,16,67},{55,3,53},{39,0,37},{13,0,14},{0,0,0},{111,47,102},{97,39,89},{84,28,76},{70,17,62},{55,4,49},{39,0,33},{13,0,10},{0,0,0},
-{111,48,96},{97,39,83},{84,29,72},{70,17,58},{55,5,45},{39,0,29},{13,0,7},{0,0,0},{111,49,90},{98,39,78},{84,30,67},{69,18,54},{54,6,41},{39,0,25},{13,0,5},{0,0,0},{111,49,84},{98,39,72},{84,30,61},{69,19,49},{54,6,36},{39,0,21},{13,0,3},{0,0,0},{112,49,78},{99,39,66},{85,31,55},{70,20,44},{54,6,31},{39,1,15},{13,0,1},{0,0,0},
-{112,49,71},{99,40,61},{85,31,50},{70,20,39},{54,7,26},{39,1,11},{13,0,1},{0,0,0},{113,49,65},{99,41,55},{85,31,45},{70,21,34},{54,8,21},{38,1,7},{13,0,1},{0,0,0},{113,49,59},{99,41,49},{85,31,40},{70,21,29},{54,8,16},{38,1,4},{13,0,1},{0,0,0},{112,50,54},{99,41,44},{85,32,35},{70,22,24},{54,9,11},{37,1,2},{12,0,0},{0,0,0},
-{0,182,240},{0,161,213},{0,140,186},{0,120,159},{0,99,133},{0,77,105},{0,51,74},{0,10,34},{0,181,228},{0,160,202},{0,140,176},{0,119,151},{0,99,126},{0,77,99},{0,51,70},{0,9,31},{0,180,217},{0,160,191},{0,140,167},{0,119,143},{0,99,118},{0,77,93},{0,51,65},{0,9,29},{0,179,205},{0,159,182},{0,139,159},{0,118,136},{0,98,112},{0,77,89},{0,51,61},{0,9,25},
-{0,179,194},{0,158,172},{0,139,151},{0,118,129},{0,98,106},{0,77,84},{0,51,57},{0,9,21},{0,178,184},{0,157,162},{0,138,142},{0,118,121},{0,98,100},{0,76,78},{0,51,53},{0,9,17},{0,178,173},{0,157,153},{0,138,133},{0,118,113},{0,98,94},{0,76,73},{0,51,48},{0,9,12},{0,177,162},{0,157,144},{0,137,125},{0,117,106},{0,97,87},{0,76,68},{0,50,44},{0,8,7},
-{1,177,152},{1,157,134},{0,137,117},{0,117,99},{0,97,81},{0,76,63},{0,50,40},{0,8,4},{2,176,142},{2,156,125},{1,137,109},{0,116,92},{0,96,75},{0,76,58},{0,51,35},{0,7,1},{4,175,130},{3,155,115},{2,137,100},{0,116,85},{0,96,69},{0,76,52},{0,51,30},{0,7,0},{5,174,118},{4,154,105},{3,136,91},{1,116,77},{0,96,62},{0,75,46},{0,50,24},{0,7,0},
-{6,174,107},{5,154,95},{3,136,82},{1,116,69},{0,96,55},{0,75,39},{0,50,18},{0,7,0},{7,174,95},{5,154,85},{4,135,73},{1,115,60},{0,95,48},{0,75,33},{0,50,12},{0,7,0},{7,174,86},{6,154,77},{4,135,66},{2,115,54},{0,95,42},{0,75,27},{0,50,7},{0,7,0},{7,174,76},{6,154,68},{4,134,58},{2,115,48},{0,95,37},{0,74,22},{0,50,2},{0,7,0},
-{0,173,233},{0,153,206},{0,133,180},{0,114,154},{0,93,128},{0,72,102},{0,47,71},{0,5,32},{0,172,221},{0,152,196},{0,133,170},{0,113,146},{0,94,122},{0,72,96},{0,47,67},{0,4,28},{0,171,210},{0,151,185},{0,133,162},{0,113,138},{0,94,114},{0,72,90},{0,47,62},{0,4,26},{1,170,199},{1,151,176},{1,132,154},{0,112,132},{0,93,108},{0,72,86},{0,47,58},{0,4,22},
-{2,170,189},{2,151,167},{1,132,146},{0,112,125},{0,93,103},{0,72,81},{0,47,54},{0,4,18},{3,169,179},{2,150,158},{2,131,138},{1,112,117},{0,92,97},{0,71,75},{0,47,50},{0,4,13},{3,169,168},{2,150,149},{2,131,129},{1,112,110},{0,92,91},{0,71,70},{0,47,46},{0,4,9},{3,168,157},{3,149,140},{2,130,121},{1,111,103},{0,92,84},{0,71,65},{0,46,42},{0,3,4},
-{4,168,147},{3,149,130},{2,130,113},{2,111,96},{0,92,78},{0,71,60},{0,46,38},{0,3,2},{5,167,138},{4,148,121},{3,130,106},{2,110,89},{1,91,72},{0,71,55},{0,47,33},{0,3,0},{6,166,127},{5,148,112},{4,130,97},{2,110,82},{1,91,66},{0,71,50},{0,47,28},{0,3,0},{7,166,116},{6,147,102},{4,129,89},{2,110,75},{1,91,60},{0,71,44},{0,46,22},{0,3,0},
-{7,166,105},{6,147,93},{5,129,80},{3,110,67},{1,91,53},{0,71,37},{0,46,16},{0,3,0},{8,166,93},{7,147,83},{5,128,71},{3,109,59},{1,90,46},{0,71,31},{0,46,10},{0,3,0},{8,166,84},{7,147,75},{5,128,64},{3,109,52},{1,90,40},{0,71,25},{0,46,6},{0,3,0},{8,165,75},{7,147,66},{5,128,57},{3,109,47},{2,90,35},{0,70,20},{0,46,2},{0,3,0},
-{0,164,225},{0,145,199},{0,126,173},{0,107,148},{0,87,124},{0,67,99},{0,42,68},{0,0,30},{0,163,214},{0,144,189},{0,125,164},{0,107,141},{0,88,118},{0,67,94},{0,42,64},{0,0,26},{1,162,203},{1,143,179},{0,125,156},{0,107,134},{0,88,111},{0,67,88},{0,42,60},{0,0,23},{2,162,193},{2,143,170},{1,125,149},{0,106,128},{0,87,105},{0,67,84},{0,43,56},{0,0,19},
-{4,162,183},{3,143,162},{2,125,142},{1,106,121},{0,87,100},{0,67,79},{0,43,52},{0,0,15},{5,161,173},{4,142,153},{3,124,134},{1,105,114},{0,86,94},{0,67,73},{0,43,48},{0,0,10},{6,160,162},{5,142,144},{4,124,126},{2,105,107},{1,86,88},{0,67,68},{0,43,44},{0,0,6},{6,160,152},{5,141,135},{4,123,118},{2,105,100},{1,86,82},{0,67,63},{0,43,40},{0,0,2},
-{7,159,143},{6,141,127},{4,123,110},{3,105,94},{1,86,76},{0,67,58},{0,43,36},{0,0,0},{7,158,134},{6,140,118},{5,122,103},{3,104,87},{1,85,70},{0,67,53},{0,43,31},{0,0,0},{8,158,124},{7,140,109},{5,122,95},{4,104,80},{1,85,64},{0,67,48},{0,43,26},{0,0,0},{8,158,114},{7,139,100},{6,122,87},{4,104,73},{2,85,58},{0,67,42},{0,43,21},{0,0,0},
-{9,158,103},{7,139,91},{6,122,79},{4,104,65},{2,85,51},{0,67,36},{0,43,15},{0,0,0},{9,158,92},{8,139,81},{6,121,70},{4,103,58},{2,84,45},{0,66,30},{0,43,9},{0,0,0},{10,158,83},{8,139,73},{6,121,63},{4,103,51},{2,84,39},{0,66,24},{0,43,5},{0,0,0},{10,157,74},{9,139,65},{6,121,56},{5,103,45},{3,84,34},{1,66,19},{0,43,2},{0,0,0},
-{2,155,219},{2,138,193},{2,120,169},{1,101,144},{0,83,120},{0,63,95},{0,38,66},{0,0,27},{3,154,208},{3,137,183},{2,119,160},{1,101,137},{0,83,114},{0,63,90},{0,38,62},{0,0,23},{4,154,197},{3,136,174},{3,119,152},{2,101,130},{1,83,107},{0,63,85},{0,38,58},{0,0,19},{5,154,187},{4,136,166},{3,119,145},{2,101,124},{1,83,102},{0,63,81},{0,39,54},{0,0,15},
-{6,154,178},{5,136,158},{4,119,138},{2,101,117},{1,83,97},{0,63,76},{0,39,50},{0,0,11},{6,153,169},{5,135,149},{4,118,130},{3,100,110},{1,82,91},{0,63,71},{0,39,46},{0,0,6},{7,153,158},{6,135,140},{5,118,122},{3,100,104},{1,82,86},{0,63,66},{0,39,42},{0,0,4},{7,152,148},{6,134,131},{5,117,114},{4,100,97},{2,82,79},{0,63,61},{0,39,38},{0,0,1},
-{8,152,139},{7,134,123},{5,117,107},{4,100,91},{2,82,73},{0,63,56},{0,39,34},{0,0,0},{8,151,130},{7,134,114},{6,117,100},{4,99,84},{2,81,68},{0,63,51},{0,39,29},{0,0,0},{9,151,120},{7,134,106},{6,117,92},{4,99,77},{2,81,62},{0,63,46},{0,39,24},{0,0,0},{9,151,110},{8,133,97},{6,116,84},{5,99,71},{2,81,56},{1,63,40},{0,39,19},{0,0,0},
-{10,151,100},{8,133,88},{6,116,76},{5,99,63},{3,81,49},{1,63,34},{0,39,13},{0,0,0},{11,150,89},{8,133,79},{7,116,68},{5,98,56},{3,80,43},{1,62,28},{0,39,7},{0,0,0},{15,150,81},{11,133,71},{7,116,61},{5,98,50},{3,80,37},{1,62,23},{0,39,4},{0,0,0},{19,150,73},{15,132,63},{7,116,54},{5,98,44},{3,80,32},{1,62,18},{0,39,2},{0,0,0},
-{4,147,212},{3,130,187},{3,113,164},{2,95,140},{0,78,116},{0,59,91},{0,34,63},{0,0,24},{5,146,201},{5,129,178},{4,113,155},{2,95,133},{1,78,110},{0,59,87},{0,34,59},{0,0,20},{6,146,191},{5,129,169},{4,113,147},{3,95,126},{1,78,104},{0,59,82},{0,34,55},{0,0,15},{7,146,182},{6,129,161},{5,112,141},{4,95,120},{2,78,99},{0,59,78},{0,35,51},{0,0,11},
-{8,146,173},{6,129,153},{5,112,134},{4,95,113},{2,78,94},{0,59,73},{0,35,47},{0,0,7},{8,145,164},{7,128,144},{6,112,126},{4,95,107},{2,77,88},{1,59,68},{0,35,43},{0,0,4},{8,145,154},{7,128,136},{6,112,118},{4,95,101},{2,77,83},{1,59,63},{0,35,39},{0,0,2},{10,144,144},{7,127,127},{6,111,111},{5,94,94},{3,77,76},{1,59,58},{0,35,35},{0,0,1},
-{11,144,135},{9,127,119},{6,111,104},{5,94,88},{3,77,70},{1,59,54},{0,35,31},{0,0,0},{12,143,126},{10,127,111},{7,111,97},{5,94,81},{3,76,65},{1,59,49},{0,35,27},{0,0,0},{12,143,117},{11,127,103},{8,111,89},{5,94,74},{3,76,59},{1,59,44},{0,35,22},{0,0,0},{13,143,107},{11,126,94},{9,110,81},{6,93,68},{3,76,53},{1,59,38},{0,35,17},{0,0,0},
-{15,143,97},{12,126,85},{10,110,73},{6,93,61},{3,76,47},{1,59,32},{0,35,11},{0,0,0},{17,142,87},{12,126,76},{10,110,65},{6,93,55},{4,75,42},{1,58,26},{0,35,6},{0,0,0},{23,142,79},{17,126,69},{10,110,59},{7,93,49},{4,75,36},{1,58,21},{0,35,4},{0,0,0},{29,142,72},{21,125,62},{10,109,53},{7,93,43},{4,75,31},{1,58,16},{0,35,2},{0,0,0},
-{6,138,205},{5,122,181},{5,106,158},{3,89,135},{2,72,112},{0,54,89},{0,30,61},{0,0,21},{7,137,194},{6,122,172},{5,106,151},{4,89,129},{2,72,106},{1,54,84},{0,30,57},{0,0,17},{8,137,185},{7,122,163},{6,106,143},{4,89,122},{3,72,100},{1,54,79},{0,30,53},{0,0,13},{8,137,176},{7,121,156},{6,105,136},{5,89,116},{3,72,95},{1,54,75},{0,31,49},{0,0,9},
-{9,137,167},{7,121,148},{6,105,129},{5,89,110},{3,72,90},{1,54,70},{0,31,45},{0,0,5},{9,137,158},{8,120,140},{6,105,122},{5,89,104},{3,71,85},{1,54,66},{0,31,41},{0,0,2},{10,137,149},{8,120,132},{7,105,114},{5,89,98},{3,71,80},{1,54,61},{0,31,37},{0,0,1},{14,136,140},{9,120,123},{7,104,107},{5,88,91},{3,71,74},{1,54,56},{0,31,33},{0,0,0},
-{18,136,131},{13,120,115},{9,104,101},{6,88,85},{4,71,68},{1,54,52},{0,31,29},{0,0,0},{21,136,123},{18,120,108},{12,104,94},{6,88,78},{4,71,63},{2,54,47},{0,31,25},{0,0,0},{25,136,114},{21,120,100},{14,104,87},{7,88,72},{4,71,57},{2,54,42},{0,31,20},{0,0,0},{29,135,105},{24,119,92},{17,103,79},{8,87,66},{4,70,51},{2,53,36},{0,31,15},{0,0,0},
-{32,135,95},{26,119,83},{19,103,71},{10,87,59},{4,70,45},{2,53,30},{0,31,9},{0,0,0},{35,134,85},{29,119,74},{22,103,63},{11,87,53},{4,71,40},{2,54,24},{0,31,4},{0,0,0},{38,134,77},{31,119,67},{23,103,57},{12,87,47},{4,71,34},{2,54,19},{0,31,3},{0,0,0},{41,135,70},{34,118,61},{23,103,52},{12,87,41},{5,70,29},{2,53,14},{0,31,1},{0,0,0},
-{8,130,198},{7,114,175},{6,99,153},{5,83,130},{3,66,108},{1,49,86},{0,25,58},{0,0,18},{10,129,188},{9,114,166},{7,99,146},{6,83,124},{3,66,103},{1,49,81},{0,26,54},{0,0,14},{12,129,179},{10,114,158},{8,99,138},{6,83,117},{4,66,97},{1,49,76},{0,26,50},{0,0,10},{13,129,170},{12,113,151},{9,98,131},{6,83,112},{4,66,92},{1,49,72},{0,26,46},{0,0,6},
-{15,129,161},{13,113,143},{10,98,124},{7,83,107},{4,66,87},{1,49,67},{0,26,42},{0,0,2},{16,129,152},{14,113,135},{11,98,118},{7,83,101},{4,66,82},{2,49,63},{0,26,38},{0,0,1},{18,129,144},{14,113,127},{12,98,111},{7,83,95},{4,66,77},{2,49,58},{0,26,35},{0,0,0},{22,128,136},{16,112,120},{12,98,104},{8,82,88},{5,66,72},{2,49,54},{0,27,31},{0,0,0},
-{27,128,128},{20,112,112},{15,98,98},{9,82,82},{5,66,66},{2,49,49},{0,27,27},{0,0,0},{32,128,120},{27,112,105},{18,97,91},{10,82,75},{5,66,60},{2,49,44},{0,27,23},{0,0,0},{38,128,111},{31,112,97},{22,97,84},{12,82,69},{5,66,54},{2,49,39},{0,27,18},{0,0,0},{42,127,102},{35,111,89},{25,97,77},{13,81,63},{5,65,48},{2,48,33},{0,27,12},{0,0,0},
-{45,127,93},{37,111,81},{28,97,69},{15,81,57},{6,65,43},{2,48,28},{0,27,8},{0,0,0},{49,126,83},{41,111,72},{32,97,61},{17,82,51},{6,66,38},{2,49,22},{0,27,3},{0,0,0},{51,126,75},{42,111,65},{32,97,55},{18,82,45},{6,66,32},{2,49,17},{0,27,2},{0,0,0},{52,127,68},{44,111,59},{33,97,50},{19,81,39},{7,65,28},{2,48,12},{0,27,1},{0,0,0},
-{9,121,191},{8,107,169},{7,92,148},{5,77,126},{4,61,104},{2,44,83},{0,20,56},{0,0,15},{15,121,182},{14,106,161},{10,92,141},{7,77,120},{4,61,99},{2,44,78},{0,21,52},{0,0,11},{21,121,173},{19,106,153},{15,92,133},{9,77,113},{4,61,93},{2,44,73},{0,21,48},{0,0,6},{26,121,164},{23,106,146},{18,91,127},{10,77,108},{5,61,89},{2,44,69},{0,21,44},{0,0,3},
-{30,121,156},{25,106,138},{21,91,120},{12,77,103},{5,61,84},{2,44,64},{0,21,41},{0,0,1},{33,120,148},{27,106,131},{22,91,114},{12,77,97},{5,61,79},{2,44,60},{0,22,37},{0,0,0},{35,120,140},{28,106,123},{23,91,108},{14,77,92},{5,61,74},{2,44,55},{0,22,33},{0,0,0},{38,120,132},{31,105,116},{25,91,101},{16,77,85},{6,61,69},{3,44,51},{0,22,29},{0,0,0},
-{41,120,124},{35,105,109},{27,91,95},{18,77,79},{8,61,63},{3,44,47},{0,22,25},{0,0,0},{46,120,116},{38,105,102},{29,90,88},{19,76,74},{8,61,58},{3,44,43},{0,23,21},{0,0,0},{49,120,108},{41,105,94},{32,90,81},{21,76,68},{8,61,53},{3,44,38},{0,23,16},{0,0,0},{51,120,99},{44,104,87},{34,90,74},{22,76,61},{9,60,47},{3,44,32},{0,23,10},{0,0,0},
-{53,120,90},{46,104,79},{36,90,66},{23,76,55},{10,60,42},{3,44,27},{0,23,7},{0,0,0},{56,119,82},{48,104,70},{38,90,59},{25,76,49},{11,61,36},{4,44,21},{0,22,2},{0,0,0},{57,119,74},{49,104,64},{38,90,53},{25,76,43},{11,61,31},{4,44,16},{0,22,2},{0,0,0},{58,119,67},{50,104,58},{39,90,48},{26,76,38},{12,60,27},{4,44,11},{0,22,1},{0,0,0},
-{19,113,185},{17,99,164},{13,86,143},{10,71,122},{6,55,100},{2,38,80},{0,14,53},{0,0,12},{26,113,176},{24,99,156},{18,85,136},{13,71,116},{6,56,95},{2,39,75},{0,15,50},{0,0,8},{33,113,167},{29,99,148},{23,85,129},{15,71,109},{7,56,89},{3,39,70},{0,16,46},{0,0,3},{38,113,159},{33,99,141},{26,85,123},{17,71,104},{8,55,85},{4,39,66},{0,16,42},{0,0,1},
-{43,113,151},{36,99,134},{29,85,116},{19,71,99},{8,55,81},{4,39,62},{0,16,39},{0,0,0},{46,112,144},{38,99,127},{31,85,110},{20,71,93},{9,55,76},{4,39,58},{0,17,35},{0,0,0},{48,112,136},{40,99,119},{33,85,104},{21,71,88},{9,55,71},{4,39,53},{0,17,31},{0,0,0},{50,112,128},{43,99,112},{35,85,97},{23,71,82},{10,56,66},{4,40,49},{0,17,27},{0,0,0},
-{52,112,120},{45,99,105},{36,85,91},{25,71,77},{12,56,61},{4,40,45},{0,17,23},{0,0,0},{55,112,112},{47,98,99},{37,84,86},{26,70,72},{13,56,56},{4,40,41},{1,18,19},{0,0,0},{57,112,104},{49,98,92},{39,84,79},{28,70,66},{13,56,51},{4,40,36},{0,18,14},{0,0,0},{59,112,96},{50,98,85},{40,84,72},{29,70,59},{14,56,45},{4,40,30},{0,18,8},{0,0,0},
-{61,112,88},{51,98,77},{41,84,64},{29,70,53},{15,56,40},{4,40,25},{0,18,5},{0,0,0},{62,111,80},{52,98,68},{43,84,57},{31,70,47},{16,56,34},{5,40,19},{0,18,2},{0,0,0},{63,111,72},{53,98,62},{43,84,51},{31,70,41},{16,56,29},{5,40,14},{0,18,2},{0,0,0},{64,111,65},{55,98,56},{44,84,46},{32,70,36},{16,56,25},{5,40,9},{1,18,1},{0,0,0},
-{37,105,180},{34,92,159},{27,79,139},{19,65,118},{9,49,97},{3,33,77},{0,9,50},{0,0,9},{43,105,171},{38,92,152},{30,78,132},{21,65,112},{10,50,92},{4,34,72},{1,10,47},{0,0,5},{47,105,162},{41,92,144},{33,78,124},{23,65,105},{12,50,86},{4,34,68},{1,11,44},{0,0,1},{49,105,155},{43,92,137},{35,78,119},{25,65,101},{13,50,82},{5,34,64},{1,11,40},{0,0,0},
-{51,105,147},{45,92,130},{36,78,113},{27,65,96},{14,50,78},{5,34,60},{1,11,37},{0,0,0},{54,104,140},{47,92,123},{38,78,107},{28,65,90},{15,50,73},{5,34,56},{1,11,33},{0,0,0},{56,104,132},{48,92,115},{39,78,101},{29,65,85},{16,50,68},{5,34,51},{1,11,29},{0,0,0},{58,104,124},{49,92,108},{41,78,94},{30,64,80},{17,51,63},{5,35,47},{1,11,25},{0,0,0},
-{60,104,116},{51,92,102},{43,78,88},{31,64,74},{17,51,59},{5,35,43},{1,11,21},{0,0,0},{62,104,109},{51,91,96},{44,79,83},{32,65,69},{18,51,54},{5,35,39},{1,12,17},{0,0,0},{63,104,101},{53,91,89},{44,79,77},{32,65,63},{18,51,49},{5,35,34},{1,12,13},{0,0,0},{65,104,94},{55,91,82},{45,78,70},{33,65,57},{19,51,44},{6,35,29},{1,13,7},{0,0,0},
-{65,104,86},{56,91,75},{46,78,63},{33,65,51},{20,51,39},{6,35,24},{1,13,4},{0,0,0},{66,104,77},{57,91,67},{47,78,56},{34,65,45},{21,51,33},{6,35,18},{1,13,2},{0,0,0},{67,104,71},{58,91,61},{47,78,50},{34,65,40},{21,51,28},{6,35,13},{1,13,1},{0,0,0},{68,104,64},{59,91,55},{47,78,45},{35,65,35},{20,51,24},{7,36,8},{1,13,0},{0,0,0},
-{50,97,174},{45,84,153},{36,71,134},{27,58,114},{15,43,94},{5,27,74},{0,5,48},{0,0,6},{54,97,165},{47,84,146},{39,72,127},{30,59,108},{17,44,89},{6,28,69},{1,6,44},{0,0,3},{57,97,157},{49,84,139},{40,72,120},{31,59,102},{18,44,83},{6,28,65},{1,7,41},{0,0,0},{58,97,150},{50,84,132},{42,72,115},{32,59,98},{19,44,79},{7,28,61},{1,7,37},{0,0,0},
-{59,97,142},{51,84,125},{43,72,110},{32,59,93},{19,44,75},{7,28,57},{1,7,34},{0,0,0},{61,96,135},{52,84,119},{44,72,104},{33,59,87},{20,44,70},{8,29,53},{1,7,31},{0,0,0},{62,96,128},{54,84,112},{45,72,98},{34,59,82},{20,44,65},{8,29,49},{1,7,27},{0,0,0},{63,96,121},{55,84,105},{46,72,91},{35,58,77},{21,45,61},{8,29,45},{1,7,22},{0,0,0},
-{65,96,113},{56,84,99},{46,72,85},{35,58,72},{21,45,57},{8,29,41},{1,7,18},{0,0,0},{66,95,106},{56,84,93},{47,72,80},{36,59,66},{22,45,52},{9,30,36},{1,8,14},{0,0,0},{68,95,98},{58,84,86},{47,72,74},{36,59,61},{23,45,47},{9,30,32},{1,8,10},{0,0,0},{69,96,91},{59,84,79},{48,72,68},{37,59,55},{24,46,42},{10,30,27},{1,8,6},{0,0,0},
-{69,96,83},{60,84,72},{49,72,61},{37,59,49},{24,46,37},{10,30,22},{1,8,4},{0,0,0},{70,96,75},{61,83,65},{50,72,54},{38,59,43},{25,46,31},{9,30,16},{1,8,2},{0,0,0},{71,96,69},{61,83,59},{50,72,49},{38,59,38},{25,46,26},{9,30,11},{1,8,1},{0,0,0},{72,96,63},{62,83,53},{51,72,44},{39,59,33},{25,46,22},{10,31,6},{1,8,0},{0,0,0},
-{59,88,167},{52,76,147},{44,64,129},{35,51,110},{22,37,91},{7,20,71},{1,3,46},{0,0,4},{61,88,159},{54,76,140},{45,65,123},{36,52,105},{23,38,86},{8,21,67},{1,4,42},{0,0,1},{62,88,151},{56,76,133},{46,65,116},{36,52,99},{24,38,81},{9,22,63},{1,4,39},{0,0,0},{63,88,145},{57,76,127},{47,65,111},{38,52,94},{25,38,77},{10,22,59},{2,4,35},{0,0,0},
-{64,88,138},{57,76,121},{48,65,106},{38,52,89},{25,38,72},{10,22,55},{2,4,32},{0,0,0},{66,88,131},{58,77,115},{48,65,100},{38,52,84},{26,38,68},{11,23,51},{2,4,29},{0,0,0},{68,88,124},{58,77,109},{48,65,94},{38,52,79},{26,38,63},{11,23,47},{2,4,25},{0,0,0},{69,88,117},{59,76,102},{49,65,89},{39,52,75},{27,39,59},{12,23,43},{2,4,20},{0,0,0},
-{71,88,110},{61,76,96},{50,65,83},{39,52,70},{27,39,55},{12,23,39},{2,4,16},{0,0,0},{72,88,103},{61,77,90},{51,65,78},{40,53,64},{27,39,50},{13,24,34},{2,4,12},{0,0,0},{72,88,96},{62,77,84},{51,65,72},{40,53,59},{27,39,45},{13,24,30},{2,4,8},{0,0,0},{72,88,89},{62,77,77},{52,66,66},{41,53,53},{28,40,40},{13,25,25},{2,5,5},{0,0,0},
-{73,88,81},{63,77,70},{52,66,59},{41,53,47},{28,40,35},{13,25,20},{2,5,3},{0,0,0},{74,88,73},{64,76,63},{53,65,53},{42,53,42},{29,40,29},{13,25,14},{2,5,1},{0,0,0},{74,88,67},{64,76,57},{53,65,48},{42,53,37},{29,40,24},{13,25,9},{2,5,1},{0,0,0},{74,88,62},{65,76,52},{54,65,43},{42,53,32},{29,40,20},{13,25,4},{2,5,0},{0,0,0},
-{66,78,161},{58,67,143},{49,56,125},{40,43,106},{27,29,88},{12,12,68},{1,1,43},{0,0,2},{67,79,154},{59,68,136},{50,57,119},{41,44,101},{28,30,83},{13,13,64},{2,2,39},{0,0,1},{68,79,146},{60,68,128},{51,57,112},{41,44,95},{29,30,78},{14,14,60},{2,2,36},{0,0,0},{69,79,140},{61,68,123},{52,57,108},{42,44,91},{30,30,74},{15,15,56},{2,2,32},{0,0,0},
-{70,79,133},{62,68,117},{52,57,103},{42,44,86},{30,30,69},{15,15,52},{2,2,29},{0,0,0},{72,79,127},{62,68,111},{52,57,97},{42,44,81},{30,31,65},{14,16,48},{2,2,26},{0,0,0},{72,79,120},{62,68,105},{52,57,91},{42,44,76},{30,31,60},{14,16,44},{2,2,22},{0,0,0},{73,79,113},{63,68,99},{53,57,86},{43,45,72},{30,32,56},{15,16,40},{2,2,17},{0,0,0},
-{75,79,107},{63,68,93},{53,57,80},{43,45,67},{30,32,52},{15,16,36},{2,2,13},{0,0,0},{76,79,100},{64,69,87},{54,57,75},{43,46,61},{30,33,47},{15,17,32},{2,2,10},{0,0,0},{76,79,93},{65,69,81},{54,57,69},{43,46,56},{30,33,42},{15,17,27},{2,2,7},{0,0,0},{76,79,86},{66,69,75},{55,58,63},{44,46,50},{30,34,38},{16,18,23},{2,3,5},{0,0,0},
-{76,79,78},{66,69,68},{55,58,57},{44,46,45},{30,34,33},{16,18,18},{2,3,3},{0,0,0},{77,79,71},{67,68,61},{56,57,51},{45,46,40},{31,34,28},{16,18,12},{2,3,1},{0,0,0},{77,79,66},{67,68,56},{56,57,46},{45,46,36},{31,34,23},{16,18,8},{2,3,1},{0,0,0},{78,80,61},{68,68,51},{57,57,42},{45,47,31},{31,34,19},{16,19,4},{2,3,0},{0,0,0},
-{72,68,157},{62,58,139},{53,48,121},{44,35,102},{31,20,84},{17,4,64},{2,0,40},{0,0,0},{73,69,150},{63,59,132},{54,48,115},{45,36,97},{32,21,79},{17,5,60},{3,0,36},{0,0,0},{74,69,142},{64,59,124},{55,48,108},{45,36,91},{32,21,74},{17,5,57},{3,0,33},{0,0,0},{75,69,136},{65,59,119},{56,48,104},{46,37,87},{33,22,70},{18,6,53},{3,0,29},{0,0,0},
-{75,69,129},{65,59,113},{56,48,99},{46,37,83},{33,23,66},{18,6,49},{3,0,26},{0,0,0},{76,70,123},{65,59,107},{56,49,93},{45,37,78},{33,24,62},{18,7,45},{3,0,23},{0,0,0},{76,70,116},{66,59,101},{56,49,87},{45,37,73},{33,24,57},{18,7,42},{3,0,19},{0,0,0},{77,70,109},{66,60,95},{57,49,82},{46,38,68},{33,25,53},{19,8,38},{3,0,15},{0,0,0},
-{78,70,103},{67,60,90},{57,49,77},{46,38,63},{33,25,49},{19,9,34},{3,0,11},{0,0,0},{79,70,97},{68,61,85},{58,50,72},{46,39,58},{33,26,45},{19,10,30},{3,1,8},{0,0,0},{79,70,90},{69,61,79},{58,50,66},{46,39,53},{33,26,40},{19,10,25},{3,1,6},{0,0,0},{79,70,83},{70,60,73},{58,50,60},{46,39,48},{34,27,36},{20,10,21},{3,1,4},{0,0,0},
-{79,70,76},{70,60,66},{59,50,55},{46,39,43},{34,27,31},{20,10,16},{3,1,2},{0,0,0},{79,70,69},{70,61,60},{60,50,49},{47,40,38},{34,27,26},{20,11,10},{3,1,1},{0,0,0},{80,70,64},{70,61,54},{60,50,44},{47,40,34},{34,27,22},{20,11,7},{3,1,1},{0,0,0},{81,71,59},{71,61,49},{60,50,40},{47,40,30},{34,28,18},{20,12,4},{3,1,0},{0,0,0},
-{75,57,151},{66,48,134},{57,38,117},{46,24,99},{33,11,81},{19,2,62},{2,0,38},{0,0,0},{76,58,144},{67,49,127},{58,38,111},{47,25,94},{34,12,77},{19,2,58},{3,0,35},{0,0,0},{77,58,136},{68,49,120},{59,38,104},{47,25,89},{35,12,72},{19,2,55},{3,0,32},{0,0,0},{78,59,131},{68,49,114},{59,38,100},{47,27,85},{35,13,68},{20,3,51},{3,0,28},{0,0,0},
-{78,59,125},{68,49,109},{59,39,96},{47,27,81},{35,14,64},{20,3,48},{3,0,24},{0,0,0},{79,60,119},{69,50,104},{59,40,90},{47,28,75},{34,15,60},{19,3,44},{3,0,21},{0,0,0},{79,60,113},{69,50,99},{59,40,85},{47,28,71},{34,15,55},{19,3,40},{3,0,17},{0,0,0},{80,60,106},{69,51,93},{59,40,80},{47,29,66},{35,16,51},{20,4,36},{3,0,13},{0,0,0},
-{80,60,100},{69,51,88},{59,40,75},{47,29,62},{35,16,47},{20,4,32},{3,0,10},{0,0,0},{81,61,94},{70,52,82},{60,41,70},{47,30,57},{35,17,44},{20,5,29},{3,1,7},{0,0,0},{81,61,88},{71,52,77},{60,41,65},{47,30,52},{35,17,39},{20,5,24},{3,1,5},{0,0,0},{81,61,81},{71,52,71},{60,42,59},{48,31,47},{35,18,35},{21,5,19},{3,1,3},{0,0,0},
-{81,61,74},{71,52,64},{61,42,54},{48,31,42},{35,18,30},{21,5,14},{3,1,2},{0,0,0},{81,61,68},{72,52,58},{61,42,48},{48,32,37},{35,18,25},{20,6,9},{3,1,1},{0,0,0},{82,61,62},{72,52,53},{61,42,43},{48,32,33},{35,19,21},{20,6,6},{3,1,1},{0,0,0},{82,62,57},{73,52,48},{62,42,39},{48,32,29},{36,20,16},{20,7,4},{3,1,0},{0,0,0},
-{78,46,146},{70,37,129},{60,26,113},{48,12,96},{36,2,78},{20,0,60},{2,0,36},{0,0,0},{80,47,139},{71,38,123},{61,27,107},{49,13,91},{37,2,74},{20,0,56},{2,0,33},{0,0,0},{81,47,131},{72,38,116},{62,27,100},{50,14,86},{37,2,70},{20,0,53},{3,0,30},{0,0,0},{82,48,126},{72,39,110},{62,28,96},{50,16,82},{37,3,66},{21,0,49},{3,0,26},{0,0,0},
-{82,48,121},{72,39,105},{62,29,92},{50,17,78},{37,4,62},{21,0,46},{3,0,22},{0,0,0},{82,49,115},{72,40,101},{62,30,87},{49,18,72},{36,5,58},{20,0,42},{3,0,19},{0,0,0},{82,50,109},{72,41,96},{62,30,82},{49,18,68},{36,5,53},{20,0,38},{3,0,15},{0,0,0},{83,50,102},{72,41,91},{61,31,77},{49,19,64},{37,6,49},{21,0,34},{3,0,11},{0,0,0},
-{83,50,96},{72,41,85},{61,31,73},{49,20,60},{37,7,45},{21,0,30},{3,0,8},{0,0,0},{84,51,91},{73,42,79},{62,32,68},{50,21,55},{37,8,42},{21,1,27},{3,0,6},{0,0,0},{84,51,85},{73,42,74},{62,32,63},{50,21,50},{37,8,38},{21,1,23},{3,0,4},{0,0,0},{84,51,79},{73,43,68},{63,33,57},{50,22,45},{37,9,33},{22,1,17},{3,0,2},{0,0,0},
-{84,51,72},{73,43,62},{63,33,52},{50,22,40},{37,9,28},{22,1,12},{3,0,1},{0,0,0},{84,52,66},{74,42,56},{63,33,46},{50,23,36},{37,9,24},{21,1,8},{3,0,0},{0,0,0},{84,52,60},{74,42,51},{63,33,41},{50,23,31},{37,10,19},{21,1,5},{3,0,0},{0,0,0},{84,52,55},{75,43,46},{63,34,37},{50,24,27},{38,11,14},{21,2,3},{3,0,0},{0,0,0},
-{0,174,239},{0,154,211},{0,134,185},{0,114,158},{0,95,132},{0,74,105},{0,49,74},{0,3,35},{0,173,227},{0,153,200},{0,134,175},{0,114,150},{0,94,125},{0,74,99},{0,49,70},{0,4,31},{0,172,216},{0,153,190},{0,134,166},{0,114,142},{0,94,117},{0,74,93},{0,49,65},{0,4,28},{0,171,205},{0,152,180},{0,133,158},{0,113,135},{0,93,112},{0,73,89},{0,49,61},{0,4,24},
-{0,171,194},{0,151,171},{0,133,150},{0,113,128},{0,93,106},{0,73,84},{0,49,57},{0,4,21},{0,170,184},{0,150,162},{0,132,141},{0,112,121},{0,93,100},{0,73,78},{0,48,53},{0,3,17},{0,170,173},{0,150,153},{0,131,133},{0,112,113},{0,93,94},{0,73,73},{0,48,48},{0,3,12},{0,169,162},{0,150,144},{0,131,125},{0,112,106},{0,93,88},{0,73,68},{0,49,44},{0,3,7},
-{0,168,152},{0,149,134},{0,131,117},{0,112,100},{0,93,82},{0,73,63},{0,49,40},{0,3,4},{0,167,142},{0,148,125},{0,130,110},{0,111,93},{0,92,76},{0,73,59},{0,49,36},{0,3,1},{0,167,131},{0,148,116},{0,130,101},{0,111,86},{0,92,70},{0,73,53},{0,49,31},{0,3,0},{0,167,121},{0,148,106},{0,130,92},{0,111,78},{0,91,63},{0,72,47},{0,48,25},{0,3,0},
-{0,167,110},{0,148,96},{0,130,84},{0,111,70},{0,91,56},{0,72,41},{0,48,20},{0,3,0},{0,166,98},{0,147,87},{0,129,75},{0,110,63},{0,92,50},{0,72,35},{0,48,14},{0,3,0},{0,166,89},{0,147,79},{0,129,68},{0,110,57},{0,92,44},{0,72,30},{0,48,9},{0,3,0},{0,165,79},{0,147,72},{0,128,62},{0,110,52},{0,92,39},{0,73,25},{0,49,4},{0,3,0},
-{0,165,232},{0,146,204},{0,127,179},{0,108,153},{0,90,127},{0,69,101},{0,45,71},{0,1,32},{0,164,220},{0,145,194},{0,127,170},{0,108,146},{0,89,121},{0,70,96},{0,45,67},{0,2,28},{0,163,209},{0,145,185},{0,127,161},{0,108,138},{0,89,114},{0,70,90},{0,45,62},{0,2,25},{0,163,199},{0,145,175},{0,126,154},{0,107,131},{0,88,108},{0,69,86},{0,45,58},{0,2,21},
-{0,163,188},{0,144,166},{0,126,146},{0,107,124},{0,88,103},{0,69,81},{0,45,54},{0,2,18},{0,162,178},{0,143,157},{0,126,137},{0,107,117},{0,88,97},{0,69,75},{0,44,50},{0,1,14},{0,162,168},{0,143,148},{0,125,129},{0,107,110},{0,88,91},{0,69,70},{0,44,46},{0,1,9},{0,161,157},{0,143,140},{0,125,122},{0,106,103},{0,88,85},{0,69,65},{0,45,42},{0,1,4},
-{0,160,147},{0,142,131},{0,125,114},{0,106,97},{0,88,79},{0,69,61},{0,45,38},{0,1,2},{0,160,138},{0,141,122},{0,124,107},{0,105,90},{0,87,73},{0,69,56},{0,45,34},{0,1,0},{0,160,128},{0,141,113},{0,124,98},{0,105,83},{0,87,67},{0,69,50},{0,45,29},{0,1,0},{0,160,118},{0,141,103},{0,124,90},{0,106,76},{0,87,60},{0,68,44},{0,44,23},{0,1,0},
-{0,160,107},{0,141,94},{0,124,82},{0,106,68},{0,87,54},{0,68,39},{0,44,18},{0,1,0},{0,159,96},{0,140,84},{0,123,73},{0,105,61},{0,87,48},{0,68,33},{0,44,12},{0,1,0},{0,159,87},{0,140,77},{0,123,66},{0,105,55},{0,87,42},{0,68,28},{0,44,7},{0,1,0},{0,158,78},{0,140,70},{0,122,60},{0,105,50},{0,87,38},{0,68,23},{0,45,3},{0,1,0},
-{0,157,224},{0,138,197},{0,120,173},{0,102,148},{0,84,123},{0,64,98},{0,40,69},{0,0,30},{0,156,212},{0,137,188},{0,119,164},{0,102,141},{0,84,117},{0,65,93},{0,41,64},{0,0,26},{0,155,201},{0,137,179},{0,119,156},{0,102,133},{0,84,111},{0,65,88},{0,41,60},{0,0,23},{0,155,192},{0,137,170},{0,119,149},{0,101,126},{0,83,105},{0,65,84},{0,41,56},{0,0,19},
-{0,155,182},{0,137,161},{0,119,141},{0,101,120},{0,83,100},{0,65,79},{0,41,52},{0,0,15},{0,154,172},{0,136,152},{0,119,133},{0,101,114},{0,82,94},{0,65,73},{0,41,48},{0,0,11},{0,154,162},{0,135,144},{0,119,126},{0,101,107},{0,82,88},{0,65,68},{0,41,44},{0,0,7},{0,153,152},{0,135,135},{0,118,119},{0,100,100},{0,82,82},{0,64,63},{0,41,40},{0,0,2},
-{0,152,143},{0,135,127},{0,118,111},{0,100,94},{0,82,76},{0,64,59},{0,41,36},{0,0,0},{0,152,134},{0,134,119},{0,117,104},{0,99,87},{0,81,70},{0,64,54},{0,41,32},{0,0,0},{0,152,125},{0,134,110},{0,117,96},{0,99,80},{0,81,64},{0,64,48},{0,41,27},{0,0,0},{0,152,115},{0,133,101},{0,117,88},{0,100,74},{0,82,58},{0,64,42},{0,41,21},{0,0,0},
-{0,152,104},{0,133,92},{0,117,80},{0,100,66},{0,82,52},{0,64,37},{0,41,16},{0,0,0},{0,151,94},{0,133,82},{0,116,72},{0,99,59},{0,81,46},{0,64,31},{0,41,10},{0,0,0},{0,151,86},{0,133,75},{0,116,65},{0,99,53},{0,81,41},{0,64,26},{0,41,6},{0,0,0},{0,150,78},{0,133,68},{0,116,58},{0,99,48},{0,81,37},{0,64,21},{0,41,2},{0,0,0},
-{0,149,218},{0,131,192},{0,115,169},{0,97,144},{0,79,119},{0,60,94},{0,36,66},{0,0,27},{0,148,206},{0,130,183},{0,114,160},{0,97,137},{0,79,113},{0,61,89},{0,37,62},{0,0,23},{0,148,196},{0,130,174},{0,114,151},{0,97,129},{0,79,107},{0,61,84},{0,37,58},{0,0,19},{0,147,187},{0,130,166},{0,113,144},{0,96,122},{0,79,101},{0,61,80},{0,37,54},{0,0,15},
-{0,147,178},{0,130,157},{0,113,137},{0,96,116},{0,79,96},{0,61,76},{0,37,50},{0,0,11},{0,147,168},{0,129,148},{0,113,129},{0,96,110},{0,78,90},{0,61,71},{0,37,46},{0,0,7},{0,147,158},{0,129,140},{0,113,122},{0,96,104},{0,78,85},{0,61,66},{0,37,42},{0,0,4},{0,146,148},{0,129,131},{0,112,115},{0,96,97},{0,78,80},{0,60,61},{0,37,38},{0,0,1},
-{0,145,139},{0,129,123},{0,112,107},{0,96,91},{0,78,74},{0,60,57},{0,37,34},{0,0,0},{0,145,130},{0,128,115},{0,112,100},{0,95,84},{0,77,68},{0,60,52},{0,37,30},{0,0,0},{0,145,121},{0,128,107},{0,112,93},{0,95,78},{0,77,62},{0,60,46},{0,37,25},{0,0,0},{0,145,111},{0,127,99},{0,111,85},{0,95,72},{0,78,56},{0,60,41},{0,37,20},{0,0,0},
-{0,145,101},{0,127,90},{0,111,77},{0,95,64},{0,78,50},{0,60,36},{0,37,15},{0,0,0},{0,144,91},{0,127,80},{0,111,70},{0,94,57},{0,77,44},{0,60,30},{0,37,9},{0,0,0},{0,144,84},{0,127,73},{0,111,63},{0,94,51},{0,77,39},{0,60,25},{0,37,5},{0,0,0},{0,144,77},{0,127,66},{0,111,57},{0,94,47},{0,77,35},{0,60,20},{0,37,2},{0,0,0},
-{0,141,211},{0,124,187},{0,109,164},{0,92,139},{0,74,115},{0,56,91},{0,32,63},{0,0,24},{0,140,200},{0,123,178},{0,108,155},{0,92,132},{0,74,110},{0,56,86},{0,33,59},{0,0,20},{0,140,190},{0,123,169},{0,108,146},{0,92,124},{0,74,104},{0,56,81},{0,33,55},{0,0,16},{0,139,182},{0,123,161},{0,107,139},{0,91,118},{0,74,98},{0,57,77},{0,33,51},{0,0,12},
-{0,139,173},{0,123,153},{0,107,132},{0,91,113},{0,74,93},{0,57,73},{0,33,47},{0,0,7},{0,139,164},{0,122,144},{0,107,125},{0,91,107},{0,74,87},{0,57,68},{0,34,43},{0,0,4},{0,139,154},{0,122,136},{0,107,118},{0,91,101},{0,74,82},{0,57,63},{0,34,39},{0,0,2},{0,138,144},{0,122,127},{0,106,111},{0,91,94},{0,73,77},{0,56,58},{0,33,35},{0,0,1},
-{0,138,135},{0,122,119},{0,106,104},{0,91,88},{0,73,71},{0,56,54},{0,33,31},{0,0,0},{0,138,126},{0,121,112},{0,106,97},{0,90,81},{0,73,65},{0,56,49},{0,33,27},{0,0,0},{0,138,117},{0,121,104},{0,106,90},{0,90,75},{0,73,60},{0,56,44},{0,33,22},{0,0,0},{0,137,107},{0,121,96},{0,105,82},{0,90,69},{0,73,54},{0,56,39},{0,33,18},{0,0,0},
-{0,137,98},{0,121,87},{0,105,74},{0,90,62},{0,73,49},{0,56,34},{0,33,13},{0,0,0},{0,136,89},{0,120,78},{0,105,67},{0,89,55},{0,73,43},{0,56,28},{0,33,7},{0,0,0},{0,136,82},{0,120,71},{0,105,61},{0,89,50},{0,73,38},{0,56,23},{0,33,5},{0,0,0},{0,137,75},{0,120,64},{0,105,56},{0,89,45},{0,73,33},{0,56,19},{0,33,2},{0,0,0},
-{0,134,204},{0,117,181},{0,102,158},{0,86,134},{0,69,111},{0,52,89},{0,28,61},{0,0,21},{0,133,194},{0,116,172},{0,102,150},{0,86,128},{0,69,106},{0,52,84},{0,29,57},{0,0,17},{0,132,184},{0,116,163},{0,102,142},{0,86,120},{0,69,100},{0,52,79},{0,29,53},{0,0,13},{0,132,176},{0,116,155},{0,101,135},{0,85,114},{0,69,95},{0,52,75},{0,29,49},{0,0,9},
-{0,132,167},{0,116,147},{0,101,128},{0,85,109},{0,69,90},{0,52,70},{0,29,45},{0,0,5},{0,132,158},{0,115,140},{0,101,121},{0,85,103},{0,69,85},{0,52,66},{0,29,41},{0,0,2},{0,132,150},{0,115,132},{0,101,114},{0,85,98},{0,69,80},{0,52,61},{0,29,37},{0,0,1},{0,131,140},{0,115,123},{0,100,107},{0,85,91},{0,68,75},{0,52,56},{0,29,33},{0,0,0},
-{0,130,132},{0,115,115},{0,100,101},{0,85,85},{0,68,69},{0,52,52},{0,29,29},{0,0,0},{0,130,123},{0,114,108},{0,100,94},{0,84,79},{0,68,63},{0,52,47},{0,29,25},{0,0,0},{0,130,114},{0,114,101},{0,100,88},{0,84,73},{0,68,58},{0,52,42},{0,29,20},{0,0,0},{0,130,105},{0,114,93},{0,99,80},{0,84,67},{0,68,52},{0,51,37},{0,29,16},{0,0,0},
-{0,130,96},{0,114,85},{0,99,72},{0,84,60},{0,68,47},{0,51,32},{0,29,11},{0,0,0},{0,129,87},{0,113,76},{0,99,65},{0,84,53},{0,68,41},{0,51,26},{0,29,5},{0,0,0},{0,129,80},{0,113,69},{0,99,59},{0,84,48},{0,68,36},{0,51,21},{0,29,4},{0,0,0},{0,130,73},{0,113,62},{0,99,54},{0,84,43},{0,68,31},{0,52,17},{0,29,2},{0,0,0},
-{0,126,198},{0,109,175},{0,96,152},{0,80,129},{0,64,108},{0,47,86},{0,23,58},{0,0,18},{0,125,188},{0,109,166},{0,96,145},{0,80,123},{0,64,103},{0,47,81},{0,24,54},{0,0,14},{0,124,178},{0,109,158},{0,96,137},{0,80,117},{0,64,97},{0,47,76},{0,24,50},{0,0,10},{0,124,170},{0,109,150},{0,95,131},{0,80,111},{0,64,92},{0,47,72},{0,24,46},{0,0,6},
-{0,124,162},{0,109,142},{0,95,125},{0,80,106},{0,64,87},{0,47,67},{0,24,43},{0,0,2},{0,124,153},{0,109,135},{0,95,118},{0,80,100},{0,64,82},{0,47,63},{0,24,39},{0,0,1},{0,124,145},{0,109,127},{0,95,111},{0,80,95},{0,64,77},{0,47,58},{0,24,35},{0,0,0},{0,123,137},{0,108,119},{0,94,104},{0,79,88},{0,63,72},{0,47,54},{0,24,31},{0,0,0},
-{0,122,129},{0,108,112},{0,94,98},{0,79,82},{0,63,66},{0,47,49},{0,24,27},{0,0,0},{0,122,120},{0,108,105},{0,94,91},{0,79,76},{0,63,61},{0,47,44},{0,24,23},{0,0,0},{0,122,111},{0,108,98},{0,94,85},{0,79,70},{0,63,56},{0,47,40},{0,24,18},{0,0,0},{0,122,102},{0,107,90},{0,93,78},{0,79,64},{0,63,50},{0,46,34},{0,24,13},{0,0,0},
-{0,122,94},{0,107,82},{0,93,70},{0,79,58},{0,63,45},{0,46,29},{0,24,8},{0,0,0},{0,121,85},{0,107,74},{0,93,63},{0,79,51},{0,63,39},{0,46,24},{0,24,4},{0,0,0},{0,121,78},{0,107,67},{0,93,57},{0,79,46},{0,63,34},{0,46,19},{0,24,3},{0,0,0},{0,122,71},{0,107,61},{0,93,52},{0,79,41},{0,63,29},{0,47,15},{0,24,2},{0,0,0},
-{0,118,191},{0,102,168},{0,89,147},{0,75,125},{0,59,105},{0,42,83},{0,18,56},{0,0,15},{0,117,181},{0,102,161},{0,89,140},{0,75,119},{0,59,99},{0,42,78},{0,18,52},{0,0,11},{0,117,172},{0,102,153},{0,89,133},{0,75,113},{0,59,93},{0,42,73},{0,18,48},{0,0,6},{0,117,165},{0,102,145},{0,89,127},{0,75,108},{0,59,89},{0,42,69},{0,18,44},{0,0,3},
-{0,117,157},{0,102,137},{0,89,121},{0,75,103},{0,59,84},{0,42,65},{0,18,41},{0,0,1},{0,116,148},{0,102,130},{0,89,115},{0,75,97},{0,59,79},{0,42,60},{0,18,37},{0,0,0},{0,116,140},{0,102,123},{0,89,108},{0,75,92},{0,59,74},{0,42,55},{0,18,33},{0,0,0},{0,116,133},{0,102,116},{0,88,101},{0,74,86},{0,58,69},{0,42,51},{0,19,30},{0,0,0},
-{0,115,125},{0,102,109},{0,88,95},{0,74,80},{0,58,64},{0,42,47},{0,19,26},{0,0,0},{0,115,116},{0,101,102},{0,88,88},{0,74,74},{0,58,60},{0,42,43},{0,19,22},{0,0,0},{0,115,108},{0,101,95},{0,88,82},{0,74,68},{0,58,54},{0,42,39},{0,19,17},{0,0,0},{0,115,99},{0,101,87},{0,88,76},{0,74,62},{0,58,48},{0,42,33},{0,18,11},{0,0,0},
-{0,115,91},{0,101,79},{0,88,68},{0,74,56},{0,58,43},{0,42,28},{0,18,7},{0,0,0},{0,114,83},{0,101,72},{0,88,61},{0,74,50},{0,58,38},{0,42,23},{0,19,3},{0,0,0},{0,114,76},{0,101,66},{0,88,55},{0,74,45},{0,58,32},{0,42,17},{0,19,2},{0,0,0},{0,115,70},{0,101,60},{0,87,50},{0,73,40},{0,58,27},{0,42,12},{0,19,1},{0,0,0},
-{0,110,185},{0,96,163},{0,83,142},{0,69,121},{0,53,101},{0,36,80},{0,13,54},{0,0,12},{0,109,175},{0,96,156},{0,83,136},{0,69,115},{0,53,95},{0,37,75},{0,13,50},{0,0,8},{0,109,166},{0,96,148},{0,83,129},{0,69,109},{0,53,90},{0,37,71},{0,13,46},{0,0,3},{0,109,159},{0,96,141},{0,83,123},{0,69,104},{0,54,86},{0,38,67},{0,13,42},{0,0,1},
-{0,109,152},{0,96,133},{0,83,117},{0,69,99},{0,54,81},{0,38,63},{0,13,39},{0,0,0},{0,109,144},{0,96,126},{0,83,111},{0,69,93},{0,54,76},{0,38,58},{0,13,35},{0,0,0},{0,109,136},{0,96,119},{0,83,104},{0,69,88},{0,54,71},{0,38,53},{0,13,31},{0,0,0},{0,109,129},{0,96,112},{0,82,97},{0,68,83},{0,54,66},{0,38,49},{0,14,28},{0,0,0},
-{0,109,121},{0,96,106},{0,82,91},{0,68,77},{0,54,62},{0,38,45},{0,14,24},{0,0,0},{0,108,112},{0,95,99},{0,82,86},{0,68,72},{0,54,58},{0,38,41},{0,14,20},{0,0,0},{0,108,105},{0,95,92},{0,82,80},{0,68,66},{0,54,52},{0,38,37},{0,14,15},{0,0,0},{0,108,97},{0,95,85},{0,82,74},{0,68,60},{0,54,46},{0,38,31},{0,13,9},{0,0,0},
-{0,108,89},{0,95,77},{0,82,66},{0,68,54},{0,54,41},{0,38,26},{0,13,6},{0,0,0},{0,108,81},{0,95,70},{0,82,59},{0,68,48},{0,54,36},{0,38,21},{0,14,2},{0,0,0},{0,108,74},{1,95,64},{0,82,53},{0,68,43},{0,54,30},{0,38,15},{0,14,2},{0,0,0},{0,108,68},{2,95,58},{0,81,48},{0,68,38},{0,54,25},{0,38,10},{0,14,1},{0,0,0},
-{0,102,179},{0,89,158},{0,76,138},{0,63,117},{0,47,97},{0,31,77},{0,9,51},{0,0,9},{0,102,170},{0,89,151},{0,76,132},{0,63,112},{0,48,92},{0,32,72},{0,9,47},{0,0,5},{0,102,161},{0,89,143},{0,76,125},{0,63,106},{0,48,87},{0,32,68},{0,9,44},{0,0,1},{0,102,154},{0,89,137},{0,77,119},{0,63,101},{0,49,83},{0,33,64},{0,9,40},{0,0,0},
-{0,102,147},{0,89,129},{0,77,113},{0,63,96},{0,49,78},{0,33,60},{0,9,37},{0,0,0},{0,102,140},{0,89,122},{0,76,107},{0,63,90},{0,49,74},{0,33,56},{0,10,33},{0,0,0},{0,102,132},{0,89,116},{0,76,101},{0,63,85},{0,49,69},{0,33,52},{0,10,30},{0,0,0},{0,102,125},{0,89,109},{0,77,94},{0,63,80},{0,49,64},{0,33,47},{0,10,26},{0,0,0},
-{0,102,117},{0,89,103},{0,77,88},{0,63,74},{0,49,59},{0,33,43},{0,10,22},{0,0,0},{0,101,109},{0,88,96},{0,76,83},{0,63,69},{0,49,55},{0,34,39},{0,10,18},{0,0,0},{0,101,102},{0,88,90},{0,76,77},{0,63,64},{0,49,50},{0,34,35},{0,10,13},{0,0,0},{0,101,96},{0,88,83},{0,76,71},{0,63,58},{0,49,44},{0,34,30},{0,10,8},{0,0,0},
-{0,101,88},{0,88,76},{0,76,65},{0,63,53},{0,49,39},{0,34,25},{0,10,5},{0,0,0},{0,101,79},{0,88,69},{0,76,58},{0,62,47},{0,49,34},{0,34,20},{0,10,2},{0,0,0},{0,101,72},{2,88,62},{0,76,52},{0,62,42},{0,49,29},{0,34,14},{0,10,1},{0,0,0},{1,101,66},{5,88,56},{0,76,47},{0,63,37},{0,49,24},{0,34,9},{0,10,0},{0,0,0},
-{0,94,173},{0,82,153},{0,70,134},{0,57,114},{0,41,94},{0,25,74},{0,6,48},{0,0,6},{0,94,165},{0,82,146},{0,70,127},{0,57,109},{0,42,89},{0,26,69},{0,6,45},{0,0,3},{0,94,156},{0,82,138},{0,70,120},{0,57,103},{0,42,84},{0,26,66},{0,6,42},{0,0,0},{0,94,149},{0,82,132},{0,70,115},{0,57,98},{0,43,80},{0,27,62},{0,6,38},{0,0,0},
-{1,94,142},{0,82,125},{0,70,110},{0,57,93},{0,43,75},{0,27,58},{0,6,34},{0,0,0},{3,94,135},{2,82,119},{0,70,104},{0,57,87},{0,43,71},{0,27,54},{0,7,31},{0,0,0},{5,94,128},{4,82,113},{1,70,98},{0,57,82},{0,43,66},{0,27,49},{0,7,28},{0,0,0},{5,94,121},{4,82,106},{1,71,91},{0,57,77},{0,43,62},{0,28,45},{0,7,24},{0,0,0},
-{6,94,114},{4,82,100},{2,71,86},{0,57,72},{0,43,57},{0,28,41},{0,7,19},{0,0,0},{7,93,106},{5,82,93},{3,70,80},{0,57,67},{0,44,53},{0,29,37},{0,7,15},{0,0,0},{8,93,99},{6,82,87},{4,70,74},{1,57,62},{0,44,48},{0,29,33},{0,7,11},{0,0,0},{9,93,93},{7,82,80},{4,70,68},{1,57,56},{0,44,42},{0,29,28},{0,7,7},{0,0,0},
-{9,93,85},{8,82,73},{5,70,62},{2,57,51},{0,44,37},{0,29,23},{0,7,4},{0,0,0},{10,93,77},{9,82,67},{6,70,56},{2,57,45},{0,44,32},{0,29,17},{0,7,2},{0,0,0},{10,93,70},{11,82,60},{6,70,51},{2,57,40},{0,44,27},{0,29,12},{0,7,1},{0,0,0},{11,93,64},{13,82,54},{6,70,46},{3,57,35},{0,44,23},{0,29,7},{0,7,0},{0,0,0},
-{0,86,167},{0,75,148},{0,63,130},{0,50,111},{0,35,91},{0,18,71},{0,2,46},{0,0,4},{0,86,159},{0,75,141},{0,63,123},{0,50,105},{0,36,86},{0,20,67},{0,3,43},{0,0,1},{0,86,151},{0,75,133},{0,63,116},{0,50,99},{0,36,81},{0,20,64},{0,3,40},{0,0,0},{0,86,144},{0,75,127},{1,63,111},{0,51,94},{0,37,77},{0,21,60},{0,4,36},{0,0,0},
-{2,86,137},{1,75,121},{1,63,106},{0,51,89},{0,37,73},{0,21,56},{0,4,32},{0,0,0},{8,86,131},{6,75,115},{1,64,100},{0,51,84},{0,37,69},{0,21,52},{0,4,29},{0,0,0},{12,86,124},{10,75,109},{2,64,94},{0,51,79},{0,37,64},{0,21,47},{0,4,26},{0,0,0},{13,86,117},{10,75,103},{3,64,89},{0,51,75},{0,37,60},{0,22,43},{0,4,22},{0,0,0},
-{16,86,111},{11,75,97},{5,64,84},{0,51,70},{0,37,55},{0,22,39},{0,4,17},{0,0,0},{19,86,104},{14,75,90},{8,64,78},{1,51,65},{0,38,51},{0,23,35},{0,4,12},{0,0,0},{22,86,97},{16,75,84},{10,64,72},{2,51,60},{0,38,46},{0,23,31},{0,4,9},{0,0,0},{23,86,90},{19,75,78},{11,64,66},{3,51,54},{0,38,41},{0,24,26},{0,5,6},{0,0,0},
-{24,86,83},{22,75,71},{14,64,60},{4,51,49},{0,38,36},{0,24,21},{0,5,3},{0,0,0},{26,86,75},{23,75,65},{16,64,54},{6,51,43},{0,38,30},{0,23,15},{0,4,1},{0,0,0},{27,86,69},{24,75,58},{16,64,49},{6,51,38},{0,38,25},{0,23,10},{0,4,1},{0,0,0},{28,86,63},{24,75,53},{16,64,44},{7,51,34},{0,38,21},{0,23,5},{0,4,0},{0,0,0},
-{12,77,162},{8,67,143},{7,55,126},{3,42,107},{0,27,88},{0,11,68},{0,1,43},{0,0,2},{13,77,154},{10,67,136},{8,55,119},{4,43,102},{1,28,83},{0,12,64},{0,1,40},{0,0,1},{14,77,146},{12,67,128},{8,55,113},{5,43,96},{1,29,78},{0,13,61},{0,1,37},{0,0,0},{14,78,140},{12,67,123},{10,55,108},{5,43,91},{2,30,74},{0,13,57},{0,2,33},{0,0,0},
-{15,78,133},{13,67,117},{10,55,103},{6,43,86},{2,30,70},{0,14,53},{0,2,29},{0,0,0},{20,78,127},{17,67,111},{11,56,97},{6,44,81},{2,31,66},{0,15,49},{0,2,26},{0,0,0},{24,78,121},{20,67,106},{11,56,91},{6,44,76},{2,31,61},{0,15,44},{0,2,23},{0,0,0},{25,78,114},{21,67,100},{12,56,86},{6,45,72},{2,31,57},{0,16,40},{0,2,19},{0,0,0},
-{27,78,108},{22,67,94},{14,56,81},{6,45,68},{2,31,53},{0,16,36},{0,2,14},{0,0,0},{30,78,101},{24,67,87},{16,56,75},{7,45,63},{2,32,48},{0,17,32},{0,2,10},{0,0,0},{32,78,94},{26,67,81},{17,56,69},{8,45,57},{2,32,43},{0,17,28},{0,2,7},{0,0,0},{33,78,87},{28,67,75},{19,56,63},{10,45,51},{2,32,39},{0,17,24},{0,3,5},{0,0,0},
-{34,78,80},{30,67,69},{21,56,57},{10,45,46},{2,32,34},{0,17,19},{0,3,3},{0,0,0},{36,78,73},{31,67,62},{23,56,52},{12,45,41},{2,33,29},{0,17,13},{0,2,1},{0,0,0},{37,78,67},{32,67,57},{23,56,47},{12,45,37},{2,33,24},{0,17,9},{0,2,1},{0,0,0},{38,78,61},{32,67,52},{24,56,43},{12,45,33},{2,33,20},{0,17,5},{0,2,0},{0,0,0},
-{28,68,156},{19,58,138},{17,47,122},{7,35,103},{0,20,84},{0,5,65},{0,0,40},{0,0,0},{31,68,149},{23,58,131},{19,48,115},{9,36,98},{2,21,80},{0,5,61},{0,0,36},{0,0,0},{33,68,142},{27,58,124},{20,48,109},{11,36,92},{3,22,75},{0,5,57},{0,0,33},{0,0,0},{33,69,136},{28,59,119},{22,48,104},{12,36,88},{4,23,71},{0,6,53},{0,0,29},{0,0,0},
-{33,69,129},{28,59,113},{22,48,99},{13,36,83},{4,23,67},{0,7,50},{0,0,26},{0,0,0},{34,70,123},{29,59,107},{23,49,93},{14,37,78},{4,24,62},{0,8,46},{0,0,23},{0,0,0},{36,70,117},{32,59,102},{23,49,88},{15,37,73},{4,24,58},{0,8,42},{0,0,19},{0,0,0},{37,70,110},{33,59,96},{24,49,83},{14,38,69},{4,25,54},{0,9,38},{0,1,15},{0,0,0},
-{39,70,104},{34,59,90},{24,49,78},{14,38,65},{4,25,50},{0,9,34},{0,1,11},{0,0,0},{41,70,97},{34,59,85},{25,49,73},{14,38,60},{4,26,46},{0,10,30},{0,1,8},{0,0,0},{41,70,91},{35,59,79},{26,49,67},{15,38,55},{4,26,41},{0,10,26},{0,1,6},{0,0,0},{42,70,85},{36,60,73},{28,49,61},{17,38,49},{5,26,37},{0,10,22},{0,1,4},{0,0,0},
-{43,70,78},{36,60,67},{28,49,55},{17,38,44},{5,26,32},{0,10,17},{0,1,2},{0,0,0},{44,70,71},{37,60,60},{29,49,50},{18,39,40},{5,27,27},{0,11,11},{0,1,1},{0,0,0},{45,70,65},{38,60,55},{29,49,45},{18,39,35},{5,27,23},{0,11,8},{0,1,1},{0,0,0},{46,70,59},{39,60,50},{30,49,41},{18,39,31},{6,28,19},{0,11,5},{0,1,0},{0,0,0},
-{37,58,151},{30,49,133},{25,38,118},{14,25,100},{5,12,82},{0,2,63},{0,0,38},{0,0,0},{40,58,144},{33,49,127},{27,39,112},{17,26,95},{6,12,78},{1,2,59},{0,0,35},{0,0,0},{41,58,137},{36,49,120},{27,39,106},{18,26,89},{7,13,73},{1,2,56},{0,0,32},{0,0,0},{41,59,131},{36,50,115},{29,39,101},{19,27,85},{8,14,69},{1,3,52},{0,0,28},{0,0,0},
-{41,60,125},{36,50,110},{29,39,96},{20,27,80},{8,14,65},{1,3,48},{0,0,25},{0,0,0},{42,61,119},{37,50,104},{30,40,90},{20,28,76},{8,15,60},{1,4,44},{0,0,21},{0,0,0},{44,61,113},{38,50,99},{30,40,85},{20,29,71},{8,15,56},{1,4,40},{0,0,17},{0,0,0},{45,61,107},{38,51,93},{30,41,81},{20,30,67},{9,16,52},{1,4,36},{0,1,13},{0,0,0},
-{46,61,101},{39,51,88},{30,41,76},{20,30,63},{9,16,48},{1,4,32},{0,1,10},{0,0,0},{47,61,95},{40,51,83},{31,41,71},{20,30,58},{9,17,44},{1,5,29},{0,1,7},{0,0,0},{47,61,89},{41,51,77},{31,41,66},{21,30,53},{9,17,40},{1,5,25},{0,1,5},{0,0,0},{47,62,83},{41,52,71},{33,41,60},{23,30,48},{10,18,36},{1,5,20},{0,1,3},{0,0,0},
-{48,62,76},{41,52,65},{33,41,54},{23,30,43},{10,18,31},{1,5,15},{0,1,2},{0,0,0},{49,62,69},{42,52,59},{34,41,48},{23,31,38},{9,19,26},{1,6,10},{0,1,1},{0,0,0},{49,62,64},{42,52,54},{34,41,44},{23,31,34},{10,19,21},{1,6,7},{0,1,1},{0,0,0},{50,62,58},{43,52,49},{35,41,40},{23,31,30},{11,20,17},{2,6,4},{0,1,0},{0,0,0},
-{46,48,146},{41,39,129},{33,29,114},{23,15,97},{10,3,79},{1,0,60},{0,0,36},{0,0,0},{47,48,139},{42,39,123},{34,29,108},{24,16,92},{11,3,75},{2,0,57},{0,0,33},{0,0,0},{48,48,132},{43,39,116},{34,29,102},{25,16,86},{12,3,70},{2,0,54},{0,0,30},{0,0,0},{48,49,127},{43,40,111},{35,30,97},{26,17,82},{13,4,66},{2,0,50},{0,0,26},{0,0,0},
-{48,50,121},{43,40,106},{35,30,92},{26,18,77},{13,5,62},{2,0,46},{0,0,23},{0,0,0},{49,51,115},{44,41,100},{35,31,87},{25,19,73},{13,5,58},{2,0,42},{0,0,19},{0,0,0},{50,51,109},{44,41,95},{35,31,82},{25,20,69},{13,5,54},{2,0,38},{0,0,15},{0,0,0},{51,52,103},{43,42,90},{35,32,78},{25,21,65},{14,6,50},{3,0,34},{0,0,11},{0,0,0},
-{52,52,97},{44,42,85},{35,32,74},{25,21,61},{14,7,46},{3,0,30},{0,0,8},{0,0,0},{52,52,92},{45,43,80},{36,33,69},{26,22,56},{14,8,42},{3,1,27},{0,0,6},{0,0,0},{52,52,86},{46,43,74},{36,33,64},{27,22,51},{14,8,38},{3,1,23},{0,0,4},{0,0,0},{52,53,80},{45,43,68},{37,34,58},{28,23,46},{15,9,34},{3,1,18},{0,0,2},{0,0,0},
-{52,53,73},{45,43,63},{37,34,52},{28,23,41},{15,9,29},{3,1,13},{0,0,1},{0,0,0},{53,53,67},{46,43,57},{38,33,46},{28,23,36},{14,10,24},{3,1,8},{0,0,0},{0,0,0},{53,53,62},{46,43,52},{38,33,42},{28,23,32},{15,10,19},{3,1,5},{0,0,0},{0,0,0},{54,53,57},{47,44,48},{39,34,38},{28,24,28},{16,11,15},{4,2,3},{0,0,0},{0,0,0}};
-// START
-
-#define PC (16*16*8)
-#define PM ( 16*8)
-#define PY ( 8)
-#define PK ( 1)
-#define RC (7)
-#define RM (15)
-#define RY (15)
-#define RK (7)
-
-static inline double clip01(double x) {
- return (x < 0) ? 0 : ((x > 1) ? 1 : x);
-}
-
-void old_getRGB(GfxColor *color, GfxRGB *rgb)
-{
- double c, m, y, aw, ac, am, ay, ar, ag, ab;
-
- c = clip01(color->c[0] + color->c[3]);
- m = clip01(color->c[1] + color->c[3]);
- y = clip01(color->c[2] + color->c[3]);
- aw = (1-c) * (1-m) * (1-y);
- ac = c * (1-m) * (1-y);
- am = (1-c) * m * (1-y);
- ay = (1-c) * (1-m) * y;
- ar = (1-c) * m * y;
- ag = c * (1-m) * y;
- ab = c * m * (1-y);
- rgb->r = clip01(aw + 0.9137*am + 0.9961*ay + 0.9882*ar);
- rgb->g = clip01(aw + 0.6196*ac + ay + 0.5176*ag);
- rgb->b = clip01(aw + 0.7804*ac + 0.5412*am + 0.0667*ar + 0.2118*ag + 0.4863*ab);
-}
-
-int check(float c, float m, float y, float k, float r, float g, float b)
-{
- GfxRGB rgb2;
- memset(&rgb2,0,sizeof(GfxRGB));
- GfxColor col;
- col.c[0] = c;
- col.c[1] = m;
- col.c[2] = y;
- col.c[3] = k;
- old_getRGB(&col, &rgb2);
-
- double dr = r - rgb2.r;
- double dg = g - rgb2.g;
- double db = b - rgb2.b;
- if(sqrt(dr*dr+dg*dg+db*db) > 0.5) {
- printf("%f %f %f %f -> %02x%02x%02x / %02x%02x%02x\n",
- c,m,y,k,
- (int)(r*255),(int)(g*255),(int)(b*255),
- (int)(rgb2.r*255), (int)(rgb2.g*255), (int)(rgb2.b*255));
- return 0;
- }
- return 1;
-}
-void convert_cmyk2rgb(float c,float m,float y,float k, unsigned char*r, unsigned char*g, unsigned char*b)
-{
- c = c<0?0:(c>1?1:c<=1?c:0.5);
- m = m<0?0:(m>1?1:m<=1?m:0.5);
- y = y<0?0:(y>1?1:y<=1?y:0.5);
- k = k<0?0:(k>1?1:k<=1?k:0.5);
-
- int cc = (int)(c*7.0);
- int mm = (int)(m*15.0);
- int yy = (int)(y*15.0);
- int kk = (int)(k*7.0);
-
- float rc = c*7.0 - cc;
- float rm = m*15.0 - mm;
- float ry = y*15.0 - yy;
- float rk = k*7.0 - kk;
-
- int pp = cc*PC + mm*PM + yy*PY + kk*PK;
- int pc = cc>=RC?pp:pp + PC;
- int pm = mm>=RM?pp:pp + PM;
- int py = yy>=RY?pp:pp + PY;
- int pk = kk>=RK?pp:pp + PK;
-
- int rr = (int)((int)cmyk2rgb[pp].r
- + ((int)cmyk2rgb[pc].r - (int)cmyk2rgb[pp].r)*rc
- + ((int)cmyk2rgb[pm].r - (int)cmyk2rgb[pp].r)*rm
- + ((int)cmyk2rgb[py].r - (int)cmyk2rgb[pp].r)*ry
- + ((int)cmyk2rgb[pk].r - (int)cmyk2rgb[pp].r)*rk);
- int gg = (int)((int)cmyk2rgb[pp].g
- + ((int)cmyk2rgb[pc].g - (int)cmyk2rgb[pp].g)*rc
- + ((int)cmyk2rgb[pm].g - (int)cmyk2rgb[pp].g)*rm
- + ((int)cmyk2rgb[py].g - (int)cmyk2rgb[pp].g)*ry
- + ((int)cmyk2rgb[pk].g - (int)cmyk2rgb[pp].g)*rk);
- int bb = (int)((int)cmyk2rgb[pp].b
- + ((int)cmyk2rgb[pc].b - (int)cmyk2rgb[pp].b)*rc
- + ((int)cmyk2rgb[pm].b - (int)cmyk2rgb[pp].b)*rm
- + ((int)cmyk2rgb[py].b - (int)cmyk2rgb[pp].b)*ry
- + ((int)cmyk2rgb[pk].b - (int)cmyk2rgb[pp].b)*rk);
- *r = rr<0?0:(rr>255?255:rr);
- *g = gg<0?0:(gg>255?255:gg);
- *b = bb<0?0:(bb>255?255:bb);
-
- int t;
- float r2=0,g2=0,b2=0;
- for(t=0;t<16;t++) {
- int p2 = pp;
- if(t&1) p2+=(pc-pp);
- if(t&2) p2+=(pm-pp);
- if(t&4) p2+=(py-pp);
- if(t&8) p2+=(pk-pp);
- float rrc = t&1?rc:1-rc;
- float rrm = t&2?rm:1-rm;
- float rry = t&4?ry:1-ry;
- float rrk = t&8?rk:1-rk;
- float f = rrc*rrm*rry*rrk;
- r2 += cmyk2rgb[p2].r*f;
- g2 += cmyk2rgb[p2].g*f;
- b2 += cmyk2rgb[p2].b*f;
- }
-
- if(r2<0)r2=0; if(r2>255)r2=255;
- if(g2<0)g2=0; if(g2>255)g2=255;
- if(b2<0)b2=0; if(b2>255)b2=255;
-
- *r = (unsigned char)r2;
- *g = (unsigned char)g2;
- *b = (unsigned char)b2;
-
- /*f(!check(c,m,y,k, *r/255.0, *g/255.0, *b/255.0)) {
- for(t=0;t<16;t++) {
- int p2 = pp;
- if(t&1) p2+=(pc-pp);
- if(t&2) p2+=(pm-pp);
- if(t&4) p2+=(py-pp);
- if(t&8) p2+=(pk-pp);
- float rrc = t&1?rc:1-rc;
- float rrm = t&2?rm:1-rm;
- float rry = t&4?ry:1-ry;
- float rrk = t&8?rk:1-rk;
- float f = rrc*rrm*rry*rrk;
- //printf("%d%d%d%d %f %02x%02x%02x\n", !!(t&8),!!(t&4),!!(t&2),!!(t&1), f, cmyk2rgb[p2].r, cmyk2rgb[p2].g, cmyk2rgb[p2].b);
- }
- }*/
-}
-
-// END
+++ /dev/null
-#ifndef __cmyk_h__
-#define __cmyk_h__
-void convert_cmyk2rgb(float c,float m,float y,float k, unsigned char*r, unsigned char*g, unsigned char*b);
-#endif
+++ /dev/null
-//========================================================================
-//
-// config.h
-//
-// Copyright 1996-2005 Glyph & Cog, LLC
-//
-//========================================================================
-
-#ifndef CONFIG_H
-#define CONFIG_H
-
-//------------------------------------------------------------------------
-// version
-//------------------------------------------------------------------------
-
-// xpdf version
-#define xpdfVersion "3.01"
-#define xpdfVersionNum 3.01
-#define xpdfMajorVersion 3
-#define xpdfMinorVersion 1
-#define xpdfUpdateVersion 0
-#define xpdfMajorVersionStr "3"
-#define xpdfMinorVersionStr "1"
-#define xpdfUpdateVersionStr "0"
-
-// supported PDF version
-#define supportedPDFVersionStr "1.5"
-#define supportedPDFVersionNum 1.5
-
-// copyright notice
-#define xpdfCopyright "Copyright 1996-2005 Glyph & Cog, LLC"
-
-// Windows resource file stuff
-#define winxpdfVersion "WinXpdf 3.01"
-#define xpdfCopyrightAmp "Copyright 1996-2005 Glyph && Cog, LLC"
-
-//------------------------------------------------------------------------
-// paper size
-//------------------------------------------------------------------------
-
-// default paper size (in points) for PostScript output
-#ifdef A4_PAPER
-#define defPaperWidth 595 // ISO A4 (210x297 mm)
-#define defPaperHeight 842
-#else
-#define defPaperWidth 612 // American letter (8.5x11")
-#define defPaperHeight 792
-#endif
-
-//------------------------------------------------------------------------
-// config file (xpdfrc) path
-//------------------------------------------------------------------------
-
-// user config file name, relative to the user's home directory
-#if defined(VMS) || (defined(WIN32) && !defined(__CYGWIN32__))
-#define xpdfUserConfigFile "xpdfrc"
-#else
-#define xpdfUserConfigFile ".xpdfrc"
-#endif
-
-// system config file name (set via the configure script)
-#ifdef SYSTEM_XPDFRC
-#define xpdfSysConfigFile SYSTEM_XPDFRC
-#else
-// under Windows, we get the directory with the executable and then
-// append this file name
-#define xpdfSysConfigFile "xpdfrc"
-#endif
-
-//------------------------------------------------------------------------
-// X-related constants
-//------------------------------------------------------------------------
-
-// default maximum size of color cube to allocate
-#define defaultRGBCube 5
-
-// number of fonts (combined t1lib, FreeType, X server) to cache
-#define xOutFontCacheSize 64
-
-// number of Type 3 fonts to cache
-#define xOutT3FontCacheSize 8
-
-//------------------------------------------------------------------------
-// popen
-//------------------------------------------------------------------------
-
-#if defined(_MSC_VER) || defined(__BORLANDC__)
-#define popen _popen
-#define pclose _pclose
-#endif
-
-#if defined(VMS) || defined(VMCMS) || defined(DOS) || defined(OS2) || defined(__EMX__) || defined(WIN32) || defined(__DJGPP__) || defined(MACOS)
-#define POPEN_READ_MODE "rb"
-#else
-#define POPEN_READ_MODE "r"
-#endif
-
-//------------------------------------------------------------------------
-// Win32 stuff
-//------------------------------------------------------------------------
-
-#ifdef CDECL
-#undef CDECL
-#endif
-
-#if defined(_MSC_VER) || defined(__BORLANDC__)
-#define CDECL __cdecl
-#else
-#define CDECL
-#endif
-
-#endif
+++ /dev/null
-//========================================================================
-//
-// gfile.cc
-//
-// Miscellaneous file and directory name manipulation.
-//
-// Copyright 1996-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#include <aconf.h>
-
-#ifndef WIN32
-# if defined(MACOS)
-# include <sys/stat.h>
-# elif !defined(ACORN)
-# include <sys/types.h>
-# include <sys/stat.h>
-# include <fcntl.h>
-# endif
-# include <limits.h>
-# include <string.h>
-# if !defined(VMS) && !defined(ACORN) && !defined(MACOS)
-# include <pwd.h>
-# endif
-# if defined(VMS) && (__DECCXX_VER < 50200000)
-# include <unixlib.h>
-# endif
-#endif // WIN32
-#include "GString.h"
-#include "gfile.h"
-
-// Some systems don't define this, so just make it something reasonably
-// large.
-#ifndef PATH_MAX
-#define PATH_MAX 1024
-#endif
-
-//------------------------------------------------------------------------
-
-GString *getHomeDir() {
-#ifdef VMS
- //---------- VMS ----------
- return new GString("SYS$LOGIN:");
-
-#elif defined(__EMX__) || defined(WIN32)
- //---------- OS/2+EMX and Win32 ----------
- char *s;
- GString *ret;
-
- if ((s = getenv("HOME")))
- ret = new GString(s);
- else
- ret = new GString(".");
- return ret;
-
-#elif defined(ACORN)
- //---------- RISCOS ----------
- return new GString("@");
-
-#elif defined(MACOS)
- //---------- MacOS ----------
- return new GString(":");
-
-#else
- //---------- Unix ----------
- char *s;
- struct passwd *pw;
- GString *ret;
-
- if ((s = getenv("HOME"))) {
- ret = new GString(s);
- } else {
- if ((s = getenv("USER")))
- pw = getpwnam(s);
- else
- pw = getpwuid(getuid());
- if (pw)
- ret = new GString(pw->pw_dir);
- else
- ret = new GString(".");
- }
- return ret;
-#endif
-}
-
-GString *getCurrentDir() {
- char buf[PATH_MAX+1];
-
-#if defined(__EMX__)
- if (_getcwd2(buf, sizeof(buf)))
-#elif defined(WIN32)
- if (GetCurrentDirectory(sizeof(buf), buf))
-#elif defined(ACORN)
- if (strcpy(buf, "@"))
-#elif defined(MACOS)
- if (strcpy(buf, ":"))
-#else
- if (getcwd(buf, sizeof(buf)))
-#endif
- return new GString(buf);
- return new GString();
-}
-
-GString *appendToPath(GString *path, char *fileName) {
-#if defined(VMS)
- //---------- VMS ----------
- //~ this should handle everything necessary for file
- //~ requesters, but it's certainly not complete
- char *p0, *p1, *p2;
- char *q1;
-
- p0 = path->getCString();
- p1 = p0 + path->getLength() - 1;
- if (!strcmp(fileName, "-")) {
- if (*p1 == ']') {
- for (p2 = p1; p2 > p0 && *p2 != '.' && *p2 != '['; --p2) ;
- if (*p2 == '[')
- ++p2;
- path->del(p2 - p0, p1 - p2);
- } else if (*p1 == ':') {
- path->append("[-]");
- } else {
- path->clear();
- path->append("[-]");
- }
- } else if ((q1 = strrchr(fileName, '.')) && !strncmp(q1, ".DIR;", 5)) {
- if (*p1 == ']') {
- path->insert(p1 - p0, '.');
- path->insert(p1 - p0 + 1, fileName, q1 - fileName);
- } else if (*p1 == ':') {
- path->append('[');
- path->append(']');
- path->append(fileName, q1 - fileName);
- } else {
- path->clear();
- path->append(fileName, q1 - fileName);
- }
- } else {
- if (*p1 != ']' && *p1 != ':')
- path->clear();
- path->append(fileName);
- }
- return path;
-
-#elif defined(WIN32)
- //---------- Win32 ----------
- GString *tmp;
- char buf[256];
- char *fp;
-
- tmp = new GString(path);
- tmp->append('/');
- tmp->append(fileName);
- GetFullPathName(tmp->getCString(), sizeof(buf), buf, &fp);
- delete tmp;
- path->clear();
- path->append(buf);
- return path;
-
-#elif defined(ACORN)
- //---------- RISCOS ----------
- char *p;
- int i;
-
- path->append(".");
- i = path->getLength();
- path->append(fileName);
- for (p = path->getCString() + i; *p; ++p) {
- if (*p == '/') {
- *p = '.';
- } else if (*p == '.') {
- *p = '/';
- }
- }
- return path;
-
-#elif defined(MACOS)
- //---------- MacOS ----------
- char *p;
- int i;
-
- path->append(":");
- i = path->getLength();
- path->append(fileName);
- for (p = path->getCString() + i; *p; ++p) {
- if (*p == '/') {
- *p = ':';
- } else if (*p == '.') {
- *p = ':';
- }
- }
- return path;
-
-#elif defined(__EMX__)
- //---------- OS/2+EMX ----------
- int i;
-
- // appending "." does nothing
- if (!strcmp(fileName, "."))
- return path;
-
- // appending ".." goes up one directory
- if (!strcmp(fileName, "..")) {
- for (i = path->getLength() - 2; i >= 0; --i) {
- if (path->getChar(i) == '/' || path->getChar(i) == '\\' ||
- path->getChar(i) == ':')
- break;
- }
- if (i <= 0) {
- if (path->getChar(0) == '/' || path->getChar(0) == '\\') {
- path->del(1, path->getLength() - 1);
- } else if (path->getLength() >= 2 && path->getChar(1) == ':') {
- path->del(2, path->getLength() - 2);
- } else {
- path->clear();
- path->append("..");
- }
- } else {
- if (path->getChar(i-1) == ':')
- ++i;
- path->del(i, path->getLength() - i);
- }
- return path;
- }
-
- // otherwise, append "/" and new path component
- if (path->getLength() > 0 &&
- path->getChar(path->getLength() - 1) != '/' &&
- path->getChar(path->getLength() - 1) != '\\')
- path->append('/');
- path->append(fileName);
- return path;
-
-#else
- //---------- Unix ----------
- int i;
-
- // appending "." does nothing
- if (!strcmp(fileName, "."))
- return path;
-
- // appending ".." goes up one directory
- if (!strcmp(fileName, "..")) {
- for (i = path->getLength() - 2; i >= 0; --i) {
- if (path->getChar(i) == '/')
- break;
- }
- if (i <= 0) {
- if (path->getChar(0) == '/') {
- path->del(1, path->getLength() - 1);
- } else {
- path->clear();
- path->append("..");
- }
- } else {
- path->del(i, path->getLength() - i);
- }
- return path;
- }
-
- // otherwise, append "/" and new path component
- if (path->getLength() > 0 &&
- path->getChar(path->getLength() - 1) != '/')
- path->append('/');
- path->append(fileName);
- return path;
-#endif
-}
-
-GString *grabPath(char *fileName) {
-#ifdef VMS
- //---------- VMS ----------
- char *p;
-
- if ((p = strrchr(fileName, ']')))
- return new GString(fileName, p + 1 - fileName);
- if ((p = strrchr(fileName, ':')))
- return new GString(fileName, p + 1 - fileName);
- return new GString();
-
-#elif defined(__EMX__) || defined(WIN32)
- //---------- OS/2+EMX and Win32 ----------
- char *p;
-
- if ((p = strrchr(fileName, '/')))
- return new GString(fileName, p - fileName);
- if ((p = strrchr(fileName, '\\')))
- return new GString(fileName, p - fileName);
- if ((p = strrchr(fileName, ':')))
- return new GString(fileName, p + 1 - fileName);
- return new GString();
-
-#elif defined(ACORN)
- //---------- RISCOS ----------
- char *p;
-
- if ((p = strrchr(fileName, '.')))
- return new GString(fileName, p - fileName);
- return new GString();
-
-#elif defined(MACOS)
- //---------- MacOS ----------
- char *p;
-
- if ((p = strrchr(fileName, ':')))
- return new GString(fileName, p - fileName);
- return new GString();
-
-#else
- //---------- Unix ----------
- char *p;
-
- if ((p = strrchr(fileName, '/')))
- return new GString(fileName, p - fileName);
- return new GString();
-#endif
-}
-
-GBool isAbsolutePath(char *path) {
-#ifdef VMS
- //---------- VMS ----------
- return strchr(path, ':') ||
- (path[0] == '[' && path[1] != '.' && path[1] != '-');
-
-#elif defined(__EMX__) || defined(WIN32)
- //---------- OS/2+EMX and Win32 ----------
- return path[0] == '/' || path[0] == '\\' || path[1] == ':';
-
-#elif defined(ACORN)
- //---------- RISCOS ----------
- return path[0] == '$';
-
-#elif defined(MACOS)
- //---------- MacOS ----------
- return path[0] != ':';
-
-#else
- //---------- Unix ----------
- return path[0] == '/';
-#endif
-}
-
-GString *makePathAbsolute(GString *path) {
-#ifdef VMS
- //---------- VMS ----------
- char buf[PATH_MAX+1];
-
- if (!isAbsolutePath(path->getCString())) {
- if (getcwd(buf, sizeof(buf))) {
- path->insert(0, buf);
- }
- }
- return path;
-
-#elif defined(WIN32)
- //---------- Win32 ----------
- char buf[_MAX_PATH];
- char *fp;
-
- buf[0] = '\0';
- if (!GetFullPathName(path->getCString(), _MAX_PATH, buf, &fp)) {
- path->clear();
- return path;
- }
- path->clear();
- path->append(buf);
- return path;
-
-#elif defined(ACORN)
- //---------- RISCOS ----------
- path->insert(0, '@');
- return path;
-
-#elif defined(MACOS)
- //---------- MacOS ----------
- path->del(0, 1);
- return path;
-
-#else
- //---------- Unix and OS/2+EMX ----------
- struct passwd *pw;
- char buf[PATH_MAX+1];
- GString *s;
- char *p1, *p2;
- int n;
-
- if (path->getChar(0) == '~') {
- if (path->getChar(1) == '/' ||
-#ifdef __EMX__
- path->getChar(1) == '\\' ||
-#endif
- path->getLength() == 1) {
- path->del(0, 1);
- s = getHomeDir();
- path->insert(0, s);
- delete s;
- } else {
- p1 = path->getCString() + 1;
-#ifdef __EMX__
- for (p2 = p1; *p2 && *p2 != '/' && *p2 != '\\'; ++p2) ;
-#else
- for (p2 = p1; *p2 && *p2 != '/'; ++p2) ;
-#endif
- if ((n = p2 - p1) > PATH_MAX)
- n = PATH_MAX;
- strncpy(buf, p1, n);
- buf[n] = '\0';
- if ((pw = getpwnam(buf))) {
- path->del(0, p2 - p1 + 1);
- path->insert(0, pw->pw_dir);
- }
- }
- } else if (!isAbsolutePath(path->getCString())) {
- if (getcwd(buf, sizeof(buf))) {
-#ifndef __EMX__
- path->insert(0, '/');
-#endif
- path->insert(0, buf);
- }
- }
- return path;
-#endif
-}
-
-time_t getModTime(char *fileName) {
-#ifdef WIN32
- //~ should implement this, but it's (currently) only used in xpdf
- return 0;
-#else
- struct stat statBuf;
-
- if (stat(fileName, &statBuf)) {
- return 0;
- }
- return statBuf.st_mtime;
-#endif
-}
-
-GBool openTempFile(GString **name, FILE **f, char *mode, char *ext) {
-#if defined(WIN32)
- //---------- Win32 ----------
- char *s;
-
- if (!(s = _tempnam(getenv("TEMP"), NULL))) {
- return gFalse;
- }
- *name = new GString(s);
- free(s);
- if (ext) {
- (*name)->append(ext);
- }
- if (!(*f = fopen((*name)->getCString(), mode))) {
- delete (*name);
- return gFalse;
- }
- return gTrue;
-#elif defined(VMS) || defined(__EMX__) || defined(ACORN) || defined(MACOS)
- //---------- non-Unix ----------
- char *s;
-
- // There is a security hole here: an attacker can create a symlink
- // with this file name after the tmpnam call and before the fopen
- // call. I will happily accept fixes to this function for non-Unix
- // OSs.
- if (!(s = tmpnam(NULL))) {
- return gFalse;
- }
- *name = new GString(s);
- if (ext) {
- (*name)->append(ext);
- }
- if (!(*f = fopen((*name)->getCString(), mode))) {
- delete (*name);
- return gFalse;
- }
- return gTrue;
-#else
- //---------- Unix ----------
- char *s;
- int fd;
-
- if (ext) {
-#if HAVE_MKSTEMPS
- if ((s = getenv("TMPDIR"))) {
- *name = new GString(s);
- } else {
- *name = new GString("/tmp");
- }
- (*name)->append("/XXXXXX")->append(ext);
- fd = mkstemps((*name)->getCString(), strlen(ext));
-#else
- if (!(s = tmpnam(NULL))) {
- return gFalse;
- }
- *name = new GString(s);
- (*name)->append(ext);
- fd = open((*name)->getCString(), O_WRONLY | O_CREAT | O_EXCL, 0600);
-#endif
- } else {
-#if HAVE_MKSTEMP
- if ((s = getenv("TMPDIR"))) {
- *name = new GString(s);
- } else {
- *name = new GString("/tmp");
- }
- (*name)->append("/XXXXXX");
- fd = mkstemp((*name)->getCString());
-#else // HAVE_MKSTEMP
- if (!(s = tmpnam(NULL))) {
- return gFalse;
- }
- *name = new GString(s);
- fd = open((*name)->getCString(), O_WRONLY | O_CREAT | O_EXCL, 0600);
-#endif // HAVE_MKSTEMP
- }
- if (fd < 0 || !(*f = fdopen(fd, mode))) {
- delete *name;
- return gFalse;
- }
- return gTrue;
-#endif
-}
-
-GBool executeCommand(char *cmd) {
-#ifdef VMS
- return system(cmd) ? gTrue : gFalse;
-#else
- return system(cmd) ? gFalse : gTrue;
-#endif
-}
-
-char *getLine(char *buf, int size, FILE *f) {
- int c, i;
-
- i = 0;
- while (i < size - 1) {
- if ((c = fgetc(f)) == EOF) {
- break;
- }
- buf[i++] = (char)c;
- if (c == '\x0a') {
- break;
- }
- if (c == '\x0d') {
- c = fgetc(f);
- if (c == '\x0a' && i < size - 1) {
- buf[i++] = (char)c;
- } else if (c != EOF) {
- ungetc(c, f);
- }
- break;
- }
- }
- buf[i] = '\0';
- if (i == 0) {
- return NULL;
- }
- return buf;
-}
-
-//------------------------------------------------------------------------
-// GDir and GDirEntry
-//------------------------------------------------------------------------
-
-GDirEntry::GDirEntry(char *dirPath, char *nameA, GBool doStat) {
-#ifdef VMS
- char *p;
-#elif defined(WIN32)
- int fa;
- GString *s;
-#elif defined(ACORN)
-#else
- struct stat st;
- GString *s;
-#endif
-
- name = new GString(nameA);
- dir = gFalse;
- if (doStat) {
-#ifdef VMS
- if (!strcmp(nameA, "-") ||
- ((p = strrchr(nameA, '.')) && !strncmp(p, ".DIR;", 5)))
- dir = gTrue;
-#elif defined(ACORN)
-#else
- s = new GString(dirPath);
- appendToPath(s, nameA);
-#ifdef WIN32
- fa = GetFileAttributes(s->getCString());
- dir = (fa != 0xFFFFFFFF && (fa & FILE_ATTRIBUTE_DIRECTORY));
-#else
- if (stat(s->getCString(), &st) == 0)
- dir = S_ISDIR(st.st_mode);
-#endif
- delete s;
-#endif
- }
-}
-
-GDirEntry::~GDirEntry() {
- delete name;
-}
-
-GDir::GDir(char *name, GBool doStatA) {
- path = new GString(name);
- doStat = doStatA;
-#if defined(WIN32)
- GString *tmp;
-
- tmp = path->copy();
- tmp->append("/*.*");
- hnd = FindFirstFile(tmp->getCString(), &ffd);
- delete tmp;
-#elif defined(ACORN)
-#elif defined(MACOS)
-#else
- dir = opendir(name);
-#ifdef VMS
- needParent = strchr(name, '[') != NULL;
-#endif
-#endif
-}
-
-GDir::~GDir() {
- delete path;
-#if defined(WIN32)
- if (hnd) {
- FindClose(hnd);
- hnd = NULL;
- }
-#elif defined(ACORN)
-#elif defined(MACOS)
-#else
- if (dir)
- closedir(dir);
-#endif
-}
-
-GDirEntry *GDir::getNextEntry() {
- GDirEntry *e;
-
-#if defined(WIN32)
- if (hnd) {
- e = new GDirEntry(path->getCString(), ffd.cFileName, doStat);
- if (hnd && !FindNextFile(hnd, &ffd)) {
- FindClose(hnd);
- hnd = NULL;
- }
- } else {
- e = NULL;
- }
-#elif defined(ACORN)
-#elif defined(MACOS)
-#elif defined(VMS)
- struct dirent *ent;
- e = NULL;
- if (dir) {
- if (needParent) {
- e = new GDirEntry(path->getCString(), "-", doStat);
- needParent = gFalse;
- return e;
- }
- ent = readdir(dir);
- if (ent) {
- e = new GDirEntry(path->getCString(), ent->d_name, doStat);
- }
- }
-#else
- struct dirent *ent;
- e = NULL;
- if (dir) {
- ent = readdir(dir);
- if (ent && !strcmp(ent->d_name, ".")) {
- ent = readdir(dir);
- }
- if (ent) {
- e = new GDirEntry(path->getCString(), ent->d_name, doStat);
- }
- }
-#endif
-
- return e;
-}
-
-void GDir::rewind() {
-#ifdef WIN32
- GString *tmp;
-
- if (hnd)
- FindClose(hnd);
- tmp = path->copy();
- tmp->append("/*.*");
- hnd = FindFirstFile(tmp->getCString(), &ffd);
- delete tmp;
-#elif defined(ACORN)
-#elif defined(MACOS)
-#else
- if (dir)
- rewinddir(dir);
-#ifdef VMS
- needParent = strchr(path->getCString(), '[') != NULL;
-#endif
-#endif
-}
+++ /dev/null
-//========================================================================
-//
-// gfile.h
-//
-// Miscellaneous file and directory name manipulation.
-//
-// Copyright 1996-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#ifndef GFILE_H
-#define GFILE_H
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stddef.h>
-#if defined(WIN32)
-# include <sys/stat.h>
-# ifdef FPTEX
-# include <win32lib.h>
-# else
-# include <windows.h>
-# endif
-#elif defined(ACORN)
-#elif defined(MACOS)
-# include <ctime.h>
-#else
-# include <unistd.h>
-# include <sys/types.h>
-# ifdef VMS
-# include "vms_dirent.h"
-# elif HAVE_DIRENT_H
-# include <dirent.h>
-# define NAMLEN(d) strlen((d)->d_name)
-# else
-# define dirent direct
-# define NAMLEN(d) (d)->d_namlen
-# if HAVE_SYS_NDIR_H
-# include <sys/ndir.h>
-# endif
-# if HAVE_SYS_DIR_H
-# include <sys/dir.h>
-# endif
-# if HAVE_NDIR_H
-# include <ndir.h>
-# endif
-# endif
-#endif
-#include "gtypes.h"
-
-class GString;
-
-//------------------------------------------------------------------------
-
-// Get home directory path.
-extern GString *getHomeDir();
-
-// Get current directory.
-extern GString *getCurrentDir();
-
-// Append a file name to a path string. <path> may be an empty
-// string, denoting the current directory). Returns <path>.
-extern GString *appendToPath(GString *path, char *fileName);
-
-// Grab the path from the front of the file name. If there is no
-// directory component in <fileName>, returns an empty string.
-extern GString *grabPath(char *fileName);
-
-// Is this an absolute path or file name?
-extern GBool isAbsolutePath(char *path);
-
-// Make this path absolute by prepending current directory (if path is
-// relative) or prepending user's directory (if path starts with '~').
-extern GString *makePathAbsolute(GString *path);
-
-// Get the modification time for <fileName>. Returns 0 if there is an
-// error.
-extern time_t getModTime(char *fileName);
-
-// Create a temporary file and open it for writing. If <ext> is not
-// NULL, it will be used as the file name extension. Returns both the
-// name and the file pointer. For security reasons, all writing
-// should be done to the returned file pointer; the file may be
-// reopened later for reading, but not for writing. The <mode> string
-// should be "w" or "wb". Returns true on success.
-extern GBool openTempFile(GString **name, FILE **f, char *mode, char *ext);
-
-// Execute <command>. Returns true on success.
-extern GBool executeCommand(char *cmd);
-
-// Just like fgets, but handles Unix, Mac, and/or DOS end-of-line
-// conventions.
-extern char *getLine(char *buf, int size, FILE *f);
-
-//------------------------------------------------------------------------
-// GDir and GDirEntry
-//------------------------------------------------------------------------
-
-class GDirEntry {
-public:
-
- GDirEntry(char *dirPath, char *nameA, GBool doStat);
- ~GDirEntry();
- GString *getName() { return name; }
- GBool isDir() { return dir; }
-
-private:
-
- GString *name; // dir/file name
- GBool dir; // is it a directory?
-};
-
-class GDir {
-public:
-
- GDir(char *name, GBool doStatA = gTrue);
- ~GDir();
- GDirEntry *getNextEntry();
- void rewind();
-
-private:
-
- GString *path; // directory path
- GBool doStat; // call stat() for each entry?
-#if defined(WIN32)
- WIN32_FIND_DATA ffd;
- HANDLE hnd;
-#elif defined(ACORN)
-#elif defined(MACOS)
-#else
- DIR *dir; // the DIR structure from opendir()
-#ifdef VMS
- GBool needParent; // need to return an entry for [-]
-#endif
-#endif
-};
-
-#endif
+++ /dev/null
-/*
- * gmem.c
- *
- * Memory routines with out-of-memory checking.
- *
- * Copyright 1996-2003 Glyph & Cog, LLC
- */
-
-#include <aconf.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <stddef.h>
-#include <string.h>
-#include "gmem.h"
-
-#ifdef DEBUG_MEM
-
-typedef struct _GMemHdr {
- int size;
- int index;
- struct _GMemHdr *next;
-} GMemHdr;
-
-#define gMemHdrSize ((sizeof(GMemHdr) + 7) & ~7)
-#define gMemTrlSize (sizeof(long))
-
-#if gmemTrlSize==8
-#define gMemDeadVal 0xdeadbeefdeadbeefUL
-#else
-#define gMemDeadVal 0xdeadbeefUL
-#endif
-
-/* round data size so trailer will be aligned */
-#define gMemDataSize(size) \
- ((((size) + gMemTrlSize - 1) / gMemTrlSize) * gMemTrlSize)
-
-#define gMemNLists 64
-#define gMemListShift 4
-#define gMemListMask (gMemNLists - 1)
-static GMemHdr *gMemList[gMemNLists] = {
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
-};
-
-static int gMemIndex = 0;
-static int gMemAlloc = 0;
-static int gMemInUse = 0;
-
-#endif /* DEBUG_MEM */
-
-void *gmalloc(int size) {
-#ifdef DEBUG_MEM
- int size1;
- char *mem;
- GMemHdr *hdr;
- void *data;
- int lst;
- unsigned long *trl, *p;
-
- if (size == 0)
- return NULL;
- size1 = gMemDataSize(size);
- if (!(mem = (char *)malloc(size1 + gMemHdrSize + gMemTrlSize))) {
- fprintf(stderr, "Out of memory\n");
- exit(1);
- }
- hdr = (GMemHdr *)mem;
- data = (void *)(mem + gMemHdrSize);
- trl = (unsigned long *)(mem + gMemHdrSize + size1);
- hdr->size = size;
- hdr->index = gMemIndex++;
- lst = ((int)hdr >> gMemListShift) & gMemListMask;
- hdr->next = gMemList[lst];
- gMemList[lst] = hdr;
- ++gMemAlloc;
- gMemInUse += size;
- for (p = (unsigned long *)data; p <= trl; ++p)
- *p = gMemDeadVal;
- return data;
-#else
- void *p;
-
- if (size == 0)
- return NULL;
- if (!(p = malloc(size))) {
- fprintf(stderr, "Out of memory\n");
- exit(1);
- }
- return p;
-#endif
-}
-
-void *grealloc(void *p, int size) {
-#ifdef DEBUG_MEM
- GMemHdr *hdr;
- void *q;
- int oldSize;
-
- if (size == 0) {
- if (p)
- gfree(p);
- return NULL;
- }
- if (p) {
- hdr = (GMemHdr *)((char *)p - gMemHdrSize);
- oldSize = hdr->size;
- q = gmalloc(size);
- memcpy(q, p, size < oldSize ? size : oldSize);
- gfree(p);
- } else {
- q = gmalloc(size);
- }
- return q;
-#else
- void *q;
-
- if (size == 0) {
- if (p)
- free(p);
- return NULL;
- }
- if (p)
- q = realloc(p, size);
- else
- q = malloc(size);
- if (!q) {
- fprintf(stderr, "Out of memory\n");
- exit(1);
- }
- return q;
-#endif
-}
-
-void *gmallocn(int nObjs, int objSize) {
- int n;
-
- n = nObjs * objSize;
- if (objSize == 0 || n / objSize != nObjs) {
- fprintf(stderr, "Bogus memory allocation size\n");
- exit(1);
- }
- return gmalloc(n);
-}
-
-void *greallocn(void *p, int nObjs, int objSize) {
- int n;
-
- n = nObjs * objSize;
- if (objSize == 0 || n / objSize != nObjs) {
- fprintf(stderr, "Bogus memory allocation size\n");
- exit(1);
- }
- return grealloc(p, n);
-}
-
-void gfree(void *p) {
-#ifdef DEBUG_MEM
- int size;
- GMemHdr *hdr;
- GMemHdr *prevHdr, *q;
- int lst;
- unsigned long *trl, *clr;
-
- if (p) {
- hdr = (GMemHdr *)((char *)p - gMemHdrSize);
- lst = ((int)hdr >> gMemListShift) & gMemListMask;
- for (prevHdr = NULL, q = gMemList[lst]; q; prevHdr = q, q = q->next) {
- if (q == hdr)
- break;
- }
- if (q) {
- if (prevHdr)
- prevHdr->next = hdr->next;
- else
- gMemList[lst] = hdr->next;
- --gMemAlloc;
- gMemInUse -= hdr->size;
- size = gMemDataSize(hdr->size);
- trl = (unsigned long *)((char *)hdr + gMemHdrSize + size);
- if (*trl != gMemDeadVal) {
- fprintf(stderr, "Overwrite past end of block %d at address %p\n",
- hdr->index, p);
- }
- for (clr = (unsigned long *)hdr; clr <= trl; ++clr)
- *clr = gMemDeadVal;
- free(hdr);
- } else {
- fprintf(stderr, "Attempted to free bad address %p\n", p);
- }
- }
-#else
- if (p)
- free(p);
-#endif
-}
-
-#ifdef DEBUG_MEM
-void gMemReport(FILE *f) {
- GMemHdr *p;
- int lst;
-
- fprintf(f, "%d memory allocations in all\n", gMemIndex);
- if (gMemAlloc > 0) {
- fprintf(f, "%d memory blocks left allocated:\n", gMemAlloc);
- fprintf(f, " index size\n");
- fprintf(f, "-------- --------\n");
- for (lst = 0; lst < gMemNLists; ++lst) {
- for (p = gMemList[lst]; p; p = p->next)
- fprintf(f, "%8d %8d\n", p->index, p->size);
- }
- } else {
- fprintf(f, "No memory blocks left allocated\n");
- }
-}
-#endif
-
-char *copyString(char *s) {
- char *s1;
-
- s1 = (char *)gmalloc(strlen(s) + 1);
- strcpy(s1, s);
- return s1;
-}
+++ /dev/null
-/*
- * gmem.h
- *
- * Memory routines with out-of-memory checking.
- *
- * Copyright 1996-2003 Glyph & Cog, LLC
- */
-
-#ifndef GMEM_H
-#define GMEM_H
-
-#include <stdio.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
- * Same as malloc, but prints error message and exits if malloc()
- * returns NULL.
- */
-extern void *gmalloc(int size);
-
-/*
- * Same as realloc, but prints error message and exits if realloc()
- * returns NULL. If <p> is NULL, calls malloc instead of realloc().
- */
-extern void *grealloc(void *p, int size);
-
-/*
- * These are similar to gmalloc and grealloc, but take an object count
- * and size. The result is similar to allocating nObjs * objSize
- * bytes, but there is an additional error check that the total size
- * doesn't overflow an int.
- */
-extern void *gmallocn(int nObjs, int objSize);
-extern void *greallocn(void *p, int nObjs, int objSize);
-
-/*
- * Same as free, but checks for and ignores NULL pointers.
- */
-extern void gfree(void *p);
-
-#ifdef DEBUG_MEM
-/*
- * Report on unfreed memory.
- */
-extern void gMemReport(FILE *f);
-#else
-#define gMemReport(f)
-#endif
-
-/*
- * Allocate memory and copy a string into it.
- */
-extern char *copyString(char *s);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
+++ /dev/null
-/*
- * gtypes.h
- *
- * Some useful simple types.
- *
- * Copyright 1996-2003 Glyph & Cog, LLC
- */
-
-#ifndef GTYPES_H
-#define GTYPES_H
-
-/*
- * These have stupid names to avoid conflicts with some (but not all)
- * C++ compilers which define them.
- */
-typedef int GBool;
-#define gTrue 1
-#define gFalse 0
-
-/*
- * These have stupid names to avoid conflicts with <sys/types.h>,
- * which on various systems defines some random subset of these.
- */
-typedef unsigned char Guchar;
-typedef unsigned short Gushort;
-typedef unsigned int Guint;
-typedef unsigned long Gulong;
-
-#endif