[poppler] poppler/poppler: ArthurOutputDev.cc, NONE,
1.1 ArthurOutputDev.h, NONE, 1.1 Makefile.am, 1.8, 1.9
Brad Hards
bradh at freedesktop.org
Tue Jun 28 03:00:11 PDT 2005
- Previous message: [poppler] poppler/qt4: Makefile.am,NONE,1.1
- Next message: [poppler] poppler/qt4/src: Doxyfile, NONE, 1.1 Makefile.am, NONE,
1.1 poppler-document.cc, NONE, 1.1 poppler-page.cc, NONE,
1.1 poppler-private.h, NONE, 1.1 poppler-qt4.h, NONE, 1.1
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
Update of /cvs/poppler/poppler/poppler
In directory gabe:/tmp/cvs-serv23886/poppler
Modified Files:
Makefile.am
Added Files:
ArthurOutputDev.cc ArthurOutputDev.h
Log Message:
Initial import of Qt4 bindings, and for a Qt4 "Arthur" (QPainter)
backend renderer.
The bindings are currently unstable - you can expect substantial change
in both source and binary interfaces.
The Arthur renderer currently does a reasonable job of rendering path
and fill, but the image rendering doesn't work (for reasons that aren't
clear to me) and text rendering doesn't use the right glyphs - it just
draws with the current font. There is a lot of work to do on this
too. Help is, of coure, welcome.
--- NEW FILE: ArthurOutputDev.cc ---
//========================================================================
//
// ArthurOutputDev.cc
//
// Copyright 2003 Glyph & Cog, LLC
// Copyright 2004 Red Hat, Inc
//
//========================================================================
#include <config.h>
#ifdef USE_GCC_PRAGMAS
#pragma implementation
#endif
#include <string.h>
#include <math.h>
#include "goo/gfile.h"
#include "GlobalParams.h"
#include "Error.h"
#include "Object.h"
#include "GfxState.h"
#include "GfxFont.h"
#include "Link.h"
#include "CharCodeToUnicode.h"
#include "FontEncodingTables.h"
#include <fofi/FoFiTrueType.h>
#include "ArthurOutputDev.h"
#include <QtCore/QtDebug>
#include <QtGui/QPainterPath>
//------------------------------------------------------------------------
//------------------------------------------------------------------------
// ArthurOutputDev
//------------------------------------------------------------------------
ArthurOutputDev::ArthurOutputDev(QPainter *painter):
m_painter(painter)
{
m_currentBrush = QBrush(Qt::SolidPattern);
}
ArthurOutputDev::~ArthurOutputDev()
{
}
void ArthurOutputDev::startDoc(XRef *xrefA) {
}
void ArthurOutputDev::startPage(int pageNum, GfxState *state)
{
}
void ArthurOutputDev::endPage() {
}
void ArthurOutputDev::drawLink(Link *link, Catalog *catalog)
{
}
void ArthurOutputDev::saveState(GfxState *state)
{
m_painter->save();
}
void ArthurOutputDev::restoreState(GfxState *state)
{
m_painter->restore();
}
void ArthurOutputDev::updateAll(GfxState *state)
{
qDebug() << "updateAll";
}
void ArthurOutputDev::updateCTM(GfxState *state, double m11, double m12,
double m21, double m22,
double m31, double m32)
{
qDebug() << "updateCTM";
}
void ArthurOutputDev::updateLineDash(GfxState *state)
{
qDebug() << "updateLineDash";
}
void ArthurOutputDev::updateFlatness(GfxState *state)
{
qDebug() << "updateFlatness";
}
void ArthurOutputDev::updateLineJoin(GfxState *state)
{
switch (state->getLineJoin()) {
case 0:
m_currentPen.setJoinStyle(Qt::MiterJoin);
break;
case 1:
m_currentPen.setJoinStyle(Qt::RoundJoin);
break;
case 2:
m_currentPen.setJoinStyle(Qt::BevelJoin);
break;
}
m_painter->setPen(m_currentPen);
}
void ArthurOutputDev::updateLineCap(GfxState *state)
{
switch (state->getLineCap()) {
case 0:
m_currentPen.setCapStyle(Qt::FlatCap);
break;
case 1:
m_currentPen.setCapStyle(Qt::RoundCap);
break;
case 2:
m_currentPen.setCapStyle(Qt::SquareCap);
break;
}
m_painter->setPen(m_currentPen);
}
void ArthurOutputDev::updateMiterLimit(GfxState *state)
{
#if 0
cairo_set_miter_limit (cairo, state->getMiterLimit());
#endif
}
void ArthurOutputDev::updateLineWidth(GfxState *state)
{
m_currentPen.setWidthF(state->getTransformedLineWidth());
m_painter->setPen(m_currentPen);
}
void ArthurOutputDev::updateFillColor(GfxState *state)
{
GfxRGB rgb;
QColor brushColour = m_currentBrush.color();
state->getFillRGB(&rgb);
brushColour.setRgbF(rgb.r, rgb.g, rgb.b, brushColour.alphaF());
m_currentBrush.setColor(brushColour);
m_painter->setBrush(m_currentBrush);
}
void ArthurOutputDev::updateStrokeColor(GfxState *state)
{
GfxRGB rgb;
QColor penColour = m_currentPen.color();
state->getStrokeRGB(&rgb);
penColour.setRgbF(rgb.r, rgb.g, rgb.b, penColour.alphaF());
m_currentPen.setColor(penColour);
m_painter->setPen(m_currentPen);
}
void ArthurOutputDev::updateFillOpacity(GfxState *state)
{
QColor brushColour= m_currentBrush.color();
brushColour.setAlphaF(state->getFillOpacity());
m_currentBrush.setColor(brushColour);
m_painter->setBrush(m_currentBrush);
}
void ArthurOutputDev::updateStrokeOpacity(GfxState *state)
{
QColor penColour= m_currentPen.color();
penColour.setAlphaF(state->getStrokeOpacity());
m_currentPen.setColor(penColour);
m_painter->setPen(m_currentPen);
}
void ArthurOutputDev::updateFont(GfxState *state)
{
// Something like
// currentFont.setPointSize( state->getFontSize() );
// m_painter->setFont(currentFont);
// but with transformation matrices and such...
#if 0
cairo_font_face_t *font_face;
double m11, m12, m21, m22;
double w;
cairo_matrix_t matrix;
LOG(printf ("updateFont() font=%s\n", state->getFont()->getName()->getCString()));
/* Needs to be rethough, since fonts are now handled by cairo */
needFontUpdate = gFalse;
currentFont = fontEngine->getFont (state->getFont(), xref);
state->getFontTransMat(&m11, &m12, &m21, &m22);
m11 *= state->getHorizScaling();
m12 *= state->getHorizScaling();
w = currentFont->getSubstitutionCorrection(state->getFont());
m12 *= w;
m22 *= w;
LOG(printf ("font matrix: %f %f %f %f\n", m11, m12, m21, m22));
font_face = currentFont->getFontFace();
cairo_set_font_face (cairo, font_face);
matrix.xx = m11;
matrix.xy = -m21;
matrix.yx = m12;
matrix.yy = -m22;
matrix.x0 = 0;
matrix.y0 = 0;
cairo_set_font_matrix (cairo, &matrix);
#endif
}
static QPainterPath convertPath(GfxState *state, GfxPath *path)
{
GfxSubpath *subpath;
double x1, y1, x2, y2, x3, y3;
int i, j;
QPainterPath qPath;
for (i = 0; i < path->getNumSubpaths(); ++i) {
subpath = path->getSubpath(i);
if (subpath->getNumPoints() > 0) {
state->transform(subpath->getX(0), subpath->getY(0), &x1, &y1);
qPath.moveTo(x1, y1);
j = 1;
while (j < subpath->getNumPoints()) {
if (subpath->getCurve(j)) {
state->transform(subpath->getX(j), subpath->getY(j), &x1, &y1);
state->transform(subpath->getX(j+1), subpath->getY(j+1), &x2, &y2);
state->transform(subpath->getX(j+2), subpath->getY(j+2), &x3, &y3);
qPath.cubicTo( x1, y1, x2, y2, x3, y3);
j += 3;
} else {
state->transform(subpath->getX(j), subpath->getY(j), &x1, &y1);
qPath.lineTo(x1, y1);
++j;
}
}
if (subpath->isClosed()) {
qPath.closeSubpath();
}
}
}
return qPath;
}
void ArthurOutputDev::stroke(GfxState *state)
{
m_painter->drawPath( convertPath( state, state->getPath() ) );
}
void ArthurOutputDev::fill(GfxState *state)
{
m_painter->fillPath( convertPath( state, state->getPath() ), m_currentBrush );
}
void ArthurOutputDev::eoFill(GfxState *state)
{
#if 0
doPath (state, state->getPath(), gFalse);
cairo_set_fill_rule (cairo, CAIRO_FILL_RULE_EVEN_ODD);
cairo_set_source_rgb (cairo,
fill_color.r, fill_color.g, fill_color.b);
LOG(printf ("fill-eo\n"));
cairo_fill (cairo);
#endif
}
void ArthurOutputDev::clip(GfxState *state)
{
qDebug() << "got clip";
m_painter->setClipPath(convertPath( state, state->getPath() ) );
}
void ArthurOutputDev::eoClip(GfxState *state)
{
qDebug() << "got eoClip";
#if 0
doPath (state, state->getPath(), gFalse);
cairo_set_fill_rule (cairo, CAIRO_FILL_RULE_EVEN_ODD);
cairo_clip (cairo);
LOG (printf ("clip-eo\n"));
#endif
}
void ArthurOutputDev::drawString(GfxState *state, GooString *s)
{
GfxFont *font;
int wMode;
int render;
// the number of bytes in the string and not the number of glyphs?
int len = s->getLength();
char *p = s->getCString();
int count = 0;
double curX, curY;
double riseX, riseY;
font = state->getFont();
wMode = font->getWMode();
if (m_needFontUpdate) {
updateFont(state);
}
// check for invisible text -- this is used by Acrobat Capture
render = state->getRender();
if (render == 3) {
return;
}
// ignore empty strings
if (len == 0)
return;
state->textTransformDelta(0, state->getRise(), &riseX, &riseY);
curX = state->getCurX();
curY = state->getCurY();
while (len > 0) {
double x, y;
double x1, y1;
double dx, dy, tdx, tdy;
double originX, originY, tOriginX, tOriginY;
int n, uLen;
CharCode code;
Unicode u[8];
n = font->getNextChar(p, len, &code,
u, (int)(sizeof(u) / sizeof(Unicode)), &uLen,
&dx, &dy, &originX, &originY);
if (wMode) {
dx *= state->getFontSize();
dy = dy * state->getFontSize() + state->getCharSpace();
if (n == 1 && *p == ' ') {
dy += state->getWordSpace();
}
} else {
dx = dx * state->getFontSize() + state->getCharSpace();
if (n == 1 && *p == ' ') {
dx += state->getWordSpace();
}
dx *= state->getHorizScaling();
dy *= state->getFontSize();
}
originX *= state->getFontSize();
originY *= state->getFontSize();
state->textTransformDelta(dx, dy, &tdx, &tdy);
state->textTransformDelta(originX, originY, &tOriginX, &tOriginY);
x = curX + riseX;
y = curY + riseY;
x -= tOriginX;
y -= tOriginY;
state->transform(x, y, &x1, &y1);
//glyphs[count].index = currentFont->getGlyph (code, u, uLen);
m_painter->drawText(QPointF(x1,y1), QString(*p) );
curX += tdx;
curY += tdy;
p += n;
len -= n;
count++;
}
#if 0
// fill
if (!(render & 1)) {
LOG (printf ("fill string\n"));
cairo_set_source_rgb (cairo,
fill_color.r, fill_color.g, fill_color.b);
cairo_show_glyphs (cairo, glyphs, count);
}
// stroke
if ((render & 3) == 1 || (render & 3) == 2) {
LOG (printf ("stroke string\n"));
cairo_set_source_rgb (cairo,
stroke_color.r, stroke_color.g, stroke_color.b);
cairo_glyph_path (cairo, glyphs, count);
cairo_stroke (cairo);
}
// clip
if (render & 4) {
// FIXME: This is quite right yet, we need to accumulate all
// glyphs within one text object before we clip. Right now this
// just add this one string.
LOG (printf ("clip string\n"));
cairo_glyph_path (cairo, glyphs, count);
cairo_clip (cairo);
}
#endif
}
GBool ArthurOutputDev::beginType3Char(GfxState *state, double x, double y,
double dx, double dy,
CharCode code, Unicode *u, int uLen)
{
return gFalse;
}
void ArthurOutputDev::endType3Char(GfxState *state)
{
}
void ArthurOutputDev::type3D0(GfxState *state, double wx, double wy)
{
}
void ArthurOutputDev::type3D1(GfxState *state, double wx, double wy,
double llx, double lly, double urx, double ury)
{
}
void ArthurOutputDev::endTextObject(GfxState *state)
{
}
void ArthurOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str,
int width, int height, GBool invert,
GBool inlineImg)
{
qDebug() << "drawImageMask";
#if 0
unsigned char *buffer;
unsigned char *dest;
cairo_surface_t *image;
cairo_pattern_t *pattern;
int x, y;
ImageStream *imgStr;
Guchar *pix;
double *ctm;
cairo_matrix_t matrix;
int invert_bit;
int row_stride;
row_stride = (width + 3) & ~3;
buffer = (unsigned char *) malloc (height * row_stride);
if (buffer == NULL) {
error(-1, "Unable to allocate memory for image.");
return;
}
/* TODO: Do we want to cache these? */
imgStr = new ImageStream(str, width, 1, 1);
imgStr->reset();
invert_bit = invert ? 1 : 0;
for (y = 0; y < height; y++) {
pix = imgStr->getLine();
dest = buffer + y * row_stride;
for (x = 0; x < width; x++) {
if (pix[x] ^ invert_bit)
*dest++ = 0;
else
*dest++ = 255;
}
}
image = cairo_image_surface_create_for_data (buffer, CAIRO_FORMAT_A8,
width, height, row_stride);
if (image == NULL)
return;
pattern = cairo_pattern_create_for_surface (image);
if (pattern == NULL)
return;
ctm = state->getCTM();
LOG (printf ("drawImageMask %dx%d, matrix: %f, %f, %f, %f, %f, %f\n",
width, height, ctm[0], ctm[1], ctm[2], ctm[3], ctm[4], ctm[5]));
matrix.xx = ctm[0] / width;
matrix.xy = -ctm[2] / height;
matrix.yx = ctm[1] / width;
matrix.yy = -ctm[3] / height;
matrix.x0 = ctm[2] + ctm[4];
matrix.y0 = ctm[3] + ctm[5];
cairo_matrix_invert (&matrix);
cairo_pattern_set_matrix (pattern, &matrix);
cairo_pattern_set_filter (pattern, CAIRO_FILTER_BEST);
/* FIXME: Doesn't the image mask support any colorspace? */
cairo_set_source_rgb (cairo, fill_color.r, fill_color.g, fill_color.b);
cairo_mask (cairo, pattern);
cairo_pattern_destroy (pattern);
cairo_surface_destroy (image);
free (buffer);
delete imgStr;
#endif
}
//TODO: lots more work here.
void ArthurOutputDev::drawImage(GfxState *state, Object *ref, Stream *str,
int width, int height,
GfxImageColorMap *colorMap,
int *maskColors, GBool inlineImg)
{
qDebug() << "drawImage";
if (inlineImg == gTrue) {
qDebug() << "drawImage inline";
}
unsigned char *buffer;
unsigned int *dest;
// cairo_surface_t *image;
// cairo_pattern_t *pattern;
int x, y;
ImageStream *imgStr;
Guchar *pix;
GfxRGB rgb;
int alpha, i;
double *ctm;
// cairo_matrix_t matrix;
QMatrix matrix;
int is_identity_transform;
buffer = (unsigned char *)gmalloc (width * height * 4);
/* TODO: Do we want to cache these? */
imgStr = new ImageStream(str, width,
colorMap->getNumPixelComps(),
colorMap->getBits());
imgStr->reset();
/* ICCBased color space doesn't do any color correction
* so check its underlying color space as well */
is_identity_transform = colorMap->getColorSpace()->getMode() == csDeviceRGB ||
colorMap->getColorSpace()->getMode() == csICCBased &&
((GfxICCBasedColorSpace*)colorMap->getColorSpace())->getAlt()->getMode() == csDeviceRGB;
if (maskColors) {
for (y = 0; y < height; y++) {
dest = (unsigned int *) (buffer + y * 4 * width);
pix = imgStr->getLine();
colorMap->getRGBLine (pix, dest, width);
for (x = 0; x < width; x++) {
for (i = 0; i < colorMap->getNumPixelComps(); ++i) {
if (pix[i] < maskColors[2*i] * 255||
pix[i] > maskColors[2*i+1] * 255) {
*dest = *dest | 0xff000000;
break;
}
}
pix += colorMap->getNumPixelComps();
dest++;
}
}
// image = cairo_image_surface_create_for_data (buffer, CAIRO_FORMAT_ARGB32, width, height, width * 4);
m_image = new QImage(buffer, width, height, QImage::Format_ARGB32);
}
else {
for (y = 0; y < height; y++) {
dest = (unsigned int *) (buffer + y * 4 * width);
pix = imgStr->getLine();
colorMap->getRGBLine (pix, dest, width);
}
// image = cairo_image_surface_create_for_data (buffer, CAIRO_FORMAT_RGB24, width, height, width * 4);
m_image = new QImage(buffer, width, height, QImage::Format_RGB32);
}
if (m_image == NULL || m_image->isNull()) {
qDebug() << "Null image";
return;
}
#if 0
pattern = cairo_pattern_create_for_surface (image);
if (pattern == NULL)
return;
ctm = state->getCTM();
matrix.xx = ctm[0] / width;
matrix.xy = -ctm[2] / height;
matrix.yx = ctm[1] / width;
matrix.yy = -ctm[3] / height;
matrix.x0 = ctm[2] + ctm[4];
matrix.y0 = ctm[3] + ctm[5];
cairo_matrix_invert (&matrix);
cairo_pattern_set_matrix (pattern, &matrix);
cairo_pattern_set_filter (pattern, CAIRO_FILTER_BILINEAR);
cairo_set_source (cairo, pattern);
cairo_paint (cairo);
cairo_pattern_destroy (pattern);
cairo_surface_destroy (image);
#endif
// TODO - figure out how to apply the matrix
// verify image is correct.
m_image->save("m_image.png", "PNG");
m_painter->drawImage( QPoint(0,0), *m_image );
//free (buffer);
//delete imgStr;
}
--- NEW FILE: ArthurOutputDev.h ---
//========================================================================
//
// ArthurOutputDev.h
//
// Copyright 2003 Glyph & Cog, LLC
// Copyright 2004 Red Hat, INC
//
//========================================================================
#ifndef CAIROOUTPUTDEV_H
#define CAIROOUTPUTDEV_H
#ifdef USE_GCC_PRAGMAS
#pragma interface
#endif
#include "goo/gtypes.h"
#include "OutputDev.h"
#include "GfxState.h"
#include <QtGui/QPainter>
class GfxState;
class GfxPath;
class Gfx8BitFont;
struct GfxRGB;
//------------------------------------------------------------------------
// ArthurOutputDev - Qt 4 QPainter renderer
//------------------------------------------------------------------------
class ArthurOutputDev: public OutputDev {
public:
// Constructor.
ArthurOutputDev(QPainter *painter );
// Destructor.
virtual ~ArthurOutputDev();
//----- 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 gFalse; }
// 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);
virtual void updateFillOpacity(GfxState *state);
virtual void updateStrokeOpacity(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 drawString(GfxState *state, GooString *s);
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 gFalse; }
private:
QPainter *m_painter;
QFont m_currentFont;
QPen m_currentPen;
QBrush m_currentBrush;
GBool m_needFontUpdate; // set when the font needs to be updated
QImage *m_image;
};
#endif
Index: Makefile.am
===================================================================
RCS file: /cvs/poppler/poppler/poppler/Makefile.am,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -d -r1.8 -r1.9
--- Makefile.am 28 Jun 2005 03:44:12 -0000 1.8
+++ Makefile.am 28 Jun 2005 10:00:09 -0000 1.9
@@ -15,6 +15,22 @@
endif
+if BUILD_POPPLER_QT4
+
+arthur_headers = \
+ ArthurOutputDev.h
+
+arthur_sources = \
+ ArthurOutputDev.cc
+
+arthur_includes = \
+ $(POPPLER_QT4_CXXFLAGS)
+
+arthur_libs = \
+ $(POPPLER_QT4_LIBS)
+
+endif
+
if BUILD_CAIRO_OUTPUT
@@ -60,6 +76,7 @@
-I$(top_srcdir) \
$(splash_includes) \
$(cairo_includes) \
+ $(arthur_includes) \
-DDATADIR=\""$(datadir)"\"
lib_LTLIBRARIES = libpoppler.la
@@ -69,6 +86,7 @@
$(top_builddir)/fofi/libfofi.la \
$(splash_libs) \
$(cairo_libs) \
+ $(arthur_libs) \
$(libjpeg_libs) \
$(zlib_libs)
@@ -76,6 +94,7 @@
poppler_include_HEADERS = \
$(splash_headers) \
$(cairo_headers) \
+ $(arthur_headers) \
Annot.h \
Array.h \
BaseFile.h \
@@ -127,6 +146,7 @@
libpoppler_la_SOURCES = \
$(splash_sources) \
$(cairo_sources) \
+ $(arthur_sources) \
$(libjpeg_sources) \
$(zlib_sources) \
Annot.cc \
- Previous message: [poppler] poppler/qt4: Makefile.am,NONE,1.1
- Next message: [poppler] poppler/qt4/src: Doxyfile, NONE, 1.1 Makefile.am, NONE,
1.1 poppler-document.cc, NONE, 1.1 poppler-page.cc, NONE,
1.1 poppler-private.h, NONE, 1.1 poppler-qt4.h, NONE, 1.1
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
More information about the poppler
mailing list