Commit 2bfdb0f3 authored by Pino Toscano's avatar Pino Toscano

New backend: DVI.

Adapted from the DVI plugin of KViewShell.
It can:
- load documents
- generate correctly the pixmaps for the images
- rotate the pages
- extract the text from the pages (thus search and text selection are possible)
- extract the URL hyperlinks from the documents

Credits for this work goes to Luigi Toscano, thanks Luigi!

CCMAIL: Luigi Toscano <luigi.toscano@tiscali.it>

svn path=/trunk/playground/graphics/okular/; revision=555582
parent 63c15804
......@@ -14,6 +14,7 @@ endif(CHM_FOUND)
if(DJVULIBRE_FOUND)
add_subdirectory(djvu)
endif(DJVULIBRE_FOUND)
add_subdirectory(dvi)
#original Makefile.am contents follow:
......
include_directories(
${CMAKE_SOURCE_DIR}/okular
${CMAKE_BINARY_DIR}/okular
)
#add_definitions(-DDEBUG_DVIRENDERER -DDEBUG_RENDER -DDEBUG_PRESCAN)
########### next target ###############
set(okularGenerator_dvi_SRCS
generator_dvi.cpp
bigEndianByteReader.cpp
dviRenderer.cpp
dviRenderer_draw.cpp
dviRenderer_prescan.cpp
dviRenderer_dr.cpp
special.cpp
dviFile.cpp
dviPageInfo.cpp
psgs.cpp
psheader.cpp
glyph.cpp
TeXFont.cpp
TeXFontDefinition.cpp
vf.cpp
TeXFont_PFB.cpp
TeXFont_PK.cpp
TeXFont_TFM.cpp
util.cpp
pageSize.cpp
simplePageSize.cpp
length.cpp
fontEncoding.cpp
fontEncodingPool.cpp
fontMap.cpp
fontpool.cpp
fontprogress.cpp
dvisourcesplitter.cpp
)
kde4_automoc(${okularGenerator_dvi_SRCS})
kde4_add_plugin(okularGenerator_dvi WITH_PREFIX ${okularGenerator_dvi_SRCS})
kde4_install_libtool_file( ${PLUGIN_INSTALL_DIR} okularGenerator_dvi )
target_link_libraries(okularGenerator_dvi ${KDE4_KDECORE_LIBS} okularcore m ${KDE4_KDEPRINT_LIBS} ${KDE4_KDEUI_LIBS} )
install_targets(${PLUGIN_INSTALL_DIR} okularGenerator_dvi )
########### install files ###############
install_files( ${SERVICES_INSTALL_DIR} FILES libokularGenerator_dvi.desktop )
// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; c-brace-offset: 0; -*-
#include <config.h>
#include "TeXFont.h"
TeXFont::~TeXFont()
{}
// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; c-brace-offset: 0; -*-
// TeXFont.h
//
// Part of KDVI - A DVI previewer for the KDE desktop environment
//
// (C) 2003 Stefan Kebekus
// Distributed under the GPL
#ifndef _TEXFONT_H
#define _TEXFONT_H
#include "glyph.h"
#include "TeXFontDefinition.h"
class TeXFont {
public:
TeXFont(TeXFontDefinition *_parent)
{
parent = _parent;
errorMessage = QString::null;
};
virtual ~TeXFont();
void setDisplayResolution()
{
for(unsigned int i=0; i<TeXFontDefinition::max_num_of_chars_in_font; i++)
glyphtable[i].shrunkenCharacter = QImage();
};
virtual glyph* getGlyph(quint16 character, bool generateCharacterPixmap=false, const QColor& color=Qt::black) = 0;
// Checksum of the font. Used e.g. by PK fonts. This field is filled
// in by the constructor, or set to 0.0, if the font format does not
// contain checksums.
quint32 checksum;
// If the font or if some glyphs could not be loaded, error messages
// will be put here.
QString errorMessage;
protected:
glyph glyphtable[TeXFontDefinition::max_num_of_chars_in_font];
TeXFontDefinition *parent;
};
#endif
// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; c-brace-offset: 0; -*-
#include <config.h>
#include "TeXFontDefinition.h"
#include "dviRenderer.h"
#include "kvs_debug.h"
#ifdef HAVE_FREETYPE
# include "TeXFont_PFB.h"
#endif
#include "TeXFont_PK.h"
#include "TeXFont_TFM.h"
#include "xdvi.h"
#include <klocale.h>
#include <QFile>
extern const int MFResolutions[];
#define PK_PRE 247
#define PK_ID 89
#define PK_MAGIC (PK_PRE << 8) + PK_ID
#define GF_PRE 247
#define GF_ID 131
#define GF_MAGIC (GF_PRE << 8) + GF_ID
#define VF_PRE 247
#define VF_ID_BYTE 202
#define VF_MAGIC (VF_PRE << 8) + VF_ID_BYTE
// #define DEBUG_FONT
TeXFontDefinition::TeXFontDefinition(QString nfontname, double _displayResolution_in_dpi, quint32 chk, qint32 _scaled_size_in_DVI_units,
class fontPool *pool, double _enlargement)
{
#ifdef DEBUG_FONT
kDebug(kvs::dvi) << "TeXFontDefinition::TeXFontDefinition(...); fontname=" << nfontname << ", enlargement=" << _enlargement << endl;
#endif
enlargement = _enlargement;
font_pool = pool;
fontname = nfontname;
font = 0;
displayResolution_in_dpi = _displayResolution_in_dpi;
checksum = chk;
flags = TeXFontDefinition::FONT_IN_USE;
file = 0;
filename = QString::null;
scaled_size_in_DVI_units = _scaled_size_in_DVI_units;
macrotable = 0;
// By default, this font contains only empty characters. After the
// font has been loaded, this function pointer will be replaced by
// another one.
set_char_p = &dviRenderer::set_empty_char;
}
TeXFontDefinition::~TeXFontDefinition()
{
#ifdef DEBUG_FONT
kDebug(kvs::dvi) << "discarding font " << fontname << " at " << (int)(enlargement * MFResolutions[font_pool->getMetafontMode()] + 0.5) << " dpi" << endl;
#endif
if (font != 0) {
delete font;
font = 0;
}
if (macrotable != 0) {
delete [] macrotable;
macrotable = 0;
}
if (flags & FONT_LOADED) {
if (file != 0) {
fclose(file);
file = 0;
}
if (flags & FONT_VIRTUAL)
vf_table.clear();
}
}
void TeXFontDefinition::fontNameReceiver(const QString& fname)
{
#ifdef DEBUG_FONT
kDebug(kvs::dvi) << "void TeXFontDefinition::fontNameReceiver( " << fname << " )" << endl;
#endif
flags |= TeXFontDefinition::FONT_LOADED;
filename = fname;
#ifdef HAVE_FREETYPE
fullFontName = QString::null;
fullEncodingName = QString::null;
#endif
file = fopen(QFile::encodeName(filename), "r");
// Check if the file could be opened. If not, try to find the file
// in the DVI file's directory. If that works, modify the filename
// accordingly and go on.
if (file == 0) {
QString filename_test(font_pool->getExtraSearchPath() + "/" + filename);
file = fopen( QFile::encodeName(filename_test), "r");
if (file == 0) {
kError(kvs::dvi) << i18n("Cannot find font %1, file %2.", fontname, filename) << endl;
return;
} else
filename = filename_test;
}
set_char_p = &dviRenderer::set_char;
int magic = two(file);
if (fname.endsWith("pk"))
if (magic == PK_MAGIC) {
fclose(file);
file = 0;
font = new TeXFont_PK(this);
set_char_p = &dviRenderer::set_char;
if ((checksum != 0) && (checksum != font->checksum))
kWarning(kvs::dvi) << i18n("Checksum mismatch for font file %1", filename) << endl;
fontTypeName = "TeX PK";
return;
}
if (fname.endsWith(".vf"))
if (magic == VF_MAGIC) {
read_VF_index();
set_char_p = &dviRenderer::set_vf_char;
fontTypeName = i18n("TeX virtual");
return;
}
if (fname.endsWith(".tfm")) {
fclose(file);
file = 0;
font = new TeXFont_TFM(this);
set_char_p = &dviRenderer::set_char;
fontTypeName = i18n("TeX Font Metric");
return;
}
// None of these known types? Then it should be one of the font
// formats that are handled by the FreeType library
fclose(file);
file = 0;
#ifdef HAVE_FREETYPE
// Find the encoding for that font
const QString &enc = font_pool->fontsByTeXName.findEncoding(fontname);
if (enc.isEmpty() == false) {
#ifdef DEBUG_FONT
kDebug(kvs::dvi) << "Font " << fontname << " uses encoding " << enc << endl;
#endif
font = new TeXFont_PFB(this, font_pool->encodingPool.findByName(enc), font_pool->fontsByTeXName.findSlant(fontname) );
} else {
#ifdef DEBUG_FONT
kDebug(kvs::dvi) << "Font " << fontname << " does not have an encoding." << endl;
#endif
font = new TeXFont_PFB(this);
}
set_char_p = &dviRenderer::set_char;
fontTypeName = i18n("FreeType");
return;
#else
// If we don't have the FreeType library, we should never have
// reached this point. Complain, and leave this font blank
kError(kvs::dvi) << i18n("Cannot recognize format for font file %1", filename) << endl;
#endif
}
void TeXFontDefinition::reset()
{
if (font != 0) {
delete font;
font = 0;
}
if (macrotable != 0) {
delete [] macrotable;
macrotable = 0;
}
if (flags & FONT_LOADED) {
if (file != 0) {
fclose(file);
file = 0;
}
if (flags & FONT_VIRTUAL)
vf_table.clear();
}
filename = QString::null;
flags = TeXFontDefinition::FONT_IN_USE;
set_char_p = &dviRenderer::set_empty_char;
}
void TeXFontDefinition::setDisplayResolution(double _displayResolution_in_dpi)
{
displayResolution_in_dpi = _displayResolution_in_dpi;
if (font != 0)
font->setDisplayResolution();
}
/** mark_as_used marks the font, and all the fonts it referrs to, as
used, i.e. their FONT_IN_USE-flag is set. */
void TeXFontDefinition::mark_as_used()
{
#ifdef DEBUG_FONT
kDebug(kvs::dvi) << "TeXFontDefinition::mark_as_used()" << endl;
#endif
if (flags & TeXFontDefinition::FONT_IN_USE)
return;
flags |= TeXFontDefinition::FONT_IN_USE;
// For virtual fonts, also go through the list of referred fonts
if (flags & TeXFontDefinition::FONT_VIRTUAL) {
Q3IntDictIterator<TeXFontDefinition> it(vf_table);
while( it.current() ) {
it.current()->flags |= TeXFontDefinition::FONT_IN_USE;
++it;
}
}
}
macro::macro()
{
pos = 0; /* address of first byte of macro */
end = 0; /* address of last+1 byte */
dvi_advance_in_units_of_design_size_by_2e20 = 0; /* DVI units to move reference point */
free_me = false;
}
macro::~macro()
{
if ((pos != 0L) && (free_me == true))
delete [] pos;
}
// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; c-brace-offset: 0; -*-
/*
* The layout of a font information block.
* There is one of these for every loaded font or magnification thereof.
* Duplicates are eliminated: this is necessary because of possible recursion
* in virtual fonts.
*
* Also note the strange units. The design size is in 1/2^20 point
* units (also called micro-points), and the individual character widths
* are in the TFM file in 1/2^20 ems units, i.e., relative to the design size.
*
* We then change the sizes to SPELL units (unshrunk pixel / 2^16).
*/
#ifndef _FONT_H
#define _FONT_H
#include <Q3IntDict>
#include <QString>
#include <cstdio>
class dviRenderer;
class TeXFont;
typedef void (dviRenderer::*set_char_proc)(unsigned int, unsigned int);
// Per character information for virtual fonts
class macro {
public:
macro();
~macro();
// address of first byte of macro
unsigned char* pos;
// address of last+1 byte
unsigned char* end;
// DVI units to move reference point
qint32 dvi_advance_in_units_of_design_size_by_2e20;
// if memory at pos should be returned on destruction
bool free_me;
};
class TeXFontDefinition {
public:
// Currently, kdvi supports fonts with at most 256 characters to
// comply with "The DVI Driver Standard, Level 0". If you change
// this value here, make sure to go through all the source and
// ensure that character numbers are stored in ints rather than
// unsigned chars.
static const unsigned int max_num_of_chars_in_font = 256;
enum font_flags {
// used for housekeeping
FONT_IN_USE = 1,
// if font file has been read
FONT_LOADED = 2,
// if font is virtual
FONT_VIRTUAL = 4,
// if kpathsea has already tried to find the font name
FONT_KPSE_NAME = 8
};
TeXFontDefinition(QString nfontname, double _displayResolution_in_dpi, quint32 chk, qint32 _scaled_size_in_DVI_units,
class fontPool *pool, double _enlargement);
~TeXFontDefinition();
void reset();
void fontNameReceiver(const QString&);
// Members for character fonts
void setDisplayResolution(double _displayResolution_in_dpi);
bool isLocated() const {return ((flags & FONT_KPSE_NAME) != 0);}
void markAsLocated() {flags |= FONT_KPSE_NAME;}
void mark_as_used();
// Pointer to the pool that contains this font.
class fontPool *font_pool;
// name of font, such as "cmr10"
QString fontname;
// flags byte (see values below)
unsigned char flags;
double enlargement;
// Scaled size from the font definition command; in DVI units
qint32 scaled_size_in_DVI_units;
// proc used to set char
set_char_proc set_char_p;
// Resolution of the display device (resolution will usually be
// scaled, according to the zoom)
double displayResolution_in_dpi;
// open font file or NULL
FILE* file;
// name of font file
QString filename;
TeXFont* font;
// used by (loaded) virtual fonts
macro* macrotable;
// used by (loaded) virtual fonts, list of fonts used by this vf,
Q3IntDict<TeXFontDefinition> vf_table;
// acessible by number
// used by (loaded) virtual fonts, list of fonts used by this vf
TeXFontDefinition* first_font;
#ifdef HAVE_FREETYPE
const QString &getFullFontName() const {return fullFontName;}
const QString &getFullEncodingName() const {return fullEncodingName;}
#endif
const QString &getFontTypeName() const {return fontTypeName;}
#ifdef HAVE_FREETYPE
/** For FREETYPE fonts, which use a map file, this field will
contain the full name of the font (e.g. 'Computer Modern'). If
the name does not exist, or cannot be found, this field will be
QString::null. Only subclasses of TeXFont should write into this
field. */
QString fullFontName;
/** For FREETYPE fonts, which use a map file, this field will
contain the full name of the font encoding (e.g. 'TexBase1'). If
the encoding name does not exist, or cannot be found, this field
will be QString::null. Only subclasses of TeXFont should write
into this field. */
QString fullEncodingName;
#endif
private:
quint32 checksum;
/** This will be set to a human-readable description of the font,
e.g. "virtual" or "TeX PK", or "Type 1" */
QString fontTypeName;
// Functions related to virtual fonts
void read_VF_index(void );
};
#endif
// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; c-brace-offset: 0; -*-
// TeXFont_PFB.cpp
//
// Part of KDVI - A DVI previewer for the KDE desktop environment
//
// (C) 2003 Stefan Kebekus
// Distributed under the GPL
// This file is compiled only if the FreeType library is present on
// the system
#include <config.h>
#ifdef HAVE_FREETYPE
#include "TeXFont_PFB.h"
#include "fontpool.h"
#include "kvs_debug.h"
#include <klocale.h>
#include <QImage>
//#define DEBUG_PFB 1
TeXFont_PFB::TeXFont_PFB(TeXFontDefinition *parent, fontEncoding *enc, double slant)
: TeXFont(parent)
{
#ifdef DEBUG_PFB
if (enc != 0)
kDebug(kvs::dvi) << "TeXFont_PFB::TeXFont_PFB( parent=" << parent << ", encoding=" << enc->encodingFullName << " )" << endl;
else
kDebug(kvs::dvi) << "TeXFont_PFB::TeXFont_PFB( parent=" << parent << ", encoding=0 )" << endl;
#endif
fatalErrorInFontLoading = false;
int error = FT_New_Face( parent->font_pool->FreeType_library, parent->filename.toLocal8Bit(), 0, &face );
if ( error == FT_Err_Unknown_File_Format ) {
errorMessage = i18n("The font file %1 could be opened and read, but its font format is unsupported.", parent->filename);
kError(kvs::dvi) << errorMessage << endl;
fatalErrorInFontLoading = true;
return;
} else
if ( error ) {
errorMessage = i18n("The font file %1 is broken, or it could not be opened or read.", parent->filename);
kError(kvs::dvi) << errorMessage << endl;
fatalErrorInFontLoading = true;
return;
}
// Take care of slanting, and transform all characters in the font, if necessary.
if (slant != 0.0) {
// Construct a transformation matrix for vertical shear which will
// be used to transform the characters.
transformationMatrix.xx = 0x10000;
transformationMatrix.xy = (FT_Fixed)(slant * 0x10000);
transformationMatrix.yx = 0;
transformationMatrix.yy = 0x10000;
FT_Set_Transform( face, &transformationMatrix, 0);
}
if (face->family_name != 0)
parent->fullFontName = face->family_name;
// Finally, we need to set up the charMap array, which maps TeX
// character codes to glyph indices in the font. (Remark: the
// charMap, and the font encoding procedure is necessary, because
// TeX is only able to address character codes 0-255 while
// e.g. Type1 fonts may contain several thousands of characters)
if (enc != 0) {
parent->fullEncodingName = enc->encodingFullName.remove(QString::fromLatin1( "Encoding" ));
parent->fullEncodingName = enc->encodingFullName.remove(QString::fromLatin1( "encoding" ));
// An encoding vector is given for this font, i.e. an array of
// character names (such as: 'parenleft' or 'dotlessj'). We use
// the FreeType library function 'FT_Get_Name_Index()' to