From 21cb03fcbc200bd6384647c8774e380da2d37629 Mon Sep 17 00:00:00 2001 From: Eygene Ryabinkin Date: Sat, 8 Oct 2011 23:06:05 +0400 Subject: [PATCH] Xpdf: update to 3.03 For changed items since 3.02 look at the CHANGES entries at http://foolabs.com/xpdf/CHANGES: the list is too large to included here. Signed-off-by: Eygene Ryabinkin --- graphics/xpdf/Makefile | 15 +- graphics/xpdf/distinfo | 14 +- graphics/xpdf/files/extra-patch-draw-annotations | 2077 ++++++++++++++++++++++ graphics/xpdf/files/patch-Makefile.in | 12 +- graphics/xpdf/files/patch-configure | 15 - graphics/xpdf/files/patch-configure.in | 11 +- graphics/xpdf/files/patch-fofi_FoFiTrueType.cc | 11 - graphics/xpdf/files/patch-splash_Splash.cc | 14 - graphics/xpdf/files/patch-xpdf::Makefile.in | 12 +- graphics/xpdf/pkg-plist | 1 + 10 files changed, 2103 insertions(+), 79 deletions(-) create mode 100644 graphics/xpdf/files/extra-patch-draw-annotations delete mode 100644 graphics/xpdf/files/patch-configure delete mode 100644 graphics/xpdf/files/patch-fofi_FoFiTrueType.cc delete mode 100644 graphics/xpdf/files/patch-splash_Splash.cc diff --git a/graphics/xpdf/Makefile b/graphics/xpdf/Makefile index 7ecbf7b..e8aa4fc 100644 --- a/graphics/xpdf/Makefile +++ b/graphics/xpdf/Makefile @@ -6,18 +6,12 @@ # PORTNAME= xpdf -PORTVERSION= 3.02 -PORTREVISION= 16 +PORTVERSION= 3.03 CATEGORIES= graphics print MASTER_SITES= ftp://ftp.foolabs.com/pub/xpdf/ \ ${MASTER_SITE_TEX_CTAN} MASTER_SITE_SUBDIR= support/xpdf -PATCH_SITES= ftp://ftp.foolabs.com/pub/xpdf/ -PATCHFILES= xpdf-3.02pl1.patch xpdf-3.02pl2.patch xpdf-3.02pl3.patch \ - xpdf-3.02pl4.patch xpdf-3.02pl5.patch -PATCH_DIST_STRIP= -p1 - MAINTAINER= araujo@FreeBSD.org COMMENT= Display PDF files, and convert them to other formats @@ -31,6 +25,7 @@ CONFLICTS= poppler-utils-0.* USE_GMAKE= yes USE_AUTOTOOLS= autoconf CPPFLAGS+= -I${LOCALBASE}/include +CXXFLAGS+= -I${LOCALBASE}/include LDFLAGS+= -L${LOCALBASE}/lib CONFIGURE_ARGS= --enable-opi \ --with-t1-library="${LOCALBASE}/lib" \ @@ -56,7 +51,8 @@ CONFIGURE_ARGS+=--without-libpaper-library CONFIGURE_ARGS+= --enable-a4-paper .endif -MAN1= pdffonts.1 \ +MAN1= pdfdetach.1 \ + pdffonts.1 \ pdfimages.1 \ pdfinfo.1 \ pdftoppm.1 \ @@ -79,8 +75,7 @@ PLIST_SUB+= X11="" .if defined(WITH_DRAW) # add support for adding/deleting drawing annotations in PDF files -PATCH_SITES+= http://info.iet.unipi.it/~luigi/FreeBSD/ -PATCHFILES+= patch-zz-xpdf-annot.20080728a +EXTRA_PATCHES+= ${FILESDIR}/extra-patch-draw-annotations post-patch: ${REINPLACE_CMD} -e 's|undef USE_COMBO_BOX|define USE_COMBO_BOX 1|' \ diff --git a/graphics/xpdf/distinfo b/graphics/xpdf/distinfo index ba8d1cb..6e12a23 100644 --- a/graphics/xpdf/distinfo +++ b/graphics/xpdf/distinfo @@ -1,14 +1,4 @@ -SHA256 (xpdf-3.02.tar.gz) = b33a7d56f454c331ae50996f989e86c9166e57af97b74de28cddf3d51ac11f00 -SIZE (xpdf-3.02.tar.gz) = 674912 -SHA256 (xpdf-3.02pl1.patch) = 58f613b00b414a86aa776b76fcd899bb415e4ee4edc2184c8a7c4ed1004dbbf3 -SIZE (xpdf-3.02pl1.patch) = 1050 -SHA256 (xpdf-3.02pl2.patch) = d1c1d887b0b8a5283f04f825e44f085f2e92daf7b518889acf1bc89ea07ed9d9 -SIZE (xpdf-3.02pl2.patch) = 20843 -SHA256 (xpdf-3.02pl3.patch) = 594ce8fbd23bff29eacddfae3533c63c7e86b4a24f7d45e44f1937d3d19e534b -SIZE (xpdf-3.02pl3.patch) = 30727 -SHA256 (xpdf-3.02pl4.patch) = b0844395411318766ef750987787f778231e94bc15f04f7f7d16f41fd58188b0 -SIZE (xpdf-3.02pl4.patch) = 6982 -SHA256 (xpdf-3.02pl5.patch) = 92fcb3083a19e37b3096978043faea8c777e7aaeca3834b832d99bc2af3171ba -SIZE (xpdf-3.02pl5.patch) = 1065 +SHA256 (xpdf-3.03.tar.gz) = 02cf63d8f6326eda644096cd0f969e1588702ad87222c1e9388a93c270fbceca +SIZE (xpdf-3.03.tar.gz) = 795537 SHA256 (patch-zz-xpdf-annot.20080728a) = c96308c0fb90450251a6f8a19b5436a5fd5d70b4d6af2626ba85d3c4b7300fe1 SIZE (patch-zz-xpdf-annot.20080728a) = 69092 diff --git a/graphics/xpdf/files/extra-patch-draw-annotations b/graphics/xpdf/files/extra-patch-draw-annotations new file mode 100644 index 0000000..0a90d13 --- /dev/null +++ b/graphics/xpdf/files/extra-patch-draw-annotations @@ -0,0 +1,2077 @@ +From 357979d0f29f771762d283ca8b7871ce1d7d13b3 Mon Sep 17 00:00:00 2001 +From: Eygene Ryabinkin +Date: Sun, 9 Oct 2011 16:49:18 +0400 +Subject: [PATCH] Add support for drawing annotations + +Port patch of Luigi Rizzo and his students to 3.03. + +Signed-off-by: Eygene Ryabinkin +--- + CHANGES | 55 +++++++ + doc/xpdf.1 | 2 +- + xpdf/Annot.cc | 60 ++++++++ + xpdf/Annot.h | 8 + + xpdf/GlobalParams.cc | 19 ++- + xpdf/GlobalParams.h | 3 + + xpdf/PDFCore.cc | 150 ++++++++++++++++++++ + xpdf/PDFCore.h | 34 +++++ + xpdf/PDFDoc.cc | 324 ++++++++++++++++++++++++++++++++++++++++++ + xpdf/PDFDoc.h | 12 ++ + xpdf/Page.cc | 8 + + xpdf/Page.h | 11 ++ + xpdf/XPDFCore.cc | 267 ++++++++++++++++++++++++++++++++++- + xpdf/XPDFCore.h | 17 ++- + xpdf/XPDFViewer.cc | 382 ++++++++++++++++++++++++++++++++++++++++++++++++-- + xpdf/XPDFViewer.h | 21 +++ + 16 files changed, 1347 insertions(+), 26 deletions(-) + +diff --git a/CHANGES b/CHANGES +index cde9756..b9b8b71 100644 +--- CHANGES ++++ CHANGES +@@ -2147,3 +2147,58 @@ Implement embedding of external 16-bit fonts (without subsetting) in + PostScript output. + Added the minLineWidth xpdfrc command. + Added warning messages for font substitutions. ++ ++ ++3.03-annot (3.02-annot 2008-jul-15, 3.03 port 2011-oct-08) ++------------------------ ++This patch implements editable annotations (currently ++only freehand drawing) for xpdf. ++ ++An annotation requires three components to be added ++to the pdf file: ++ +++ the inklist, which contains point coordinates meant to ++ be used at 'selection' time; +++ the 'stream' contains the points to be plotted +++ the xref contains references to the objects ++ ++The code in this patch ++./xpdf/Annot.cc ../../work/xpdf-3.03/xpdf/Annot.cc ++./xpdf/Annot.h ../../work/xpdf-3.03/xpdf/Annot.h ++ code to support inklist and selection ++ ++./xpdf/GlobalParams.cc ../../work/xpdf-3.03/xpdf/GlobalParams.cc ++./xpdf/GlobalParams.h ../../work/xpdf-3.03/xpdf/GlobalParams.h ++ new bindings for the keys, basically mouse release and delete ++ ++./xpdf/PDFCore.cc ../../work/xpdf-3.03/xpdf/PDFCore.cc ++./xpdf/PDFCore.h ../../work/xpdf-3.03/xpdf/PDFCore.h ++ ++ code to create the various pieces of the annotation. ++ There are three strings used to hold the 'annotation', ++ the stream and the 'appreareance' object, which are built ++ as the user moves the mouse with the left key pressed. ++ ++./xpdf/PDFDoc.cc ../../work/xpdf-3.03/xpdf/PDFDoc.cc ++./xpdf/PDFDoc.h ../../work/xpdf-3.03/xpdf/PDFDoc.h ++ Code to manipulate the document. ++ addTempAnnotation() adds the pieces of a new annotation ++ to an existing file, making a temporary copy if necessary; ++ ++ delTempAnnotation() removes an annotation, for simplicity ++ it does so by overwriting the blocks with whitespace so that ++ the xref does not change. ++ ++./xpdf/Page.cc ../../work/xpdf-3.03/xpdf/Page.cc ++./xpdf/Page.h ../../work/xpdf-3.03/xpdf/Page.h ++ some bits to support selection ++ ++./xpdf/XPDFCore.cc ../../work/xpdf-3.03/xpdf/XPDFCore.cc ++./xpdf/XPDFCore.h ../../work/xpdf-3.03/xpdf/XPDFCore.h ++ creation of the annotation, similar to PDFCore.cc ++ Also implement a dialog box. ++ ++./xpdf/XPDFViewer.cc ../../work/xpdf-3.03/xpdf/XPDFViewer.cc ++./xpdf/XPDFViewer.h ../../work/xpdf-3.03/xpdf/XPDFViewer.h ++ various GUI items, such as the box to select color and width, ++ and hooks to call the 'save' option when exiting. +diff --git a/doc/xpdf.1 b/doc/xpdf.1 +index 05c0af9..fb6f260 100644 +--- doc/xpdf.1 ++++ doc/xpdf.1 +@@ -765,7 +765,7 @@ The default key bindings are as follows: + bind end any scrollToBottomRight + bind pgup any pageUp + bind backspace any pageUp +- bind delete any pageUp ++ bind delete any deleteAnnotation + bind pgdn any pageDown + bind space any pageDown + bind left any scrollLeft(16) +diff --git a/xpdf/Annot.cc b/xpdf/Annot.cc +index 887157f..6917674 100644 +--- xpdf/Annot.cc ++++ xpdf/Annot.cc +@@ -264,6 +264,10 @@ Annot::Annot(PDFDoc *docA, Dict *dict, Ref *refA) { + } + asObj.free(); + ++ //----- parse the inkList ++ ++ dict->lookup("InkList", &inkList); ++ + //----- get the annotation appearance + + if (apObj.isDict()) { +@@ -295,6 +299,7 @@ Annot::~Annot() { + delete appearanceState; + } + appearance.free(); ++ inkList.free(); + if (appearBuf) { + delete appearBuf; + } +@@ -678,6 +683,61 @@ void Annot::generateFieldAppearance(Dict *field, Dict *annot, Dict *acroForm) { + mkObj.free(); + } + ++static void get_coord(Object &array, int pos, double &ret) { ++ Object coord; ++ array.arrayGet(pos, &coord); ++ if (coord.isReal()) { ++ ret = coord.getReal(); ++ } ++ coord.free(); ++} ++ ++/* return true if the point falls within the annotation */ ++GBool Annot::selectAnnotation(double ux, double uy) { ++ int i, j; ++ ++ if (!inkList.isArray()) { ++ return gFalse; ++ } ++ // scan the array and see if the point we clicked is close to any ++ // segment connecting two points of the annotation ++ int ilength = inkList.arrayGetLength(); ++ ++ for (i = 0; i < ilength; i++) { ++ Object array; ++ if (!inkList.arrayGet(i, &array)->isArray()) ++ continue; ++ ++ int alength = array.arrayGetLength(); ++ double ox = -1, oy = -1; ++ for (j = 0; j < alength; j += 2) { ++ if (ox == -1 || oy == -1) { // first point ++ get_coord(array, j, ox); ++ get_coord(array, j + 1, oy); ++ continue; ++ } ++ double cx = ox, cy = oy; // default ++ get_coord(array, j, cx); ++ get_coord(array, j + 1, cy); ++ if (ox == cx && oy == cy) // same point, go on ++ continue; ++ // below, compute a rectangle around the segment and see if the ++ // point falls into the rectangle. ++ double dx = cx - ox; ++ double dy = cy - oy; ++ double l = sqrt(dx*dx + dy*dy); ++ double x = ((ux - ox)*dx + (uy - oy)*dy)/l; ++ double y = (-(ux - ox)*dy + (uy - oy)*dx)/l; ++ ++ if (x >= -2 && x<= l + 2 && y >= -4 && y <= 4) ++ return gTrue; ++ ox = cx; ++ oy = cy; ++ } ++ } ++ return gFalse; ++} ++ + // Set the current fill or stroke color, based on (which should + // have 1, 3, or 4 elements). If is +1, color is brightened; + // if is -1, color is darkened; otherwise color is not +diff --git a/xpdf/Annot.h b/xpdf/Annot.h +index 987e80e..dac6c7c 100644 +--- xpdf/Annot.h ++++ xpdf/Annot.h +@@ -80,6 +80,13 @@ public: + // Get appearance object. + Object *getAppearance(Object *obj) { return appearance.fetch(xref, obj); } + ++ // Get annotation rectangle ++ void getRectangle(double *Xmin, double *Ymin, double *Xmax, double *Ymax) ++ { *Xmin = xMin; *Ymin = yMin; *Xmax = xMax; *Ymax = yMax; } ++ ++ // check if the given point is within the annotation rectangle ++ GBool selectAnnotation(double ux, double uy); ++ + AnnotBorderStyle *getBorderStyle() { return borderStyle; } + + GBool match(Ref *refA) +@@ -112,6 +119,7 @@ private: + GString *appearanceState; // appearance state name + Object appearance; // a reference to the Form XObject stream + // for the normal appearance ++ Object inkList; // a reference to the InkList array + GString *appearBuf; + double xMin, yMin, // annotation rectangle + xMax, yMax; +diff --git a/xpdf/GlobalParams.cc b/xpdf/GlobalParams.cc +index 63e932b..33425dc 100644 +--- xpdf/GlobalParams.cc ++++ xpdf/GlobalParams.cc +@@ -466,6 +466,18 @@ KeyBinding::KeyBinding(int codeA, int modsA, int contextA, + cmds->append(new GString(cmd1)); + } + ++KeyBinding::KeyBinding(int codeA, int modsA, int contextA, ++ const char *cmd0, const char *cmd1, ++ const char *cmd2) { ++ code = codeA; ++ mods = modsA; ++ context = contextA; ++ cmds = new GList(); ++ cmds->append(new GString(cmd0)); ++ cmds->append(new GString(cmd1)); ++ cmds->append(new GString(cmd2)); ++} ++ + KeyBinding::KeyBinding(int codeA, int modsA, int contextA, GList *cmdsA) { + code = codeA; + mods = modsA; +@@ -819,10 +831,9 @@ void GlobalParams::createDefaultKeyBindings() { + + //----- mouse buttons + keyBindings->append(new KeyBinding(xpdfKeyCodeMousePress1, xpdfKeyModNone, +- xpdfKeyContextAny, "startSelection")); ++ xpdfKeyContextAny, "startDraw", "startSelection")); + keyBindings->append(new KeyBinding(xpdfKeyCodeMouseRelease1, xpdfKeyModNone, +- xpdfKeyContextAny, "endSelection", +- "followLinkNoSel")); ++ xpdfKeyContextAny, "endDraw", "endSelection", "followLinkNoSel")); + keyBindings->append(new KeyBinding(xpdfKeyCodeMousePress2, xpdfKeyModNone, + xpdfKeyContextAny, "startPan")); + keyBindings->append(new KeyBinding(xpdfKeyCodeMouseRelease2, xpdfKeyModNone, +@@ -855,7 +866,7 @@ void GlobalParams::createDefaultKeyBindings() { + keyBindings->append(new KeyBinding(xpdfKeyCodeBackspace, xpdfKeyModNone, + xpdfKeyContextAny, "pageUp")); + keyBindings->append(new KeyBinding(xpdfKeyCodeDelete, xpdfKeyModNone, +- xpdfKeyContextAny, "pageUp")); ++ xpdfKeyContextAny, "deleteAnnotation")); + keyBindings->append(new KeyBinding(xpdfKeyCodePgDn, xpdfKeyModNone, + xpdfKeyContextAny, "pageDown")); + keyBindings->append(new KeyBinding(' ', xpdfKeyModNone, +diff --git a/xpdf/GlobalParams.h b/xpdf/GlobalParams.h +index e2da5ca..635faf3 100644 +--- xpdf/GlobalParams.h ++++ xpdf/GlobalParams.h +@@ -112,6 +112,9 @@ public: + KeyBinding(int codeA, int modsA, int contextA, const char *cmd0); + KeyBinding(int codeA, int modsA, int contextA, + const char *cmd0, const char *cmd1); ++ KeyBinding(int codeA, int modsA, int contextA, ++ const char *cmd0, const char *cmd1, ++ const char *cmd2); + KeyBinding(int codeA, int modsA, int contextA, GList *cmdsA); + ~KeyBinding(); + }; +diff --git a/xpdf/PDFCore.cc b/xpdf/PDFCore.cc +index 6435815..0c66fa7 100644 +--- xpdf/PDFCore.cc ++++ xpdf/PDFCore.cc +@@ -84,6 +84,8 @@ PDFCore::PDFCore(SplashColorMode colorModeA, int bitmapRowPadA, + int i; + + doc = NULL; ++ modified = gFalse; ++ temporary = gFalse; + continuousMode = globalParams->getContinuousView(); + drawAreaWidth = drawAreaHeight = 0; + maxPageW = totalDocH = 0; +@@ -92,12 +94,19 @@ PDFCore::PDFCore(SplashColorMode colorModeA, int bitmapRowPadA, + midPage = 0; + scrollX = scrollY = 0; + zoom = defZoom; ++ color[0] = 0xff; color[1] = color[2] = 0x00; ++ thickness = 1; + dpi = 0; + rotate = 0; + + selectPage = 0; + selectULX = selectLRX = 0; + selectULY = selectLRY = 0; ++ ++ drawing = gFalse; ++ lastDrawnX = lastDrawnY = -1; ++ lastStreamX = lastStreamY = -1; ++ + dragging = gFalse; + lastDragLeft = lastDragTop = gTrue; + selectXorColor[0] = selectXorColor[1] = selectXorColor[2] = 0; +@@ -910,6 +919,8 @@ void PDFCore::needTile(PDFCorePage *page, int x, int y) { + GBool PDFCore::gotoNextPage(int inc, GBool top) { + int pg, scrollYA; + ++ if (modified) // or look at *doc->getAnnotationObject() ++ finalizeDraw(); + if (!doc || doc->getNumPages() == 0 || topPage >= doc->getNumPages()) { + return gFalse; + } +@@ -1547,6 +1558,145 @@ void PDFCore::moveSelection(int pg, int x, int y) { + newSelectLRX, newSelectLRY); + } + ++// finalize a pending draw command, by collating all pieces of info ++// into the final file. ++GBool PDFCore::finalizeDraw() { ++ int pg; ++ GString *s = *doc->getAnnotationObject(); ++ if (!s) ++ return gFalse; ++ // add the bounding box ++ s->appendf( ++ "]\n"\ ++ "/Rect[{0:.1f} {1:.1f} {2:.1f} {3:.1f}]\n", ++ rectXmin - thickness, rectYmin - thickness, rectXmax + thickness, rectYmax + thickness); ++ ++ *doc->getAppereanceObject() = GString::format( ++ "<<\n"\ ++ "/Matrix [1.0 0.0 0.0 1.0 {0:.1f} {1:.1f}]\n"\ ++ "/Subtype /Form\n"\ ++ "/Length {2:d}\n"\ ++ "/FormType 1\n"\ ++ "/Type /XObject\n"\ ++ "/BBox[{3:.1f} {4:.1f} {5:.1f} {6:.1f}]\n"\ ++ ">>\n"\ ++ "stream\n"\ ++ "{7:t}"\ ++ "endstream\n"\ ++ "endobject\n", ++ -rectXmin + thickness, -rectYmin + thickness, ++ (*doc->getAppereanceStream())->getLength(), ++ rectXmin - thickness, rectYmin - thickness, rectXmax + thickness, rectYmax + thickness, ++ (*doc->getAppereanceStream())); ++ ++ pg = topPage; ++ doc->addTempAnnotation(pg, getTemporary()); ++ GString *temp = doc->getFileName()->copy(); ++ if (getTemporary() == gFalse) ++ temp->append(".temp"); ++ setTemporary(gTrue); ++ setModified(gFalse); ++ loadFile(temp); ++ displayPage(pg, getZoom(), getRotate(), gFalse, gFalse); ++ delete temp; ++ return gTrue; ++} ++ ++/* draw the next point */ ++void PDFCore::drawPoint(int pg, int x, int y) { ++ //int newSelectULX, newSelectULY, newSelectLRX, newSelectLRY; ++ GBool haveSel; ++ SplashColor xorColor; ++ PDFCorePage *page; ++ SplashPattern *pattern; ++ int i; ++ ++ haveSel = selectULX != selectLRX && selectULY != selectLRY; ++ ++ if (haveSel) { ++ xorColor[0] = xorColor[1] = xorColor[2] = 0xff; ++ xorRectangle(selectPage, selectULX, selectULY, selectLRX, selectLRY, ++ new SplashSolidColor(xorColor)); ++ } ++ page = findPage(pg); ++ if (!page) ++ return; ++ if (haveSel) { ++ redrawWindow(page->xDest + selectULX, page->yDest + selectULY, ++ selectLRX - selectULX + 1, selectLRY - selectULY + 1, gFalse); ++ } ++ selectULX = selectLRX = selectULY = selectLRY = 0; ++ xorColor[0] = color[0]; ++ xorColor[1] = color[1]; ++ xorColor[2] = color[2]; ++ pattern = new SplashSolidColor(xorColor); ++ ++ // The page can have multiple tiles, so we work on each of them. ++ // In practice, most of the times we have only one tile. ++ for (i = 0; i < page->tiles->getLength(); ++i) { ++ int xi = 0, yi = 0, wi = 0, hi = 0; ++ PDFCoreTile *tile = (PDFCoreTile *)page->tiles->get(i); ++ Splash *splash = new Splash(tile->bitmap, gFalse); ++ ++ splash->setFillPattern(pattern->copy()); ++ if (lastDrawnX != -1 && lastDrawnY != -1) { ++ // draw a line from the previous point (lastDrawnX, lastDrawnY) ++ // to the current one. ++ SplashCoord xx0 = (SplashCoord)(lastDrawnX - tile->xMin); ++ SplashCoord yy0 = (SplashCoord)(lastDrawnY - tile->yMin); ++ SplashCoord xx1 = (SplashCoord)(x - tile->xMin); ++ SplashCoord yy1 = (SplashCoord)(y - tile->yMin); ++ SplashPath *path = new SplashPath(); ++ path->moveTo(xx0, yy0); ++ path->lineTo(xx1, yy1); ++ path->close(); ++ splash->fill(path, gTrue); ++ delete path; ++ delete splash; ++ ++ // the following code computes the size of the region to redraw ++ // which goes between min(x, lastDrawnX) and max(...) ++ // on both coordinates. ++ // Also if the region is outside the tile, we truncate it. ++ if (x < lastDrawnX) { ++ xi = x - tile->xMin; ++ wi = lastDrawnX - x; ++ } else { ++ xi = lastDrawnX - tile->xMin; ++ wi = x - lastDrawnX; ++ } ++ if (xi < 0) { ++ wi += xi; ++ xi = 0; ++ } ++ if (xi + wi > tile->bitmap->getWidth()) { ++ wi = tile->bitmap->getWidth() - xi; ++ } ++ if (y < lastDrawnY) { ++ yi = y - tile->yMin; ++ hi = lastDrawnY - y; ++ } else { ++ yi = lastDrawnY - tile->yMin; ++ hi = y - lastDrawnY; ++ } ++ if (yi < 0) { ++ hi += yi; ++ yi = 0; ++ } ++ if (yi + hi > tile->bitmap->getHeight()) { ++ hi = tile->bitmap->getHeight() - yi; ++ } ++ wi = wi ? wi : 1; // make sure size is at least 1 pixel ++ hi = hi ? hi : 1; ++ updateTileData(tile, xi, yi, wi, hi, gTrue); ++ redrawWindow(page->xDest + xi, page->yDest + yi, wi, hi, gFalse); ++ } ++ lastDrawnX = x; ++ lastDrawnY = y; ++ } ++ delete pattern; ++} ++ + void PDFCore::xorRectangle(int pg, int x0, int y0, int x1, int y1, + SplashPattern *pattern, PDFCoreTile *oneTile) { + Splash *splash; +diff --git a/xpdf/PDFCore.h b/xpdf/PDFCore.h +index 264756f..53e61b9 100644 +--- xpdf/PDFCore.h ++++ xpdf/PDFCore.h +@@ -204,6 +204,10 @@ public: + GBool getSelection(int *pg, double *ulx, double *uly, + double *lrx, double *lry); + ++ // Note drawing ++ GBool finalizeDraw(); ++ void drawPoint(int pg, int x, int y); ++ + // Text extraction. + GString *extractText(int pg, double xMin, double yMin, + double xMax, double yMax); +@@ -240,6 +244,11 @@ public: + int getPageNum() { return topPage; } + double getZoom() { return zoom; } + double getZoomDPI() { return dpi; } ++ void setColor(Guchar R, Guchar G, Guchar B) { ++ color[0] = R; color[1] = G; color[2] = B; ++ } ++ void setThickness(int value) { thickness = value; } ++ + int getRotate() { return rotate; } + GBool getContinuousMode() { return continuousMode; } + virtual void setReverseVideo(GBool reverseVideoA); +@@ -251,6 +260,10 @@ public: + int getDrawAreaHeight() { return drawAreaHeight; } + virtual void setBusyCursor(GBool busy) = 0; + LinkAction *findLink(int pg, double x, double y); ++ GBool getModified() { return modified; } ++ void setModified(GBool mod) { modified = mod; } ++ GBool getTemporary() { return temporary; } ++ void setTemporary(GBool mod) { temporary = mod; } + + protected: + +@@ -280,6 +293,9 @@ protected: + virtual GBool checkForNewFile() { return gFalse; } + + PDFDoc *doc; // current PDF file ++ GBool modified; // set if the document need to be saved ++ // before quitting ++ GBool temporary; // set if the current document is temporary + GBool continuousMode; // false for single-page mode, true for + // continuous mode + int drawAreaWidth, // size of the PDF display area +@@ -299,12 +315,30 @@ protected: + double zoom; // current zoom level, in percent of 72 dpi + double dpi; // current zoom level, in DPI + int rotate; // current page rotation ++ Guchar color[3]; // current color used for drawing annotations ++ int thickness; // current thickness used for drawing annotations + + int selectPage; // page number of current selection + int selectULX, // coordinates of current selection, + selectULY, // in device space -- (ULX==LRX || ULY==LRY) + selectLRX, // means there is no selection + selectLRY; ++ ++ GBool drawing; // set while drawing is happening; everytime we release ++ // the mouse button, drawing is reset ++ int lastDrawnX, // coordinates of the last drawed point: used for rendering ++ lastDrawnY; // on the screen ++ double lastStreamX, // coordinates of the last stored point inside the ++ lastStreamY; // temporary file of the annotation stream ++ int streamSize; ++ ++ int numDrawnPoints; // counter for the points added to the temp stream; ++ ++ double rectXmin, // coordinates of the bounding box for the annotation ++ rectYmin, // we are drawing at execution time ++ rectXmax, ++ rectYmax; ++ + GBool dragging; // set while selection is being dragged + GBool lastDragLeft; // last dragged selection edge was left/right + GBool lastDragTop; // last dragged selection edge was top/bottom +diff --git a/xpdf/PDFDoc.cc b/xpdf/PDFDoc.cc +index b20ef2c..3af84b8 100644 +--- xpdf/PDFDoc.cc ++++ xpdf/PDFDoc.cc +@@ -55,6 +55,7 @@ PDFDoc::PDFDoc(GString *fileNameA, GString *ownerPassword, + #ifdef WIN32 + int n, i; + #endif ++ annotationObject = appereanceObject = appereanceStream = NULL; + + ok = gFalse; + errCode = errNone; +@@ -106,6 +107,7 @@ PDFDoc::PDFDoc(GString *fileNameA, GString *ownerPassword, + delete fileName2; + } + #endif ++ annotationObject = appereanceObject = appereanceStream = NULL; + + // create stream + obj.initNull(); +@@ -200,6 +202,7 @@ PDFDoc::PDFDoc(BaseStream *strA, GString *ownerPassword, + outline = NULL; + #endif + optContent = NULL; ++ annotationObject = appereanceObject = appereanceStream = NULL; + ok = setup(ownerPassword, userPassword); + } + +@@ -470,6 +473,327 @@ GBool PDFDoc::saveAs(GString *name) { + return gTrue; + } + ++// copy data from str to tempFp. If len == -1 copy to the end ++// of file, otherwise copy the specified number of bytes. ++static int stream_copy(BaseStream *str, FILE *tempFp, int len) { ++ int i; ++ for (i = 0; len == -1 || i < len; i++) { ++ int c = str->getChar(); ++ if (c == EOF) ++ break; ++ fputc(c, tempFp); ++ } ++ return i; // number of bytes written ++} ++ ++// make a copy of the stream into a temp file, ++// increase len by the amount of bytes written ++static FILE *make_temp_copy(GString *fileName, BaseStream *str, int *len) ++{ ++ int dummy = 0; ++ if (len == NULL) ++ len = &dummy; ++ GString *tempFileName = fileName->copy()->append(".temp"); ++ FILE *tempFp = fopen(tempFileName->getCString(), "wb"); ++ delete tempFileName; ++ if (tempFp == NULL) /*ERROR*/ ++ return NULL; ++ str->reset(); ++ *len += stream_copy(str, tempFp, -1); // copy to EOF ++ str->close(); ++ return tempFp; ++} ++ ++// called when the user closes an annotation so it is saved. ++// We need to make a temporary copy, and append the various pieces. ++GString *PDFDoc::addTempAnnotation(int pg, GBool temporary) { ++ int written = 0, c, ++ offPage = 0, ++ offAnnArr = 0, ++ offAnn, ++ offAp, start, end, numObjects = xref->getNumObjects(); ++ ++ GString *tempFileName; ++ // make a temporary copy of the whole file. ++ FILE *tempFp = make_temp_copy(fileName, str, &written); ++ if (tempFp == NULL) //ERROR ++ return NULL; ++ ++ Page *page = catalog->getPage(pg); ++ Object obj; ++ Annots *annotList = new Annots(this, page->getAnnots(&obj)); ++ obj.free(); ++ Ref *ref = catalog->getPageRef(pg); ++ XRefEntry *pageRef = xref->getEntry(ref->num); ++ str->reset(); ++ Lexer *lexer = new Lexer(xref, str); ++ ++ if (annotList->getNumAnnots() == 0) { ++ // there are no annotations yet. ++ offPage = written; ++ lexer->setPos(pageRef->offset); ++ start = lexer->getPos(); ++ lexer->getObj(&obj); // get page number ++ obj.free(); ++ lexer->getObj(&obj); // get page gen ++ obj.free(); ++ lexer->getObj(&obj); // get "obj" ++ obj.free(); ++ lexer->getObj(&obj); // get begin of dictionary ++ obj.free(); ++ ++ end = lexer->getPos(); ++ lexer->setPos(start); ++ written += stream_copy(str, tempFp, end - start); ++ start = end; ++ written += fprintf(tempFp, " /Annots [ %d 0 R ]", numObjects); ++ } else { ++ // we do have an annotation, either object or inline. ++ // Locate the beginning of the array and add the new entry there. ++ if (page->getAnnotNum() != -1) { // annotation object, jump there. ++ offAnnArr = written; ++ lexer->setPos(xref->getEntry(page->getAnnotNum())->offset); ++ start = lexer->getPos(); ++ lexer->getObj(&obj); // get annotation array number ++ obj.free(); ++ lexer->getObj(&obj); // get annotation array gen ++ obj.free(); ++ lexer->getObj(&obj); // get "obj" ++ obj.free(); ++ lexer->getObj(&obj); // get begin of array "[" ++ obj.free(); ++ } else { ++ // the annotation is inline. Again, move to the beginning of ++ // the object and write the new annotation in the first position. ++ offPage = written; ++ lexer->setPos(pageRef->offset); ++ start = lexer->getPos(); ++ while (1) { ++ lexer->getObj(&obj); ++ if (obj.isName() && !strncmp("Annots", obj.getName(), 6)) { ++ obj.free(); ++ lexer->getObj(&obj); // begin of array "[" ++ obj.free(); ++ break; ++ } ++ obj.free(); ++ } ++ } ++ // common part to update an existing annotation. ++ end = lexer->getPos(); ++ lexer->setPos(start); ++ written += stream_copy(str, tempFp, end - start); ++ start = end; ++ written += fprintf(tempFp, " %d 0 R ", numObjects); ++ } ++ // copy till "endobj" ++ while (1) { ++ lexer->getObj(&obj); ++ if (obj.isCmd() && !strncmp("endobj", obj.getCmd(), 6)) { ++ obj.free(); ++ break; ++ } ++ obj.free(); ++ } ++ end = lexer->getPos(); ++ ++ lexer->setPos(start); ++ written += stream_copy(str, tempFp, end - start); ++ fputc('\n', tempFp); ++ written++; ++ // Add annotation object ++ offAnn = written; ++ written += fprintf(tempFp, "%d 0 obj\n", numObjects); ++ written += fprintf(tempFp, "%s", annotationObject->getCString()); ++ written += fprintf(tempFp, "/AP\n<<\n/N %d 0 R\n>>\n>>\nendobj\n", numObjects + 1); ++ numObjects++; ++ ++ // Add appereance object ++ offAp = written; ++ written += fprintf(tempFp, "%d 0 obj\n", numObjects); ++ written += fprintf(tempFp, "%s", appereanceObject->getCString()); ++ delete annotationObject; ++ delete appereanceObject; ++ delete appereanceStream; ++ /* XREF */ ++ ++ int the_ref; // reference to put in the xref ++ int the_offset; // offset to put in the xref ++ if (annotList->getNumAnnots() == 0) { // no pre-existing annotation ++ the_ref = ref->num; ++ the_offset = offPage; ++ } else if (page->getAnnotNum() != -1) { ++ // preexisting annotation array ++ the_ref = page->getAnnotNum(); ++ the_offset = offAnnArr; ++ } else { ++ // inline annotation ++ the_ref = ref->num; ++ the_offset = offPage; ++ } ++ fprintf(tempFp, ++ "xref\n"\ ++ "%d 1\n"\ ++ "%010d 00000 n \n"\ ++ "%d 2\n"\ ++ "%010d 00000 n \n"\ ++ "%010d 00000 n \n"\ ++ "trailer\n"\ ++ "<<\n"\ ++ "/Size %d\n"\ ++ "/Prev %d\n"\ ++ "/Root %d %d R\n"\ ++ ">>\n"\ ++ "startxref\n"\ ++ "%d\n"\ ++ "%%%%EOF\n", ++ the_ref, the_offset, ++ numObjects - 1, offAnn, offAp, ++ numObjects + 1, xref->getLastXRefPos(), ++ xref->getRootNum(), xref->getRootGen(), written); ++ // XXX keep the space above after the 'n', see pg.94 pdf reference 1.7 ++ delete annotList; ++ fclose(tempFp); ++ str->close(); ++ ++ if (temporary) { ++ tempFileName = fileName->copy(); ++ rename(tempFileName->append(".temp")->getCString(), ++ fileName->getCString()); ++ delete tempFileName; ++ } ++ return NULL; ++} ++ ++// write len spaces to the file, used to overwrite 'deleted' data ++static void write_spaces(FILE *fp, int len) { ++ int i; ++ for (i=0; i < len; i++) ++ fputc(' ', fp); ++} ++ ++// remove annotation n on page pg ++void PDFDoc::delTempAnnotation(int pg, int n, GBool temporary) { ++ XRefEntry *target; ++ Page *page; ++ Object obj; ++ GString *tempFileName; ++ Lexer *lexer; ++ FILE *tempFp; ++ int i, start, end; ++ ++ tempFp = make_temp_copy(fileName, str, NULL); ++ if (tempFp == NULL) { /*ERROR*/ ++ return; ++ } ++ ++ str->reset(); ++ lexer = new Lexer(xref, str); ++ page = catalog->getPage(pg); ++ if (page->getAnnotNum() != -1) { // annotation in the array ++ target = xref->getEntry(page->getAnnotNum()); ++ lexer->setPos(target->offset); ++ lexer->getObj(&obj); // - annotation array number ++ obj.free(); ++ lexer->getObj(&obj); // - annotation array gen ++ obj.free(); ++ lexer->getObj(&obj); // - "obj" string ++ obj.free(); ++ } else { // inline annotation ++ target = xref->getEntry(catalog->getPageRef(pg)->num); ++ lexer->setPos(target->offset); ++ // locate the Annots object ++ while(1) { ++ lexer->getObj(&obj); ++ if (obj.isName() && !strncmp("Annots", obj.getName(), 6)) { ++ obj.free(); ++ break; ++ } ++ obj.free(); ++ } ++ } ++ lexer->getObj(&obj); // - "[" begin of array ++ obj.free(); ++ // skip the first n-1 annotations, jump to target annotation ++ for (i = 0; i < n; i++) { ++ lexer->getObj(&obj); // annotation number ++ obj.free(); ++ lexer->getObj(&obj); // annotation gen ++ obj.free(); ++ lexer->getObj(&obj); // "R" ++ obj.free(); ++ } ++ ++ // compute the width of the target annotation ++ start = lexer->getPos(); ++ lexer->getObj(&obj); // annotation number ++ n = obj.getInt(); ++ obj.free(); ++ lexer->getObj(&obj); // annotation gen ++ obj.free(); ++ lexer->getObj(&obj); // "R" ++ obj.free(); ++ end = lexer->getPos(); ++ ++ // overwrite data with spaces ++ fseek(tempFp, start, SEEK_SET); ++ write_spaces(tempFp, end - start); ++ ++ // now locate and compute size of the annotation object ++ target = xref->getEntry(n); ++ lexer->setPos(target->offset); ++ start = target->offset; ++ while (1) { ++ lexer->getObj(&obj); ++ if (obj.isName() && !strncmp("N", obj.getName(), 1)) { ++ obj.free(); ++ lexer->getObj(&obj); ++ n = obj.getInt(); ++ } else if (obj.isCmd() && !strncmp("endobj", obj.getCmd(), 6)) { ++ obj.free(); ++ break; ++ } ++ obj.free(); ++ } ++ end = lexer->getPos(); ++ ++ fseek(tempFp, start, SEEK_SET); ++ write_spaces(tempFp, end - start); ++ ++ // and finally do the same for the stream ++ target = xref->getEntry(n); ++ lexer->setPos(target->offset); ++ start = target->offset; ++ while (1) { ++ lexer->getObj(&obj); ++ if (obj.isName() && (strncmp("Length", obj.getName(), 6) == 0)) { ++ obj.free(); ++ lexer->getObj(&obj); ++ n = obj.getInt(); ++ } else if (obj.isCmd() && (strncmp("stream", obj.getCmd(), 6) == 0)) { ++ lexer->setPos(lexer->getPos() + n); ++ } else if (obj.isCmd() && (strncmp("endobj", obj.getCmd(), 6) == 0)) { ++ obj.free(); ++ break; ++ } ++ obj.free(); ++ } ++ end = lexer->getPos(); ++ ++ fseek(tempFp, start, SEEK_SET); ++ write_spaces(tempFp, end - start); // overwrite data with spaces ++ ++ str->close(); ++ fclose(tempFp); ++ ++ if (temporary) { ++ tempFileName = fileName->copy(); ++ rename(tempFileName->append(".temp")->getCString(), ++ fileName->getCString()); ++ delete tempFileName; ++ } ++} ++ + GBool PDFDoc::saveEmbeddedFile(int idx, char *path) { + FILE *f; + GBool ret; +diff --git a/xpdf/PDFDoc.h b/xpdf/PDFDoc.h +index 94fcfb7..8084940 100644 +--- xpdf/PDFDoc.h ++++ xpdf/PDFDoc.h +@@ -162,6 +162,14 @@ public: + // Save this file with another name. + GBool saveAs(GString *name); + ++ // Save file with added annotations ++ GString *addTempAnnotation(int pg, GBool temporary); ++ void delTempAnnotation(int pg, int n, GBool temporary); ++ // Misc access for temporary annotations ++ GString **getAnnotationObject() { return &annotationObject; } ++ GString **getAppereanceObject() { return &appereanceObject; } ++ GString **getAppereanceStream() { return &appereanceStream; } ++ + // Return a pointer to the PDFCore object. + PDFCore *getCore() { return core; } + +@@ -201,6 +209,10 @@ private: + #endif + OptionalContent *optContent; + ++ GString *annotationObject, // local buffers used during creation of ++ *appereanceObject, // temporary annotations ++ *appereanceStream; ++ + GBool ok; + int errCode; + }; +diff --git a/xpdf/Page.cc b/xpdf/Page.cc +index 189d2a2..f0430a9 100644 +--- xpdf/Page.cc ++++ xpdf/Page.cc +@@ -244,6 +244,13 @@ Page::Page(PDFDoc *docA, int numA, Dict *pageDict, PageAttrs *attrsA) { + annots.free(); + goto err2; + } ++ if (annots.isRef()) { ++ annotNum = annots.getRef().num; ++ annotGen = annots.getRef().gen; ++ } else { ++ annotNum = annotGen = -1; ++ } ++ selectedAnnotation = -1; + + // contents + pageDict->lookupNF("Contents", &contents); +@@ -295,6 +302,7 @@ void Page::display(OutputDev *out, double hDPI, double vDPI, + GBool printing, + GBool (*abortCheckCbk)(void *data), + void *abortCheckCbkData) { ++ setSelectedAnnotation(-1); + displaySlice(out, hDPI, vDPI, rotate, useMediaBox, crop, + -1, -1, -1, -1, printing, + abortCheckCbk, abortCheckCbkData); +diff --git a/xpdf/Page.h b/xpdf/Page.h +index 102eca8..bede41e 100644 +--- xpdf/Page.h ++++ xpdf/Page.h +@@ -16,6 +16,8 @@ + #endif + + #include "Object.h" ++#include "GfxState.h" ++#include "Annot.h" + + class Dict; + class PDFDoc; +@@ -153,6 +155,12 @@ public: + // Get annotations array. + Object *getAnnots(Object *obj) { return annots.fetch(xref, obj); } + ++ // Get annotations information ++ int getAnnotNum() { return annotNum; } ++ int getAnnotGen() { return annotGen; } ++ int getSelectedAnnotation () { return selectedAnnotation; } ++ void setSelectedAnnotation (int i) { selectedAnnotation = i; } ++ + // Return a list of links. + Links *getLinks(); + +@@ -192,6 +200,9 @@ private: + int num; // page number + PageAttrs *attrs; // page attributes + Object annots; // annotations array ++ int annotNum, ++ annotGen, ++ selectedAnnotation; + Object contents; // page contents + GBool ok; // true if page is valid + }; +diff --git a/xpdf/XPDFCore.cc b/xpdf/XPDFCore.cc +index b98bc37..2a3e922 100644 +--- xpdf/XPDFCore.cc ++++ xpdf/XPDFCore.cc +@@ -29,6 +29,7 @@ + #include "TextOutputDev.h" + #include "SplashBitmap.h" + #include "SplashPattern.h" ++#include "Annot.h" + #include "XPDFApp.h" + #include "XPDFCore.h" + +@@ -140,6 +141,8 @@ XPDFCore::XPDFCore(Widget shellA, Widget parentWidgetA, + hyperlinksEnabled = gTrue; + selectEnabled = gTrue; + ++ drawEnabled = gFalse; ++ + // do X-specific initialization and create the widgets + initWindow(); + initPasswordDialog(); +@@ -166,6 +169,9 @@ XPDFCore::~XPDFCore() { + if (selectCursor) { + XFreeCursor(display, selectCursor); + } ++ if (drawCursor) { ++ XFreeCursor(display, drawCursor); ++ } + } + + //------------------------------------------------------------------------ +@@ -353,14 +359,43 @@ void XPDFCore::endPan(int wx, int wy) { + //------------------------------------------------------------------------ + // selection + //------------------------------------------------------------------------ +- + void XPDFCore::startSelection(int wx, int wy) { + int pg, x, y; ++ double Xmin, Ymin, Xmax, Ymax, ux, uy; ++ int dxmin, dymin, dxmax, dymax; + + takeFocus(); + if (doc && doc->getNumPages() > 0) { +- if (selectEnabled) { +- if (cvtWindowToDev(wx, wy, &pg, &x, &y)) { ++ if (cvtWindowToDev(wx, wy, &pg, &x, &y)) { ++ if (selectEnabled && !drawEnabled) { ++ // this block is used to check if we are trying ++ // to select an annotation ++ XRef *xref = doc->getXRef(); ++ Catalog *cat = doc->getCatalog(); ++ ++ //printf("%d\n", xref->getNumObjects()); ++ Page *page = cat->getPage(pg); ++ Object obj; ++ Annots *annotList = new Annots(doc, page->getAnnots(&obj)); ++ ++ obj.free(); ++ int i, length = annotList->getNumAnnots(); ++ for (i = 0; i < length; ++i) { ++ Annot *annot = annotList->getAnnot(i); ++ annot->getRectangle(&Xmin, &Ymin, &Xmax, &Ymax); ++ cvtUserToDev(pg, Xmin, Ymin, &dxmin, &dymax); ++ cvtUserToDev(pg, Xmax, Ymax, &dxmax, &dymin); ++ cvtWindowToUser(wx, wy, &pg, &ux, &uy); ++ if (annot->selectAnnotation(ux, uy)) { ++ page->setSelectedAnnotation(i); ++ setSelection(pg, dxmin, dymin, dxmax, dymax); ++ delete annotList; ++ return; ++ } ++ } ++ delete annotList; ++ // otherwise, we start a selection ++ page->setSelectedAnnotation(-1); + setSelection(pg, x, y, x, y); + setCursor(selectCursor); + dragging = gTrue; +@@ -379,7 +414,8 @@ void XPDFCore::endSelection(int wx, int wy) { + dragging = gFalse; + setCursor(None); + if (ok) { +- moveSelection(pg, x, y); ++ if (selectEnabled && !drawEnabled) ++ moveSelection(pg, x, y); + } + #ifndef NO_TEXT_SELECT + if (selectULX != selectLRX && +@@ -455,6 +491,151 @@ Boolean XPDFCore::convertSelectionCbk(Widget widget, Atom *selection, + } + + //------------------------------------------------------------------------ ++// annotations ++//------------------------------------------------------------------------ ++// called when pressing the 'draw' button, creates the header for ++// the annotation and the stream. ++void XPDFCore::initializeDraw(int pg, int x, int y) { ++ double dx, dy; ++ double r, g, b; ++ ++ GString **ann = doc->getAnnotationObject(); ++ if (*ann) // annotation already started. ++ return; ++ r = 1.0*(Guint)color[0]/(Guint)0xff; ++ g = 1.0*(Guint)color[1]/(Guint)0xff; ++ b = 1.0*(Guint)color[2]/(Guint)0xff; ++ ++ cvtDevToUser(pg, x, y, &dx, &dy); ++ *ann = GString::format( ++ "<<\n"\ ++ "/Type/Annot\n"\ ++ "/Subtype/Ink\n"\ ++ "/C[{0:.1f} {1:.1f} {2:.1f}]\n"\ ++ "/Subject(Pencil)\n"\ ++ "/BS <>\n"\ ++ "/InkList[", r, g, b, thickness); ++ ++ *doc->getAppereanceStream() = GString::format( ++ "{0:.1f} {1:.1f} {2:.1f} RG\n{3:d} w\n", r, g, b, thickness); ++ ++ numDrawnPoints = 0; ++ rectXmin = rectXmax = dx; ++ rectYmin = rectYmax = dy; ++} ++ ++// the actual callback on a start Draw ++void XPDFCore::startDraw(int wx, int wy) { ++ int pg, x, y; ++ ++ lastDrawnX = lastDrawnY = -1; ++ takeFocus(); ++ if (!doc || doc->getNumPages() == 0 || !drawEnabled || ++ !cvtWindowToDev(wx, wy, &pg, &x, &y)) ++ return; ++ initializeDraw(pg, x, y); ++ modified = gTrue; // or look at *doc->getAnnotationObject() ++ continueDraw(pg, x, y, 0); ++ drawing = gTrue; ++ drawPoint(pg, x, y); ++ setCursor(drawCursor); ++} ++ ++// flag=0 on the first point, 1 on intermediate, 2 on the last one. ++// add an element to the annotation and also to the stream ++void XPDFCore::continueDraw(int pg, int x, int y, int flag) { ++ GString *s = *doc->getAnnotationObject(); ++ double dx, dy; ++ ++ cvtDevToUser(pg, x, y, &dx, &dy); ++ if (flag == 0) ++ s->append("["); ++ s->appendf("{0:.1f} {1:.1f} ", dx, dy); ++ if (flag == 2) ++ s->append("]"); ++ ++ s = *doc->getAppereanceStream(); ++ if (flag == 0) { // first point, store unconditionally ++ s->appendf("{0:.1f} {1:.1f} m\n", dx, dy); ++ numDrawnPoints++; ++ lastStreamX = dx; ++ lastStreamY = dy; ++ } else if (flag == 1) { // other point ++ // compute distance, ignore if too close ++ double delta = (lastStreamX - dx)*(lastStreamX - dx) + ++ (lastStreamY - dy)*(lastStreamY - dy); ++ if (delta > 49) { ++ s->appendf("{0:.1f} {1:.1f} ", dx, dy); ++ numDrawnPoints++; ++ if (numDrawnPoints%3 == 1) ++ s->append("c\n"); ++ lastStreamX = dx; ++ lastStreamY = dy; ++ } ++ } else { // XXX final point. We do not plot the point itself, ++ // and close the bezier curve in a sensible way depending on ++ // the number of points previously printed. ++ if (numDrawnPoints%3 == 2) ++ s->append("l\nS\n"); ++ else if (numDrawnPoints%3 == 0) ++ s->append("v\nS\n"); ++ else ++ s->append("S\n"); ++ numDrawnPoints = 0; ++ } ++ ++ // update the coordinates of the bounding box ++ if (dx < rectXmin) ++ rectXmin = dx; ++ if (dx > rectXmax) ++ rectXmax = dx; ++ if (dy < rectYmin) ++ rectYmin = dy; ++ if (dy > rectYmax) ++ rectYmax = dy; ++} ++ ++// should be similar to endSelection ++void XPDFCore::endDraw(int wx, int wy) { ++ int pg, x, y; ++ GBool ok; ++ ++ ok = cvtWindowToDev(wx, wy, &pg, &x, &y); ++ if (drawEnabled) { ++ drawing = gFalse; ++ setCursor(None); ++ if (ok) { ++ drawPoint(pg, x, y); ++ } else { // outside the window, reuse the last point ++ x = lastDrawnX; ++ y = lastDrawnY; ++ } ++ continueDraw(pg, x, y, 2); ++ } ++} ++ ++// handler when deleting an annotation: make a temp copy, ++// overwrite the object with whitespace, and reload. ++void XPDFCore::deleteAnnotation() { ++ Catalog *cat = doc->getCatalog(); ++ if (!cat) ++ return; ++ Page *page = cat->getPage(topPage); ++ if (!page || page->getSelectedAnnotation() == -1) ++ return; ++ ++ int pg = topPage; ++ doc->delTempAnnotation(pg, page->getSelectedAnnotation(), getTemporary()); ++ GString *temp = doc->getFileName()->copy(); ++ if (getTemporary() == gFalse) ++ temp->append(".temp"); ++ setTemporary(gTrue); ++ loadFile(temp); ++ displayPage(pg, getZoom(), getRotate(), gFalse, gFalse); ++ return; ++} ++ ++//------------------------------------------------------------------------ + // hyperlinks + //------------------------------------------------------------------------ + +@@ -894,6 +1075,7 @@ void XPDFCore::initWindow() { + busyCursor = XCreateFontCursor(display, XC_watch); + linkCursor = XCreateFontCursor(display, XC_hand2); + selectCursor = XCreateFontCursor(display, XC_cross); ++ drawCursor = XCreateFontCursor(display, XC_pencil); + currentCursor = 0; + + // create the scrolled window and scrollbars +@@ -1095,7 +1277,16 @@ void XPDFCore::inputCbk(Widget widget, XtPointer ptr, XtPointer callData) { + &pg, &x, &y); + if (core->dragging) { + if (ok) { +- core->moveSelection(pg, x, y); ++ if (core->selectEnabled) { ++ core->moveSelection(pg, x, y); ++ } ++ } ++ } else if (core->drawing) { ++ if (ok) { ++ if (core->drawEnabled) { ++ core->continueDraw(pg, x, y, 1); ++ core->drawPoint(pg, x, y); ++ } + } + } else if (core->hyperlinksEnabled) { + core->cvtDevToUser(pg, x, y, &xu, &yu); +@@ -1512,6 +1703,72 @@ void XPDFCore::dialogCancelCbk(Widget widget, XtPointer ptr, + core->dialogDone = -1; + } + ++GBool XPDFCore::doPromptDialog(const char *title, GString *msg) { ++ Widget dialog; ++ XtAppContext appContext; ++ Arg args[20]; ++ int n; ++ XmString s1, s2, s3; ++ XEvent event; ++ char *wtitle; ++ ++ n = 0; ++ XtSetArg(args[n], XmNdialogType, XmDIALOG_PROMPT); ++n; ++ XtSetArg(args[n], XmNdialogStyle, XmDIALOG_PRIMARY_APPLICATION_MODAL); ++n; ++ wtitle = new char[strlen(title) + 1]; ++ strcpy(wtitle, title); ++ s1 = XmStringCreateLocalized(wtitle); ++ XtSetArg(args[n], XmNdialogTitle, s1); ++n; ++ s2 = XmStringCreateLocalized(msg->getCString()); ++ XtSetArg(args[n], XmNselectionLabelString, s2); ++n; ++ s3 = XmStringCreateLocalized(""); ++ XtSetArg(args[n], XmNtextString, s3); ++n; ++ dialog = XmCreatePromptDialog(drawArea, "promptDialog", args, n); ++ XmStringFree(s1); ++ XmStringFree(s2); ++ XmStringFree(s3); ++ delete[] wtitle; ++ XtManageChild(dialog); ++ ++ XtAddCallback(dialog, XmNokCallback, ++ &dialogPromptOkCbk, (XtPointer)this); ++ XtAddCallback(dialog, XmNcancelCallback, ++ &dialogPromptCancelCbk, (XtPointer)this); ++ ++ appContext = XtWidgetToApplicationContext(dialog); ++ dialogDone = 0; ++ do { ++ XtAppNextEvent(appContext, &event); ++ XtDispatchEvent(&event); ++ } while (!dialogDone); ++ ++ XtUnmanageChild(dialog); ++ XtDestroyWidget(dialog); ++ ++ return dialogDone > 0; ++} ++ ++void XPDFCore::dialogPromptOkCbk(Widget widget, XtPointer ptr, ++ XtPointer callData) { ++ XPDFCore *core = (XPDFCore *)ptr; ++ XmSelectionBoxCallbackStruct *selection = ++ (XmSelectionBoxCallbackStruct *)callData; ++ char *str = (char *)XmStringUnparse(selection->value, 0, XmCHARSET_TEXT, XmCHARSET_TEXT, 0, 0, XmOUTPUT_ALL); ++ printf("%s\n", (str && str[0]) ? str : "(NULL)"); ++ XtFree(str); ++ core->dialogDone = 1; ++} ++ ++void XPDFCore::dialogPromptCancelCbk(Widget widget, XtPointer ptr, ++ XtPointer callData) { ++ XPDFCore *core = (XPDFCore *)ptr; ++ XmSelectionBoxCallbackStruct *selection = ++ (XmSelectionBoxCallbackStruct *)callData; ++ printf("(NULL)\n"); ++ core->dialogDone = -1; ++} ++ ++ + //------------------------------------------------------------------------ + // password dialog + //------------------------------------------------------------------------ +diff --git a/xpdf/XPDFCore.h b/xpdf/XPDFCore.h +index be1dcfa..080e2ee 100644 +--- xpdf/XPDFCore.h ++++ xpdf/XPDFCore.h +@@ -99,6 +99,13 @@ public: + void endSelection(int wx, int wy); + void copySelection(); + ++ //----- annotations ++ void initializeDraw(int pg, int x, int y); ++ void startDraw(int wx, int wy); ++ void continueDraw(int pg, int x, int y, int flag); ++ void endDraw(int wx, int wy); ++ void deleteAnnotation(); ++ + //----- hyperlinks + + void doAction(LinkAction *action); +@@ -118,6 +125,7 @@ public: + GBool doQuestionDialog(const char *title, GString *msg); + void doInfoDialog(const char *title, GString *msg); + void doErrorDialog(const char *title, GString *msg); ++ GBool doPromptDialog(const char *title, GString *msg); + + //----- password dialog + +@@ -130,6 +138,8 @@ public: + virtual void setBusyCursor(GBool busy); + Cursor getBusyCursor() { return busyCursor; } + void takeFocus(); ++ void enableDraw(GBool on) { drawEnabled = on; } ++ GBool getDrawEnabled() { return drawEnabled; } + void enableHyperlinks(GBool on) { hyperlinksEnabled = on; } + GBool getHyperlinksEnabled() { return hyperlinksEnabled; } + void enableSelect(GBool on) { selectEnabled = on; } +@@ -191,6 +201,10 @@ private: + XtPointer callData); + static void passwordCancelCbk(Widget widget, XtPointer ptr, + XtPointer callData); ++ static void dialogPromptOkCbk(Widget widget, XtPointer ptr, ++ XtPointer callData); ++ static void dialogPromptCancelCbk(Widget widget, XtPointer ptr, ++ XtPointer callData); + + Gulong paperPixel; + Gulong mattePixel; +@@ -216,7 +230,7 @@ private: + Widget vScrollBar; + Widget drawAreaFrame; + Widget drawArea; +- Cursor busyCursor, linkCursor, selectCursor; ++ Cursor busyCursor, linkCursor, selectCursor, drawCursor; + Cursor currentCursor; + GC drawAreaGC; // GC for blitting into drawArea + +@@ -240,6 +254,7 @@ private: + XPDFMouseCbk mouseCbk; + void *mouseCbkData; + ++ GBool drawEnabled; //flag indicating whether we are drawing or not + GBool hyperlinksEnabled; + GBool selectEnabled; + +diff --git a/xpdf/XPDFViewer.cc b/xpdf/XPDFViewer.cc +index 2de349d..3b0d381 100644 +--- xpdf/XPDFViewer.cc ++++ xpdf/XPDFViewer.cc +@@ -151,6 +151,43 @@ static ZoomMenuInfo zoomMenuInfo[nZoomMenuItems] = { + { "fit width", zoomWidth } + }; + ++struct ThicknessMenuInfo { ++ char *label; ++ int value; ++}; ++ ++static ThicknessMenuInfo thicknessMenuInfo[] = { ++ { " 1" , 1 }, ++ { " 2" , 2 }, ++ { " 3" , 3 }, ++ { " 4" , 4 }, ++ { " 5" , 5 }, ++ { " 6" , 6 }, ++ { " 7" , 7 }, ++ { " 8" , 8 }, ++ { " 9" , 9 } ++}; ++#define nThicknessMenuItems (sizeof(thicknessMenuInfo)/sizeof(ThicknessMenuInfo)) ++ ++struct ColorMenuInfo { ++ char* label; ++ Guchar R; ++ Guchar G; ++ Guchar B; ++}; ++ ++static ColorMenuInfo colorMenuInfo[] = { ++ {"Black", 0x00, 0x00, 0x00}, ++ {"Blue", 0x00, 0x00, 0xff}, ++ {"Green", 0x00, 0xff, 0x00}, ++ {"Cyan", 0x00, 0xff, 0xff}, ++ {"Red", 0xff, 0x00, 0x00}, ++ {"Magenta", 0xff, 0x00, 0xff}, ++ {"Yellow", 0xff, 0xff, 0x00}, ++ {"White", 0xff, 0xff, 0xff} ++}; ++#define nColorMenuItems (sizeof(colorMenuInfo)/sizeof(ColorMenuInfo)) ++ + #define maxZoomIdx 0 + #define defZoomIdx 3 + #define minZoomIdx 7 +@@ -166,6 +203,8 @@ XPDFViewerCmd XPDFViewer::cmdTab[] = { + { "closeOutline", 0, gFalse, gFalse, &XPDFViewer::cmdCloseOutline }, + { "closeWindow", 0, gFalse, gFalse, &XPDFViewer::cmdCloseWindow }, + { "continuousMode", 0, gFalse, gFalse, &XPDFViewer::cmdContinuousMode }, ++ { "deleteAnnotation", 0, gTrue, gTrue, &XPDFViewer::cmdDeleteAnnotation }, ++ { "endDraw", 0, gTrue, gTrue, &XPDFViewer::cmdEndDraw}, + { "endPan", 0, gTrue, gTrue, &XPDFViewer::cmdEndPan }, + { "endSelection", 0, gTrue, gTrue, &XPDFViewer::cmdEndSelection }, + { "find", 0, gTrue, gFalse, &XPDFViewer::cmdFind }, +@@ -224,6 +263,7 @@ XPDFViewerCmd XPDFViewer::cmdTab[] = { + { "scrollUpPrevPage", 1, gTrue, gFalse, &XPDFViewer::cmdScrollUpPrevPage }, + { "setSelection", 5, gTrue, gFalse, &XPDFViewer::cmdSetSelection }, + { "singlePageMode", 0, gFalse, gFalse, &XPDFViewer::cmdSinglePageMode }, ++ { "startDraw", 0, gTrue, gTrue, &XPDFViewer::cmdStartDraw }, + { "startPan", 0, gTrue, gTrue, &XPDFViewer::cmdStartPan }, + { "startSelection", 0, gTrue, gTrue, &XPDFViewer::cmdStartSelection }, + { "toggleContinuousMode", 0, gFalse, gFalse, &XPDFViewer::cmdToggleContinuousMode }, +@@ -425,6 +465,7 @@ void XPDFViewer::clear() { + XtVaSetValues(prevPageBtn, XmNsensitive, False, NULL); + XtVaSetValues(nextTenPageBtn, XmNsensitive, False, NULL); + XtVaSetValues(nextPageBtn, XmNsensitive, False, NULL); ++ XtVaSetValues(drawBtn, XmNsensitive, False, NULL); + } + + // remove the old outline +@@ -502,6 +543,7 @@ void XPDFViewer::doLink(int wx, int wy, GBool onlyIfNoSelection, + double xu, yu, selULX, selULY, selLRX, selLRY; + + if (core->getHyperlinksEnabled() && ++ !core->getDrawEnabled() && + core->cvtWindowToUser(wx, wy, &pg, &xu, &yu) && + !(onlyIfNoSelection && + core->getSelection(&selPg, &selULX, &selULY, &selLRX, &selLRY))) { +@@ -803,9 +845,30 @@ void XPDFViewer::cmdCloseOutline(GString *args[], int nArgs, + #endif + } + ++GBool XPDFViewer::save_helper() { ++ GBool flag = gFalse; ++ ++ if (core->getTemporary()) { ++ GString *msg = new GString("The file has been modified:\nwould you like to save changes?"); ++ flag = core->doQuestionDialog("Xpdf", msg); ++ delete msg; ++ } ++ if (flag) { ++ mapSaveAsDialog(); ++ } else { ++ if (core->getTemporary() && core->getDoc() != NULL) ++ remove(core->getDoc()->getFileName()->getCString()); ++ // we close the document anyways XXX not always ++ } ++ core->setTemporary(gFalse); ++ return flag; ++} ++ + void XPDFViewer::cmdCloseWindow(GString *args[], int nArgs, + XEvent *event) { +- app->close(this, gFalse); ++ if (!save_helper()) { ++ app->close(this, gFalse); ++ } + } + + void XPDFViewer::cmdContinuousMode(GString *args[], int nArgs, +@@ -821,6 +884,16 @@ void XPDFViewer::cmdContinuousMode(GString *args[], int nArgs, + XtVaSetValues(btn, XmNset, XmSET, NULL); + } + ++void XPDFViewer::cmdDeleteAnnotation(GString *args[], int nArgs, ++ XEvent *event) { ++ core->deleteAnnotation(); ++} ++ ++void XPDFViewer::cmdEndDraw(GString *args[], int nArgs, ++ XEvent *event) { ++ core->endDraw(mouseX(event), mouseY(event)); ++} ++ + void XPDFViewer::cmdEndPan(GString *args[], int nArgs, + XEvent *event) { + core->endPan(mouseX(event), mouseY(event)); +@@ -965,17 +1038,23 @@ void XPDFViewer::cmdNextPageNoScroll(GString *args[], int nArgs, + + void XPDFViewer::cmdOpen(GString *args[], int nArgs, + XEvent *event) { +- mapOpenDialog(gFalse); ++ if (!save_helper()) { ++ mapOpenDialog(gFalse); ++ } + } + + void XPDFViewer::cmdOpenFile(GString *args[], int nArgs, + XEvent *event) { +- open(args[0], 1, NULL); ++ if (!save_helper()) { ++ open(args[0], 1, NULL); ++ } + } + + void XPDFViewer::cmdOpenFileAtDest(GString *args[], int nArgs, + XEvent *event) { +- open(args[0], 1, args[1]); ++ if (!save_helper()) { ++ open(args[0], 1, args[1]); ++ } + } + + void XPDFViewer::cmdOpenFileAtDestInNewWin(GString *args[], int nArgs, +@@ -985,7 +1064,9 @@ void XPDFViewer::cmdOpenFileAtDestInNewWin(GString *args[], int nArgs, + + void XPDFViewer::cmdOpenFileAtPage(GString *args[], int nArgs, + XEvent *event) { +- open(args[0], atoi(args[1]->getCString()), NULL); ++ if (!save_helper()) { ++ open(args[0], atoi(args[1]->getCString()), NULL); ++ } + } + + void XPDFViewer::cmdOpenFileAtPageInNewWin(GString *args[], int nArgs, +@@ -1062,7 +1143,9 @@ void XPDFViewer::cmdPrint(GString *args[], int nArgs, + + void XPDFViewer::cmdQuit(GString *args[], int nArgs, + XEvent *event) { +- app->quit(); ++ if (!save_helper()) { ++ app->quit(); ++ } + } + + void XPDFViewer::cmdRaise(GString *args[], int nArgs, +@@ -1339,6 +1422,11 @@ void XPDFViewer::cmdSinglePageMode(GString *args[], int nArgs, + XtVaSetValues(btn, XmNset, XmUNSET, NULL); + } + ++void XPDFViewer::cmdStartDraw(GString *args[], int nArgs, ++ XEvent *event) { ++ core->startDraw(mouseX(event), mouseY(event)); ++} ++ + void XPDFViewer::cmdStartPan(GString *args[], int nArgs, + XEvent *event) { + core->startPan(mouseX(event), mouseY(event)); +@@ -1603,6 +1691,8 @@ void XPDFViewer::initWindow(GBool fullScreen) { + NULL); + XtVaSetValues(printBtn, XmNnavigationType, XmEXCLUSIVE_TAB_GROUP, + NULL); ++ XtVaSetValues(colorWidget, XmNnavigationType, XmEXCLUSIVE_TAB_GROUP, ++ NULL); + XtVaSetValues(aboutBtn, XmNnavigationType, XmEXCLUSIVE_TAB_GROUP, + NULL); + XtVaSetValues(quitBtn, XmNnavigationType, XmEXCLUSIVE_TAB_GROUP, +@@ -1632,6 +1722,31 @@ void XPDFViewer::initWindow(GBool fullScreen) { + } + } + ++Widget XPDFViewer::mk_button(char *label, char *tooltip, Widget left, ++ XmString pixmap_s, void (callback)(Widget , XtPointer , XtPointer )) { ++ int n = 0; ++ Arg args[20]; ++ Widget ret; ++ ++ if (left) { ++ XtSetArg(args[n], XmNleftAttachment, XmATTACH_WIDGET); ++n; ++ XtSetArg(args[n], XmNleftWidget, left); ++n; ++ } else { ++ XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); ++n; ++ } ++ XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); ++n; ++ XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); ++n; ++ XtSetArg(args[n], XmNmarginWidth, 6); ++n; ++ XtSetArg(args[n], XmNsensitive, False); ++n; ++ XtSetArg(args[n], XmNlabelString, pixmap_s); ++n; ++ ret = XmCreatePushButton(toolBar, label, args, n); ++ addToolTip(ret, tooltip); ++ XtManageChild(ret); ++ XtAddCallback(ret, XmNactivateCallback, ++ callback, (XtPointer)this); ++ return ret; ++} ++ + void XPDFViewer::initToolbar(Widget parent) { + Widget label, lastBtn; + #ifndef USE_COMBO_BOX +@@ -1651,6 +1766,14 @@ void XPDFViewer::initToolbar(Widget parent) { + // pixmaps later + emptyString = XmStringCreateLocalized(""); + ++#if 1 ++ backBtn = mk_button("back", "Back", NULL, emptyString, &backCbk); ++ prevTenPageBtn = mk_button("prevTenPage", "-10 pages", backBtn, emptyString, &prevTenPageCbk); ++ prevPageBtn = mk_button("prevPage", "Previous page", prevTenPageBtn, emptyString, &prevPageCbk); ++ nextPageBtn = mk_button("nextPage", "Next page", prevPageBtn, emptyString, &nextPageCbk); ++ nextTenPageBtn = mk_button("nextTenPage", "+10 pages", nextPageBtn, emptyString, &nextTenPageCbk); ++ forwardBtn = mk_button("forward", "Forward", nextTenPageBtn, emptyString, &forwardCbk); ++#else + // page movement buttons + n = 0; + XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); ++n; +@@ -1729,6 +1852,7 @@ void XPDFViewer::initToolbar(Widget parent) { + XtManageChild(forwardBtn); + XtAddCallback(forwardBtn, XmNactivateCallback, + &forwardCbk, (XtPointer)this); ++#endif + + // page number display + n = 0; +@@ -1828,6 +1952,14 @@ void XPDFViewer::initToolbar(Widget parent) { + zoomWidget = zoomMenu; + #endif + ++#if 1 ++ findBtn = mk_button("find", "Find", zoomWidget, emptyString, &findCbk); ++ printBtn = mk_button("print", "Print", findBtn, emptyString, &printCbk); ++ aboutBtn = mk_button("about", "About / help", printBtn, emptyString, &aboutCbk); ++ XtVaSetValues(findBtn, XmNsensitive, True, NULL); ++ XtVaSetValues(printBtn, XmNsensitive, True, NULL); ++ XtVaSetValues(aboutBtn, XmNsensitive, True, NULL); ++#else + // find/print/about buttons + n = 0; + XtSetArg(args[n], XmNleftAttachment, XmATTACH_WIDGET); ++n; +@@ -1865,7 +1997,124 @@ void XPDFViewer::initToolbar(Widget parent) { + XtManageChild(aboutBtn); + XtAddCallback(aboutBtn, XmNactivateCallback, + &aboutCbk, (XtPointer)this); +- lastBtn = aboutBtn; ++#endif ++ ++ //thickness menu ++ XmString st3[nThicknessMenuItems]; ++ for (i = 0; i < nThicknessMenuItems ; ++i) { ++ st3[i] = XmStringCreateLocalized(thicknessMenuInfo[i].label); ++ } ++#if USE_COMBO_BOX ++ n = 0; ++ XtSetArg(args[n], XmNleftAttachment, XmATTACH_WIDGET); ++n; ++ XtSetArg(args[n], XmNleftWidget, aboutBtn); ++n; ++ XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); ++n; ++ XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); ++n; ++ XtSetArg(args[n], XmNmarginWidth, 0); ++n; ++ XtSetArg(args[n], XmNmarginHeight, 0); ++n; ++ XtSetArg(args[n], XmNcomboBoxType, XmDROP_DOWN_LIST); ++n; ++ XtSetArg(args[n], XmNpositionMode, XmONE_BASED); ++n; ++ XtSetArg(args[n], XmNcolumns, 3); ++n; ++ XtSetArg(args[n], XmNitems, st3); ++n; ++ XtSetArg(args[n], XmNitemCount, nThicknessMenuItems); ++n; ++ //XtSetArg(args[n], XmNvisibleItemCount, nThicknessMenuItems); ++n; ++ thicknessWidget = XmCreateComboBox(toolBar, "thicknessComboBox", args, n); ++ addToolTip(thicknessWidget, "Annotation Thickness"); ++ XtAddCallback(thicknessWidget, XmNselectionCallback, ++ &thicknessComboBoxCbk, (XtPointer)this); ++#else ++ Widget menuPane2; ++ n = 0; ++ menuPane2 = XmCreatePulldownMenu(toolBar, "thicknessMenuPane", args, n); ++ for (i = 0; i < nThicknessMenuItems; ++i) { ++ n = 0; ++ XtSetArg(args[n], XmNlabelString, st3[i]); ++n; ++ XtSetArg(args[n], XmNuserData, (XtPointer)i); ++n; ++ sprintf(buf, "thickness%d", i); ++ btn = XmCreatePushButton(menuPane2, buf, args, n); ++ XtManageChild(btn); ++ XtAddCallback(btn, XmNactivateCallback, ++ &thicknessMenuCbk, (XtPointer)this); ++ thicknessMenuBtns[i] = btn; ++ } ++ n = 0; ++ XtSetArg(args[n], XmNleftAttachment, XmATTACH_WIDGET); ++n; ++ XtSetArg(args[n], XmNleftWidget, aboutBtn); ++n; ++ XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); ++n; ++ XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); ++n; ++ XtSetArg(args[n], XmNmarginWidth, 0); ++n; ++ XtSetArg(args[n], XmNmarginHeight, 0); ++n; ++ XtSetArg(args[n], XmNselectedPosition, 5); ++n; ++ XtSetArg(args[n], XmNsubMenuId, menuPane2); ++n; ++ thicknessWidget = XmCreateOptionMenu(toolBar, "thicknessMenu", args, n); ++ addToolTip(thicknessWidget, "Thickness"); ++#endif ++ XtManageChild(thicknessWidget); ++ for (i = 0; i < nThicknessMenuItems; ++i) { ++ XmStringFree(st3[i]); ++ } ++ ++ //color menu ++ XmString st2[nColorMenuItems]; ++ for (i = 0; i < nColorMenuItems ; ++i) { ++ st2[i] = XmStringCreateLocalized(colorMenuInfo[i].label); ++ } ++#if USE_COMBO_BOX ++ n = 0; ++ XtSetArg(args[n], XmNleftAttachment, XmATTACH_WIDGET); ++n; ++ XtSetArg(args[n], XmNleftWidget, thicknessWidget); ++n; ++ XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); ++n; ++ XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); ++n; ++ XtSetArg(args[n], XmNmarginWidth, 0); ++n; ++ XtSetArg(args[n], XmNmarginHeight, 0); ++n; ++ XtSetArg(args[n], XmNcomboBoxType, XmDROP_DOWN_LIST); ++n; ++ XtSetArg(args[n], XmNpositionMode, XmONE_BASED); ++n; ++ XtSetArg(args[n], XmNselectedPosition, 5); ++n; ++ XtSetArg(args[n], XmNcolumns, 7); ++n; ++ XtSetArg(args[n], XmNitems, st2); ++n; ++ XtSetArg(args[n], XmNitemCount, nColorMenuItems); ++n; ++ XtSetArg(args[n], XmNvisibleItemCount, nColorMenuItems); ++n; ++ colorWidget = XmCreateComboBox(toolBar, "colorComboBox", args, n); ++ addToolTip(colorWidget, "Annotation Color"); ++ XtAddCallback(colorWidget, XmNselectionCallback, ++ &color_Cbk, (XtPointer)this); ++#else ++ Widget menuPane1; ++ n = 0; ++ menuPane1 = XmCreatePulldownMenu(toolBar, "colorMenuPane", args, n); ++ for (i = 0; i < nColorMenuItems; ++i) { ++ n = 0; ++ XtSetArg(args[n], XmNlabelString, st2[i]); ++n; ++ XtSetArg(args[n], XmNuserData, (XtPointer)i); ++n; ++ sprintf(buf, "color%d", i); ++ btn = XmCreatePushButton(menuPane1, buf, args, n); ++ XtManageChild(btn); ++ XtAddCallback(btn, XmNactivateCallback, ++ &color_Cbk, (XtPointer)this); ++ colorMenuBtns[i] = btn; ++ } ++ n = 0; ++ XtSetArg(args[n], XmNleftAttachment, XmATTACH_WIDGET); ++n; ++ XtSetArg(args[n], XmNleftWidget, aboutBtn); ++n; ++ XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); ++n; ++ XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); ++n; ++ XtSetArg(args[n], XmNmarginWidth, 0); ++n; ++ XtSetArg(args[n], XmNmarginHeight, 0); ++n; ++ XtSetArg(args[n], XmNselectedPosition, 5); ++n; ++ XtSetArg(args[n], XmNsubMenuId, menuPane1); ++n; ++ colorWidget = XmCreateOptionMenu(toolBar, "colorMenu", args, n); ++ addToolTip(colorWidget, "Color"); ++#endif ++ XtManageChild(colorWidget); ++ for (i = 0; i < nColorMenuItems; ++i) { ++ XmStringFree(st2[i]); ++ } ++ ++ // draw button ++ s = XmStringCreateLocalized("Draw"); ++ drawBtn = mk_button("draw", "Draw", colorWidget, s, &drawCbk); ++ XmStringFree(s); ++ lastBtn = drawBtn; + + // quit button + n = 0; +@@ -2055,6 +2304,16 @@ void XPDFViewer::initPopupMenu() { + XtManageChild(btn); + XtAddCallback(btn, XmNactivateCallback, + &zoomToSelectionCbk, (XtPointer)this); ++ ++ ++ s = XmStringCreateLocalized("Draw"); ++ XtSetArg(args[n], XmNlabelString, s); ++n; ++ btn = XmCreatePushButton(popupMenu, "draw", args, n); ++ XmStringFree(s); ++ XtManageChild(btn); ++ XtAddCallback(btn, XmNactivateCallback, ++ &drawCbk, (XtPointer)this); ++ + n = 0; + btn = XmCreateSeparator(popupMenu, "sep2", args, n); + XtManageChild(btn); +@@ -2420,7 +2679,6 @@ void XPDFViewer::forwardCbk(Widget widget, XtPointer ptr, + } + + #if USE_COMBO_BOX +- + void XPDFViewer::zoomComboBoxCbk(Widget widget, XtPointer ptr, + XtPointer callData) { + XPDFViewer *viewer = (XPDFViewer *)ptr; +@@ -2456,6 +2714,14 @@ void XPDFViewer::zoomComboBoxCbk(Widget widget, XtPointer ptr, + viewer->core->takeFocus(); + } + ++void XPDFViewer::thicknessComboBoxCbk(Widget widget, XtPointer ptr, ++ XtPointer callData) { ++ XPDFViewer *viewer = (XPDFViewer *)ptr; ++ XmComboBoxCallbackStruct *data = (XmComboBoxCallbackStruct *)callData; ++ ++ viewer->core->setThickness(thicknessMenuInfo[data->item_position - 1].value); ++} ++ + #else // USE_COMBO_BOX + + void XPDFViewer::zoomMenuCbk(Widget widget, XtPointer ptr, +@@ -2476,8 +2742,40 @@ void XPDFViewer::zoomMenuCbk(Widget widget, XtPointer ptr, + viewer->core->takeFocus(); + } + ++void XPDFViewer::thicknessMenuCbk(Widget widget, XtPointer ptr, ++ XtPointer callData) { ++ XPDFViewer *viewer = (XPDFViewer *)ptr; ++ XmPushButtonCallbackStruct *data = (XmPushButtonCallbackStruct *)callData; ++ XtPointer userData; ++ ++ XtVaGetValues(widget, XmNuserData, &userData, NULL); ++ viewer->core->setColor(thicknessMenuInfo[(long)userData].value); ++} ++ + #endif // USE_COMBO_BOX + ++/* menu or combobox callback for colors */ ++void XPDFViewer::color_Cbk(Widget widget, XtPointer ptr, ++ XtPointer callData) { ++ XPDFViewer *viewer = (XPDFViewer *)ptr; ++ long i; ++#if USE_COMBO_BOX ++ XmComboBoxCallbackStruct *data = (XmComboBoxCallbackStruct *)callData; ++ i = data->item_position -1; ++#else ++ XmPushButtonCallbackStruct *data = (XmPushButtonCallbackStruct *)callData; ++ XtPointer userData; ++ ++ XtVaGetValues(widget, XmNuserData, &userData, NULL); ++ i = (long)userData; ++#endif ++ viewer->core->setColor( ++ colorMenuInfo[i].R, ++ colorMenuInfo[i].G, ++ colorMenuInfo[i].B ++ ); ++} ++ + void XPDFViewer::findCbk(Widget widget, XtPointer ptr, + XtPointer callData) { + XPDFViewer *viewer = (XPDFViewer *)ptr; +@@ -2505,18 +2803,52 @@ void XPDFViewer::aboutCbk(Widget widget, XtPointer ptr, + XtManageChild(viewer->aboutDialog); + } + ++void XPDFViewer::drawCbk(Widget widget, XtPointer ptr, ++ XtPointer callData) { ++ Arg args[1]; ++ int n = 0; ++ XmString label_str; ++ ++ XPDFViewer *viewer = (XPDFViewer *)ptr; ++ if (!viewer->core->getDrawEnabled()) { ++ label_str = XmStringCreateLocalized("End Draw"); ++ if (!viewer->core->getFullScreen()) { ++ // disable color, and thickness drop down menu ++ XtVaSetValues(viewer->colorWidget, XmNsensitive, False, NULL); ++ XtVaSetValues(viewer->thicknessWidget, XmNsensitive, False, NULL); ++ } ++ viewer->core->enableDraw(gTrue); ++ } else { ++ if (!viewer->core->getFullScreen()) { ++ // enable color, and thickness drop down menu ++ XtVaSetValues(viewer->colorWidget, XmNsensitive, True, NULL); ++ XtVaSetValues(viewer->thicknessWidget, XmNsensitive, True, NULL); ++ } ++ if (viewer->core->getModified()) { ++ viewer->core->finalizeDraw(); ++ } ++ label_str = XmStringCreateLocalized("Draw"); ++ viewer->core->enableDraw(gFalse); ++ } ++ XtSetArg(args[n],XmNlabelString, label_str); ++n; ++ XtSetValues(widget, args, n); ++ XmStringFree(label_str); ++} ++ + void XPDFViewer::quitCbk(Widget widget, XtPointer ptr, + XtPointer callData) { + XPDFViewer *viewer = (XPDFViewer *)ptr; +- +- viewer->app->quit(); ++ if (!viewer->save_helper()) { ++ viewer->app->quit(); ++ } + } + + void XPDFViewer::openCbk(Widget widget, XtPointer ptr, + XtPointer callData) { + XPDFViewer *viewer = (XPDFViewer *)ptr; +- +- viewer->mapOpenDialog(gFalse); ++ if (!viewer->save_helper()) { ++ viewer->mapOpenDialog(gFalse); ++ } + } + + void XPDFViewer::openInNewWindowCbk(Widget widget, XtPointer ptr, +@@ -2593,8 +2925,9 @@ void XPDFViewer::zoomToSelectionCbk(Widget widget, XtPointer ptr, + void XPDFViewer::closeCbk(Widget widget, XtPointer ptr, + XtPointer callData) { + XPDFViewer *viewer = (XPDFViewer *)ptr; +- +- viewer->app->close(viewer, gFalse); ++ if (!viewer->save_helper()) { ++ viewer->app->close(viewer, gFalse); ++ } + } + + void XPDFViewer::closeMsgCbk(Widget widget, XtPointer ptr, +@@ -2690,6 +3023,12 @@ void XPDFViewer::updateCbk(void *data, GString *fileName, + XtVaSetValues(viewer->linkLabel, XmNlabelString, s, NULL); + XmStringFree(s); + } ++ ++ if (globalParams->getPSFile() == NULL && // NOT a Postscript file ++ viewer->core->getDoc() != NULL && // a PDF doc is open ++ !viewer->core->getDoc()->isEncrypted()) { // the document is not encrypted ++ XtVaSetValues(viewer->drawBtn, XmNsensitive, gTrue, NULL); ++ } + } + } + +@@ -2976,6 +3315,9 @@ void XPDFViewer::openOkCbk(Widget widget, XtPointer ptr, + Boolean sep; + GString *fileNameStr; + ++ if (!viewer->openInNewWindow) { ++ viewer->core->setModified(gFalse); ++ } + XmStringInitContext(&context, data->value); + if (XmStringGetNextSegment(context, &fileName, &charSet, &dir, &sep)) { + fileNameStr = new GString(fileName); +@@ -3225,7 +3567,7 @@ void XPDFViewer::saveAsOkCbk(Widget widget, XtPointer ptr, + XmFileSelectionBoxCallbackStruct *data = + (XmFileSelectionBoxCallbackStruct *)callData; + char *fileName; +- GString *fileNameStr; ++ GString *fileNameStr, *temp; + XmStringContext context; + XmStringCharSet charSet; + XmStringDirection dir; +@@ -3235,6 +3577,16 @@ void XPDFViewer::saveAsOkCbk(Widget widget, XtPointer ptr, + if (XmStringGetNextSegment(context, &fileName, &charSet, &dir, &sep)) { + fileNameStr = new GString(fileName); + viewer->core->getDoc()->saveAs(fileNameStr); ++ temp = viewer->core->getDoc()->getFileName()->copy(); ++ makePathAbsolute(temp); ++ if (strcmp(temp->getCString(), fileNameStr->getCString()) == 0) { ++ // if the old name and the new one are equal, it's ++ // better to reset the temporary flag; if the user try ++ // to save the file using the name of the temporary file, ++ // on "quit event" xpdf could delete the file!!! ++ viewer->core->setTemporary(gFalse); ++ } ++ delete temp; + delete fileNameStr; + XtFree(charSet); + XtFree(fileName); +diff --git a/xpdf/XPDFViewer.h b/xpdf/XPDFViewer.h +index 8a345e8..998b245 100644 +--- xpdf/XPDFViewer.h ++++ xpdf/XPDFViewer.h +@@ -104,6 +104,8 @@ private: + void cmdCloseOutline(GString *args[], int nArgs, XEvent *event); + void cmdCloseWindow(GString *args[], int nArgs, XEvent *event); + void cmdContinuousMode(GString *args[], int nArgs, XEvent *event); ++ void cmdDeleteAnnotation(GString *args[], int nArgs, XEvent *event); ++ void cmdEndDraw(GString *args[], int nArgs, XEvent *event); + void cmdEndPan(GString *args[], int nArgs, XEvent *event); + void cmdEndSelection(GString *args[], int nArgs, XEvent *event); + void cmdFind(GString *args[], int nArgs, XEvent *event); +@@ -162,6 +164,7 @@ private: + void cmdScrollUpPrevPage(GString *args[], int nArgs, XEvent *event); + void cmdSetSelection(GString *args[], int nArgs, XEvent *event); + void cmdSinglePageMode(GString *args[], int nArgs, XEvent *event); ++ void cmdStartDraw(GString *args[], int nArgs, XEvent *event); + void cmdStartPan(GString *args[], int nArgs, XEvent *event); + void cmdStartSelection(GString *args[], int nArgs, XEvent *event); + void cmdToggleContinuousMode(GString *args[], int nArgs, XEvent *event); +@@ -178,6 +181,10 @@ private: + //----- GUI code: main window + void initWindow(GBool fullScreen); + void initToolbar(Widget parent); ++ Widget mk_button(char *label, char *tooltip, Widget left, XmString pixmap_s, ++ void (callback)(Widget , XtPointer , XtPointer )); ++ ++ + #ifndef DISABLE_OUTLINE + void initPanedWin(Widget parent); + #endif +@@ -204,16 +211,24 @@ private: + #if USE_COMBO_BOX + static void zoomComboBoxCbk(Widget widget, XtPointer ptr, + XtPointer callData); ++ static void thicknessComboBoxCbk(Widget widget, XtPointer ptr, ++ XtPointer callData); + #else + static void zoomMenuCbk(Widget widget, XtPointer ptr, + XtPointer callData); ++ static void thicknessMenuCbk(Widget widget, XtPointer ptr, ++ XtPointer callData); + #endif ++ static void color_Cbk(Widget widget, XtPointer ptr, ++ XtPointer callData); + static void findCbk(Widget widget, XtPointer ptr, + XtPointer callData); + static void printCbk(Widget widget, XtPointer ptr, + XtPointer callData); + static void aboutCbk(Widget widget, XtPointer ptr, + XtPointer callData); ++ static void drawCbk(Widget widget, XtPointer ptr, ++ XtPointer callData); + static void quitCbk(Widget widget, XtPointer ptr, + XtPointer callData); + static void openCbk(Widget widget, XtPointer ptr, +@@ -251,6 +266,7 @@ private: + XtPointer callData); + #endif + ++ GBool save_helper(); // save temp file on close + //----- GUI code: "about" dialog + void initAboutDialog(); + +@@ -292,6 +308,7 @@ private: + + XPDFApp *app; + GBool ok; ++ GBool modified; + + Display *display; + int screenNum; +@@ -321,11 +338,15 @@ private: + #else + Widget zoomMenu; + Widget zoomMenuBtns[nZoomMenuItems]; ++ Widget colorMenuBtns[nColorMenuItems]; + #endif + Widget zoomWidget; + Widget findBtn; + Widget printBtn; + Widget aboutBtn; ++ Widget thicknessWidget; ++ Widget colorWidget; ++ Widget drawBtn; + Widget linkLabel; + Widget quitBtn; + Widget popupMenu; +-- +1.7.3.4 + diff --git a/graphics/xpdf/files/patch-Makefile.in b/graphics/xpdf/files/patch-Makefile.in index 071cf5f..50ad02a 100644 --- a/graphics/xpdf/files/patch-Makefile.in +++ b/graphics/xpdf/files/patch-Makefile.in @@ -1,18 +1,18 @@ ---- Makefile.in.orig Tue Feb 27 14:05:51 2007 -+++ Makefile.in -@@ -82,7 +82,7 @@ - $(INSTALL_PROGRAM) xpdf/pdftotext$(EXE) $(DESTDIR)@bindir@/pdftotext$(EXE) +--- Makefile.in.orig 2011-08-16 01:08:52.000000000 +0400 ++++ Makefile.in 2011-10-08 22:38:12.274453018 +0400 +@@ -89,7 +89,7 @@ $(INSTALL_PROGRAM) xpdf/pdfinfo$(EXE) $(DESTDIR)@bindir@/pdfinfo$(EXE) $(INSTALL_PROGRAM) xpdf/pdffonts$(EXE) $(DESTDIR)@bindir@/pdffonts$(EXE) + $(INSTALL_PROGRAM) xpdf/pdfdetach$(EXE) $(DESTDIR)@bindir@/pdfdetach$(EXE) -@X@ $(INSTALL_PROGRAM) xpdf/pdftoppm$(EXE) $(DESTDIR)@bindir@/pdftoppm$(EXE) + $(INSTALL_PROGRAM) xpdf/pdftoppm$(EXE) $(DESTDIR)@bindir@/pdftoppm$(EXE) $(INSTALL_PROGRAM) xpdf/pdfimages$(EXE) $(DESTDIR)@bindir@/pdfimages$(EXE) -mkdir -p $(DESTDIR)@mandir@/man1 @X@ $(INSTALL_DATA) $(srcdir)/doc/xpdf.1 $(DESTDIR)@mandir@/man1/xpdf.1 -@@ -90,7 +90,7 @@ - $(INSTALL_DATA) $(srcdir)/doc/pdftotext.1 $(DESTDIR)@mandir@/man1/pdftotext.1 +@@ -98,7 +98,7 @@ $(INSTALL_DATA) $(srcdir)/doc/pdfinfo.1 $(DESTDIR)@mandir@/man1/pdfinfo.1 $(INSTALL_DATA) $(srcdir)/doc/pdffonts.1 $(DESTDIR)@mandir@/man1/pdffonts.1 + $(INSTALL_DATA) $(srcdir)/doc/pdfdetach.1 $(DESTDIR)@mandir@/man1/pdfdetach.1 -@X@ $(INSTALL_DATA) $(srcdir)/doc/pdftoppm.1 $(DESTDIR)@mandir@/man1/pdftoppm.1 + $(INSTALL_DATA) $(srcdir)/doc/pdftoppm.1 $(DESTDIR)@mandir@/man1/pdftoppm.1 $(INSTALL_DATA) $(srcdir)/doc/pdfimages.1 $(DESTDIR)@mandir@/man1/pdfimages.1 diff --git a/graphics/xpdf/files/patch-configure b/graphics/xpdf/files/patch-configure deleted file mode 100644 index 5efb6b3..0000000 --- a/graphics/xpdf/files/patch-configure +++ /dev/null @@ -1,15 +0,0 @@ ---- configure.orig Tue Feb 27 14:05:51 2007 -+++ configure -@@ -11798,8 +11798,8 @@ - { echo "$as_me:$LINENO: WARNING: Couldn't find FreeType" >&5 - echo "$as_me: WARNING: Couldn't find FreeType" >&2;}; - fi -- { echo "$as_me:$LINENO: WARNING: -- You will be able to compile pdftops, pdftotext, -- pdfinfo, pdffonts, and pdfimages, but not xpdf or pdftoppm" >&5 --echo "$as_me: WARNING: -- You will be able to compile pdftops, pdftotext, -- pdfinfo, pdffonts, and pdfimages, but not xpdf or pdftoppm" >&2;} -+ { echo "$as_me:$LINENO: WARNING: -- You will be able to compile pdftoppm, pdftops, pdftotext, -+ pdfinfo, pdffonts, and pdfimages, but not xpdf" >&5 -+echo "$as_me: WARNING: -- You will be able to compile pdftoppm, pdftops, pdftotext, -+ pdfinfo, pdffonts, and pdfimages, but not xpdf" >&2;} - fi diff --git a/graphics/xpdf/files/patch-configure.in b/graphics/xpdf/files/patch-configure.in index 9c23e3b..c4382e4 100644 --- a/graphics/xpdf/files/patch-configure.in +++ b/graphics/xpdf/files/patch-configure.in @@ -1,11 +1,12 @@ ---- configure.in.orig Tue Feb 27 14:05:51 2007 -+++ configure.in -@@ -348,6 +348,6 @@ +--- configure.in.orig 2011-08-16 01:08:53.000000000 +0400 ++++ configure.in 2011-10-08 22:56:17.559452442 +0400 +@@ -368,7 +368,6 @@ if test "x$smr_have_freetype2_library" != xyes; then AC_MSG_WARN([Couldn't find FreeType]); fi - AC_MSG_WARN([-- You will be able to compile pdftops, pdftotext, -- pdfinfo, pdffonts, and pdfimages, but not xpdf or pdftoppm]) +- pdfinfo, pdffonts, pdfdetach, and pdfimages, but not xpdf +- or pdftoppm]) + AC_MSG_WARN([-- You will be able to compile pdftoppm, pdftops, pdftotext, -+ pdfinfo, pdffonts, and pdfimages, but not xpdf]) ++ pdfinfo, pdffonts, pdfdetach, and pdfimages, but not xpdf]) fi diff --git a/graphics/xpdf/files/patch-fofi_FoFiTrueType.cc b/graphics/xpdf/files/patch-fofi_FoFiTrueType.cc deleted file mode 100644 index e8d2f32..0000000 --- a/graphics/xpdf/files/patch-fofi_FoFiTrueType.cc +++ /dev/null @@ -1,11 +0,0 @@ ---- fofi/FoFiTrueType.cc.orig 2010-12-29 12:13:14.000000000 -0800 -+++ fofi/FoFiTrueType.cc 2010-12-29 12:15:15.000000000 -0800 -@@ -906,7 +906,7 @@ - // check for an incorrect cmap table length - badCmapLen = gFalse; - cmapLen = 0; // make gcc happy -- if (!missingCmap) { -+ if (!missingCmap && cmaps != NULL && nCmaps != 0) { - cmapLen = cmaps[0].offset + cmaps[0].len; - for (i = 1; i < nCmaps; ++i) { - if (cmaps[i].offset + cmaps[i].len > cmapLen) { diff --git a/graphics/xpdf/files/patch-splash_Splash.cc b/graphics/xpdf/files/patch-splash_Splash.cc deleted file mode 100644 index 186b760..0000000 --- a/graphics/xpdf/files/patch-splash_Splash.cc +++ /dev/null @@ -1,14 +0,0 @@ ---- splash/Splash.cc.orig Tue Feb 27 14:05:52 2007 -+++ splash/Splash.cc -@@ -2826,7 +2826,10 @@ - void Splash::compositeBackground(SplashColorPtr color) { - SplashColorPtr p; - Guchar *q; -- Guchar alpha, alpha1, c, color0, color1, color2, color3; -+ Guchar alpha, alpha1, c, color0, color1, color2; -+#if SPLASH_CMYK -+ Guchar color3; -+#endif - int x, y, mask; - - switch (bitmap->mode) { diff --git a/graphics/xpdf/files/patch-xpdf::Makefile.in b/graphics/xpdf/files/patch-xpdf::Makefile.in index 8479fee..da82783 100644 --- a/graphics/xpdf/files/patch-xpdf::Makefile.in +++ b/graphics/xpdf/files/patch-xpdf::Makefile.in @@ -1,11 +1,11 @@ ---- xpdf/Makefile.in.orig Tue Feb 27 14:05:52 2007 -+++ xpdf/Makefile.in -@@ -110,7 +110,7 @@ - pdffonts$(EXE) pdftoppm$(EXE) pdfimages$(EXE) +--- xpdf/Makefile.in.orig 2011-08-16 01:08:53.000000000 +0400 ++++ xpdf/Makefile.in 2011-10-08 22:44:10.580458757 +0400 +@@ -112,7 +112,7 @@ + pdffonts$(EXE) pdfdetach$(EXE) pdftoppm$(EXE) pdfimages$(EXE) all-no-x: pdftops$(EXE) pdftotext$(EXE) pdfinfo$(EXE) pdffonts$(EXE) \ -- pdfimages$(EXE) -+ pdftoppm$(EXE) pdfimages$(EXE) +- pdfdetach$(EXE) pdfimages$(EXE) ++ pdfdetach$(EXE) pdfimages$(EXE) pdftoppm$(EXE) #------------------------------------------------------------------------ diff --git a/graphics/xpdf/pkg-plist b/graphics/xpdf/pkg-plist index 9ea6607..8b48a4d 100644 --- a/graphics/xpdf/pkg-plist +++ b/graphics/xpdf/pkg-plist @@ -1,3 +1,4 @@ +bin/pdfdetach bin/pdffonts bin/pdfimages bin/pdfinfo -- 1.7.3.4