poppler/ArthurOutputDev.cc | 123 +++++++++++++++++++-------------------------- poppler/ArthurOutputDev.h | 2 qt4/src/poppler-page.cc | 62 +++++++++++++++------- qt4/src/poppler-qt4.h | 65 +++++++++++++++++++++++ 4 files changed, 162 insertions(+), 90 deletions(-)
New commits: commit f077e82af0724be88d28c896a3c208f1d50ccff9 Author: Pino Toscano <[email protected]> Date: Sun Nov 7 21:50:48 2010 +0100 [qt4] New Page::renderToPainter() This new painter-based painting function ican be used for painting (with Arthur only for now) without getting an image first. Also add a new flag type for it, with a single item telling whether do not save+restore the provided painter. Mostly based on a patch by Matthias Fauconneau ([email protected]), thanks! diff --git a/qt4/src/poppler-page.cc b/qt4/src/poppler-page.cc index 293d09b..1b55c33 100644 --- a/qt4/src/poppler-page.cc +++ b/qt4/src/poppler-page.cc @@ -8,6 +8,7 @@ * Copyright (C) 2009 Shawn Rutledge <[email protected]> * Copyright (C) 2010, Guillermo Amaral <[email protected]> * Copyright (C) 2010 Suzuki Toshiya <[email protected]> + * Copyright (C) 2010 Matthias Fauconneau <[email protected]> * * 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 @@ -250,25 +251,7 @@ QImage Page::renderToImage(double xres, double yres, int x, int y, int w, int h, QImage tmpimg(w == -1 ? qRound( size.width() * xres / 72.0 ) : w, h == -1 ? qRound( size.height() * yres / 72.0 ) : h, QImage::Format_ARGB32); QPainter painter(&tmpimg); - if (m_page->parentDoc->m_hints & Document::Antialiasing) - painter.setRenderHint(QPainter::Antialiasing); - if (m_page->parentDoc->m_hints & Document::TextAntialiasing) - painter.setRenderHint(QPainter::TextAntialiasing); - painter.translate(x == -1 ? 0 : -x, y == -1 ? 0 : -y); - ArthurOutputDev arthur_output(&painter); - arthur_output.startDoc(m_page->parentDoc->doc->getXRef()); - m_page->parentDoc->doc->displayPageSlice(&arthur_output, - m_page->index + 1, - xres, - yres, - rotation, - false, - true, - false, - x, - y, - w, - h); + renderToPainter(&painter, xres, yres, x, y, w, h, rotate, DontSaveAndRestore); painter.end(); img = tmpimg; break; @@ -278,6 +261,47 @@ QImage Page::renderToImage(double xres, double yres, int x, int y, int w, int h, return img; } +bool Page::renderToPainter(QPainter* painter, double xres, double yres, int x, int y, int w, int h, Rotation rotate, PainterFlags flags) const +{ + if (!painter) + return false; + + switch(m_page->parentDoc->m_backend) + { + case Poppler::Document::SplashBackend: + return false; + case Poppler::Document::ArthurBackend: + { + const bool savePainter = !(flags & DontSaveAndRestore); + if (savePainter) + painter->save(); + if (m_page->parentDoc->m_hints & Document::Antialiasing) + painter->setRenderHint(QPainter::Antialiasing); + if (m_page->parentDoc->m_hints & Document::TextAntialiasing) + painter->setRenderHint(QPainter::TextAntialiasing); + painter->translate(x == -1 ? 0 : -x, y == -1 ? 0 : -y); + ArthurOutputDev arthur_output(painter); + arthur_output.startDoc(m_page->parentDoc->doc->getXRef()); + m_page->parentDoc->doc->displayPageSlice(&arthur_output, + m_page->index + 1, + xres, + yres, + (int)rotate * 90, + false, + true, + false, + x, + y, + w, + h); + if (savePainter) + painter->restore(); + return true; + } + } + return false; +} + QImage Page::thumbnail() const { unsigned char* data = 0; diff --git a/qt4/src/poppler-qt4.h b/qt4/src/poppler-qt4.h index d742973..c50e4f9 100644 --- a/qt4/src/poppler-qt4.h +++ b/qt4/src/poppler-qt4.h @@ -3,9 +3,10 @@ * Copyright (C) 2005, 2007, Brad Hards <[email protected]> * Copyright (C) 2005-2010, Albert Astals Cid <[email protected]> * Copyright (C) 2005, Stefan Kebekus <[email protected]> - * Copyright (C) 2006-2009, Pino Toscano <[email protected]> + * Copyright (C) 2006-2010, Pino Toscano <[email protected]> * Copyright (C) 2009 Shawn Rutledge <[email protected]> * Copyright (C) 2010 Suzuki Toshiya <[email protected]> + * Copyright (C) 2010 Matthias Fauconneau <[email protected]> * * 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 @@ -398,6 +399,22 @@ delete it; RawOrderLayout ///< The text is returned without any type of processing }; + /** + Additional flags for the renderToPainter method + \since 0.16 + */ + enum PainterFlag { + /** + Do not save/restore the caller-owned painter. + + renderToPainter() by default preserves, using save() + restore(), + the state of the painter specified; if this is not needed, this + flag can avoid this job + */ + DontSaveAndRestore = 0x00000001 + }; + Q_DECLARE_FLAGS( PainterFlags, PainterFlag ) + /** Render the page to a QImage using the current \link Document::renderBackend() Document renderer\endlink. @@ -438,6 +455,51 @@ delete it; */ QImage renderToImage(double xres=72.0, double yres=72.0, int x=-1, int y=-1, int w=-1, int h=-1, Rotation rotate = Rotate0) const; + /** + Render the page to the specified QPainter using the current + \link Document::renderBackend() Document renderer\endlink. + + If \p x = \p y = \p w = \p h = -1, the method will automatically + compute the size of the page area from the horizontal and vertical + resolutions specified in \p xres and \p yres. Otherwise, the + method renders only a part of the page, specified by the + parameters (\p x, \p y, \p w, \p h) in pixel coordinates. + + \param painter the painter to paint on + + \param x specifies the left x-coordinate of the box, in + pixels. + + \param y specifies the top y-coordinate of the box, in + pixels. + + \param w specifies the width of the box, in pixels. + + \param h specifies the height of the box, in pixels. + + \param xres horizontal resolution of the graphics device, + in dots per inch + + \param yres vertical resolution of the graphics device, in + dots per inch + + \param rotate how to rotate the page + + \param flags additional painter flags + + \warning The parameter (\p x, \p y, \p w, \p h) are not + well-tested. Unusual or meaningless parameters may lead to + rather unexpected results. + + \returns whether the painting succeeded + + \note This method is only supported for Arthur + + \since 0.16 + */ + bool renderToPainter(QPainter* painter, double xres=72.0, double yres=72.0, int x=-1, int y=-1, int w=-1, int h=-1, + Rotation rotate = Rotate0, PainterFlags flags = 0) const; + /** Get the page thumbnail if it exists. @@ -1626,6 +1688,7 @@ height = dummy.height(); } +Q_DECLARE_OPERATORS_FOR_FLAGS(Poppler::Page::PainterFlags) Q_DECLARE_OPERATORS_FOR_FLAGS(Poppler::Document::RenderHints) Q_DECLARE_OPERATORS_FOR_FLAGS(Poppler::PDFConverter::PDFOptions) Q_DECLARE_OPERATORS_FOR_FLAGS(Poppler::PSConverter::PSOptions) commit df02d1fc9e65422121e5e8f493c13229552ec0e7 Author: Pino Toscano <[email protected]> Date: Sun Nov 7 19:47:56 2010 +0100 [arthur] remove unused 'm_image' attribute diff --git a/poppler/ArthurOutputDev.cc b/poppler/ArthurOutputDev.cc index 7e417c0..54acf12 100644 --- a/poppler/ArthurOutputDev.cc +++ b/poppler/ArthurOutputDev.cc @@ -91,7 +91,6 @@ ArthurOutputDev::ArthurOutputDev(QPainter *painter): m_currentBrush = QBrush(Qt::SolidPattern); m_fontEngine = 0; m_font = 0; - m_image = 0; } ArthurOutputDev::~ArthurOutputDev() diff --git a/poppler/ArthurOutputDev.h b/poppler/ArthurOutputDev.h index 5340318..3fa586b 100644 --- a/poppler/ArthurOutputDev.h +++ b/poppler/ArthurOutputDev.h @@ -16,6 +16,7 @@ // Copyright (C) 2005 Brad Hards <[email protected]> // Copyright (C) 2005 Albert Astals Cid <[email protected]> // Copyright (C) 2009 Carlos Garcia Campos <[email protected]> +// Copyright (C) 2010, 2010 Pino Toscano <[email protected]> // // 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 @@ -150,7 +151,6 @@ private: QPen m_currentPen; QBrush m_currentBrush; GBool m_needFontUpdate; // set when the font needs to be updated - QImage *m_image; SplashFontEngine *m_fontEngine; SplashFont *m_font; // current font XRef *xref; // xref table for current document commit b29582cd0d542a3e70dbca3fb75770daa4cc91ca Author: Matthias Fauconneau <[email protected]> Date: Sun Nov 7 19:44:11 2010 +0100 [arthur] small fixes and memory leaks - fix font rendering (transforming the glyph path and not only the glyph origin) - fix image rendering (alpha was set to zero) diff --git a/poppler/ArthurOutputDev.cc b/poppler/ArthurOutputDev.cc index 7573f3f..7e417c0 100644 --- a/poppler/ArthurOutputDev.cc +++ b/poppler/ArthurOutputDev.cc @@ -18,6 +18,7 @@ // Copyright (C) 2008, 2010 Pino Toscano <[email protected]> // Copyright (C) 2009 Carlos Garcia Campos <[email protected]> // Copyright (C) 2009 Petr Gajdos <[email protected]> +// Copyright (C) 2010 Matthias Fauconneau <[email protected]> // // 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 @@ -269,7 +270,7 @@ void ArthurOutputDev::updateFont(GfxState *state) GfxFontType fontType; SplashOutFontFileID *id; SplashFontFile *fontFile; - SplashFontSrc *fontsrc; + SplashFontSrc *fontsrc = NULL; FoFiTrueType *ff; Ref embRef; Object refObj, strObj; @@ -342,7 +343,7 @@ void ArthurOutputDev::updateFont(GfxState *state) if (fileName) fontsrc->setFile(fileName, gFalse); else - fontsrc->setBuf(tmpBuf, tmpBufLen, gFalse); + fontsrc->setBuf(tmpBuf, tmpBufLen, gTrue); // load the font file switch (fontType) { @@ -484,11 +485,15 @@ void ArthurOutputDev::updateFont(GfxState *state) mat[2] = m21; mat[3] = -m22; m_font = m_fontEngine->getFont(fontFile, mat, matrix); + if (fontsrc && !fontsrc->isFile) + fontsrc->unref(); return; err2: delete id; err1: + if (fontsrc && !fontsrc->isFile) + fontsrc->unref(); return; #endif } @@ -530,7 +535,7 @@ static QPainterPath convertPath(GfxState *state, GfxPath *path, Qt::FillRule fil void ArthurOutputDev::stroke(GfxState *state) { - m_painter->drawPath( convertPath( state, state->getPath(), Qt::OddEvenFill ) ); + m_painter->strokePath( convertPath( state, state->getPath(), Qt::OddEvenFill ), m_currentPen ); } void ArthurOutputDev::fill(GfxState *state) @@ -559,6 +564,7 @@ void ArthurOutputDev::drawChar(GfxState *state, double x, double y, CharCode code, int nBytes, Unicode *u, int uLen) { #ifdef HAVE_SPLASH double x1, y1; + double x2, y2; // SplashPath *path; int render; @@ -577,41 +583,36 @@ void ArthurOutputDev::drawChar(GfxState *state, double x, double y, x -= originX; y -= originY; - state->transform(x, y, &x1, &y1); // fill if (!(render & 1)) { - int x0, y0, xFrac, yFrac; - - x0 = static_cast<int>(floor(x1)); - xFrac = splashFloor((x1 - x0) * splashFontFraction); - y0 = static_cast<int>(floor(y1)); - yFrac = splashFloor((y1 - y0) * splashFontFraction); SplashPath * fontPath; fontPath = m_font->getGlyphPath(code); if (fontPath) { QPainterPath qPath; qPath.setFillRule(Qt::WindingFill); for (int i = 0; i < fontPath->length; ++i) { - if (fontPath->flags[i] & splashPathFirst) { - qPath.moveTo(fontPath->pts[i].x+x0, fontPath->pts[i].y+y0); - } else if (fontPath->flags[i] & splashPathCurve) { - qPath.quadTo(fontPath->pts[i].x+x0, fontPath->pts[i].y+y0, - fontPath->pts[i+1].x+x0, fontPath->pts[i+1].y+y0); - ++i; - } -// FIXME fix this -// else if (fontPath->flags[i] & splashPathArcCW) { -// qDebug() << "Need to implement arc"; -// } - else { - qPath.lineTo(fontPath->pts[i].x+x0, fontPath->pts[i].y+y0); - } - if (fontPath->flags[i] & splashPathLast) { - qPath.closeSubpath(); - } + if (fontPath->flags[i] & splashPathFirst) { + state->transform(fontPath->pts[i].x+x, -fontPath->pts[i].y+y, &x1, &y1); + qPath.moveTo(x1,y1); + } else if (fontPath->flags[i] & splashPathCurve) { + state->transform(fontPath->pts[i].x+x, -fontPath->pts[i].y+y, &x1, &y1); + state->transform(fontPath->pts[i+1].x+x, -fontPath->pts[i+1].y+y, &x2, &y2); + qPath.quadTo(x1,y1,x2,y2); + ++i; + } + // FIXME fix this + // else if (fontPath->flags[i] & splashPathArcCW) { + // qDebug() << "Need to implement arc"; + // } + else { + state->transform(fontPath->pts[i].x+x, -fontPath->pts[i].y+y, &x1, &y1); + qPath.lineTo(x1,y1); + } + if (fontPath->flags[i] & splashPathLast) { + qPath.closeSubpath(); + } } - m_painter->save(); GfxRGB rgb; QColor brushColour = m_currentBrush.color(); state->getFillRGB(&rgb); @@ -622,7 +623,7 @@ void ArthurOutputDev::drawChar(GfxState *state, double x, double y, penColour.setRgbF(colToDbl(rgb.r), colToDbl(rgb.g), colToDbl(rgb.b), state->getStrokeOpacity()); m_painter->setPen(penColour); m_painter->drawPath( qPath ); - m_painter->restore(); + delete fontPath; } } @@ -762,8 +763,8 @@ void ArthurOutputDev::drawImage(GfxState *state, Object *ref, Stream *str, GfxImageColorMap *colorMap, GBool interpolate, int *maskColors, GBool inlineImg) { - unsigned char *buffer; - unsigned int *dest; + unsigned int *data; + unsigned int *line; int x, y; ImageStream *imgStr; Guchar *pix; @@ -771,9 +772,9 @@ void ArthurOutputDev::drawImage(GfxState *state, Object *ref, Stream *str, double *ctm; QMatrix matrix; int is_identity_transform; + QImage image; + int stride; - buffer = (unsigned char *)gmallocn3(width, height, 4); - /* TODO: Do we want to cache these? */ imgStr = new ImageStream(str, width, colorMap->getNumPixelComps(), @@ -786,51 +787,36 @@ void ArthurOutputDev::drawImage(GfxState *state, Object *ref, Stream *str, (colorMap->getColorSpace()->getMode() == csICCBased && ((GfxICCBasedColorSpace*)colorMap->getColorSpace())->getAlt()->getMode() == csDeviceRGB); - if (maskColors) { - for (y = 0; y < height; y++) { - dest = (unsigned int *) (buffer + y * 4 * width); - pix = imgStr->getLine(); - colorMap->getRGBLine (pix, dest, width); + image = QImage(width, height, QImage::Format_ARGB32); + data = (unsigned int *)image.bits(); + stride = image.bytesPerLine()/4; + for (y = 0; y < height; y++) { + pix = imgStr->getLine(); + line = data+y*stride; + colorMap->getRGBLine(pix, line, width); + if (maskColors) { for (x = 0; x < width; x++) { - for (i = 0; i < colorMap->getNumPixelComps(); ++i) { - - if (pix[i] < maskColors[2*i] * 255|| - pix[i] > maskColors[2*i+1] * 255) { - *dest = *dest | 0xff000000; - break; - } - } - pix += colorMap->getNumPixelComps(); - dest++; + for (i = 0; i < colorMap->getNumPixelComps(); ++i) { + if (pix[i] < maskColors[2*i] * 255|| + pix[i] > maskColors[2*i+1] * 255) { + *line = *line | 0xff000000; + break; + } + } + pix += colorMap->getNumPixelComps(); + line++; } + } else { + for (x = 0; x < width; x++) { *line = *line | 0xff000000; line++; } } - - m_image = new QImage(buffer, width, height, QImage::Format_ARGB32); - } - else { - for (y = 0; y < height; y++) { - dest = (unsigned int *) (buffer + y * 4 * width); - pix = imgStr->getLine(); - colorMap->getRGBLine (pix, dest, width); - } - - m_image = new QImage(buffer, width, height, QImage::Format_RGB32); } - if (m_image == NULL || m_image->isNull()) { - qDebug() << "Null image"; - delete imgStr; - return; - } ctm = state->getCTM(); matrix.setMatrix(ctm[0] / width, ctm[1] / width, -ctm[2] / height, -ctm[3] / height, ctm[2] + ctm[4], ctm[3] + ctm[5]); m_painter->setMatrix(matrix, true); - m_painter->drawImage( QPoint(0,0), *m_image ); - delete m_image; - m_image = 0; - free (buffer); + m_painter->drawImage( QPoint(0,0), image ); delete imgStr; } _______________________________________________ poppler mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/poppler
