campo-sirio/xvaga/xvtpdf.cpp
guy c5797bd448 Patch level : 10.0 272
Files correlati     : xvaga.dll
Ricompilazione Demo : [ ]
Commento            :
0001220: Esportazione in PDF
Se imposto il foglio in orizzontale, l'esportazione in pdf sembra rigirare il foglio in verticale troncando la stampa. Impostando la stampante come pdf creator la stampa viene corretta.


git-svn-id: svn://10.65.10.50/trunk@18609 c028cbd2-c16b-5b4b-a496-9718f37d4682
2009-03-25 15:49:53 +00:00

1210 lines
31 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] = "";
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");
}
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") );
m_clipping = false;
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_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 (m_pen.GetStyle () != wxTRANSPARENT)
SetPen(m_pen);
if (m_brush.GetStyle() != wxTRANSPARENT)
SetBrush(m_brush);
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;
}
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)
{
double smallest = 0.0;
if (width < height)
smallest = width;
else
smallest = 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));
}
}
//-- 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;
int intNewHandle = -1;
for (int i=PDF_IMG_CACHE_SIZE;i>0;i--)
{
int idx = (i + m_cacheidx) % PDF_IMG_CACHE_SIZE;
if (m_filenames[idx]!="" && m_filenames[idx]==name)
intFound = idx;
if (intFound>=0)
break;
}
if (intFound<0 && (intNewHandle=m_PDFlib->PDF_load_image(m_p, "auto", name, 0, ""))>=0)
{
PDF_TRY_DL(m_PDFlib, m_p)
{
m_filenames[m_cacheidx] = name;
m_handles[m_cacheidx] = intNewHandle;
intFound = m_cacheidx;
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 m_handles[intFound];
}
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_fontsize);
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
{
if (m_font.Ok())
return m_fontsize;
else
return (12 * PDF_DPI) / 72;
}
wxCoord TwxPDFDC::GetCharWidth() const
{
return (wxCoord) (GetCharHeight() * 72.0 / 120.0);
}
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 ((theFont==NULL&&m_font.Ok()) || (m_font.Ok()&&(*theFont==m_font)))
{
if (x)
*x = m_PDFlib->PDF_stringwidth(m_p, text, m_fontnr, m_fontsize);
if (y)
*y = m_fontsize;
}
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 = 0;
if (e)
*e = 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));
}
}
//-- 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_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;
unsigned char red = m_pen.GetColour().Red();
unsigned char blue = m_pen.GetColour().Blue();
unsigned char green = m_pen.GetColour().Green();
double redPDF = (double)(red) / 255.0;
double bluePDF = (double)(blue) / 255.0;
double greenPDF = (double)(green) / 255.0;
int intStyle = m_pen.GetStyle();
bool solid = false;
switch (intStyle)
{
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")
{
int intWidth = m_pen.GetWidth();
if (intWidth == 0)
intWidth = 1;
m_PDFlib->PDF_setlinewidth(m_p, 1000 * intWidth / 1000.0f);
if (!solid)
m_PDFlib->PDF_setdashpattern(m_p, pdfdash);
else
m_PDFlib->PDF_setdash(m_p, 0, 0);
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 wxColor& color ) const
{
wxCHECK_RET( m_ok, wxT("invalid PDF dc") );
if (!color.Ok())
return;
unsigned char red = color.Red();
unsigned char blue = color.Blue();
unsigned char green = color.Green();
double redPDF = (double)(red) / 255.0;
double bluePDF = (double)(blue) / 255.0;
double greenPDF = (double)(green) / 255.0;
PDF_TRY_DL(m_PDFlib, m_p)
{
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") );
if (m_clipping)
DestroyClippingRegion();
wxDC::DoSetClippingRegion(x, y, w, 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));
}
}
wxDC::DestroyClippingRegion();
}