de3f13e217
Skia does not work with a native print graphics contexts. I am not sure why but from what I can see, the Skia implementation drawing to a bitmap buffer. However, in an NSPrintOperation, the print view's backing buffer is CGPDFContext so even if this bug could be solved by blitting the Skia bitmap buffer, the printed PDF would not have selectable text so always disable Skia for print graphics contexts. Change-Id: I214ba83b6e368af3ef51ea770b093612d04047a0 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/143798 Tested-by: Jenkins Reviewed-by: Caolán McNamara <caolanm@redhat.com>
678 lines
24 KiB
C++
678 lines
24 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
/*
|
|
* This file is part of the LibreOffice project.
|
|
*
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
*
|
|
* This file incorporates work covered by the following license notice:
|
|
*
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
* contributor license agreements. See the NOTICE file distributed
|
|
* with this work for additional information regarding copyright
|
|
* ownership. The ASF licenses this file to you under the Apache
|
|
* License, Version 2.0 (the "License"); you may not use this file
|
|
* except in compliance with the License. You may obtain a copy of
|
|
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
|
|
*/
|
|
|
|
#include <officecfg/Office/Common.hxx>
|
|
|
|
#include <vcl/gdimtf.hxx>
|
|
#include <vcl/print.hxx>
|
|
#include <sal/macros.h>
|
|
#include <osl/diagnose.h>
|
|
#include <tools/long.hxx>
|
|
|
|
#include <osx/salinst.h>
|
|
#include <osx/salprn.h>
|
|
#include <osx/printview.h>
|
|
#include <quartz/salgdi.h>
|
|
#include <osx/saldata.hxx>
|
|
#include <quartz/utils.h>
|
|
|
|
#include <jobset.h>
|
|
#include <salptype.hxx>
|
|
|
|
#include <com/sun/star/beans/PropertyValue.hpp>
|
|
#include <com/sun/star/awt/Size.hpp>
|
|
#include <com/sun/star/uno/Sequence.hxx>
|
|
|
|
#include <algorithm>
|
|
#include <cstdlib>
|
|
|
|
using namespace vcl;
|
|
using namespace com::sun::star;
|
|
using namespace com::sun::star::beans;
|
|
|
|
AquaSalInfoPrinter::AquaSalInfoPrinter( const SalPrinterQueueInfo& i_rQueue ) :
|
|
mpGraphics( nullptr ),
|
|
mbGraphics( false ),
|
|
mbJob( false ),
|
|
mpPrinter( nil ),
|
|
mpPrintInfo( nil ),
|
|
mePageOrientation( Orientation::Portrait ),
|
|
mnStartPageOffsetX( 0 ),
|
|
mnStartPageOffsetY( 0 ),
|
|
mnCurPageRangeStart( 0 ),
|
|
mnCurPageRangeCount( 0 )
|
|
{
|
|
NSString* pStr = CreateNSString( i_rQueue.maPrinterName );
|
|
mpPrinter = [NSPrinter printerWithName: pStr];
|
|
[pStr release];
|
|
|
|
NSPrintInfo* pShared = [NSPrintInfo sharedPrintInfo];
|
|
if( pShared )
|
|
{
|
|
mpPrintInfo = [pShared copy];
|
|
[mpPrintInfo setPrinter: mpPrinter];
|
|
mePageOrientation = ([mpPrintInfo orientation] == NSPaperOrientationLandscape) ? Orientation::Landscape : Orientation::Portrait;
|
|
[mpPrintInfo setOrientation: NSPaperOrientationPortrait];
|
|
}
|
|
|
|
mpGraphics = new AquaSalGraphics(true);
|
|
|
|
const int nWidth = 100, nHeight = 100;
|
|
mpContextMemory.reset(new (std::nothrow) sal_uInt8[nWidth * 4 * nHeight]);
|
|
|
|
if (mpContextMemory)
|
|
{
|
|
mrContext = CGBitmapContextCreate(mpContextMemory.get(),
|
|
nWidth, nHeight, 8, nWidth * 4,
|
|
GetSalData()->mxRGBSpace, kCGImageAlphaNoneSkipFirst);
|
|
if( mrContext )
|
|
SetupPrinterGraphics( mrContext );
|
|
}
|
|
}
|
|
|
|
AquaSalInfoPrinter::~AquaSalInfoPrinter()
|
|
{
|
|
delete mpGraphics;
|
|
if( mpPrintInfo )
|
|
[mpPrintInfo release];
|
|
if( mrContext )
|
|
CFRelease( mrContext );
|
|
}
|
|
|
|
void AquaSalInfoPrinter::SetupPrinterGraphics( CGContextRef i_rContext ) const
|
|
{
|
|
if( mpGraphics )
|
|
{
|
|
if( mpPrintInfo )
|
|
{
|
|
// FIXME: get printer resolution
|
|
sal_Int32 nDPIX = 720, nDPIY = 720;
|
|
NSSize aPaperSize = [mpPrintInfo paperSize];
|
|
|
|
NSRect aImageRect = [mpPrintInfo imageablePageBounds];
|
|
if( mePageOrientation == Orientation::Portrait )
|
|
{
|
|
// move mirrored CTM back into paper
|
|
double dX = 0, dY = aPaperSize.height;
|
|
// move CTM to reflect imageable area
|
|
dX += aImageRect.origin.x;
|
|
dY -= aPaperSize.height - aImageRect.size.height - aImageRect.origin.y;
|
|
CGContextTranslateCTM( i_rContext, dX + mnStartPageOffsetX, dY - mnStartPageOffsetY );
|
|
// scale to be top/down and reflect our "virtual" DPI
|
|
CGContextScaleCTM( i_rContext, 72.0/double(nDPIX), -(72.0/double(nDPIY)) );
|
|
}
|
|
else
|
|
{
|
|
// move CTM to reflect imageable area
|
|
double dX = aImageRect.origin.x, dY = aPaperSize.height - aImageRect.size.height - aImageRect.origin.y;
|
|
CGContextTranslateCTM( i_rContext, -dX, -dY );
|
|
// turn by 90 degree
|
|
CGContextRotateCTM( i_rContext, M_PI/2 );
|
|
// move turned CTM back into paper
|
|
dX = aPaperSize.height;
|
|
dY = -aPaperSize.width;
|
|
CGContextTranslateCTM( i_rContext, dX + mnStartPageOffsetY, dY - mnStartPageOffsetX );
|
|
// scale to be top/down and reflect our "virtual" DPI
|
|
CGContextScaleCTM( i_rContext, -(72.0/double(nDPIY)), (72.0/double(nDPIX)) );
|
|
}
|
|
mpGraphics->SetPrinterGraphics( i_rContext, nDPIX, nDPIY );
|
|
}
|
|
else
|
|
OSL_FAIL( "no print info in SetupPrinterGraphics" );
|
|
}
|
|
}
|
|
|
|
SalGraphics* AquaSalInfoPrinter::AcquireGraphics()
|
|
{
|
|
SalGraphics* pGraphics = mbGraphics ? nullptr : mpGraphics;
|
|
mbGraphics = true;
|
|
return pGraphics;
|
|
}
|
|
|
|
void AquaSalInfoPrinter::ReleaseGraphics( SalGraphics* )
|
|
{
|
|
mbGraphics = false;
|
|
}
|
|
|
|
bool AquaSalInfoPrinter::Setup( weld::Window*, ImplJobSetup* )
|
|
{
|
|
return false;
|
|
}
|
|
|
|
bool AquaSalInfoPrinter::SetPrinterData( ImplJobSetup* io_pSetupData )
|
|
{
|
|
// FIXME: implement driver data
|
|
if( io_pSetupData && io_pSetupData->GetDriverData() )
|
|
return SetData( JobSetFlags::ALL, io_pSetupData );
|
|
|
|
bool bSuccess = true;
|
|
|
|
// set system type
|
|
io_pSetupData->SetSystem( JOBSETUP_SYSTEM_MAC );
|
|
|
|
// get paper format
|
|
if( mpPrintInfo )
|
|
{
|
|
NSSize aPaperSize = [mpPrintInfo paperSize];
|
|
double width = aPaperSize.width, height = aPaperSize.height;
|
|
// set paper
|
|
PaperInfo aInfo( PtTo10Mu( width ), PtTo10Mu( height ) );
|
|
aInfo.doSloppyFit();
|
|
io_pSetupData->SetPaperFormat( aInfo.getPaper() );
|
|
if( io_pSetupData->GetPaperFormat() == PAPER_USER )
|
|
{
|
|
io_pSetupData->SetPaperWidth( PtTo10Mu( width ) );
|
|
io_pSetupData->SetPaperHeight( PtTo10Mu( height ) );
|
|
}
|
|
else
|
|
{
|
|
io_pSetupData->SetPaperWidth( 0 );
|
|
io_pSetupData->SetPaperHeight( 0 );
|
|
}
|
|
|
|
// set orientation
|
|
io_pSetupData->SetOrientation( mePageOrientation );
|
|
|
|
io_pSetupData->SetPaperBin( 0 );
|
|
io_pSetupData->SetDriverData( static_cast<sal_uInt8*>(std::malloc( 4 )) );
|
|
io_pSetupData->SetDriverDataLen( 4 );
|
|
}
|
|
else
|
|
bSuccess = false;
|
|
|
|
return bSuccess;
|
|
}
|
|
|
|
void AquaSalInfoPrinter::setPaperSize( tools::Long i_nWidth, tools::Long i_nHeight, Orientation i_eSetOrientation )
|
|
{
|
|
|
|
Orientation ePaperOrientation = Orientation::Portrait;
|
|
const PaperInfo* pPaper = matchPaper( i_nWidth, i_nHeight, ePaperOrientation );
|
|
|
|
if( pPaper )
|
|
{
|
|
NSString* pPaperName = [CreateNSString( OStringToOUString(PaperInfo::toPSName(pPaper->getPaper()), RTL_TEXTENCODING_ASCII_US) ) autorelease];
|
|
[mpPrintInfo setPaperName: pPaperName];
|
|
}
|
|
else if( i_nWidth > 0 && i_nHeight > 0 )
|
|
{
|
|
NSSize aPaperSize = { static_cast<CGFloat>(TenMuToPt(i_nWidth)), static_cast<CGFloat>(TenMuToPt(i_nHeight)) };
|
|
[mpPrintInfo setPaperSize: aPaperSize];
|
|
}
|
|
// this seems counterintuitive
|
|
mePageOrientation = i_eSetOrientation;
|
|
}
|
|
|
|
bool AquaSalInfoPrinter::SetData( JobSetFlags i_nFlags, ImplJobSetup* io_pSetupData )
|
|
{
|
|
if( ! io_pSetupData || io_pSetupData->GetSystem() != JOBSETUP_SYSTEM_MAC )
|
|
return false;
|
|
|
|
if( mpPrintInfo )
|
|
{
|
|
if( i_nFlags & JobSetFlags::ORIENTATION )
|
|
mePageOrientation = io_pSetupData->GetOrientation();
|
|
|
|
if( i_nFlags & JobSetFlags::PAPERSIZE )
|
|
{
|
|
// set paper format
|
|
tools::Long width = 21000, height = 29700;
|
|
if( io_pSetupData->GetPaperFormat() == PAPER_USER )
|
|
{
|
|
// #i101108# sanity check
|
|
if( io_pSetupData->GetPaperWidth() && io_pSetupData->GetPaperHeight() )
|
|
{
|
|
width = io_pSetupData->GetPaperWidth();
|
|
height = io_pSetupData->GetPaperHeight();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
PaperInfo aInfo( io_pSetupData->GetPaperFormat() );
|
|
width = aInfo.getWidth();
|
|
height = aInfo.getHeight();
|
|
}
|
|
|
|
setPaperSize( width, height, mePageOrientation );
|
|
}
|
|
}
|
|
|
|
return mpPrintInfo != nil;
|
|
}
|
|
|
|
sal_uInt16 AquaSalInfoPrinter::GetPaperBinCount( const ImplJobSetup* )
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
OUString AquaSalInfoPrinter::GetPaperBinName( const ImplJobSetup*, sal_uInt16 )
|
|
{
|
|
return OUString();
|
|
}
|
|
|
|
sal_uInt32 AquaSalInfoPrinter::GetCapabilities( const ImplJobSetup*, PrinterCapType i_nType )
|
|
{
|
|
switch( i_nType )
|
|
{
|
|
case PrinterCapType::SupportDialog:
|
|
return 0;
|
|
case PrinterCapType::Copies:
|
|
return 0xffff;
|
|
case PrinterCapType::CollateCopies:
|
|
return 0xffff;
|
|
case PrinterCapType::SetOrientation:
|
|
return 1;
|
|
case PrinterCapType::SetPaperSize:
|
|
return 1;
|
|
case PrinterCapType::SetPaper:
|
|
return 1;
|
|
case PrinterCapType::ExternalDialog:
|
|
return officecfg::Office::Common::Misc::UseSystemPrintDialog::get()
|
|
? 1 : 0;
|
|
case PrinterCapType::PDF:
|
|
return 1;
|
|
case PrinterCapType::UsePullModel:
|
|
return 1;
|
|
default: break;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void AquaSalInfoPrinter::GetPageInfo( const ImplJobSetup*,
|
|
tools::Long& o_rOutWidth, tools::Long& o_rOutHeight,
|
|
Point& rPageOffset,
|
|
Size& rPaperSize )
|
|
{
|
|
if( mpPrintInfo )
|
|
{
|
|
sal_Int32 nDPIX = 72, nDPIY = 72;
|
|
mpGraphics->GetResolution( nDPIX, nDPIY );
|
|
const double fXScaling = static_cast<double>(nDPIX)/72.0,
|
|
fYScaling = static_cast<double>(nDPIY)/72.0;
|
|
|
|
NSSize aPaperSize = [mpPrintInfo paperSize];
|
|
rPaperSize.setWidth( static_cast<tools::Long>( double(aPaperSize.width) * fXScaling ) );
|
|
rPaperSize.setHeight( static_cast<tools::Long>( double(aPaperSize.height) * fYScaling ) );
|
|
|
|
NSRect aImageRect = [mpPrintInfo imageablePageBounds];
|
|
rPageOffset.setX( static_cast<tools::Long>( aImageRect.origin.x * fXScaling ) );
|
|
rPageOffset.setY( static_cast<tools::Long>( (aPaperSize.height - aImageRect.size.height - aImageRect.origin.y) * fYScaling ) );
|
|
o_rOutWidth = static_cast<tools::Long>( aImageRect.size.width * fXScaling );
|
|
o_rOutHeight = static_cast<tools::Long>( aImageRect.size.height * fYScaling );
|
|
|
|
if( mePageOrientation == Orientation::Landscape )
|
|
{
|
|
std::swap( o_rOutWidth, o_rOutHeight );
|
|
// swap width and height
|
|
tools::Long n = rPaperSize.Width();
|
|
rPaperSize.setWidth(rPaperSize.Height());
|
|
rPaperSize.setHeight(n);
|
|
// swap offset x and y
|
|
n = rPageOffset.X();
|
|
rPageOffset.setX(rPageOffset.Y());
|
|
rPageOffset.setY(n);
|
|
}
|
|
}
|
|
}
|
|
|
|
static Size getPageSize( vcl::PrinterController const & i_rController, sal_Int32 i_nPage )
|
|
{
|
|
Size aPageSize;
|
|
uno::Sequence< PropertyValue > const aPageParms( i_rController.getPageParameters( i_nPage ) );
|
|
for( const PropertyValue & pv : aPageParms )
|
|
{
|
|
if ( pv.Name == "PageSize" )
|
|
{
|
|
awt::Size aSize;
|
|
pv.Value >>= aSize;
|
|
aPageSize.setWidth( aSize.Width );
|
|
aPageSize.setHeight( aSize.Height );
|
|
break;
|
|
}
|
|
}
|
|
return aPageSize;
|
|
}
|
|
|
|
bool AquaSalInfoPrinter::StartJob( const OUString* i_pFileName,
|
|
const OUString& i_rJobName,
|
|
ImplJobSetup* i_pSetupData,
|
|
vcl::PrinterController& i_rController
|
|
)
|
|
{
|
|
if( mbJob )
|
|
return false;
|
|
|
|
bool bSuccess = false;
|
|
bool bWasAborted = false;
|
|
AquaSalInstance* pInst = GetSalData()->mpInstance;
|
|
PrintAccessoryViewState aAccViewState;
|
|
sal_Int32 nAllPages = 0;
|
|
|
|
// reset IsLastPage
|
|
i_rController.setLastPage( false );
|
|
|
|
// update job data
|
|
if( i_pSetupData )
|
|
SetData( JobSetFlags::ALL, i_pSetupData );
|
|
|
|
// do we want a progress panel ?
|
|
bool bShowProgressPanel = true;
|
|
beans::PropertyValue* pMonitor = i_rController.getValue( OUString( "MonitorVisible" ) );
|
|
if( pMonitor )
|
|
pMonitor->Value >>= bShowProgressPanel;
|
|
if( ! i_rController.isShowDialogs() )
|
|
bShowProgressPanel = false;
|
|
|
|
// possibly create one job for collated output
|
|
bool bSinglePrintJobs = i_rController.getPrinter()->IsSinglePrintJobs();
|
|
|
|
// FIXME: jobStarted() should be done after the print dialog has ended (if there is one)
|
|
// how do I know when that might be ?
|
|
i_rController.jobStarted();
|
|
|
|
int nCopies = i_rController.getPrinter()->GetCopyCount();
|
|
int nJobs = 1;
|
|
if( bSinglePrintJobs )
|
|
{
|
|
nJobs = nCopies;
|
|
nCopies = 1;
|
|
}
|
|
|
|
for( int nCurJob = 0; nCurJob < nJobs; nCurJob++ )
|
|
{
|
|
aAccViewState.bNeedRestart = true;
|
|
do
|
|
{
|
|
if( aAccViewState.bNeedRestart )
|
|
{
|
|
mnCurPageRangeStart = 0;
|
|
mnCurPageRangeCount = 0;
|
|
nAllPages = i_rController.getFilteredPageCount();
|
|
}
|
|
|
|
aAccViewState.bNeedRestart = false;
|
|
|
|
Size aCurSize( 21000, 29700 );
|
|
if( nAllPages > 0 )
|
|
{
|
|
mnCurPageRangeCount = 1;
|
|
aCurSize = getPageSize( i_rController, mnCurPageRangeStart );
|
|
Size aNextSize( aCurSize );
|
|
|
|
// print pages up to a different size
|
|
while( mnCurPageRangeCount + mnCurPageRangeStart < nAllPages )
|
|
{
|
|
aNextSize = getPageSize( i_rController, mnCurPageRangeStart + mnCurPageRangeCount );
|
|
if( aCurSize == aNextSize // same page size
|
|
||
|
|
(aCurSize.Width() == aNextSize.Height() && aCurSize.Height() == aNextSize.Width()) // same size, but different orientation
|
|
)
|
|
{
|
|
mnCurPageRangeCount++;
|
|
}
|
|
else
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
mnCurPageRangeCount = 0;
|
|
|
|
// now for the current run
|
|
mnStartPageOffsetX = mnStartPageOffsetY = 0;
|
|
// setup the paper size and orientation
|
|
// do this on our associated Printer object, since that is
|
|
// out interface to the applications which occasionally rely on the paper
|
|
// information (e.g. brochure printing scales to the found paper size)
|
|
// also SetPaperSizeUser has the advantage that we can share a
|
|
// platform independent paper matching algorithm
|
|
VclPtr<Printer> pPrinter( i_rController.getPrinter() );
|
|
pPrinter->SetMapMode( MapMode( MapUnit::Map100thMM ) );
|
|
pPrinter->SetPaperSizeUser( aCurSize );
|
|
|
|
// create view
|
|
NSView* pPrintView = [[AquaPrintView alloc] initWithController: &i_rController withInfoPrinter: this];
|
|
|
|
NSMutableDictionary* pPrintDict = [mpPrintInfo dictionary];
|
|
|
|
// set filename
|
|
if( i_pFileName )
|
|
{
|
|
[mpPrintInfo setJobDisposition: NSPrintSaveJob];
|
|
NSString* pPath = CreateNSString( *i_pFileName );
|
|
[pPrintDict setObject:[NSURL fileURLWithPath:pPath] forKey:NSPrintJobSavingURL];
|
|
[pPath release];
|
|
}
|
|
|
|
[pPrintDict setObject: [[NSNumber numberWithInt: nCopies] autorelease] forKey: NSPrintCopies];
|
|
if( nCopies > 1 )
|
|
[pPrintDict setObject: [[NSNumber numberWithBool: pPrinter->IsCollateCopy()] autorelease] forKey: NSPrintMustCollate];
|
|
[pPrintDict setObject: [[NSNumber numberWithBool: YES] autorelease] forKey: NSPrintDetailedErrorReporting];
|
|
[pPrintDict setObject: [[NSNumber numberWithInt: 1] autorelease] forKey: NSPrintFirstPage];
|
|
// #i103253# weird: for some reason, autoreleasing the value below like the others above
|
|
// leads do a double free malloc error. Why this value should behave differently from all the others
|
|
// is a mystery.
|
|
[pPrintDict setObject: [NSNumber numberWithInt: mnCurPageRangeCount] forKey: NSPrintLastPage];
|
|
|
|
// create print operation
|
|
NSPrintOperation* pPrintOperation = [NSPrintOperation printOperationWithView: pPrintView printInfo: mpPrintInfo];
|
|
|
|
if( pPrintOperation )
|
|
{
|
|
NSObject* pReleaseAfterUse = nil;
|
|
bool bShowPanel = !i_rController.isDirectPrint()
|
|
&& (officecfg::Office::Common::Misc::UseSystemPrintDialog::
|
|
get())
|
|
&& i_rController.isShowDialogs();
|
|
[pPrintOperation setShowsPrintPanel: bShowPanel ? YES : NO ];
|
|
[pPrintOperation setShowsProgressPanel: bShowProgressPanel ? YES : NO];
|
|
|
|
// set job title (since MacOSX 10.5)
|
|
if( [pPrintOperation respondsToSelector: @selector(setJobTitle:)] )
|
|
[pPrintOperation performSelector: @selector(setJobTitle:) withObject: [CreateNSString( i_rJobName ) autorelease]];
|
|
|
|
if( bShowPanel && mnCurPageRangeStart == 0 && nCurJob == 0) // only the first range of pages (in the first job) gets the accessory view
|
|
pReleaseAfterUse = [AquaPrintAccessoryView setupPrinterPanel: pPrintOperation withController: &i_rController withState: &aAccViewState];
|
|
|
|
bSuccess = true;
|
|
mbJob = true;
|
|
pInst->startedPrintJob();
|
|
bool wasSuccessful = [pPrintOperation runOperation];
|
|
pInst->endedPrintJob();
|
|
bSuccess = wasSuccessful;
|
|
bWasAborted = [[[pPrintOperation printInfo] jobDisposition] compare: NSPrintCancelJob] == NSOrderedSame;
|
|
mbJob = false;
|
|
if( pReleaseAfterUse )
|
|
[pReleaseAfterUse release];
|
|
}
|
|
|
|
mnCurPageRangeStart += mnCurPageRangeCount;
|
|
mnCurPageRangeCount = 1;
|
|
} while( aAccViewState.bNeedRestart || mnCurPageRangeStart + mnCurPageRangeCount < nAllPages );
|
|
}
|
|
|
|
// inform application that it can release its data
|
|
// this is awkward, but the XRenderable interface has no method for this,
|
|
// so we need to call XRenderable::render one last time with IsLastPage = true
|
|
i_rController.setLastPage( true );
|
|
GDIMetaFile aPageFile;
|
|
if( mrContext )
|
|
SetupPrinterGraphics( mrContext );
|
|
i_rController.getFilteredPageFile( 0, aPageFile );
|
|
|
|
i_rController.setJobState( bWasAborted
|
|
? view::PrintableState_JOB_ABORTED
|
|
: view::PrintableState_JOB_SPOOLED );
|
|
|
|
mnCurPageRangeStart = mnCurPageRangeCount = 0;
|
|
|
|
return bSuccess;
|
|
}
|
|
|
|
bool AquaSalInfoPrinter::EndJob()
|
|
{
|
|
mnStartPageOffsetX = mnStartPageOffsetY = 0;
|
|
mbJob = false;
|
|
return true;
|
|
}
|
|
|
|
bool AquaSalInfoPrinter::AbortJob()
|
|
{
|
|
mbJob = false;
|
|
|
|
// FIXME: implementation
|
|
return false;
|
|
}
|
|
|
|
SalGraphics* AquaSalInfoPrinter::StartPage( ImplJobSetup* i_pSetupData, bool i_bNewJobData )
|
|
{
|
|
if( i_bNewJobData && i_pSetupData )
|
|
SetPrinterData( i_pSetupData );
|
|
|
|
CGContextRef rContext = [[NSGraphicsContext currentContext] CGContext];
|
|
|
|
SetupPrinterGraphics( rContext );
|
|
|
|
return mpGraphics;
|
|
}
|
|
|
|
bool AquaSalInfoPrinter::EndPage()
|
|
{
|
|
mpGraphics->InvalidateContext();
|
|
return true;
|
|
}
|
|
|
|
AquaSalPrinter::AquaSalPrinter( AquaSalInfoPrinter* i_pInfoPrinter ) :
|
|
mpInfoPrinter( i_pInfoPrinter )
|
|
{
|
|
}
|
|
|
|
AquaSalPrinter::~AquaSalPrinter()
|
|
{
|
|
}
|
|
|
|
bool AquaSalPrinter::StartJob( const OUString* i_pFileName,
|
|
const OUString& i_rJobName,
|
|
const OUString&,
|
|
ImplJobSetup* i_pSetupData,
|
|
vcl::PrinterController& i_rController )
|
|
{
|
|
return mpInfoPrinter->StartJob( i_pFileName, i_rJobName, i_pSetupData, i_rController );
|
|
}
|
|
|
|
bool AquaSalPrinter::StartJob( const OUString* /*i_pFileName*/,
|
|
const OUString& /*i_rJobName*/,
|
|
const OUString& /*i_rAppName*/,
|
|
sal_uInt32 /*i_nCopies*/,
|
|
bool /*i_bCollate*/,
|
|
bool /*i_bDirect*/,
|
|
ImplJobSetup* )
|
|
{
|
|
OSL_FAIL( "should never be called" );
|
|
return false;
|
|
}
|
|
|
|
bool AquaSalPrinter::EndJob()
|
|
{
|
|
return mpInfoPrinter->EndJob();
|
|
}
|
|
|
|
SalGraphics* AquaSalPrinter::StartPage( ImplJobSetup* i_pSetupData, bool i_bNewJobData )
|
|
{
|
|
return mpInfoPrinter->StartPage( i_pSetupData, i_bNewJobData );
|
|
}
|
|
|
|
void AquaSalPrinter::EndPage()
|
|
{
|
|
mpInfoPrinter->EndPage();
|
|
}
|
|
|
|
void AquaSalInfoPrinter::InitPaperFormats( const ImplJobSetup* )
|
|
{
|
|
m_aPaperFormats.clear();
|
|
m_bPapersInit = true;
|
|
|
|
if( mpPrinter )
|
|
{
|
|
SAL_WNODEPRECATED_DECLARATIONS_PUSH
|
|
//TODO: 10.9 statusForTable:, stringListForKey:inTable:
|
|
if( [mpPrinter statusForTable: @"PPD"] == NSPrinterTableOK )
|
|
{
|
|
NSArray* pPaperNames = [mpPrinter stringListForKey: @"PageSize" inTable: @"PPD"];
|
|
if( pPaperNames )
|
|
{
|
|
unsigned int nPapers = [pPaperNames count];
|
|
for( unsigned int i = 0; i < nPapers; i++ )
|
|
{
|
|
NSString* pPaper = [pPaperNames objectAtIndex: i];
|
|
// first try to match the name
|
|
OString aPaperName( [pPaper UTF8String] );
|
|
Paper ePaper = PaperInfo::fromPSName( aPaperName );
|
|
if( ePaper != PAPER_USER )
|
|
{
|
|
m_aPaperFormats.push_back( PaperInfo( ePaper ) );
|
|
}
|
|
else
|
|
{
|
|
NSSize aPaperSize = [mpPrinter pageSizeForPaper: pPaper];
|
|
if( aPaperSize.width > 0 && aPaperSize.height > 0 )
|
|
{
|
|
PaperInfo aInfo( PtTo10Mu( aPaperSize.width ),
|
|
PtTo10Mu( aPaperSize.height ) );
|
|
if( aInfo.getPaper() == PAPER_USER )
|
|
aInfo.doSloppyFit();
|
|
m_aPaperFormats.push_back( aInfo );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
SAL_WNODEPRECATED_DECLARATIONS_POP
|
|
}
|
|
}
|
|
|
|
const PaperInfo* AquaSalInfoPrinter::matchPaper( tools::Long i_nWidth, tools::Long i_nHeight, Orientation& o_rOrientation ) const
|
|
{
|
|
if( ! m_bPapersInit )
|
|
const_cast<AquaSalInfoPrinter*>(this)->InitPaperFormats( nullptr );
|
|
|
|
const PaperInfo* pMatch = nullptr;
|
|
o_rOrientation = Orientation::Portrait;
|
|
for( int n = 0; n < 2 ; n++ )
|
|
{
|
|
for( size_t i = 0; i < m_aPaperFormats.size(); i++ )
|
|
{
|
|
if( std::abs( m_aPaperFormats[i].getWidth() - i_nWidth ) < 50 &&
|
|
std::abs( m_aPaperFormats[i].getHeight() - i_nHeight ) < 50 )
|
|
{
|
|
pMatch = &m_aPaperFormats[i];
|
|
return pMatch;
|
|
}
|
|
}
|
|
o_rOrientation = Orientation::Landscape;
|
|
std::swap( i_nWidth, i_nHeight );
|
|
}
|
|
return pMatch;
|
|
}
|
|
|
|
int AquaSalInfoPrinter::GetLandscapeAngle( const ImplJobSetup* )
|
|
{
|
|
return 900;
|
|
}
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|