QOutputDev is no longer a OutputDev subclass but a SplashOutputDev sublclass. That makes xpdf do all the work related to rendering (sorting lots of problems with fonts, etc). That should improve the render quality of kpdf drastically.

svn path=/trunk/kdegraphics/kpdf/; revision=340973
This commit is contained in:
Albert Astals Cid 2004-08-25 16:27:34 +00:00
parent ee86e7f46b
commit 264b6249ab
60 changed files with 7930 additions and 1111 deletions

View file

@ -1,3 +1,6 @@
2004-08-25 Albert Astals Cid <tsdgeos@terra.es>
* Completely use xpdf code for rendering that solves most font problems
2004-08-23 Albert Astals Cid <tsdgeos@terra.es>
* Replace xpdf version with lastest one (3.00) that supports PDF 1.5

View file

@ -1,6 +1 @@
SUBDIRS = . fofi goo xpdf kpdf
noinst_HEADERS = aconf.h
aconf.h:
ln -s ../config.h aconf.h
SUBDIRS = fofi goo splash xpdf kpdf

4
aconf.h Normal file
View file

@ -0,0 +1,4 @@
#include "../config.h"
#define HAVE_FREETYPE_H HAVE_FREETYPE
#define HAVE_FREETYPE_FREETYPE_H HAVE_FREETYPE

View file

@ -3,8 +3,7 @@ INCLUDES = -I.. -I$(srcdir)/../goo $(all_includes)
libfofi_la_LDFLAGS = $(all_libraries)
libfofi_la_SOURCES = FoFiBase.cc FoFiEncodings.cc FoFiTrueType.cc \
FoFiType1.cc FoFiType1C.cc
libfofi_la_COMPILE_FIRST = ../aconf.h
METASOURCES = AUTO
noinst_LTLIBRARIES = libfofi.la
noinst_LTLIBRARIES = libfofi.la

View file

@ -1,6 +1,5 @@
INCLUDES = -I..
libgoo_la_SOURCES = GHash.cc GList.cc GString.cc gfile.cc gmem.c gmempp.cc
libgoo_la_COMPILE_FIRST = ../aconf.h
noinst_LTLIBRARIES = libgoo.la

View file

@ -1,5 +1,5 @@
# set the include path for X, qt and KDE
INCLUDES = -I.. -I$(srcdir)/../goo -I$(srcdir)/../xpdf $(all_includes)
INCLUDES = -I.. -I$(srcdir)/../splash -I$(srcdir)/../fofi -I$(srcdir)/../goo -I$(srcdir)/../xpdf $(all_includes) $(FREETYPE_CFLAGS)
# these are the headers for your project
noinst_HEADERS = kpdf_shell.h kpdf_part.h kpdf_canvas.h kpdf_pagewidget.h QOutputDevPixmap.h QOutputDev.h
@ -27,7 +27,7 @@ bin_PROGRAMS = kpdf
kpdf_SOURCES = main.cpp kpdf_shell.cpp
kpdf_LDFLAGS = $(KDE_RPATH) $(all_libraries)
kpdf_LDADD = $(LIB_KPARTS)
kpdf_COMPILE_FIRST = ../aconf.h part.h
kpdf_COMPILE_FIRST = part.h
EXTRA_DIST = kpdf.desktop
xdg_apps_DATA = kpdf.desktop

File diff suppressed because it is too large Load diff

View file

