#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_pageNumber = 0; m_topDown = true; m_clipping = false; m_pageopen = false; m_printData = printData; m_fileName = strFilename; 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) wxLogError( _("Cannot create PDFlib object (DLL not found?)\n")); } TwxPDFDC::~TwxPDFDC () { if (m_PDFlib != NULL) PDF_delete_dl(m_PDFlib, m_p); } //-- 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!")); m_ok = false; return false; } PDF_TRY_DL(m_PDFlib, m_p) { const wxString strFontPath = ::wxGetOSDirectory() + "\\Fonts"; m_PDFlib->PDF_set_parameter(m_p, "SearchPath", strFontPath); } 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; m_ok = true; return 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; int size_x, size_y; DoGetSize (&size_x, &size_y); m_pageNumber++; SetAxisOrientation(true, false); PDF_TRY_DL(m_PDFlib, m_p) { m_PDFlib->PDF_begin_page_ext(m_p, size_x * 72.0 / PDF_DPI, size_y * 72.0 / PDF_DPI, ""); m_PDFlib->PDF_scale(m_p, (72.0 / PDF_DPI), (72.0 / PDF_DPI)); 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;iPDF_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;iPDF_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::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() || 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; } 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(); }