CAIRO_PRINT_CTX class
CAIRO_PRINT_CTX provides a Cairo context created from wxPrintDC. It allows one to prepare printouts using the Cairo library and let wxWidgets handle the rest.
This commit is contained in:
parent
f948e46330
commit
5a64343fb4
|
@ -67,6 +67,7 @@ set( GAL_SRCS
|
|||
# Cairo GAL
|
||||
gal/cairo/cairo_gal.cpp
|
||||
gal/cairo/cairo_compositor.cpp
|
||||
gal/cairo/cairo_print.cpp
|
||||
)
|
||||
|
||||
set( LEGACY_GAL_SRCS
|
||||
|
|
|
@ -0,0 +1,181 @@
|
|||
/*
|
||||
* Copyright (C) 2018 CERN
|
||||
* Author: Maciej Suminski <maciej.suminski@cern.ch>
|
||||
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <gal/cairo/cairo_print.h>
|
||||
|
||||
#include <stdexcept>
|
||||
#include <wx/dcclient.h>
|
||||
#include <wx/dcgraph.h>
|
||||
#include <wx/dcmemory.h>
|
||||
#include <wx/dcprint.h>
|
||||
|
||||
#ifdef __WXMSW__
|
||||
#include <windows.h>
|
||||
#include <gdiplus.h>
|
||||
#include <cairo-win32.h>
|
||||
#include <wx/msw/enhmeta.h>
|
||||
#endif /* __WXMSW__ */
|
||||
|
||||
#ifdef __WXMAC__
|
||||
#include <ApplicationServices/ApplicationServices.h>
|
||||
#include <cairo-quartz.h>
|
||||
#endif /* __WXMAC__ */
|
||||
|
||||
using namespace KIGFX;
|
||||
|
||||
CAIRO_PRINT_CTX::CAIRO_PRINT_CTX( wxDC* aDC )
|
||||
: m_gcdc( nullptr ), m_ctx( nullptr ), m_surface( nullptr )
|
||||
{
|
||||
if( wxPrinterDC* printerDC = dynamic_cast<wxPrinterDC*>( aDC ) )
|
||||
m_gcdc = new wxGCDC( *printerDC );
|
||||
else if( wxMemoryDC* memoryDC = dynamic_cast<wxMemoryDC*>( aDC ) )
|
||||
m_gcdc = new wxGCDC( *memoryDC );
|
||||
else if( wxWindowDC* windowDC = dynamic_cast<wxWindowDC*>( aDC ) )
|
||||
m_gcdc = new wxGCDC( *windowDC );
|
||||
#ifdef __WXMSW__
|
||||
else if( wxEnhMetaFileDC* enhMFDC = dynamic_cast<wxEnhMetaFileDC*>( aDC ) )
|
||||
m_gcdc = new wxGCDC( *enhMFDC );
|
||||
#endif /* __WXMSW__ */
|
||||
else
|
||||
throw std::runtime_error( "Unhandled wxDC type" );
|
||||
|
||||
wxGraphicsContext* gctx = m_gcdc->GetGraphicsContext();
|
||||
|
||||
if( !gctx )
|
||||
throw std::runtime_error( "Could not get the Graphics Context" );
|
||||
|
||||
#ifdef __WXGTK__
|
||||
m_ctx = static_cast<cairo_t*>( gctx->GetNativeContext() );
|
||||
m_surface = cairo_get_target( m_ctx );
|
||||
// Magic value: apparently for linux, all printers are 72 DPI
|
||||
m_dpi = 72.0;
|
||||
#endif /* __WXGTK__ */
|
||||
|
||||
#ifdef __WXMSW__
|
||||
Gdiplus::Graphics* g = static_cast<Gdiplus::Graphics*>( gctx->GetNativeContext() );
|
||||
m_hdc = g->GetHDC();
|
||||
m_surface = cairo_win32_printing_surface_create( static_cast<HDC>( m_hdc ) );
|
||||
m_ctx = cairo_create( m_surface );
|
||||
m_dpi = GetDeviceCaps( static_cast<HDC>( m_hdc ), LOGPIXELSX );
|
||||
#endif /* __WXMSW__ */
|
||||
|
||||
#ifdef __WXMAC__
|
||||
wxSize size = m_gcdc->GetSize();
|
||||
CGContextRef cg = (CGContextRef) gctx->GetNativeContext();
|
||||
m_surface = cairo_quartz_surface_create_for_cg_context( cg, size.x, size.y );
|
||||
m_ctx = cairo_create( m_surface );
|
||||
wxASSERT( aDC->GetPPI().x == aDC->GetPPI().y );
|
||||
m_dpi = aDC->GetPPI().x;
|
||||
#endif /* __WXMAC__ */
|
||||
|
||||
if( !m_ctx || cairo_status( m_ctx ) != CAIRO_STATUS_SUCCESS )
|
||||
throw std::runtime_error( "Could not create Cairo context" );
|
||||
|
||||
if( !m_surface || cairo_surface_status( m_surface ) != CAIRO_STATUS_SUCCESS )
|
||||
throw std::runtime_error( "Could not create Cairo surface" );
|
||||
|
||||
cairo_reference( m_ctx );
|
||||
cairo_surface_reference( m_surface );
|
||||
}
|
||||
|
||||
|
||||
CAIRO_PRINT_CTX::~CAIRO_PRINT_CTX()
|
||||
{
|
||||
#ifdef __WXMSW__
|
||||
cairo_surface_show_page( m_surface );
|
||||
wxGraphicsContext* gctx = m_gcdc->GetGraphicsContext();
|
||||
Gdiplus::Graphics* g = static_cast<Gdiplus::Graphics*>( gctx->GetNativeContext() );
|
||||
g->ReleaseHDC( static_cast<HDC>( m_hdc ) );
|
||||
#endif /* __WXMSW__ */
|
||||
|
||||
cairo_surface_destroy( m_surface );
|
||||
cairo_destroy( m_ctx );
|
||||
delete m_gcdc;
|
||||
}
|
||||
|
||||
|
||||
CAIRO_PRINT_GAL::CAIRO_PRINT_GAL( GAL_DISPLAY_OPTIONS& aDisplayOptions,
|
||||
cairo_t* aContext, cairo_surface_t* aSurface )
|
||||
: CAIRO_GAL_BASE( aDisplayOptions )
|
||||
{
|
||||
cairo_reference( aContext );
|
||||
cairo_surface_reference( aSurface );
|
||||
context = currentContext = aContext;
|
||||
surface = aSurface;
|
||||
m_clearColor = COLOR4D( 1.0, 1.0, 1.0, 1.0 );
|
||||
resetContext();
|
||||
}
|
||||
|
||||
|
||||
void CAIRO_PRINT_GAL::ComputeWorldScreenMatrix()
|
||||
{
|
||||
// worldUnitLength = inch per integer
|
||||
worldUnitLength = 1e-9 /* 1 nm */ / 0.0254 /* 1 inch in meters */;
|
||||
worldScale = screenDPI * worldUnitLength * zoomFactor;
|
||||
|
||||
const auto paperSizeIU = VECTOR2D( m_nativePaperSize.y, m_nativePaperSize.x ) /* inches */ * 0.0254 * 1e9 /* 1 inch in nm */;
|
||||
const auto paperSizeIUTransposed = VECTOR2D( paperSizeIU.y, paperSizeIU.x );
|
||||
|
||||
MATRIX3x3D scale, translation, flip, rotate, lookat;
|
||||
|
||||
scale.SetIdentity();
|
||||
translation.SetIdentity();
|
||||
flip.SetIdentity();
|
||||
rotate.SetIdentity();
|
||||
lookat.SetIdentity();
|
||||
|
||||
if( m_hasNativeLandscapeRotation )
|
||||
{
|
||||
translation.SetTranslation( 0.5 / GetZoomFactor() * paperSizeIUTransposed );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( isLandscape() )
|
||||
{
|
||||
translation.SetTranslation( 0.5 / GetZoomFactor() * paperSizeIU );
|
||||
rotate.SetRotation( 90.0 * M_PI / 180.0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
translation.SetTranslation( 0.5 / GetZoomFactor() * paperSizeIUTransposed );
|
||||
}
|
||||
}
|
||||
|
||||
scale.SetScale( VECTOR2D( worldScale, worldScale ) );
|
||||
flip.SetScale( VECTOR2D( globalFlipX ? -1.0 : 1.0, globalFlipY ? -1.0 : 1.0 ) );
|
||||
lookat.SetTranslation( -lookAtPoint );
|
||||
|
||||
worldScreenMatrix = scale * translation * flip * rotate * lookat;
|
||||
screenWorldMatrix = worldScreenMatrix.Inverse();
|
||||
}
|
||||
|
||||
|
||||
void CAIRO_PRINT_GAL::SetNativePaperSize( const VECTOR2D& aSize, bool aHasNativeLandscapeRotation )
|
||||
{
|
||||
m_nativePaperSize = aSize;
|
||||
m_hasNativeLandscapeRotation = aHasNativeLandscapeRotation;
|
||||
}
|
||||
|
||||
|
||||
void CAIRO_PRINT_GAL::SetSheetSize( const VECTOR2D& aSize )
|
||||
{
|
||||
// Convert aSize (inches) to pixels
|
||||
SetScreenSize( VECTOR2I( std::ceil( aSize.x * screenDPI ) * 2,
|
||||
std::ceil( aSize.y * screenDPI ) * 2 ) );
|
||||
}
|
|
@ -0,0 +1,115 @@
|
|||
/*
|
||||
* Copyright (C) 2018 CERN
|
||||
* Author: Maciej Suminski <maciej.suminski@cern.ch>
|
||||
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _CAIRO_PRINT_H_
|
||||
#define _CAIRO_PRINT_H_
|
||||
|
||||
#include <gal/cairo/cairo_gal.h>
|
||||
|
||||
class wxDC;
|
||||
class wxGCDC;
|
||||
|
||||
namespace KIGFX
|
||||
{
|
||||
/**
|
||||
* CAIRO_PRINT_CTX provides a Cairo context created from wxPrintDC.
|
||||
* It allows one to prepare printouts using the Cairo library and let wxWidgets handle the rest.
|
||||
*/
|
||||
class CAIRO_PRINT_CTX
|
||||
{
|
||||
public:
|
||||
CAIRO_PRINT_CTX( wxDC* aDC );
|
||||
~CAIRO_PRINT_CTX();
|
||||
|
||||
cairo_t* GetContext() const
|
||||
{
|
||||
return m_ctx;
|
||||
}
|
||||
|
||||
cairo_surface_t* GetSurface() const
|
||||
{
|
||||
return m_surface;
|
||||
}
|
||||
|
||||
double GetNativeDPI() const
|
||||
{
|
||||
return m_dpi;
|
||||
}
|
||||
|
||||
bool HasNativeLandscapeRotation() const
|
||||
{
|
||||
#ifdef __WXGTK__
|
||||
return false;
|
||||
#else
|
||||
return true;
|
||||
#endif /* not __WXGTK__ */
|
||||
}
|
||||
|
||||
private:
|
||||
wxGCDC* m_gcdc;
|
||||
cairo_t* m_ctx;
|
||||
cairo_surface_t* m_surface;
|
||||
|
||||
#ifdef __WXMSW__
|
||||
///> DC handle on Windows
|
||||
void* m_hdc; // the real type is HDC, but do not pull in extra headers
|
||||
#endif /* __WXMSW__ */
|
||||
|
||||
double m_dpi;
|
||||
};
|
||||
|
||||
|
||||
class CAIRO_PRINT_GAL : public CAIRO_GAL_BASE
|
||||
{
|
||||
public:
|
||||
CAIRO_PRINT_GAL( GAL_DISPLAY_OPTIONS& aDisplayOptions,
|
||||
cairo_t* aContext, cairo_surface_t* aSurface );
|
||||
|
||||
void ComputeWorldScreenMatrix() override;
|
||||
|
||||
/**
|
||||
* @param aSize is the printing sheet size expressed in inches.
|
||||
* @param aRotateIfLandscape true if the platform requires 90 degrees
|
||||
* rotation in order to print in landscape format.
|
||||
*/
|
||||
void SetNativePaperSize( const VECTOR2D& aSize, bool aRotateIfLandscape );
|
||||
|
||||
/**
|
||||
* @param aSize is the schematics sheet size expressed in inches.
|
||||
*/
|
||||
void SetSheetSize( const VECTOR2D& aSize );
|
||||
|
||||
private:
|
||||
///> Returns true if page orientation is landscape
|
||||
bool isLandscape() const
|
||||
{
|
||||
return m_nativePaperSize.x > m_nativePaperSize.y;
|
||||
}
|
||||
|
||||
///> Printout size
|
||||
VECTOR2D m_nativePaperSize;
|
||||
|
||||
///> Flag indicating whether the platform rotates page automatically or
|
||||
///> GAL needs to handle it in the transformation matrix
|
||||
bool m_hasNativeLandscapeRotation;
|
||||
|
||||
};
|
||||
} // namespace KIGFX
|
||||
|
||||
#endif /* _CAIRO_PRINT_H_ */
|
Loading…
Reference in New Issue