campo-sirio/xvaga/xvtpdf.cpp
guy 869692a6fd Patch level :
Files correlati     : xvaga.dll
Ricompilazione Demo : [ ]
Commento            :
Migliorato clipping nei PDF


git-svn-id: svn://10.65.10.50/branches/R_10_00@22015 c028cbd2-c16b-5b4b-a496-9718f37d4682
2011-04-21 14:33:34 +00:00

1234 lines
33 KiB
C++
Executable File

#include "wxinc.h"
#include "XFont.h"
#include "xvtpdf.h"
#define RAD2DEG 57.29577951308
#define BEZIERK 0.55228475
#define PDF_DPI 720
IMPLEMENT_DYNAMIC_CLASS(TwxPDFDC, wxDC)
//-- Contructor and Destructor -------------------------------------------
TwxPDFDC::TwxPDFDC()
{
wxASSERT(false); // Dummy constructor!
}
TwxPDFDC::TwxPDFDC (const wxPrintData& printData, const char* strFilename)
: m_PDFlib(NULL), m_p(NULL), m_fileName(strFilename)
{
m_pageNumber = 0;
m_topDown = true;
m_clipping = false;
m_pageopen = false;
m_printData = printData;
for(int i=0; i < PDF_IMG_CACHE_SIZE; i++)
{
m_filenames[i].Empty();
m_handles[i] = 0;
}
m_cacheidx = 0;
m_PDFlib = PDF_new_dl(&m_p);
m_ok = m_PDFlib != NULL;
if (!m_ok)
::wxMessageBox(_("Cannot create PDFlib object (DLL not found?)"), "PDFlib", wxOK|wxICON_ERROR);
}
TwxPDFDC::~TwxPDFDC ()
{
if (m_PDFlib != NULL)
{
PDF_delete_dl(m_PDFlib, m_p);
m_PDFlib = NULL;
m_p = NULL;
}
}
//-- Status --------------------------------------------------------------
bool TwxPDFDC::Ok() const
{ return m_ok; }
//-- Document and Pages --------------------------------------------------
bool TwxPDFDC::StartDoc( const wxString& message )
{
wxCHECK_MSG( m_ok, FALSE, wxT("invalid PDF dc") );
if (m_PDFlib->PDF_begin_document(m_p, m_fileName, 0, "") == -1)
{
wxLogError( _("Cannot open file for PDF printing!"));
return m_ok = false;
}
PDF_TRY_DL(m_PDFlib, m_p)
{
wxString strFontPath;
wxChar* lpszFontPath = strFontPath.GetWriteBuf(_MAX_PATH);
::GetFontsFolder(lpszFontPath, _MAX_PATH);
strFontPath.UngetWriteBuf();
m_PDFlib->PDF_set_parameter(m_p, "SearchPath", strFontPath);
const wxString strUser = wxGetUserId();
m_PDFlib->PDF_set_info(m_p, "Author", strUser);
m_PDFlib->PDF_set_info(m_p, "Creator", "Campo");
m_PDFlib->PDF_set_info(m_p, "Title", message);
}
PDF_CATCH_DL(m_PDFlib, m_p)
{
wxLogError("%s: %s", m_PDFlib->PDF_get_apiname(m_p), m_PDFlib->PDF_get_errmsg(m_p));
m_ok = false;
}
m_pageNumber = 0;
return m_ok = true;
}
void TwxPDFDC::EndDoc ()
{
wxCHECK_RET( m_ok, wxT("invalid PDF dc") );
ResetClipping();
PDF_TRY_DL(m_PDFlib, m_p)
{
m_PDFlib->PDF_end_document(m_p, "");
}
PDF_CATCH_DL(m_PDFlib, m_p)
{
wxLogError("%s: %s", m_PDFlib->PDF_get_apiname(m_p), m_PDFlib->PDF_get_errmsg(m_p));
m_ok = false;
}
}
void TwxPDFDC::StartPage()
{
wxCHECK_RET( m_ok, wxT("invalid PDF dc") );
if (m_pageopen)
return;
m_pageNumber++;
SetAxisOrientation(true, false);
PDF_TRY_DL(m_PDFlib, m_p)
{
int size_x, size_y; DoGetSize(&size_x, &size_y);
const double scale = 72.0 / PDF_DPI;
m_PDFlib->PDF_begin_page_ext(m_p, size_x*scale, size_y*scale, "");
m_PDFlib->PDF_scale(m_p, scale, scale);
m_pageopen = true;
}
PDF_CATCH_DL(m_PDFlib, m_p)
{
wxLogError("%s: %s", m_PDFlib->PDF_get_apiname(m_p), m_PDFlib->PDF_get_errmsg(m_p));
m_ok = false;
}
SetBrush(*wxBLACK_BRUSH);
SetPen(*wxBLACK_PEN);
SetBackground(*wxWHITE_BRUSH);
SetTextForeground(*wxBLACK);
}
void TwxPDFDC::EndPage()
{
wxCHECK_RET( m_ok, wxT("invalid PDF dc") );
if (!m_ok || !m_pageopen)
return;
if (m_clipping)
DestroyClippingRegion();
PDF_TRY_DL(m_PDFlib, m_p)
{
m_PDFlib->PDF_end_page_ext(m_p, "");
m_pageopen = false;
}
PDF_CATCH_DL(m_PDFlib, m_p)
{
wxLogError("%s: %s", m_PDFlib->PDF_get_apiname(m_p), m_PDFlib->PDF_get_errmsg(m_p));
m_ok = false;
}
}
//-- Graphics ------------------------------------------------------------
void TwxPDFDC::DoDrawPoint(wxCoord x, wxCoord y)
{
DoDrawLine(x, y, x+1, y);
}
void TwxPDFDC::DoDrawLine(wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2)
{
wxCHECK_RET( m_ok, wxT("invalid PDF dc") );
if (m_pen.GetStyle() == wxTRANSPARENT)
return;
SetPen(m_pen);
PDF_TRY_DL(m_PDFlib, m_p)
{
m_PDFlib->PDF_moveto(m_p, x1, y1);
m_PDFlib->PDF_lineto(m_p, x2, y2);
m_PDFlib->PDF_stroke(m_p);
CalcBoundingBox(x1, y1);
CalcBoundingBox(x2, y2);
}
PDF_CATCH_DL(m_PDFlib, m_p)
{
wxLogError("%s: %s", m_PDFlib->PDF_get_apiname(m_p), m_PDFlib->PDF_get_errmsg(m_p));
}
}
void TwxPDFDC::DoDrawLines (int n, wxPoint points[], wxCoord xoffset, wxCoord yoffset)
{
wxCHECK_RET( m_ok, wxT("invalid PDF dc") );
if (m_pen.GetStyle() == wxTRANSPARENT)
return;
if (n <= 0)
return;
SetPen(m_pen);
PDF_TRY_DL(m_PDFlib, m_p)
{
int i;
CalcBoundingBox(points[0].x+xoffset, points[0].y+yoffset);
m_PDFlib->PDF_moveto(m_p, points[0].x+xoffset, points[0].y+yoffset);
for (i=1;i<n;i++)
{
m_PDFlib->PDF_lineto(m_p, points[i].x+xoffset, points[i].y+yoffset);
CalcBoundingBox(points[i].x+xoffset, points[i].y+yoffset);
}
m_PDFlib->PDF_stroke(m_p);
}
PDF_CATCH_DL(m_PDFlib, m_p)
{
wxLogError("%s: %s", m_PDFlib->PDF_get_apiname(m_p), m_PDFlib->PDF_get_errmsg(m_p));
}
}
void TwxPDFDC::DoDrawPolygon (int n, wxPoint points[], wxCoord xoffset, wxCoord yoffset, int WXUNUSED(fillStyle))
{
wxCHECK_RET( m_ok, wxT("invalid PDF dc") );
if (n <= 0)
return;
if (m_pen.GetStyle() == wxTRANSPARENT && m_brush.GetStyle() == wxTRANSPARENT)
return;
if (m_pen.GetStyle () != wxTRANSPARENT)
SetPen(m_pen);
if (m_brush.GetStyle() != wxTRANSPARENT)
SetBrush(m_brush);
PDF_TRY_DL(m_PDFlib, m_p)
{
CalcBoundingBox(points[0].x + xoffset, points[0].y + yoffset);
m_PDFlib->PDF_moveto(m_p, points[0].x+xoffset, points[0].y+yoffset);
for (int i=1;i<n;i++)
{
m_PDFlib->PDF_lineto(m_p, points[i].x+xoffset, points[i].y+yoffset);
CalcBoundingBox(points[i].x+xoffset, points[i].y+yoffset);
}
m_PDFlib->PDF_closepath(m_p);
if (m_pen.GetStyle () != wxTRANSPARENT && m_brush.GetStyle() != wxTRANSPARENT)
m_PDFlib->PDF_fill_stroke(m_p);
else
{
if (m_pen.GetStyle () != wxTRANSPARENT)
m_PDFlib->PDF_stroke(m_p);
else
m_PDFlib->PDF_fill(m_p);
}
}
PDF_CATCH_DL(m_PDFlib, m_p)
{
wxLogError("%s: %s", m_PDFlib->PDF_get_apiname(m_p), m_PDFlib->PDF_get_errmsg(m_p));
}
}
void TwxPDFDC::DoDrawRectangle (wxCoord x, wxCoord y, wxCoord width, wxCoord height)
{
wxCHECK_RET( m_ok, wxT("invalid PDF dc") );
if (m_pen.GetStyle() == wxTRANSPARENT && m_brush.GetStyle() == wxTRANSPARENT)
return;
if (m_pen.GetStyle () != wxTRANSPARENT)
SetPen(m_pen);
if (m_brush.GetStyle() != wxTRANSPARENT)
SetBrush(m_brush);
PDF_TRY_DL(m_PDFlib, m_p)
{
m_PDFlib->PDF_rect(m_p, x, y + height, width, height);
CalcBoundingBox( x, y );
CalcBoundingBox( x + width, y + height );
if (m_pen.GetStyle () != wxTRANSPARENT && m_brush.GetStyle() != wxTRANSPARENT)
m_PDFlib->PDF_fill_stroke(m_p);
else
{
if (m_pen.GetStyle () != wxTRANSPARENT)
m_PDFlib->PDF_stroke(m_p);
else
m_PDFlib->PDF_fill(m_p);
}
}
PDF_CATCH_DL(m_PDFlib, m_p)
{
wxLogError("%s: %s", m_PDFlib->PDF_get_apiname(m_p), m_PDFlib->PDF_get_errmsg(m_p));
}
}
void TwxPDFDC::DoDrawArc (wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2, wxCoord xc, wxCoord yc)
{
wxCHECK_RET( m_ok, wxT("invalid PDF dc") );
if (m_pen.GetStyle() == wxTRANSPARENT && m_brush.GetStyle() == wxTRANSPARENT)
return;
if (m_pen.GetStyle () != wxTRANSPARENT)
SetPen(m_pen);
if (m_brush.GetStyle() != wxTRANSPARENT)
SetBrush(m_brush);
const wxCoord radius = (wxCoord)_hypot(x1 - xc, y1 - yc) / 2;
double alpha1, alpha2;
if (x1 == x2 && y1 == y2)
{
alpha1 = 0.0;
alpha2 = 360.0;
}
else if (radius == 0.0)
{
alpha1 = alpha2 = 0.0;
}
else
{
alpha1 = (x1 - xc == 0) ?
(y1 - yc < 0) ? 90.0 : -90.0 :
-atan2(double(y1-yc), double(x1-xc)) * RAD2DEG;
alpha2 = (x2 - xc == 0) ?
(y2 - yc < 0) ? 90.0 : -90.0 :
-atan2(double(y2-yc), double(x2-xc)) * RAD2DEG;
}
while (alpha1 < 0) alpha1 += 360;
while (alpha2 <= 0) alpha2 += 360; // adjust angles to be between
while (alpha1 > 360) alpha1 -= 360; // 0 and 360 degree
while (alpha2 > 360) alpha2 -= 360;
PDF_TRY_DL(m_PDFlib, m_p)
{
m_PDFlib->PDF_moveto(m_p, xc, yc);
m_PDFlib->PDF_arc(m_p, xc, yc, radius, alpha1, alpha2);
m_PDFlib->PDF_closepath(m_p);
CalcBoundingBox( xc-radius, yc-radius );
CalcBoundingBox( xc+radius, yc+radius );
if (m_pen.GetStyle () != wxTRANSPARENT && m_brush.GetStyle() != wxTRANSPARENT)
m_PDFlib->PDF_fill_stroke(m_p);
else
{
if (m_pen.GetStyle () != wxTRANSPARENT)
m_PDFlib->PDF_stroke(m_p);
else
m_PDFlib->PDF_fill(m_p);
}
}
PDF_CATCH_DL(m_PDFlib, m_p)
{
wxLogError("%s: %s", m_PDFlib->PDF_get_apiname(m_p), m_PDFlib->PDF_get_errmsg(m_p));
}
}
void TwxPDFDC::DoDrawEllipse (wxCoord x, wxCoord y, wxCoord width, wxCoord height)
{
wxCHECK_RET( m_ok, wxT("invalid PDF dc") );
if (m_pen.GetStyle() == wxTRANSPARENT && m_brush.GetStyle() == wxTRANSPARENT)
return;
if (m_pen.GetStyle () != wxTRANSPARENT)
SetPen(m_pen);
if (m_brush.GetStyle() != wxTRANSPARENT)
SetBrush(m_brush);
PDF_TRY_DL(m_PDFlib, m_p)
{
width /= 2;
height /= 2;
x += width;
y += height;
m_PDFlib->PDF_moveto(m_p, x+width, y);
m_PDFlib->PDF_curveto(m_p, x+width, y+BEZIERK*height, x+BEZIERK*width, y+height, x, y+height);
m_PDFlib->PDF_curveto(m_p, x-BEZIERK*width, y+height, x-width, y+BEZIERK*height, x-width, y);
m_PDFlib->PDF_curveto(m_p, x-width, y-BEZIERK*height, x-BEZIERK*width, y-height, x, y-height);
m_PDFlib->PDF_curveto(m_p, x+BEZIERK*width, y-height, x+width, y-BEZIERK*height, x+width, y);
m_PDFlib->PDF_closepath(m_p);
CalcBoundingBox(x-width, y-height);
CalcBoundingBox(x+width, y+height);
if (m_pen.GetStyle () != wxTRANSPARENT && m_brush.GetStyle() != wxTRANSPARENT)
m_PDFlib->PDF_fill_stroke(m_p);
else
{
if (m_pen.GetStyle () != wxTRANSPARENT)
m_PDFlib->PDF_stroke(m_p);
else
m_PDFlib->PDF_fill(m_p);
}
}
PDF_CATCH_DL(m_PDFlib, m_p)
{
wxLogError("%s: %s", m_PDFlib->PDF_get_apiname(m_p), m_PDFlib->PDF_get_errmsg(m_p));
}
}
void TwxPDFDC::DoDrawEllipticArc(wxCoord x,wxCoord y,wxCoord w,wxCoord h,double sa,double ea)
{
wxCHECK_RET( m_ok, wxT("invalid PDF dc") );
if (m_pen.GetStyle() == wxTRANSPARENT && m_brush.GetStyle() == wxTRANSPARENT)
return;
if (sa>=360 || sa<=-360) sa=sa-int(sa/360)*360;
if (ea>=360 || ea<=-360) ea=ea-int(ea/360)*360;
if (sa<0) sa+=360;
if (ea<0) ea+=360;
if (sa==ea)
{
DrawEllipse(x,y,w,h);
return;
}
if (m_pen.GetStyle () != wxTRANSPARENT)
SetPen(m_pen);
if (m_brush.GetStyle() != wxTRANSPARENT)
SetBrush(m_brush);
PDF_TRY_DL(m_PDFlib, m_p)
{
m_PDFlib->PDF_save(m_p);
m_PDFlib->PDF_moveto(m_p, x, y);
m_PDFlib->PDF_scale(m_p, 1, h/w);
m_PDFlib->PDF_arc(m_p, x, y, w, sa, ea);
m_PDFlib->PDF_closepath(m_p);
CalcBoundingBox( x ,y );
CalcBoundingBox( x+w, y+h );
if (m_pen.GetStyle () != wxTRANSPARENT && m_brush.GetStyle() != wxTRANSPARENT)
m_PDFlib->PDF_fill_stroke(m_p);
else
{
if (m_pen.GetStyle () != wxTRANSPARENT)
m_PDFlib->PDF_stroke(m_p);
else
m_PDFlib->PDF_fill(m_p);
}
m_PDFlib->PDF_restore(m_p);
}
PDF_CATCH_DL(m_PDFlib, m_p)
{
wxLogError("%s: %s", m_PDFlib->PDF_get_apiname(m_p), m_PDFlib->PDF_get_errmsg(m_p));
}
}
void TwxPDFDC::DoDrawRoundedRectangle (wxCoord x, wxCoord y, wxCoord width, wxCoord height, double radius)
{
wxCHECK_RET( m_ok, wxT("invalid PDF dc") );
if (m_pen.GetStyle() == wxTRANSPARENT && m_brush.GetStyle() == wxTRANSPARENT)
return;
if (m_pen.GetStyle () != wxTRANSPARENT)
SetPen(m_pen);
if (m_brush.GetStyle() != wxTRANSPARENT)
SetBrush(m_brush);
if (radius < 0.0)
{
const double smallest = width < height ? width : height;
radius = (-radius * smallest);
}
PDF_TRY_DL(m_PDFlib, m_p)
{
m_PDFlib->PDF_moveto(m_p, x, y+radius);
m_PDFlib->PDF_lineto(m_p, x, y+height-radius);
m_PDFlib->PDF_arc(m_p, x+radius, y+height-radius, radius, 180, 270);
m_PDFlib->PDF_lineto(m_p, x+width-radius, y+height);
m_PDFlib->PDF_arc(m_p, x+width-radius, y+height-radius, radius, 270, 360);
m_PDFlib->PDF_lineto(m_p, x+width, y+radius);
m_PDFlib->PDF_arc(m_p, x+width-radius, y+radius, radius, 0, 90);
m_PDFlib->PDF_lineto(m_p, x+radius, y);
m_PDFlib->PDF_arc(m_p, x+radius, y+radius, radius, 90, 180);
m_PDFlib->PDF_closepath(m_p);
CalcBoundingBox(x ,y);
CalcBoundingBox(x+width, y+height);
if (m_pen.GetStyle () != wxTRANSPARENT && m_brush.GetStyle() != wxTRANSPARENT)
m_PDFlib->PDF_fill_stroke(m_p);
else
{
if (m_pen.GetStyle () != wxTRANSPARENT)
m_PDFlib->PDF_stroke(m_p);
else
m_PDFlib->PDF_fill(m_p);
}
}
PDF_CATCH_DL(m_PDFlib, m_p)
{
wxLogError("%s: %s", m_PDFlib->PDF_get_apiname(m_p), m_PDFlib->PDF_get_errmsg(m_p));
}
}
void TwxPDFDC::DoDrawSpline( wxList *points )
{
wxCHECK_RET( m_ok, wxT("invalid PDF dc") );
SetPen(m_pen);
double a, b, c, d, x1, y1, x2, y2, x3, y3;
wxPoint *p, *q;
wxNode *node = points->GetFirst();
p = (wxPoint *)node->GetData();
x1 = p->x;
y1 = p->y;
node = node->GetNext();
p = (wxPoint *)node->GetData();
c = p->x;
d = p->y;
x3 = a = (double)(x1 + c) / 2;
y3 = b = (double)(y1 + d) / 2;
PDF_TRY_DL(m_PDFlib, m_p)
{
m_PDFlib->PDF_moveto(m_p, x1, y1);
m_PDFlib->PDF_lineto(m_p, x3, y3);
CalcBoundingBox( (wxCoord)x1, (wxCoord)y1 );
CalcBoundingBox( (wxCoord)x3, (wxCoord)y3 );
while ((node = node->GetNext()) != NULL)
{
q = (wxPoint *)node->GetData();
x1 = x3;
y1 = y3;
x2 = c;
y2 = d;
c = q->x;
d = q->y;
x3 = (double)(x2 + c) / 2;
y3 = (double)(y2 + d) / 2;
m_PDFlib->PDF_curveto(m_p, x1, y1, x2, y2, x3, y3);
CalcBoundingBox( (wxCoord)x1, (wxCoord)y1 );
CalcBoundingBox( (wxCoord)x3, (wxCoord)y3 );
}
m_PDFlib->PDF_lineto(m_p, c, d);
m_PDFlib->PDF_stroke(m_p);
}
PDF_CATCH_DL(m_PDFlib, m_p)
{
wxLogError("%s: %s", m_PDFlib->PDF_get_apiname(m_p), m_PDFlib->PDF_get_errmsg(m_p));
}
}
void TwxPDFDC::DoGradientFillLinear(const wxRect& rect, const wxColour& initialColour, const wxColour& destColour, wxDirection nDirection)
{
wxCHECK_RET( m_ok, wxT("invalid PDF dc") );
PDF_TRY_DL(m_PDFlib, m_p)
{
const double ir = initialColour.Red() / 255.0;
const double ig = initialColour.Green() / 255.0;
const double ib = initialColour.Blue() / 255.0;
const double fr = destColour.Red() / 255.0;
const double fg = destColour.Green() / 255.0;
const double fb = destColour.Blue() / 255.0;
const double x = rect.x;
const double y = rect.y;
const double w = rect.width;
const double h = rect.height;
m_PDFlib->PDF_save(m_p);
m_PDFlib->PDF_setcolor(m_p, "fill", "rgb", ir, ig, ib, 0);
m_PDFlib->PDF_moveto(m_p, x, y);
m_PDFlib->PDF_lineto(m_p, x+w, y);
m_PDFlib->PDF_lineto(m_p, x+w, y+h);
m_PDFlib->PDF_lineto(m_p, x, y+h);
m_PDFlib->PDF_closepath(m_p);
m_PDFlib->PDF_clip(m_p);
CalcBoundingBox(x ,y);
CalcBoundingBox(x+w, y+h);
double x0=x,y0=y+h/2,x1=x+w,y1=y0;
switch (nDirection)
{
case wxNORTH: x0=x+w/2; y0=y+h; x1=x0; y1 = y; break;
case wxSOUTH: x0=x+w/2; y0=y; x1=x0; y1 = y+h; break;
case wxWEST : x0=x+w; y0=y+h/2; x1=x; y1 = y0; break;
case wxEAST :
default : x0=x; y0=y+h/2; x1=x+w; y1 = y0; break;
}
const int sh = m_PDFlib->PDF_shading(m_p, "axial", x0, y0, x1, y1, fr, fg, fb, 0.0, "");
m_PDFlib->PDF_shfill(m_p, sh);
m_PDFlib->PDF_restore(m_p);
}
PDF_CATCH_DL(m_PDFlib, m_p)
{
wxLogError("%s: %s", m_PDFlib->PDF_get_apiname(m_p), m_PDFlib->PDF_get_errmsg(m_p));
}
}
//-- Images and Bitmaps --------------------------------------------------
void TwxPDFDC::DoDrawIcon( const wxIcon& icon, wxCoord x, wxCoord y )
{
DrawBitmap( icon, x, y, TRUE );
}
void TwxPDFDC::DoDrawBitmap( const wxBitmap& bitmap, wxCoord x, wxCoord y, bool WXUNUSED(useMask) )
{
wxCHECK_RET( m_ok, wxT("invalid PDF dc") );
if (!bitmap.Ok())
return;
int intImgHandle = GetBitmapHandle(bitmap);
const wxCoord h = bitmap.GetHeight();
if (intImgHandle<0)
return;
PDF_TRY_DL(m_PDFlib, m_p)
{
m_PDFlib->PDF_fit_image(m_p, intImgHandle, x, y+h, "");
}
PDF_CATCH_DL(m_PDFlib, m_p)
{
wxLogError("%s: %s", m_PDFlib->PDF_get_apiname(m_p), m_PDFlib->PDF_get_errmsg(m_p));
}
}
void TwxPDFDC::DoDrawImage( const wxString& name, const wxRect& dst )
{
wxCHECK_RET( m_ok, wxT("invalid PDF dc") );
const int intImgHandle = GetImageHandle(name);
if (intImgHandle<0)
return;
PDF_TRY_DL(m_PDFlib, m_p)
{
wxString strOptions;
strOptions.Printf("boxsize={%d %d} fitmethod=entire", dst.GetWidth(), dst.GetHeight());
m_PDFlib->PDF_fit_image(m_p, intImgHandle, dst.GetX(), dst.GetY()+dst.GetHeight(), strOptions);
}
PDF_CATCH_DL(m_PDFlib, m_p)
{
wxLogError("%s: %s", m_PDFlib->PDF_get_apiname(m_p), m_PDFlib->PDF_get_errmsg(m_p));
}
}
int TwxPDFDC::GetBitmapHandle(const wxBitmap& bitmap) const
{
wxString strFilename = wxGetTempFileName(wxT("tmpbmp"));
((wxBitmap&)bitmap).SaveFile(strFilename, wxBITMAP_TYPE_PNG);
PDF_TRY_DL(m_PDFlib, m_p)
{
return m_PDFlib->PDF_load_image(m_p, "png", strFilename, 0, "");
}
PDF_CATCH_DL(m_PDFlib, m_p)
{
wxLogError("%s: %s", m_PDFlib->PDF_get_apiname(m_p), m_PDFlib->PDF_get_errmsg(m_p));
}
return -1;
}
int TwxPDFDC::GetImageHandle(const wxString& name)
{
int intFound = -1;
if (!name.IsEmpty())
{
for (int i=PDF_IMG_CACHE_SIZE; i>0; i--)
{
const int idx = (i + m_cacheidx) % PDF_IMG_CACHE_SIZE;
if (m_filenames[idx]==name)
{
intFound = idx;
break;
}
}
// Se non la trovo, provo ad aggiungerla
if (intFound<0 && m_cacheidx<PDF_IMG_CACHE_SIZE)
{
const int intNewHandle = m_PDFlib->PDF_load_image(m_p, "auto", name, 0, "");
if (intNewHandle >=0 )
{
PDF_TRY_DL(m_PDFlib, m_p)
{
m_filenames[m_cacheidx] = name;
m_handles[m_cacheidx] = intNewHandle;
intFound = m_cacheidx++;
}
PDF_CATCH_DL(m_PDFlib, m_p)
{
wxLogError("%s: %s", m_PDFlib->PDF_get_apiname(m_p), m_PDFlib->PDF_get_errmsg(m_p));
}
}
}
}
return intFound >= 0 ? m_handles[intFound] : -1;
}
bool TwxPDFDC::DoBlit( wxCoord xdest, wxCoord ydest,
wxCoord fwidth, wxCoord fheight,
wxDC *source,
wxCoord xsrc, wxCoord ysrc,
int rop, bool WXUNUSED(useMask), wxCoord WXUNUSED(xsrcMask), wxCoord WXUNUSED(ysrcMask) )
{
wxCHECK_MSG( m_ok, FALSE, wxT("invalid PDF dc") );
wxCHECK_MSG( source, FALSE, wxT("invalid source dc") );
wxBitmap bitmap( (int)fwidth, (int)fheight );
wxMemoryDC memDC;
memDC.SelectObject(bitmap);
memDC.Blit(0, 0, fwidth, fheight, source, xsrc, ysrc, rop);
memDC.SelectObject(wxNullBitmap);
DrawBitmap( bitmap, xdest, ydest );
return TRUE;
}
//-- Text ----------------------------------------------------------------
void TwxPDFDC::DoDrawText( const wxString& text, wxCoord x, wxCoord y )
{
wxCHECK_RET( m_ok, wxT("invalid PDF dc") );
SetFont(m_font);
SetFontColor(m_textForegroundColour);
PDF_TRY_DL(m_PDFlib, m_p)
{
m_PDFlib->PDF_set_text_pos(m_p, x, y + m_ascent);
m_PDFlib->PDF_show(m_p, text);
wxCoord text_w = m_PDFlib->PDF_stringwidth(m_p, text, m_fontnr, m_fontsize);
CalcBoundingBox( x, y );
CalcBoundingBox( x + text_w , y + m_fontsize );
}
PDF_CATCH_DL(m_PDFlib, m_p)
{
wxLogError("%s: %s", m_PDFlib->PDF_get_apiname(m_p), m_PDFlib->PDF_get_errmsg(m_p));
}
SetBrush(m_brush);
}
void TwxPDFDC::DoDrawRotatedText( const wxString& text, wxCoord x, wxCoord y, double angle )
{
if (angle == 0.0)
{
DoDrawText(text, x, y);
return;
}
wxCHECK_RET( m_ok, wxT("invalid PDF dc") );
SetFont( m_font );
PDF_TRY_DL(m_PDFlib, m_p)
{
m_PDFlib->PDF_save(m_p);
m_PDFlib->PDF_set_text_pos(m_p, x, y);
m_PDFlib->PDF_translate(m_p, x, y);
m_PDFlib->PDF_rotate(m_p, angle);
m_PDFlib->PDF_show(m_p, text);
m_PDFlib->PDF_restore(m_p);
CalcBoundingBox( x, y );
CalcBoundingBox( m_PDFlib->PDF_get_value(m_p, "textx", x), m_PDFlib->PDF_get_value(m_p, "texty", y) );
}
PDF_CATCH_DL(m_PDFlib, m_p)
{
wxLogError("%s: %s", m_PDFlib->PDF_get_apiname(m_p), m_PDFlib->PDF_get_errmsg(m_p));
}
}
wxCoord TwxPDFDC::GetCharHeight() const
{
wxCoord y = 0;
DoGetTextExtent("M", NULL, &y, NULL, NULL, NULL);
return y;
}
wxCoord TwxPDFDC::GetCharWidth() const
{
wxCoord x = 0;
DoGetTextExtent("M", &x, NULL, NULL, NULL, NULL);
return x;
}
void TwxPDFDC::DoGetTextExtent(const wxString& text,
wxCoord *x, wxCoord *y,
wxCoord *d, wxCoord *e,
wxFont *theFont ) const
{
PDF_TRY_DL(m_PDFlib, m_p)
{
if (d) *d = 0;
if (e) *e = 0;
if (m_font.Ok() && (theFont==NULL || *theFont==m_font))
{
if (x) *x = m_PDFlib->PDF_stringwidth(m_p, text, m_fontnr, m_fontsize);
if (y) *y = m_fontsize;
if (d) *d = m_descent;
if (e) *e = m_leading;
}
else
{
if (theFont!=NULL)
{
wxString strStyle = (theFont->GetWeight()==wxBOLD?"bold":"");
strStyle += (theFont->GetStyle()==wxITALIC?"italic":"");
wxString strFamily = theFont->GetFaceName();
double fontsize = theFont->GetPointSize();
int fontnr = m_PDFlib->PDF_load_font(m_p, strFamily, 0, "auto", "fontstyle {" + strStyle + "}");
if (x) *x = m_PDFlib->PDF_stringwidth(m_p, text, fontnr, fontsize);
if (y) *y = fontsize;
if (d) *d = fontsize/5;
if (e) *e = fontsize/10;
}
}
}
PDF_CATCH_DL(m_PDFlib, m_p)
{
wxLogError("%s: %s", m_PDFlib->PDF_get_apiname(m_p), m_PDFlib->PDF_get_errmsg(m_p));
}
}
//-- Settings ------------------------------------------------------------
bool TwxPDFDC::IsValidFontFile(const char* szFontFile) const
{
wxString strFile = szFontFile;
strFile.MakeLower();
return strFile.EndsWith(".ttf");
}
bool TwxPDFDC::GetFontFamily(const wxFont& font, wxString& file, wxString& family) const
{
static wxFont m_LastFont;
static wxString m_LastFile, m_strFamily;
if (!m_LastFont.IsOk() ||
font.GetPointSize()!= m_LastFont.GetPointSize() || // FAMILY NON DOVREBBE DIPENDERE DA POINTSIZE!
font.GetWeight() != m_LastFont.GetWeight() ||
font.GetStyle() != m_LastFont.GetStyle() ||
font.GetFaceName() != m_LastFont.GetFaceName())
{
wxString strStyle = font.GetWeight() >= wxBOLD ? " Bold" : "";
strStyle += font.GetStyle() == wxITALIC ? " Italic" : "";
m_strFamily = font.GetFaceName();
TCHAR szDisplayName[MAX_PATH], szFontFile[MAX_PATH];
bool ok = GetFontFile(m_strFamily + strStyle, szDisplayName, MAX_PATH, szFontFile, MAX_PATH) != 0;
if (ok)
m_strFamily += strStyle;
else
ok = GetFontFile(m_strFamily, szDisplayName, MAX_PATH, szFontFile, MAX_PATH) != 0;
m_LastFont = font;
if (ok)
m_LastFile = szFontFile;
else
m_LastFile = m_strFamily = wxEmptyString;
if (!IsValidFontFile(szFontFile))
{
const wxFont swiss(font.GetPointSize(), font.GetFamily(), font.GetStyle(),
font.GetWeight(), font.GetUnderlined());
return GetFontFamily(swiss, file, family);
}
}
file = m_LastFile;
family = m_strFamily;
return !file.IsEmpty();
}
void TwxPDFDC::SetFont( const wxFont& font )
{
wxCHECK_RET( m_ok, wxT("invalid PDF dc") );
if (!font.Ok())
return;
wxString strFontFile, strFamily;
bool ok = GetFontFamily(font, strFontFile, strFamily);
if (ok)
{
PDF_TRY_DL(m_PDFlib, m_p)
{
const wxString strScope = m_PDFlib->PDF_get_parameter(m_p, "scope", 0);
if (strScope != "document") // Solitamente strScope = "page"
{
const wxString strParameter = strFamily + "=" + strFontFile;
m_PDFlib->PDF_set_parameter(m_p, "FontOutline", strParameter);
m_fontsize = font.GetPointSize();
// maialata gigante da eliminare data dal fatto che a volte la GetPointSize() scazza
// completamente a ritornare la dimensione (problema di wxWindoz) e ritorna un valore
// molto molto minore di quello effettivo
if (m_fontsize < 36)
m_fontsize *= 9;
m_descent = m_fontsize/5;
m_ascent = m_fontsize-m_descent;
m_leading = m_descent/2;
m_font = font;
m_fontnr = m_PDFlib->PDF_load_font(m_p, strFamily, 0, "host", "");
m_PDFlib->PDF_setfont(m_p, m_fontnr, m_fontsize);
m_PDFlib->PDF_set_parameter(m_p, "underline", m_font.GetUnderlined()?"true":"false");
}
}
PDF_CATCH_DL(m_PDFlib, m_p)
{
wxLogError("%s: %s", m_PDFlib->PDF_get_apiname(m_p), m_PDFlib->PDF_get_errmsg(m_p));
}
}
else
wxLogError("SetFont(%s): Can't find font file", (const char*)font.GetFaceName());
}
void TwxPDFDC::SetPen( const wxPen& pen )
{
wxCHECK_RET( m_ok, wxT("invalid PDF dc") );
if (!pen.Ok())
return;
m_pen = pen;
static const char *dotted = "dasharray {2 5} dashphase {2}";
static const char *short_dashed = "dasharray {4 4} dashphase {2}";
static const char *long_dashed = "dasharray {4 8} dashphase {2}";
static const char *dotted_dashed = "dasharray {6 6 2 6} dashphase {4}";
const char *pdfdash = (char *) NULL;
const double redPDF = m_pen.GetColour().Red() / 255.0;
const double greenPDF = m_pen.GetColour().Green() / 255.0;
const double bluePDF = m_pen.GetColour().Blue() / 255.0;
bool solid = false;
switch (m_pen.GetStyle())
{
case wxDOT : pdfdash = dotted; break;
case wxSHORT_DASH : pdfdash = short_dashed; break;
case wxLONG_DASH : pdfdash = long_dashed; break;
case wxDOT_DASH : pdfdash = dotted_dashed; break;
case wxSOLID :
case wxTRANSPARENT:
default : solid = true; break;
}
PDF_TRY_DL(m_PDFlib, m_p)
{
wxString strScope = m_PDFlib->PDF_get_parameter(m_p, "scope", 0);
if (strScope != "document")
{
const int nWidth = m_pen.GetWidth();
const double dWidth = nWidth <= 0 ? 1 : nWidth;
m_PDFlib->PDF_setlinewidth(m_p, dWidth);
if (solid)
m_PDFlib->PDF_setdash(m_p, 0, 0);
else
m_PDFlib->PDF_setdashpattern(m_p, pdfdash);
m_PDFlib->PDF_setcolor(m_p, "stroke", "rgb", redPDF, greenPDF, bluePDF, 0);
}
}
PDF_CATCH_DL(m_PDFlib, m_p)
{
wxLogError("%s: %s", m_PDFlib->PDF_get_apiname(m_p), m_PDFlib->PDF_get_errmsg(m_p));
}
}
void TwxPDFDC::SetBrush( const wxBrush& brush )
{
wxCHECK_RET( m_ok, wxT("invalid PDF dc") );
if (!brush.Ok())
return;
m_brush = brush;
unsigned char red = m_brush.GetColour().Red();
unsigned char blue = m_brush.GetColour().Blue();
unsigned char green = m_brush.GetColour().Green();
double redPDF = (double)(red) / 255.0;
double bluePDF = (double)(blue) / 255.0;
double greenPDF = (double)(green) / 255.0;
int intPatHandle;
int intStyle = m_brush.GetStyle();
bool solid = (intStyle==wxSOLID || intStyle==wxTRANSPARENT);
wxSize step = GetPPI();
step.x /= 180;
step.y /= 180;
PDF_TRY_DL(m_PDFlib, m_p)
{
wxString strScope = m_PDFlib->PDF_get_parameter(m_p, "scope", 0);
if (strScope != "document")
{
intPatHandle = m_PDFlib->PDF_begin_pattern(m_p, step.x, step.y , step.x, step.y, 2);
m_PDFlib->PDF_setlinewidth(m_p, 0.2f);
switch (intStyle)
{
case wxBDIAGONAL_HATCH:
m_PDFlib->PDF_moveto(m_p, 0, 0);
m_PDFlib->PDF_lineto(m_p, step.x, step.y);
m_PDFlib->PDF_stroke(m_p);
break;
case wxCROSSDIAG_HATCH:
m_PDFlib->PDF_moveto(m_p, 0, step.y);
m_PDFlib->PDF_lineto(m_p, step.x, 0);
m_PDFlib->PDF_stroke(m_p);
m_PDFlib->PDF_moveto(m_p, 0, 0);
m_PDFlib->PDF_lineto(m_p, step.x, step.y);
m_PDFlib->PDF_stroke(m_p);
break;
case wxFDIAGONAL_HATCH:
m_PDFlib->PDF_moveto(m_p, 0, step.y);
m_PDFlib->PDF_lineto(m_p, step.x, 0);
m_PDFlib->PDF_stroke(m_p);
break;
case wxCROSS_HATCH:
m_PDFlib->PDF_moveto(m_p, 0, step.y/2);
m_PDFlib->PDF_lineto(m_p, step.x, step.y/2);
m_PDFlib->PDF_stroke(m_p);
m_PDFlib->PDF_moveto(m_p, step.x/2, 0);
m_PDFlib->PDF_lineto(m_p, step.x/2, step.y);
m_PDFlib->PDF_stroke(m_p);
break;
case wxHORIZONTAL_HATCH:
m_PDFlib->PDF_moveto(m_p, 0, step.y/2);
m_PDFlib->PDF_lineto(m_p, step.x, step.y/2);
m_PDFlib->PDF_stroke(m_p);
break;
case wxVERTICAL_HATCH:
m_PDFlib->PDF_moveto(m_p, step.x/2, 0);
m_PDFlib->PDF_lineto(m_p, step.x/2, step.y);
m_PDFlib->PDF_stroke(m_p);
break;
default:
break;
}
m_PDFlib->PDF_end_pattern(m_p);
}
m_PDFlib->PDF_setcolor(m_p, "fill", "rgb", redPDF, greenPDF, bluePDF, 0);
if (!solid)
m_PDFlib->PDF_setcolor(m_p, "fill", "pattern", intPatHandle, 0, 0, 0);
}
PDF_CATCH_DL(m_PDFlib, m_p)
{
wxLogError("%s: %s", m_PDFlib->PDF_get_apiname(m_p), m_PDFlib->PDF_get_errmsg(m_p));
}
}
void TwxPDFDC::SetFontColor( const wxColour& color ) const
{
wxCHECK_RET( m_ok, wxT("invalid PDF dc") );
if (!color.Ok())
return;
PDF_TRY_DL(m_PDFlib, m_p)
{
const double redPDF = color.Red() / 255.0;
const double bluePDF = color.Blue() / 255.0;
const double greenPDF = color.Green() / 255.0;
m_PDFlib->PDF_setcolor(m_p, "fill", "rgb", redPDF, greenPDF, bluePDF, 0);
}
PDF_CATCH_DL(m_PDFlib, m_p)
{
wxLogError("%s: %s", m_PDFlib->PDF_get_apiname(m_p), m_PDFlib->PDF_get_errmsg(m_p));
}
}
void TwxPDFDC::SetAxisOrientation( bool xLeftRight, bool yBottomUp )
{
wxCHECK_RET( m_ok, wxT("invalid PDF dc") );
m_topDown = !yBottomUp;
//m_signX = (xLeftRight ? 1 : -1);
//m_signY = (yBottomUp ? 1 : -1);
PDF_TRY_DL(m_PDFlib, m_p)
{
m_PDFlib->PDF_set_parameter(m_p, "topdown", m_topDown?"true":"false");
}
PDF_CATCH_DL(m_PDFlib, m_p)
{
wxLogError("%s: %s", m_PDFlib->PDF_get_apiname(m_p), m_PDFlib->PDF_get_errmsg(m_p));
}
}
void TwxPDFDC::SetDeviceOrigin(wxCoord x, wxCoord y)
{
wxCHECK_RET( m_ok, wxT("invalid PDF dc") );
PDF_TRY_DL(m_PDFlib, m_p)
{
m_PDFlib->PDF_translate(m_p, x, y);
}
PDF_CATCH_DL(m_PDFlib, m_p)
{
wxLogError("%s: %s", m_PDFlib->PDF_get_apiname(m_p), m_PDFlib->PDF_get_errmsg(m_p));
}
}
//-- Page Size -----------------------------------------------------------
void TwxPDFDC::DoGetSizeMM(int* size_x, int* size_y) const
{
const wxSize s = m_printData.GetPaperSize();
if (m_printData.GetOrientation() == wxLANDSCAPE)
{
*size_x = s.y;
*size_y = s.x;
}
else
{
*size_x = s.x;
*size_y = s.y;
}
}
void TwxPDFDC::DoGetSize(int *width, int *height) const
{
DoGetSizeMM(width, height);
*width = *width * (10 * PDF_DPI) / 254 ;
*height = *height * (10 * PDF_DPI) / 254 ;
}
wxSize TwxPDFDC::GetPPI(void) const
{
return wxSize(PDF_DPI, PDF_DPI);
}
//-- Unimplemented -------------------------------------------------------
void TwxPDFDC::SetBackground (const wxBrush& brush)
{
// unimplemented
}
void TwxPDFDC::SetLogicalFunction (int WXUNUSED(function))
{
// unimplemented
}
void TwxPDFDC::Clear()
{
// unimplemented
}
bool TwxPDFDC::DoFloodFill (wxCoord WXUNUSED(x), wxCoord WXUNUSED(y), const wxColour &WXUNUSED(col), int WXUNUSED(style))
{
// unimplemented
return FALSE;
}
bool TwxPDFDC::DoGetPixel (wxCoord WXUNUSED(x), wxCoord WXUNUSED(y), wxColour * WXUNUSED(col)) const
{
// unimplemented
return FALSE;
}
void TwxPDFDC::DoCrossHair (wxCoord WXUNUSED(x), wxCoord WXUNUSED(y))
{
// unimplemented
}
//-- Clipping ------------------------------------------------------------
void TwxPDFDC::DoSetClippingRegion (wxCoord x, wxCoord y, wxCoord w, wxCoord h)
{
wxCHECK_RET( m_ok, wxT("invalid PDF dc") );
ResetClipping(); // Almost useless
m_clipX1 = x; m_clipX2 = x+w;
m_clipY1 = y; m_clipY2 = y+h;
m_clipping = true;
PDF_TRY_DL(m_PDFlib, m_p)
{
m_PDFlib->PDF_save(m_p);
m_PDFlib->PDF_moveto(m_p, x, y);
m_PDFlib->PDF_lineto(m_p, x+w, y);
m_PDFlib->PDF_lineto(m_p, x+w, y+h);
m_PDFlib->PDF_lineto(m_p, x, y+h);
m_PDFlib->PDF_closepath(m_p);
m_PDFlib->PDF_clip(m_p);
}
PDF_CATCH_DL(m_PDFlib, m_p)
{
wxLogError("%s: %s", m_PDFlib->PDF_get_apiname(m_p), m_PDFlib->PDF_get_errmsg(m_p));
}
}
void TwxPDFDC::DestroyClippingRegion()
{
wxCHECK_RET( m_ok, wxT("invalid PDF dc") );
if (m_clipping)
{
m_clipping = false;
PDF_TRY_DL(m_PDFlib, m_p)
{
m_PDFlib->PDF_restore(m_p);
}
PDF_CATCH_DL(m_PDFlib, m_p)
{
wxLogError("%s: %s", m_PDFlib->PDF_get_apiname(m_p), m_PDFlib->PDF_get_errmsg(m_p));
}
}
ResetClipping();
}