mirror of
https://invent.kde.org/graphics/okular
synced 2024-08-24 18:35:37 +00:00
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:
parent
ee86e7f46b
commit
264b6249ab
|
@ -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
|
||||
|
||||
|
|
|
@ -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
4
aconf.h
Normal file
|
@ -0,0 +1,4 @@
|
|||
#include "../config.h"
|
||||
|
||||
#define HAVE_FREETYPE_H HAVE_FREETYPE
|
||||
#define HAVE_FREETYPE_FREETYPE_H HAVE_FREETYPE
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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
9
splash/Makefile.am
Normal 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
1648
splash/Splash.cc
Normal file
File diff suppressed because it is too large
Load diff
176
splash/Splash.h
Normal file
176
splash/Splash.h
Normal 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
134
splash/SplashBitmap.cc
Normal 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
48
splash/SplashBitmap.h
Normal 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
270
splash/SplashClip.cc
Normal 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
88
splash/SplashClip.h
Normal 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
32
splash/SplashErrorCodes.h
Normal 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
288
splash/SplashFTFont.cc
Normal 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
54
splash/SplashFTFont.h
Normal 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
|
133
splash/SplashFTFontEngine.cc
Normal file
133
splash/SplashFTFontEngine.cc
Normal 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
|
60
splash/SplashFTFontEngine.h
Normal file
60
splash/SplashFTFontEngine.h
Normal 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
111
splash/SplashFTFontFile.cc
Normal 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
70
splash/SplashFTFontFile.h
Normal 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
166
splash/SplashFont.cc
Normal 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
89
splash/SplashFont.h
Normal 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
245
splash/SplashFontEngine.cc
Normal 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
85
splash/SplashFontEngine.h
Normal 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
55
splash/SplashFontFile.cc
Normal 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
60
splash/SplashFontFile.h
Normal 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
|
23
splash/SplashFontFileID.cc
Normal file
23
splash/SplashFontFileID.cc
Normal 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
30
splash/SplashFontFileID.h
Normal 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
|
26
splash/SplashGlyphBitmap.h
Normal file
26
splash/SplashGlyphBitmap.h
Normal 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
46
splash/SplashMath.h
Normal 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
177
splash/SplashPath.cc
Normal 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
107
splash/SplashPath.h
Normal 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
64
splash/SplashPattern.cc
Normal 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
81
splash/SplashPattern.h
Normal 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
107
splash/SplashScreen.cc
Normal 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
40
splash/SplashScreen.h
Normal 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
99
splash/SplashState.cc
Normal 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
88
splash/SplashState.h
Normal 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
251
splash/SplashT1Font.cc
Normal 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
51
splash/SplashT1Font.h
Normal 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
|
124
splash/SplashT1FontEngine.cc
Normal file
124
splash/SplashT1FontEngine.cc
Normal 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
|
53
splash/SplashT1FontEngine.h
Normal file
53
splash/SplashT1FontEngine.h
Normal 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
|
96
splash/SplashT1FontFile.cc
Normal file
96
splash/SplashT1FontFile.cc
Normal 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
57
splash/SplashT1FontFile.h
Normal 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
77
splash/SplashTypes.h
Normal 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
417
splash/SplashXPath.cc
Normal 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
92
splash/SplashXPath.h
Normal 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
|
271
splash/SplashXPathScanner.cc
Normal file
271
splash/SplashXPathScanner.cc
Normal 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;
|
||||
}
|
74
splash/SplashXPathScanner.h
Normal file
74
splash/SplashXPathScanner.h
Normal 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
|
|
@ -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
1345
xpdf/SplashOutputDev.cc
Normal file
File diff suppressed because it is too large
Load diff
195
xpdf/SplashOutputDev.h
Normal file
195
xpdf/SplashOutputDev.h
Normal 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
|
Loading…
Reference in a new issue