From 02255e07d75191d1146e21d4218835a79214a970 Mon Sep 17 00:00:00 2001 From: Robert Roebling Date: Mon, 10 Sep 2007 14:00:44 +0000 Subject: [PATCH] Rewrote scaling code for GNOME print backend. The inverted Y axis is now handled internally. Resulotion is not set to 600 dpi git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@48628 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- include/wx/dc.h | 87 ++++++++++++++++++++ include/wx/gtk/gnome/gprint.h | 40 +--------- src/common/dcbase.cpp | 6 +- src/common/prntbase.cpp | 43 ++++++---- src/gtk/gnome/gprint.cpp | 144 +++++++++++----------------------- 5 files changed, 169 insertions(+), 151 deletions(-) diff --git a/include/wx/dc.h b/include/wx/dc.h index b71344643e..a77cfee664 100644 --- a/include/wx/dc.h +++ b/include/wx/dc.h @@ -29,6 +29,7 @@ #include "wx/list.h" // we use wxList in inline functions #include "wx/dynarray.h" #include "wx/math.h" +#include "wx/image.h" // 1 if using the reorganized DC code #define wxUSE_NEW_DC 0 @@ -873,6 +874,49 @@ public: bool useMask = false) { m_pimpl->DoDrawBitmap(bmp, pt.x, pt.y, useMask); } + virtual void DrawScaledBitmap(const wxBitmap &bmp, wxCoord x, wxCoord y, wxCoord w, wxCoord h, bool useMask = false, int quality = wxIMAGE_QUALITY_NORMAL) + { + if (bmp.GetWidth() != w || bmp.GetHeight() != h) + { + if (quality != wxIMAGE_QUALITY_HIGH) + quality = wxIMAGE_QUALITY_NORMAL; + wxImage tmpImg = bmp.ConvertToImage(); + tmpImg.Rescale( w, h, quality ); + wxBitmap scaledBmp(tmpImg); + m_pimpl->DoDrawBitmap(scaledBmp, x, y, useMask); + } + else + m_pimpl->DoDrawBitmap(bmp, x, y, useMask); + } + virtual void DrawScaledBitmap(const wxBitmap &bmp, const wxPoint& pt, const wxSize& sz, bool useMask = false, int quality = wxIMAGE_QUALITY_NORMAL) + { + if (bmp.GetWidth() != sz.x || bmp.GetHeight() != sz.y) + { + if (quality != wxIMAGE_QUALITY_HIGH) + quality = wxIMAGE_QUALITY_NORMAL; + wxImage tmpImg = bmp.ConvertToImage(); + tmpImg.Rescale( sz.x, sz.y, quality ); + wxBitmap scaledBmp(tmpImg); + m_pimpl->DoDrawBitmap(scaledBmp, pt.x, pt.y, useMask); + } + else + m_pimpl->DoDrawBitmap(bmp, pt.x, pt.y, useMask); + } + virtual void DrawScaledBitmap(const wxBitmap &bmp, const wxRect& rect, bool useMask = false, int quality = wxIMAGE_QUALITY_NORMAL) + { + if (bmp.GetWidth() != rect.width || bmp.GetHeight() != rect.height) + { + if (quality != wxIMAGE_QUALITY_HIGH) + quality = wxIMAGE_QUALITY_NORMAL; + wxImage tmpImg = bmp.ConvertToImage(); + tmpImg.Rescale( rect.width, rect.height, quality ); + wxBitmap scaledBmp(tmpImg); + m_pimpl->DoDrawBitmap(scaledBmp, rect.x, rect.y, useMask); + } + else + m_pimpl->DoDrawBitmap(bmp, rect.x, rect.y, useMask); + } + void DrawText(const wxString& text, wxCoord x, wxCoord y) { m_pimpl->DoDrawText(text, x, y); } void DrawText(const wxString& text, const wxPoint& pt) @@ -1189,6 +1233,49 @@ public: bool useMask = false) { DoDrawBitmap(bmp, pt.x, pt.y, useMask); } + virtual void DrawScaledBitmap(const wxBitmap &bmp, wxCoord x, wxCoord y, wxCoord w, wxCoord h, bool useMask = false, int quality = wxIMAGE_QUALITY_NORMAL) + { + if (bmp.GetWidth() != w || bmp.GetHeight() != h) + { + if (quality != wxIMAGE_QUALITY_HIGH) + quality = wxIMAGE_QUALITY_NORMAL; + wxImage tmpImg = bmp.ConvertToImage(); + tmpImg.Rescale( w, h, quality ); + wxBitmap scaledBmp(tmpImg); + DoDrawBitmap(scaledBmp, x, y, useMask); + } + else + DoDrawBitmap(bmp, x, y, useMask); + } + virtual void DrawScaledBitmap(const wxBitmap &bmp, const wxPoint& pt, const wxSize& sz, bool useMask = false, int quality = wxIMAGE_QUALITY_NORMAL) + { + if (bmp.GetWidth() != sz.x || bmp.GetHeight() != sz.y) + { + if (quality != wxIMAGE_QUALITY_HIGH) + quality = wxIMAGE_QUALITY_NORMAL; + wxImage tmpImg = bmp.ConvertToImage(); + tmpImg.Rescale( sz.x, sz.y, quality ); + wxBitmap scaledBmp(tmpImg); + DoDrawBitmap(scaledBmp, pt.x, pt.y, useMask); + } + else + DoDrawBitmap(bmp, pt.x, pt.y, useMask); + } + virtual void DrawScaledBitmap(const wxBitmap &bmp, const wxRect& rect, bool useMask = false, int quality = wxIMAGE_QUALITY_NORMAL) + { + if (bmp.GetWidth() != rect.width || bmp.GetHeight() != rect.height) + { + if (quality != wxIMAGE_QUALITY_HIGH) + quality = wxIMAGE_QUALITY_NORMAL; + wxImage tmpImg = bmp.ConvertToImage(); + tmpImg.Rescale( rect.width, rect.height, quality ); + wxBitmap scaledBmp(tmpImg); + DoDrawBitmap(scaledBmp, rect.x, rect.y, useMask); + } + else + DoDrawBitmap(bmp, rect.x, rect.y, useMask); + } + void DrawText(const wxString& text, wxCoord x, wxCoord y) { DoDrawText(text, x, y); } void DrawText(const wxString& text, const wxPoint& pt) diff --git a/include/wx/gtk/gnome/gprint.h b/include/wx/gtk/gnome/gprint.h index e49838e62e..59d3be5521 100644 --- a/include/wx/gtk/gnome/gprint.h +++ b/include/wx/gtk/gnome/gprint.h @@ -232,9 +232,6 @@ public: wxCoord GetCharWidth() const; bool CanGetTextExtent() const { return true; } wxSize GetPPI() const; - void SetAxisOrientation( bool xLeftRight, bool yBottomUp ); - void SetLogicalOrigin( wxCoord x, wxCoord y ); - void SetDeviceOrigin( wxCoord x, wxCoord y ); virtual int GetDepth() const { return 24; } void SetBackgroundMode(int WXUNUSED(mode)) { } void SetPalette(const wxPalette& WXUNUSED(palette)) { } @@ -289,47 +286,14 @@ private: unsigned char m_currentRed; unsigned char m_currentGreen; unsigned char m_currentBlue; - - int m_deviceOffsetY; + + double m_pageHeight; GnomePrintContext *m_gpc; GnomePrintJob* m_job; void makeEllipticalPath(wxCoord x, wxCoord y, wxCoord width, wxCoord height); -private: - wxCoord XDEV2LOG(wxCoord x) const - { - return wxRound((double)(x - m_deviceOriginX) / m_scaleX) * m_signX + m_logicalOriginX; - } - wxCoord XDEV2LOGREL(wxCoord x) const - { - return wxRound((double)(x) / m_scaleX); - } - wxCoord YDEV2LOG(wxCoord y) const - { - return wxRound((double)(y + m_deviceOriginY - m_deviceOffsetY) / m_scaleY) * m_signY + m_logicalOriginY; - } - wxCoord YDEV2LOGREL(wxCoord y) const - { - return wxRound((double)(y) / m_scaleY); - } - wxCoord XLOG2DEV(wxCoord x) const - { - return wxRound((double)(x - m_logicalOriginX) * m_scaleX) * m_signX + m_deviceOriginX; - } - wxCoord XLOG2DEVREL(wxCoord x) const - { - return wxRound((double)(x) * m_scaleX); - } - wxCoord YLOG2DEV(wxCoord y) const - { - return wxRound((double)(y - m_logicalOriginY) * m_scaleY) * m_signY - m_deviceOriginY + m_deviceOffsetY; - } - wxCoord YLOG2DEVREL(wxCoord y) const - { - return wxRound((double)(y) * m_scaleY); - } private: DECLARE_DYNAMIC_CLASS(wxGnomePrintDC) DECLARE_NO_COPY_CLASS(wxGnomePrintDC) diff --git a/src/common/dcbase.cpp b/src/common/dcbase.cpp index 94eba63f8b..9f28a5f0ad 100644 --- a/src/common/dcbase.cpp +++ b/src/common/dcbase.cpp @@ -513,12 +513,12 @@ wxCoord wxImplDC::DeviceToLogicalYRel(wxCoord y) const wxCoord wxImplDC::LogicalToDeviceX(wxCoord x) const { - return wxRound((double)(x - m_logicalOriginX) * m_scaleX) * m_signX + m_deviceOriginX + m_deviceLocalOriginX; + return wxRound((double)(x - m_logicalOriginX) * m_scaleX) * m_signX + m_deviceOriginX * m_signY + m_deviceLocalOriginX; } wxCoord wxImplDC::LogicalToDeviceY(wxCoord y) const { - return wxRound((double)(y - m_logicalOriginY) * m_scaleY) * m_signY + m_deviceOriginY + m_deviceLocalOriginY; + return wxRound((double)(y - m_logicalOriginY) * m_scaleY) * m_signY + m_deviceOriginY * m_signY + m_deviceLocalOriginY; } wxCoord wxImplDC::LogicalToDeviceXRel(wxCoord x) const @@ -601,6 +601,7 @@ void wxImplDC::SetDeviceLocalOrigin( wxCoord x, wxCoord y ) void wxImplDC::SetAxisOrientation( bool xLeftRight, bool yBottomUp ) { // only wxPostScripDC has m_signX = -1, we override SetAxisOrientation there + // wxWidgets 2.9: no longer override it m_signX = (xLeftRight ? 1 : -1); m_signY = (yBottomUp ? -1 : 1); ComputeScaleAndOrigin(); @@ -1706,6 +1707,7 @@ void wxDCBase::SetDeviceLocalOrigin( wxCoord x, wxCoord y ) void wxDCBase::SetAxisOrientation( bool xLeftRight, bool yBottomUp ) { // only wxPostScripDC has m_signX = -1, we override SetAxisOrientation there + // wxWidgets 2.9: no longer override it m_signX = (xLeftRight ? 1 : -1); m_signY = (yBottomUp ? -1 : 1); ComputeScaleAndOrigin(); diff --git a/src/common/prntbase.cpp b/src/common/prntbase.cpp index a71ce9e69d..25bbd8ae09 100644 --- a/src/common/prntbase.cpp +++ b/src/common/prntbase.cpp @@ -733,28 +733,42 @@ wxRect wxPrintout::GetLogicalPageMarginsRect(const wxPageSetupDialogData& pageSe // Return the rectangle in logical units that corresponds to the region // within the page margins as specified by the given wxPageSetupDialogData // object. - wxRect paperRect = GetPaperRectPixels(); + + // We get the paper size in device units and the margins in mm, + // so we need to calculate the conversion with this trick wxCoord pw, ph; GetPageSizePixels(&pw, &ph); - wxPoint topLeft = pageSetupData.GetMarginTopLeft(); - wxPoint bottomRight = pageSetupData.GetMarginBottomRight(); wxCoord mw, mh; GetPageSizeMM(&mw, &mh); float mmToDeviceX = float(pw) / mw; float mmToDeviceY = float(ph) / mh; - wxRect pageMarginsRect(paperRect.x + wxRound(mmToDeviceX * topLeft.x), - paperRect.y + wxRound(mmToDeviceY * topLeft.y), - paperRect.width - wxRound(mmToDeviceX * (topLeft.x + bottomRight.x)), + + // paper size in device units + wxRect paperRect = GetPaperRectPixels(); + + // margins in mm + wxPoint topLeft = pageSetupData.GetMarginTopLeft(); + wxPoint bottomRight = pageSetupData.GetMarginBottomRight(); + + // calculate margins in device units + wxRect pageMarginsRect( + paperRect.x + wxRound(mmToDeviceX * topLeft.x), + paperRect.y + wxRound(mmToDeviceY * topLeft.y), + paperRect.width - wxRound(mmToDeviceX * (topLeft.x + bottomRight.x)), paperRect.height - wxRound(mmToDeviceY * (topLeft.y + bottomRight.y))); + wxCoord w, h; m_printoutDC->GetSize(&w, &h); - if (w == pw && h == ph) { + if (w == pw && h == ph) + { // this DC matches the printed page, so no scaling - return wxRect(m_printoutDC->DeviceToLogicalX(pageMarginsRect.x), + return wxRect( + m_printoutDC->DeviceToLogicalX(pageMarginsRect.x), m_printoutDC->DeviceToLogicalY(pageMarginsRect.y), m_printoutDC->DeviceToLogicalXRel(pageMarginsRect.width), m_printoutDC->DeviceToLogicalYRel(pageMarginsRect.height)); } + // This DC doesn't match the printed page, so we have to scale. float scaleX = float(w) / pw; float scaleY = float(h) / ph; @@ -767,17 +781,18 @@ wxRect wxPrintout::GetLogicalPageMarginsRect(const wxPageSetupDialogData& pageSe void wxPrintout::SetLogicalOrigin(wxCoord x, wxCoord y) { // Set the device origin by specifying a point in logical coordinates. - m_printoutDC->SetDeviceOrigin(m_printoutDC->LogicalToDeviceX(x), - m_printoutDC->LogicalToDeviceY(y)); + m_printoutDC->SetDeviceOrigin( + m_printoutDC->LogicalToDeviceX(x), + m_printoutDC->LogicalToDeviceY(y) ); } void wxPrintout::OffsetLogicalOrigin(wxCoord xoff, wxCoord yoff) { // Offset the device origin by a specified distance in device coordinates. - wxCoord x = m_printoutDC->LogicalToDeviceX(0); - wxCoord y = m_printoutDC->LogicalToDeviceY(0); - m_printoutDC->SetDeviceOrigin(x + m_printoutDC->LogicalToDeviceXRel(xoff), - y + m_printoutDC->LogicalToDeviceYRel(yoff)); + wxPoint dev_org = m_printoutDC->GetDeviceOrigin(); + m_printoutDC->SetDeviceOrigin( + dev_org.x + m_printoutDC->LogicalToDeviceXRel(xoff), + dev_org.y + m_printoutDC->LogicalToDeviceYRel(yoff) ); } diff --git a/src/gtk/gnome/gprint.cpp b/src/gtk/gnome/gprint.cpp index 5e5aa5c796..41a53a64f3 100644 --- a/src/gtk/gnome/gprint.cpp +++ b/src/gtk/gnome/gprint.cpp @@ -40,8 +40,6 @@ #include #include -static const double RAD2DEG = 180.0 / M_PI; - #include "wx/link.h" wxFORCE_LINK_THIS_MODULE(gnome_print) @@ -945,6 +943,19 @@ bool wxGnomePrinter::Setup( wxWindow *parent ) // wxGnomePrintDC //----------------------------------------------------------------------------- +// conversion +static const double RAD2DEG = 180.0 / M_PI; + +// we don't want to use only 72 dpi from GNOME print +static const int DPI = 600; +static const double PS2DEV = 600.0 / 72.0; +static const double DEV2PS = 72.0 / 600.0; + +#define XLOG2DEV(x) ((double)(LogicalToDeviceX(x)) * DEV2PS) +#define XLOG2DEVREL(x) ((double)(LogicalToDeviceXRel(x)) * DEV2PS) +#define YLOG2DEV(x) ((m_pageHeight - (double)LogicalToDeviceY(x)) * DEV2PS) +#define YLOG2DEVREL(x) ((double)(LogicalToDeviceYRel(x)) * DEV2PS) + IMPLEMENT_CLASS(wxGnomePrintDC, wxDC) wxGnomePrintDC::wxGnomePrintDC( const wxPrintData& data ) @@ -965,10 +976,11 @@ wxGnomePrintDC::wxGnomePrintDC( const wxPrintData& data ) m_currentBlue = 0; m_currentGreen = 0; - m_signX = 1; // default x-axis left to right - m_signY = -1; // default y-axis bottom up -> top down + // Query page size. This seems to omit the margins + double pw,ph; + gs_lgp->gnome_print_job_get_page_size( native->GetPrintJob(), &pw, &ph ); - GetSize( NULL, &m_deviceOffsetY ); + m_pageHeight = ph * PS2DEV; } wxGnomePrintDC::~wxGnomePrintDC() @@ -1069,8 +1081,8 @@ void wxGnomePrintDC::DoDrawEllipticArc(wxCoord x,wxCoord y,wxCoord w,wxCoord h,d x += w/2; y += h/2; - int xx = XLOG2DEV(x); - int yy = YLOG2DEV(y); + double xx = XLOG2DEV(x); + double yy = YLOG2DEV(y); gs_libGnomePrint->gnome_print_gsave( m_gpc ); @@ -1078,8 +1090,8 @@ void wxGnomePrintDC::DoDrawEllipticArc(wxCoord x,wxCoord y,wxCoord w,wxCoord h,d double scale = (double)YLOG2DEVREL(h) / (double) XLOG2DEVREL(w); gs_libGnomePrint->gnome_print_scale( m_gpc, 1.0, scale ); - xx = 0; - yy = 0; + xx = 0.0; + yy = 0.0; if (m_brush.GetStyle () != wxTRANSPARENT) { @@ -1496,8 +1508,8 @@ void wxGnomePrintDC::DoDrawText(const wxString& text, wxCoord x, wxCoord y ) void wxGnomePrintDC::DoDrawRotatedText(const wxString& text, wxCoord x, wxCoord y, double angle) { - x = XLOG2DEV(x); - y = YLOG2DEV(y); + double xx = XLOG2DEV(x); + double yy = YLOG2DEV(y); bool underlined = m_font.Ok() && m_font.GetUnderlined(); @@ -1543,76 +1555,30 @@ void wxGnomePrintDC::DoDrawRotatedText(const wxString& text, wxCoord x, wxCoord } int w,h; - - if (fabs(m_scaleY - 1.0) > 0.00001) - { - // If there is a user or actually any scale applied to - // the device context, scale the font. - - // scale font description - gint oldSize = pango_font_description_get_size( m_fontdesc ); - double size = oldSize; - size = size * m_scaleY; - pango_font_description_set_size( m_fontdesc, (gint)size ); - - // actually apply scaled font - pango_layout_set_font_description( m_layout, m_fontdesc ); - - pango_layout_get_pixel_size( m_layout, &w, &h ); + pango_layout_get_pixel_size( m_layout, &w, &h ); #if 0 if ( m_backgroundMode == wxSOLID ) { gdk_gc_set_foreground(m_textGC, m_textBackgroundColour.GetColor()); - gdk_draw_rectangle(m_window, m_textGC, TRUE, x, y, w, h); + gdk_draw_rectangle(m_window, m_textGC, TRUE, xx, yy, w, h); gdk_gc_set_foreground(m_textGC, m_textForegroundColour.GetColor()); } #endif - // Draw layout. - gs_libGnomePrint->gnome_print_moveto (m_gpc, x, y); - if (fabs(angle) > 0.00001) - { - gs_libGnomePrint->gnome_print_gsave( m_gpc ); - gs_libGnomePrint->gnome_print_rotate( m_gpc, angle ); - gs_libGnomePrint->gnome_print_pango_layout( m_gpc, m_layout ); - gs_libGnomePrint->gnome_print_grestore( m_gpc ); - } - else - { - gs_libGnomePrint->gnome_print_pango_layout( m_gpc, m_layout ); - } - - // reset unscaled size - pango_font_description_set_size( m_fontdesc, oldSize ); - - // actually apply unscaled font - pango_layout_set_font_description( m_layout, m_fontdesc ); - } - else - { - pango_layout_get_pixel_size( m_layout, &w, &h ); -#if 0 - if ( m_backgroundMode == wxSOLID ) - { - gdk_gc_set_foreground(m_textGC, m_textBackgroundColour.GetColor()); - gdk_draw_rectangle(m_window, m_textGC, TRUE, x, y, w, h); - gdk_gc_set_foreground(m_textGC, m_textForegroundColour.GetColor()); - } -#endif - // Draw layout. - gs_libGnomePrint->gnome_print_moveto (m_gpc, x, y); - if (fabs(angle) > 0.00001) - { - gs_libGnomePrint->gnome_print_gsave( m_gpc ); - gs_libGnomePrint->gnome_print_rotate( m_gpc, angle ); - gs_libGnomePrint->gnome_print_pango_layout( m_gpc, m_layout ); - gs_libGnomePrint->gnome_print_grestore( m_gpc ); - } - else - { - gs_libGnomePrint->gnome_print_pango_layout( m_gpc, m_layout ); - } - } + // Draw layout. + gs_libGnomePrint->gnome_print_moveto (m_gpc, xx, yy); + + gs_libGnomePrint->gnome_print_gsave( m_gpc ); + + gs_libGnomePrint->gnome_print_scale( m_gpc, m_scaleX * DEV2PS, m_scaleY * DEV2PS ); + + if (fabs(angle) > 0.00001) + gs_libGnomePrint->gnome_print_rotate( m_gpc, angle ); + + gs_libGnomePrint->gnome_print_pango_layout( m_gpc, m_layout ); + + gs_libGnomePrint->gnome_print_grestore( m_gpc ); + if (underlined) { // undo underline attributes setting: @@ -1891,9 +1857,9 @@ void wxGnomePrintDC::DoGetSize(int* width, int* height) const gs_libGnomePrint->gnome_print_job_get_page_size( native->GetPrintJob(), &pw, &ph ); if (width) - *width = (int) (pw + 0.5); + *width = wxRound( pw * PS2DEV ); if (height) - *height = (int) (ph + 0.5); + *height = wxRound( ph * PS2DEV ); } void wxGnomePrintDC::DoGetSizeMM(int *width, int *height) const @@ -1921,35 +1887,19 @@ void wxGnomePrintDC::DoGetSizeMM(int *width, int *height) const wxSize wxGnomePrintDC::GetPPI() const { - return wxSize(72,72); -} - -void wxGnomePrintDC::SetAxisOrientation( bool xLeftRight, bool yBottomUp ) -{ - m_signX = (xLeftRight ? 1 : -1); - m_signY = (yBottomUp ? 1 : -1); - - ComputeScaleAndOrigin(); -} - -void wxGnomePrintDC::SetLogicalOrigin( wxCoord x, wxCoord y ) -{ - wxDC::SetLogicalOrigin( x, y ); -} - -void wxGnomePrintDC::SetDeviceOrigin( wxCoord x, wxCoord y ) -{ - wxDC::SetDeviceOrigin( x, y ); + return wxSize(DPI,DPI); } void wxGnomePrintDC::SetPrintData(const wxPrintData& data) { m_printData = data; + int height; if (m_printData.GetOrientation() == wxPORTRAIT) - GetSize( NULL, &m_deviceOffsetY ); + GetSize( NULL, &height ); else - GetSize( &m_deviceOffsetY, NULL ); + GetSize( &height, NULL ); + m_deviceLocalOriginY = height; } void wxGnomePrintDC::SetResolution(int ppi) @@ -1958,7 +1908,7 @@ void wxGnomePrintDC::SetResolution(int ppi) int wxGnomePrintDC::GetResolution() { - return 72; + return DPI; } // ----------------------------------------------------------------------------