From 3bb2dc06d0393fbd794faca14a5c118e7f191f5d Mon Sep 17 00:00:00 2001 From: kramm Date: Mon, 5 Jun 2006 07:47:02 +0000 Subject: [PATCH] moved ../../pdf2swf/xpdf to . --- lib/xpdf/Stream.cc | 4574 +++++++++++++++++++++++++++++++++++++++++++ lib/xpdf/UnicodeMap.h | 123 ++ lib/xpdf/UnicodeMapTables.h | 361 ++++ lib/xpdf/XRef.cc | 888 +++++++++ lib/xpdf/XRef.h | 131 ++ lib/xpdf/aconf.h | 24 + lib/xpdf/cmyk.cc | 661 +++++++ lib/xpdf/cmyk.h | 4 + lib/xpdf/config.h | 112 ++ lib/xpdf/gfile.cc | 751 +++++++ lib/xpdf/gfile.h | 141 ++ lib/xpdf/gmem.c | 229 +++ lib/xpdf/gmem.h | 62 + lib/xpdf/gtypes.h | 29 + lib/xpdf/pdf.cc | 357 ++++ lib/xpdf/pdf.h | 37 + 16 files changed, 8484 insertions(+) create mode 100644 lib/xpdf/Stream.cc create mode 100644 lib/xpdf/UnicodeMap.h create mode 100644 lib/xpdf/UnicodeMapTables.h create mode 100644 lib/xpdf/XRef.cc create mode 100644 lib/xpdf/XRef.h create mode 100644 lib/xpdf/aconf.h create mode 100644 lib/xpdf/cmyk.cc create mode 100644 lib/xpdf/cmyk.h create mode 100644 lib/xpdf/config.h create mode 100644 lib/xpdf/gfile.cc create mode 100644 lib/xpdf/gfile.h create mode 100644 lib/xpdf/gmem.c create mode 100644 lib/xpdf/gmem.h create mode 100644 lib/xpdf/gtypes.h create mode 100644 lib/xpdf/pdf.cc create mode 100644 lib/xpdf/pdf.h diff --git a/lib/xpdf/Stream.cc b/lib/xpdf/Stream.cc new file mode 100644 index 0000000..7a663d3 --- /dev/null +++ b/lib/xpdf/Stream.cc @@ -0,0 +1,4574 @@ +//======================================================================== +// +// Stream.cc +// +// Copyright 1996-2003 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include +#include +#ifndef WIN32 +#include +#else +extern "C" int unlink(char *filename); +#endif +#include +#include +#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 of 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; +} diff --git a/lib/xpdf/UnicodeMap.h b/lib/xpdf/UnicodeMap.h new file mode 100644 index 0000000..0f86101 --- /dev/null +++ b/lib/xpdf/UnicodeMap.h @@ -0,0 +1,123 @@ +//======================================================================== +// +// UnicodeMap.h +// +// Mapping from Unicode to an encoding. +// +// Copyright 2001-2003 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef UNICODEMAP_H +#define UNICODEMAP_H + +#include + +#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 . 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 + // . + GBool match(GString *encodingNameA); + + // Map Unicode to the target encoding. Fills in with the + // output and returns the number of bytes used. Output will be + // truncated at 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 . 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 diff --git a/lib/xpdf/UnicodeMapTables.h b/lib/xpdf/UnicodeMapTables.h new file mode 100644 index 0000000..9c51034 --- /dev/null +++ b/lib/xpdf/UnicodeMapTables.h @@ -0,0 +1,361 @@ +//======================================================================== +// +// 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)) diff --git a/lib/xpdf/XRef.cc b/lib/xpdf/XRef.cc new file mode 100644 index 0000000..b371541 --- /dev/null +++ b/lib/xpdf/XRef.cc @@ -0,0 +1,888 @@ +//======================================================================== +// +// XRef.cc +// +// Copyright 1996-2003 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include +#include +#include +#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 , + // generation 0. + ObjectStream(XRef *xref, int objStrNumA); + + ~ObjectStream(); + + // Return the object number of this object stream. + int getObjStrNum() { return objStrNum; } + + // Get the th object from this stream, which should be + // object number , 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; +} diff --git a/lib/xpdf/XRef.h b/lib/xpdf/XRef.h new file mode 100644 index 0000000..f9dede3 --- /dev/null +++ b/lib/xpdf/XRef.h @@ -0,0 +1,131 @@ +//======================================================================== +// +// XRef.h +// +// Copyright 1996-2003 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef XREF_H +#define XREF_H + +#include + +#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 array + int rootNum, rootGen; // catalog dict + GBool ok; // true if xref table is valid + int errCode; // error code (if 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 diff --git a/lib/xpdf/aconf.h b/lib/xpdf/aconf.h new file mode 100644 index 0000000..524ccee --- /dev/null +++ b/lib/xpdf/aconf.h @@ -0,0 +1,24 @@ +/* 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 diff --git a/lib/xpdf/cmyk.cc b/lib/xpdf/cmyk.cc new file mode 100644 index 0000000..c74f743 --- /dev/null +++ b/lib/xpdf/cmyk.cc @@ -0,0 +1,661 @@ +#include +#include +#include +#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 diff --git a/lib/xpdf/cmyk.h b/lib/xpdf/cmyk.h new file mode 100644 index 0000000..1efb467 --- /dev/null +++ b/lib/xpdf/cmyk.h @@ -0,0 +1,4 @@ +#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 diff --git a/lib/xpdf/config.h b/lib/xpdf/config.h new file mode 100644 index 0000000..f21e311 --- /dev/null +++ b/lib/xpdf/config.h @@ -0,0 +1,112 @@ +//======================================================================== +// +// 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 "pdf2swf.conf" +#else +#define xpdfUserConfigFile ".pdf2swf.conf" +#endif + +// system config file name (set via the configure script) +#ifndef WIN32 +#define xpdfSysConfigFile "/etc/pdf2swf.conf" +#else +// under Windows, we get the directory with the executable and then +// append this file name +#define xpdfSysConfigFile "pdf2swf.conf" +#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 diff --git a/lib/xpdf/gfile.cc b/lib/xpdf/gfile.cc new file mode 100644 index 0000000..5fa0762 --- /dev/null +++ b/lib/xpdf/gfile.cc @@ -0,0 +1,751 @@ +//======================================================================== +// +// gfile.cc +// +// Miscellaneous file and directory name manipulation. +// +// Copyright 1996-2003 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifndef WIN32 +# if defined(MACOS) +# include +# elif !defined(ACORN) +# include +# include +# include +# endif +# include +# include +# if !defined(VMS) && !defined(ACORN) && !defined(MACOS) +# include +# endif +# if defined(VMS) && (__DECCXX_VER < 50200000) +# include +# 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 +} + +static char* getTempDir() +{ +#ifdef WIN32 + char*dir = getenv("TMP"); + if(!dir) dir = getenv("TEMP"); + if(!dir) dir = getenv("tmp"); + if(!dir) dir = getenv("temp"); + if(!dir) dir = "C:\\"; +#else + char* dir = "/tmp/"; +#endif + return dir; +} + +char* mktmpname(char*ptr) { + static char tmpbuf[128]; + char*dir = getTempDir(); + int l = strlen(dir); + char*sep = ""; + if(!ptr) + ptr = tmpbuf; + if(l && dir[l-1]!='/' && dir[l-1]!='\\') { +#ifdef WIN32 + sep = "\\"; +#else + sep = "/"; +#endif + } + + // used to be mktemp. This does remove the warnings, but + // It's not exactly an improvement. +#ifdef HAVE_LRAND48 + sprintf(ptr, "%s%s%08x%08x",dir,sep,lrand48(),lrand48()); +#else +# ifdef HAVE_RAND + sprintf(ptr, "%s%s%08x%08x",dir,sep,rand(),rand()); +# else + static int count = 1; + sprintf(ptr, "%s%s%08x%04x%04x",dir,sep,time(0),(unsigned int)tmpbuf^((unsigned int)tmpbuf)>>16,count); + count ++; +# endif +#endif + return ptr; +} + + +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 = mktmpname(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 = mktmpname(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 = mktmpname(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 +} diff --git a/lib/xpdf/gfile.h b/lib/xpdf/gfile.h new file mode 100644 index 0000000..10a4226 --- /dev/null +++ b/lib/xpdf/gfile.h @@ -0,0 +1,141 @@ +//======================================================================== +// +// gfile.h +// +// Miscellaneous file and directory name manipulation. +// +// Copyright 1996-2003 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef GFILE_H +#define GFILE_H + +#include +#include +#include +#if defined(WIN32) +# include +# ifdef FPTEX +# include +# else +# include +# endif +#elif defined(ACORN) +#elif defined(MACOS) +# include +#else +# include +# include +# ifdef VMS +# include "vms_dirent.h" +# elif HAVE_DIRENT_H +# include +# define NAMLEN(d) strlen((d)->d_name) +# else +# define dirent direct +# define NAMLEN(d) (d)->d_namlen +# if HAVE_SYS_NDIR_H +# include +# endif +# if HAVE_SYS_DIR_H +# include +# endif +# if HAVE_NDIR_H +# include +# endif +# endif +#endif +#include "gtypes.h" + +class GString; + +//------------------------------------------------------------------------ + +// Get home directory path. +extern GString *getHomeDir(); + +// Get current directory. +extern GString *getCurrentDir(); + +/* create a temporary filename */ +char* mktmpname(char*ptr); + +// Append a file name to a path string. may be an empty +// string, denoting the current directory). Returns . +extern GString *appendToPath(GString *path, char *fileName); + +// Grab the path from the front of the file name. If there is no +// directory component in , 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 . Returns 0 if there is an +// error. +extern time_t getModTime(char *fileName); + +// Create a temporary file and open it for writing. If 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 string +// should be "w" or "wb". Returns true on success. +extern GBool openTempFile(GString **name, FILE **f, char *mode, char *ext); + +// Execute . 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 diff --git a/lib/xpdf/gmem.c b/lib/xpdf/gmem.c new file mode 100644 index 0000000..a0f2cf5 --- /dev/null +++ b/lib/xpdf/gmem.c @@ -0,0 +1,229 @@ +/* + * gmem.c + * + * Memory routines with out-of-memory checking. + * + * Copyright 1996-2003 Glyph & Cog, LLC + */ + +#include +#include +#include +#include +#include +#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; +} diff --git a/lib/xpdf/gmem.h b/lib/xpdf/gmem.h new file mode 100644 index 0000000..e74d182 --- /dev/null +++ b/lib/xpdf/gmem.h @@ -0,0 +1,62 @@ +/* + * gmem.h + * + * Memory routines with out-of-memory checking. + * + * Copyright 1996-2003 Glyph & Cog, LLC + */ + +#ifndef GMEM_H +#define GMEM_H + +#include + +#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

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 diff --git a/lib/xpdf/gtypes.h b/lib/xpdf/gtypes.h new file mode 100644 index 0000000..9f64f57 --- /dev/null +++ b/lib/xpdf/gtypes.h @@ -0,0 +1,29 @@ +/* + * 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 , + * 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 diff --git a/lib/xpdf/pdf.cc b/lib/xpdf/pdf.cc new file mode 100644 index 0000000..f2e13e9 --- /dev/null +++ b/lib/xpdf/pdf.cc @@ -0,0 +1,357 @@ +#include "../gfxdevice.h" +#include "../gfxsource.h" +#include "../log.h" +#include "GlobalParams.h" +#include "InfoOutputDev.h" +#include "GFXOutputDev.h" +#include "../mem.h" +#include "pdf.h" + +static parameter_t* device_config = 0; +static parameter_t* device_config_next = 0; + +int jpeg_dpi = 0; +int ppm_dpi = 0; + +static double zoom = 72; /* xpdf: 86 */ + +typedef struct _pdf_page_info +{ + int xMin, yMin, xMax, yMax; + int width,height; + int number_of_images; + int number_of_links; + int number_of_fonts; +} pdf_page_info_t; + +typedef struct _pdf_doc_internal +{ + int protect; + PDFDoc*doc; + InfoOutputDev*info; + GFXOutputDev*outputDev; + pdf_page_info_t*pages; +} pdf_doc_internal_t; + +typedef struct _pdf_page_internal +{ +} pdf_page_internal_t; + +typedef struct _dev_output_internal +{ + GFXOutputDev*outputDev; +} dev_output_internal_t; + + +static char* dirseparator() +{ +#ifdef WIN32 + return "\\"; +#else + return "/"; +#endif +} + + +void pdfpage_destroy(gfxpage_t*pdf_page) +{ + pdf_page_internal_t*i= (pdf_page_internal_t*)pdf_page->internal; + free(pdf_page->internal);pdf_page->internal = 0; + free(pdf_page);pdf_page=0; +} + +void render2(gfxpage_t*page, gfxdevice_t*output) +{ + pdf_doc_internal_t*pi = (pdf_doc_internal_t*)page->parent->internal; + + if(!pi) { + msg(" pdf_page_render: Parent PDF this page belongs to doesn't exist yet/anymore"); + return; + } + + if(pi->protect) { + gfxdevice_t*dev = pi->outputDev->device; + dev->setparameter(dev, "protect", "1"); + } + pi->outputDev->setInfo(pi->info); + pi->outputDev->setXRef(pi->doc, pi->doc->getXRef()); + pi->doc->displayPage((OutputDev*)pi->outputDev, page->nr, zoom, zoom, /*rotate*/0, true, true, /*doLinks*/(int)1); +} + + +void pdfpage_render(gfxpage_t*page, gfxdevice_t*output) +{ + pdf_doc_internal_t*pi = (pdf_doc_internal_t*)page->parent->internal; + pi->outputDev->setDevice(output); + pi->outputDev->setMove(0,0); + pi->outputDev->setClip(0,0,0,0); + render2(page, output); + pi->outputDev->setDevice(0); +} + +void pdfpage_rendersection(gfxpage_t*page, gfxdevice_t*output, gfxcoord_t x, gfxcoord_t y, gfxcoord_t _x1, gfxcoord_t _y1, gfxcoord_t _x2, gfxcoord_t _y2) +{ + int x1=(int)_x1,y1=(int)_y1,x2=(int)_x2,y2=(int)_y2; + pdf_doc_internal_t*pi = (pdf_doc_internal_t*)page->parent->internal; + pi->outputDev->setDevice(output); + pi->outputDev->setMove((int)x,(int)y); + if((x1|y1|x2|y2)==0) x2++; + pi->outputDev->setClip((int)x1,(int)y1,(int)x2,(int)y2); + render2(page, output); + pi->outputDev->setDevice(0); +} + +void pdf_doc_destroy(gfxdocument_t*gfx) +{ + pdf_doc_internal_t*i= (pdf_doc_internal_t*)gfx->internal; + + delete i->doc; i->doc=0; + free(i->pages); i->pages = 0; + + if(i->info) { + delete i->info;i->info=0; + } + + free(gfx->internal);gfx->internal=0; + free(gfx);gfx=0; +} + +void pdf_doc_set_parameter(gfxdocument_t*gfx, char*name, char*value) +{ + pdf_doc_internal_t*i= (pdf_doc_internal_t*)gfx->internal; + if(!strcmp(name, "pagemap")) { + GFXOutputDev*o = i->outputDev; + int pdfpage=0, outputpage=0; + sscanf(value,"%d:%d", &pdfpage, &outputpage); + o->preparePage(pdfpage, outputpage); + } else { + msg(" Ignored parameter: %s=%s", name, value); + } +} + +gfxpage_t* pdf_doc_getpage(gfxdocument_t*doc, int page) +{ + pdf_doc_internal_t*di= (pdf_doc_internal_t*)doc->internal; + + if(page < 1 || page > doc->num_pages) + return 0; + + gfxpage_t* pdf_page = (gfxpage_t*)malloc(sizeof(gfxpage_t)); + pdf_page_internal_t*pi= (pdf_page_internal_t*)malloc(sizeof(pdf_page_internal_t)); + memset(pi, 0, sizeof(pdf_page_internal_t)); + pdf_page->internal = pi; + + pdf_page->destroy = pdfpage_destroy; + pdf_page->render = pdfpage_render; + pdf_page->rendersection = pdfpage_rendersection; + pdf_page->width = di->pages[page-1].width; + pdf_page->height = di->pages[page-1].height; + + pdf_page->parent = doc; + pdf_page->nr = page; + return pdf_page; +} + +void storeDeviceParameter(char*name, char*value) +{ + parameter_t*p = new parameter_t(); + p->name = strdup(name); + p->value = strdup(value); + p->next = 0; + if(device_config_next) { + device_config_next->next = p; + device_config_next = p; + } else { + device_config = p; + device_config_next = p; + } +} + +void pdf_set_parameter(char*name, char*value) +{ + msg(" setting parameter %s to \"%s\"", name, value); + if(!strncmp(name, "fontdir", strlen("fontdir"))) { + addGlobalFontDir(value); + } else if(!strncmp(name, "font", strlen("font"))) { + addGlobalFont(value); + } else if(!strncmp(name, "languagedir", strlen("languagedir"))) { + addGlobalLanguageDir(value); + } else if(!strcmp(name, "zoom")) { + char buf[80]; + zoom = atof(value); + sprintf(buf, "%f", (double)jpeg_dpi/(double)zoom); + storeDeviceParameter("jpegsubpixels", buf); + sprintf(buf, "%f", (double)ppm_dpi/(double)zoom); + storeDeviceParameter("ppmsubpixels", buf); + } else if(!strcmp(name, "jpegdpi")) { + char buf[80]; + jpeg_dpi = atoi(value); + sprintf(buf, "%f", (double)jpeg_dpi/(double)zoom); + storeDeviceParameter("jpegsubpixels", buf); + } else if(!strcmp(name, "ppmdpi")) { + char buf[80]; + ppm_dpi = atoi(value); + sprintf(buf, "%f", (double)ppm_dpi/(double)zoom); + storeDeviceParameter("ppmsubpixels", buf); + } else { + storeDeviceParameter(name,value); + } +} + +static void printInfoString(Dict *infoDict, char *key, char *fmt) { + Object obj; + GString *s1, *s2; + int i; + + if (infoDict->lookup(key, &obj)->isString()) { + s1 = obj.getString(); + if ((s1->getChar(0) & 0xff) == 0xfe && + (s1->getChar(1) & 0xff) == 0xff) { + s2 = new GString(); + for (i = 2; i < obj.getString()->getLength(); i += 2) { + if (s1->getChar(i) == '\0') { + s2->append(s1->getChar(i+1)); + } else { + delete s2; + s2 = new GString(""); + break; + } + } + printf(fmt, s2->getCString()); + delete s2; + } else { + printf(fmt, s1->getCString()); + } + } + obj.free(); +} + +static void printInfoDate(Dict *infoDict, char *key, char *fmt) { + Object obj; + char *s; + + if (infoDict->lookup(key, &obj)->isString()) { + s = obj.getString()->getCString(); + if (s[0] == 'D' && s[1] == ':') { + s += 2; + } + printf(fmt, s); + } + obj.free(); +} + + + +gfxdocument_t*pdf_open(char*filename) +{ + gfxdocument_t*pdf_doc = (gfxdocument_t*)malloc(sizeof(gfxdocument_t)); + memset(pdf_doc, 0, sizeof(gfxdocument_t)); + pdf_doc_internal_t*i= (pdf_doc_internal_t*)malloc(sizeof(pdf_doc_internal_t)); + memset(i, 0, sizeof(pdf_doc_internal_t)); + pdf_doc->internal = i; + char*userPassword; + + filename = strdup(filename); + + char*x = 0; + if((x = strchr(filename, '|'))) { + *x = 0; + userPassword = x+1; + } + + GString *fileName = new GString(filename); + GString *userPW; + Object info; + + // read config file + if(!globalParams) + globalParams = new GlobalParams(""); + + // open PDF file + if (userPassword && userPassword[0]) { + userPW = new GString(userPassword); + } else { + userPW = NULL; + } + i->doc = new PDFDoc(fileName, userPW); + if (userPW) { + delete userPW; + } + if (!i->doc->isOk()) { + return 0; + } + + // print doc info + i->doc->getDocInfo(&info); + if (info.isDict() && + (getScreenLogLevel()>=LOGLEVEL_NOTICE)) { + printInfoString(info.getDict(), "Title", "Title: %s\n"); + printInfoString(info.getDict(), "Subject", "Subject: %s\n"); + printInfoString(info.getDict(), "Keywords", "Keywords: %s\n"); + printInfoString(info.getDict(), "Author", "Author: %s\n"); + printInfoString(info.getDict(), "Creator", "Creator: %s\n"); + printInfoString(info.getDict(), "Producer", "Producer: %s\n"); + printInfoDate(info.getDict(), "CreationDate", "CreationDate: %s\n"); + printInfoDate(info.getDict(), "ModDate", "ModDate: %s\n"); + printf("Pages: %d\n", i->doc->getNumPages()); + printf("Linearized: %s\n", i->doc->isLinearized() ? "yes" : "no"); + printf("Encrypted: "); + if (i->doc->isEncrypted()) { + printf("yes (print:%s copy:%s change:%s addNotes:%s)\n", + i->doc->okToPrint() ? "yes" : "no", + i->doc->okToCopy() ? "yes" : "no", + i->doc->okToChange() ? "yes" : "no", + i->doc->okToAddNotes() ? "yes" : "no"); + } else { + printf("no\n"); + } + } + info.free(); + + pdf_doc->num_pages = i->doc->getNumPages(); + i->protect = 0; + if (i->doc->isEncrypted()) { + if(!i->doc->okToCopy()) { + printf("PDF disallows copying.\n"); + return 0; + } + if(!i->doc->okToChange() || !i->doc->okToAddNotes()) + i->protect = 1; + } + + InfoOutputDev*io = new InfoOutputDev(); + int t; + i->pages = (pdf_page_info_t*)malloc(sizeof(pdf_page_info_t)*pdf_doc->num_pages); + for(t=1;t<=pdf_doc->num_pages;t++) { + i->doc->displayPage((OutputDev*)io, t, zoom, zoom, /*rotate*/0, /*usemediabox*/true, /*crop*/true, /*doLinks*/(int)1); + i->pages[t-1].xMin = io->x1; + i->pages[t-1].yMin = io->y1; + i->pages[t-1].xMax = io->x2; + i->pages[t-1].yMax = io->y2; + i->pages[t-1].width = io->x2 - io->x1; + i->pages[t-1].height = io->y2 - io->y1; + i->pages[t-1].number_of_images = io->num_images; + i->pages[t-1].number_of_links = io->num_links; + i->pages[t-1].number_of_fonts = io->num_fonts; + } + i->info = io; + i->outputDev = new GFXOutputDev(device_config); + + pdf_doc->get = 0; + pdf_doc->destroy = pdf_doc_destroy; + pdf_doc->set_parameter = pdf_doc_set_parameter; + pdf_doc->getpage = pdf_doc_getpage; + + + return pdf_doc; + +} + +gfxsource_t*gfxsource_pdf_create() +{ + gfxsource_t*src = (gfxsource_t*)malloc(sizeof(gfxsource_t)); + memset(src, 0, sizeof(gfxsource_t)); + src->set_parameter = pdf_set_parameter; + src->open = pdf_open; + return src; +} diff --git a/lib/xpdf/pdf.h b/lib/xpdf/pdf.h new file mode 100644 index 0000000..3a6f4fc --- /dev/null +++ b/lib/xpdf/pdf.h @@ -0,0 +1,37 @@ +/* swfoutput.h + Header file for swfoutput.cc (and swfoutput_x11.cc). + + Part of the swftools package. + + Copyright (c) 2001,2002,2003 Matthias Kramm + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#ifndef __pdfsource_h__ +#define __pdfsource_h__ + +#include "../gfxsource.h" + +#ifdef __cplusplus +extern "C" { +#endif + +gfxsource_t*gfxsource_pdf_create(); + +#ifdef __cplusplus +} +#endif + +#endif //__pdfsource_h__ -- 1.7.10.4