diff options
Diffstat (limited to 'kfaxview')
-rw-r--r-- | kfaxview/Makefile.am | 38 | ||||
-rw-r--r-- | kfaxview/faxmultipage.cpp | 85 | ||||
-rw-r--r-- | kfaxview/faxmultipage.h | 120 | ||||
-rw-r--r-- | kfaxview/faxrenderer.cpp | 204 | ||||
-rw-r--r-- | kfaxview/faxrenderer.h | 90 | ||||
-rw-r--r-- | kfaxview/hi16-app-kfaxview.png | bin | 0 -> 787 bytes | |||
-rw-r--r-- | kfaxview/hi22-app-kfaxview.png | bin | 0 -> 1241 bytes | |||
-rw-r--r-- | kfaxview/hi32-app-kfaxview.png | bin | 0 -> 1928 bytes | |||
-rw-r--r-- | kfaxview/hi48-app-kfaxview.png | bin | 0 -> 3352 bytes | |||
-rw-r--r-- | kfaxview/hisc-app-kfaxview.svgz | bin | 0 -> 11876 bytes | |||
-rw-r--r-- | kfaxview/kfaxmultipage.desktop | 60 | ||||
-rw-r--r-- | kfaxview/kfaxmultipage_tiff.desktop | 57 | ||||
-rw-r--r-- | kfaxview/kfaxview.desktop | 82 | ||||
-rw-r--r-- | kfaxview/libkfaximage/Makefile.am | 14 | ||||
-rw-r--r-- | kfaxview/libkfaximage/faxexpand.cpp | 745 | ||||
-rw-r--r-- | kfaxview/libkfaximage/faxexpand.h | 126 | ||||
-rw-r--r-- | kfaxview/libkfaximage/faxinit.cpp | 345 | ||||
-rw-r--r-- | kfaxview/libkfaximage/kfaximage.cpp | 667 | ||||
-rw-r--r-- | kfaxview/libkfaximage/kfaximage.h | 162 | ||||
-rw-r--r-- | kfaxview/main.cpp | 174 |
20 files changed, 2969 insertions, 0 deletions
diff --git a/kfaxview/Makefile.am b/kfaxview/Makefile.am new file mode 100644 index 00000000..669fcd9b --- /dev/null +++ b/kfaxview/Makefile.am @@ -0,0 +1,38 @@ +INCLUDES = -I$(top_srcdir)/kviewshell \ + -I$(top_builddir)/kviewshell \ + -I$(kde_includes)/kviewshell \ + -I$(srcdir)/libkfaximage \ + -I$(top_srcdir) $(all_includes) + +SUBDIRS = libkfaximage . + +KDE_ICON = kfaxview + +METASOURCES = AUTO + +bin_PROGRAMS = kfaxview +kfaxview_SOURCES = main.cpp +kfaxview_LDFLAGS = $(all_libraries) $(KDE_RPATH) +kfaxview_LDADD = ../kviewshell/libifaces.la ../kviewshell/libkviewshell.la -lkparts + +# this is where the desktop file will go +kde_services_DATA = kfaxmultipage.desktop kfaxmultipage_tiff.desktop + +# this is where the shell's XML-GUI resource file goes +shellrcdir = $(kde_datadir)/kfaxview + +kde_module_LTLIBRARIES = kfaxviewpart.la +kfaxviewpart_la_LDFLAGS = $(all_libraries) $(KDE_PLUGIN) -module +kfaxviewpart_la_LIBADD = -lkdeprint -lkparts $(top_builddir)/kviewshell/libkmultipage.la libkfaximage/libkfaximage.la +kfaxviewpart_la_SOURCES = faxmultipage.cpp faxrenderer.cpp + +partdir = $(kde_datadir)/kfaxview +part_DATA = ../kviewshell/kviewshell.rc + +messages: rc.cpp + $(XGETTEXT) *.cpp -o $(podir)/kfaxview.pot + +xdg_apps_DATA = kfaxview.desktop + +# The next line switches the API documentation on +include ../admin/Doxyfile.am diff --git a/kfaxview/faxmultipage.cpp b/kfaxview/faxmultipage.cpp new file mode 100644 index 00000000..bbf4e566 --- /dev/null +++ b/kfaxview/faxmultipage.cpp @@ -0,0 +1,85 @@ +/*************************************************************************** + * Copyright (C) 2005 by Stefan Kebekus * + * kebekus@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 <config.h> + +#include <kfiledialog.h> +#include <kparts/genericfactory.h> + +#include "faxmultipage.h" + + + +typedef KParts::GenericFactory<FaxMultiPage> FaxMultiPageFactory; +K_EXPORT_COMPONENT_FACTORY(kfaxviewpart, FaxMultiPageFactory) + + +FaxMultiPage::FaxMultiPage(QWidget *parentWidget, const char *widgetName, QObject *parent, + const char *name, const QStringList&) + : KMultiPage(parentWidget, widgetName, parent, name), faxRenderer(parentWidget) +{ + /* This is kparts wizardry that cannot be understood by man. Simply + change the names to match your implementation. */ + setInstance(FaxMultiPageFactory::instance()); + faxRenderer.setName("Fax renderer"); + + setXMLFile("kfaxview.rc"); + + /* It is very important that this method is called in the + constructor. Otherwise kmultipage does not know how to render + files, and crashes may result. */ + setRenderer(&faxRenderer); +} + + +FaxMultiPage::~FaxMultiPage() +{ + ; +} + + +KAboutData* FaxMultiPage::createAboutData() +{ + /* You obviously want to change this to match your setup */ + KAboutData* about = new KAboutData("kfaxview", I18N_NOOP("KFaxView"), "0.1", + I18N_NOOP("KViewshell Fax Plugin."), + KAboutData::License_GPL, + "Stefan Kebekus", + I18N_NOOP("This program previews fax (g3) files.")); + + about->addAuthor ("Stefan Kebekus", + I18N_NOOP("Current Maintainer."), + "kebekus@kde.org", + "http://www.mi.uni-koeln.de/~kebekus"); + return about; +} + + +QStringList FaxMultiPage::fileFormats() const +{ + /* This list is used in the file selection dialog when the file is + saved */ + QStringList r; + r << i18n("*.g3|Fax (g3) file (*.g3)"); + return r; +} + + +#include "faxmultipage.moc" diff --git a/kfaxview/faxmultipage.h b/kfaxview/faxmultipage.h new file mode 100644 index 00000000..1ea8b6c5 --- /dev/null +++ b/kfaxview/faxmultipage.h @@ -0,0 +1,120 @@ +/*************************************************************************** + * Copyright (C) 2005 by Stefan Kebekus * + * kebekus@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. * + ***************************************************************************/ + +#ifndef FAXMULTIPAGE_H +#define FAXMULTIPAGE_H + +#include <qstringlist.h> + +#include "kmultipage.h" +#include "faxrenderer.h" + + + +/*! \mainpage FaxMultiPage + +\section intro_sec Introduction + +FaxMultiPage is a minimal, but well-documented reference +implementation of a kviewshell plugin that can serve as a starting +point for implementations. + +\section install_sec Usage + +When FaxMultiPage and the associated files are installed, the +kviewshell program can open TIFF-Fax anf G3 fax files, i.e. files of +mime types image/fax-g3 or image/tiff. + +\section content Content + +Only the two classes that are absolutely necessary for a working +plugin are implemented. The only other file that is installed are +desktop file, which tells kviewshell to use the plugin. + +- FaxMultiPage, an implementation of a KMultiPage. In a larger +application, this class would contain the GUI elements that the plugin +adds to the GUI of the kviewshell. For viewing FAXes, no special GUI +elements are required, and this plugin does only the minimal +initialization required. + +- FaxRenderer, an implementation of a DocumentRenderer. This class is +responsible for document loading and rendering. + +- kfaxmultipage.desktop and kfaxmultipage_tiff.desktop are desktop +entry files that associate the plugin wit image/fax-g3 or image/tiff +mime-types. Without these files installed, the file dialog in +kviewshell would not show FAX files, and the command line "kvieshell +test.g3" would fail with an error dialog "No plugin for image/fax-g3 +files installed". +*/ + + + + +/*! \brief Well-documented minimal implementation of a KMultiPage + +This class provides a well-documented reference implementation of a +KMultiPage, suitable as a starting point for a real-world +implementation. In a larger application, this class would contain the +GUI elements that the plugin adds to the GUI of the kviewshell. For +viewing FAXes, no special GUI elements are required, and this plugin +does only the minimal initialization required. +*/ + +class FaxMultiPage : public KMultiPage +{ + Q_OBJECT + +public: + /** Constructor + + The constructor needs to initialize several members of the + kmultipage. Please have a look at the constructor's source code to + see how to adjust this for your implementation. + */ + FaxMultiPage(QWidget *parentWidget, const char *widgetName, QObject *parent, + const char *name, const QStringList& args = QStringList()); + + /** Destructor + + This destructor does nothing. + */ + virtual ~FaxMultiPage(); + + /** List of file formats for file saving + + This method returns the list of supported file formats for saving + the file. + */ + virtual QStringList fileFormats() const; + + /** Author information + + This member returns a structure that contains information about the + authors of the implementation + */ + static KAboutData* createAboutData(); + + private: + /** This member holds the renderer which is used by the demo implementation */ + FaxRenderer faxRenderer; +}; + +#endif diff --git a/kfaxview/faxrenderer.cpp b/kfaxview/faxrenderer.cpp new file mode 100644 index 00000000..ec18d431 --- /dev/null +++ b/kfaxview/faxrenderer.cpp @@ -0,0 +1,204 @@ +/*************************************************************************** + * Copyright (C) 2005 by Stefan Kebekus * + * kebekus@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 <config.h> + +#include <kmessagebox.h> +#include <kdebug.h> +#include <klocale.h> +#include <qfileinfo.h> +#include <qpainter.h> + +#include "documentWidget.h" +#include "faxrenderer.h" +#include "faxmultipage.h" + +//#define KF_DEBUG + +FaxRenderer::FaxRenderer(QWidget* par) + : DocumentRenderer(par) +{ +#ifdef KF_DEBUG + kdError() << "FaxRenderer( parent=" << par << " )" << endl; +#endif +} + + + +FaxRenderer::~FaxRenderer() +{ +#ifdef KF_DEBUG + kdDebug() << "~FaxRenderer" << endl; +#endif + + // Wait for all access to this documentRenderer to finish + mutex.lock(); + mutex.unlock(); +} + + +void FaxRenderer::drawPage(double resolution, RenderedDocumentPage* page) +{ +#ifdef KF_DEBUG + kdDebug() << "FaxRenderer::drawPage(documentPage*) called, page number " << page->getPageNumber() << endl; +#endif + + // Paranoid safety checks + if (page == 0) { + kdError() << "FaxRenderer::drawPage(documentPage*) called with argument == 0" << endl; + return; + } + if (page->getPageNumber() == 0) { + kdError() << "FaxRenderer::drawPage(documentPage*) called for a documentPage with page number 0" << endl; + return; + } + + // Wait for all access to this documentRenderer to finish + mutex.lock(); + + // more paranoid safety checks + if (page->getPageNumber() > numPages) { + kdError() << "FaxRenderer::drawPage(documentPage*) called for a documentPage with page number " << page->getPageNumber() + << " but the current fax file has only " << numPages << " pages." << endl; + mutex.unlock(); + return; + } + + QImage img = fax.page(page->getPageNumber() - 1); + + SimplePageSize psize = pageSizes[page->getPageNumber() - 1]; + if (psize.isValid()) { + QPainter *foreGroundPaint = page->getPainter(); + if (foreGroundPaint != 0) { + // Compute an image for the page. + + // WARNING: It may be tempting to compute the image size in + // pixel, using page->height() and page->width(). DON'T DO + // THAT. KViewShell uses transformations e.g. to rotate the + // page, and sets the argument 'resolution' accordingly. Similar + // problems occur if KViewShell required a shrunken version of + // the page, e.g. to print multiple pages on one sheet of paper. + + int width_in_pixel = qRound(resolution * psize.width().getLength_in_inch()); + int height_in_pixel = qRound(resolution * psize.height().getLength_in_inch()); + + img = img.smoothScale(width_in_pixel, height_in_pixel); + foreGroundPaint->drawImage(0, 0, img); + page->returnPainter(foreGroundPaint); + } + } else + kdError() << "FaxRenderer::drawPage() called, but page size for page " << page->getPageNumber() << " is invalid." << endl; + + // To indicate that the page was drawn, we set the appropriate flas in the page structure + page->isEmpty = false; + + mutex.unlock(); +} + + +bool FaxRenderer::setFile(const QString &fname, const KURL &) +{ +#ifdef KF_DEBUG + kdDebug() << "FaxRenderer::setFile(" << fname << ") called" << endl; +#endif + + // Wait for all access to this documentRenderer to finish + mutex.lock(); + + // If fname is the empty string, then this means: "close". + if (fname.isEmpty()) { + kdDebug() << "FaxRenderer::setFile( ... ) called with empty filename. Closing the file." << endl; + mutex.unlock(); + return true; + } + + // Paranoid saftey checks: make sure the file actually exists, and + // that it is a file, not a directory. Otherwise, show an error + // message and exit.. + QFileInfo fi(fname); + QString filename = fi.absFilePath(); + if (!fi.exists() || fi.isDir()) { + KMessageBox::error( parentWidget, + i18n("<qt><strong>File error.</strong> The specified file '%1' does not exist.</qt>").arg(filename), + i18n("File Error")); + // the return value 'false' indicates that this operation was not successful. + mutex.unlock(); + return false; + } + + // Now we assume that the file is fine and load the file into the + // fax member. We abort on error and give an error message. + bool ok = fax.loadImage(filename); + + // It can happen that fax.loadImage() returns with 'ok == true', but + // still the file could NOT be loaded. This happens, e.g. for TIFF + // file that do NOT contain FAX, but other image formats. We handle + // that case here also. + if ( (!ok) || (fax.numPages() == 0)) { + // Unfortunately, it can happen that fax.loadImage() fails WITHOUT + // leaving an error message in fax.errorString(). We try to handle + // this case gracefully. + if (fax.errorString().isEmpty()) + KMessageBox::error( parentWidget, + i18n("<qt><strong>File error.</strong> The specified file '%1' could not be loaded.</qt>").arg(filename), + i18n("File Error")); + else + KMessageBox::detailedError( parentWidget, + i18n("<qt><strong>File error.</strong> The specified file '%1' could not be loaded.</qt>").arg(filename), + fax.errorString(), + i18n("File Error")); + clear(); + mutex.unlock(); + return false; + } + + // Set the number of pages page sizes + numPages = fax.numPages(); + + // Set the page size for the first page in the pageSizes array. + // The rest of the page sizes will be calculated on demand by the drawPage function. + pageSizes.resize(numPages); + Length w,h; + + if (numPages != 0) { + for(Q_UINT16 pg=0; pg < numPages; pg++) { + QSize pageSize = fax.page_size(pg); + QPoint dpi = fax.page_dpi(pg); + double dpix = dpi.x(); + double dpiy = dpi.y(); + + if (dpix*dpiy < 1.0) { + kdError() << "File invalid resolutions, dpi x = " << dpix << ", dpi y = " << dpiy << ". This information will be ignored and 75 DPI assumed." << endl; + dpix = dpiy = 75.0; + } + + w.setLength_in_inch(pageSize.width() / dpix); + h.setLength_in_inch(pageSize.height() / dpiy); + pageSizes[pg].setPageSize(w, h); + } + } + + // the return value 'true' indicates that this operation was not successful. + mutex.unlock(); + return true; +} + + +#include "faxrenderer.moc" diff --git a/kfaxview/faxrenderer.h b/kfaxview/faxrenderer.h new file mode 100644 index 00000000..d2b37657 --- /dev/null +++ b/kfaxview/faxrenderer.h @@ -0,0 +1,90 @@ +/*************************************************************************** + * Copyright (C) 2005 by Stefan Kebekus * + * kebekus@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. * + ***************************************************************************/ + +#ifndef _FAXRENDERER_H_ +#define _FAXRENDERER_H_ + + +#include "documentRenderer.h" +#include "kfaximage.h" + +class documentPage; + +/*! \brief Well-documented minimal implementation of a documentRenderer for reading FAX files + +This class provides a well-documented reference implementation of a +documentRenderer, suitable as a starting point for a real-world +implementation. This class is responsible for document loading and +rendering. Apart from the constructor and the descructor, it +implements only the necessary methods setFile() and drawPage(). +*/ + +class FaxRenderer : public DocumentRenderer +{ + Q_OBJECT + +public: + /** Default constructor + + This constructor simply prints a message (if debugging is + enabled) and calls the default constructor. + */ + FaxRenderer(QWidget* parent); + + /** Destructor + + The destructor simpley prints a message if debugging is + enabled. It uses the mutex to ensure that this class is not + destructed while another thread is currently using it. + */ + ~FaxRenderer(); + + /** Opening a file + + This implementation does the necessary consistency checks and + complains, e.g. if the file does not exist. It then uses the + member 'fax' to load the fax file and initializes the + appropriate data structures. The code for loading and rendering + is contained in the class "KFaxImage", to keep this reference + implementation short. + + @param fname the name of the file that should be opened. + */ + virtual bool setFile(const QString& fname, const KURL &); + + /** Rendering a page + + This implementation first checks if the arguments are in a + reasonable range, and error messages are printed if this is not + so. Secondly, the page is rendered by the KFaxImage class and + the drawn. + + @param res resolution at which drawing should take place + + @param page pointer to a page structur on which we should draw + */ + void drawPage(double res, RenderedDocumentPage* page); + +private: + /** This class holds the fax file */ + KFaxImage fax; +}; + +#endif diff --git a/kfaxview/hi16-app-kfaxview.png b/kfaxview/hi16-app-kfaxview.png Binary files differnew file mode 100644 index 00000000..bb676f8b --- /dev/null +++ b/kfaxview/hi16-app-kfaxview.png diff --git a/kfaxview/hi22-app-kfaxview.png b/kfaxview/hi22-app-kfaxview.png Binary files differnew file mode 100644 index 00000000..90fc64b0 --- /dev/null +++ b/kfaxview/hi22-app-kfaxview.png diff --git a/kfaxview/hi32-app-kfaxview.png b/kfaxview/hi32-app-kfaxview.png Binary files differnew file mode 100644 index 00000000..7330eb41 --- /dev/null +++ b/kfaxview/hi32-app-kfaxview.png diff --git a/kfaxview/hi48-app-kfaxview.png b/kfaxview/hi48-app-kfaxview.png Binary files differnew file mode 100644 index 00000000..3f58c369 --- /dev/null +++ b/kfaxview/hi48-app-kfaxview.png diff --git a/kfaxview/hisc-app-kfaxview.svgz b/kfaxview/hisc-app-kfaxview.svgz Binary files differnew file mode 100644 index 00000000..f46fd440 --- /dev/null +++ b/kfaxview/hisc-app-kfaxview.svgz diff --git a/kfaxview/kfaxmultipage.desktop b/kfaxview/kfaxmultipage.desktop new file mode 100644 index 00000000..1bfc9acc --- /dev/null +++ b/kfaxview/kfaxmultipage.desktop @@ -0,0 +1,60 @@ +[Desktop Entry] +Name=kfaxview +Name[hu]=KFaxView +Name[ja]=KfaxView +Name[nb]=Kfaxview +Name[ne]=केडीई फ्याक्स दृश्य +Name[ro]=KFaxiView +Name[sv]=Kfaxview +Name[zh_CN]=KFaxView +Icon=kfaxview +Type=Service +Comment=KViewShell plugin for fax files +Comment[bg]=Приставка за факс файлове +Comment[br]=Lugent KViewShell evit ar restroù faks +Comment[bs]=KViewShell dodatak za fax datoteke +Comment[ca]=Connector pel KViewShell per a fitxers de fax +Comment[cs]=KViewShell modul pro faxové soubory +Comment[da]=Kviewshell-plugin for telefaxfiler +Comment[de]=Ein Modul für KViewShell zum Betrachten von Faxdateien +Comment[el]=Πρόσθετο του KViewShell για αρχεία φαξ +Comment[eo]=KViewShell-kromaĵo for faksdosieroj +Comment[es]=Extensión KViewShell para archivos de fax +Comment[et]=KView faksifailide plugin +Comment[eu]=Fax fitxategientzatko KViewShell-en plugina +Comment[fa]=وصلۀ KViewShell برای پروندههای دورنگار +Comment[fi]=KViewShell sovelma faksitiedostoille +Comment[fr]=Module KViewShell pour les fichiers de fax +Comment[gl]=Extensión de KViewShell para ficheiros de fax +Comment[hu]=KViewShell-modul faxfájlokhoz +Comment[is]=KViewShell íforrit fyrir faxskrár +Comment[it]=Plugin KViewShell per file di fax +Comment[ja]=ファクスファイル用の KViewShell プラグイン +Comment[kk]=Факс файлдарын қарау плагин модулі +Comment[km]=កម្មវិធីជំនួយ KViewShell សម្រាប់ឯកសារទូរសារ +Comment[lt]=KViewShell priedas fakso byloms +Comment[ms]=Plugin KViewShell untuk fail faks +Comment[nb]=KViewShell programtillegg for faksfiler +Comment[nds]="KViewShell"-Moduul för Faxdateien +Comment[ne]=फ्याक्स फाइलका लागि केडीई दृश्य शेल प्लगइन +Comment[nl]=KViewShell-plugin voor faxbestanden +Comment[nn]=KViewShell-programtillegg for faksfiler +Comment[pl]=Wtyczka KViewShell do plików faksów +Comment[pt]='Plugin' do KViewShell para ficheiros de Fax +Comment[pt_BR]=Plugin KViewShell para arquivos de fax +Comment[ru]=Компонент просмотра факсов +Comment[sk]=KViewShell modul pre faxové súbory +Comment[sl]=Vstavek za KViewShell za fakse +Comment[sr]=KViewShell-ов прикључак за факс фајлове +Comment[sr@Latn]=KViewShell-ov priključak za faks fajlove +Comment[sv]=Kviewshell-insticksprogram för telefaxfiler +Comment[th]=ปลั๊กอินสำหรับแสดงแฟ้มโทรสารของ KViewShell +Comment[tr]=Faks dosyaları için KViewShell eklentisi +Comment[uk]=Втулок перегляду файлів факсів для KViewShell +Comment[zh_CN]=传真文件的 KViewShell 插件 +Comment[zh_HK]=傳真檔的 KViewShell 插件 +Comment[zh_TW]=KViewShell 傳真檔外掛程式 +ServiceTypes=KViewShell/MultiPage +X-KDE-MimeTypes=image/fax-g3 +X-KDE-Library=kfaxviewpart +X-KDE-MultiPageVersion=2 diff --git a/kfaxview/kfaxmultipage_tiff.desktop b/kfaxview/kfaxmultipage_tiff.desktop new file mode 100644 index 00000000..a1b33913 --- /dev/null +++ b/kfaxview/kfaxmultipage_tiff.desktop @@ -0,0 +1,57 @@ +[Desktop Entry] +Name=kfaxview_tiff +Name[da]=Kfaxview TIFF +Name[ne]=केडीई फ्याक्स दृश्य टिफ +Name[sv]=Kfaxview TIFF +Name[zh_CN]=KFaxView_tiff +Icon=kfaxview +Type=Service +Comment=KViewShell plugin for fax files +Comment[bg]=Приставка за факс файлове +Comment[br]=Lugent KViewShell evit ar restroù faks +Comment[bs]=KViewShell dodatak za fax datoteke +Comment[ca]=Connector pel KViewShell per a fitxers de fax +Comment[cs]=KViewShell modul pro faxové soubory +Comment[da]=Kviewshell-plugin for telefaxfiler +Comment[de]=Ein Modul für KViewShell zum Betrachten von Faxdateien +Comment[el]=Πρόσθετο του KViewShell για αρχεία φαξ +Comment[eo]=KViewShell-kromaĵo for faksdosieroj +Comment[es]=Extensión KViewShell para archivos de fax +Comment[et]=KView faksifailide plugin +Comment[eu]=Fax fitxategientzatko KViewShell-en plugina +Comment[fa]=وصلۀ KViewShell برای پروندههای دورنگار +Comment[fi]=KViewShell sovelma faksitiedostoille +Comment[fr]=Module KViewShell pour les fichiers de fax +Comment[gl]=Extensión de KViewShell para ficheiros de fax +Comment[hu]=KViewShell-modul faxfájlokhoz +Comment[is]=KViewShell íforrit fyrir faxskrár +Comment[it]=Plugin KViewShell per file di fax +Comment[ja]=ファクスファイル用の KViewShell プラグイン +Comment[kk]=Факс файлдарын қарау плагин модулі +Comment[km]=កម្មវិធីជំនួយ KViewShell សម្រាប់ឯកសារទូរសារ +Comment[lt]=KViewShell priedas fakso byloms +Comment[ms]=Plugin KViewShell untuk fail faks +Comment[nb]=KViewShell programtillegg for faksfiler +Comment[nds]="KViewShell"-Moduul för Faxdateien +Comment[ne]=फ्याक्स फाइलका लागि केडीई दृश्य शेल प्लगइन +Comment[nl]=KViewShell-plugin voor faxbestanden +Comment[nn]=KViewShell-programtillegg for faksfiler +Comment[pl]=Wtyczka KViewShell do plików faksów +Comment[pt]='Plugin' do KViewShell para ficheiros de Fax +Comment[pt_BR]=Plugin KViewShell para arquivos de fax +Comment[ru]=Компонент просмотра факсов +Comment[sk]=KViewShell modul pre faxové súbory +Comment[sl]=Vstavek za KViewShell za fakse +Comment[sr]=KViewShell-ов прикључак за факс фајлове +Comment[sr@Latn]=KViewShell-ov priključak za faks fajlove +Comment[sv]=Kviewshell-insticksprogram för telefaxfiler +Comment[th]=ปลั๊กอินสำหรับแสดงแฟ้มโทรสารของ KViewShell +Comment[tr]=Faks dosyaları için KViewShell eklentisi +Comment[uk]=Втулок перегляду файлів факсів для KViewShell +Comment[zh_CN]=传真文件的 KViewShell 插件 +Comment[zh_HK]=傳真檔的 KViewShell 插件 +Comment[zh_TW]=KViewShell 傳真檔外掛程式 +ServiceTypes=KViewShell/MultiPage +X-KDE-MimeTypes=image/tiff +X-KDE-Library=kfaxviewpart +X-KDE-MultiPageVersion=2 diff --git a/kfaxview/kfaxview.desktop b/kfaxview/kfaxview.desktop new file mode 100644 index 00000000..4dc74ff1 --- /dev/null +++ b/kfaxview/kfaxview.desktop @@ -0,0 +1,82 @@ +[Desktop Entry] +GenericName=Fax Viewer +GenericName[af]=Faks Aansig +GenericName[ar]=عارض الفاكس +GenericName[bg]=Преглед на факсове +GenericName[br]=Gweler faks +GenericName[bs]=Preglednik faxova +GenericName[ca]=Visualitzador de fax +GenericName[cs]=Prohlížeč faxů +GenericName[cy]=Gwelydd Ffacs +GenericName[da]=Fax-fremviser +GenericName[de]=Faxbetrachter +GenericName[el]=Προβολέας φαξ +GenericName[eo]=Faksrigardilo +GenericName[es]=Visor de faxes +GenericName[et]=Fakside vaataja +GenericName[eu]=Fax ikustailua +GenericName[fa]=مشاهدهگر دورنگار +GenericName[fi]=Faksinäytin +GenericName[fr]=Afficheur de fax +GenericName[gl]=Visor de fax +GenericName[he]=מציג פקסים +GenericName[hi]=फ़ैक्स प्रदर्शक +GenericName[hr]=Preglednik faksova +GenericName[hu]=Faxnézegető +GenericName[is]=Fax sjá +GenericName[it]=Visore di fax +GenericName[ja]=ファクスビューア +GenericName[kk]=Факсты қарау +GenericName[km]=កម្មវិធីមើលទូរសារ +GenericName[lt]=Faksų žiūriklis +GenericName[lv]=Faksu Skatītājs +GenericName[ms]=Pemapar Faks +GenericName[nb]=Faksfremviser +GenericName[nds]=Faxkieker +GenericName[ne]=फ्याक्स द्रष्टा +GenericName[nl]=Faxweergaveprogramma +GenericName[nn]=Faksvisar +GenericName[pa]=ਫੈਕਸ ਦਰਸ਼ਕ +GenericName[pl]=Przeglądarka faksów +GenericName[pt]=Visualizador de Faxes +GenericName[pt_BR]=Visualizador de Faxes +GenericName[ro]=Vizualizor FAX +GenericName[ru]=Просмотр факсов +GenericName[se]=Fáksačájeheaddji +GenericName[sk]=Prehliadač faxov +GenericName[sl]=Pregledovalnik faksov +GenericName[sr]=Приказивач факсова +GenericName[sr@Latn]=Prikazivač faksova +GenericName[sv]=Faxvisare +GenericName[ta]=ஃபாக்ஸ் காட்சி +GenericName[tg]=Хондани факс +GenericName[th]=เครื่องมือแสดงโทรสารของ KDE +GenericName[tr]=Faks Görüntüleyici +GenericName[uk]=Переглядач факсів +GenericName[uz]=Faks koʻruvchi +GenericName[uz@cyrillic]=Факс кўрувчи +GenericName[ven]=Muvhoni wa Fekisi +GenericName[wa]=Håyneu di facs +GenericName[xh]=Umboniseli Wefax +GenericName[zh_CN]=传真查看器 +GenericName[zh_HK]=傳真檢視器 +GenericName[zh_TW]=傳真檢視器 +GenericName[zu]=Umbonisi wefax +Name=KFaxView +Name[nb]=Kfaxview +Name[ne]=केडीई फ्याक्स दृश्य +Name[sv]=Kfaxview +Name[zh_TW]=KFaxView 傳真檢視 +MimeType=image/fax-g3; +InitialPreference=6 +Exec=kfaxview %f +Icon=kfaxview +Path= +Type=Application +Terminal=false +ServiceTypes=Browser/View +X-KDE-Library=kviewerpart +X-KDE-BrowserView-Args=fax +DocPath=kfaxview/index.html +X-KDE-StartupNotify=true +Categories=Qt;KDE;Graphics; diff --git a/kfaxview/libkfaximage/Makefile.am b/kfaxview/libkfaximage/Makefile.am new file mode 100644 index 00000000..616afb3c --- /dev/null +++ b/kfaxview/libkfaximage/Makefile.am @@ -0,0 +1,14 @@ +INCLUDES = -I$(top_srcdir) $(all_includes) + +lib_LTLIBRARIES = libkfaximage.la +libkfaximage_la_LDFLAGS = $(all_libraries) -no-undefined -avoid-version +libkfaximage_la_LIBADD = $(LIB_KDECORE) +libkfaximage_la_SOURCES = kfaximage.cpp faxexpand.cpp faxinit.cpp + +include_HEADERS = kfaximage.h +noinst_HEADERS = faxexpand.h + +METASOURCES = AUTO + +messages: rc.cpp + $(XGETTEXT) $(libkfaximage_la_SOURCES) -o $(podir)/libkfaximgage.pot diff --git a/kfaxview/libkfaximage/faxexpand.cpp b/kfaxview/libkfaximage/faxexpand.cpp new file mode 100644 index 00000000..9c4b4082 --- /dev/null +++ b/kfaxview/libkfaximage/faxexpand.cpp @@ -0,0 +1,745 @@ +/* Expand one page of fax data + Copyright (C) 1990, 1995 Frank D. Cringle. + +This file is part of viewfax - g3/g4 fax processing software. + +viewfax 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 <config.h> + +#include <stdlib.h> +#include <stdio.h> +#include <sys/types.h> + +#include <kdebug.h> + +#include "faxexpand.h" + +//Uncomment this for verbose debug output +//#define DEBUG_FAX +#define verbose false + +pagenode::pagenode() +{ +} + +/* Note that NeedBits() only works for n <= 16 */ +#define NeedBits(n) do { \ + if (BitsAvail < (n)) { \ + BitAcc |= *sp++ << BitsAvail; \ + BitsAvail += 16; \ + } \ +} while (0) +#define GetBits(n) (BitAcc & ((1<<(n))-1)) +#define ClrBits(n) do { \ + BitAcc >>= (n); \ + BitsAvail -= (n); \ +} while (0) + +#ifdef DEBUG_FAX +#define DEBUG_SHOW putchar(BitAcc & (1 << t) ? '1' : '0') +#define LOOKUP(wid,tab) do { \ + int t; \ + NeedBits(wid); \ + TabEnt = tab + GetBits(wid); \ + printf("%08lX/%d: %s%5d\t", BitAcc, BitsAvail, \ + StateNames[TabEnt->State], TabEnt->Param); \ + for (t = 0; t < TabEnt->Width; t++) \ + DEBUG_SHOW; \ + putchar('\n'); \ + fflush(stdout); \ + ClrBits(TabEnt->Width); \ +} while (0) + +#define SETVAL(x) do { \ + *pa++ = RunLength + (x); \ + printf("SETVAL: %d\t%d\n", RunLength + (x), a0); \ + a0 += x; \ + RunLength = 0; \ +} while (0) + +const char *StateNames[] = { + "Null ", + "Pass ", + "Horiz ", + "V0 ", + "VR ", + "VL ", + "Ext ", + "TermW ", + "TermB ", + "MakeUpW", + "MakeUpB", + "MakeUp ", + "EOL ", +}; + +#else +#define LOOKUP(wid,tab) do { \ + NeedBits(wid); \ + TabEnt = tab + GetBits(wid); \ + ClrBits(TabEnt->Width); \ +} while (0) + +#define SETVAL(x) do { \ + *pa++ = RunLength + (x); \ + a0 += x; \ + RunLength = 0; \ +} while (0) +#endif + +#define dumpruns(runs) do { \ + printf("-------------------- %d\n", LineNum); \ + for (pa = runs, a0 = 0; a0 < lastx; a0 += *pa++) \ + printf("%4d %d\n", a0, *pa); \ +} while (0) + +#define EndOfData(pn) (sp >= pn->data + pn->length/sizeof(*pn->data)) + +/* This macro handles coding errors in G3 data. + We redefine it below for the G4 case */ +#define SKIP_EOL do { \ + while (!EndOfData(pn)) { \ + NeedBits(11); \ + if (GetBits(11) == 0) \ + break; \ + ClrBits(1); \ + } \ + ClrBits(11); \ + goto EOL; \ +} while (0) +#define eol2lab EOL2: + +/* the line expanders are written as macros so that they can be reused + (twice each) but still have direct access to the local variables of + the "calling" function */ +#define expand1d() do { \ + while (a0 < lastx) { \ + int done = 0; \ + while (!done) { /* white first */ \ + LOOKUP(12, WhiteTable); \ + switch (TabEnt->State) { \ + case S_EOL: \ + EOLcnt = 1; \ + goto EOL; \ + case S_TermW: \ + SETVAL(TabEnt->Param); \ + done = 1; \ + break; \ + case S_MakeUpW: \ + case S_MakeUp: \ + a0 += TabEnt->Param; \ + RunLength += TabEnt->Param; \ + break; \ + case S_Ext: \ + unexpected("Extension code", LineNum); \ + SKIP_EOL; \ + break; \ + default: \ + unexpected("WhiteTable", LineNum); \ + SKIP_EOL; \ + break; \ + } \ + } \ + done = a0 >= lastx; \ + while (!done) { /* then black */ \ + LOOKUP(13, BlackTable); \ + switch (TabEnt->State) { \ + case S_EOL: \ + EOLcnt = 1; \ + goto EOL; \ + case S_TermB: \ + SETVAL(TabEnt->Param); \ + done = 1; \ + break; \ + case S_MakeUpB: \ + case S_MakeUp: \ + a0 += TabEnt->Param; \ + RunLength += TabEnt->Param; \ + break; \ + case S_Ext: \ + unexpected("Extension code", LineNum); \ + SKIP_EOL; \ + break; \ + default: \ + unexpected("BlackTable", LineNum); \ + SKIP_EOL; \ + break; \ + } \ + } \ + } \ + EOL: ; \ +} while (0) + +#define CHECK_b1 do { \ + if (pa != thisrun) while (b1 <= a0 && b1 < lastx) { \ + b1 += pb[0] + pb[1]; \ + pb += 2; \ + } \ +} while (0) + +#define expand2d(eolab) do { \ + while (a0 < lastx) { \ + LOOKUP(7, MainTable); \ + switch (TabEnt->State) { \ + case S_Pass: \ + CHECK_b1; \ + b1 += *pb++; \ + RunLength += b1 - a0; \ + a0 = b1; \ + b1 += *pb++; \ + break; \ + case S_Horiz: \ + if ((pa-run0)&1) { \ + int done = 0; \ + while (!done) { /* black first */ \ + LOOKUP(13, BlackTable); \ + switch (TabEnt->State) { \ + case S_TermB: \ + SETVAL(TabEnt->Param); \ + done = 1; \ + break; \ + case S_MakeUpB: \ + case S_MakeUp: \ + a0 += TabEnt->Param; \ + RunLength += TabEnt->Param; \ + break; \ + default: \ + unexpected("BlackTable", LineNum); \ + SKIP_EOL; \ + break; \ + } \ + } \ + done = 0; \ + while (!done) { /* then white */ \ + LOOKUP(12, WhiteTable); \ + switch (TabEnt->State) { \ + case S_TermW: \ + SETVAL(TabEnt->Param); \ + done = 1; \ + break; \ + case S_MakeUpW: \ + case S_MakeUp: \ + a0 += TabEnt->Param; \ + RunLength += TabEnt->Param; \ + break; \ + default: \ + unexpected("WhiteTable", LineNum); \ + SKIP_EOL; \ + break; \ + } \ + } \ + } \ + else { \ + int done = 0; \ + while (!done) { /* white first */ \ + LOOKUP(12, WhiteTable); \ + switch (TabEnt->State) { \ + case S_TermW: \ + SETVAL(TabEnt->Param); \ + done = 1; \ + break; \ + case S_MakeUpW: \ + case S_MakeUp: \ + a0 += TabEnt->Param; \ + RunLength += TabEnt->Param; \ + break; \ + default: \ + unexpected("WhiteTable", LineNum); \ + SKIP_EOL; \ + break; \ + } \ + } \ + done = 0; \ + while (!done) { /* then black */ \ + LOOKUP(13, BlackTable); \ + switch (TabEnt->State) { \ + case S_TermB: \ + SETVAL(TabEnt->Param); \ + done = 1; \ + break; \ + case S_MakeUpB: \ + case S_MakeUp: \ + a0 += TabEnt->Param; \ + RunLength += TabEnt->Param; \ + break; \ + default: \ + unexpected("BlackTable", LineNum); \ + SKIP_EOL; \ + break; \ + } \ + } \ + } \ + CHECK_b1; \ + break; \ + case S_V0: \ + CHECK_b1; \ + SETVAL(b1 - a0); \ + b1 += *pb++; \ + break; \ + case S_VR: \ + CHECK_b1; \ + SETVAL(b1 - a0 + TabEnt->Param); \ + b1 += *pb++; \ + break; \ + case S_VL: \ + CHECK_b1; \ + SETVAL(b1 - a0 - TabEnt->Param); \ + b1 -= *--pb; \ + break; \ + case S_Ext: \ + *pa++ = lastx - a0; \ + if (verbose) \ + kdDebug() << "Line " << LineNum << ": extension code\n";\ + SKIP_EOL; \ + break; \ + case S_EOL: \ + *pa++ = lastx - a0; \ + NeedBits(4); \ + if (GetBits(4) && verbose) /* already seen 7 zeros */ \ + kdDebug() << "Line " << LineNum << ": Bad EOL\n"; \ + ClrBits(4); \ + EOLcnt = 1; \ + goto eolab; \ + break; \ + default: \ + unexpected("MainTable", LineNum); \ + SKIP_EOL; \ + break; \ + } \ + } \ + if (RunLength) { \ + if (RunLength + a0 < lastx) { \ + /* expect a final V0 */ \ + NeedBits(1); \ + if (!GetBits(1)) { \ + unexpected("MainTable", LineNum); \ + SKIP_EOL; \ + } \ + ClrBits(1); \ + } \ + SETVAL(0); \ + } \ + eol2lab ; \ +} while (0) + +static void +unexpected(const char *what, int LineNum) +{ + if (verbose) + kdError() << "Line " << LineNum << ": Unexpected state in " + << what << endl; +} + +/* Expand tiff modified huffman data (g3-1d without EOLs) */ +void +MHexpand(struct pagenode *pn, drawfunc df) +{ + int a0; /* reference element */ + int lastx; /* copy line width to register */ + t32bits BitAcc; /* bit accumulator */ + int BitsAvail; /* # valid bits in BitAcc */ + int RunLength; /* Length of current run */ + t16bits *sp; /* pointer into compressed data */ + pixnum *pa; /* pointer into new line */ + int EOLcnt; /* number of consecutive EOLs */ + int LineNum; /* line number */ + pixnum *runs; /* list of run lengths */ + struct tabent *TabEnt; + + sp = pn->data; + BitAcc = 0; + BitsAvail = 0; + lastx = pn->size.width(); + runs = (pixnum *) malloc(lastx * sizeof(pixnum)); + for (LineNum = 0; LineNum < pn->rowsperstrip; ) { +#ifdef DEBUG_FAX + printf("\nBitAcc=%08lX, BitsAvail = %d\n", BitAcc, BitsAvail); + printf("-------------------- %d\n", LineNum); + fflush(stdout); +#endif + RunLength = 0; + pa = runs; + a0 = 0; + EOLcnt = 0; + if (BitsAvail & 7) /* skip to byte boundary */ + ClrBits(BitsAvail & 7); + expand1d(); + if (RunLength) + SETVAL(0); + if (a0 != lastx) { + if (verbose) + kdWarning() << "Line " << LineNum << ": length is " + << a0 << " (expected "<< lastx << ")\n"; + while (a0 > lastx) + a0 -= *--pa; + if (a0 < lastx) { + if ((pa - runs) & 1) + SETVAL(0); + SETVAL(lastx - a0); + } + } + (*df)(runs, LineNum++, pn); + } + free(runs); +} + +/* Expand group-3 1-dimensional data */ +void +g31expand(struct pagenode *pn, drawfunc df) +{ + int a0; /* reference element */ + int lastx; /* copy line width to register */ + t32bits BitAcc; /* bit accumulator */ + int BitsAvail; /* # valid bits in BitAcc */ + int RunLength; /* Length of current run */ + t16bits *sp; /* pointer into compressed data */ + pixnum *pa; /* pointer into new line */ + int EOLcnt; /* number of consecutive EOLs */ + int LineNum; /* line number */ + pixnum *runs; /* list of run lengths */ + struct tabent *TabEnt; + + sp = pn->data; + BitAcc = 0; + BitsAvail = 0; + lastx = pn->size.width(); + runs = (pixnum *) malloc(lastx * sizeof(pixnum)); + EOLcnt = 0; + for (LineNum = 0; LineNum < pn->rowsperstrip; ) { +#ifdef DEBUG_FAX + printf("\nBitAcc=%08lX, BitsAvail = %d\n", BitAcc, BitsAvail); + printf("-------------------- %d\n", LineNum); + fflush(stdout); +#endif + if (EOLcnt == 0) + while (!EndOfData(pn)) { + /* skip over garbage after a coding error */ + NeedBits(11); + if (GetBits(11) == 0) + break; + ClrBits(1); + } + for (EOLcnt = 1; !EndOfData(pn); EOLcnt++) { + /* we have seen 11 zeros, which implies EOL, + skip possible fill bits too */ + while (1) { + NeedBits(8); + if (GetBits(8)) + break; + ClrBits(8); + } + while (GetBits(1) == 0) + ClrBits(1); + ClrBits(1); /* the eol flag */ + NeedBits(11); + if (GetBits(11)) + break; + ClrBits(11); + } + if (EOLcnt > 1 && EOLcnt != 6 && verbose) + kdError() << "Line " << LineNum << ": bad RTC (" << EOLcnt << " EOLs)\n"; + if (EOLcnt >= 6 || EndOfData(pn)) { + free(runs); + return; + } + RunLength = 0; + pa = runs; + a0 = 0; + EOLcnt = 0; + expand1d(); + if (RunLength) + SETVAL(0); + if (a0 != lastx) { + if (verbose) + kdWarning() << "Line " << LineNum << ": length is " + << a0 << " (expected "<< lastx << ")\n"; + while (a0 > lastx) + a0 -= *--pa; + if (a0 < lastx) { + if ((pa - runs) & 1) + SETVAL(0); + SETVAL(lastx - a0); + } + } + (*df)(runs, LineNum++, pn); + } + free(runs); +} + +/* Expand group-3 2-dimensional data */ +void +g32expand(struct pagenode *pn, drawfunc df) +{ + int RunLength; /* Length of current run */ + int a0; /* reference element */ + int b1; /* next change on previous line */ + int lastx = pn->size.width();/* copy line width to register */ + pixnum *run0, *run1; /* run length arrays */ + pixnum *thisrun, *pa, *pb; /* pointers into runs */ + t16bits *sp; /* pointer into compressed data */ + t32bits BitAcc; /* bit accumulator */ + int BitsAvail; /* # valid bits in BitAcc */ + int EOLcnt; /* number of consecutive EOLs */ + int refline = 0; /* 1D encoded reference line */ + int LineNum; /* line number */ + struct tabent *TabEnt; + + sp = pn->data; + BitAcc = 0; + BitsAvail = 0; + /* allocate space for 2 runlength arrays */ + run0 = (pixnum *) malloc(2 * ((lastx+5)&~1) * sizeof(pixnum)); + run1 = run0 + ((lastx+5)&~1); + run1[0] = lastx; + run1[1] = 0; + EOLcnt = 0; + for (LineNum = 0; LineNum < pn->rowsperstrip; ) { +#ifdef DEBUG_FAX + printf("\nBitAcc=%08lX, BitsAvail = %d\n", BitAcc, BitsAvail); + printf("-------------------- %d\n", LineNum); + fflush(stdout); +#endif + if (EOLcnt == 0) + while (!EndOfData(pn)) { + /* skip over garbage after a coding error */ + NeedBits(11); + if (GetBits(11) == 0) + break; + ClrBits(1); + } + for (EOLcnt = 1; !EndOfData(pn); EOLcnt++) { + /* we have seen 11 zeros, which implies EOL, + skip possible fill bits too */ + while (1) { + NeedBits(8); + if (GetBits(8)) + break; + ClrBits(8); + } + while (GetBits(1) == 0) + ClrBits(1); + ClrBits(1); /* the eol flag */ + NeedBits(12); + refline = GetBits(1); /* 1D / 2D flag */ + ClrBits(1); + if (GetBits(11)) + break; + ClrBits(11); + } + if (EOLcnt > 1 && EOLcnt != 6 && verbose) + kdError() << "Line " << LineNum << ": bad RTC (" << EOLcnt << " EOLs)\n"; + if (EOLcnt >= 6 || EndOfData(pn)) { + free(run0); + return; + } + if (LineNum == 0 && refline == 0 && verbose) + kdDebug() << "First line is 2-D encoded\n"; + RunLength = 0; + if (LineNum & 1) { + pa = run1; + pb = run0; + } + else { + pa = run0; + pb = run1; + } + thisrun = pa; + EOLcnt = 0; + a0 = 0; + b1 = *pb++; + + if (refline) { + expand1d(); + } + else { + expand2d(EOL2); + } + if (RunLength) + SETVAL(0); + if (a0 != lastx) { + if (verbose) + kdWarning() << "Line " << LineNum << ": length is " + << a0 << " (expected "<< lastx << ")\n"; + while (a0 > lastx) + a0 -= *--pa; + if (a0 < lastx) { + if ((pa - run0) & 1) + SETVAL(0); + SETVAL(lastx - a0); + } + } + SETVAL(0); /* imaginary change at end of line for reference */ + (*df)(thisrun, LineNum++, pn); + } + free(run0); +} + +/* Redefine the "skip to eol" macro. We cannot recover from coding + errors in G4 data */ +#undef SKIP_EOL +#undef eol2lab +#define SKIP_EOL do { \ + if (verbose) \ + kdError() << "Line " << LineNum << ": G4 coding error\n"; \ + free(run0); \ + return; \ +} while (0) +#define eol2lab + +/* Expand group-4 data */ +void +g4expand(struct pagenode *pn, drawfunc df) +{ + int RunLength; /* Length of current run */ + int a0; /* reference element */ + int b1; /* next change on previous line */ + int lastx = pn->size.width();/* copy line width to register */ + pixnum *run0, *run1; /* run length arrays */ + pixnum *thisrun, *pa, *pb; /* pointers into runs */ + t16bits *sp; /* pointer into compressed data */ + t32bits BitAcc; /* bit accumulator */ + int BitsAvail; /* # valid bits in BitAcc */ + int LineNum; /* line number */ + int EOLcnt; + struct tabent *TabEnt; + + sp = pn->data; + BitAcc = 0; + BitsAvail = 0; + /* allocate space for 2 runlength arrays */ + run0 = (pixnum *) malloc(2 * ((lastx+5)&~1) * sizeof(pixnum)); + run1 = run0 + ((lastx+5)&~1); + run1[0] = lastx; /* initial reference line */ + run1[1] = 0; + + for (LineNum = 0; LineNum < pn->rowsperstrip; ) { +#ifdef DEBUG_FAX + printf("\nBitAcc=%08lX, BitsAvail = %d\n", BitAcc, BitsAvail); + printf("-------------------- %d\n", LineNum); + fflush(stdout); +#endif + RunLength = 0; + if (LineNum & 1) { + pa = run1; + pb = run0; + } + else { + pa = run0; + pb = run1; + } + thisrun = pa; + a0 = 0; + b1 = *pb++; + expand2d(EOFB); + if (a0 < lastx) { + if ((pa - run0) & 1) + SETVAL(0); + SETVAL(lastx - a0); + } + SETVAL(0); /* imaginary change at end of line for reference */ + (*df)(thisrun, LineNum++, pn); + continue; + EOFB: + NeedBits(13); + if (GetBits(13) != 0x1001 && verbose) + kdError() << "Bad RTC\n"; + break; + } + free(run0); +} + +static const unsigned char zerotab[256] = { + 0x88, 0x07, 0x16, 0x06, 0x25, 0x05, 0x15, 0x05, + 0x34, 0x04, 0x14, 0x04, 0x24, 0x04, 0x14, 0x04, + 0x43, 0x03, 0x13, 0x03, 0x23, 0x03, 0x13, 0x03, + 0x33, 0x03, 0x13, 0x03, 0x23, 0x03, 0x13, 0x03, + 0x52, 0x02, 0x12, 0x02, 0x22, 0x02, 0x12, 0x02, + 0x32, 0x02, 0x12, 0x02, 0x22, 0x02, 0x12, 0x02, + 0x42, 0x02, 0x12, 0x02, 0x22, 0x02, 0x12, 0x02, + 0x32, 0x02, 0x12, 0x02, 0x22, 0x02, 0x12, 0x02, + 0x61, 0x01, 0x11, 0x01, 0x21, 0x01, 0x11, 0x01, + 0x31, 0x01, 0x11, 0x01, 0x21, 0x01, 0x11, 0x01, + 0x41, 0x01, 0x11, 0x01, 0x21, 0x01, 0x11, 0x01, + 0x31, 0x01, 0x11, 0x01, 0x21, 0x01, 0x11, 0x01, + 0x51, 0x01, 0x11, 0x01, 0x21, 0x01, 0x11, 0x01, + 0x31, 0x01, 0x11, 0x01, 0x21, 0x01, 0x11, 0x01, + 0x41, 0x01, 0x11, 0x01, 0x21, 0x01, 0x11, 0x01, + 0x31, 0x01, 0x11, 0x01, 0x21, 0x01, 0x11, 0x01, + 0x70, 0x00, 0x10, 0x00, 0x20, 0x00, 0x10, 0x00, + 0x30, 0x00, 0x10, 0x00, 0x20, 0x00, 0x10, 0x00, + 0x40, 0x00, 0x10, 0x00, 0x20, 0x00, 0x10, 0x00, + 0x30, 0x00, 0x10, 0x00, 0x20, 0x00, 0x10, 0x00, + 0x50, 0x00, 0x10, 0x00, 0x20, 0x00, 0x10, 0x00, + 0x30, 0x00, 0x10, 0x00, 0x20, 0x00, 0x10, 0x00, + 0x40, 0x00, 0x10, 0x00, 0x20, 0x00, 0x10, 0x00, + 0x30, 0x00, 0x10, 0x00, 0x20, 0x00, 0x10, 0x00, + 0x60, 0x00, 0x10, 0x00, 0x20, 0x00, 0x10, 0x00, + 0x30, 0x00, 0x10, 0x00, 0x20, 0x00, 0x10, 0x00, + 0x40, 0x00, 0x10, 0x00, 0x20, 0x00, 0x10, 0x00, + 0x30, 0x00, 0x10, 0x00, 0x20, 0x00, 0x10, 0x00, + 0x50, 0x00, 0x10, 0x00, 0x20, 0x00, 0x10, 0x00, + 0x30, 0x00, 0x10, 0x00, 0x20, 0x00, 0x10, 0x00, + 0x40, 0x00, 0x10, 0x00, 0x20, 0x00, 0x10, 0x00, + 0x30, 0x00, 0x10, 0x00, 0x20, 0x00, 0x10, 0x00 +}; + +#define check(v) do { \ + prezeros = zerotab[v]; \ + postzeros = prezeros & 15; \ + prezeros >>= 4; \ + if (prezeros == 8) { \ + zeros += 8; \ + continue; \ + } \ + if (zeros + prezeros < 11) { \ + empty = 0; \ + zeros = postzeros; \ + continue; \ + } \ + zeros = postzeros; \ + if (empty) \ + EOLcnt++; \ + lines++; \ + empty = 1; \ +} while (0) + +/* count fax lines */ +int +G3count(struct pagenode *pn, int twoD) +{ + t16bits *p = pn->data; + t16bits *end = p + pn->length/sizeof(*p); + int lines = 0; /* lines seen so far */ + int zeros = 0; /* number of consecutive zero bits seen */ + int EOLcnt = 0; /* number of consecutive EOLs seen */ + int empty = 1; /* empty line */ + int prezeros, postzeros; + + while (p < end && EOLcnt < 6) { + t16bits bits = *p++; + check(bits&255); + if (twoD && (prezeros + postzeros == 7)) { + if (postzeros || ((bits & 0x100) == 0)) + zeros--; + } + check(bits>>8); + if (twoD && (prezeros + postzeros == 7)) { + if (postzeros || ((p < end) && ((*p & 1) == 0))) + zeros--; + } + } + return lines - EOLcnt; /* don't count trailing EOLs */ +} diff --git a/kfaxview/libkfaximage/faxexpand.h b/kfaxview/libkfaximage/faxexpand.h new file mode 100644 index 00000000..8da4e8bc --- /dev/null +++ b/kfaxview/libkfaximage/faxexpand.h @@ -0,0 +1,126 @@ +/* Include file for fax routines + Copyright (C) 1990, 1995 Frank D. Cringle. + Copyright (C) 2005 Helge Deller <deller@kde.org> + +This file is part of viewfax - g3/g4 fax processing software. + +viewfax 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. */ + +#ifndef _faxexpand_h_ +#define _faxexpand_h_ + +#include <sys/types.h> +#include <unistd.h> + +#include <qglobal.h> +#include <qimage.h> + +#define t32bits Q_UINT32 +#define t16bits Q_UINT16 + +typedef t16bits pixnum; + +class pagenode; + +/* drawfunc() points to a function which processes a line of the + expanded image described as a list of run lengths. + run is the base of an array of lengths, starting with a + (possibly empty) white run for line number linenum. + pn points to the page descriptor */ +typedef void (*drawfunc)(pixnum *run, int linenum, class pagenode *pn); + +struct strip { /* tiff strip descriptor */ + off_t offset; /* offset in file */ + off_t size; /* size of this strip */ +}; + + +/* defines for the pagenode member: type */ +#define FAX_TIFF 1 +#define FAX_RAW 2 + +class pagenode { /* compressed page descriptor */ + public: + pagenode(); + ~pagenode() { }; + int nstrips; /* number of strips */ + int rowsperstrip; /* number of rows per strip */ + int stripnum; /* current strip while expanding */ + struct strip *strips; /* array of strips containing fax data in file */ + t16bits *data; /* in-memory copy of strip */ + size_t length; /* length of data */ + QSize size; /* width & height of page in pixels */ + int inverse; /* black <=> white */ + int lsbfirst; /* bit order is lsb first */ + int type; /* Bernd: tiff vs no tiff*/ + int orient; /* orientation - upsidedown, landscape, mirrored */ + int vres; /* vertical resolution: 1 = fine */ + QPoint dpi; /* DPI horz/vert */ + void (*expander)(class pagenode *, drawfunc); + QImage image; + unsigned int bytes_per_line; +}; + +extern class pagenode *firstpage, *lastpage, *thispage; +extern class pagenode defaultpage; + +/* page orientation flags */ +#define TURN_NONE 0 +#define TURN_U 1 +#define TURN_L 2 +#define TURN_M 4 + +/* fsm state codes */ +#define S_Null 0 +#define S_Pass 1 +#define S_Horiz 2 +#define S_V0 3 +#define S_VR 4 +#define S_VL 5 +#define S_Ext 6 +#define S_TermW 7 +#define S_TermB 8 +#define S_MakeUpW 9 +#define S_MakeUpB 10 +#define S_MakeUp 11 +#define S_EOL 12 + +/* state table entry */ +struct tabent { + unsigned char State; + unsigned char Width; /* width of code in bits */ + pixnum Param; /* run length */ +}; + +extern struct tabent MainTable[]; /* 2-D state table */ +extern struct tabent WhiteTable[]; /* White run lengths */ +extern struct tabent BlackTable[]; /* Black run lengths */ + +void MHexpand(class pagenode *pn, drawfunc df); +void g31expand(class pagenode *pn, drawfunc df); +void g32expand(class pagenode *pn, drawfunc df); +void g4expand(class pagenode *pn, drawfunc df); + +unsigned char *getstrip(class pagenode *pn, int strip); +class pagenode *notefile(const char *name); +int notetiff(const char *name); + +/* initialise code tables */ +extern void fax_init_tables(void); + +/* count lines in image */ +extern int G3count(class pagenode *pn, int twoD); + +#endif diff --git a/kfaxview/libkfaximage/faxinit.cpp b/kfaxview/libkfaximage/faxinit.cpp new file mode 100644 index 00000000..aa6166aa --- /dev/null +++ b/kfaxview/libkfaximage/faxinit.cpp @@ -0,0 +1,345 @@ +/* Initialise fax decoder tables + Copyright (C) 1990, 1995 Frank D. Cringle. + +This file is part of viewfax - g3/g4 fax processing software. + +viewfax 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 <config.h> + +#include <sys/types.h> +#include "faxexpand.h" + +struct tabent MainTable[128]; +struct tabent WhiteTable[4096]; +struct tabent BlackTable[8192]; + +struct proto { + t16bits code; /* right justified, lsb-first, zero filled */ + t16bits val; /* (pixel count)<<4 + code width */ +}; + +static const struct proto Pass[] = { +{ 0x0008, 4 }, +{ 0, 0 } +}; + +static const struct proto Horiz[] = { +{ 0x0004, 3 }, +{ 0, 0 } +}; + +static const struct proto V0[] = { +{ 0x0001, 1 }, +{ 0, 0 } +}; + +static const struct proto VR[] = { +{ 0x0006, (1<<4)+3 }, +{ 0x0030, (2<<4)+6 }, +{ 0x0060, (3<<4)+7 }, +{ 0, 0 } +}; + +static const struct proto VL[] = { +{ 0x0002, (1<<4)+3 }, +{ 0x0010, (2<<4)+6 }, +{ 0x0020, (3<<4)+7 }, +{ 0, 0 } +}; + +static const struct proto ExtV[] = { +{ 0x0040, 7 }, +{ 0, 0 } +}; + +static const struct proto EOLV[] = { +{ 0x0000, 7 }, +{ 0, 0 } +}; + +static const struct proto MakeUpW[] = { +{ 0x001b, 1029 }, +{ 0x0009, 2053 }, +{ 0x003a, 3078 }, +{ 0x0076, 4103 }, +{ 0x006c, 5128 }, +{ 0x00ec, 6152 }, +{ 0x0026, 7176 }, +{ 0x00a6, 8200 }, +{ 0x0016, 9224 }, +{ 0x00e6, 10248 }, +{ 0x0066, 11273 }, +{ 0x0166, 12297 }, +{ 0x0096, 13321 }, +{ 0x0196, 14345 }, +{ 0x0056, 15369 }, +{ 0x0156, 16393 }, +{ 0x00d6, 17417 }, +{ 0x01d6, 18441 }, +{ 0x0036, 19465 }, +{ 0x0136, 20489 }, +{ 0x00b6, 21513 }, +{ 0x01b6, 22537 }, +{ 0x0032, 23561 }, +{ 0x0132, 24585 }, +{ 0x00b2, 25609 }, +{ 0x0006, 26630 }, +{ 0x01b2, 27657 }, +{ 0, 0 } +}; + +static const struct proto MakeUpB[] = { +{ 0x03c0, 1034 }, +{ 0x0130, 2060 }, +{ 0x0930, 3084 }, +{ 0x0da0, 4108 }, +{ 0x0cc0, 5132 }, +{ 0x02c0, 6156 }, +{ 0x0ac0, 7180 }, +{ 0x06c0, 8205 }, +{ 0x16c0, 9229 }, +{ 0x0a40, 10253 }, +{ 0x1a40, 11277 }, +{ 0x0640, 12301 }, +{ 0x1640, 13325 }, +{ 0x09c0, 14349 }, +{ 0x19c0, 15373 }, +{ 0x05c0, 16397 }, +{ 0x15c0, 17421 }, +{ 0x0dc0, 18445 }, +{ 0x1dc0, 19469 }, +{ 0x0940, 20493 }, +{ 0x1940, 21517 }, +{ 0x0540, 22541 }, +{ 0x1540, 23565 }, +{ 0x0b40, 24589 }, +{ 0x1b40, 25613 }, +{ 0x04c0, 26637 }, +{ 0x14c0, 27661 }, +{ 0, 0 } +}; + +static const struct proto MakeUp[] = { +{ 0x0080, 28683 }, +{ 0x0180, 29707 }, +{ 0x0580, 30731 }, +{ 0x0480, 31756 }, +{ 0x0c80, 32780 }, +{ 0x0280, 33804 }, +{ 0x0a80, 34828 }, +{ 0x0680, 35852 }, +{ 0x0e80, 36876 }, +{ 0x0380, 37900 }, +{ 0x0b80, 38924 }, +{ 0x0780, 39948 }, +{ 0x0f80, 40972 }, +{ 0, 0 } +}; + +static const struct proto TermW[] = { +{ 0x00ac, 8 }, +{ 0x0038, 22 }, +{ 0x000e, 36 }, +{ 0x0001, 52 }, +{ 0x000d, 68 }, +{ 0x0003, 84 }, +{ 0x0007, 100 }, +{ 0x000f, 116 }, +{ 0x0019, 133 }, +{ 0x0005, 149 }, +{ 0x001c, 165 }, +{ 0x0002, 181 }, +{ 0x0004, 198 }, +{ 0x0030, 214 }, +{ 0x000b, 230 }, +{ 0x002b, 246 }, +{ 0x0015, 262 }, +{ 0x0035, 278 }, +{ 0x0072, 295 }, +{ 0x0018, 311 }, +{ 0x0008, 327 }, +{ 0x0074, 343 }, +{ 0x0060, 359 }, +{ 0x0010, 375 }, +{ 0x000a, 391 }, +{ 0x006a, 407 }, +{ 0x0064, 423 }, +{ 0x0012, 439 }, +{ 0x000c, 455 }, +{ 0x0040, 472 }, +{ 0x00c0, 488 }, +{ 0x0058, 504 }, +{ 0x00d8, 520 }, +{ 0x0048, 536 }, +{ 0x00c8, 552 }, +{ 0x0028, 568 }, +{ 0x00a8, 584 }, +{ 0x0068, 600 }, +{ 0x00e8, 616 }, +{ 0x0014, 632 }, +{ 0x0094, 648 }, +{ 0x0054, 664 }, +{ 0x00d4, 680 }, +{ 0x0034, 696 }, +{ 0x00b4, 712 }, +{ 0x0020, 728 }, +{ 0x00a0, 744 }, +{ 0x0050, 760 }, +{ 0x00d0, 776 }, +{ 0x004a, 792 }, +{ 0x00ca, 808 }, +{ 0x002a, 824 }, +{ 0x00aa, 840 }, +{ 0x0024, 856 }, +{ 0x00a4, 872 }, +{ 0x001a, 888 }, +{ 0x009a, 904 }, +{ 0x005a, 920 }, +{ 0x00da, 936 }, +{ 0x0052, 952 }, +{ 0x00d2, 968 }, +{ 0x004c, 984 }, +{ 0x00cc, 1000 }, +{ 0x002c, 1016 }, +{ 0, 0 } +}; + +static const struct proto TermB[] = { +{ 0x03b0, 10 }, +{ 0x0002, 19 }, +{ 0x0003, 34 }, +{ 0x0001, 50 }, +{ 0x0006, 67 }, +{ 0x000c, 84 }, +{ 0x0004, 100 }, +{ 0x0018, 117 }, +{ 0x0028, 134 }, +{ 0x0008, 150 }, +{ 0x0010, 167 }, +{ 0x0050, 183 }, +{ 0x0070, 199 }, +{ 0x0020, 216 }, +{ 0x00e0, 232 }, +{ 0x0030, 249 }, +{ 0x03a0, 266 }, +{ 0x0060, 282 }, +{ 0x0040, 298 }, +{ 0x0730, 315 }, +{ 0x00b0, 331 }, +{ 0x01b0, 347 }, +{ 0x0760, 363 }, +{ 0x00a0, 379 }, +{ 0x0740, 395 }, +{ 0x00c0, 411 }, +{ 0x0530, 428 }, +{ 0x0d30, 444 }, +{ 0x0330, 460 }, +{ 0x0b30, 476 }, +{ 0x0160, 492 }, +{ 0x0960, 508 }, +{ 0x0560, 524 }, +{ 0x0d60, 540 }, +{ 0x04b0, 556 }, +{ 0x0cb0, 572 }, +{ 0x02b0, 588 }, +{ 0x0ab0, 604 }, +{ 0x06b0, 620 }, +{ 0x0eb0, 636 }, +{ 0x0360, 652 }, +{ 0x0b60, 668 }, +{ 0x05b0, 684 }, +{ 0x0db0, 700 }, +{ 0x02a0, 716 }, +{ 0x0aa0, 732 }, +{ 0x06a0, 748 }, +{ 0x0ea0, 764 }, +{ 0x0260, 780 }, +{ 0x0a60, 796 }, +{ 0x04a0, 812 }, +{ 0x0ca0, 828 }, +{ 0x0240, 844 }, +{ 0x0ec0, 860 }, +{ 0x01c0, 876 }, +{ 0x0e40, 892 }, +{ 0x0140, 908 }, +{ 0x01a0, 924 }, +{ 0x09a0, 940 }, +{ 0x0d40, 956 }, +{ 0x0340, 972 }, +{ 0x05a0, 988 }, +{ 0x0660, 1004 }, +{ 0x0e60, 1020 }, +{ 0, 0 } +}; + +static const struct proto ExtH[] = { +{ 0x0100, 9 }, +{ 0, 0 } +}; + +static const struct proto EOLH[] = { +{ 0x0000, 11 }, +{ 0, 0 } +}; + +static void +FillTable(struct tabent *T, int Size, const struct proto *P, int State) +{ + int limit = 1 << Size; + + while (P->val) { + int width = P->val & 15; + int param = P->val >> 4; + int incr = 1 << width; + int code; + for (code = P->code; code < limit; code += incr) { + struct tabent *E = T+code; + E->State = State; + E->Width = width; + E->Param = param; + } + P++; + } +} + +/* initialise the huffman code tables */ +void +fax_init_tables(void) +{ + static bool already_initialized = 0; + if (already_initialized) + return; + + ++already_initialized; + + FillTable(MainTable, 7, Pass, S_Pass); + FillTable(MainTable, 7, Horiz, S_Horiz); + FillTable(MainTable, 7, V0, S_V0); + FillTable(MainTable, 7, VR, S_VR); + FillTable(MainTable, 7, VL, S_VL); + FillTable(MainTable, 7, ExtV, S_Ext); + FillTable(MainTable, 7, EOLV, S_EOL); + FillTable(WhiteTable, 12, MakeUpW, S_MakeUpW); + FillTable(WhiteTable, 12, MakeUp, S_MakeUp); + FillTable(WhiteTable, 12, TermW, S_TermW); + FillTable(WhiteTable, 12, ExtH, S_Ext); + FillTable(WhiteTable, 12, EOLH, S_EOL); + FillTable(BlackTable, 13, MakeUpB, S_MakeUpB); + FillTable(BlackTable, 13, MakeUp, S_MakeUp); + FillTable(BlackTable, 13, TermB, S_TermB); + FillTable(BlackTable, 13, ExtH, S_Ext); + FillTable(BlackTable, 13, EOLH, S_EOL); +} diff --git a/kfaxview/libkfaximage/kfaximage.cpp b/kfaxview/libkfaximage/kfaximage.cpp new file mode 100644 index 00000000..28744923 --- /dev/null +++ b/kfaxview/libkfaximage/kfaximage.cpp @@ -0,0 +1,667 @@ +/* + This file is part of KDE FAX image library + Copyright (c) 2005 Helge Deller <deller@kde.org> + + based on Frank D. Cringle's viewfax package + Copyright (C) 1990, 1995 Frank D. Cringle. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include <config.h> + +#include <stdlib.h> + +#include <qimage.h> +#include <qfile.h> + +#include <kglobal.h> +#include <klocale.h> +#include <kdebug.h> + +#include "faxexpand.h" +#include "kfaximage.h" + +static const char FAXMAGIC[] = "\000PC Research, Inc\000\000\000\000\000\000"; +static const char littleTIFF[] = "\x49\x49\x2a\x00"; +static const char bigTIFF[] = "\x4d\x4d\x00\x2a"; + +KFaxImage::KFaxImage( const QString &filename, QObject *parent, const char *name ) + : QObject(parent,name) +{ + KGlobal::locale()->insertCatalogue( QString::fromLatin1("libkfaximage") ); + loadImage(filename); +} + +KFaxImage::~KFaxImage() +{ } + +bool KFaxImage::loadImage( const QString &filename ) +{ + reset(); + + m_filename = filename; + m_errorString = QString::null; + + if (m_filename.isEmpty()) + return false; + + int ok = notetiff(); + if (!ok) { + reset(); + } + return ok == 1; +} + +void KFaxImage::reset() +{ + fax_init_tables(); + m_pagenodes.setAutoDelete(true); + m_pagenodes.clear(); + // do not reset m_errorString and m_filename, since + // they may be needed by calling application +} + +QImage KFaxImage::page( unsigned int pageNr ) +{ + if (pageNr >= numPages()) { + kdDebug() << "KFaxImage::page() called with invalid page number\n"; + return QImage(); + } + pagenode *pn = m_pagenodes.at(pageNr); + GetImage(pn); + return pn->image; +} + +QPoint KFaxImage::page_dpi( unsigned int pageNr ) +{ + if (pageNr >= numPages()) { + kdDebug() << "KFaxImage::page_dpi() called with invalid page number\n"; + return QPoint(0,0); + } + pagenode *pn = m_pagenodes.at(pageNr); + GetImage(pn); + return pn->dpi; +} + +QSize KFaxImage::page_size( unsigned int pageNr ) +{ + if (pageNr >= numPages()) { + kdDebug() << "KFaxImage::page_size() called with invalid page number\n"; + return QSize(0,0); + } + pagenode *pn = m_pagenodes.at(pageNr); + GetImage(pn); + return pn->size; +} + + +pagenode *KFaxImage::AppendImageNode(int type) +{ + pagenode *pn = new pagenode(); + if (pn) { + pn->type = type; + pn->expander = g31expand; + pn->strips = NULL; + pn->size = QSize(1728,2339); + pn->vres = -1; + pn->dpi = KFAX_DPI_FINE; + m_pagenodes.append(pn); + } + return pn; +} + +bool KFaxImage::NewImage(pagenode *pn, int w, int h) +{ + pn->image = QImage( w, h, 1, 2, QImage::systemByteOrder() ); + pn->image.setColor(0, qRgb(255,255,255)); + pn->image.setColor(1, qRgb(0,0,0)); + pn->data = (Q_UINT16*) pn->image.bits(); + pn->bytes_per_line = pn->image.bytesPerLine(); + pn->dpi = KFAX_DPI_FINE; + + return !pn->image.isNull(); +} + +void KFaxImage::FreeImage(pagenode *pn) +{ + pn->image = QImage(); + pn->data = NULL; + pn->bytes_per_line = 0; +} + +void KFaxImage::kfaxerror(const QString& error) +{ + m_errorString = error; + kdError() << "kfaxerror: " << error << endl; +} + + +/* Enter an argument in the linked list of pages */ +pagenode * +KFaxImage::notefile(int type) +{ + pagenode *newnode = new pagenode(); + newnode->type = type; + newnode->size = QSize(1728,0); + return newnode; +} + +static t32bits +get4(unsigned char *p, QImage::Endian endian) +{ + return (endian == QImage::BigEndian) + ? (p[0]<<24)|(p[1]<<16)|(p[2]<<8)|p[3] : + p[0]|(p[1]<<8)|(p[2]<<16)|(p[3]<<24); +} + +static int +get2(unsigned char *p, QImage::Endian endian) +{ + return (endian == QImage::BigEndian) ? (p[0]<<8)|p[1] : p[0]|(p[1]<<8); +} + +/* generate pagenodes for the images in a tiff file */ +int +KFaxImage::notetiff() +{ +#define SC(x) (char *)(x) + unsigned char header[8]; + QImage::Endian endian; + t32bits IFDoff; + pagenode *pn = NULL; + QString str; + + QFile file(filename()); + if (!file.open(IO_ReadOnly)) { + kfaxerror(i18n("Unable to open file for reading.")); + return 0; + } + + if (file.readBlock(SC(header), 8) != 8) { + kfaxerror(i18n("Unable to read file header (file too short).")); + return 0; + } + if (memcmp(header, &littleTIFF, 4) == 0) + endian = QImage::LittleEndian; + else if (memcmp(header, &bigTIFF, 4) == 0) + endian = QImage::BigEndian; + else { + maybe_RAW_FAX: + kfaxerror(i18n("This is not a TIFF FAX file.")); + // AppendImageNode(FAX_RAW); + return 0; + } + IFDoff = get4(header+4, endian); + if (IFDoff & 1) { + goto maybe_RAW_FAX; + } + do { /* for each page */ + unsigned char buf[8]; + unsigned char *dir = NULL , *dp = NULL; + int ndirent; + pixnum iwidth = 1728; + pixnum iheight = 2339; + int inverse = false; + int lsbfirst = 0; + int t4opt = 0, comp = 0; + int orient = TURN_NONE; + int yres = 196; /* 98.0 */ + struct strip *strips = NULL; + unsigned int rowsperstrip = 0; + t32bits nstrips = 1; + + if (!file.at(IFDoff)) { + realbad: + kfaxerror( i18n("Invalid or incomplete TIFF file.") ); + bad: + if (strips) + free(strips); + if (dir) + free(dir); + file.close(); + return 1; + } + if (file.readBlock(SC(buf), 2) != 2) + goto realbad; + ndirent = get2(buf, endian); + int len = 12*ndirent+4; + dir = (unsigned char *) malloc(len); + if (file.readBlock(SC(dir), len) != len) + goto realbad; + for (dp = dir; ndirent; ndirent--, dp += 12) { + /* for each directory entry */ + int tag, ftype; + t32bits count, value = 0; + tag = get2(dp, endian); + ftype = get2(dp+2, endian); + count = get4(dp+4, endian); + switch(ftype) { /* value is offset to list if count*size > 4 */ + case 3: /* short */ + value = get2(dp+8, endian); + break; + case 4: /* long */ + value = get4(dp+8, endian); + break; + case 5: /* offset to rational */ + value = get4(dp+8, endian); + break; + } + switch(tag) { + case 256: /* ImageWidth */ + iwidth = value; + break; + case 257: /* ImageLength */ + iheight = value; + break; + case 259: /* Compression */ + comp = value; + break; + case 262: /* PhotometricInterpretation */ + inverse ^= (value == 1); + break; + case 266: /* FillOrder */ + lsbfirst = (value == 2); + break; + case 273: /* StripOffsets */ + nstrips = count; + strips = (struct strip *) malloc(count * sizeof *strips); + if (count == 1 || (count == 2 && ftype == 3)) { + strips[0].offset = value; + if (count == 2) + strips[1].offset = get2(dp+10, endian); + break; + } + if (!file.at(value)) + goto realbad; + for (count = 0; count < nstrips; count++) { + if (file.readBlock(SC(buf), (ftype == 3) ? 2 : 4) <= 0) + goto realbad; + strips[count].offset = (ftype == 3) ? + get2(buf, endian) : get4(buf, endian); + } + break; + case 274: /* Orientation */ + switch(value) { + default: /* row0 at top, col0 at left */ + orient = 0; + break; + case 2: /* row0 at top, col0 at right */ + orient = TURN_M; + break; + case 3: /* row0 at bottom, col0 at right */ + orient = TURN_U; + break; + case 4: /* row0 at bottom, col0 at left */ + orient = TURN_U|TURN_M; + break; + case 5: /* row0 at left, col0 at top */ + orient = TURN_M|TURN_L; + break; + case 6: /* row0 at right, col0 at top */ + orient = TURN_U|TURN_L; + break; + case 7: /* row0 at right, col0 at bottom */ + orient = TURN_U|TURN_M|TURN_L; + break; + case 8: /* row0 at left, col0 at bottom */ + orient = TURN_L; + break; + } + break; + case 278: /* RowsPerStrip */ + rowsperstrip = value; + break; + case 279: /* StripByteCounts */ + if (count != nstrips) { + str = i18n("In file %1\nStripsPerImage tag 273=%2,tag279=%3\n") + .arg(filename()).arg(nstrips).arg(count); + kfaxerror(str); + goto realbad; + } + if (count == 1 || (count == 2 && ftype == 3)) { + strips[0].size = value; + if (count == 2) + strips[1].size = get2(dp+10, endian); + break; + } + if (!file.at(value)) + goto realbad; + for (count = 0; count < nstrips; count++) { + if (file.readBlock(SC(buf), (ftype == 3) ? 2 : 4) <= 0) + goto realbad; + strips[count].size = (ftype == 3) ? + get2(buf, endian) : get4(buf, endian); + } + break; + case 283: /* YResolution */ + if (!file.at(value) || + file.readBlock(SC(buf), 8) != 8) + goto realbad; + yres = get4(buf, endian) / get4(buf+4, endian); + break; + case 292: /* T4Options */ + t4opt = value; + break; + case 293: /* T6Options */ + /* later */ + break; + case 296: /* ResolutionUnit */ + if (value == 3) + yres = (yres * 254) / 100; /* *2.54 */ + break; + } + } + IFDoff = get4(dp, endian); + free(dir); + dir = NULL; + if (comp == 5) { + // compression type 5 is LZW compression // XXX + kfaxerror(i18n("Due to patent reasons LZW (Lempel-Ziv & Welch) " + "compressed Fax files cannot be loaded yet.\n")); + goto bad; + } + if (comp < 2 || comp > 4) { + kfaxerror(i18n("This version can only handle Fax files\n")); + goto bad; + } + pn = AppendImageNode(FAX_TIFF); + pn->nstrips = nstrips; + pn->rowsperstrip = nstrips > 1 ? rowsperstrip : iheight; + pn->strips = strips; + pn->size = QSize(iwidth,iheight); + pn->inverse = inverse; + pn->lsbfirst = lsbfirst; + pn->orient = orient; + pn->dpi.setY(yres); + pn->vres = (yres > 150) ? 1:0; /* arbitrary threshold for fine resolution */ + if (comp == 2) + pn->expander = MHexpand; + else if (comp == 3) + pn->expander = (t4opt & 1) ? g32expand : g31expand; + else + pn->expander = g4expand; + } while (IFDoff); + file.close(); + return 1; +#undef UC +} + +/* report error and remove bad file from the list */ +void +KFaxImage::badfile(pagenode *pn) +{ + kfaxerror(i18n("%1: Bad Fax File").arg(filename())); + FreeImage(pn); +} + +/* rearrange input bits into t16bits lsb-first chunks */ +static void +normalize(pagenode *pn, int revbits, int swapbytes, size_t length) +{ + t32bits *p = (t32bits *) pn->data; + + kdDebug() << "normalize = " << ((revbits<<1)|swapbytes) << endl; + switch ((revbits<<1)|swapbytes) { + case 0: + break; + case 1: + for ( ; length; length -= 4) { + t32bits t = *p; + *p++ = ((t & 0xff00ff00) >> 8) | ((t & 0x00ff00ff) << 8); + } + break; + case 2: + for ( ; length; length -= 4) { + t32bits t = *p; + t = ((t & 0xf0f0f0f0) >> 4) | ((t & 0x0f0f0f0f) << 4); + t = ((t & 0xcccccccc) >> 2) | ((t & 0x33333333) << 2); + *p++ = ((t & 0xaaaaaaaa) >> 1) | ((t & 0x55555555) << 1); + } + break; + case 3: + for ( ; length; length -= 4) { + t32bits t = *p; + t = ((t & 0xff00ff00) >> 8) | ((t & 0x00ff00ff) << 8); + t = ((t & 0xf0f0f0f0) >> 4) | ((t & 0x0f0f0f0f) << 4); + t = ((t & 0xcccccccc) >> 2) | ((t & 0x33333333) << 2); + *p++ = ((t & 0xaaaaaaaa) >> 1) | ((t & 0x55555555) << 1); + } + } +} + + +/* get compressed data into memory */ +unsigned char * +KFaxImage::getstrip(pagenode *pn, int strip) +{ + size_t offset, roundup; + unsigned char *Data; + + union { t16bits s; unsigned char b[2]; } so; +#define ShortOrder so.b[1] + so.s = 1; /* XXX */ + + QFile file(filename()); + if (!file.open(IO_ReadOnly)) { + badfile(pn); + return NULL; + } + + if (pn->strips == NULL) { + offset = 0; + pn->length = file.size(); + } + else if (strip < pn->nstrips) { + offset = pn->strips[strip].offset; + pn->length = pn->strips[strip].size; + } + else { + kfaxerror( i18n("Trying to expand too many strips.") ); + return NULL; + } + + /* round size to full boundary plus t32bits */ + roundup = (pn->length + 7) & ~3; + + Data = (unsigned char *) malloc(roundup); + /* clear the last 2 t32bits, to force the expander to terminate + even if the file ends in the middle of a fax line */ + *((t32bits *) Data + roundup/4 - 2) = 0; + *((t32bits *) Data + roundup/4 - 1) = 0; + + /* we expect to get it in one gulp... */ + if (!file.at(offset) || + (size_t) file.readBlock((char *)Data, pn->length) != pn->length) { + badfile(pn); + free(Data); + return NULL; + } + file.close(); + + pn->data = (t16bits *) Data; + if (pn->strips == NULL && memcmp(Data, FAXMAGIC, sizeof(FAXMAGIC)-1) == 0) { + /* handle ghostscript / PC Research fax file */ + if (Data[24] != 1 || Data[25] != 0){ + kfaxerror( i18n("Only the first page of the PC Research multipage file will be shown.") ); + } + pn->length -= 64; + pn->vres = Data[29]; + pn->data += 32; + roundup -= 64; + } + + normalize(pn, !pn->lsbfirst, ShortOrder, roundup); + if (pn->size.height() == 0) + pn->size.setHeight( G3count(pn, pn->expander == g32expand) ); + if (pn->size.height() == 0) { + + kfaxerror( i18n("No fax found in file.") ); + badfile(pn); + free(Data); + return NULL; + } + if (pn->strips == NULL) + pn->rowsperstrip = pn->size.height(); + return Data; +} + + +static void +drawline(pixnum *run, int LineNum, pagenode *pn) +{ + t32bits *p, *p1; /* p - current line, p1 - low-res duplicate */ + pixnum *r; /* pointer to run-lengths */ + t32bits pix; /* current pixel value */ + t32bits acc; /* pixel accumulator */ + int nacc; /* number of valid bits in acc */ + int tot; /* total pixels in line */ + int n; + + LineNum += pn->stripnum * pn->rowsperstrip; + if (LineNum >= pn->size.height()) { + if (LineNum == pn->size.height()) + kdError() << "Height exceeded\n"; + return; + } + + p = (t32bits *) pn->image.scanLine(LineNum*(2-pn->vres)); + p1 =(t32bits *)( pn->vres ? 0 : pn->image.scanLine(1+LineNum*(2-pn->vres))); + r = run; + acc = 0; + nacc = 0; + pix = pn->inverse ? ~0 : 0; + tot = 0; + while (tot < pn->size.width()) { + n = *r++; + tot += n; + /* Watch out for buffer overruns, e.g. when n == 65535. */ + if (tot > pn->size.width()) + break; + if (pix) + acc |= (~(t32bits)0 >> nacc); + else if (nacc) + acc &= (~(t32bits)0 << (32 - nacc)); + else + acc = 0; + if (nacc + n < 32) { + nacc += n; + pix = ~pix; + continue; + } + *p++ = acc; + if (p1) + *p1++ = acc; + n -= 32 - nacc; + while (n >= 32) { + n -= 32; + *p++ = pix; + if (p1) + *p1++ = pix; + } + acc = pix; + nacc = n; + pix = ~pix; + } + if (nacc) { + *p++ = acc; + if (p1) + *p1++ = acc; + } +} + +int +KFaxImage::GetPartImage(pagenode *pn, int n) +{ + unsigned char *Data = getstrip(pn, n); + if (Data == 0) + return 3; + pn->stripnum = n; + (*pn->expander)(pn, drawline); + free(Data); + return 1; +} + +int +KFaxImage::GetImage(pagenode *pn) +{ + if (!pn->image.isNull()) + return 1; + + int i; + if (pn->strips == 0) { + + kdDebug() << "Loading RAW fax file " << m_filename << " size=" << pn->size << endl; + + /* raw file; maybe we don't have the height yet */ + unsigned char *Data = getstrip(pn, 0); + if (Data == 0){ + return 0; + } + if (!NewImage(pn, pn->size.width(), (pn->vres ? 1:2) * pn->size.height())) + return 0; + + (*pn->expander)(pn, drawline); + } + else { + /* multi-strip tiff */ + kdDebug() << "Loading MULTI STRIP TIFF fax file " << m_filename << endl; + + if (!NewImage(pn, pn->size.width(), (pn->vres ? 1:2) * pn->size.height())) + return 0; + pn->stripnum = 0; + kdDebug() << "has " << pn->nstrips << " strips.\n"; + for (i = 0; i < pn->nstrips; i++){ + + int k = GetPartImage(pn, i); + if ( k == 3 ){ + FreeImage(pn); + kfaxerror( i18n("Fax G3 format not yet supported.") ); + return k; + } + + } + } + + // byte-swapping the image on little endian machines +#if defined(Q_BYTE_ORDER) && (Q_BYTE_ORDER == Q_LITTLE_ENDIAN) + for (int y=pn->image.height()-1; y>=0; --y) { + Q_UINT32 *source = (Q_UINT32 *) pn->image.scanLine(y); + Q_UINT32 *dest = source; + for (int x=(pn->bytes_per_line/4)-1; x>=0; --x) { + Q_UINT32 dv = 0, sv = *source; + for (int bit=32; bit>0; --bit) { + dv <<= 1; + dv |= sv&1; + sv >>= 1; + } + *dest = dv; + ++dest; + ++source; + } + } +#endif + + kdDebug() << filename() + << "\n\tsize = " << pn->size + << "\n\tDPI = " << pn->dpi + << "\n\tresolution = " << (pn->vres ? "fine" : "normal") + << endl; + + return 1; +} + + +#include "kfaximage.moc" diff --git a/kfaxview/libkfaximage/kfaximage.h b/kfaxview/libkfaximage/kfaximage.h new file mode 100644 index 00000000..0ed2db90 --- /dev/null +++ b/kfaxview/libkfaximage/kfaximage.h @@ -0,0 +1,162 @@ +/* + This file is part of KDE FAX image loading library + Copyright (c) 2005 Helge Deller <deller@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef _LIBKFAXIMAGE_H_ +#define _LIBKFAXIMAGE_H_ + +#include <qobject.h> +#include <qstring.h> +#include <qimage.h> +#include <qptrlist.h> +#include <kdelibs_export.h> + +class pagenode; + + +/** + * This is KFaxImage, a class for loading FAX files under KDE + * + * @short KFaxImage + * @author Helge Deller + * @version 0.1 + * + * + * Standard fax dpi values: + * ------------------------ + * Standard: 203 dpi x 98 lpi + * Fine: 203 dpi x 196 lpi + * Super Fine: 203 dpi y 392 lpi, or + * 406 dpi x 392 lpi + */ + +#define KFAX_DPI_STANDARD QPoint(203,98) +#define KFAX_DPI_FINE QPoint(203,196) +#define KFAX_DPI_SUPERFINE QPoint(406,392) + + +class KDE_EXPORT KFaxImage : public QObject +{ + Q_OBJECT + +public: + + /** + * KFaxImage - the KDE FAX loader class + * constructor. + * @param filename: an optional FAX file which should be loaded. + * @see: numPages + */ + + KFaxImage( const QString &filename = QString::null, QObject *parent = 0, const char *name = 0 ); + + /** + * Destructor + * + * releases internal allocated memory. + */ + + virtual ~KFaxImage(); + + /** + * loads the FAX image and returns true when sucessful. + * @param filename: the file which should be loaded. + * @return boolean value on success or failure + * @see: numPages + * @see: errorString + */ + + bool loadImage( const QString &filename ); + + /** + * returns currently loaded image file name. + * @return FAX filename + */ + + QString filename() { return m_filename; }; + + /** + * returns number of pages which are stored in the FAX file + * @return page count + */ + + unsigned int numPages() const { return m_pagenodes.count(); }; + + /** + * returns a QImage which holds the contents of page pageNr + * @param pageNr: page number (starting with 0) + * @return QImage of the page pageNr + */ + + QImage page( unsigned int pageNr ); + + /** + * returns the DPI (dots per inch) of page pageNr + * @param pageNr: page number (starting with 0) + * @return a QPoint value with the DPIs in X- and Y-direction + */ + + QPoint page_dpi( unsigned int pageNr ); + + /** + * returns the physical pixels of page pageNr + * @param pageNr: page number (starting with 0) + * @return a QSize value with the width and height of the image + */ + + QSize page_size( unsigned int pageNr ); + + /** + * @return a user-visible, translated error string + */ + + const QString errorString() const { return m_errorString; }; + + + + private: + + /** + * private member variables + */ + + QString m_filename; + QString m_errorString; + + typedef QPtrList<pagenode> t_PageNodeList; + t_PageNodeList m_pagenodes; + + /** + * private member functions + */ + + void reset(); + void kfaxerror(const QString& error); + pagenode *AppendImageNode(int type); + bool NewImage(pagenode *pn, int w, int h); + void FreeImage(pagenode *pn); + unsigned char *getstrip(pagenode *pn, int strip); + int GetPartImage(pagenode *pn, int n); + int GetImage(pagenode *pn); + pagenode *notefile(int type); + int notetiff(); + void badfile(pagenode *pn); +}; + +#endif /* _LIBKFAXIMAGE_H_ */ + diff --git a/kfaxview/main.cpp b/kfaxview/main.cpp new file mode 100644 index 00000000..8e967a96 --- /dev/null +++ b/kfaxview/main.cpp @@ -0,0 +1,174 @@ +#include <config.h> + +#include <dcopclient.h> +#include <dcopref.h> +#include <kapplication.h> +#include <kcmdlineargs.h> +#include <kdebug.h> +#include <kurl.h> +#include <klocale.h> +#include <kaboutdata.h> +#include <qdir.h> + +#include <stdlib.h> + +#include "kviewshell.h" + + +static KCmdLineOptions options[] = +{ + { "unique", I18N_NOOP("Check if the file is loaded in another KFaxView instance.\nIf it is, bring up the other KFaxView. Otherwise, load the file."), 0 }, + { "g", 0, 0 }, + { "goto <pagenumber>", I18N_NOOP("Navigate to this page"), 0 }, + // The rest of the options are only for compability with the old KFax + { "f", 0, 0 }, + { "fine", I18N_NOOP("(obsolete)"), 0 }, + { "n", 0, 0 }, + { "normal", I18N_NOOP("(obsolete)"), 0 }, + { "height", I18N_NOOP("(obsolete)"), 0 }, + { "w", 0, 0 }, + { "width", I18N_NOOP("(obsolete)"), 0 }, + { "l", 0, 0 }, + { "landscape", I18N_NOOP("(obsolete)"), 0 }, + { "u", 0, 0 }, + { "upsidedown", I18N_NOOP("(obsolete)"), 0 }, + { "i", 0, 0 }, + { "invert", I18N_NOOP("(obsolete)"), 0 }, + { "m", 0, 0 }, + { "mem <bytes>", I18N_NOOP("(obsolete)"), 0 }, + { "r", 0, 0 }, + { "reverse", I18N_NOOP("(obsolete)"), 0 }, + { "2" , I18N_NOOP("(obsolete)"), 0 }, + { "4", I18N_NOOP("(obsolete)"), 0 }, + { "+file(s)", I18N_NOOP("Files to load"), 0 }, + KCmdLineLastOption +}; + + +static const char description[] = I18N_NOOP("A previewer for Fax files."); + + +int main(int argc, char** argv) +{ + KAboutData about ("kfaxview", I18N_NOOP("KFaxView"), "3.5", + description, KAboutData::License_GPL, + "Stephan Kebekus, Helge Deller", + I18N_NOOP("Fax-G3 plugin for the KViewShell document viewer framework.")); + + about.addAuthor ("Stefan Kebekus", + I18N_NOOP("KViewShell plugin"), + "kebekus@kde.org", + "http://www.mi.uni-koeln.de/~kebekus"); + + about.addAuthor ("Wilfried Huss", + I18N_NOOP("KViewShell maintainer"), + "Wilfried.Huss@gmx.at"); + + about.addAuthor ("Helge Deller", + I18N_NOOP("Fax file loading"), + "deller@gmx.de"); + + KCmdLineArgs::init(argc, argv, &about); + KCmdLineArgs::addCmdLineOptions(options); + KApplication app; + + // see if we are starting with session management + if (app.isRestored()) + { + RESTORE(KViewShell); + } + else + { + KCmdLineArgs* args = KCmdLineArgs::parsedArgs(); + + if (args->isSet("unique")) + { + // With --unique, we need 2 arguments. + if (args->count() < 1) + { + args->usage(); + exit(-1); + } + + // Find the fully qualified file name of the file we are + // loading. Complain, if we are given a URL which does not point + // to a local file. + KURL url(args->url(0)); + + if (!url.isValid()) + { + kdError(4300) << QString(I18N_NOOP("The URL %1 is not well-formed.")).arg(args->arg(0)) << endl; + return -1; + } + + if (!url.isLocalFile()) + { + kdError(4300) << QString(I18N_NOOP("The URL %1 does not point to a local file. You can only specify local " + "files if you are using the '--unique' option.")).arg(args->arg(0)) << endl; + return -1; + } + + QString qualPath = QFileInfo(url.path()).absFilePath(); + + app.dcopClient()->attach(); + // We need to register as "kviewshell" to stay compatible with existing DCOP-skripts. + QCString id = app.dcopClient()->registerAs("unique-kviewshell"); + if (id.isNull()) + kdError(4300) << "There was an error using dcopClient()->registerAs()." << endl; + QCStringList apps = app.dcopClient()->registeredApplications(); + for ( QCStringList::Iterator it = apps.begin(); it != apps.end(); ++it ) + { + if ((*it).find("kviewshell") == 0) + { + QByteArray data, replyData; + QCString replyType; + QDataStream arg(data, IO_WriteOnly); + bool result; + arg << qualPath.stripWhiteSpace(); + if (!app.dcopClient()->call( *it, "kmultipage", "is_file_loaded(QString)", data, replyType, replyData)) + kdError(4300) << "There was an error using DCOP." << endl; + else + { + QDataStream reply(replyData, IO_ReadOnly); + if (replyType == "bool") + { + reply >> result; + if (result == true) + { + if (app.dcopClient()->send( *it, "kmultipage", "jumpToReference(QString)", url.ref()) == true) + { + app.dcopClient()->detach(); + return 0; + } + } + } + else + kdError(4300) << "The DCOP function 'doIt' returned an unexpected type of reply!"; + } + } + } + } + + // We need to register as "kviewshell" to stay compatible with existing DCOP-skripts. + app.dcopClient()->registerAs("kviewshell"); + KViewShell* shell = new KViewShell("image/fax-g3"); + shell->show(); + app.processEvents(); + + if (args->count() > 0) + { + KURL url = args->url(0); + if (!url.hasRef() && args->isSet("goto")) + { + // If the url doesn't already has a reference part, add the + // argument of --goto to the url as reference, to make the + // KViewShell jump to this page. + QString reference = args->getOption("goto"); + url.setHTMLRef(reference); + } + shell->openURL(url); + } + } + + return app.exec(); +} |