/* * Copyright (c) 2002 Nicolas HADACEK (hadacek@kde.org) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "FilterDevice.h" #include #include #include #include "GfxState.h" #include "Link.h" #include "FilterPage.h" #include "data.h" #include "dialog.h" namespace PDFImport { Device::Device(Data &data) : _data(data), _fillColor(TQt::white), _strokeColor(TQt::black) { _pages.setAutoDelete(true); } Device::~Device() { clear(); } void Device::clear() { _images.clear(); } void Device::init() { // get some global infos on frames size const double maxH = _data.pageRect().bottom(); const double maxR = _data.pageRect().right(); double maxHeaderBottom = 0; double minBodyTop = maxH; double minHeaderBodyDelta = maxH; double maxBodyBottom = 0; double minFooterTop = maxH; double minBodyFooterDelta = maxH; double minLeft = maxR; double maxRight = 0; for (Page *page = _pages.first(); page; page = _pages.next()) { const DRect &hr = page->rects()[Header]; const DRect &br = page->rects()[Body]; const DRect &fr = page->rects()[Footer]; if ( hr.isValid() ) { maxHeaderBottom = kMax(maxHeaderBottom, hr.bottom()); if ( br.isValid() ) minHeaderBodyDelta = kMin(minHeaderBodyDelta, br.top() - hr.bottom()); minLeft = kMin(minLeft, hr.left()); maxRight = kMax(maxRight, hr.right()); } if ( fr.isValid() ) { minFooterTop = kMin(minFooterTop, fr.top()); if ( br.isValid() ) minBodyFooterDelta = kMin(minBodyFooterDelta, fr.top() - br.bottom()); minLeft = kMin(minLeft, fr.left()); maxRight = kMax(maxRight, fr.right()); } if ( br.isValid() ) { minBodyTop = kMin(minBodyTop, br.top()); maxBodyBottom = kMax(maxBodyBottom, br.bottom()); minLeft = kMin(minLeft, br.left()); maxRight = kMax(maxRight, br.right()); } } // set minimal top and maximal bottom to body frame double minTop = kMax(maxHeaderBottom+minHeaderBodyDelta, minBodyTop); double maxBottom = kMin(minFooterTop-minBodyFooterDelta, maxBodyBottom); for (Page *page = _pages.first(); page; page = _pages.next()) { DRect &r = page->rects()[Body]; if ( r.top()>minTop ) r.setTop(minTop); if ( r.bottom()rects()[Header]; if ( hr.isValid() ) { if ( hr.left()>minLeft ) hr.setLeft(minLeft); if ( hr.right()rects()[Footer]; if ( fr.isValid() ) { if ( fr.left()>minLeft ) fr.setLeft(minLeft); if ( fr.right()rects(), page->pictures); page->dump(); } void Device::startPage(int, GfxState *) { _pages.append( new Page(_data) ); } void Device::endPage() { if ( !_currentImage.image.isNull() ) addImage(); current()->endPage(); clear(); kdDebug(30516) << "-- end page --------------------------" << endl; } void Device::updateFont(GfxState *state) { current()->updateFont(state); } void Device::beginString(GfxState *state, GString *) { current()->beginString(state, state->getCurX(), state->getCurY()); } void Device::endString(GfxState *) { current()->endString(); } void Device::drawChar(GfxState *state, double x, double y, double dx, double dy, double, double, CharCode, Unicode *u, int uLen) { current()->addChar(state, x, y, dx, dy, u, uLen); } void Device::drawLink(::Link* link, Catalog *cat) { double x1, y1, x2, y2, w; link->getBorder(&x1, &y1, &x2, &y2, &w); int ux1, uy1, ux2, uy2; cvtUserToDev(x1, y1, &ux1, &uy1); cvtUserToDev(x2, y2, &ux2, &uy2); DRect r(kMin(ux1, ux2), kMax(ux1, ux2), kMin(uy1, uy2), kMax(uy1, uy2)); Link *l = new Link(r, *link->getAction(), *cat); current()->addLink(l); } void Device::addImage() { // kdDebug(30516) << "-> add image" << endl; if ( _currentImage.image.width()==0 || _currentImage.image.height()==0 ) { kdDebug(30516) << "image has null width or height !" << endl; _currentImage = Image(); return; } // check if same image already put at same place (don't know why it // appends sometimes : related to KWord printing to pdf ?) ImageList::iterator it; for (it=_images.begin(); it!=_images.end(); ++it) { if ( (*it).rect==_currentImage.rect && (*it).image==_currentImage.image ) { kdDebug(30516) << "image already there !\n"; _currentImage = Image(); return; } } // add image TQString name = TQString("pictures/picture%1.png").arg(_data.imageIndex()); TQDomElement frameset = _data.pictureFrameset(_currentImage.rect); current()->pictures.append(frameset); TQDomElement picture = _data.createElement("PICTURE"); picture.setAttribute("keepAspectRatio", "false"); frameset.appendChild(picture); TQDomElement key = _data.createElement("KEY"); key.setAttribute("msec", 0); key.setAttribute("second", 0); key.setAttribute("minute", 0); key.setAttribute("hour", 0); key.setAttribute("day", 1); key.setAttribute("month", 1); key.setAttribute("year", 1970); key.setAttribute("filename", name); picture.appendChild(key); key = _data.createElement("KEY"); key.setAttribute("msec", 0); key.setAttribute("second", 0); key.setAttribute("minute", 0); key.setAttribute("hour", 0); key.setAttribute("day", 1); key.setAttribute("month", 1); key.setAttribute("year", 1970); key.setAttribute("filename", name); key.setAttribute("name", name); _data.pictures().appendChild(key); KoStoreDevice *sd = _data.chain()->storageFile(name, KoStore::Write); TQImageIO io(sd, "PNG"); io.setImage(_currentImage.image); bool ok = io.write(); Q_ASSERT(ok); sd->close(); _images.append(_currentImage); _currentImage = Image(); } void Device::computeGeometry(GfxState *state, Image &image) { double xt, yt, wt, ht; state->transform(0, 0, &xt, &yt); state->transformDelta(1, 1, &wt, &ht); image.rect.setLeft(xt + (wt>0 ? 0 : wt)); image.rect.setRight(image.rect.left() + fabs(wt)); image.rect.setTop(yt + (ht>0 ? 0 : ht)); image.rect.setBottom(image.rect.top() + fabs(ht)); // #### TODO : take care of image transform (rotation,...) } uint Device::initImage(GfxState *state, int width, int height, bool withMask) { // get image geometry Image image; image.mask = withMask; computeGeometry(state, image); // check if new image // kdDebug(30516) << "current image " << _currentImage.image.width() // << " " << _currentImage.rect.left() // << " " << _currentImage.rect.right() // << " " << _currentImage.rect.bottom() // << " " << _currentImage.mask << endl; // kdDebug(30516) << "new image " << width // << " " << image.rect.left() << " " << image.rect.right() // << " " << image.rect.top() // << " " << image.mask << endl; if ( !_currentImage.image.isNull() && (_currentImage.image.width()!=width || !equal(image.rect.left(), _currentImage.rect.left()) || !equal(image.rect.right(), _currentImage.rect.right()) || !equal(image.rect.top(), _currentImage.rect.bottom()) || image.mask!=_currentImage.mask) ) addImage(); uint offset = (_currentImage.image.isNull() ? 0 : _currentImage.image.height()); image.image = TQImage(width, offset + height, 32); image.image.setAlphaBuffer(withMask); if ( !_currentImage.image.isNull() ) { // copy previous // kdDebug(30516) << "image continued..." << endl; for (int j=0; j<_currentImage.image.height(); j++) { TQRgb *pix = (TQRgb *)_currentImage.image.scanLine(j); TQRgb *newPix = (TQRgb *)image.image.scanLine(j); for (int i=0; igetPath(); uint nbPaths = path->getNumSubpaths(); DPathVector vector; for (uint i=0; igetSubpath(i); uint nbPoints = spath->getNumPoints(); DPath dpath; for (uint k=0; k=1 && spath->getCurve(k) ) { kdDebug(30516) << " bezier curve : ignore !" << endl; dpath = DPath(); break; } else { DPoint dpoint; state->transform(spath->getX(k), spath->getY(k), &dpoint.x, &dpoint.y); dpath.push_back(dpoint); } } if ( dpath.size()!=0 ) vector.push_back(dpath); } return vector; } } // namespace