@ -1,4 +1,5 @@
/* This file is part of the KDE libraries
Copyright (C) 2004 Albert Astals Cid <tsdgeos@terra.es>
Copyright (C) 2001, 2003 Christophe Devriese <oelewapperke@kde.org>
Copyright 1996 Derek B. Noonburg
@ -24,165 +25,49 @@
#pragma interface
#endif
#include "aconf.h"
#include <stddef.h>
#include "XRef.h"
#include "SplashOutputDev.h"
class Object;
#include <qcolor.h>
#include <qobject.h>
#include "config.h"
#include "CharTypes.h"
#include "GlobalParams.h"
#include "OutputDev.h"
class GString;
class GList;
struct GfxRGB;
class GfxFont;
class GfxSubpath;
class TextPage;
class XOutputFontCache;
class Link;
class Catalog;
class DisplayFontParam;
class UnicodeMap;
class CharCodeToUnicode;
class QPainter;
class QPixmap;
class QPointArray;
typedef double fp_t;
//------------------------------------------------------------------------
// Constants
// QOutputDev
//------------------------------------------------------------------------
//------------------------------------------------------------------------
// Misc types
//------------------------------------------------------------------------
//------------------------------------------------------------------------
// XOutputDev
//------------------------------------------------------------------------
class QOutputDev : public QObject, public OutputDev {
Q_OBJECT
public:
// Constructor.
QOutputDev( QPainter * p = 0 );
// Destructor.
virtual ~QOutputDev();
//---- get info about output device
// Does this device use upside-down coordinates?
// (Upside-down means (0,0) is the top left corner of the page.)
virtual GBool upsideDown() { return gTrue; }
// Does this device use drawChar() or drawString()?
virtual GBool useDrawChar() { return gTrue; }
// Does this device use beginType3Char/endType3Char? Otherwise,
// text in Type 3 fonts will be drawn with drawChar/drawString.
virtual GBool interpretType3Chars() { return gFalse; }
// Does this device need non-text content?
virtual GBool needNonText() { return gFalse; }
//----- initialization and control
// Start a page.
virtual void startPage(int pageNum, GfxState *state);
// End a page.
virtual void endPage();
//----- link borders
virtual void drawLink(Link *link, Catalog *catalog);
//----- save/restore graphics state
virtual void saveState(GfxState *state);
virtual void restoreState(GfxState *state);
//----- update graphics state
virtual void updateAll(GfxState *state);
virtual void updateCTM(GfxState *state, fp_t m11, fp_t m12,
fp_t m21, fp_t m22, fp_t m31, fp_t m32);
virtual void updateLineDash(GfxState *state);
virtual void updateFlatness(GfxState *state);
virtual void updateLineJoin(GfxState *state);
virtual void updateLineCap(GfxState *state);
virtual void updateMiterLimit(GfxState *state);
virtual void updateLineWidth(GfxState *state);
virtual void updateFillColor(GfxState *state);
virtual void updateStrokeColor(GfxState *state);
//----- update text state
virtual void updateFont(GfxState *state);
//----- path painting
virtual void stroke(GfxState *state);
virtual void fill(GfxState *state);
virtual void eoFill(GfxState *state);
//----- path clipping
virtual void clip(GfxState *state);
virtual void eoClip(GfxState *state);
//----- text drawing
virtual void beginString(GfxState *state, GString *s);
virtual void endString(GfxState *state);
virtual void drawChar(GfxState *state, fp_t x, fp_t y,
fp_t dx, fp_t dy,
fp_t originX, fp_t originY,
CharCode code, Unicode *u, int uLen);
//----- image drawing
virtual void drawImageMask(GfxState *state, Object *ref, Stream *str,
int width, int height, GBool invert,
GBool inlineImg);
virtual void drawImage(GfxState *state, Object *ref, Stream *str,
int width, int height, GfxImageColorMap *colorMap,
int *maskColors, GBool inlineImg);
// Find a string. If <top> is true, starts looking at <l>,<t>;
// otherwise starts looking at top of page. If <bottom> is true,
// stops looking at <l+w-1>,<t+h-1>; otherwise stops looking at bottom
// of page. If found, sets the text bounding rectange and returns
// true; otherwise returns false.
// GBool findText ( Unicode *s, int len, GBool top, GBool bottom, int *xMin, int *yMin, int *xMax, int *yMax );
//----- special QT access
// bool findText ( const QString &str, int &l, int &t, int &w, int &h, bool top = 0, bool bottom = 0 );
// bool findText ( const QString &str, QRect &r, bool top = 0, bool bottom = 0 );
// Get the text which is inside the specified rectangle.
QString getText ( int left, int top, int width, int height );
QString getText ( const QRect &r );
protected:
QPainter *m_painter;
TextPage *m_text; // text from the current page
private:
QFont matchFont ( GfxFont *, fp_t m11, fp_t m12, fp_t m21, fp_t m22 );
void updateLineAttrs ( GfxState *state, GBool updateDash );
void doFill ( GfxState *state, bool winding );
void doClip ( GfxState *state, bool winding );
int convertPath ( GfxState *state, QPointArray &points, QMemArray<int> &lengths );
int convertSubpath ( GfxState *state, GfxSubpath *subpath, QPointArray &points );
class QOutputDev : public SplashOutputDev
{
public:
// Constructor
QOutputDev(QPainter *p, SplashColor paperColor);
// Destructor.
virtual ~QOutputDev();
// Start a page.
virtual void startPage(int pageNum, GfxState *state);
// End a page.
virtual void endPage();
//----- update text state
virtual void updateFont(GfxState *state);
//----- text drawing
virtual void drawChar(GfxState *state, double x, double y, double dx, double dy, double originX, double originY, CharCode code, Unicode *u, int uLen);
virtual GBool beginType3Char(GfxState *state, double x, double y, double dx, double dy, CharCode code, Unicode *u, int uLen);
// Clear out the document (used when displaying an empty window).
void clear();
QColor m_fillColor;
protected:
QPainter *m_painter;
private:
void draw();
TextPage *m_text; // text from the current page
};
#endif

View file

@ -18,15 +18,13 @@
// 02111-1307, USA.
#include "QOutputDevKPrinter.h"
#include "QOutputDevKPrinter.moc"
#include <kprinter.h>
#include <qpainter.h>
QOutputDevKPrinter::QOutputDevKPrinter( QPainter& painter, KPrinter& printer )
: m_printer( printer )
QOutputDevKPrinter::QOutputDevKPrinter(QPainter& painter, SplashColor paperColor, KPrinter& printer )
: QOutputDev(&painter, paperColor), m_printer( printer )
{
m_painter = &painter;
}
QOutputDevKPrinter::~QOutputDevKPrinter()

View file

@ -16,8 +16,8 @@
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
// 02111-1307, USA.
#ifndef KPDF_KPDF_QOUTPUTDEVKPRINTER_H
#define KPDF_KPDF_QOUTPUTDEVKPRINTER_H
#ifndef QOUTPUTDEVKPRINTER_H
#define OUTPUTDEVKPRINTER_H
#include "QOutputDev.h"
@ -25,9 +25,8 @@ class KPrinter;
class QOutputDevKPrinter : public QOutputDev
{
Q_OBJECT
public:
QOutputDevKPrinter( QPainter& painter, KPrinter& printer );
QOutputDevKPrinter(QPainter& painter, SplashColor paperColor, KPrinter& printer);
virtual ~QOutputDevKPrinter();
//----- initialization and control

View file

@ -45,7 +45,6 @@
#include <kdebug.h>
#include "QOutputDevPixmap.h"
#include "QOutputDevPixmap.moc"
//------------------------------------------------------------------------
// Constants and macros
@ -63,11 +62,11 @@ static inline QColor q_col ( const GfxRGB &rgb )
// QOutputDevPixmap
//------------------------------------------------------------------------
QOutputDevPixmap::QOutputDevPixmap () : QOutputDev(0), m_pixmap(0)
QOutputDevPixmap::QOutputDevPixmap(SplashColor paperColor) : QOutputDev(0, paperColor), m_pixmap(0)
{
}
QOutputDevPixmap::~QOutputDevPixmap ( )
QOutputDevPixmap::~QOutputDevPixmap( )
{
delete m_pixmap;
}

View file

@ -34,15 +34,13 @@
#include "QOutputDev.h"
typedef double fp_t;
class QPixmap;
class QOutputDevPixmap : public QOutputDev {
Q_OBJECT
public:
// Constructor.
QOutputDevPixmap( );
QOutputDevPixmap(SplashColor paperColor);
// Destructor.
virtual ~QOutputDevPixmap();

View file

@ -26,7 +26,9 @@ namespace KPDF
m_currentPage( 1 ),
m_pressedAction( 0 )
{
m_outputdev = new QOutputDevPixmap();
SplashColor paperColor;
paperColor.rgb8 = splashMakeRGB8(0xff, 0xff, 0xff);
m_outputdev = new QOutputDevPixmap(paperColor);
setFocusPolicy( QWidget::StrongFocus );
viewport()->setFocusPolicy( QWidget::WheelFocus );
}
@ -38,6 +40,7 @@ namespace KPDF
PageWidget::setPDFDocument(PDFDoc* doc)
{
m_doc = doc;
m_outputdev -> startDoc(doc->getXRef());
m_currentPage = 1;
updatePixmap();
}

View file

@ -380,7 +380,11 @@ void Part::nextThumbnail()
// Pixels per point when the zoomFactor is 1.
const double basePpp = QPaintDevice::x11AppDpiX() / 72.0;
const double ppp = basePpp * m_zoomFactor; // pixels per point
QOutputDevPixmap odev;
SplashColor paperColor;
paperColor.rgb8 = splashMakeRGB8(0xff, 0xff, 0xff);
QOutputDevPixmap odev(paperColor);
odev.startDoc(m_doc->getXRef());
m_doc->displayPage(&odev, m_nextThumbnail, ppp * 72.0, ppp * 72.0, 0, true, true);
pdfpartview->setThumbnail(m_nextThumbnail, odev.getPixmap());
@ -677,7 +681,10 @@ void Part::printPreview()
KPrinter printer;
printer.setPreviewOnly( true );
QPainter painter( &printer );
QOutputDevKPrinter printdev( painter, printer );
SplashColor paperColor;
paperColor.rgb8 = splashMakeRGB8(0xff, 0xff, 0xff);
QOutputDevKPrinter printdev( painter, paperColor, printer );
printdev.startDoc(m_doc->getXRef());
int max = m_doc->getNumPages();
for ( int i = 1; i <= max; ++i )
{
@ -690,7 +697,10 @@ void Part::printPreview()
void Part::doPrint( KPrinter& printer )
{
QPainter painter( &printer );
QOutputDevKPrinter printdev( painter, printer );
SplashColor paperColor;
paperColor.rgb8 = splashMakeRGB8(0xff, 0xff, 0xff);
QOutputDevKPrinter printdev( painter, paperColor, printer );
printdev.startDoc(m_doc->getXRef());
QValueList<int> pages = printer.pageList();
for ( QValueList<int>::ConstIterator i = pages.begin(); i != pages.end();)
{

9
splash/Makefile.am Normal file
View file

@ -0,0 +1,9 @@
INCLUDES = -I.. -I$(srcdir)/../fofi -I$(srcdir)/../goo $(LIBFREETYPE_CFLAGS)
libsplash_la_SOURCES = Splash.cc SplashBitmap.cc SplashClip.cc SplashFTFont.cc SplashFTFontEngine.cc \
SplashFTFontFile.cc SplashFont.cc SplashFontEngine.cc SplashFontFile.cc SplashFontFileID.cc \
SplashPath.cc SplashPattern.cc SplashScreen.cc SplashState.cc SplashT1Font.cc \
SplashT1FontEngine.cc SplashT1FontFile.cc SplashXPath.cc SplashXPathScanner.cc
libsplash_la_COMPILE_FIRST = ../aconf.h
noinst_LTLIBRARIES = libsplash.la

1648
splash/Splash.cc Normal file

File diff suppressed because it is too large Load diff

176
splash/Splash.h Normal file
View file

@ -0,0 +1,176 @@
//========================================================================
//
// Splash.h
//
//========================================================================
#ifndef SPLASH_H
#define SPLASH_H
#include <aconf.h>
#ifdef USE_GCC_PRAGMAS
#pragma interface
#endif
#include "SplashTypes.h"
class SplashBitmap;
class SplashGlyphBitmap;
class SplashState;
class SplashPattern;
class SplashScreen;
class SplashPath;
class SplashXPath;
class SplashClip;
class SplashFont;
//------------------------------------------------------------------------
// Retrieves the next pixel in an image mask. Normally, fills in
// *<pixel> and returns true. If the image stream is exhausted,
// returns false.
typedef GBool (*SplashImageMaskSource)(void *data, SplashMono1 *pixel);
// Retrieves the next pixel in an image. Normally, fills in *<pixel>
// (pixel color) and *<alpha> (1 for opaque, 0 for transparent), and
// returns true. If the image stream is exhausted, returns false.
typedef GBool (*SplashImageSource)(void *data, SplashColor *pixel,
Guchar *alpha);
//------------------------------------------------------------------------
// Splash
//------------------------------------------------------------------------
class Splash {
public:
// Create a new rasterizer object.
Splash(SplashBitmap *bitmapA);
~Splash();
//----- state read
SplashPattern *getStrokePattern();
SplashPattern *getFillPattern();
SplashScreen *getScreen();
SplashCoord getLineWidth();
int getLineCap();
int getLineJoin();
SplashCoord getMiterLimit();
SplashCoord getFlatness();
SplashCoord *getLineDash();
int getLineDashLength();
SplashCoord getLineDashPhase();
SplashClip *getClip();
//----- state write
void setStrokePattern(SplashPattern *strokeColor);
void setFillPattern(SplashPattern *fillColor);
void setScreen(SplashScreen *screen);
void setLineWidth(SplashCoord lineWidth);
void setLineCap(int lineCap);
void setLineJoin(int lineJoin);
void setMiterLimit(SplashCoord miterLimit);
void setFlatness(SplashCoord flatness);
// the <lineDash> array will be copied
void setLineDash(SplashCoord *lineDash, int lineDashLength,
SplashCoord lineDashPhase);
void clipResetToRect(SplashCoord x0, SplashCoord y0,
SplashCoord x1, SplashCoord y1);
SplashError clipToRect(SplashCoord x0, SplashCoord y0,
SplashCoord x1, SplashCoord y1);
SplashError clipToPath(SplashPath *path, GBool eo);
//----- state save/restore
void saveState();
SplashError restoreState();
//----- drawing operations
// Fill the bitmap with <color>. This is not subject to clipping.
void clear(SplashColor color);
// Stroke a path using the current stroke pattern.
SplashError stroke(SplashPath *path);
// Fill a path using the current fill pattern.
SplashError fill(SplashPath *path, GBool eo);
// Fill a path, XORing with the current fill pattern.
SplashError xorFill(SplashPath *path, GBool eo);
// Draw a character, using the current fill pattern.
SplashError fillChar(SplashCoord x, SplashCoord y, int c, SplashFont *font);
// Draw a glyph, using the current fill pattern. This function does
// not free any data, i.e., it ignores glyph->freeData.
SplashError fillGlyph(SplashCoord x, SplashCoord y,
SplashGlyphBitmap *glyph);
// Draws an image mask using the fill color. This will read <w>*<h>
// pixels from <src>, in raster order, starting with the top line.
// "1" pixels will be drawn with the current fill color; "0" pixels
// are transparent. The matrix:
// [ mat[0] mat[1] 0 ]
// [ mat[2] mat[3] 0 ]
// [ mat[4] mat[5] 1 ]
// maps a unit square to the desired destination for the image, in
// PostScript style:
// [x' y' 1] = [x y 1] * mat
// Note that the Splash y axis points downward, and the image source
// is assumed to produce pixels in raster order, starting from the
// top line.
SplashError fillImageMask(SplashImageMaskSource src, void *srcData,
int w, int h, SplashCoord *mat);
// Draw an image. This will read <w>*<h> pixels from <src>, in
// raster order, starting with the top line. These pixels are
// assumed to be in the source mode, <srcMode>. The following
// combinations of source and target modes are supported:
// source target
// ------ ------
// Mono1 Mono1
// Mono8 Mono1 -- with dithering
// Mono8 Mono8
// RGB8 RGB8
// BGR8packed BGR8Packed
// The matrix behaves as for fillImageMask.
SplashError drawImage(SplashImageSource src, void *srcData,
SplashColorMode srcMode,
int w, int h, SplashCoord *mat);
//~ drawMaskedImage
//----- misc
// Return the associated bitmap.
SplashBitmap *getBitmap() { return bitmap; }
// Toggle debug mode on or off.
void setDebugMode(GBool debugModeA) { debugMode = debugModeA; }
private:
void strokeNarrow(SplashXPath *xPath);
void strokeWide(SplashXPath *xPath);
SplashXPath *makeDashedPath(SplashXPath *xPath);
SplashError fillWithPattern(SplashPath *path, GBool eo,
SplashPattern *pattern);
void drawPixel(int x, int y, SplashColor *color, GBool noClip);
void drawPixel(int x, int y, SplashPattern *pattern, GBool noClip);
void drawSpan(int x0, int x1, int y, SplashPattern *pattern, GBool noClip);
void xorSpan(int x0, int x1, int y, SplashPattern *pattern, GBool noClip);
void putPixel(int x, int y, SplashColor *pixel);
void getPixel(int x, int y, SplashColor *pixel);
void dumpPath(SplashPath *path);
SplashBitmap *bitmap;
SplashState *state;
GBool debugMode;
};
#endif

134
splash/SplashBitmap.cc Normal file
View file

@ -0,0 +1,134 @@
//========================================================================
//
// SplashBitmap.cc
//
//========================================================================
#include <aconf.h>
#ifdef USE_GCC_PRAGMAS
#pragma implementation
#endif
#include <stdio.h>
#include "gmem.h"
#include "SplashErrorCodes.h"
#include "SplashBitmap.h"
//------------------------------------------------------------------------
// SplashBitmap
//------------------------------------------------------------------------
SplashBitmap::SplashBitmap(int widthA, int heightA, SplashColorMode modeA) {
width = widthA;
height = heightA;
mode = modeA;
switch (mode) {
case splashModeMono1:
rowSize = (width + 7) >> 3;
data.mono1 = (SplashMono1P *)
gmalloc(rowSize * height * sizeof(SplashMono1P));
break;
case splashModeMono8:
rowSize = width;
data.mono8 = (SplashMono8 *)
gmalloc(width * height * sizeof(SplashMono8));
break;
case splashModeRGB8:
rowSize = width << 2;
data.rgb8 = (SplashRGB8 *)
gmalloc(width * height * sizeof(SplashRGB8));
break;
case splashModeBGR8Packed:
rowSize = (width * 3 + 3) & ~3;
data.bgr8 = (SplashBGR8P *)
gmalloc(rowSize * height * sizeof(SplashMono1P));
}
}
SplashBitmap::~SplashBitmap() {
switch (mode) {
case splashModeMono1:
gfree(data.mono1);
break;
case splashModeMono8:
gfree(data.mono8);
break;
case splashModeRGB8:
gfree(data.rgb8);
break;
case splashModeBGR8Packed:
gfree(data.bgr8);
break;
}
}
SplashError SplashBitmap::writePNMFile(char *fileName) {
FILE *f;
SplashMono1P *mono1;
SplashMono8 *mono8;
SplashRGB8 *rgb8;
SplashBGR8P *bgr8line, *bgr8;
int x, y;
if (!(f = fopen(fileName, "wb"))) {
return splashErrOpenFile;
}
switch (mode) {
case splashModeMono1:
fprintf(f, "P4\n%d %d\n", width, height);
mono1 = data.mono1;
for (y = 0; y < height; ++y) {
for (x = 0; x < width; x += 8) {
fputc(*mono1 ^ 0xff, f);
++mono1;
}
}
break;
case splashModeMono8:
fprintf(f, "P5\n%d %d\n255\n", width, height);
mono8 = data.mono8;
for (y = 0; y < height; ++y) {
for (x = 0; x < width; ++x) {
fputc(*mono8, f);
++mono8;
}
}
break;
case splashModeRGB8:
fprintf(f, "P6\n%d %d\n255\n", width, height);
rgb8 = data.rgb8;
for (y = 0; y < height; ++y) {
for (x = 0; x < width; ++x) {
fputc(splashRGB8R(*rgb8), f);
fputc(splashRGB8G(*rgb8), f);
fputc(splashRGB8B(*rgb8), f);
++rgb8;
}
}
break;
case splashModeBGR8Packed:
fprintf(f, "P6\n%d %d\n255\n", width, height);
bgr8line = data.bgr8;
for (y = 0; y < height; ++y) {
bgr8 = bgr8line;
for (x = 0; x < width; ++x) {
fputc(bgr8[2], f);
fputc(bgr8[1], f);
fputc(bgr8[0], f);
bgr8 += 3;
}
bgr8line += rowSize;
}
break;
}
fclose(f);
return splashOk;
}

48
splash/SplashBitmap.h Normal file
View file

@ -0,0 +1,48 @@
//========================================================================
//
// SplashBitmap.h
//
//========================================================================
#ifndef SPLASHBITMAP_H
#define SPLASHBITMAP_H
#include <aconf.h>
#ifdef USE_GCC_PRAGMAS
#pragma interface
#endif
#include "SplashTypes.h"
//------------------------------------------------------------------------
// SplashBitmap
//------------------------------------------------------------------------
class SplashBitmap {
public:
// Create a new bitmap.
SplashBitmap(int widthA, int heightA, SplashColorMode modeA);
~SplashBitmap();
int getWidth() { return width; }
int getHeight() { return height; }
int getRowSize() { return rowSize; }
SplashColorMode getMode() { return mode; }
SplashColorPtr getDataPtr() { return data; }
SplashError writePNMFile(char *fileName);
private:
int width, height; // size of bitmap
int rowSize; // size of one row of data, in bytes
SplashColorMode mode; // color mode
SplashColorPtr data;
friend class Splash;
};
#endif

270
splash/SplashClip.cc Normal file
View file

@ -0,0 +1,270 @@
//========================================================================
//
// SplashClip.cc
//
//========================================================================
#include <aconf.h>
#ifdef USE_GCC_PRAGMAS
#pragma implementation
#endif
#include <stdlib.h>
#include <string.h>
#include "gmem.h"
#include "SplashErrorCodes.h"
#include "SplashMath.h"
#include "SplashPath.h"
#include "SplashXPath.h"
#include "SplashXPathScanner.h"
#include "SplashClip.h"
//------------------------------------------------------------------------
// SplashClip.flags
//------------------------------------------------------------------------
#define splashClipEO 0x01 // use even-odd rule
//------------------------------------------------------------------------
// SplashClip
//------------------------------------------------------------------------
SplashClip::SplashClip(SplashCoord x0, SplashCoord y0,
SplashCoord x1, SplashCoord y1) {
if (x0 < x1) {
xMin = splashFloor(x0);
xMax = splashFloor(x1);
} else {
xMin = splashFloor(x1);
xMax = splashFloor(x0);
}
if (y0 < y1) {
yMin = splashFloor(y0);
yMax = splashFloor(y1);
} else {
yMin = splashFloor(y1);
yMax = splashFloor(y0);
}
paths = NULL;
flags = NULL;
scanners = NULL;
length = size = 0;
}
SplashClip::SplashClip(SplashClip *clip) {
int i;
xMin = clip->xMin;
yMin = clip->yMin;
xMax = clip->xMax;
yMax = clip->yMax;
length = clip->length;
size = clip->size;
paths = (SplashXPath **)gmalloc(size * sizeof(SplashXPath *));
flags = (Guchar *)gmalloc(size * sizeof(Guchar));
scanners = (SplashXPathScanner **)
gmalloc(size * sizeof(SplashXPathScanner *));
for (i = 0; i < length; ++i) {
paths[i] = clip->paths[i]->copy();
flags[i] = clip->flags[i];
scanners[i] = new SplashXPathScanner(paths[i], flags[i] & splashClipEO);
}
}
SplashClip::~SplashClip() {
int i;
for (i = 0; i < length; ++i) {
delete paths[i];
delete scanners[i];
}
gfree(paths);
gfree(flags);
gfree(scanners);
}
void SplashClip::grow(int nPaths) {
if (length + nPaths > size) {
if (size == 0) {
size = 32;
}
while (size < length + nPaths) {
size *= 2;
}
paths = (SplashXPath **)grealloc(paths, size * sizeof(SplashXPath *));
flags = (Guchar *)grealloc(flags, size * sizeof(Guchar));
scanners = (SplashXPathScanner **)
grealloc(scanners, size * sizeof(SplashXPathScanner *));
}
}
void SplashClip::resetToRect(SplashCoord x0, SplashCoord y0,
SplashCoord x1, SplashCoord y1) {
int i;
for (i = 0; i < length; ++i) {
delete paths[i];
delete scanners[i];
}
gfree(paths);
gfree(flags);
gfree(scanners);
paths = NULL;
flags = NULL;
scanners = NULL;
length = size = 0;
if (x0 < x1) {
xMin = splashFloor(x0);
xMax = splashFloor(x1);
} else {
xMin = splashFloor(x1);
xMax = splashFloor(x0);
}
if (y0 < y1) {
yMin = splashFloor(y0);
yMax = splashFloor(y1);
} else {
yMin = splashFloor(y1);
yMax = splashFloor(y0);
}
}
SplashError SplashClip::clipToRect(SplashCoord x0, SplashCoord y0,
SplashCoord x1, SplashCoord y1) {
int x0I, y0I, x1I, y1I;
if (x0 < x1) {
x0I = splashFloor(x0);
x1I = splashFloor(x1);
} else {
x0I = splashFloor(x1);
x1I = splashFloor(x0);
}
if (x0I > xMin) {
xMin = x0I;
}
if (x1I < xMax) {
xMax = x1I;
}
if (y0 < y1) {
y0I = splashFloor(y0);
y1I = splashFloor(y1);
} else {
y0I = splashFloor(y1);
y1I = splashFloor(y0);
}
if (y0I > yMin) {
yMin = y0I;
}
if (y1I < yMax) {
yMax = y1I;
}
return splashOk;
}
SplashError SplashClip::clipToPath(SplashPath *path, SplashCoord flatness,
GBool eo) {
SplashXPath *xPath;
xPath = new SplashXPath(path, flatness, gTrue);
// check for an empty path
if (xPath->length == 0) {
xMax = xMin - 1;
yMax = yMin - 1;
delete xPath;
// check for a rectangle
} else if (xPath->length == 4 &&
((xPath->segs[0].x0 == xPath->segs[0].x1 &&
xPath->segs[0].x0 == xPath->segs[1].x0 &&
xPath->segs[0].x0 == xPath->segs[3].x1 &&
xPath->segs[2].x0 == xPath->segs[2].x1 &&
xPath->segs[2].x0 == xPath->segs[1].x1 &&
xPath->segs[2].x0 == xPath->segs[3].x0 &&
xPath->segs[1].y0 == xPath->segs[1].y1 &&
xPath->segs[1].y0 == xPath->segs[0].y1 &&
xPath->segs[1].y0 == xPath->segs[2].y0 &&
xPath->segs[3].y0 == xPath->segs[3].y1 &&
xPath->segs[3].y0 == xPath->segs[0].y0 &&
xPath->segs[3].y0 == xPath->segs[2].y1) ||
(xPath->segs[0].y0 == xPath->segs[0].y1 &&
xPath->segs[0].y0 == xPath->segs[1].y0 &&
xPath->segs[0].y0 == xPath->segs[3].y1 &&
xPath->segs[2].y0 == xPath->segs[2].y1 &&
xPath->segs[2].y0 == xPath->segs[1].y1 &&
xPath->segs[2].y0 == xPath->segs[3].y0 &&
xPath->segs[1].x0 == xPath->segs[1].x1 &&
xPath->segs[1].x0 == xPath->segs[0].x1 &&
xPath->segs[1].x0 == xPath->segs[2].x0 &&
xPath->segs[3].x0 == xPath->segs[3].x1 &&
xPath->segs[3].x0 == xPath->segs[0].x0 &&
xPath->segs[3].x0 == xPath->segs[2].x1))) {
clipToRect(xPath->segs[0].x0, xPath->segs[0].y0,
xPath->segs[2].x0, xPath->segs[2].y0);
delete xPath;
} else {
grow(1);
xPath->sort();
paths[length] = xPath;
flags[length] = eo ? splashClipEO : 0;
scanners[length] = new SplashXPathScanner(xPath, eo);
++length;
}
return splashOk;
}
GBool SplashClip::test(int x, int y) {
int i;
// check the rectangle
if (x < xMin || x > xMax || y < yMin || y > yMax) {
return gFalse;
}
// check the paths
for (i = 0; i < length; ++i) {
if (!scanners[i]->test(x, y)) {
return gFalse;
}
}
return gTrue;
}
SplashClipResult SplashClip::testRect(int rectXMin, int rectYMin,
int rectXMax, int rectYMax) {
if (rectXMax < xMin || rectXMin > xMax ||
rectYMax < yMin || rectYMin > yMax) {
return splashClipAllOutside;
}
if (rectXMin >= xMin && rectXMax <= xMax &&
rectYMin >= yMin && rectYMax <= yMax &&
length == 0) {
return splashClipAllInside;
}
return splashClipPartial;
}
SplashClipResult SplashClip::testSpan(int spanXMin, int spanXMax, int spanY) {
int i;
if (spanXMax < xMin || spanXMin > xMax ||
spanY < yMin || spanY > yMax) {
return splashClipAllOutside;
}
if (!(spanXMin >= xMin && spanXMax <= xMax &&
spanY >= yMin && spanY <= yMax)) {
return splashClipPartial;
}
for (i = 0; i < length; ++i) {
if (!scanners[i]->testSpan(xMin, xMax, spanY)) {
return splashClipPartial;
}
}
return splashClipAllInside;
}

88
splash/SplashClip.h Normal file
View file

@ -0,0 +1,88 @@
//========================================================================
//
// SplashClip.h
//
//========================================================================
#ifndef SPLASHCLIP_H
#define SPLASHCLIP_H
#include <aconf.h>
#ifdef USE_GCC_PRAGMAS
#pragma interface
#endif
#include "SplashTypes.h"
class SplashPath;
class SplashXPath;
class SplashXPathScanner;
//------------------------------------------------------------------------
enum SplashClipResult {
splashClipAllInside,
splashClipAllOutside,
splashClipPartial
};
//------------------------------------------------------------------------
// SplashClip
//------------------------------------------------------------------------
class SplashClip {
public:
// Create a clip, for the given rectangle.
SplashClip(SplashCoord x0, SplashCoord y0,
SplashCoord x1, SplashCoord y1);
// Copy a clip.
SplashClip *copy() { return new SplashClip(this); }
~SplashClip();
// Reset the clip to a rectangle.
void resetToRect(SplashCoord x0, SplashCoord y0,
SplashCoord x1, SplashCoord y1);
// Intersect the clip with a rectangle.
SplashError clipToRect(SplashCoord x0, SplashCoord y0,
SplashCoord x1, SplashCoord y1);
// Interesect the clip with <path>.
SplashError clipToPath(SplashPath *path, SplashCoord flatness,
GBool eo);
// Returns true if (<x>,<y>) is inside the clip.
GBool test(int x, int y);
// Tests a rectangle against the clipping region. Returns one of:
// - splashClipAllInside if the entire rectangle is inside the
// clipping region, i.e., all pixels in the rectangle are
// visible
// - splashClipAllOutside if the entire rectangle is outside the
// clipping region, i.e., all the pixels in the rectangle are
// clipped
// - splashClipPartial if the rectangle is part inside and part
// outside the clipping region
SplashClipResult testRect(int rectXMin, int rectYMin,
int rectXMax, int rectYMax);
// Similar to testRect, but tests a horizontal span.
SplashClipResult testSpan(int spanXMin, int spanXMax, int spanY);
private:
SplashClip(SplashClip *clip);
void grow(int nPaths);
int xMin, yMin, xMax, yMax;
SplashXPath **paths;
Guchar *flags;
SplashXPathScanner **scanners;
int length, size;
};
#endif

32
splash/SplashErrorCodes.h Normal file
View file

@ -0,0 +1,32 @@
//========================================================================
//
// SplashErrorCodes.h
//
//========================================================================
#ifndef SPLASHERRORCODES_H
#define SPLASHERRORCODES_H
#include <aconf.h>
//------------------------------------------------------------------------
#define splashOk 0 // no error
#define splashErrNoCurPt 1 // no current point
#define splashErrEmptyPath 2 // zero points in path
#define splashErrBogusPath 3 // only one point in subpath
#define splashErrNoSave 4 // state stack is empty
#define splashErrOpenFile 5 // couldn't open file
#define splashErrNoGlyph 6 // couldn't get the requested glyph
#define splashErrModeMismatch 7 // invalid combination of color modes
#define splashErrSingularMatrix 8 // matrix is singular
#endif

288
splash/SplashFTFont.cc Normal file
View file

@ -0,0 +1,288 @@
//========================================================================
//
// SplashFTFont.cc
//
//========================================================================
#include <aconf.h>
#if HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H
#ifdef USE_GCC_PRAGMAS
#pragma implementation
#endif
#include "freetype/ftoutln.h"
#include "freetype/internal/ftobjs.h" // needed for FT_New_Size decl
#include "gmem.h"
#include "SplashMath.h"
#include "SplashGlyphBitmap.h"
#include "SplashPath.h"
#include "SplashFTFontEngine.h"
#include "SplashFTFontFile.h"
#include "SplashFTFont.h"
//------------------------------------------------------------------------
static int glyphPathMoveTo(FT_Vector *pt, void *path);
static int glyphPathLineTo(FT_Vector *pt, void *path);
static int glyphPathConicTo(FT_Vector *ctrl, FT_Vector *pt, void *path);
static int glyphPathCubicTo(FT_Vector *ctrl1, FT_Vector *ctrl2,
FT_Vector *pt, void *path);
//------------------------------------------------------------------------
// SplashFTFont
//------------------------------------------------------------------------
SplashFTFont::SplashFTFont(SplashFTFontFile *fontFileA, SplashCoord *matA):
SplashFont(fontFileA, matA, fontFileA->engine->aa)
{
FT_Face face;
SplashCoord size, div;
int x, y;
face = fontFileA->face;
if (FT_New_Size(face, &sizeObj)) {
return;
}
face->size = sizeObj;
size = splashSqrt(mat[2]*mat[2] + mat[3]*mat[3]);
if (FT_Set_Pixel_Sizes(face, 0, (int)size)) {
return;
}
div = face->bbox.xMax > 20000 ? 65536 : 1;
// transform the four corners of the font bounding box -- the min
// and max values form the bounding box of the transformed font
x = (int)((mat[0] * face->bbox.xMin + mat[2] * face->bbox.yMin) /
(div * face->units_per_EM));
xMin = xMax = x;
y = (int)((mat[1] * face->bbox.xMin + mat[3] * face->bbox.yMin) /
(div * face->units_per_EM));
yMin = yMax = y;
x = (int)((mat[0] * face->bbox.xMin + mat[2] * face->bbox.yMax) /
(div * face->units_per_EM));
if (x < xMin) {
xMin = x;
} else if (x > xMax) {
xMax = x;
}
y = (int)((mat[1] * face->bbox.xMin + mat[3] * face->bbox.yMax) /
(div * face->units_per_EM));
if (y < yMin) {
yMin = y;
} else if (y > yMax) {
yMax = y;
}
x = (int)((mat[0] * face->bbox.xMax + mat[2] * face->bbox.yMin) /
(div * face->units_per_EM));
if (x < xMin) {
xMin = x;
} else if (x > xMax) {
xMax = x;
}
y = (int)((mat[1] * face->bbox.xMax + mat[3] * face->bbox.yMin) /
(div * face->units_per_EM));
if (y < yMin) {
yMin = y;
} else if (y > yMax) {
yMax = y;
}
x = (int)((mat[0] * face->bbox.xMax + mat[2] * face->bbox.yMax) /
(div * face->units_per_EM));
if (x < xMin) {
xMin = x;
} else if (x > xMax) {
xMax = x;
}
y = (int)((mat[1] * face->bbox.xMax + mat[3] * face->bbox.yMax) /
(div * face->units_per_EM));
if (y < yMin) {
yMin = y;
} else if (y > yMax) {
yMax = y;
}
// This is a kludge: some buggy PDF generators embed fonts with
// zero bounding boxes.
if (xMax == xMin) {
xMin = 0;
xMax = (int)size;
}
if (yMax == yMin) {
yMin = 0;
yMax = (int)(1.2 * size);
}
// compute the transform matrix
matrix.xx = (FT_Fixed)((mat[0] / size) * 65536);
matrix.yx = (FT_Fixed)((mat[1] / size) * 65536);
matrix.xy = (FT_Fixed)((mat[2] / size) * 65536);
matrix.yy = (FT_Fixed)((mat[3] / size) * 65536);
}
SplashFTFont::~SplashFTFont() {
}
GBool SplashFTFont::getGlyph(int c, int xFrac, int yFrac,
SplashGlyphBitmap *bitmap) {
return SplashFont::getGlyph(c, xFrac, 0, bitmap);
}
GBool SplashFTFont::makeGlyph(int c, int xFrac, int yFrac,
SplashGlyphBitmap *bitmap) {
SplashFTFontFile *ff;
FT_Vector offset;
FT_GlyphSlot slot;
FT_UInt gid;
int rowSize;
Guchar *p, *q;
int i;
ff = (SplashFTFontFile *)fontFile;
ff->face->size = sizeObj;
offset.x = (FT_Pos)(xFrac * splashFontFractionMul * 64);
offset.y = 0;
FT_Set_Transform(ff->face, &matrix, &offset);
slot = ff->face->glyph;
if (ff->codeToGID && c < ff->codeToGIDLen) {
gid = (FT_UInt)ff->codeToGID[c];
} else {
gid = (FT_UInt)c;
}
// if we have the FT2 bytecode interpreter, autohinting won't be used
#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
if (FT_Load_Glyph(ff->face, gid,
aa ? FT_LOAD_NO_BITMAP : FT_LOAD_DEFAULT)) {
return gFalse;
}
#else
// FT2's autohinting doesn't always work very well (especially with
// font subsets), so turn it off if anti-aliasing is enabled; if
// anti-aliasing is disabled, this seems to be a tossup - some fonts
// look better with hinting, some without, so leave hinting on
if (FT_Load_Glyph(ff->face, gid,
aa ? FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP
: FT_LOAD_DEFAULT)) {
return gFalse;
}
#endif
if (FT_Render_Glyph(slot, aa ? ft_render_mode_normal
: ft_render_mode_mono)) {
return gFalse;
}
bitmap->x = -slot->bitmap_left;
bitmap->y = slot->bitmap_top;
bitmap->w = slot->bitmap.width;
bitmap->h = slot->bitmap.rows;
bitmap->aa = aa;
if (aa) {
rowSize = bitmap->w;
} else {
rowSize = (bitmap->w + 7) >> 3;
}
bitmap->data = (Guchar *)gmalloc(rowSize * bitmap->h);
bitmap->freeData = gTrue;
for (i = 0, p = bitmap->data, q = slot->bitmap.buffer;
i < bitmap->h;
++i, p += rowSize, q += slot->bitmap.pitch) {
memcpy(p, q, rowSize);
}
return gTrue;
}
SplashPath *SplashFTFont::getGlyphPath(int c) {
static FT_Outline_Funcs outlineFuncs = {
&glyphPathMoveTo,
&glyphPathLineTo,
&glyphPathConicTo,
&glyphPathCubicTo,
0, 0
};
SplashFTFontFile *ff;
SplashPath *path;
FT_GlyphSlot slot;
FT_UInt gid;
FT_Glyph glyph;
ff = (SplashFTFontFile *)fontFile;
ff->face->size = sizeObj;
FT_Set_Transform(ff->face, &matrix, NULL);
slot = ff->face->glyph;
if (ff->codeToGID && c < ff->codeToGIDLen) {
gid = ff->codeToGID[c];
} else {
gid = (FT_UInt)c;
}
if (FT_Load_Glyph(ff->face, gid, FT_LOAD_DEFAULT)) {
return NULL;
}
if (FT_Get_Glyph(slot, &glyph)) {
return NULL;
}
path = new SplashPath();
FT_Outline_Decompose(&((FT_OutlineGlyph)glyph)->outline,
&outlineFuncs, path);
return path;
}
static int glyphPathMoveTo(FT_Vector *pt, void *path) {
((SplashPath *)path)->moveTo(pt->x / 64.0, -pt->y / 64.0);
return 0;
}
static int glyphPathLineTo(FT_Vector *pt, void *path) {
((SplashPath *)path)->lineTo(pt->x / 64.0, -pt->y / 64.0);
return 0;
}
static int glyphPathConicTo(FT_Vector *ctrl, FT_Vector *pt, void *path) {
SplashCoord x0, y0, x1, y1, x2, y2, x3, y3, xc, yc;
if (!((SplashPath *)path)->getCurPt(&x0, &y0)) {
return 0;
}
xc = ctrl->x / 64.0;
yc = -ctrl->y / 64.0;
x3 = pt->x / 64.0;
y3 = -pt->y / 64.0;
// A second-order Bezier curve is defined by two endpoints, p0 and
// p3, and one control point, pc:
//
// p(t) = (1-t)^2*p0 + t*(1-t)*pc + t^2*p3
//
// A third-order Bezier curve is defined by the same two endpoints,
// p0 and p3, and two control points, p1 and p2:
//
// p(t) = (1-t)^3*p0 + 3t*(1-t)^2*p1 + 3t^2*(1-t)*p2 + t^3*p3
//
// Applying some algebra, we can convert a second-order curve to a
// third-order curve:
//
// p1 = (1/3) * (p0 + 2pc)
// p2 = (1/3) * (2pc + p3)
x1 = (1.0 / 3.0) * (x0 + 2 * xc);
y1 = (1.0 / 3.0) * (y0 + 2 * yc);
x2 = (1.0 / 3.0) * (2 * xc + x3);
y2 = (1.0 / 3.0) * (2 * yc + y3);
((SplashPath *)path)->curveTo(x1, y1, x2, y2, x3, y3);
return 0;
}
static int glyphPathCubicTo(FT_Vector *ctrl1, FT_Vector *ctrl2,
FT_Vector *pt, void *path) {
((SplashPath *)path)->curveTo(ctrl1->x / 64.0, -ctrl1->y / 64.0,
ctrl2->x / 64.0, -ctrl2->y / 64.0,
pt->x / 64.0, -pt->y / 64.0);
return 0;
}
#endif // HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H

54
splash/SplashFTFont.h Normal file
View file

@ -0,0 +1,54 @@
//========================================================================
//
// SplashFTFont.h
//
//========================================================================
#ifndef SPLASHFTFONT_H
#define SPLASHFTFONT_H
#include <aconf.h>
#if HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H
#ifdef USE_GCC_PRAGMAS
#pragma interface
#endif
#include <freetype/freetype.h>
#include "SplashFont.h"
class SplashFTFontFile;
//------------------------------------------------------------------------
// SplashFTFont
//------------------------------------------------------------------------
class SplashFTFont: public SplashFont {
public:
SplashFTFont(SplashFTFontFile *fontFileA, SplashCoord *matA);
virtual ~SplashFTFont();
// Munge xFrac and yFrac before calling SplashFont::getGlyph.
virtual GBool getGlyph(int c, int xFrac, int yFrac,
SplashGlyphBitmap *bitmap);
// Rasterize a glyph. The <xFrac> and <yFrac> values are the same
// as described for getGlyph.
virtual GBool makeGlyph(int c, int xFrac, int yFrac,
SplashGlyphBitmap *bitmap);
// Return the path for a glyph.
virtual SplashPath *getGlyphPath(int c);
private:
FT_Size sizeObj;
FT_Matrix matrix;
};
#endif // HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H
#endif

View file

@ -0,0 +1,133 @@
//========================================================================
//
// SplashFTFontEngine.cc
//
//========================================================================
#include <aconf.h>
#if HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H
#ifdef USE_GCC_PRAGMAS
#pragma implementation
#endif
#include <stdio.h>
#ifndef WIN32
# include <unistd.h>
#endif
#include "gmem.h"
#include "GString.h"
#include "gfile.h"
#include "FoFiTrueType.h"
#include "FoFiType1C.h"
#include "SplashFTFontFile.h"
#include "SplashFTFontEngine.h"
#ifdef VMS
#if (__VMS_VER < 70000000)
extern "C" int unlink(char *filename);
#endif
#endif
//------------------------------------------------------------------------
static void fileWrite(void *stream, const char *data, int len) {
fwrite(data, 1, len, (FILE *)stream);
}
//------------------------------------------------------------------------
// SplashFTFontEngine
//------------------------------------------------------------------------
SplashFTFontEngine::SplashFTFontEngine(GBool aaA, FT_Library libA) {
aa = aaA;
lib = libA;
}
SplashFTFontEngine *SplashFTFontEngine::init(GBool aaA) {
FT_Library libA;
if (FT_Init_FreeType(&libA)) {
return NULL;
}
return new SplashFTFontEngine(aaA, libA);
}
SplashFTFontEngine::~SplashFTFontEngine() {
FT_Done_FreeType(lib);
}
SplashFontFile *SplashFTFontEngine::loadType1Font(SplashFontFileID *idA,
char *fileName,
GBool deleteFile,
const char **enc) {
return SplashFTFontFile::loadType1Font(this, idA, fileName, deleteFile, enc);
}
SplashFontFile *SplashFTFontEngine::loadType1CFont(SplashFontFileID *idA,
char *fileName,
GBool deleteFile,
const char **enc) {
return SplashFTFontFile::loadType1Font(this, idA, fileName, deleteFile, enc);
}
SplashFontFile *SplashFTFontEngine::loadCIDFont(SplashFontFileID *idA,
char *fileName,
GBool deleteFile) {
FoFiType1C *ff;
Gushort *cidToGIDMap;
int nCIDs;
SplashFontFile *ret;
// check for a CFF font
if ((ff = FoFiType1C::load(fileName))) {
cidToGIDMap = ff->getCIDToGIDMap(&nCIDs);
delete ff;
} else {
cidToGIDMap = NULL;
nCIDs = 0;
}
ret = SplashFTFontFile::loadCIDFont(this, idA, fileName, deleteFile,
cidToGIDMap, nCIDs);
if (!ret) {
gfree(cidToGIDMap);
}
return ret;
}
SplashFontFile *SplashFTFontEngine::loadTrueTypeFont(SplashFontFileID *idA,
char *fileName,
GBool deleteFile,
Gushort *codeToGID,
int codeToGIDLen) {
FoFiTrueType *ff;
GString *tmpFileName;
FILE *tmpFile;
SplashFontFile *ret;
if (!(ff = FoFiTrueType::load(fileName))) {
return NULL;
}
tmpFileName = NULL;
if (!openTempFile(&tmpFileName, &tmpFile, "wb", NULL)) {
delete ff;
return NULL;
}
ff->writeTTF(&fileWrite, tmpFile);
delete ff;
fclose(tmpFile);
ret = SplashFTFontFile::loadTrueTypeFont(this, idA,
tmpFileName->getCString(),
gTrue, codeToGID, codeToGIDLen);
if (ret) {
if (deleteFile) {
unlink(fileName);
}
} else {
unlink(tmpFileName->getCString());
}
delete tmpFileName;
return ret;
}
#endif // HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H

View file

@ -0,0 +1,60 @@
//========================================================================
//
// SplashFTFontEngine.h
//
//========================================================================
#ifndef SPLASHFTFONTENGINE_H
#define SPLASHFTFONTENGINE_H
#include <aconf.h>
#if HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H
#ifdef USE_GCC_PRAGMAS
#pragma interface
#endif
#include <ft2build.h>
#include FT_FREETYPE_H
#include "gtypes.h"
class SplashFontFile;
class SplashFontFileID;
//------------------------------------------------------------------------
// SplashFTFontEngine
//------------------------------------------------------------------------
class SplashFTFontEngine {
public:
static SplashFTFontEngine *init(GBool aaA);
~SplashFTFontEngine();
// Load fonts.
SplashFontFile *loadType1Font(SplashFontFileID *idA, char *fileName,
GBool deleteFile, const char **enc);
SplashFontFile *loadType1CFont(SplashFontFileID *idA, char *fileName,
GBool deleteFile, const char **enc);
SplashFontFile *loadCIDFont(SplashFontFileID *idA, char *fileName,
GBool deleteFile);
SplashFontFile *loadTrueTypeFont(SplashFontFileID *idA, char *fileName,
GBool deleteFile,
Gushort *codeToGID, int codeToGIDLen);
private:
SplashFTFontEngine(GBool aaA, FT_Library libA);
GBool aa;
FT_Library lib;
friend class SplashFTFontFile;
friend class SplashFTFont;
};
#endif // HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H
#endif

111
splash/SplashFTFontFile.cc Normal file
View file

@ -0,0 +1,111 @@
//========================================================================
//
// SplashFTFontFile.cc
//
//========================================================================
#include <aconf.h>
#if HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H
#ifdef USE_GCC_PRAGMAS
#pragma implementation
#endif
#include "gmem.h"
#include "SplashFTFontEngine.h"
#include "SplashFTFont.h"
#include "SplashFTFontFile.h"
//------------------------------------------------------------------------
// SplashFTFontFile
//------------------------------------------------------------------------
SplashFontFile *SplashFTFontFile::loadType1Font(SplashFTFontEngine *engineA,
SplashFontFileID *idA,
char *fileNameA,
GBool deleteFileA,
const char **encA) {
FT_Face faceA;
Gushort *codeToGIDA;
const char *name;
int i;
if (FT_New_Face(engineA->lib, fileNameA, 0, &faceA)) {
return NULL;
}
codeToGIDA = (Gushort *)gmalloc(256 * sizeof(int));
for (i = 0; i < 256; ++i) {
codeToGIDA[i] = 0;
if ((name = encA[i])) {
codeToGIDA[i] = (Gushort)FT_Get_Name_Index(faceA, (char*)name);
}
}
return new SplashFTFontFile(engineA, idA, fileNameA, deleteFileA,
faceA, codeToGIDA, 256);
}
SplashFontFile *SplashFTFontFile::loadCIDFont(SplashFTFontEngine *engineA,
SplashFontFileID *idA,
char *fileNameA,
GBool deleteFileA,
Gushort *codeToGIDA,
int codeToGIDLenA) {
FT_Face faceA;
if (FT_New_Face(engineA->lib, fileNameA, 0, &faceA)) {
return NULL;
}
return new SplashFTFontFile(engineA, idA, fileNameA, deleteFileA,
faceA, codeToGIDA, codeToGIDLenA);
}
SplashFontFile *SplashFTFontFile::loadTrueTypeFont(SplashFTFontEngine *engineA,
SplashFontFileID *idA,
char *fileNameA,
GBool deleteFileA,
Gushort *codeToGIDA,
int codeToGIDLenA) {
FT_Face faceA;
if (FT_New_Face(engineA->lib, fileNameA, 0, &faceA)) {
return NULL;
}
return new SplashFTFontFile(engineA, idA, fileNameA, deleteFileA,
faceA, codeToGIDA, codeToGIDLenA);
}
SplashFTFontFile::SplashFTFontFile(SplashFTFontEngine *engineA,
SplashFontFileID *idA,
char *fileNameA, GBool deleteFileA,
FT_Face faceA,
Gushort *codeToGIDA, int codeToGIDLenA):
SplashFontFile(idA, fileNameA, deleteFileA)
{
engine = engineA;
face = faceA;
codeToGID = codeToGIDA;
codeToGIDLen = codeToGIDLenA;
}
SplashFTFontFile::~SplashFTFontFile() {
if (face) {
FT_Done_Face(face);
}
if (codeToGID) {
gfree(codeToGID);
}
}
SplashFont *SplashFTFontFile::makeFont(SplashCoord *mat) {
SplashFont *font;
font = new SplashFTFont(this, mat);
font->initCache();
return font;
}
#endif // HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H

70
splash/SplashFTFontFile.h Normal file
View file

@ -0,0 +1,70 @@
//========================================================================
//
// SplashFTFontFile.h
//
//========================================================================
#ifndef SPLASHFTFONTFILE_H
#define SPLASHFTFONTFILE_H
#include <aconf.h>
#if HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H
#ifdef USE_GCC_PRAGMAS
#pragma interface
#endif
#include <ft2build.h>
#include FT_FREETYPE_H
#include "SplashFontFile.h"
class SplashFontFileID;
class SplashFTFontEngine;
//------------------------------------------------------------------------
// SplashFTFontFile
//------------------------------------------------------------------------
class SplashFTFontFile: public SplashFontFile {
public:
static SplashFontFile *loadType1Font(SplashFTFontEngine *engineA,
SplashFontFileID *idA, char *fileNameA,
GBool deleteFileA, const char **encA);
static SplashFontFile *loadCIDFont(SplashFTFontEngine *engineA,
SplashFontFileID *idA, char *fileNameA,
GBool deleteFileA,
Gushort *codeToCIDA, int codeToGIDLenA);
static SplashFontFile *loadTrueTypeFont(SplashFTFontEngine *engineA,
SplashFontFileID *idA,
char *fileNameA,
GBool deleteFileA,
Gushort *codeToGIDA,
int codeToGIDLenA);
virtual ~SplashFTFontFile();
// Create a new SplashFTFont, i.e., a scaled instance of this font
// file.
virtual SplashFont *makeFont(SplashCoord *mat);
private:
SplashFTFontFile(SplashFTFontEngine *engineA,
SplashFontFileID *idA,
char *fileNameA, GBool deleteFileA,
FT_Face faceA,
Gushort *codeToGIDA, int codeToGIDLenA);
SplashFTFontEngine *engine;
FT_Face face;
Gushort *codeToGID;
int codeToGIDLen;
friend class SplashFTFont;
};
#endif // HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H
#endif

166
splash/SplashFont.cc Normal file
View file

@ -0,0 +1,166 @@
//========================================================================
//
// SplashFont.cc
//
//========================================================================
#include <aconf.h>
#ifdef USE_GCC_PRAGMAS
#pragma implementation
#endif
#include <string.h>
#include "gmem.h"
#include "SplashMath.h"
#include "SplashGlyphBitmap.h"
#include "SplashFontFile.h"
#include "SplashFont.h"
//------------------------------------------------------------------------
struct SplashFontCacheTag {
int c;
short xFrac, yFrac; // x and y fractions
int mru; // valid bit (0x80000000) and MRU index
int x, y, w, h; // offset and size of glyph
};
//------------------------------------------------------------------------
// SplashFont
//------------------------------------------------------------------------
SplashFont::SplashFont(SplashFontFile *fontFileA, SplashCoord *matA,
GBool aaA) {
fontFile = fontFileA;
fontFile->incRefCnt();
mat[0] = matA[0];
mat[1] = matA[1];
mat[2] = matA[2];
mat[3] = matA[3];
aa = aaA;
cache = NULL;
cacheTags = NULL;
xMin = yMin = xMax = yMax = 0;
}
void SplashFont::initCache() {
int i;
// this should be (max - min + 1), but we add some padding to
// deal with rounding errors
glyphW = xMax - xMin + 3;
glyphH = yMax - yMin + 3;
if (aa) {
glyphSize = glyphW * glyphH;
} else {
glyphSize = ((glyphW + 7) >> 3) * glyphH;
}
// set up the glyph pixmap cache
cacheAssoc = 8;
if (glyphSize <= 256) {
cacheSets = 8;
} else if (glyphSize <= 512) {
cacheSets = 4;
} else if (glyphSize <= 1024) {
cacheSets = 2;
} else {
cacheSets = 1;
}
cache = (Guchar *)gmalloc(cacheSets * cacheAssoc * glyphSize);
cacheTags = (SplashFontCacheTag *)gmalloc(cacheSets * cacheAssoc *
sizeof(SplashFontCacheTag));
for (i = 0; i < cacheSets * cacheAssoc; ++i) {
cacheTags[i].mru = i & (cacheAssoc - 1);
}
}
SplashFont::~SplashFont() {
fontFile->decRefCnt();
if (cache) {
gfree(cache);
}
if (cacheTags) {
gfree(cacheTags);
}
}
GBool SplashFont::getGlyph(int c, int xFrac, int yFrac,
SplashGlyphBitmap *bitmap) {
SplashGlyphBitmap bitmap2;
int size;
Guchar *p;
int i, j, k;
// check the cache
i = (c & (cacheSets - 1)) * cacheAssoc;
for (j = 0; j < cacheAssoc; ++j) {
if ((cacheTags[i+j].mru & 0x80000000) &&
cacheTags[i+j].c == c &&
(int)cacheTags[i+j].xFrac == xFrac &&
(int)cacheTags[i+j].yFrac == yFrac) {
bitmap->x = cacheTags[i+j].x;
bitmap->y = cacheTags[i+j].y;
bitmap->w = cacheTags[i+j].w;
bitmap->h = cacheTags[i+j].h;
for (k = 0; k < cacheAssoc; ++k) {
if (k != j &&
(cacheTags[i+k].mru & 0x7fffffff) <
(cacheTags[i+j].mru & 0x7fffffff)) {
++cacheTags[i+k].mru;
}
}
cacheTags[i+j].mru = 0x80000000;
bitmap->aa = aa;
bitmap->data = cache + (i+j) * glyphSize;
bitmap->freeData = gFalse;
return gTrue;
}
}
// generate the glyph bitmap
if (!makeGlyph(c, xFrac, yFrac, &bitmap2)) {
return gFalse;
}
// if the glyph doesn't fit in the bounding box, return a temporary
// uncached bitmap
if (bitmap2.w > glyphW || bitmap2.h > glyphH) {
*bitmap = bitmap2;
return gTrue;
}
// insert glyph pixmap in cache
if (aa) {
size = bitmap2.w * bitmap2.h;
} else {
size = ((bitmap2.w + 7) >> 3) * bitmap2.h;
}
p = NULL; // make gcc happy
for (j = 0; j < cacheAssoc; ++j) {
if ((cacheTags[i+j].mru & 0x7fffffff) == cacheAssoc - 1) {
cacheTags[i+j].mru = 0x80000000;
cacheTags[i+j].c = c;
cacheTags[i+j].xFrac = (short)xFrac;
cacheTags[i+j].yFrac = (short)yFrac;
cacheTags[i+j].x = bitmap2.x;
cacheTags[i+j].y = bitmap2.y;
cacheTags[i+j].w = bitmap2.w;
cacheTags[i+j].h = bitmap2.h;
p = cache + (i+j) * glyphSize;
memcpy(p, bitmap2.data, size);
} else {
++cacheTags[i+j].mru;
}
}
*bitmap = bitmap2;
bitmap->data = p;
bitmap->freeData = gFalse;
if (bitmap2.freeData) {
gfree(bitmap2.data);
}
return gTrue;
}

89
splash/SplashFont.h Normal file
View file

@ -0,0 +1,89 @@
//========================================================================
//
// SplashFont.h
//
//========================================================================
#ifndef SPLASHFONT_H
#define SPLASHFONT_H
#include <aconf.h>
#ifdef USE_GCC_PRAGMAS
#pragma interface
#endif
#include "gtypes.h"
#include "SplashTypes.h"
struct SplashGlyphBitmap;
struct SplashFontCacheTag;
class SplashFontFile;
class SplashPath;
//------------------------------------------------------------------------
// Fractional positioning uses this many bits to the right of the
// decimal points.
#define splashFontFractionBits 2
#define splashFontFraction (1 << splashFontFractionBits)
#define splashFontFractionMul (1 / (SplashCoord)splashFontFraction)
//------------------------------------------------------------------------
// SplashFont
//------------------------------------------------------------------------
class SplashFont {
public:
SplashFont(SplashFontFile *fontFileA, SplashCoord *matA, GBool aaA);
// This must be called after the constructor, so that the subclass
// constructor has a chance to compute the bbox.
void initCache();
virtual ~SplashFont();
SplashFontFile *getFontFile() { return fontFile; }
// Return true if <this> matches the specified font file and matrix.
GBool matches(SplashFontFile *fontFileA, SplashCoord *matA) {
return fontFileA == fontFile &&
matA[0] == mat[0] && matA[1] == mat[1] &&
matA[2] == mat[2] && matA[3] == mat[3];
}
// Get a glyph - this does a cache lookup first, and if not found,
// creates a new bitmap and adds it to the cache. The <xFrac> and
// <yFrac> values are splashFontFractionBits bits each, representing
// the numerators of fractions in [0, 1), where the denominator is
// splashFontFraction = 1 << splashFontFractionBits. Subclasses
// should override this to zero out xFrac and/or yFrac if they don't
// support fractional coordinates.
virtual GBool getGlyph(int c, int xFrac, int yFrac,
SplashGlyphBitmap *bitmap);
// Rasterize a glyph. The <xFrac> and <yFrac> values are the same
// as described for getGlyph.
virtual GBool makeGlyph(int c, int xFrac, int yFrac,
SplashGlyphBitmap *bitmap) = 0;
// Return the path for a glyph.
virtual SplashPath *getGlyphPath(int c) = 0;
protected:
SplashFontFile *fontFile;
SplashCoord mat[4]; // font transform matrix
GBool aa; // anti-aliasing
int xMin, yMin, xMax, yMax; // glyph bounding box
Guchar *cache; // glyph bitmap cache
SplashFontCacheTag * // cache tags
cacheTags;
int glyphW, glyphH; // size of glyph bitmaps
int glyphSize; // size of glyph bitmaps, in bytes
int cacheSets; // number of sets in cache
int cacheAssoc; // cache associativity (glyphs per set)
};
#endif

245
splash/SplashFontEngine.cc Normal file
View file

@ -0,0 +1,245 @@
//========================================================================
//
// SplashFontEngine.cc
//
//========================================================================
#include <aconf.h>
#ifdef USE_GCC_PRAGMAS
#pragma implementation
#endif
#if HAVE_T1LIB_H
#include <t1lib.h>
#endif
#include <stdlib.h>
#include <stdio.h>
#ifndef WIN32
# include <unistd.h>
#endif
#include "gmem.h"
#include "GString.h"
#include "SplashT1FontEngine.h"
#include "SplashFTFontEngine.h"
#include "SplashFontFile.h"
#include "SplashFontFileID.h"
#include "SplashFont.h"
#include "SplashFontEngine.h"
#ifdef VMS
#if (__VMS_VER < 70000000)
extern "C" int unlink(char *filename);
#endif
#endif
//------------------------------------------------------------------------
// SplashFontEngine
//------------------------------------------------------------------------
SplashFontEngine::SplashFontEngine(
#if HAVE_T1LIB_H
GBool enableT1lib,
#endif
#if HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H
GBool enableFreeType,
#endif
GBool aa) {
int i;
for (i = 0; i < splashFontCacheSize; ++i) {
fontCache[i] = NULL;
}
#if HAVE_T1LIB_H
if (enableT1lib) {
t1Engine = SplashT1FontEngine::init(aa);
} else {
t1Engine = NULL;
}
#endif
#if HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H
if (enableFreeType) {
ftEngine = SplashFTFontEngine::init(aa);
} else {
ftEngine = NULL;
}
#endif
}
SplashFontEngine::~SplashFontEngine() {
int i;
for (i = 0; i < splashFontCacheSize; ++i) {
if (fontCache[i]) {
delete fontCache[i];
}
}
#if HAVE_T1LIB_H
if (t1Engine) {
delete t1Engine;
}
#endif
#if HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H
if (ftEngine) {
delete ftEngine;
}
#endif
}
SplashFontFile *SplashFontEngine::getFontFile(SplashFontFileID *id) {
SplashFontFile *fontFile;
int i;
for (i = 0; i < splashFontCacheSize; ++i) {
if (fontCache[i]) {
fontFile = fontCache[i]->getFontFile();
if (fontFile && fontFile->getID()->matches(id)) {
return fontFile;
}
}
}
return NULL;
}
SplashFontFile *SplashFontEngine::loadType1Font(SplashFontFileID *idA,
char *fileName,
GBool deleteFile, const char **enc) {
SplashFontFile *fontFile;
fontFile = NULL;
#if HAVE_T1LIB_H
if (!fontFile && t1Engine) {
fontFile = t1Engine->loadType1Font(idA, fileName, deleteFile, enc);
}
#endif
#if HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H
if (!fontFile && ftEngine) {
fontFile = ftEngine->loadType1Font(idA, fileName, deleteFile, enc);
}
#endif
// delete the (temporary) font file -- with Unix hard link
// semantics, this will remove the last link; otherwise it will
// return an error, leaving the file to be deleted later (if
// loadXYZFont failed, the file will always be deleted)
if (deleteFile) {
unlink(fontFile ? fontFile->fileName->getCString() : fileName);
}
return fontFile;
}
SplashFontFile *SplashFontEngine::loadType1CFont(SplashFontFileID *idA,
char *fileName,
GBool deleteFile,
const char **enc) {
SplashFontFile *fontFile;
fontFile = NULL;
#if HAVE_T1LIB_H
if (!fontFile && t1Engine) {
fontFile = t1Engine->loadType1CFont(idA, fileName, deleteFile, enc);
}
#endif
#if HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H
if (!fontFile && ftEngine) {
fontFile = ftEngine->loadType1CFont(idA, fileName, deleteFile, enc);
}
#endif
// delete the (temporary) font file -- with Unix hard link
// semantics, this will remove the last link; otherwise it will
// return an error, leaving the file to be deleted later (if
// loadXYZFont failed, the file will always be deleted)
if (deleteFile) {
unlink(fontFile ? fontFile->fileName->getCString() : fileName);
}
return fontFile;
}
SplashFontFile *SplashFontEngine::loadCIDFont(SplashFontFileID *idA,
char *fileName,
GBool deleteFile) {
SplashFontFile *fontFile;
fontFile = NULL;
#if HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H
if (!fontFile && ftEngine) {
fontFile = ftEngine->loadCIDFont(idA, fileName, deleteFile);
}
#endif
// delete the (temporary) font file -- with Unix hard link
// semantics, this will remove the last link; otherwise it will
// return an error, leaving the file to be deleted later (if
// loadXYZFont failed, the file will always be deleted)
if (deleteFile) {
unlink(fontFile ? fontFile->fileName->getCString() : fileName);
}
return fontFile;
}
SplashFontFile *SplashFontEngine::loadTrueTypeFont(SplashFontFileID *idA,
char *fileName,
GBool deleteFile,
Gushort *codeToGID,
int codeToGIDLen) {
SplashFontFile *fontFile;
fontFile = NULL;
#if HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H
if (!fontFile && ftEngine) {
fontFile = ftEngine->loadTrueTypeFont(idA, fileName, deleteFile,
codeToGID, codeToGIDLen);
}
#endif
if (!fontFile) {
gfree(codeToGID);
}
// delete the (temporary) font file -- with Unix hard link
// semantics, this will remove the last link; otherwise it will
// return an error, leaving the file to be deleted later (if
// loadXYZFont failed, the file will always be deleted)
if (deleteFile) {
unlink(fontFile ? fontFile->fileName->getCString() : fileName);
}
return fontFile;
}
SplashFont *SplashFontEngine::getFont(SplashFontFile *fontFile,
SplashCoord *mat) {
SplashFont *font;
int i, j;
font = fontCache[0];
if (font && font->matches(fontFile, mat)) {
return font;
}
for (i = 1; i < splashFontCacheSize; ++i) {
font = fontCache[i];
if (font && font->matches(fontFile, mat)) {
for (j = i; j > 0; --j) {
fontCache[j] = fontCache[j-1];
}
fontCache[0] = font;
return font;
}
}
font = fontFile->makeFont(mat);
if (fontCache[splashFontCacheSize - 1]) {
delete fontCache[splashFontCacheSize - 1];
}
for (j = splashFontCacheSize - 1; j > 0; --j) {
fontCache[j] = fontCache[j-1];
}
fontCache[0] = font;
return font;
}

85
splash/SplashFontEngine.h Normal file
View file

@ -0,0 +1,85 @@
//========================================================================
//
// SplashFontEngine.h
//
//========================================================================
#ifndef SPLASHFONTENGINE_H
#define SPLASHFONTENGINE_H
#include <aconf.h>
#ifdef USE_GCC_PRAGMAS
#pragma interface
#endif
#include "gtypes.h"
class SplashT1FontEngine;
class SplashFTFontEngine;
class SplashDTFontEngine;
class SplashFontFile;
class SplashFontFileID;
class SplashFont;
//------------------------------------------------------------------------
#define splashFontCacheSize 16
//------------------------------------------------------------------------
// SplashFontEngine
//------------------------------------------------------------------------
class SplashFontEngine {
public:
// Create a font engine.
SplashFontEngine(
#if HAVE_T1LIB_H
GBool enableT1lib,
#endif
#if HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H
GBool enableFreeType,
#endif
GBool aa);
~SplashFontEngine();
// Get a font file from the cache. Returns NULL if there is no
// matching entry in the cache.
SplashFontFile *getFontFile(SplashFontFileID *id);
// Load fonts - these create new SplashFontFile objects.
SplashFontFile *loadType1Font(SplashFontFileID *idA, char *fileName,
GBool deleteFile, const char **enc);
SplashFontFile *loadType1CFont(SplashFontFileID *idA, char *fileName,
GBool deleteFile, const char **enc);
SplashFontFile *loadCIDFont(SplashFontFileID *idA, char *fileName,
GBool deleteFile);
SplashFontFile *loadTrueTypeFont(SplashFontFileID *idA, char *fileName,
GBool deleteFile,
Gushort *codeToGID, int codeToGIDLen);
// Get a font - this does a cache lookup first, and if not found,
// creates a new SplashFont object and adds it to the cache. The
// matrix:
// [ mat[0] mat[1] ]
// [ mat[2] mat[3] ]
// specifies the font transform in PostScript style:
// [x' y'] = [x y] * mat
// Note that the Splash y axis points downward.
SplashFont *getFont(SplashFontFile *fontFile, SplashCoord *mat);
private:
SplashFont *fontCache[splashFontCacheSize];
#if HAVE_T1LIB_H
SplashT1FontEngine *t1Engine;
#endif
#if HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H
SplashFTFontEngine *ftEngine;
#endif
};
#endif

55
splash/SplashFontFile.cc Normal file
View file

@ -0,0 +1,55 @@
//========================================================================
//
// SplashFontFile.cc
//
//========================================================================
#include <aconf.h>
#ifdef USE_GCC_PRAGMAS
#pragma implementation
#endif
#include <stdio.h>
#ifndef WIN32
# include <unistd.h>
#endif
#include "GString.h"
#include "SplashFontFile.h"
#include "SplashFontFileID.h"
#ifdef VMS
#if (__VMS_VER < 70000000)
extern "C" int unlink(char *filename);
#endif
#endif
//------------------------------------------------------------------------
// SplashFontFile
//------------------------------------------------------------------------
SplashFontFile::SplashFontFile(SplashFontFileID *idA, char *fileNameA,
GBool deleteFileA) {
id = idA;
fileName = new GString(fileNameA);
deleteFile = deleteFileA;
refCnt = 0;
}
SplashFontFile::~SplashFontFile() {
if (deleteFile) {
unlink(fileName->getCString());
}
delete fileName;
delete id;
}
void SplashFontFile::incRefCnt() {
++refCnt;
}
void SplashFontFile::decRefCnt() {
if (!--refCnt) {
delete this;
}
}

60
splash/SplashFontFile.h Normal file
View file

@ -0,0 +1,60 @@
//========================================================================
//
// SplashFontFile.h
//
//========================================================================
#ifndef SPLASHFONTFILE_H
#define SPLASHFONTFILE_H
#include <aconf.h>
#ifdef USE_GCC_PRAGMAS
#pragma interface
#endif
#include "gtypes.h"
#include "SplashTypes.h"
class GString;
class SplashFontEngine;
class SplashFont;
class SplashFontFileID;
//------------------------------------------------------------------------
// SplashFontFile
//------------------------------------------------------------------------
class SplashFontFile {
public:
virtual ~SplashFontFile();
// Create a new SplashFont, i.e., a scaled instance of this font
// file.
virtual SplashFont *makeFont(SplashCoord *mat) = 0;
// Get the font file ID.
SplashFontFileID *getID() { return id; }
// Increment the reference count.
void incRefCnt();
// Decrement the reference count. If the new value is zero, delete
// the SplashFontFile object.
void decRefCnt();
protected:
SplashFontFile(SplashFontFileID *idA, char *fileNameA,
GBool deleteFileA);
SplashFontFileID *id;
GString *fileName;
GBool deleteFile;
int refCnt;
friend class SplashFontEngine;
};
#endif

View file

@ -0,0 +1,23 @@
//========================================================================
//
// SplashFontFileID.cc
//
//========================================================================
#include <aconf.h>
#ifdef USE_GCC_PRAGMAS
#pragma implementation
#endif
#include "SplashFontFileID.h"
//------------------------------------------------------------------------
// SplashFontFileID
//------------------------------------------------------------------------
SplashFontFileID::SplashFontFileID() {
}
SplashFontFileID::~SplashFontFileID() {
}

30
splash/SplashFontFileID.h Normal file
View file

@ -0,0 +1,30 @@
//========================================================================
//
// SplashFontFileID.h
//
//========================================================================
#ifndef SPLASHFONTFILEID_H
#define SPLASHFONTFILEID_H
#include <aconf.h>
#ifdef USE_GCC_PRAGMAS
#pragma interface
#endif
#include "gtypes.h"
//------------------------------------------------------------------------
// SplashFontFileID
//------------------------------------------------------------------------
class SplashFontFileID {
public:
SplashFontFileID();
virtual ~SplashFontFileID();
virtual GBool matches(SplashFontFileID *id) = 0;
};
#endif

View file

@ -0,0 +1,26 @@
//========================================================================
//
// SplashGlyphBitmap.h
//
//========================================================================
#ifndef SPLASHGLYPHBITMAP_H
#define SPLASHGLYPHBITMAP_H
#include <aconf.h>
#include "gtypes.h"
//------------------------------------------------------------------------
// SplashGlyphBitmap
//------------------------------------------------------------------------
struct SplashGlyphBitmap {
int x, y, w, h; // offset and size of glyph
GBool aa; // anti-aliased: true means 8-bit alpha
// bitmap; false means 1-bit
Guchar *data; // bitmap data
GBool freeData; // true if data memory should be freed
};
#endif

46
splash/SplashMath.h Normal file
View file

@ -0,0 +1,46 @@
//========================================================================
//
// SplashMath.h
//
//========================================================================
#ifndef SPLASHMATH_H
#define SPLASHMATH_H
#include <aconf.h>
#include <math.h>
#include "SplashTypes.h"
static inline SplashCoord splashAbs(SplashCoord x) {
return fabs(x);
}
static inline int splashFloor(SplashCoord x) {
return (int)floor(x);
}
static inline int splashCeil(SplashCoord x) {
return (int)ceil(x);
}
static inline int splashRound(SplashCoord x) {
return (int)floor(x + 0.5);
}
static inline SplashCoord splashSqrt(SplashCoord x) {
return sqrt(x);
}
static inline SplashCoord splashPow(SplashCoord x, SplashCoord y) {
return pow(x, y);
}
static inline SplashCoord splashDist(SplashCoord x0, SplashCoord y0,
SplashCoord x1, SplashCoord y1) {
SplashCoord dx, dy;
dx = x1 - x0;
dy = y1 - y0;
return sqrt(dx * dx + dy * dy);
}
#endif

177
splash/SplashPath.cc Normal file
View file

@ -0,0 +1,177 @@
//========================================================================
//
// SplashPath.cc
//
//========================================================================
#include <aconf.h>
#ifdef USE_GCC_PRAGMAS
#pragma implementation
#endif
#include <string.h>
#include "gmem.h"
#include "SplashErrorCodes.h"
#include "SplashPath.h"
//------------------------------------------------------------------------
// SplashPath
//------------------------------------------------------------------------
// A path can be in three possible states:
//
// 1. no current point -- zero or more finished subpaths
// [curSubpath == length]
//
// 2. one point in subpath
// [curSubpath == length - 1]
//
// 3. open subpath with two or more points
// [curSubpath < length - 1]
SplashPath::SplashPath() {
pts = NULL;
flags = NULL;
length = size = 0;
curSubpath = 0;
}
SplashPath::SplashPath(SplashPath *path) {
length = path->length;
size = path->size;
pts = (SplashPathPoint *)gmalloc(size * sizeof(SplashPathPoint));
flags = (Guchar *)gmalloc(size * sizeof(Guchar));
memcpy(pts, path->pts, length * sizeof(SplashPathPoint));
memcpy(flags, path->flags, length * sizeof(Guchar));
curSubpath = path->curSubpath;
}
SplashPath::~SplashPath() {
gfree(pts);
gfree(flags);
}
// Add space for <nPts> more points.
void SplashPath::grow(int nPts) {
if (length + nPts > size) {
if (size == 0) {
size = 32;
}
while (size < length + nPts) {
size *= 2;
}
pts = (SplashPathPoint *)grealloc(pts, size * sizeof(SplashPathPoint));
flags = (Guchar *)grealloc(flags, size * sizeof(Guchar));
}
}
void SplashPath::append(SplashPath *path) {
int i;
curSubpath = length + path->curSubpath;
grow(path->length);
for (i = 0; i < path->length; ++i) {
pts[length] = path->pts[i];
flags[length] = path->flags[i];
++length;
}
}
SplashError SplashPath::moveTo(SplashCoord x, SplashCoord y) {
if (onePointSubpath()) {
return splashErrBogusPath;
}
grow(1);
pts[length].x = x;
pts[length].y = y;
flags[length] = splashPathFirst | splashPathLast;
curSubpath = length++;
return splashOk;
}
SplashError SplashPath::lineTo(SplashCoord x, SplashCoord y) {
if (noCurrentPoint()) {
return splashErrNoCurPt;
}
flags[length-1] &= ~splashPathLast;
grow(1);
pts[length].x = x;
pts[length].y = y;
flags[length] = splashPathLast;
++length;
return splashOk;
}
SplashError SplashPath::curveTo(SplashCoord x1, SplashCoord y1,
SplashCoord x2, SplashCoord y2,
SplashCoord x3, SplashCoord y3) {
if (noCurrentPoint()) {
return splashErrNoCurPt;
}
flags[length-1] &= ~splashPathLast;
grow(3);
pts[length].x = x1;
pts[length].y = y1;
flags[length] = splashPathCurve;
++length;
pts[length].x = x2;
pts[length].y = y2;
flags[length] = splashPathCurve;
++length;
pts[length].x = x3;
pts[length].y = y3;
flags[length] = splashPathLast;
++length;
return splashOk;
}
SplashError SplashPath::arcCWTo(SplashCoord x1, SplashCoord y1,
SplashCoord xc, SplashCoord yc) {
if (noCurrentPoint()) {
return splashErrNoCurPt;
}
flags[length-1] &= ~splashPathLast;
grow(2);
pts[length].x = xc;
pts[length].y = yc;
flags[length] = splashPathArcCW;
++length;
pts[length].x = x1;
pts[length].y = y1;
flags[length] = splashPathLast;
++length;
return splashOk;
}
SplashError SplashPath::close() {
if (noCurrentPoint()) {
return splashErrNoCurPt;
}
if (pts[length - 1].x != pts[curSubpath].x ||
pts[length - 1].y != pts[curSubpath].y) {
lineTo(pts[curSubpath].x, pts[curSubpath].y);
}
flags[curSubpath] |= splashPathClosed;
flags[length - 1] |= splashPathClosed;
curSubpath = length;
return splashOk;
}
void SplashPath::offset(SplashCoord dx, SplashCoord dy) {
int i;
for (i = 0; i < length; ++i) {
pts[i].x += dx;
pts[i].y += dy;
}
}
GBool SplashPath::getCurPt(SplashCoord *x, SplashCoord *y) {
if (noCurrentPoint()) {
return gFalse;
}
*x = pts[length - 1].x;
*y = pts[length - 1].y;
return gTrue;
}

107
splash/SplashPath.h Normal file
View file

@ -0,0 +1,107 @@
//========================================================================
//
// SplashPath.h
//
//========================================================================
#ifndef SPLASHPATH_H
#define SPLASHPATH_H
#include <aconf.h>
#ifdef USE_GCC_PRAGMAS
#pragma interface
#endif
#include "SplashTypes.h"
//------------------------------------------------------------------------
// SplashPathPoint
//------------------------------------------------------------------------
struct SplashPathPoint {
SplashCoord x, y;
};
//------------------------------------------------------------------------
// SplashPath.flags
//------------------------------------------------------------------------
// first point on each subpath sets this flag
#define splashPathFirst 0x01
// last point on each subpath sets this flag
#define splashPathLast 0x02
// if the subpath is closed, its first and last points must be
// identical, and must set this flag
#define splashPathClosed 0x04
// curve control points set this flag
#define splashPathCurve 0x08
// clockwise arc center points set this flag
#define splashPathArcCW 0x10
//------------------------------------------------------------------------
// SplashPath
//------------------------------------------------------------------------
class SplashPath {
public:
// Create an empty path.
SplashPath();
// Copy a path.
SplashPath *copy() { return new SplashPath(this); }
~SplashPath();
// Append <path> to <this>.
void append(SplashPath *path);
// Start a new subpath.
SplashError moveTo(SplashCoord x, SplashCoord y);
// Add a line segment to the last subpath.
SplashError lineTo(SplashCoord x, SplashCoord y);
// Add a third-order (cubic) Bezier curve segment to the last
// subpath.
SplashError curveTo(SplashCoord x1, SplashCoord y1,
SplashCoord x2, SplashCoord y2,
SplashCoord x3, SplashCoord y3);
// Add a clockwise circular arc with center (xc, yc) and endpoint
// (x1, y1).
SplashError arcCWTo(SplashCoord x1, SplashCoord y1,
SplashCoord xc, SplashCoord yc);
// Close the last subpath, adding a line segment if necessary.
SplashError close();
// Add (<dx>, <dy>) to every point on this path.
void offset(SplashCoord dx, SplashCoord dy);
// Get the current point.
GBool getCurPt(SplashCoord *x, SplashCoord *y);
private:
SplashPath(SplashPath *path);
void grow(int nPts);
GBool noCurrentPoint() { return curSubpath == length; }
GBool onePointSubpath() { return curSubpath == length - 1; }
GBool openSubpath() { return curSubpath < length - 1; }
SplashPathPoint *pts; // array of points
Guchar *flags; // array of flags
int length, size; // length/size of the pts and flags arrays
int curSubpath; // index of first point in last subpath
friend class SplashXPath;
friend class Splash;
};
#endif

64
splash/SplashPattern.cc Normal file
View file

@ -0,0 +1,64 @@
//========================================================================
//
// SplashPattern.cc
//
//========================================================================
#include <aconf.h>
#ifdef USE_GCC_PRAGMAS
#pragma implementation
#endif
#include "SplashMath.h"
#include "SplashScreen.h"
#include "SplashPattern.h"
//------------------------------------------------------------------------
// SplashPattern
//------------------------------------------------------------------------
SplashPattern::SplashPattern() {
}
SplashPattern::~SplashPattern() {
}
//------------------------------------------------------------------------
// SplashSolidColor
//------------------------------------------------------------------------
SplashSolidColor::SplashSolidColor(SplashColor colorA) {
color = colorA;
}
SplashSolidColor::~SplashSolidColor() {
}
SplashColor SplashSolidColor::getColor(int x, int y) {
return color;
}
//------------------------------------------------------------------------
// SplashHalftone
//------------------------------------------------------------------------
SplashHalftone::SplashHalftone(SplashColor color0A, SplashColor color1A,
SplashScreen *screenA, SplashCoord valueA) {
color0 = color0A;
color1 = color1A;
screen = screenA;
value = valueA;
}
SplashPattern *SplashHalftone::copy() {
return new SplashHalftone(color0, color1, screen->copy(), value);
}
SplashHalftone::~SplashHalftone() {
delete screen;
}
SplashColor SplashHalftone::getColor(int x, int y) {
return screen->test(x, y, value) ? color1 : color0;
}

81
splash/SplashPattern.h Normal file
View file

@ -0,0 +1,81 @@
//========================================================================
//
// SplashPattern.h
//
//========================================================================
#ifndef SPLASHPATTERN_H
#define SPLASHPATTERN_H
#include <aconf.h>
#ifdef USE_GCC_PRAGMAS
#pragma interface
#endif
#include "SplashTypes.h"
class SplashScreen;
//------------------------------------------------------------------------
// SplashPattern
//------------------------------------------------------------------------
class SplashPattern {
public:
SplashPattern();
virtual SplashPattern *copy() = 0;
virtual ~SplashPattern();
virtual SplashColor getColor(int x, int y) = 0;
private:
};
//------------------------------------------------------------------------
// SplashSolidColor
//------------------------------------------------------------------------
class SplashSolidColor: public SplashPattern {
public:
SplashSolidColor(SplashColor colorA);
virtual SplashPattern *copy() { return new SplashSolidColor(color); }
virtual ~SplashSolidColor();
virtual SplashColor getColor(int x, int y);
private:
SplashColor color;
};
//------------------------------------------------------------------------
// SplashHalftone
//------------------------------------------------------------------------
class SplashHalftone: public SplashPattern {
public:
SplashHalftone(SplashColor color0A, SplashColor color1A,
SplashScreen *screenA, SplashCoord valueA);
virtual SplashPattern *copy();
virtual ~SplashHalftone();
virtual SplashColor getColor(int x, int y);
private:
SplashColor color0, color1;
SplashScreen *screen;
SplashCoord value;
};
#endif

107
splash/SplashScreen.cc Normal file
View file

@ -0,0 +1,107 @@
//========================================================================
//
// SplashScreen.cc
//
//========================================================================
#include <aconf.h>
#ifdef USE_GCC_PRAGMAS
#pragma implementation
#endif
#include "gmem.h"
#include "SplashMath.h"
#include "SplashScreen.h"
//------------------------------------------------------------------------
// SplashScreen
//------------------------------------------------------------------------
// This generates a 45 degree screen using a circular dot spot
// function. DPI = resolution / ((size / 2) * sqrt(2)).
// Gamma correction (gamma = 1 / 1.33) is also computed here.
SplashScreen::SplashScreen(int sizeA) {
SplashCoord *dist;
SplashCoord u, v, d;
int x, y, x1, y1, i;
size = sizeA >> 1;
if (size < 1) {
size = 1;
}
// initialize the threshold matrix
mat = (SplashCoord *)gmalloc(2 * size * size * sizeof(SplashCoord));
for (y = 0; y < 2 * size; ++y) {
for (x = 0; x < size; ++x) {
mat[y * size + x] = -1;
}
}
// build the distance matrix
dist = (SplashCoord *)gmalloc(2 * size * size * sizeof(SplashCoord));
for (y = 0; y < size; ++y) {
for (x = 0; x < size; ++x) {
if (x + y < size - 1) {
u = (SplashCoord)x + 0.5 - 0; //~ (-0.5);
v = (SplashCoord)y + 0.5 - 0;
} else {
u = (SplashCoord)x + 0.5 - (SplashCoord)size; //~ ((SplashCoord)size - 0.5);
v = (SplashCoord)y + 0.5 - (SplashCoord)size;
}
dist[y * size + x] = u*u + v*v;
}
}
for (y = 0; y < size; ++y) {
for (x = 0; x < size; ++x) {
if (x < y) {
u = (SplashCoord)x + 0.5 - 0; //~ (-0.5);
v = (SplashCoord)y + 0.5 - (SplashCoord)size;
} else {
u = (SplashCoord)x + 0.5 - (SplashCoord)size; //~ ((SplashCoord)size - 0.5);
v = (SplashCoord)y + 0.5 - 0;
}
dist[(size + y) * size + x] = u*u + v*v;
}
}
// build the threshold matrix
x1 = y1 = 0; // make gcc happy
for (i = 1; i <= 2 * size * size; ++i) {
d = 2 * size * size;
for (y = 0; y < 2 * size; ++y) {
for (x = 0; x < size; ++x) {
if (mat[y * size + x] < 0 &&
dist[y * size + x] < d) {
x1 = x;
y1 = y;
d = dist[y1 * size + x1];
}
}
}
u = 1.0 - (SplashCoord)i / (SplashCoord)(2 * size * size + 1);
mat[y1 * size + x1] = splashPow(u, 1.33);
}
gfree(dist);
}
SplashScreen::~SplashScreen() {
gfree(mat);
}
int SplashScreen::test(int x, int y, SplashCoord value) {
SplashCoord *mat1;
int xx, yy;
xx = x % (2 * size);
yy = y % (2 * size);
mat1 = mat;
if ((xx / size) ^ (yy / size)) {
mat1 += size * size;
}
xx %= size;
yy %= size;
return value < mat1[yy * size + xx] ? 0 : 1;
}

40
splash/SplashScreen.h Normal file
View file

@ -0,0 +1,40 @@
//========================================================================
//
// SplashScreen.h
//
//========================================================================
#ifndef SPLASHSCREEN_H
#define SPLASHSCREEN_H
#include <aconf.h>
#ifdef USE_GCC_PRAGMAS
#pragma interface
#endif
#include "SplashTypes.h"
//------------------------------------------------------------------------
// SplashScreen
//------------------------------------------------------------------------
class SplashScreen {
public:
SplashScreen(int sizeA);
~SplashScreen();
SplashScreen *copy() { return new SplashScreen(size << 1); }
// Return the computed pixel value (0=black, 1=white) for the gray
// level <value> at (<x>, <y>).
int test(int x, int y, SplashCoord value);
private:
SplashCoord *mat; // threshold matrix
int size; // size of the threshold matrix
};
#endif

99
splash/SplashState.cc Normal file
View file

@ -0,0 +1,99 @@
//========================================================================
//
// SplashState.cc
//
//========================================================================
#include <aconf.h>
#ifdef USE_GCC_PRAGMAS
#pragma implementation
#endif
#include <string.h>
#include "gmem.h"
#include "SplashPattern.h"
#include "SplashScreen.h"
#include "SplashClip.h"
#include "SplashState.h"
//------------------------------------------------------------------------
// SplashState
//------------------------------------------------------------------------
SplashState::SplashState(int width, int height) {
SplashColor color;
memset(&color, 0, sizeof(SplashColor));
strokePattern = new SplashSolidColor(color);
fillPattern = new SplashSolidColor(color);
screen = new SplashScreen(10);
lineWidth = 0;
lineCap = splashLineCapButt;
lineJoin = splashLineJoinMiter;
miterLimit = 10;
flatness = 1;
lineDash = NULL;
lineDashLength = 0;
lineDashPhase = 0;
clip = new SplashClip(0, 0, width - 1, height - 1);
next = NULL;
}
SplashState::SplashState(SplashState *state) {
strokePattern = state->strokePattern->copy();
fillPattern = state->fillPattern->copy();
screen = state->screen->copy();
lineWidth = state->lineWidth;
lineCap = state->lineCap;
lineJoin = state->lineJoin;
miterLimit = state->miterLimit;
flatness = state->flatness;
if (state->lineDash) {
lineDashLength = state->lineDashLength;
lineDash = (SplashCoord *)gmalloc(lineDashLength * sizeof(SplashCoord));
memcpy(lineDash, state->lineDash, lineDashLength * sizeof(SplashCoord));
} else {
lineDash = NULL;
lineDashLength = 0;
}
lineDashPhase = state->lineDashPhase;
clip = state->clip->copy();
next = NULL;
}
SplashState::~SplashState() {
delete strokePattern;
delete fillPattern;
delete screen;
gfree(lineDash);
delete clip;
}
void SplashState::setStrokePattern(SplashPattern *strokePatternA) {
delete strokePattern;
strokePattern = strokePatternA;
}
void SplashState::setFillPattern(SplashPattern *fillPatternA) {
delete fillPattern;
fillPattern = fillPatternA;
}
void SplashState::setScreen(SplashScreen *screenA) {
delete screen;
screen = screenA;
}
void SplashState::setLineDash(SplashCoord *lineDashA, int lineDashLengthA,
SplashCoord lineDashPhaseA) {
gfree(lineDash);
lineDashLength = lineDashLengthA;
if (lineDashLength > 0) {
lineDash = (SplashCoord *)gmalloc(lineDashLength * sizeof(SplashCoord));
memcpy(lineDash, lineDashA, lineDashLength * sizeof(SplashCoord));
} else {
lineDash = NULL;
}
lineDashPhase = lineDashPhaseA;
}

88
splash/SplashState.h Normal file
View file

@ -0,0 +1,88 @@
//========================================================================
//
// SplashState.h
//
//========================================================================
#ifndef SPLASHSTATE_H
#define SPLASHSTATE_H
#include <aconf.h>
#ifdef USE_GCC_PRAGMAS
#pragma interface
#endif
#include "SplashTypes.h"
class SplashPattern;
class SplashScreen;
class SplashClip;
//------------------------------------------------------------------------
// line cap values
//------------------------------------------------------------------------
#define splashLineCapButt 0
#define splashLineCapRound 1
#define splashLineCapProjecting 2
//------------------------------------------------------------------------
// line join values
//------------------------------------------------------------------------
#define splashLineJoinMiter 0
#define splashLineJoinRound 1
#define splashLineJoinBevel 2
//------------------------------------------------------------------------
// SplashState
//------------------------------------------------------------------------
class SplashState {
public:
// Create a new state object, initialized with default settings.
SplashState(int width, int height);
// Copy a state object.
SplashState *copy() { return new SplashState(this); }
~SplashState();
// Set the stroke pattern. This does not copy <strokePatternA>.
void setStrokePattern(SplashPattern *strokePatternA);
// Set the fill pattern. This does not copy <fillPatternA>.
void setFillPattern(SplashPattern *fillPatternA);
// Set the screen. This does not copy <screenA>.
void setScreen(SplashScreen *screenA);
// Set the line dash pattern. This copies the <lineDashA> array.
void setLineDash(SplashCoord *lineDashA, int lineDashLengthA,
SplashCoord lineDashPhaseA);
private:
SplashState(SplashState *state);
SplashPattern *strokePattern;
SplashPattern *fillPattern;
SplashScreen *screen;
SplashCoord lineWidth;
int lineCap;
int lineJoin;
SplashCoord miterLimit;
SplashCoord flatness;
SplashCoord *lineDash;
int lineDashLength;
SplashCoord lineDashPhase;
SplashClip *clip;
SplashState *next; // used by Splash class
friend class Splash;
};
#endif

251
splash/SplashT1Font.cc Normal file
View file

@ -0,0 +1,251 @@
//========================================================================
//
// SplashT1Font.cc
//
//========================================================================
#include <aconf.h>
#if HAVE_T1LIB_H
#ifdef USE_GCC_PRAGMAS
#pragma implementation
#endif
#include <stdlib.h>
#include <t1lib.h>
#include "gmem.h"
#include "SplashMath.h"
#include "SplashGlyphBitmap.h"
#include "SplashPath.h"
#include "SplashT1FontEngine.h"
#include "SplashT1FontFile.h"
#include "SplashT1Font.h"
//------------------------------------------------------------------------
static Guchar bitReverse[256] = {
0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
};
//------------------------------------------------------------------------
// SplashT1Font
//------------------------------------------------------------------------
SplashT1Font::SplashT1Font(SplashT1FontFile *fontFileA, SplashCoord *matA):
SplashFont(fontFileA, matA, ((SplashT1FontFile *)fontFileA)->engine->aa)
{
T1_TMATRIX matrix;
BBox bbox;
SplashCoord bbx0, bby0, bbx1, bby1;
int x, y;
t1libID = T1_CopyFont(fontFileA->t1libID);
// compute font size
size = (float)splashSqrt(mat[2]*mat[2] + mat[3]*mat[3]);
// transform the four corners of the font bounding box -- the min
// and max values form the bounding box of the transformed font
bbox = T1_GetFontBBox(t1libID);
bbx0 = 0.001 * bbox.llx;
bby0 = 0.001 * bbox.lly;
bbx1 = 0.001 * bbox.urx;
bby1 = 0.001 * bbox.ury;
// some fonts are completely broken, so we fake it (with values
// large enough that most glyphs should fit)
if (bbx0 == 0 && bby0 == 0 && bbx1 == 0 && bby1 == 0) {
bbx0 = bby0 = -0.5;
bbx1 = bby1 = 1.5;
}
x = (int)(mat[0] * bbx0 + mat[2] * bby0);
xMin = xMax = x;
y = (int)(mat[1] * bbx0 + mat[3] * bby0);
yMin = yMax = y;
x = (int)(mat[0] * bbx0 + mat[2] * bby1);
if (x < xMin) {
xMin = x;
} else if (x > xMax) {
xMax = x;
}
y = (int)(mat[1] * bbx0 + mat[3] * bby1);
if (y < yMin) {
yMin = y;
} else if (y > yMax) {
yMax = y;
}
x = (int)(mat[0] * bbx1 + mat[2] * bby0);
if (x < xMin) {
xMin = x;
} else if (x > xMax) {
xMax = x;
}
y = (int)(mat[1] * bbx1 + mat[3] * bby0);
if (y < yMin) {
yMin = y;
} else if (y > yMax) {
yMax = y;
}
x = (int)(mat[0] * bbx1 + mat[2] * bby1);
if (x < xMin) {
xMin = x;
} else if (x > xMax) {
xMax = x;
}
y = (int)(mat[1] * bbx1 + mat[3] * bby1);
if (y < yMin) {
yMin = y;
} else if (y > yMax) {
yMax = y;
}
// This is a kludge: some buggy PDF generators embed fonts with
// zero bounding boxes.
if (xMax == xMin) {
xMin = 0;
xMax = (int)size;
}
if (yMax == yMin) {
yMin = 0;
yMax = (int)(1.2 * size);
}
// Another kludge: an unusually large xMin or yMin coordinate is
// probably wrong.
if (xMin > 0) {
xMin = 0;
}
if (yMin > 0) {
yMin = 0;
}
// Another kludge: t1lib doesn't correctly handle fonts with
// real (non-integer) bounding box coordinates.
if (xMax - xMin > 5000) {
xMin = 0;
xMax = (int)size;
}
if (yMax - yMin > 5000) {
yMin = 0;
yMax = (int)(1.2 * size);
}
// transform the font
matrix.cxx = mat[0] / size;
matrix.cxy = mat[1] / size;
matrix.cyx = mat[2] / size;
matrix.cyy = mat[3] / size;
T1_TransformFont(t1libID, &matrix);
}
SplashT1Font::~SplashT1Font() {
T1_DeleteFont(t1libID);
}
GBool SplashT1Font::getGlyph(int c, int xFrac, int yFrac,
SplashGlyphBitmap *bitmap) {
return SplashFont::getGlyph(c, 0, 0, bitmap);
}
GBool SplashT1Font::makeGlyph(int c, int xFrac, int yFrac,
SplashGlyphBitmap *bitmap) {
GLYPH *glyph;
int n, i;
if (aa) {
glyph = T1_AASetChar(t1libID, c, size, NULL);
} else {
glyph = T1_SetChar(t1libID, c, size, NULL);
}
if (!glyph) {
return gFalse;
}
bitmap->x = -glyph->metrics.leftSideBearing;
bitmap->y = glyph->metrics.ascent;
bitmap->w = glyph->metrics.rightSideBearing - glyph->metrics.leftSideBearing;
bitmap->h = glyph->metrics.ascent - glyph->metrics.descent;
bitmap->aa = aa;
if (aa) {
bitmap->data = (Guchar *)glyph->bits;
bitmap->freeData = gFalse;
} else {
n = bitmap->h * ((bitmap->w + 7) >> 3);
bitmap->data = (Guchar *)gmalloc(n);
for (i = 0; i < n; ++i) {
bitmap->data[i] = bitReverse[glyph->bits[i] & 0xff];
}
bitmap->freeData = gTrue;
}
return gTrue;
}
SplashPath *SplashT1Font::getGlyphPath(int c) {
SplashPath *path;
T1_OUTLINE *outline;
T1_PATHSEGMENT *seg;
T1_BEZIERSEGMENT *bez;
SplashCoord x, y, x1, y1;
path = new SplashPath();
outline = T1_GetCharOutline(t1libID, c, size, NULL);
x = 0;
y = 0;
for (seg = outline; seg; seg = seg->link) {
switch (seg->type) {
case T1_PATHTYPE_MOVE:
x += seg->dest.x / 65536.0;
y += seg->dest.y / 65536.0;
path->moveTo(x, y);
break;
case T1_PATHTYPE_LINE:
x += seg->dest.x / 65536.0;
y += seg->dest.y / 65536.0;
path->lineTo(x, y);
break;
case T1_PATHTYPE_BEZIER:
bez = (T1_BEZIERSEGMENT *)seg;
x1 = x + bez->dest.x / 65536.0;
y1 = y + bez->dest.y / 65536.0;
path->curveTo(x + bez->B.x / 65536.0, y + bez->B.y / 65536.0,
x + bez->C.x / 65536.0, y + bez->C.y / 65536.0,
x1, y1);
x = x1;
y = y1;
break;
}
}
T1_FreeOutline(outline);
return path;
}
#endif // HAVE_T1LIB_H

51
splash/SplashT1Font.h Normal file
View file

@ -0,0 +1,51 @@
//========================================================================
//
// SplashT1Font.h
//
//========================================================================
#ifndef SPLASHT1FONT_H
#define SPLASHT1FONT_H
#include <aconf.h>
#if HAVE_T1LIB_H
#ifdef USE_GCC_PRAGMAS
#pragma interface
#endif
#include "SplashFont.h"
//------------------------------------------------------------------------
// SplashT1Font
//------------------------------------------------------------------------
class SplashT1Font: public SplashFont {
public:
SplashT1Font(SplashT1FontFile *fontFileA, SplashCoord *matA);
virtual ~SplashT1Font();
// Munge xFrac and yFrac before calling SplashFont::getGlyph.
virtual GBool getGlyph(int c, int xFrac, int yFrac,
SplashGlyphBitmap *bitmap);
// Rasterize a glyph. The <xFrac> and <yFrac> values are the same
// as described for getGlyph.
virtual GBool makeGlyph(int c, int xFrac, int yFrac,
SplashGlyphBitmap *bitmap);
// Return the path for a glyph.
virtual SplashPath *getGlyphPath(int c);
private:
int t1libID; // t1lib font ID
float size;
};
#endif // HAVE_T1LIB_H
#endif

View file

@ -0,0 +1,124 @@
//========================================================================
//
// SplashT1FontEngine.cc
//
//========================================================================
#include <aconf.h>
#if HAVE_T1LIB_H
#ifdef USE_GCC_PRAGMAS
#pragma implementation
#endif
#include <stdlib.h>
#include <stdio.h>
#ifndef WIN32
# include <unistd.h>
#endif
#include <t1lib.h>
#include "GString.h"
#include "gfile.h"
#include "FoFiType1C.h"
#include "SplashT1FontFile.h"
#include "SplashT1FontEngine.h"
#ifdef VMS
#if (__VMS_VER < 70000000)
extern "C" int unlink(char *filename);
#endif
#endif
//------------------------------------------------------------------------
int SplashT1FontEngine::t1libInitCount = 0;
//------------------------------------------------------------------------
static void fileWrite(void *stream, const char *data, int len) {
fwrite(data, 1, len, (FILE *)stream);
}
//------------------------------------------------------------------------
// SplashT1FontEngine
//------------------------------------------------------------------------
SplashT1FontEngine::SplashT1FontEngine(GBool aaA) {
aa = aaA;
}
SplashT1FontEngine *SplashT1FontEngine::init(GBool aaA) {
// grayVals[i] = round(i * 255 / 16)
static unsigned long grayVals[17] = {
0, 16, 32, 48, 64, 80, 96, 112, 128, 143, 159, 175, 191, 207, 223, 239, 255
};
//~ for multithreading: need a mutex here
if (t1libInitCount == 0) {
T1_SetBitmapPad(8);
if (!T1_InitLib(NO_LOGFILE | IGNORE_CONFIGFILE | IGNORE_FONTDATABASE |
T1_NO_AFM)) {
return NULL;
}
if (aaA) {
T1_AASetBitsPerPixel(8);
T1_AASetLevel(T1_AA_HIGH);
T1_AAHSetGrayValues(grayVals);
} else {
T1_AANSetGrayValues(0, 1);
}
}
++t1libInitCount;
return new SplashT1FontEngine(aaA);
}
SplashT1FontEngine::~SplashT1FontEngine() {
//~ for multithreading: need a mutex here
if (--t1libInitCount == 0) {
T1_CloseLib();
}
}
SplashFontFile *SplashT1FontEngine::loadType1Font(SplashFontFileID *idA,
char *fileName,
GBool deleteFile,
const char **enc) {
return SplashT1FontFile::loadType1Font(this, idA, fileName, deleteFile, enc);
}
SplashFontFile *SplashT1FontEngine::loadType1CFont(SplashFontFileID *idA,
char *fileName,
GBool deleteFile,
const char **enc) {
FoFiType1C *ff;
GString *tmpFileName;
FILE *tmpFile;
SplashFontFile *ret;
if (!(ff = FoFiType1C::load(fileName))) {
return NULL;
}
tmpFileName = NULL;
if (!openTempFile(&tmpFileName, &tmpFile, "wb", NULL)) {
delete ff;
return NULL;
}
ff->convertToType1(NULL, gTrue, &fileWrite, tmpFile);
delete ff;
fclose(tmpFile);
ret = SplashT1FontFile::loadType1Font(this, idA, tmpFileName->getCString(),
gTrue, enc);
if (ret) {
if (deleteFile) {
unlink(fileName);
}
} else {
unlink(tmpFileName->getCString());
}
delete tmpFileName;
return ret;
}
#endif // HAVE_T1LIB_H

View file

@ -0,0 +1,53 @@
//========================================================================
//
// SplashT1FontEngine.h
//
//========================================================================
#ifndef SPLASHT1FONTENGINE_H
#define SPLASHT1FONTENGINE_H
#include <aconf.h>
#if HAVE_T1LIB_H
#ifdef USE_GCC_PRAGMAS
#pragma interface
#endif
#include "gtypes.h"
class SplashFontFile;
class SplashFontFileID;
//------------------------------------------------------------------------
// SplashT1FontEngine
//------------------------------------------------------------------------
class SplashT1FontEngine {
public:
static SplashT1FontEngine *init(GBool aaA);
~SplashT1FontEngine();
// Load fonts.
SplashFontFile *loadType1Font(SplashFontFileID *idA, char *fileName,
GBool deleteFile, const char **enc);
SplashFontFile *loadType1CFont(SplashFontFileID *idA, char *fileName,
GBool deleteFile, const char **enc);
private:
SplashT1FontEngine(GBool aaA);
static int t1libInitCount;
GBool aa;
friend class SplashT1FontFile;
friend class SplashT1Font;
};
#endif // HAVE_T1LIB_H
#endif

View file

@ -0,0 +1,96 @@
//========================================================================
//
// SplashT1FontFile.cc
//
//========================================================================
#include <aconf.h>
#if HAVE_T1LIB_H
#ifdef USE_GCC_PRAGMAS
#pragma implementation
#endif
#include <string.h>
#include <t1lib.h>
#include "gmem.h"
#include "SplashT1FontEngine.h"
#include "SplashT1Font.h"
#include "SplashT1FontFile.h"
//------------------------------------------------------------------------
// SplashT1FontFile
//------------------------------------------------------------------------
SplashFontFile *SplashT1FontFile::loadType1Font(SplashT1FontEngine *engineA,
SplashFontFileID *idA,
char *fileNameA,
GBool deleteFileA,
const char **encA) {
int t1libIDA;
char **encTmp;
char *encStrTmp;
int encStrSize;
char *encPtr;
int i;
// load the font file
if ((t1libIDA = T1_AddFont(fileNameA)) < 0) {
return NULL;
}
T1_LoadFont(t1libIDA);
// reencode it
encStrSize = 0;
for (i = 0; i < 256; ++i) {
if (encA[i]) {
encStrSize += strlen(encA[i]) + 1;
}
}
encTmp = (char **)gmalloc(257 * sizeof(char *));
encStrTmp = (char *)gmalloc(encStrSize * sizeof(char));
encPtr = encStrTmp;
for (i = 0; i < 256; ++i) {
if (encA[i]) {
strcpy(encPtr, encA[i]);
encTmp[i] = encPtr;
encPtr += strlen(encPtr) + 1;
} else {
encTmp[i] = ".notdef";
}
}
encTmp[256] = "custom";
T1_ReencodeFont(t1libIDA, encTmp);
return new SplashT1FontFile(engineA, idA, fileNameA, deleteFileA,
t1libIDA, encTmp, encStrTmp);
}
SplashT1FontFile::SplashT1FontFile(SplashT1FontEngine *engineA,
SplashFontFileID *idA,
char *fileNameA, GBool deleteFileA,
int t1libIDA, char **encA, char *encStrA):
SplashFontFile(idA, fileNameA, deleteFileA)
{
engine = engineA;
t1libID = t1libIDA;
enc = encA;
encStr = encStrA;
}
SplashT1FontFile::~SplashT1FontFile() {
gfree(encStr);
gfree(enc);
T1_DeleteFont(t1libID);
}
SplashFont *SplashT1FontFile::makeFont(SplashCoord *mat) {
SplashFont *font;
font = new SplashT1Font(this, mat);
font->initCache();
return font;
}
#endif // HAVE_T1LIB_H

57
splash/SplashT1FontFile.h Normal file
View file

@ -0,0 +1,57 @@
//========================================================================
//
// SplashT1FontFile.h
//
//========================================================================
#ifndef SPLASHT1FONTFILE_H
#define SPLASHT1FONTFILE_H
#include <aconf.h>
#if HAVE_T1LIB_H
#ifdef USE_GCC_PRAGMAS
#pragma interface
#endif
#include "SplashFontFile.h"
class SplashT1FontEngine;
//------------------------------------------------------------------------
// SplashT1FontFile
//------------------------------------------------------------------------
class SplashT1FontFile: public SplashFontFile {
public:
static SplashFontFile *loadType1Font(SplashT1FontEngine *engineA,
SplashFontFileID *idA,
char *fileNameA, GBool deleteFileA,
const char **encA);
virtual ~SplashT1FontFile();
// Create a new SplashT1Font, i.e., a scaled instance of this font
// file.
virtual SplashFont *makeFont(SplashCoord *mat);
private:
SplashT1FontFile(SplashT1FontEngine *engineA,
SplashFontFileID *idA,
char *fileNameA, GBool deleteFileA,
int t1libIDA, char **encA, char *encStrA);
SplashT1FontEngine *engine;
int t1libID; // t1lib font ID
char **enc;
char *encStr;
friend class SplashT1Font;
};
#endif // HAVE_T1LIB_H
#endif

77
splash/SplashTypes.h Normal file
View file

@ -0,0 +1,77 @@
//========================================================================
//
// SplashTypes.h
//
//========================================================================
#ifndef SPLASHTYPES_H
#define SPLASHTYPES_H
#include <aconf.h>
#include "gtypes.h"
//------------------------------------------------------------------------
// coordinates
//------------------------------------------------------------------------
typedef double SplashCoord;
//------------------------------------------------------------------------
// colors
//------------------------------------------------------------------------
enum SplashColorMode {
splashModeMono1,
splashModeMono8,
splashModeRGB8,
splashModeBGR8Packed
};
// max number of components in any SplashColor
#define splashMaxColorComps 3
// 1-bit gray or alpha
typedef Guchar SplashMono1;
typedef Guchar SplashMono1P; // packed
// 8-bit gray or alpha
typedef Guchar SplashMono8;
// 3x8-bit RGB: (MSB) 00RRGGBB (LSB)
typedef Guint SplashRGB8;
#define splashRGB8R(rgb8) (((rgb8) >> 16) & 0xff)
#define splashRGB8G(rgb8) (((rgb8) >> 8) & 0xff)
#define splashRGB8B(rgb8) ((rgb8) & 0xff)
#define splashMakeRGB8(r, g, b) \
((((r) & 0xff) << 16) | (((g) & 0xff) << 8) | ((b) & 0xff))
// 3x8-bit RGB: (MSB) 00BBGGRR (LSB)
typedef Guint SplashBGR8;
typedef Guchar SplashBGR8P; // packed
#define splashBGR8R(bgr8) ((bgr8) & 0xff)
#define splashBGR8G(bgr8) (((bgr8) >> 8) & 0xff)
#define splashBGR8B(bgr8) (((bgr8) >> 16) & 0xff)
#define splashMakeBGR8(r, g, b) \
((((b) & 0xff) << 16) | (((g) & 0xff) << 8) | ((r) & 0xff))
union SplashColor {
SplashMono1 mono1;
SplashMono8 mono8;
SplashRGB8 rgb8;
SplashBGR8 bgr8;
};
union SplashColorPtr {
SplashMono1P *mono1;
SplashMono8 *mono8;
SplashRGB8 *rgb8;
SplashBGR8P *bgr8;
};
//------------------------------------------------------------------------
// error results
//------------------------------------------------------------------------
typedef int SplashError;
#endif

417
splash/SplashXPath.cc Normal file
View file

@ -0,0 +1,417 @@
//========================================================================
//
// SplashXPath.cc
//
//========================================================================
#include <aconf.h>
#ifdef USE_GCC_PRAGMAS
#pragma implementation
#endif
#include <stdlib.h>
#include <string.h>
#include "gmem.h"
#include "SplashMath.h"
#include "SplashPath.h"
#include "SplashXPath.h"
//------------------------------------------------------------------------
#define maxCurveSplits (1 << 10)
//------------------------------------------------------------------------
// SplashXPath
//------------------------------------------------------------------------
SplashXPath::SplashXPath() {
segs = NULL;
length = size = 0;
}
SplashXPath::SplashXPath(SplashPath *path, SplashCoord flatness,
GBool closeSubpaths) {
SplashCoord xc, yc, dx, dy, r, x0, y0, x1, y1;
int quad0, quad1, quad;
int i, curSubpath;
GBool last;
segs = NULL;
length = size = 0;
i = 0;
curSubpath = 0;
while (i < path->length) {
// first point in subpath - skip it
if (path->flags[i] & splashPathFirst) {
curSubpath = i;
++i;
} else {
// curve segment
if (path->flags[i] & splashPathCurve) {
addCurve(path->pts[i-1].x, path->pts[i-1].y,
path->pts[i ].x, path->pts[i ].y,
path->pts[i+1].x, path->pts[i+1].y,
path->pts[i+2].x, path->pts[i+2].y,
flatness,
(path->flags[i-1] & splashPathFirst),
(path->flags[i+2] & splashPathLast),
!closeSubpaths &&
(path->flags[i-1] & splashPathFirst) &&
!(path->flags[i-1] & splashPathClosed),
!closeSubpaths &&
(path->flags[i+2] & splashPathLast) &&
!(path->flags[i+2] & splashPathClosed));
i += 3;
// clockwise circular arc
} else if (path->flags[i] & splashPathArcCW) {
xc = path->pts[i].x;
yc = path->pts[i].y;
dx = path->pts[i+1].x - xc;
dy = path->pts[i+1].y - yc;
r = splashSqrt(dx * dx + dy * dy);
if (path->pts[i-1].x < xc && path->pts[i-1].y <= yc) {
quad0 = 0;
} else if (path->pts[i-1].x >= xc && path->pts[i-1].y < yc) {
quad0 = 1;
} else if (path->pts[i-1].x > xc && path->pts[i-1].y >= yc) {
quad0 = 2;
} else {
quad0 = 3;
}
if (path->pts[i+1].x <= xc && path->pts[i+1].y < yc) {
quad1 = 0;
} else if (path->pts[i+1].x > xc && path->pts[i+1].y <= yc) {
quad1 = 1;
} else if (path->pts[i+1].x >= xc && path->pts[i+1].y > yc) {
quad1 = 2;
} else {
quad1 = 3;
}
x0 = path->pts[i-1].x;
y0 = path->pts[i-1].y;
x1 = y1 = 0; // make gcc happy
quad = quad0;
while (1) {
switch (quad) {
case 0: x1 = xc; y1 = yc - r; break;
case 1: x1 = xc + r; y1 = yc; break;
case 2: x1 = xc; y1 = yc + r; break;
case 3: x1 = xc - r; y1 = yc; break;
}
last = gFalse;
if (quad == quad1) {
switch (quad) {
case 0:
case 1: last = path->pts[i+1].x > x0; break;
case 2:
case 3: last = path->pts[i+1].x < x0; break;
}
}
if (last) {
addArc(x0, y0, path->pts[i+1].x, path->pts[i+1].y,
xc, yc, r, quad, flatness,
quad == quad0 && (path->flags[i-1] & splashPathFirst),
(path->flags[i+1] & splashPathLast),
quad == quad0 && !closeSubpaths &&
(path->flags[i-1] & splashPathFirst) &&
!(path->flags[i-1] & splashPathClosed),
!closeSubpaths &&
(path->flags[i+1] & splashPathLast) &&
!(path->flags[i+1] & splashPathClosed));
break;
} else {
addArc(x0, y0, x1, y1,
xc, yc, r, quad, flatness,
quad == quad0 && (path->flags[i-1] & splashPathFirst),
gFalse,
quad == quad0 && !closeSubpaths &&
(path->flags[i-1] & splashPathFirst) &&
!(path->flags[i-1] & splashPathClosed),
gFalse);
x0 = x1;
y0 = y1;
quad = (quad + 1) & 3;
}
}
i += 2;
// line segment
} else {
addSegment(path->pts[i-1].x, path->pts[i-1].y,
path->pts[i].x, path->pts[i].y,
path->flags[i-1] & splashPathFirst,
path->flags[i] & splashPathLast,
!closeSubpaths &&
(path->flags[i-1] & splashPathFirst) &&
!(path->flags[i-1] & splashPathClosed),
!closeSubpaths &&
(path->flags[i] & splashPathLast) &&
!(path->flags[i] & splashPathClosed));
++i;
}
// close a subpath
if (closeSubpaths &&
(path->flags[i-1] & splashPathLast) &&
(path->pts[i-1].x != path->pts[curSubpath].x ||
path->pts[i-1].y != path->pts[curSubpath]. y)) {
addSegment(path->pts[i-1].x, path->pts[i-1].y,
path->pts[curSubpath].x, path->pts[curSubpath].y,
gFalse, gTrue, gFalse, gFalse);
}
}
}
}
SplashXPath::SplashXPath(SplashXPath *xPath) {
length = xPath->length;
size = xPath->size;
segs = (SplashXPathSeg *)gmalloc(size * sizeof(SplashXPathSeg));
memcpy(segs, xPath->segs, length * sizeof(SplashXPathSeg));
}
SplashXPath::~SplashXPath() {
gfree(segs);
}
// Add space for <nSegs> more segments
void SplashXPath::grow(int nSegs) {
if (length + nSegs > size) {
if (size == 0) {
size = 32;
}
while (size < length + nSegs) {
size *= 2;
}
segs = (SplashXPathSeg *)grealloc(segs, size * sizeof(SplashXPathSeg));
}
}
void SplashXPath::addCurve(SplashCoord x0, SplashCoord y0,
SplashCoord x1, SplashCoord y1,
SplashCoord x2, SplashCoord y2,
SplashCoord x3, SplashCoord y3,
SplashCoord flatness,
GBool first, GBool last, GBool end0, GBool end1) {
SplashCoord cx[maxCurveSplits + 1][3];
SplashCoord cy[maxCurveSplits + 1][3];
int cNext[maxCurveSplits + 1];
SplashCoord xl0, xl1, xl2, xr0, xr1, xr2, xr3, xx1, xx2, xh;
SplashCoord yl0, yl1, yl2, yr0, yr1, yr2, yr3, yy1, yy2, yh;
SplashCoord dx, dy, mx, my, d1, d2, flatness2;
int p1, p2, p3;
flatness2 = flatness * flatness;
// initial segment
p1 = 0;
p2 = maxCurveSplits;
cx[p1][0] = x0; cy[p1][0] = y0;
cx[p1][1] = x1; cy[p1][1] = y1;
cx[p1][2] = x2; cy[p1][2] = y2;
cx[p2][0] = x3; cy[p2][0] = y3;
cNext[p1] = p2;
while (p1 < maxCurveSplits) {
// get the next segment
xl0 = cx[p1][0]; yl0 = cy[p1][0];
xx1 = cx[p1][1]; yy1 = cy[p1][1];
xx2 = cx[p1][2]; yy2 = cy[p1][2];
p2 = cNext[p1];
xr3 = cx[p2][0]; yr3 = cy[p2][0];
// compute the distances from the control points to the
// midpoint of the straight line (this is a bit of a hack, but
// it's much faster than computing the actual distances to the
// line)
mx = (xl0 + xr3) * 0.5;
my = (yl0 + yr3) * 0.5;
dx = xx1 - mx;
dy = yy1 - my;
d1 = dx*dx + dy*dy;
dx = xx2 - mx;
dy = yy2 - my;
d2 = dx*dx + dy*dy;
// if the curve is flat enough, or no more subdivisions are
// allowed, add the straight line segment
if (p2 - p1 == 1 || (d1 <= flatness2 && d2 <= flatness2)) {
addSegment(xl0, yl0, xr3, yr3,
p1 == 0 && first,
p2 == maxCurveSplits && last,
p1 == 0 && end0,
p2 == maxCurveSplits && end1);
p1 = p2;
// otherwise, subdivide the curve
} else {
xl1 = (xl0 + xx1) * 0.5;
yl1 = (yl0 + yy1) * 0.5;
xh = (xx1 + xx2) * 0.5;
yh = (yy1 + yy2) * 0.5;
xl2 = (xl1 + xh) * 0.5;
yl2 = (yl1 + yh) * 0.5;
xr2 = (xx2 + xr3) * 0.5;
yr2 = (yy2 + yr3) * 0.5;
xr1 = (xh + xr2) * 0.5;
yr1 = (yh + yr2) * 0.5;
xr0 = (xl2 + xr1) * 0.5;
yr0 = (yl2 + yr1) * 0.5;
// add the new subdivision points
p3 = (p1 + p2) / 2;
cx[p1][1] = xl1; cy[p1][1] = yl1;
cx[p1][2] = xl2; cy[p1][2] = yl2;
cNext[p1] = p3;
cx[p3][0] = xr0; cy[p3][0] = yr0;
cx[p3][1] = xr1; cy[p3][1] = yr1;
cx[p3][2] = xr2; cy[p3][2] = yr2;
cNext[p3] = p2;
}
}
}
void SplashXPath::addArc(SplashCoord x0, SplashCoord y0,
SplashCoord x1, SplashCoord y1,
SplashCoord xc, SplashCoord yc,
SplashCoord r, int quad,
SplashCoord flatness,
GBool first, GBool last, GBool end0, GBool end1) {
SplashCoord px[maxCurveSplits + 1];
SplashCoord py[maxCurveSplits + 1];
int pNext[maxCurveSplits + 1];
SplashCoord r2, flatness2;
SplashCoord xx0, yy0, xx1, yy1, xm, ym, t, dx, dy;
int p1, p2, p3;
r2 = r * r;
flatness2 = flatness * flatness;
// initial segment
p1 = 0;
p2 = maxCurveSplits;
px[p1] = x0; py[p1] = y0;
px[p2] = x1; py[p2] = y1;
pNext[p1] = p2;
while (p1 < maxCurveSplits) {
// get the next segment
xx0 = px[p1]; yy0 = py[p1];
p2 = pNext[p1];
xx1 = px[p2]; yy1 = py[p2];
// compute the arc midpoint
t = (xx0 - xc) * (xx1 - xc) - (yy0 - yc) * (yy1 - yc);
xm = splashSqrt(0.5 * (r2 + t));
ym = splashSqrt(0.5 * (r2 - t));
switch (quad) {
case 0: xm = xc - xm; ym = yc - ym; break;
case 1: xm = xc + xm; ym = yc - ym; break;
case 2: xm = xc + xm; ym = yc + ym; break;
case 3: xm = xc - xm; ym = yc + ym; break;
}
// compute distance from midpoint of straight segment to midpoint
// of arc
dx = 0.5 * (xx0 + xx1) - xm;
dy = 0.5 * (yy0 + yy1) - ym;
// if the arc is flat enough, or no more subdivisions are allowed,
// add the straight line segment
if (p2 - p1 == 1 || dx * dx + dy * dy <= flatness2) {
addSegment(xx0, yy0, xx1, yy1,
p1 == 0 && first,
p2 == maxCurveSplits && last,
p1 == 0 && end0,
p2 == maxCurveSplits && end1);
p1 = p2;
// otherwise, subdivide the arc
} else {
p3 = (p1 + p2) / 2;
px[p3] = xm;
py[p3] = ym;
pNext[p1] = p3;
pNext[p3] = p2;
}
}
}
void SplashXPath::addSegment(SplashCoord x0, SplashCoord y0,
SplashCoord x1, SplashCoord y1,
GBool first, GBool last, GBool end0, GBool end1) {
grow(1);
segs[length].x0 = x0;
segs[length].y0 = y0;
segs[length].x1 = x1;
segs[length].y1 = y1;
segs[length].flags = 0;
if (first) {
segs[length].flags |= splashXPathFirst;
}
if (last) {
segs[length].flags |= splashXPathLast;
}
if (end0) {
segs[length].flags |= splashXPathEnd0;
}
if (end1) {
segs[length].flags |= splashXPathEnd1;
}
if (y1 == y0) {
segs[length].dxdy = segs[length].dydx = 0;
segs[length].flags |= splashXPathHoriz;
if (x1 == x0) {
segs[length].flags |= splashXPathVert;
}
} else if (x1 == x0) {
segs[length].dxdy = segs[length].dydx = 0;
segs[length].flags |= splashXPathVert;
} else {
segs[length].dxdy = (x1 - x0) / (y1 - y0);
segs[length].dydx = 1 / segs[length].dxdy;
}
if (y0 > y1) {
segs[length].flags |= splashXPathFlip;
}
++length;
}
static int cmpXPathSegs(const void *arg0, const void *arg1) {
SplashXPathSeg *seg0 = (SplashXPathSeg *)arg0;
SplashXPathSeg *seg1 = (SplashXPathSeg *)arg1;
SplashCoord x0, y0, x1, y1;
if (seg0->flags & splashXPathFlip) {
x0 = seg0->x1;
y0 = seg0->y1;
} else {
x0 = seg0->x0;
y0 = seg0->y0;
}
if (seg1->flags & splashXPathFlip) {
x1 = seg1->x1;
y1 = seg1->y1;
} else {
x1 = seg1->x0;
y1 = seg1->y0;
}
if (y0 != y1) {
return (y0 > y1) ? 1 : -1;
}
if (x0 != x1) {
return (x0 > x1) ? 1 : -1;
}
return 0;
}
void SplashXPath::sort() {
qsort(segs, length, sizeof(SplashXPathSeg), &cmpXPathSegs);
}

92
splash/SplashXPath.h Normal file
View file

@ -0,0 +1,92 @@
//========================================================================
//
// SplashXPath.h
//
//========================================================================
#ifndef SPLASHXPATH_H
#define SPLASHXPATH_H
#include <aconf.h>
#ifdef USE_GCC_PRAGMAS
#pragma interface
#endif
#include "SplashTypes.h"
class SplashPath;
//------------------------------------------------------------------------
// SplashXPathSeg
//------------------------------------------------------------------------
struct SplashXPathSeg {
SplashCoord x0, y0; // first endpoint
SplashCoord x1, y1; // second endpoint
SplashCoord dxdy; // slope: delta-x / delta-y
SplashCoord dydx; // slope: delta-y / delta-x
Guint flags;
};
#define splashXPathFirst 0x01 // first segment of a subpath
#define splashXPathLast 0x02 // last segment of a subpath
#define splashXPathEnd0 0x04 // first endpoint is end of an open subpath
#define splashXPathEnd1 0x08 // second endpoint is end of an open subpath
#define splashXPathHoriz 0x10 // segment is vertical (y0 == y1)
// (dxdy is undef)
#define splashXPathVert 0x20 // segment is horizontal (x0 == x1)
// (dydx is undef)
#define splashXPathFlip 0x40 // y0 > y1
//------------------------------------------------------------------------
// SplashXPath
//------------------------------------------------------------------------
class SplashXPath {
public:
// Expands (converts to segments) and flattens (converts curves to
// lines) <path>. If <closeSubpaths> is true, closes all open
// subpaths.
SplashXPath(SplashPath *path, SplashCoord flatness,
GBool closeSubpaths);
// Copy an expanded path.
SplashXPath *copy() { return new SplashXPath(this); }
~SplashXPath();
// Sort by upper coordinate (lower y), in y-major order.
void sort();
private:
SplashXPath();
SplashXPath(SplashXPath *xPath);
void grow(int nSegs);
void addCurve(SplashCoord x0, SplashCoord y0,
SplashCoord x1, SplashCoord y1,
SplashCoord x2, SplashCoord y2,
SplashCoord x3, SplashCoord y3,
SplashCoord flatness,
GBool first, GBool last, GBool end0, GBool end1);
void addArc(SplashCoord x0, SplashCoord y0,
SplashCoord x1, SplashCoord y1,
SplashCoord xc, SplashCoord yc,
SplashCoord r, int quad,
SplashCoord flatness,
GBool first, GBool last, GBool end0, GBool end1);
void addSegment(SplashCoord x0, SplashCoord y0,
SplashCoord x1, SplashCoord y1,
GBool first, GBool last, GBool end0, GBool end1);
SplashXPathSeg *segs;
int length, size; // length and size of segs array
friend class SplashXPathScanner;
friend class SplashClip;
friend class Splash;
};
#endif

View file

@ -0,0 +1,271 @@
//========================================================================
//
// SplashXPathScanner.cc
//
//========================================================================
#include <aconf.h>
#ifdef USE_GCC_PRAGMAS
#pragma implementation
#endif
#include <stdlib.h>
#include "gmem.h"
#include "SplashMath.h"
#include "SplashXPath.h"
#include "SplashXPathScanner.h"
//------------------------------------------------------------------------
struct SplashIntersect {
int x0, x1; // intersection of segment with [y, y+1)
int count; // EO/NZWN counter increment
};
static int cmpIntersect(const void *p0, const void *p1) {
return ((SplashIntersect *)p0)->x0 - ((SplashIntersect *)p1)->x0;
}
//------------------------------------------------------------------------
// SplashXPathScanner
//------------------------------------------------------------------------
SplashXPathScanner::SplashXPathScanner(SplashXPath *xPathA, GBool eoA) {
SplashXPathSeg *seg;
SplashCoord xMinFP, yMinFP, xMaxFP, yMaxFP;
int i;
xPath = xPathA;
eo = eoA;
// compute the bbox
seg = &xPath->segs[0];
if (seg->x0 <= seg->x1) {
xMinFP = seg->x0;
xMaxFP = seg->x1;
} else {
xMinFP = seg->x1;
xMaxFP = seg->x0;
}
if (seg->flags & splashXPathFlip) {
yMinFP = seg->y1;
yMaxFP = seg->y0;
} else {
yMinFP = seg->y0;
yMaxFP = seg->y1;
}
for (i = 1; i < xPath->length; ++i) {
seg = &xPath->segs[i];
if (seg->x0 < xMinFP) {
xMinFP = seg->x0;
} else if (seg->x0 > xMaxFP) {
xMaxFP = seg->x0;
}
if (seg->x1 < xMinFP) {
xMinFP = seg->x1;
} else if (seg->x1 > xMaxFP) {
xMaxFP = seg->x1;
}
if (seg->flags & splashXPathFlip) {
if (seg->y0 > yMaxFP) {
yMaxFP = seg->y0;
}
} else {
if (seg->y1 > yMaxFP) {
yMaxFP = seg->y1;
}
}
}
xMin = splashFloor(xMinFP);
xMax = splashFloor(xMaxFP);
yMin = splashFloor(yMinFP);
yMax = splashFloor(yMaxFP);
interY = 0;
xPathIdx = 0;
inter = NULL;
interLen = interSize = 0;
computeIntersections(yMin);
}
SplashXPathScanner::~SplashXPathScanner() {
gfree(inter);
}
void SplashXPathScanner::getSpanBounds(int y, int *spanXMin, int *spanXMax) {
if (interY != y) {
computeIntersections(y);
}
if (interLen > 0) {
*spanXMin = inter[0].x0;
*spanXMax = inter[interLen - 1].x1;
} else {
*spanXMin = xMax + 1;
*spanXMax = xMax;
}
}
GBool SplashXPathScanner::test(int x, int y) {
int count, i;
if (interY != y) {
computeIntersections(y);
}
count = 0;
for (i = 0; i < interLen && inter[i].x0 <= x; ++i) {
if (x <= inter[i].x1) {
return gTrue;
}
count += inter[i].count;
}
return eo ? (count & 1) : (count != 0);
}
GBool SplashXPathScanner::testSpan(int x0, int x1, int y) {
int count, xx1, i;
if (interY != y) {
computeIntersections(y);
}
count = 0;
for (i = 0; i < interLen && inter[i].x1 < x0; ++i) {
count += inter[i].count;
}
// invariant: the subspan [x0,xx1] is inside the path
xx1 = x0 - 1;
while (xx1 < x1) {
if (i >= interLen) {
return gFalse;
}
if (inter[i].x0 > xx1 + 1 &&
!(eo ? (count & 1) : (count != 0))) {
return gFalse;
}
if (inter[i].x1 > xx1) {
xx1 = inter[i].x1;
}
count += inter[i].count;
++i;
}
return gTrue;
}
GBool SplashXPathScanner::getNextSpan(int y, int *x0, int *x1) {
int xx0, xx1;
if (interY != y) {
computeIntersections(y);
}
if (interIdx >= interLen) {
return gFalse;
}
xx0 = inter[interIdx].x0;
xx1 = inter[interIdx].x1;
interCount += inter[interIdx].count;
++interIdx;
while (interIdx < interLen &&
(inter[interIdx].x0 <= xx1 ||
(eo ? (interCount & 1) : (interCount != 0)))) {
if (inter[interIdx].x1 > xx1) {
xx1 = inter[interIdx].x1;
}
interCount += inter[interIdx].count;
++interIdx;
}
*x0 = xx0;
*x1 = xx1;
return gTrue;
}
void SplashXPathScanner::computeIntersections(int y) {
SplashCoord ySegMin, ySegMax, xx0, xx1;
SplashXPathSeg *seg;
int i, j;
// find the first segment that intersects [y, y+1)
i = (y >= interY) ? xPathIdx : 0;
while (i < xPath->length &&
xPath->segs[i].y0 < y && xPath->segs[i].y1 < y) {
++i;
}
xPathIdx = i;
// find all of the segments that intersect [y, y+1) and create an
// Intersect element for each one
interLen = 0;
for (j = i; j < xPath->length; ++j) {
seg = &xPath->segs[j];
if (seg->flags & splashXPathFlip) {
ySegMin = seg->y1;
ySegMax = seg->y0;
} else {
ySegMin = seg->y0;
ySegMax = seg->y1;
}
// ensure that: ySegMin < y+1
// y <= ySegMax
if (ySegMin >= y + 1) {
break;
}
if (ySegMax < y) {
continue;
}
if (interLen == interSize) {
if (interSize == 0) {
interSize = 16;
} else {
interSize *= 2;
}
inter = (SplashIntersect *)grealloc(inter,
interSize * sizeof(SplashIntersect));
}
if (seg->flags & splashXPathHoriz) {
xx0 = seg->x0;
xx1 = seg->x1;
} else if (seg->flags & splashXPathVert) {
xx0 = xx1 = seg->x0;
} else {
if (ySegMin <= y) {
// intersection with top edge
xx0 = seg->x0 + (y - seg->y0) * seg->dxdy;
} else {
// x coord of segment endpoint with min y coord
xx0 = (seg->flags & splashXPathFlip) ? seg->x1 : seg->x0;
}
if (ySegMax >= y + 1) {
// intersection with bottom edge
xx1 = seg->x0 + (y + 1 - seg->y0) * seg->dxdy;
} else {
// x coord of segment endpoint with max y coord
xx1 = (seg->flags & splashXPathFlip) ? seg->x0 : seg->x1;
}
}
if (xx0 < xx1) {
inter[interLen].x0 = splashFloor(xx0);
inter[interLen].x1 = splashFloor(xx1);
} else {
inter[interLen].x0 = splashFloor(xx1);
inter[interLen].x1 = splashFloor(xx0);
}
if (ySegMin <= y && y < ySegMax && !(seg->flags & splashXPathHoriz)) {
inter[interLen].count = eo ? 1
: (seg->flags & splashXPathFlip) ? 1 : -1;
} else {
inter[interLen].count = 0;
}
++interLen;
}
qsort(inter, interLen, sizeof(SplashIntersect), &cmpIntersect);
interY = y;
interIdx = 0;
interCount = 0;
}

View file

@ -0,0 +1,74 @@
//========================================================================
//
// SplashXPathScanner.h
//
//========================================================================
#ifndef SPLASHXPATHSCANNER_H
#define SPLASHXPATHSCANNER_H
#include <aconf.h>
#ifdef USE_GCC_PRAGMAS
#pragma interface
#endif
#include "SplashTypes.h"
class SplashXPath;
struct SplashIntersect;
//------------------------------------------------------------------------
// SplashXPathScanner
//------------------------------------------------------------------------
class SplashXPathScanner {
public:
// Create a new SplashXPathScanner object. <xPathA> must be sorted.
SplashXPathScanner(SplashXPath *xPathA, GBool eoA);
~SplashXPathScanner();
// Return the path's bounding box.
void getBBox(int *xMinA, int *yMinA, int *xMaxA, int *yMaxA)
{ *xMinA = xMin; *yMinA = yMin; *xMaxA = xMax; *yMaxA = yMax; }
// Return the min/max x values for the span at <y>.
void getSpanBounds(int y, int *spanXMin, int *spanXMax);
// Returns true if (<x>,<y>) is inside the path.
GBool test(int x, int y);
// Returns true if the entire span ([<x0>,<x1>], <y>) is inside the
// path.
GBool testSpan(int x0, int x1, int y);
// Returns the next span inside the path at <y>. If <y> is
// different than the previous call to getNextSpan, this returns the
// first span at <y>; otherwise it returns the next span (relative
// to the previous call to getNextSpan). Returns false if there are
// no more spans at <y>.
GBool getNextSpan(int y, int *x0, int *x1);
private:
void computeIntersections(int y);
SplashXPath *xPath;
GBool eo;
int xMin, yMin, xMax, yMax;
int interY; // current y value
int interIdx; // current index into <inter> - used by
// getNextSpan
int interCount; // current EO/NZWN counter - used by
// getNextSpan
int xPathIdx; // current index into <xPath> - used by
// computeIntersections
SplashIntersect *inter; // intersections array for <interY>
int interLen; // number of intersections in <inter>
int interSize; // size of the <inter> array
};
#endif

View file

@ -1,15 +1,14 @@
INCLUDES = -I.. -I$(srcdir)/../fofi -I$(srcdir)/../goo $(all_includes) $(LIBFREETYPE_CFLAGS)
INCLUDES = -I.. -I$(srcdir)/../fofi -I$(srcdir)/../splash -I$(srcdir)/../goo $(all_includes) $(LIBFREETYPE_CFLAGS)
libxpdf_la_LDFLAGS = $(all_libraries)
libxpdf_la_LIBADD = $(LIB_X11) $(LIBFREETYPE_LIBS) $(LIBPAPER_LIBS) ../goo/libgoo.la ../fofi/libfofi.la
libxpdf_la_LIBADD = $(LIB_X11) $(LIBFREETYPE_LIBS) $(LIBPAPER_LIBS) ../goo/libgoo.la ../fofi/libfofi.la ../splash/libsplash.la
libxpdf_la_SOURCES = Annot.cc Array.cc BuiltinFont.cc BuiltinFontTables.cc \
Catalog.cc CharCodeToUnicode.cc CMap.cc Decrypt.cc Dict.cc Error.cc \
FontEncodingTables.cc Function.cc Gfx.cc \
GfxFont.cc GfxState.cc GlobalParams.cc JArithmeticDecoder.cc \
JBIG2Stream.cc Lexer.cc Link.cc NameToCharCode.cc Object.cc Outline.cc \
OutputDev.cc PDFDoc.cc PDFDocEncoding.cc PSTokenizer.cc \
Page.cc Parser.cc Stream.cc JPXStream.cc \
Page.cc Parser.cc SplashOutputDev.cc Stream.cc JPXStream.cc \
TextOutputDev.cc UnicodeMap.cc UnicodeTypeTable.cc XRef.cc
libxpdf_la_COMPILE_FIRST = ../aconf.h
noinst_LTLIBRARIES = libxpdf.la

1345
xpdf/SplashOutputDev.cc Normal file

File diff suppressed because it is too large Load diff

195
xpdf/SplashOutputDev.h Normal file
View file

@ -0,0 +1,195 @@
//========================================================================
//
// SplashOutputDev.h
//
// Copyright 2003 Glyph & Cog, LLC
//
//========================================================================
#ifndef SPLASHOUTPUTDEV_H
#define SPLASHOUTPUTDEV_H
#include <aconf.h>
#ifdef USE_GCC_PRAGMAS
#pragma interface
#endif
#include "gtypes.h"
#include "SplashTypes.h"
#include "config.h"
#include "OutputDev.h"
class GfxState;
class GfxPath;
class Gfx8BitFont;
class SplashBitmap;
class Splash;
class SplashPath;
class SplashPattern;
class SplashFontEngine;
class SplashFont;
class T3FontCache;
struct T3FontCacheTag;
struct T3GlyphStack;
struct GfxRGB;
//------------------------------------------------------------------------
// number of Type 3 fonts to cache
#define splashOutT3FontCacheSize 8
//------------------------------------------------------------------------
// SplashOutputDev
//------------------------------------------------------------------------
class SplashOutputDev: public OutputDev {
public:
// Constructor.
SplashOutputDev(SplashColorMode colorModeA, GBool reverseVideoA,
SplashColor paperColorA);
// Destructor.
virtual ~SplashOutputDev();
//----- get info about output device
// Does this device use upside-down coordinates?
// (Upside-down means (0,0) is the top left corner of the page.)
virtual GBool upsideDown() { return gTrue; }
// Does this device use drawChar() or drawString()?
virtual GBool useDrawChar() { return gTrue; }
// Does this device use beginType3Char/endType3Char? Otherwise,
// text in Type 3 fonts will be drawn with drawChar/drawString.
virtual GBool interpretType3Chars() { return gTrue; }
//----- initialization and control
// Start a page.
virtual void startPage(int pageNum, GfxState *state);
// End a page.
virtual void endPage();
//----- link borders
virtual void drawLink(Link *link, Catalog *catalog);
//----- save/restore graphics state
virtual void saveState(GfxState *state);
virtual void restoreState(GfxState *state);
//----- update graphics state
virtual void updateAll(GfxState *state);
virtual void updateCTM(GfxState *state, double m11, double m12,
double m21, double m22, double m31, double m32);
virtual void updateLineDash(GfxState *state);
virtual void updateFlatness(GfxState *state);
virtual void updateLineJoin(GfxState *state);
virtual void updateLineCap(GfxState *state);
virtual void updateMiterLimit(GfxState *state);
virtual void updateLineWidth(GfxState *state);
virtual void updateFillColor(GfxState *state);
virtual void updateStrokeColor(GfxState *state);
//----- update text state
virtual void updateFont(GfxState *state);
//----- path painting
virtual void stroke(GfxState *state);
virtual void fill(GfxState *state);
virtual void eoFill(GfxState *state);
//----- path clipping
virtual void clip(GfxState *state);
virtual void eoClip(GfxState *state);
//----- text drawing
virtual void drawChar(GfxState *state, double x, double y,
double dx, double dy,
double originX, double originY,
CharCode code, Unicode *u, int uLen);
virtual GBool beginType3Char(GfxState *state, double x, double y,
double dx, double dy,
CharCode code, Unicode *u, int uLen);
virtual void endType3Char(GfxState *state);
virtual void endTextObject(GfxState *state);
//----- image drawing
virtual void drawImageMask(GfxState *state, Object *ref, Stream *str,
int width, int height, GBool invert,
GBool inlineImg);
virtual void drawImage(GfxState *state, Object *ref, Stream *str,
int width, int height, GfxImageColorMap *colorMap,
int *maskColors, GBool inlineImg);
//----- Type 3 font operators
virtual void type3D0(GfxState *state, double wx, double wy);
virtual void type3D1(GfxState *state, double wx, double wy,
double llx, double lly, double urx, double ury);
//----- special access
// Called to indicate that a new PDF document has been loaded.
void startDoc(XRef *xrefA);
GBool isReverseVideo() { return reverseVideo; }
// Get the bitmap and its size.
SplashBitmap *getBitmap() { return bitmap; }
int getBitmapWidth();
int getBitmapHeight();
// Get the Splash object.
Splash *getSplash() { return splash; }
// XOR a rectangular region in the bitmap with <pattern>. <pattern>
// is passed to Splash::setFillPattern, so it should not be used
// after calling this function.
void xorRectangle(int x0, int y0, int x1, int y1, SplashPattern *pattern);
// Set the Splash fill color.
void setFillColor(int r, int g, int b);
// Get a font object for a Base-14 font, using the Latin-1 encoding.
SplashFont *getFont(GString *name, double *mat);
void setUnderlayCbk(void (*cbk)(void *data), void *data)
{ underlayCbk = cbk; underlayCbkData = data; }
private:
SplashPattern *getColor(double gray, GfxRGB *rgb);
SplashPath *convertPath(GfxState *state, GfxPath *path);
void drawType3Glyph(T3FontCache *t3Font,
T3FontCacheTag *tag, Guchar *data,
double x, double y);
static GBool imageMaskSrc(void *data, SplashMono1 *pixel);
static GBool imageSrc(void *data, SplashColor *pixel, Guchar *alpha);
SplashColorMode colorMode;
GBool reverseVideo; // reverse video mode
SplashColor paperColor; // paper color
XRef *xref; // xref table for current document
SplashBitmap *bitmap;
Splash *splash;
SplashFontEngine *fontEngine;
T3FontCache * // Type 3 font cache
t3FontCache[splashOutT3FontCacheSize];
int nT3Fonts; // number of valid entries in t3FontCache
T3GlyphStack *t3GlyphStack; // Type 3 glyph context stack
SplashFont *font; // current font
GBool needFontUpdate; // set when the font needs to be updated
SplashPath *textClipPath; // clipping path built with text object
void (*underlayCbk)(void *data);
void *underlayCbkData;
};
#endif