From: Matthias Kramm Date: Sun, 6 Jun 2010 00:18:41 +0000 (-0700) Subject: Merge branch 'horizontals' X-Git-Tag: version-0-9-1~5 X-Git-Url: http://git.asbjorn.biz/?p=swftools.git;a=commitdiff_plain;h=a9634f803811f39e67114955c3e9c30ae247a669;hp=70ce1703acd71940235f2db58840c21d2a697003 Merge branch 'horizontals' Conflicts: lib/gfxpoly/Makefile lib/gfxpoly/poly.h --- diff --git a/config.h.in b/config.h.in index 7f99da5..9f122a0 100644 --- a/config.h.in +++ b/config.h.in @@ -282,4 +282,13 @@ #define calloc rfx_calloc_replacement #endif +//#ifdef HAVE_BUILTIN_EXPECT +#if defined(__GNUC__) && (__GNUC__ > 2) && defined(__OPTIMIZE__) +# define likely(x) __builtin_expect((x), 1) +# define unlikely(x) __builtin_expect((x), 0) +#else +# define likely(x) (x) +# define unlikely(x) (x) +#endif + #endif diff --git a/installer/installer.c b/installer/installer.c index b62721d..d22efd5 100644 --- a/installer/installer.c +++ b/installer/installer.c @@ -534,7 +534,7 @@ BOOL CALLBACK PropertySheetFunc3(HWND hwnd, UINT message, WPARAM wParam, LPARAM SetDlgItemText(hwnd, IDC_SPACE2, ""); PropSheet_SetWizButtons(dialog, 0); SendMessage(dialog, PSM_CANCELTOCLOSE, 0, 0); //makes wine display a warning - SetDlgItemText(hwnd, IDC_TITLE, "Installing files..."); + SetDlgItemText(hwnd, IDC_TITLE, "Installing..."); statuswnd = hwnd; status_t status; status.status = PropertyArchiveStatus; diff --git a/lib/gfxpoly/Makefile b/lib/gfxpoly/Makefile index ccf252c..6faca66 100644 --- a/lib/gfxpoly/Makefile +++ b/lib/gfxpoly/Makefile @@ -37,7 +37,7 @@ xrow.o: xrow.c xrow.h ../q.h ../mem.h Makefile stroke.o: stroke.c poly.h convert.h wind.h Makefile $(CC) -c stroke.c -o stroke.o -GFX=../gfxfont.o ../gfxtools.o ../gfximage.o ../devices/ops.o ../devices/polyops.o ../devices/text.o ../devices/bbox.o ../devices/render.o ../devices/rescale.o ../devices/record.o +GFX=../gfxfont.o ../gfxtools.o ../gfximage.o ../devices/ops.o ../devices/polyops.o ../devices/text.o ../devices/bbox.o ../devices/render.o ../devices/rescale.o ../devices/record.o stroke: test_stroke.c $(OBJS) ../libgfxswf.a ../librfxswf.a ../libbase.a $(CC) test_stroke.c $(OBJS) ../libgfxswf.a ../librfxswf.a $(GFX) ../libbase.a -o stroke $(LIBS) diff --git a/lib/pdf/BitmapOutputDev.cc b/lib/pdf/BitmapOutputDev.cc index 7b7b6a5..d54c8ea 100644 --- a/lib/pdf/BitmapOutputDev.cc +++ b/lib/pdf/BitmapOutputDev.cc @@ -1699,11 +1699,20 @@ gfxbbox_t BitmapOutputDev::getImageBBox(GfxState*state) bbox.ymax=max(bbox.ymax,y); return bbox; } + +GBool invalid_size(int width, int height) +{ + if((U64)width*(U64)height > 0x7fffffffll) + return 1; + return 0; +} + void BitmapOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str, int width, int height, GBool invert, GBool inlineImg) { msg(" drawImageMask streamkind=%d", str->getKind()); + if(invalid_size(width,height)) return; CopyStream*cpystr = new CopyStream(str, height * ((width + 7) / 8)); str = cpystr->getStream(); @@ -1720,6 +1729,7 @@ void BitmapOutputDev::drawImage(GfxState *state, Object *ref, Stream *str, int *maskColors, GBool inlineImg) { msg(" drawImage streamkind=%d", str->getKind()); + if(invalid_size(width,height)) return; CopyStream*cpystr = new CopyStream(str, height * ((width * colorMap->getNumPixelComps() * colorMap->getBits() + 7) / 8)); str = cpystr->getStream(); @@ -1738,6 +1748,7 @@ void BitmapOutputDev::drawMaskedImage(GfxState *state, Object *ref, Stream *str, GBool maskInvert) { msg(" drawMaskedImage streamkind=%d", str->getKind()); + if(invalid_size(width,height)) return; CopyStream*cpystr = new CopyStream(str, height * ((width * colorMap->getNumPixelComps() * colorMap->getBits() + 7) / 8)); str = cpystr->getStream(); @@ -1757,6 +1768,7 @@ void BitmapOutputDev::drawSoftMaskedImage(GfxState *state, Object *ref, Stream * GfxImageColorMap *maskColorMap) { msg(" drawSoftMaskedImage %dx%d (%dx%d) streamkind=%d", width, height, maskWidth, maskHeight, str->getKind()); + if(invalid_size(width,height)) return; CopyStream*cpystr = new CopyStream(str, height * ((width * colorMap->getNumPixelComps() * colorMap->getBits() + 7) / 8)); str = cpystr->getStream(); diff --git a/lib/pdf/xpdf-changes.patch b/lib/pdf/xpdf-changes.patch index 850e72a..75f89a6 100644 --- a/lib/pdf/xpdf-changes.patch +++ b/lib/pdf/xpdf-changes.patch @@ -1201,3 +1201,723 @@ // 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); +--- xpdf/JBIG2Stream.cc.orig 2010-05-18 11:33:21.000000000 -0700 ++++ xpdf/JBIG2Stream.cc 2010-06-03 16:55:03.000000000 -0700 +@@ -6,7 +6,24 @@ + // + //======================================================================== + +-#include ++//======================================================================== ++// ++// Modified under the Poppler project - http://poppler.freedesktop.org ++// ++// All changes made under the Poppler project to this file are licensed ++// under GPL version 2 or later ++// ++// Copyright (C) 2006 Raj Kumar ++// Copyright (C) 2006 Paul Walmsley ++// Copyright (C) 2006-2009 Albert Astals Cid ++// Copyright (C) 2009 David Benjamin ++// ++// To see a description of the changes please see the Changelog file that ++// came with your tarball or type make ChangeLog if you are building from git ++// ++//======================================================================== ++ ++#include + + #ifdef USE_GCC_PRAGMAS + #pragma implementation +@@ -24,8 +41,8 @@ + + //------------------------------------------------------------------------ + +-static int contextSize[4] = { 16, 13, 10, 10 }; +-static int refContextSize[2] = { 13, 10 }; ++static const int contextSize[4] = { 16, 13, 10, 10 }; ++static const int refContextSize[2] = { 13, 10 }; + + //------------------------------------------------------------------------ + // JBIG2HuffmanTable +@@ -42,7 +59,7 @@ + Guint prefix; + }; + +-JBIG2HuffmanTable huffTableA[] = { ++static JBIG2HuffmanTable huffTableA[] = { + { 0, 1, 4, 0x000 }, + { 16, 2, 8, 0x002 }, + { 272, 3, 16, 0x006 }, +@@ -50,7 +67,7 @@ + { 0, 0, jbig2HuffmanEOT, 0 } + }; + +-JBIG2HuffmanTable huffTableB[] = { ++static JBIG2HuffmanTable huffTableB[] = { + { 0, 1, 0, 0x000 }, + { 1, 2, 0, 0x002 }, + { 2, 3, 0, 0x006 }, +@@ -61,7 +78,7 @@ + { 0, 0, jbig2HuffmanEOT, 0 } + }; + +-JBIG2HuffmanTable huffTableC[] = { ++static JBIG2HuffmanTable huffTableC[] = { + { 0, 1, 0, 0x000 }, + { 1, 2, 0, 0x002 }, + { 2, 3, 0, 0x006 }, +@@ -74,7 +91,7 @@ + { 0, 0, jbig2HuffmanEOT, 0 } + }; + +-JBIG2HuffmanTable huffTableD[] = { ++static JBIG2HuffmanTable huffTableD[] = { + { 1, 1, 0, 0x000 }, + { 2, 2, 0, 0x002 }, + { 3, 3, 0, 0x006 }, +@@ -84,7 +101,7 @@ + { 0, 0, jbig2HuffmanEOT, 0 } + }; + +-JBIG2HuffmanTable huffTableE[] = { ++static JBIG2HuffmanTable huffTableE[] = { + { 1, 1, 0, 0x000 }, + { 2, 2, 0, 0x002 }, + { 3, 3, 0, 0x006 }, +@@ -96,7 +113,7 @@ + { 0, 0, jbig2HuffmanEOT, 0 } + }; + +-JBIG2HuffmanTable huffTableF[] = { ++static JBIG2HuffmanTable huffTableF[] = { + { 0, 2, 7, 0x000 }, + { 128, 3, 7, 0x002 }, + { 256, 3, 8, 0x003 }, +@@ -114,7 +131,7 @@ + { 0, 0, jbig2HuffmanEOT, 0 } + }; + +-JBIG2HuffmanTable huffTableG[] = { ++static JBIG2HuffmanTable huffTableG[] = { + { -512, 3, 8, 0x000 }, + { 256, 3, 8, 0x001 }, + { 512, 3, 9, 0x002 }, +@@ -133,7 +150,7 @@ + { 0, 0, jbig2HuffmanEOT, 0 } + }; + +-JBIG2HuffmanTable huffTableH[] = { ++static JBIG2HuffmanTable huffTableH[] = { + { 0, 2, 1, 0x000 }, + { 0, 2, jbig2HuffmanOOB, 0x001 }, + { 4, 3, 4, 0x004 }, +@@ -158,7 +175,7 @@ + { 0, 0, jbig2HuffmanEOT, 0 } + }; + +-JBIG2HuffmanTable huffTableI[] = { ++static JBIG2HuffmanTable huffTableI[] = { + { 0, 2, jbig2HuffmanOOB, 0x000 }, + { -1, 3, 1, 0x002 }, + { 1, 3, 1, 0x003 }, +@@ -184,7 +201,7 @@ + { 0, 0, jbig2HuffmanEOT, 0 } + }; + +-JBIG2HuffmanTable huffTableJ[] = { ++static JBIG2HuffmanTable huffTableJ[] = { + { -2, 2, 2, 0x000 }, + { 6, 2, 6, 0x001 }, + { 0, 2, jbig2HuffmanOOB, 0x002 }, +@@ -209,7 +226,7 @@ + { 0, 0, jbig2HuffmanEOT, 0 } + }; + +-JBIG2HuffmanTable huffTableK[] = { ++static JBIG2HuffmanTable huffTableK[] = { + { 1, 1, 0, 0x000 }, + { 2, 2, 1, 0x002 }, + { 4, 4, 0, 0x00c }, +@@ -226,7 +243,7 @@ + { 0, 0, jbig2HuffmanEOT, 0 } + }; + +-JBIG2HuffmanTable huffTableL[] = { ++static JBIG2HuffmanTable huffTableL[] = { + { 1, 1, 0, 0x000 }, + { 2, 2, 0, 0x002 }, + { 3, 3, 1, 0x006 }, +@@ -243,7 +260,7 @@ + { 0, 0, jbig2HuffmanEOT, 0 } + }; + +-JBIG2HuffmanTable huffTableM[] = { ++static JBIG2HuffmanTable huffTableM[] = { + { 1, 1, 0, 0x000 }, + { 2, 3, 0, 0x004 }, + { 7, 3, 3, 0x005 }, +@@ -260,7 +277,7 @@ + { 0, 0, jbig2HuffmanEOT, 0 } + }; + +-JBIG2HuffmanTable huffTableN[] = { ++static JBIG2HuffmanTable huffTableN[] = { + { 0, 1, 0, 0x000 }, + { -2, 3, 0, 0x004 }, + { -1, 3, 0, 0x005 }, +@@ -269,7 +286,7 @@ + { 0, 0, jbig2HuffmanEOT, 0 } + }; + +-JBIG2HuffmanTable huffTableO[] = { ++static JBIG2HuffmanTable huffTableO[] = { + { 0, 1, 0, 0x000 }, + { -1, 3, 0, 0x004 }, + { 1, 3, 0, 0x005 }, +@@ -473,7 +490,7 @@ + } + + int JBIG2MMRDecoder::get2DCode() { +- CCITTCode *p; ++ const CCITTCode *p; + + if (bufLen == 0) { + buf = str->getChar() & 0xff; +@@ -500,7 +517,7 @@ + } + + int JBIG2MMRDecoder::getWhiteCode() { +- CCITTCode *p; ++ const CCITTCode *p; + Guint code; + + if (bufLen == 0) { +@@ -543,7 +560,7 @@ + } + + int JBIG2MMRDecoder::getBlackCode() { +- CCITTCode *p; ++ const CCITTCode *p; + Guint code; + + if (bufLen == 0) { +@@ -670,6 +687,7 @@ + void combine(JBIG2Bitmap *bitmap, int x, int y, Guint combOp); + Guchar *getDataPtr() { return data; } + int getDataSize() { return h * line; } ++ GBool isOk() { return data != NULL; } + + private: + +@@ -685,10 +703,11 @@ + w = wA; + h = hA; + line = (wA + 7) >> 3; ++ + if (w <= 0 || h <= 0 || line <= 0 || h >= (INT_MAX - 1) / line) { +- // force a call to gmalloc(-1), which will throw an exception +- h = -1; +- line = 2; ++ error(-1, "invalid width/height"); ++ data = NULL; ++ return; + } + // need to allocate one extra guard byte for use in combine() + data = (Guchar *)gmalloc(h * line + 1); +@@ -701,10 +720,11 @@ + w = bitmap->w; + h = bitmap->h; + line = bitmap->line; ++ + if (w <= 0 || h <= 0 || line <= 0 || h >= (INT_MAX - 1) / line) { +- // force a call to gmalloc(-1), which will throw an exception +- h = -1; +- line = 2; ++ error(-1, "invalid width/height"); ++ data = NULL; ++ return; + } + // need to allocate one extra guard byte for use in combine() + data = (Guchar *)gmalloc(h * line + 1); +@@ -735,6 +755,9 @@ + + void JBIG2Bitmap::expand(int newH, Guint pixel) { + if (newH <= h || line <= 0 || newH >= (INT_MAX - 1) / line) { ++ error(-1, "invalid width/height"); ++ gfree(data); ++ data = NULL; + return; + } + // need to allocate one extra guard byte for use in combine() +@@ -1002,6 +1025,7 @@ + Guint getSize() { return size; } + void setBitmap(Guint idx, JBIG2Bitmap *bitmap) { bitmaps[idx] = bitmap; } + JBIG2Bitmap *getBitmap(Guint idx) { return bitmaps[idx]; } ++ GBool isOk() { return bitmaps != NULL; } + void setGenericRegionStats(JArithmeticDecoderStats *stats) + { genericRegionStats = stats; } + void setRefinementRegionStats(JArithmeticDecoderStats *stats) +@@ -1022,13 +1046,9 @@ + JBIG2SymbolDict::JBIG2SymbolDict(Guint segNumA, Guint sizeA): + JBIG2Segment(segNumA) + { +- Guint i; +- + size = sizeA; + bitmaps = (JBIG2Bitmap **)gmallocn(size, sizeof(JBIG2Bitmap *)); +- for (i = 0; i < size; ++i) { +- bitmaps[i] = NULL; +- } ++ if (!bitmaps) size = 0; + genericRegionStats = NULL; + refinementRegionStats = NULL; + } +@@ -1037,9 +1057,7 @@ + Guint i; + + for (i = 0; i < size; ++i) { +- if (bitmaps[i]) { +- delete bitmaps[i]; +- } ++ delete bitmaps[i]; + } + gfree(bitmaps); + if (genericRegionStats) { +@@ -1247,6 +1265,7 @@ + Guint segNum, segFlags, segType, page, segLength; + Guint refFlags, nRefSegs; + Guint *refSegs; ++ int segDataPos; + int c1, c2, c3; + Guint i; + +@@ -1314,6 +1333,9 @@ + goto eofError2; + } + ++ // keep track of the start of the segment data ++ segDataPos = getPos(); ++ + // check for missing page information segment + if (!pageBitmap && ((segType >= 4 && segType <= 7) || + (segType >= 20 && segType <= 43))) { +@@ -1398,6 +1420,45 @@ + break; + } + ++ // Make sure the segment handler read all of the bytes in the ++ // segment data, unless this segment is marked as having an ++ // unknown length (section 7.2.7 of the JBIG2 Final Committee Draft) ++ ++ if (segLength != 0xffffffff) { ++ ++ int segExtraBytes = segDataPos + segLength - getPos(); ++ if (segExtraBytes > 0) { ++ ++ // If we didn't read all of the bytes in the segment data, ++ // indicate an error, and throw away the rest of the data. ++ ++ // v.3.1.01.13 of the LuraTech PDF Compressor Server will ++ // sometimes generate an extraneous NULL byte at the end of ++ // arithmetic-coded symbol dictionary segments when numNewSyms ++ // == 0. Segments like this often occur for blank pages. ++ ++ error(getPos(), "%d extraneous byte%s after segment", ++ segExtraBytes, (segExtraBytes > 1) ? "s" : ""); ++ ++ // Burn through the remaining bytes -- inefficient, but ++ // hopefully we're not doing this much ++ ++ int trash; ++ for (int i = segExtraBytes; i > 0; i--) { ++ readByte(&trash); ++ } ++ ++ } else if (segExtraBytes < 0) { ++ ++ // If we read more bytes than we should have, according to the ++ // segment length field, note an error. ++ ++ error(getPos(), "Previous segment handler read too many bytes"); ++ ++ } ++ ++ } ++ + gfree(refSegs); + } + +@@ -1493,6 +1554,9 @@ + codeTables = new GList(); + numInputSyms = 0; + for (i = 0; i < nRefSegs; ++i) { ++ // This is need by bug 12014, returning gFalse makes it not crash ++ // but we end up with a empty page while acroread is able to render ++ // part of it + if ((seg = findSegment(refSegs[i]))) { + if (seg->getType() == jbig2SegSymbolDict) { + j = ((JBIG2SymbolDict *)seg)->getSize(); +@@ -1503,8 +1567,11 @@ + } + numInputSyms += j; + } else if (seg->getType() == jbig2SegCodeTable) { +- codeTables->append(seg); ++ codeTables->append(seg); + } ++ } else { ++ delete codeTables; ++ return gFalse; + } + } + if (numInputSyms > UINT_MAX - numNewSyms) { +@@ -1530,12 +1600,11 @@ + k = 0; + inputSymbolDict = NULL; + for (i = 0; i < nRefSegs; ++i) { +- if ((seg = findSegment(refSegs[i]))) { +- if (seg->getType() == jbig2SegSymbolDict) { +- inputSymbolDict = (JBIG2SymbolDict *)seg; +- for (j = 0; j < inputSymbolDict->getSize(); ++j) { +- bitmaps[k++] = inputSymbolDict->getBitmap(j); +- } ++ seg = findSegment(refSegs[i]); ++ if (seg != NULL && seg->getType() == jbig2SegSymbolDict) { ++ inputSymbolDict = (JBIG2SymbolDict *)seg; ++ for (j = 0; j < inputSymbolDict->getSize(); ++j) { ++ bitmaps[k++] = inputSymbolDict->getBitmap(j); + } + } + } +@@ -1753,6 +1822,10 @@ + + // create the symbol dict object + symbolDict = new JBIG2SymbolDict(segNum, numExSyms); ++ if (!symbolDict->isOk()) { ++ delete symbolDict; ++ goto syntaxError; ++ } + + // exported symbol list + i = j = 0; +@@ -1766,6 +1839,7 @@ + if (i + run > numInputSyms + numNewSyms || + (ex && j + run > numExSyms)) { + error(getPos(), "Too many exported symbols in JBIG2 symbol dictionary"); ++ for ( ; j < numExSyms; ++j) symbolDict->setBitmap(j, NULL); + delete symbolDict; + goto syntaxError; + } +@@ -1780,6 +1854,7 @@ + } + if (j != numExSyms) { + error(getPos(), "Too few symbols in JBIG2 symbol dictionary"); ++ for ( ; j < numExSyms; ++j) symbolDict->setBitmap(j, NULL); + delete symbolDict; + goto syntaxError; + } +@@ -2095,18 +2170,20 @@ + + gfree(syms); + +- // combine the region bitmap into the page bitmap +- if (imm) { +- if (pageH == 0xffffffff && y + h > curPageH) { +- pageBitmap->expand(y + h, pageDefPixel); +- } +- pageBitmap->combine(bitmap, x, y, extCombOp); +- delete bitmap; ++ if (bitmap) { ++ // combine the region bitmap into the page bitmap ++ if (imm) { ++ if (pageH == 0xffffffff && y + h > curPageH) { ++ pageBitmap->expand(y + h, pageDefPixel); ++ } ++ pageBitmap->combine(bitmap, x, y, extCombOp); ++ delete bitmap; + +- // store the region bitmap +- } else { +- bitmap->setSegNum(segNum); +- segments->append(bitmap); ++ // store the region bitmap ++ } else { ++ bitmap->setSegNum(segNum); ++ segments->append(bitmap); ++ } + } + + // clean up the Huffman decoder +@@ -2159,6 +2236,10 @@ + + // allocate the bitmap + bitmap = new JBIG2Bitmap(0, w, h); ++ if (!bitmap->isOk()) { ++ delete bitmap; ++ return NULL; ++ } + if (defPixel) { + bitmap->clearToOne(); + } else { +@@ -2235,73 +2316,84 @@ + ri = 0; + } + if (ri) { ++ GBool decodeSuccess; + if (huff) { +- huffDecoder->decodeInt(&rdw, huffRDWTable); +- huffDecoder->decodeInt(&rdh, huffRDHTable); +- huffDecoder->decodeInt(&rdx, huffRDXTable); +- huffDecoder->decodeInt(&rdy, huffRDYTable); +- huffDecoder->decodeInt(&bmSize, huffRSizeTable); ++ decodeSuccess = huffDecoder->decodeInt(&rdw, huffRDWTable); ++ decodeSuccess = decodeSuccess && huffDecoder->decodeInt(&rdh, huffRDHTable); ++ decodeSuccess = decodeSuccess && huffDecoder->decodeInt(&rdx, huffRDXTable); ++ decodeSuccess = decodeSuccess && huffDecoder->decodeInt(&rdy, huffRDYTable); ++ decodeSuccess = decodeSuccess && huffDecoder->decodeInt(&bmSize, huffRSizeTable); + huffDecoder->reset(); + arithDecoder->start(); + } else { +- arithDecoder->decodeInt(&rdw, iardwStats); +- arithDecoder->decodeInt(&rdh, iardhStats); +- arithDecoder->decodeInt(&rdx, iardxStats); +- arithDecoder->decodeInt(&rdy, iardyStats); ++ decodeSuccess = arithDecoder->decodeInt(&rdw, iardwStats); ++ decodeSuccess = decodeSuccess && arithDecoder->decodeInt(&rdh, iardhStats); ++ decodeSuccess = decodeSuccess && arithDecoder->decodeInt(&rdx, iardxStats); ++ decodeSuccess = decodeSuccess && arithDecoder->decodeInt(&rdy, iardyStats); ++ } ++ ++ if (decodeSuccess && syms[symID]) ++ { ++ refDX = ((rdw >= 0) ? rdw : rdw - 1) / 2 + rdx; ++ refDY = ((rdh >= 0) ? rdh : rdh - 1) / 2 + rdy; ++ ++ symbolBitmap = ++ readGenericRefinementRegion(rdw + syms[symID]->getWidth(), ++ rdh + syms[symID]->getHeight(), ++ templ, gFalse, syms[symID], ++ refDX, refDY, atx, aty); + } +- refDX = ((rdw >= 0) ? rdw : rdw - 1) / 2 + rdx; +- refDY = ((rdh >= 0) ? rdh : rdh - 1) / 2 + rdy; +- +- symbolBitmap = +- readGenericRefinementRegion(rdw + syms[symID]->getWidth(), +- rdh + syms[symID]->getHeight(), +- templ, gFalse, syms[symID], +- refDX, refDY, atx, aty); + //~ do we need to use the bmSize value here (in Huffman mode)? + } else { + symbolBitmap = syms[symID]; + } + +- // combine the symbol bitmap into the region bitmap +- //~ something is wrong here - refCorner shouldn't degenerate into +- //~ two cases +- bw = symbolBitmap->getWidth() - 1; +- bh = symbolBitmap->getHeight() - 1; +- if (transposed) { +- switch (refCorner) { +- case 0: // bottom left +- bitmap->combine(symbolBitmap, tt, s, combOp); +- break; +- case 1: // top left +- bitmap->combine(symbolBitmap, tt, s, combOp); +- break; +- case 2: // bottom right +- bitmap->combine(symbolBitmap, tt - bw, s, combOp); +- break; +- case 3: // top right +- bitmap->combine(symbolBitmap, tt - bw, s, combOp); +- break; ++ if (symbolBitmap) { ++ // combine the symbol bitmap into the region bitmap ++ //~ something is wrong here - refCorner shouldn't degenerate into ++ //~ two cases ++ bw = symbolBitmap->getWidth() - 1; ++ bh = symbolBitmap->getHeight() - 1; ++ if (transposed) { ++ switch (refCorner) { ++ case 0: // bottom left ++ bitmap->combine(symbolBitmap, tt, s, combOp); ++ break; ++ case 1: // top left ++ bitmap->combine(symbolBitmap, tt, s, combOp); ++ break; ++ case 2: // bottom right ++ bitmap->combine(symbolBitmap, tt - bw, s, combOp); ++ break; ++ case 3: // top right ++ bitmap->combine(symbolBitmap, tt - bw, s, combOp); ++ break; ++ } ++ s += bh; ++ } else { ++ switch (refCorner) { ++ case 0: // bottom left ++ bitmap->combine(symbolBitmap, s, tt - bh, combOp); ++ break; ++ case 1: // top left ++ bitmap->combine(symbolBitmap, s, tt, combOp); ++ break; ++ case 2: // bottom right ++ bitmap->combine(symbolBitmap, s, tt - bh, combOp); ++ break; ++ case 3: // top right ++ bitmap->combine(symbolBitmap, s, tt, combOp); ++ break; ++ } ++ s += bw; + } +- s += bh; +- } else { +- switch (refCorner) { +- case 0: // bottom left +- bitmap->combine(symbolBitmap, s, tt - bh, combOp); +- break; +- case 1: // top left +- bitmap->combine(symbolBitmap, s, tt, combOp); +- break; +- case 2: // bottom right +- bitmap->combine(symbolBitmap, s, tt - bh, combOp); +- break; +- case 3: // top right +- bitmap->combine(symbolBitmap, s, tt, combOp); +- break; ++ if (ri) { ++ delete symbolBitmap; + } +- s += bw; +- } +- if (ri) { +- delete symbolBitmap; ++ } else { ++ // NULL symbolBitmap only happens on error ++ delete bitmap; ++ return NULL; + } + } + +@@ -2431,11 +2523,12 @@ + error(getPos(), "Bad symbol dictionary reference in JBIG2 halftone segment"); + return; + } +- if (!(seg = findSegment(refSegs[0])) || +- seg->getType() != jbig2SegPatternDict) { ++ seg = findSegment(refSegs[0]); ++ if (seg == NULL || seg->getType() != jbig2SegPatternDict) { + error(getPos(), "Bad symbol dictionary reference in JBIG2 halftone segment"); + return; + } ++ + patternDict = (JBIG2PatternDict *)seg; + bpp = 0; + i = 1; +@@ -2591,6 +2684,8 @@ + // read the bitmap + bitmap = readGenericBitmap(mmr, w, h, templ, tpgdOn, gFalse, + NULL, atx, aty, mmr ? length - 18 : 0); ++ if (!bitmap) ++ return; + + // combine the region bitmap into the page bitmap + if (imm) { +@@ -2616,7 +2711,7 @@ + int *codingLine, int *a0i, int w) { + if (a1 > codingLine[*a0i]) { + if (a1 > w) { +- error(getPos(), "JBIG2 MMR row is wrong length ({0:d})", a1); ++ error(getPos(), "JBIG2 MMR row is wrong length (%d)", a1); + a1 = w; + } + if ((*a0i & 1) ^ blackPixels) { +@@ -2630,7 +2725,7 @@ + int *codingLine, int *a0i, int w) { + if (a1 > codingLine[*a0i]) { + if (a1 > w) { +- error(getPos(), "JBIG2 MMR row is wrong length ({0:d})", a1); ++ error(getPos(), "JBIG2 MMR row is wrong length (%d)", a1); + a1 = w; + } + if ((*a0i & 1) ^ blackPixels) { +@@ -2657,13 +2752,17 @@ + JBIG2Bitmap *bitmap; + GBool ltp; + Guint ltpCX, cx, cx0, cx1, cx2; +- JBIG2BitmapPtr cxPtr0, cxPtr1; +- JBIG2BitmapPtr atPtr0, atPtr1, atPtr2, atPtr3; ++ JBIG2BitmapPtr cxPtr0 = {0}, cxPtr1 = {0}; ++ JBIG2BitmapPtr atPtr0 = {0}, atPtr1 = {0}, atPtr2 = {0}, atPtr3 = {0}; + int *refLine, *codingLine; + int code1, code2, code3; + int x, y, a0i, b1i, blackPixels, pix, i; + + bitmap = new JBIG2Bitmap(0, w, h); ++ if (!bitmap->isOk()) { ++ delete bitmap; ++ return NULL; ++ } + bitmap->clearToZero(); + + //----- MMR decode +@@ -2682,7 +2781,7 @@ + // ---> max refLine size = w + 2 + codingLine = (int *)gmallocn(w + 1, sizeof(int)); + refLine = (int *)gmallocn(w + 2, sizeof(int)); +- codingLine[0] = w; ++ for (i = 0; i < w + 1; ++i) codingLine[i] = w; + + for (y = 0; y < h; ++y) { + +@@ -3093,8 +3192,8 @@ + return; + } + if (nRefSegs == 1) { +- if (!(seg = findSegment(refSegs[0])) || +- seg->getType() != jbig2SegBitmap) { ++ seg = findSegment(refSegs[0]); ++ if (seg == NULL || seg->getType() != jbig2SegBitmap) { + error(getPos(), "Bad bitmap reference in JBIG2 generic refinement segment"); + return; + } +@@ -3143,11 +3242,24 @@ + JBIG2Bitmap *bitmap; + GBool ltp; + Guint ltpCX, cx, cx0, cx2, cx3, cx4, tpgrCX0, tpgrCX1, tpgrCX2; +- JBIG2BitmapPtr cxPtr0, cxPtr1, cxPtr2, cxPtr3, cxPtr4, cxPtr5, cxPtr6; +- JBIG2BitmapPtr tpgrCXPtr0, tpgrCXPtr1, tpgrCXPtr2; ++ JBIG2BitmapPtr cxPtr0 = {0}; ++ JBIG2BitmapPtr cxPtr1 = {0}; ++ JBIG2BitmapPtr cxPtr2 = {0}; ++ JBIG2BitmapPtr cxPtr3 = {0}; ++ JBIG2BitmapPtr cxPtr4 = {0}; ++ JBIG2BitmapPtr cxPtr5 = {0}; ++ JBIG2BitmapPtr cxPtr6 = {0}; ++ JBIG2BitmapPtr tpgrCXPtr0 = {0}; ++ JBIG2BitmapPtr tpgrCXPtr1 = {0}; ++ JBIG2BitmapPtr tpgrCXPtr2 = {0}; + int x, y, pix; + + bitmap = new JBIG2Bitmap(0, w, h); ++ if (!bitmap->isOk()) ++ { ++ delete bitmap; ++ return NULL; ++ } + bitmap->clearToZero(); + + // set up the typical row context +@@ -3332,6 +3444,12 @@ + } + pageBitmap = new JBIG2Bitmap(0, pageW, curPageH); + ++ if (!pageBitmap->isOk()) { ++ delete pageBitmap; ++ pageBitmap = NULL; ++ return; ++ } ++ + // default pixel value + if (pageDefPixel) { + pageBitmap->clearToOne(); diff --git a/wx/Makefile b/wx/Makefile index 3ed15ef..e5cde64 100644 --- a/wx/Makefile +++ b/wx/Makefile @@ -6,13 +6,15 @@ include ../Makefile.common all: pdf2swf_gui.exe pdf2swf_gui.exe: gpdf2swf.py gui/*.py viewers/*.py - cp gpdf2swf.py /xpython/main.py - cp -R viewers gui lib /xpython/ + cp -a ../installer/swftools.ico /xpython/xpython.ico + cp -a gpdf2swf.py /xpython/main.py + cp -a -R viewers gui lib /xpython/ cd /xpython/swftools;git pull cd /xpython;make xpython.exe ln -f /xpython/xpython.exe ./gpdf2swf.exe #ln -f gpdf2swf.exe ../win32_gui/ ln -f gpdf2swf.exe ../win32/ cp -R viewers/* ../win32/viewers/ + rm -rf ../win32/viewers/flexpaper* # we're not distributing flexpaper .PHONY: exe diff --git a/wx/gpdf2swf.py b/wx/gpdf2swf.py index e6941c2..4462884 100644 --- a/wx/gpdf2swf.py +++ b/wx/gpdf2swf.py @@ -26,40 +26,47 @@ from __future__ import division import __builtin__ import os import sys -import imp +#import imp -def main_is_frozen(): - return (hasattr(sys, "frozen") or # new py2exe - hasattr(sys, "importers") # old py2exe - or imp.is_frozen("__main__")) # tools/freeze - -#if not main_is_frozen(): -# try: -# import wxversion -# wxversion.select("2.6") -# except: -# wxversion.select("2.8") - -def get_main_dir(): - if main_is_frozen(): - return os.path.dirname(sys.executable) - return os.path.dirname(os.path.abspath(__file__)) -__builtin__.get_main_dir = get_main_dir -__builtin__.GPDF2SWF_BASEDIR = get_main_dir() - -pyver = "".join(map(str, sys.version_info[0:2])) -#print >>sys.stderr, pyver -if main_is_frozen(): - sys.path.insert(0, os.path.join("..", "python%s" % pyver)) -else: - sys.path.insert(0, os.path.join("..", "lib", "python")) - sys.path.insert(1, os.path.join("..", "python%s" % pyver)) +#def main_is_frozen(): +# return (hasattr(sys, "frozen") or # new py2exe +# hasattr(sys, "importers") # old py2exe +# or imp.is_frozen("__main__")) # tools/freeze +# +##if not main_is_frozen(): +## try: +## import wxversion +## wxversion.select("2.6") +## except: +## wxversion.select("2.8") +# +#def get_main_dir(): +# if main_is_frozen(): +# return os.path.dirname(sys.executable) +# return os.path.dirname(os.path.abspath(__file__)) +#__builtin__.get_main_dir = get_main_dir +#__builtin__.GPDF2SWF_BASEDIR = get_main_dir() +# +#pyver = "".join(map(str, sys.version_info[0:2])) +##print >>sys.stderr, pyver +#if main_is_frozen(): +# sys.path.insert(0, os.path.join("..", "python%s" % pyver)) +#else: +# sys.path.insert(0, os.path.join("..", "lib", "python")) +# sys.path.insert(1, os.path.join("..", "python%s" % pyver)) import wx #print >>sys.stderr, wx.VERSION from lib.app import Pdf2Swf +__builtin__.GPDF2SWF_BASEDIR = os.path.dirname(os.path.abspath(sys.argv[0])) + if __name__ == "__main__": + #print "sys.argv[0]", sys.argv[0] + #print "abspath sys.argv[0]", + #print "sys.executable", sys.executable + #print "abspath sys.executable", os.path.abspath(sys.executable) + #print "GPDF2SWF_BASEDIR", GPDF2SWF_BASEDIR app = wx.App(False) app.SetAppName(u"gpdf2swf") Pdf2Swf() diff --git a/wx/gui/dialogs.py b/wx/gui/dialogs.py index b5387c1..906afd4 100644 --- a/wx/gui/dialogs.py +++ b/wx/gui/dialogs.py @@ -113,7 +113,7 @@ class InfoDialog(wx.Dialog): class AboutDialog: def __init__(self, parent): appname = wx.GetApp().GetAppName() - version = u"0.9.0" + version = u"0.10.0" copyright = (u"Copyright (c) 2008,2009,2010\n" u"Matthias Kramm ") description = u"A graphical user interface for pdf2swf" diff --git a/wx/gui/gmain.py b/wx/gui/gmain.py index 85aa2d6..be2a0ba 100644 --- a/wx/gui/gmain.py +++ b/wx/gui/gmain.py @@ -344,7 +344,7 @@ class PdfFrame(wx.Frame): choices=["everything to bitmaps", "fonts to fonts, everything else to bitmaps", "polygons to polygons and fonts to fonts"], - size=(350,-1), style=wx.CB_DROPDOWN + size=(350,-1) ) # I'm not sure about the utility of this, so Show False self.toolbar_preview_type.Show(False) diff --git a/wx/gui/options/viewer.py b/wx/gui/options/viewer.py index b0e69ac..0432cac 100644 --- a/wx/gui/options/viewer.py +++ b/wx/gui/options/viewer.py @@ -25,52 +25,58 @@ import os import wx import operator -#import imp +import imp from lib.wordwrap import wordwrap from gui.boldstatictext import BoldStaticText import viewers import gui.fields -import viewers.raw -import viewers.simple -import viewers.rfx -import viewers.flexpaper -import viewers.technoargia +# this two are only to satisfy some plugins requirements +import gui.plugin +import shutil + +#import viewers.raw +#import viewers.simple +#import viewers.rfx +#import viewers.flexpaper +#import viewers.technoargia class Viewers: def __init__(self): - self.viewers = [ - 'raw', - 'simple', - 'rfx', - 'flexpaper', - 'technoargia', - ] - self.modules = [ - viewers.raw, - viewers.simple, - viewers.rfx, - viewers.flexpaper, - viewers.technoargia, - ] + #self.viewers = [ + # 'raw', + # 'simple', + # 'rfx', + # 'flexpaper', + # 'technoargia', + #] + self.viewers = [] + #self.modules = [ + # viewers.raw, + # viewers.simple, + # viewers.rfx, + # viewers.flexpaper, + # viewers.technoargia, + #] + self.modules = [] - #self.list_viewers() - #self.import_viewers() + self.list_viewers() + self.import_viewers() - #def list_viewers(self): - # for file in os.listdir('viewers'): - # if (file.startswith('.') or file.startswith('_') - # or file.endswith(".pyc") or not file.endswith('.py')): - # continue - # self.viewers.append(os.path.splitext(file)[0]) + def list_viewers(self): + for file in os.listdir('viewers'): + if (file.startswith('.') or file.startswith('_') + or file.endswith(".pyc") or not file.endswith('.py')): + continue + self.viewers.append(os.path.splitext(file)[0]) - #def import_viewers(self): - # for file in self.viewers: - # try: - # _temp = imp.load_source("viewers.%s" % file, os.path.join(os.getcwdu(), "viewers/%s.py" % file)) - # self.modules.append(_temp) - # except: - # print "Could not load %s" % file + def import_viewers(self): + for file in self.viewers: + try: + _temp = imp.load_source("viewers.%s" % file, os.path.join(os.getcwdu(), "viewers/%s.py" % file)) + self.modules.append(_temp) + except Exception, e: + print "Could not load %s (%s)" % (file, e) @@ -98,6 +104,8 @@ class ViewerBook(wx.Listbook): win = self.makePanel(mod) self.AddPage(win, mod, imageId=idx) + if hasattr(mod, "default"): + self.SetSelection(idx) def makePanel(self, mod): diff --git a/wx/gui/plugin.py b/wx/gui/plugin.py index f58cc50..ad52e45 100644 --- a/wx/gui/plugin.py +++ b/wx/gui/plugin.py @@ -55,11 +55,23 @@ class Plugin: #print 'basedir', basedir opj = os.path.join - locations = [os.path.normpath(opj(basedir, '..', prog))] + locations = [ + os.path.normpath(opj(basedir, prog)), + os.path.normpath(opj(basedir, "..", "src", prog)), + ] if "wxMSW" in wx.PlatformInfo: + try: + system_drive = os.environ['SYSTEMDRIVE'] + except KeyError: + system_drive = 'c:' + try: + program_files = os.environ['PROGRAMFILES'] + except KeyError: + program_files = '' locations.extend([ - opj("c:", "swftools", prog), - opj("c:", "Program Files", "SWFTools", prog) + opj("c:", os.sep, "swftools", prog), + opj("c:", os.sep, "Program Files", "SWFTools", prog), + opj(system_drive, os.sep, program_files, "SWFTools", prog), ]) else: locations.extend([ @@ -105,7 +117,9 @@ class Plugin: # To avoid an ugly "DOS Window" to show up flags = win32process.CREATE_NO_WINDOW except ImportError: - flags = 0 + # See http://msdn.microsoft.com/en-us/library/ms684863(VS.85).aspx + # for this flag (CREATE_NO_WINDOW) value + flags = 0x08000000 else: flags = 0 output = Popen(cmd, stdin=PIPE, stdout=PIPE, diff --git a/wx/lib/__init__.py b/wx/lib/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/wx/lib/app.py b/wx/lib/app.py new file mode 100644 index 0000000..f524cdd --- /dev/null +++ b/wx/lib/app.py @@ -0,0 +1,519 @@ +#!/usr/bin/env python +# -*- coding: UTF-8 -*- +# +# gpdf2swf.py +# graphical user interface for pdf2swf +# +# Part of the swftools package. +# +# Copyright (c) 2008,2009 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 */ + +from __future__ import division +import os +import wx +import time +import pickle + +from lib.wordwrap import wordwrap +from wx.lib.pubsub import Publisher + +from document import Document +from gui.dialogs import (ProgressDialog, OptionsDialog, AboutDialog, InfoDialog) +from gui.gmain import (PdfFrame, + ID_INVERT_SELECTION, ID_SELECT_ODD, + ID_ONE_PAGE_PER_FILE, + ID_SELECT_EVEN, ID_DOC_INFO, + ) + + +def GetDataDir(): + """ + Return the standard location on this platform for application data + """ + sp = wx.StandardPaths.Get() + return sp.GetUserDataDir() + +def GetConfig(): + if not os.path.exists(GetDataDir()): + os.makedirs(GetDataDir()) + + config = wx.FileConfig( + localFilename=os.path.join(GetDataDir(), "options")) + return config + + +class Pdf2Swf: + def __init__(self): + self.__doc = Document() + + self.__threads = {} + + self.__busy = None + self.__progress = None + + self.__can_save = False + self.__can_viewinfo = False + + self.view = PdfFrame() + wx.GetApp().SetTopWindow(self.view) + # Call Show after the current and pending event + # handlers have been completed. Otherwise on MSW + # we see the frame been draw and after that we saw + # the menubar appear + wx.CallAfter(self.view.Show) + + self.options = OptionsDialog(self.view) + self.__ReadConfigurationFile() + + self.view.toolbar_preview_type.SetSelection(0) + + Publisher.subscribe(self.OnPageChanged, "PAGE_CHANGED") + Publisher.subscribe(self.OnFileLoaded, "FILE_LOADED") + Publisher.subscribe(self.OnFileNotLoaded, "FILE_NOT_LOADED") + Publisher.subscribe(self.OnDiffSizes, "DIFF_SIZES") + Publisher.subscribe(self.OnThumbnailAdded, "THUMBNAIL_ADDED") + Publisher.subscribe(self.OnThumbnailDone, "THUMBNAIL_DONE") + Publisher.subscribe(self.OnProgressBegin, "SWF_BEGIN_SAVE") + Publisher.subscribe(self.OnProgressUpdate, "SWF_PAGE_SAVED") + Publisher.subscribe(self.OnProgressDone, "SWF_FILE_SAVED") + Publisher.subscribe(self.OnCombineError, "SWF_COMBINE_ERROR") + Publisher.subscribe(self.OnFileDroped, "FILE_DROPED") + Publisher.subscribe(self.OnFilesDroped, "FILES_DROPED") + Publisher.subscribe(self.OnPluginOnePagePerFileNotSupported, + "PLUGIN_ONE_PAGE_PER_FILE_NOT_SUPPORTED") + Publisher.subscribe(self.OnPluginError, "PLUGIN_ERROR") + + self.view.Bind(wx.EVT_MENU, self.OnMenuOpen, id=wx.ID_OPEN) + self.view.Bind(wx.EVT_MENU, self.OnMenuSave, id=wx.ID_SAVE) + self.view.Bind(wx.EVT_MENU, self.OnMenuSaveSelected, id=wx.ID_SAVEAS) + self.view.Bind(wx.EVT_MENU, self.OnMenuExit, id=wx.ID_EXIT) + self.view.Bind(wx.EVT_MENU_RANGE, self.OnFileHistory, + id=wx.ID_FILE1, id2=wx.ID_FILE9) + + self.view.Bind(wx.EVT_UPDATE_UI, self.OnUpdateUI, id=wx.ID_SAVE) + self.view.Bind(wx.EVT_UPDATE_UI, self.OnUpdateUI, id=wx.ID_SAVEAS) + + self.view.Bind(wx.EVT_MENU, self.OnMenuSelectAll, id=wx.ID_SELECTALL) + self.view.Bind(wx.EVT_MENU, + self.OnMenuInvertSelection, id=ID_INVERT_SELECTION) + self.view.Bind(wx.EVT_MENU, self.OnMenuSelectOdd, id=ID_SELECT_ODD) + self.view.Bind(wx.EVT_MENU, self.OnMenuSelectEven, id=ID_SELECT_EVEN) + self.view.Bind(wx.EVT_MENU, self.OnMenuOptions, id=wx.ID_PREFERENCES) + + self.view.Bind(wx.EVT_UPDATE_UI, self.OnUpdateUI, id=wx.ID_SELECTALL) + self.view.Bind(wx.EVT_UPDATE_UI, self.OnUpdateUI, id=ID_INVERT_SELECTION) + self.view.Bind(wx.EVT_UPDATE_UI, self.OnUpdateUI, id=ID_SELECT_ODD) + self.view.Bind(wx.EVT_UPDATE_UI, self.OnUpdateUI, id=ID_SELECT_EVEN) + + self.view.Bind(wx.EVT_MENU, self.OnAbout, id=wx.ID_ABOUT) + + self.view.Bind(wx.EVT_MENU, self.OnZoom, id=wx.ID_ZOOM_IN) + self.view.Bind(wx.EVT_MENU, self.OnZoom, id=wx.ID_ZOOM_OUT) + self.view.Bind(wx.EVT_MENU, self.OnZoom, id=wx.ID_ZOOM_100) + self.view.Bind(wx.EVT_MENU, self.OnFit, id=wx.ID_ZOOM_FIT) + self.view.Bind(wx.EVT_MENU, self.OnShowDocInfo, id=ID_DOC_INFO) + + self.view.Bind(wx.EVT_UPDATE_UI, self.OnUpdateUI, id=wx.ID_ZOOM_IN) + self.view.Bind(wx.EVT_UPDATE_UI, self.OnUpdateUI, id=wx.ID_ZOOM_OUT) + self.view.Bind(wx.EVT_UPDATE_UI, self.OnUpdateUI, id=wx.ID_ZOOM_100) + self.view.Bind(wx.EVT_UPDATE_UI, self.OnUpdateUI, id=wx.ID_ZOOM_FIT) + self.view.Bind(wx.EVT_UPDATE_UI, self.OnUpdateUIInfo, id=ID_DOC_INFO) + + self.view.page_list.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnSelectItem) + self.view.Bind(wx.EVT_CLOSE, self.OnMenuExit) + + self.view.toolbar_preview_type.Bind(wx.EVT_CHOICE, + self.OnPreviewType) + + # statusbar cancel thumbanails generation button + self.view.statusbar.btn_cancel.Bind(wx.EVT_BUTTON, + self.OnThumbnailCancel) + + # Don't know where the problem is (python/xpython or wxwidgets/wxpython) + # but I found that this hack was necessary to avoid the app enter in a + # idle state. We must, for example, move the mouse inside the app + # for threads continue their job. + # There is no need for this when freezing with other utils, like + # py2exe, pyinstaller, cxfreeze + if "wxMSW" in wx.PlatformInfo: + self.timer = wx.Timer(self.view) + self.view.Bind(wx.EVT_TIMER, lambda evt: None) + self.timer.Start(50) + + def OnFilesDroped(self, evt): + dlg = wx.MessageDialog(self.view, + u"You must drop only one file.", + u"Notice", + style=wx.OK, pos=wx.DefaultPosition) + dlg.ShowModal() + dlg.Destroy() + + def OnFileDroped(self, message): + self.__Load(message.data["filename"]) + + def OnPluginOnePagePerFileNotSupported(self, message): + self.Message(u"Selected viewer does not support " + u"one page per file. ") + + def OnPluginError(self, message): + self.Message(u"Error applying selected viewer") + + def OnFileHistory(self, evt): + # get the file based on the menu ID + fileNum = evt.GetId() - wx.ID_FILE1 + filename = self.view.filehistory.GetHistoryFile(fileNum) + + self.__Load(filename) + + def OnProgressBegin(self, message): + pages = message.data["pages"] + style = ( + wx.PD_APP_MODAL|wx.PD_ELAPSED_TIME| + wx.PD_REMAINING_TIME|wx.PD_CAN_ABORT| + wx.PD_AUTO_HIDE + ) + self.__progress = ProgressDialog(u"Saving...", + u"Start saving SWF pages", + maximum=pages, + parent=self.view, style=style) + self.__progress.Show() + self.view.SetStatusText(u"Saving document...") + + def OnProgressUpdate(self, message): + pagenr = message.data["pagenr"] + pages = message.data["pages"] + + keep_running = self.__progress.Update( + pagenr, + u"Saving SWF page %d of %d" % (pagenr, pages) + ) + + if not keep_running and self.__threads.has_key("progress"): + self.view.SetStatusText(u"Cancelling...") + self.__threads.pop("progress").Stop() + + + def OnProgressDone(self, message): + if self.__threads.has_key("progress"): # it goes all the way? + self.__threads.pop("progress") + self.view.SetStatusText(u"SWF document saved successfully.") + else: + self.view.SetStatusText(u"") + + self.__progress.Destroy() + self.__progress = None + + def OnCombineError(self, message): + from wx.lib.dialogs import ScrolledMessageDialog + ScrolledMessageDialog(self.view, message.data, u"Notice").ShowModal() + + + def OnThumbnailAdded(self, message): + self.view.statusbar.SetGaugeValue(message.data['pagenr']) + tot = self.view.page_list.GetItemCount() + self.view.SetStatusText(u"Generating thumbnails %s/%d" % + (message.data['pagenr'], tot), 0) + + def OnThumbnailDone(self, message): + self.view.statusbar.SetGaugeValue(0) + self.view.SetStatusText(u"", 0) + if self.__threads.has_key("thumbnails"): + self.__threads.pop("thumbnails") + self.view.SendSizeEvent() + + def OnThumbnailCancel(self, event): + if self.__threads.has_key("thumbnails"): + self.__threads["thumbnails"].Stop() + + def OnSelectItem(self, event): + self.__doc.ChangePage(event.GetIndex() + 1) + + def OnPreviewType(self, event): + filename = self.__doc.filename + if filename: + self.__Load(filename) + + def OnPageChanged(self, message): + # ignore if we have more than one item selected + if self.view.page_list.GetSelectedItemCount() > 1: + return + + self.view.page_preview.DisplayPage(message.data) + + def SetTitle(self): + name = wx.GetApp().GetAppName() + filename = os.path.basename(self.__doc.filename) + if self.__doc.title != "n/a": + t = "%s - %s (%s)" % (name, filename, self.__doc.title) + else: + t = "%s - %s" % (name, filename) + self.view.SetTitle(t) + + def OnFileLoaded(self, message): + if self.__progress: + self.__progress.Destroy() + self.__progress = None + + self.__can_viewinfo = True + del self.__busy + + self.SetTitle() + + if self.__doc.oktocopy == 'no': + self.__can_save = False + self.view.page_list.DisplayEmptyThumbnails(0) + self.view.page_preview.Clear() + self.view.SetStatusText(u"") + self.Message( + u"This PDF disallows copying, cannot be converted." + ) + return + + #if not self.__doc.oktoprint: + self.view.SetStatusText(u"Document loaded successfully.") + + self.view.page_list.DisplayEmptyThumbnails(message.data["pages"]) + thumbs = self.__doc.GetThumbnails() + t = self.view.page_list.DisplayThumbnails(thumbs) + self.__threads["thumbnails"] = t + self.view.statusbar.SetGaugeRange(message.data["pages"]) + #del self.__busy + + def OnFileNotLoaded(self, message): + self.__can_save = False + self.__can_viewinfo = False + del self.__busy + self.view.SetStatusText(u"") + self.Message( + u"Could not open file %s" % message.data['filename'] + ) + + def OnDiffSizes(self, message): + # just let the user know- for now, we can't handle this properly + self.Message( + u"In this PDF, width or height are not the same for " + u"each page. This might cause problems if you export " + u"pages of different dimensions into the same SWF file." + ) + + def OnMenuOpen(self, event): + dlg = wx.FileDialog(self.view, u"Choose PDF File:", + style=wx.OPEN|wx.CHANGE_DIR, + wildcard = u"PDF files (*.pdf)|*.pdf|all files (*.*)|*.*") + + if dlg.ShowModal() == wx.ID_OK: + filename = dlg.GetPath() + self.__Load(filename) + + def OnMenuSave(self, event, pages=None): + defaultFile = self.__doc.lastsavefile + if "wxMSW" in wx.PlatformInfo: + allFiles = "*.*" + else: + allFiles = "*" + self.view.SetStatusText(u"") + dlg = wx.FileDialog(self.view, u"Choose Save Filename:", + style = wx.SAVE | wx.OVERWRITE_PROMPT, + defaultFile=os.path.basename(defaultFile), + wildcard=u"SWF files (*.swf)|*.swf" + "|all files (%s)|%s" % (allFiles, allFiles)) + + + if dlg.ShowModal() == wx.ID_OK: + menubar = self.view.GetMenuBar() + one_file_per_page = menubar.IsChecked(ID_ONE_PAGE_PER_FILE) + + self.__threads["progress"] = self.__doc.SaveSWF(dlg.GetPath(), + one_file_per_page, + pages, self.options) + + def OnUpdateUI(self, event): + menubar = self.view.GetMenuBar() + menubar.Enable(event.GetId(), self.__can_save) + + self.view.GetToolBar().EnableTool(event.GetId(), self.__can_save) + + def OnUpdateUIInfo(self, event): + menubar = self.view.GetMenuBar() + menubar.Enable(event.GetId(), self.__can_viewinfo) + + self.view.GetToolBar().EnableTool(event.GetId(), self.__can_viewinfo) + + def OnMenuSaveSelected(self, event): + pages = [] + page = self.view.page_list.GetFirstSelected() + pages.append(page+1) + + while True: + page = self.view.page_list.GetNextSelected(page) + if page == -1: + break + pages.append(page+1) + + self.OnMenuSave(event, pages) + + def OnMenuExit(self, event): + self.view.SetStatusText(u"Cleaning up...") + + # Stop any running thread + self.__StopThreads() + + config = GetConfig() + self.view.filehistory.Save(config) + config.Flush() + # A little extra cleanup is required for the FileHistory control + del self.view.filehistory + + # Save quality options + dirpath = GetDataDir() + data = self.options.quality_panel.pickle() + try: + f = file(os.path.join(dirpath, 'quality.pkl'), 'wb') + pickle.dump(data, f) + f.close() + except Exception: + pass + + # Save viewer options + try: + f = file(os.path.join(dirpath, 'viewers.pkl'), 'wb') + data = self.options.viewers_panel.pickle() + pickle.dump(data, f) + f.close() + except Exception: + pass + + self.view.Destroy() + + def OnMenuSelectAll(self, event): + for i in range(0, self.view.page_list.GetItemCount()): + self.view.page_list.Select(i, True) + + def OnMenuInvertSelection(self, event): + for i in range(0, self.view.page_list.GetItemCount()): + self.view.page_list.Select(i, not self.view.page_list.IsSelected(i)) + + def OnMenuSelectOdd(self, event): + for i in range(0, self.view.page_list.GetItemCount()): + self.view.page_list.Select(i, not bool(i%2)) + + def OnMenuSelectEven(self, event): + for i in range(0, self.view.page_list.GetItemCount()): + self.view.page_list.Select(i, bool(i%2)) + + def OnMenuOptions(self, event): + self.options.ShowModal() + + def OnFit(self, event): + self.__doc.Fit(self.view.page_preview.GetClientSize()) + + def OnZoom(self, event): + zoom = { + wx.ID_ZOOM_IN: .1, + wx.ID_ZOOM_OUT: -.1, + wx.ID_ZOOM_100: 1, + } + self.__doc.Zoom(zoom[event.GetId()]) + + def OnShowDocInfo(self, event): + info = InfoDialog(self.view) + info.info.display(self.__doc) + info.Show() + + def OnAbout(self, evt): + AboutDialog(self.view) + + def __Load(self, filename): + self.__can_save = True + self.__StopThreads() + self.view.SetStatusText(u"Loading document...") + self.__busy = wx.BusyInfo(u"One moment please, " + u"opening pdf document...") + + self.view.filehistory.AddFileToHistory(filename) + try: + # I dont care if this, for some reason, + # give some error. I just swallow it + os.chdir(os.path.dirname(filename)) + except: + pass + + # Need to delay the file load a little bit + # for the BusyInfo get a change to repaint itself + #wx.FutureCall(150, self.__doc.Load, filename) + sel = self.view.toolbar_preview_type.GetSelection() + #print sel + PREV_TYPE = { + 0 : [('bitmap', '1'), ('poly2bitmap', '0'), ('bitmapfonts', '1'),], + 1 : [('bitmap', '0'), ('poly2bitmap', '1'), ('bitmapfonts', '0'),], + 2 : [('bitmap', '0'), ('poly2bitmap', '0'), ('bitmapfonts', '0'),], + } + self.__doc.preview_parameters = PREV_TYPE[sel] + wx.CallAfter(self.__doc.Load, filename) + + def __StopThreads(self): + for n, t in self.__threads.items(): + t.Stop() + + running = True + while running: + running = False + for n, t in self.__threads.items(): + running = running + t.IsRunning() + time.sleep(0.1) + + def __ReadConfigurationFile(self): + config = GetConfig() + self.view.filehistory.Load(config) + + dirpath = GetDataDir() + try: + f = file(os.path.join(dirpath, 'quality.pkl'), 'rb') + #try: + if 1: + data = pickle.load(f) + self.options.quality_panel.unpickle(data) + #except: + # self.Message( + # u"Error loading quality settings. " + # u"They will be reset to defaults. ") + f.close() + except Exception: + pass + + try: + f = file(os.path.join(dirpath, 'viewers.pkl'), 'rb') + #try: + if 1: + data = pickle.load(f) + self.options.viewers_panel.unpickle(data) + #except: + # self.Message( + # u"Error loading viewers settings. " + # u"They will be reset to defaults. ") + f.close() + except Exception: + pass + #d = pickle.load(f) + + def Message(self, message): + dlg = wx.MessageDialog(self.view, + message, + style=wx.OK, pos=wx.DefaultPosition) + dlg.ShowModal() + dlg.Destroy() + diff --git a/wx/lib/document.py b/wx/lib/document.py new file mode 100644 index 0000000..de0af53 --- /dev/null +++ b/wx/lib/document.py @@ -0,0 +1,255 @@ +#!/usr/bin/env python +# -*- coding: UTF-8 -*- +# +# gpdf2swf.py +# graphical user interface for pdf2swf +# +# Part of the swftools package. +# +# Copyright (c) 2008,2009 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 */ + +from __future__ import division +import os +import time +import thread +import gfx +import wx +from wx.lib.pubsub import Publisher +from subprocess import Popen, PIPE + +class _SaveSWFThread: + def __init__(self, pdffilename, filename, one_page_per_file, doc, pages, options): + #self.__doc = doc + self.__filename = filename + self.__pdffilename = pdffilename + self.__pages = pages or range(1, doc.pages+1) + self.__options = options + self.__one_page_per_file = one_page_per_file + + def Start(self): + self.__keep_running = self.__running = True + thread.start_new_thread(self.Run, ()) + #self.Run() + + def Stop(self): + self.__keep_running = False + + def IsRunning(self): + return self.__running + + def Run(self): + swf = gfx.SWF() + + try: + plugin = self.__options.viewers.init(swf, self.__filename) + except Exception, e: + wx.CallAfter(Publisher.sendMessage, "PLUGIN_ERROR") + self.__running = False + return + + if self.__one_page_per_file and not plugin.one_page_per_file: + wx.CallAfter(Publisher.sendMessage, + "PLUGIN_ONE_PAGE_PER_FILE_NOT_SUPPORTED", + {'plugin': plugin,}) + self.__running = False + return + + pages = len(self.__pages) + wx.CallAfter(Publisher.sendMessage, "SWF_BEGIN_SAVE", + {'pages': pages,}) + + time.sleep(0.05) + + self.setparameters(gfx) + self.__doc = gfx.open("pdf", self.__pdffilename) + + self.setparameters(swf) + + try: + plugin.before_render() + except Exception, e: + wx.CallAfter(Publisher.sendMessage, "PLUGIN_ERROR") + self.__running = False + return + + for pagenr in self.__pages: + page = self.__doc.getPage(pagenr) + swf.startpage(page.width, page.height) + page.render(swf) + swf.endpage() + wx.CallAfter(Publisher.sendMessage, "SWF_PAGE_SAVED", + {'pagenr': pagenr, + 'pages': pages,}) + time.sleep(0.05) + + if self.__one_page_per_file: + form = '.%%0%dd.swf' % len(str(len(self.__pages))) + filename = self.__filename.replace('.swf', form % pagenr) + swf.save(filename) + swf = gfx.SWF() + + try: + plugin = self.__options.viewers.init(swf, self.__filename) + except Exception, e: + wx.CallAfter(Publisher.sendMessage, "PLUGIN_ERROR") + self.__running = False + return + + self.setparameters(swf) + + if not self.__keep_running: + break + else: + # This will not run if we break the for loop + if not self.__one_page_per_file: + try: + plugin.before_save(page) + except Exception, e: + wx.CallAfter(Publisher.sendMessage, "PLUGIN_ERROR") + self.__running = False + return + swf.save(self.__filename) + try: + plugin.after_save(page) + except Exception, e: + wx.CallAfter(Publisher.sendMessage, "PLUGIN_ERROR") + self.__running = False + return + + # No need. But to be sure that it's clean up + # as soon as possible + del swf + + wx.CallAfter(Publisher.sendMessage, "SWF_FILE_SAVED") + time.sleep(0.05) + + self.__running = False + + def setparameters(self, swf): + #print "driver", swf + for opt in self.__options.quality: + if type(opt.name) in (tuple, list): + for name, value in ( + # Example to better understand the list comprehension: + # opt.name = ['a', 'b', 'c'] + # opt.value = [1, 2, 3] + # zip them = [('a',1), ('b', 2), ('c', 3)] + # pair will be in this example ('a', 1) due to + # the if pair[1] condition + pair for pair in zip(opt.name, opt.value) #if pair[1] == 1 + ): + #print "1.swf.setparameter(%s, %s)" % (name, value) + swf.setparameter(str(name), str(value)) + else: + #print "2.swf.setparameter(%s, %s)" % (opt.name, str(opt.value)) + swf.setparameter(opt.name, str(opt.value)) + + #swf.setparameter('noclips', '1') + #swf.setparameter('reordertags', '1') + #swf.setparameter('animate', '1') + +PDF_INFO = [ + "title", "subject", "keywords", "author", + "creator", "producer", "creationdate", "moddate", + "linearized", "tagged", "encrypted", "oktoprint", + "oktocopy", "oktochange", "oktoaddnotes", "version", +] + +class Document(object): + def __init__(self): + self.__page = None + self.__zoom = 1 + self.__lastsavefile = "output.swf" + self.__pdffilename = None + self.__preview_parameters = [] + + def __getattr__(self, name): + if name in PDF_INFO: + return self.__pdf.getInfo(name) or "n/a" + raise AttributeError, name + + def filename(self): + return self.__pdffilename + filename = property(filename) + + def __get_lastsavefile(self): + return self.__lastsavefile + def __set_lastsavefile(self, lastsavefile): + self.__lastsavefile = lastsavefile + lastsavefile = property(__get_lastsavefile, __set_lastsavefile) + + def __SwapExtension(self, filename, newext): + basename, ext = os.path.splitext(filename) + return "%s.%s" % (basename, newext) + + def __Reload(self): + Publisher.sendMessage("PAGE_CHANGED", + {'page': self.__page, + 'width': int(self.__page.width * self.__zoom), + 'height': int(self.__page.height * self.__zoom)}) + + def __get_preview_parameters(self): + return self.__preview_parameters + def __set_preview_parameters(self, parameters): + self.__preview_parameters = parameters + preview_parameters = property(__get_preview_parameters, + __set_preview_parameters) + + def Load(self, filename): + self.__lastsavefile = self.__SwapExtension(filename, "swf") + self.__pdffilename = filename + + #print 'Load',self.__preview_parameters + for parameter, value in self.__preview_parameters: + gfx.setparameter(parameter, value) + + try: + self.__pdf = gfx.open("pdf", filename) + except: + Publisher.sendMessage("FILE_NOT_LOADED", {'filename': filename}) + else: + Publisher.sendMessage("FILE_LOADED", {'pages': self.__pdf.pages}) + + def ChangePage(self, pagenr=1, size=None): + self.__page = page = self.__pdf.getPage(pagenr) + self.__Reload() + + def Fit(self, size): + w = size[0] / self.__page.width + h = size[1] / self.__page.height + self.__zoom = min(w, h) + self.__Reload() + + def Zoom(self, zoom): + if zoom == 1: + self.__zoom = 1 + else: + self.__zoom += zoom + self.__Reload() + + def GetThumbnails(self): + for pagenr in range(1, self.__pdf.pages + 1): + page = self.__pdf.getPage(pagenr) + yield page + + def SaveSWF(self, filename, one_page_per_file, pages, options): + self.__lastsavefile = filename + t = _SaveSWFThread(self.__pdffilename, filename, one_page_per_file, self.__pdf, pages, options) + t.Start() + return t + + diff --git a/wx/lib/embeddedimage.py b/wx/lib/embeddedimage.py new file mode 100644 index 0000000..5b3cad4 --- /dev/null +++ b/wx/lib/embeddedimage.py @@ -0,0 +1,74 @@ +#---------------------------------------------------------------------- +# Name: wx.lib.embeddedimage +# Purpose: Defines a class used for embedding PNG images in Python +# code. The primary method of using this module is via +# the code generator in wx.tools.img2py. +# +# Author: Anthony Tuininga +# +# Created: 26-Nov-2007 +# RCS-ID: $Id: embeddedimage.py 59672 2009-03-20 20:59:42Z RD $ +# Copyright: (c) 2007 by Anthony Tuininga +# Licence: wxWindows license +#---------------------------------------------------------------------- + +import base64 +import cStringIO +import wx + +try: + b64decode = base64.b64decode +except AttributeError: + b64decode = base64.decodestring + + +class PyEmbeddedImage(object): + """ + PyEmbeddedImage is primarily intended to be used by code generated + by img2py as a means of embedding image data in a python module so + the image can be used at runtime without needing to access the + image from an image file. This makes distributing icons and such + that an application uses simpler since tools like py2exe will + automatically bundle modules that are imported, and the + application doesn't have to worry about how to locate the image + files on the user's filesystem. + + The class can also be used for image data that may be acquired + from some other source at runtime, such as over the network or + from a database. In this case pass False for isBase64 (unless the + data actually is base64 encoded.) Any image type that + wx.ImageFromStream can handle should be okay. + """ + + def __init__(self, data, isBase64=True): + self.data = data + self.isBase64 = isBase64 + + def GetBitmap(self): + return wx.BitmapFromImage(self.GetImage()) + + def GetData(self): + if self.isBase64: + data = b64decode(self.data) + return data + + def GetIcon(self): + icon = wx.EmptyIcon() + icon.CopyFromBitmap(self.GetBitmap()) + return icon + + def GetImage(self): + stream = cStringIO.StringIO(self.GetData()) + return wx.ImageFromStream(stream) + + # added for backwards compatibility + getBitmap = GetBitmap + getData = GetData + getIcon = GetIcon + getImage = GetImage + + # define properties, for convenience + Bitmap = property(GetBitmap) + Icon = property(GetIcon) + Image = property(GetImage) + diff --git a/wx/lib/images.py b/wx/lib/images.py new file mode 100644 index 0000000..7b34b74 --- /dev/null +++ b/wx/lib/images.py @@ -0,0 +1,107 @@ +#---------------------------------------------------------------------- +# This file was generated by /usr/bin/img2py +# +from embeddedimage import PyEmbeddedImage + +blank = PyEmbeddedImage( + "iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAAAXNSR0IArs4c6QAAAAZiS0dE" + "AP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9kHDAscKjCK/4UAAABo" + "SURBVHja7dABAcBAEAIgXf/Ofo8dRKDblqPa5stxAgQIECBAgAABAgQIECBAgAABAgQIECBA" + "gAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIEPALTbLLAQ8OIAV9" + "8WNeKwAAAABJRU5ErkJggg==") +getblankData = blank.GetData +getblankImage = blank.GetImage +getblankBitmap = blank.GetBitmap +getblankIcon = blank.GetIcon + +#---------------------------------------------------------------------- +stop = PyEmbeddedImage( + "iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAAAXNSR0IArs4c6QAAAAZiS0dE" + "AP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9kHGAEINtjJMYEAAADV" + "SURBVBjTPc8xTgJBAEbh988sLFkDXEAvgB338AhauI3EUqOVVhR6gq0s9Do2WpDVipaOLCZL" + "LGZ+G+IJ3ve0KssBUo3UWAJANtgL7JcCqXZVNcxmKXVdBBMn06S2bdT3xOvh8D3P50nPTyF2" + "O3xyjG9vpI/PrM3mrHAI/PZ9PHp79Xi5VAZ+7u7t7TY6BAI2g/2ehDAgBXSwABTKmWIyTr44" + "D93Do0FQX6Kv76T1Omo1Gl25qhqdzlLqdtE5E6fTpLaN6vuFVmU5kFQTQmMdMjn/b/4BTeBh" + "NrAp1ecAAAAASUVORK5CYII=") +getstopData = stop.GetData +getstopImage = stop.GetImage +getstopBitmap = stop.GetBitmap +getstopIcon = stop.GetIcon + +#---------------------------------------------------------------------- +gpdf2swf = PyEmbeddedImage( + "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" + "fQAAAABJRU5ErkJggg==") +getgpdf2swfData = gpdf2swf.GetData +getgpdf2swfImage = gpdf2swf.GetImage +getgpdf2swfBitmap = gpdf2swf.GetBitmap +getgpdf2swfIcon = gpdf2swf.GetIcon + diff --git a/wx/lib/utils.py b/wx/lib/utils.py new file mode 100644 index 0000000..75e80ff --- /dev/null +++ b/wx/lib/utils.py @@ -0,0 +1,55 @@ +import wx + +def blank_bmp(w, h, color="white"): + bmp = wx.EmptyBitmap(max(w,1) , max(h,1)) + clear_bmp(bmp, color) + return bmp + +def clear_bmp(bmp, color): + dc = wx.MemoryDC() + dc.SelectObject(bmp) + dc.SetBackground(wx.Brush(color)) + dc.Clear() + + +# Taken and adapt from django.utils.encoding +class GPdf2SwfUnicodeDecodeError(UnicodeDecodeError): + def __init__(self, obj, *args): + self.obj = obj + UnicodeDecodeError.__init__(self, *args) + + def __str__(self): + original = UnicodeDecodeError.__str__(self) + return '%s. You passed in %r (%s)' % (original, self.obj, + type(self.obj)) + +def force_unicode(s, encoding='utf-8', strings_only=False, errors='strict'): + try: + if not isinstance(s, basestring,): + if hasattr(s, '__unicode__'): + s = unicode(s) + else: + try: + s = unicode(str(s), encoding, errors) + except UnicodeEncodeError: + if not isinstance(s, Exception): + raise + # If we get to here, the caller has passed in an Exception + # subclass populated with non-ASCII data without special + # handling to display as a string. We need to handle this + # without raising a further exception. We do an + # approximation to what the Exception's standard str() + # output should be. + s = ' '.join([force_unicode(arg, encoding, strings_only, + errors) for arg in s]) + elif not isinstance(s, unicode): + # Note: We use .decode() here, instead of unicode(s, encoding, + # errors), so that if s is a SafeString, it ends up being a + # SafeUnicode at the end. + s = s.decode(encoding, errors) + except UnicodeDecodeError, e: + raise GPdf2SwfUnicodeDecodeError(s, *e.args) + #raise UnicodeDecodeError(*e.args) + return s + + diff --git a/wx/lib/wordwrap.py b/wx/lib/wordwrap.py new file mode 100644 index 0000000..4b1a5f8 --- /dev/null +++ b/wx/lib/wordwrap.py @@ -0,0 +1,97 @@ +#---------------------------------------------------------------------- +# Name: wx.lib.wordwrap +# Purpose: Contains a function to aid in word-wrapping some text +# +# Author: Robin Dunn +# +# Created: 15-Oct-2006 +# RCS-ID: $Id: wordwrap.py 54718 2008-07-19 18:57:26Z RD $ +# Copyright: (c) 2006 by Total Control Software +# Licence: wxWindows license +#---------------------------------------------------------------------- + +def wordwrap(text, width, dc, breakLongWords=True, margin=0): + """ + Returns a copy of text with newline characters inserted where long + lines should be broken such that they will fit within the given + width, with the given margin left and right, on the given `wx.DC` + using its current font settings. By default words that are wider + than the margin-adjusted width will be broken at the nearest + character boundary, but this can be disabled by passing ``False`` + for the ``breakLongWords`` parameter. + """ + + wrapped_lines = [] + text = text.split('\n') + for line in text: + pte = dc.GetPartialTextExtents(line) + wid = ( width - (2*margin+1)*dc.GetTextExtent(' ')[0] + - max([0] + [pte[i]-pte[i-1] for i in range(1,len(pte))]) ) + idx = 0 + start = 0 + startIdx = 0 + spcIdx = -1 + while idx < len(pte): + # remember the last seen space + if line[idx] == ' ': + spcIdx = idx + + # have we reached the max width? + if pte[idx] - start > wid and (spcIdx != -1 or breakLongWords): + if spcIdx != -1: + idx = spcIdx + 1 + wrapped_lines.append(' '*margin + line[startIdx : idx] + ' '*margin) + start = pte[idx] + startIdx = idx + spcIdx = -1 + + idx += 1 + + wrapped_lines.append(' '*margin + line[startIdx : idx] + ' '*margin) + + return '\n'.join(wrapped_lines) + + + +if __name__ == '__main__': + import wx + class TestPanel(wx.Panel): + def __init__(self, parent): + wx.Panel.__init__(self, parent) + + self.tc = wx.TextCtrl(self, -1, "", (20,20), (150,150), wx.TE_MULTILINE) + self.Bind(wx.EVT_TEXT, self.OnDoUpdate, self.tc) + self.Bind(wx.EVT_SIZE, self.OnSize) + + + def OnSize(self, evt): + wx.CallAfter(self.OnDoUpdate, None) + + + def OnDoUpdate(self, evt): + WIDTH = self.GetSize().width - 220 + HEIGHT = 200 + bmp = wx.EmptyBitmap(WIDTH, HEIGHT) + mdc = wx.MemoryDC(bmp) + mdc.SetBackground(wx.Brush("white")) + mdc.Clear() + mdc.SetPen(wx.Pen("black")) + mdc.SetFont(wx.Font(10, wx.SWISS, wx.NORMAL, wx.NORMAL)) + mdc.DrawRectangle(0,0, WIDTH, HEIGHT) + + text = wordwrap(self.tc.GetValue(), WIDTH-2, mdc, False) + #print repr(text) + mdc.DrawLabel(text, (1,1, WIDTH-2, HEIGHT-2)) + + del mdc + dc = wx.ClientDC(self) + dc.DrawBitmap(bmp, 200, 20) + + + app = wx.App(False) + frm = wx.Frame(None, title="Test wordWrap") + pnl = TestPanel(frm) + frm.Show() + app.MainLoop() + + diff --git a/wx/viewers/flexpaper.py b/wx/viewers/flexpaper.py index bc55b20..79177e1 100644 --- a/wx/viewers/flexpaper.py +++ b/wx/viewers/flexpaper.py @@ -24,7 +24,7 @@ from gui.fields import Choose, ChooseAndInt -order = 3 +order = 2 type = "custom" name = u"Flex Paper Viewer" desc = u"""Provides a light weight document viewer with: @@ -112,7 +112,7 @@ viewer_options = [ html_template = open('viewers/flexpaper/FlexPaperViewer.html').read() from gui.plugin import Plugin -import os +import os, sys class FlexPaper(Plugin): def __init__(self, swf, filename): @@ -138,16 +138,14 @@ class FlexPaper(Plugin): htmlfilename = self._swap_extension(self.__filename, "html") f = open(htmlfilename, "wb") - try: - f.write(html_template % template_vars) - except Exception, e: - print e + f.write(html_template % template_vars) f.close() import shutil opj = os.path.join - src = opj(os.path.dirname(__file__), 'flexpaper') + basedir = GPDF2SWF_BASEDIR + src = opj(basedir, 'viewers', 'flexpaper') dst = os.path.dirname(self.__filename) shutil.copy(opj(src, 'FlexPaperViewer.swf'), dst) diff --git a/wx/viewers/flexpaper/FlexPaper_source.tar.gz b/wx/viewers/flexpaper/FlexPaper_source.tar.gz new file mode 100644 index 0000000..d9b5e2d Binary files /dev/null and b/wx/viewers/flexpaper/FlexPaper_source.tar.gz differ diff --git a/wx/viewers/raw.py b/wx/viewers/raw.py index 8a92849..7e92457 100644 --- a/wx/viewers/raw.py +++ b/wx/viewers/raw.py @@ -24,7 +24,7 @@ from gui.fields import Choose -order = 0 +order = 4 type = "core" name = u"No Viewer" desc = (u'The SWF will be in "raw" format, with each page a seperate frame. ' diff --git a/wx/viewers/rfx.py b/wx/viewers/rfx.py index 433f153..adcb9cf 100644 --- a/wx/viewers/rfx.py +++ b/wx/viewers/rfx.py @@ -24,7 +24,8 @@ from gui.fields import Choose, ChooseAndInt -order = 2 +order = 0 +default = True type = "custom" name = u"rfx Viewer" desc = u"A more sophisticated viewer with zooming and scrolling." @@ -71,7 +72,7 @@ html_template = """ """ from gui.plugin import Plugin -import os +import os, sys class Rfx(Plugin): def __init__(self, swf, filename): @@ -86,7 +87,10 @@ class Rfx(Plugin): setattr(self, "_%s" % opt.name, opt.value) def after_save(self, page): - viewerfilename = self._swap_extension(__file__, "swf", self._flashversion) + basedir = GPDF2SWF_BASEDIR + viewerfilename = os.path.join(basedir, + "viewers", + "rfx%s.swf" % self._flashversion) self.swfcombine( u"%s" % viewerfilename, diff --git a/wx/viewers/simple.py b/wx/viewers/simple.py index dd59332..443c620 100644 --- a/wx/viewers/simple.py +++ b/wx/viewers/simple.py @@ -24,7 +24,7 @@ from gui.fields import Hidden, Choose -order = 1 +order = 3 type = "core" name = u"Simple Viewer" desc = (u"A tiny viewer, which attaches directly to the SWF, " diff --git a/wx/viewers/technoargia.py b/wx/viewers/technoargia.py index 7d6afa2..52cc488 100644 --- a/wx/viewers/technoargia.py +++ b/wx/viewers/technoargia.py @@ -24,7 +24,7 @@ from gui.fields import Choose, ChooseAndInt, Hidden -order = 4 +order = 1 type = "custom" name = u"technoargia Viewer" desc = (u"Simple viewer with home link from Laurent Lalanne" @@ -71,7 +71,7 @@ html_template = """ """ from gui.plugin import Plugin -import os +import os, sys class Technoargia(Plugin): def __init__(self, swf, filename): @@ -86,7 +86,10 @@ class Technoargia(Plugin): setattr(self, "_%s" % opt.name, opt.value) def after_save(self, page): - viewerfilename = self._swap_extension(__file__, "swf") + basedir = GPDF2SWF_BASEDIR + viewerfilename = os.path.join(basedir, + "viewers", + "technoargia.swf") self.swfcombine( u"%s" % viewerfilename,