/* -*- 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 .
*/
// caution: does not ensure uniqueness void insert( sal_Int32 i_nPageNo, const GDIMetaFile& i_rPage, const PrinterController::PageSize& i_rSize )
{
sal_Int32 nReplacePage = maCacheRanking.back();
maPages[ nReplacePage ].aPage = i_rPage;
maPages[ nReplacePage ].aSize = i_rSize;
maPageNumbers[ nReplacePage ] = i_nPageNo; // cache insertion means in our case, the page was just queried // so update the ranking
updateRanking( nReplacePage );
}
// caution: bad algorithm; should there ever be reason to increase the cache size beyond 6 // this needs to be urgently rewritten. However do NOT increase the cache size lightly, // whole pages can be rather memory intensive bool get( sal_Int32 i_nPageNo, GDIMetaFile& o_rPageFile, PrinterController::PageSize& o_rSize )
{ for( sal_Int32 i = 0; i < nCacheSize; ++i )
{ if( maPageNumbers[i] == i_nPageNo )
{
updateRanking( i );
o_rPageFile = maPages[i].aPage;
o_rSize = maPages[i].aSize; returntrue;
}
} returnfalse;
}
void invalidate()
{ for( sal_Int32 i = 0; i < nCacheSize; ++i )
{
maPageNumbers[i] = -1;
maPages[i].aPage.Clear();
maCacheRanking[i] = nCacheSize - i - 1;
}
}
};
// set by user through printer properties subdialog of printer settings dialog
Size maDefaultPageSize; // set by user through print dialog
Size maUserPageSize; // set by user through print dialog
Orientation meUserOrientation; // set by user through printer properties subdialog of printer settings dialog
sal_Int32 mnDefaultPaperBin; // Set by user through printer properties subdialog of print dialog. // Overrides application-set tray for a page.
sal_Int32 mnFixedPaperBin;
// N.B. Apparently we have three levels of paper tray settings // (latter overrides former): // 1. default tray // 2. tray set for a concrete page by an application, e.g., writer // allows setting a printer tray (for the default printer) for a // page style. This setting can be overridden by user by selecting // "Use only paper tray from printer preferences" on the Options // page in the print dialog, in which case the default tray is // used for all pages. // 3. tray set in printer properties the printer dialog // I'm not quite sure why 1. and 3. are distinct, but the commit // history suggests this is intentional...
try
{ #ifdef MACOSX // Try to mimic the save dialog behavior when using the native // print dialog to save to PDF. if( pPrinter )
{ // Set the suggested file name if possible if( !rJobName.isEmpty() )
xFilePicker->setDefaultName( rJobName );
// macOS normally saves only to PDF if( pPrinter->GetCapabilities( PrinterCapType::PDF ) )
{
xFilePicker->appendFilter( u"Portable Document Format"_ustr, u"*.pdf"_ustr );
// check if there is a default printer; if not, show an error box (if appropriate) if( GetDefaultPrinterName().isEmpty() )
{ if (xController->isShowDialogs())
{
std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(xController->getWindow(), u"vcl/ui/errornoprinterdialog.ui"_ustr));
std::unique_ptr<weld::MessageDialog> xBox(xBuilder->weld_message_dialog(u"ErrorNoPrinterDialog"_ustr));
xBox->run();
}
xController->setValue( u"IsDirect"_ustr,
css::uno::Any( false ) );
}
// setup printer
// #i114306# changed behavior back from persistence // if no specific printer is already set, create the default printer if (!xController->getPrinter())
{
OUString aPrinterName( i_rInitSetup.GetPrinterName() );
VclPtrInstance<Printer> xPrinter( aPrinterName );
xPrinter->SetJobSetup(i_rInitSetup);
xController->setPrinter(xPrinter);
xController->setPapersizeFromSetup(xPrinter->GetPrinterSettingsPreferred());
}
// reset last page property
xController->setLastPage(false);
// update "PageRange" property inferring from other properties: // case 1: "Pages" set from UNO API -> // setup "Print Selection" and insert "PageRange" attribute // case 2: "All pages" is selected // update "Page range" attribute to have a sensible default, // but leave "All" as selected
// "Pages" attribute from API is now equivalent to "PageRange" // AND "PrintContent" = 1 except calc where it is "PrintRange" = 1 // Argh ! That sure needs cleaning up
css::beans::PropertyValue* pContentVal = xController->getValue(u"PrintRange"_ustr); if( ! pContentVal )
pContentVal = xController->getValue(u"PrintContent"_ustr);
// case 1: UNO API has set "Pages"
css::beans::PropertyValue* pPagesVal = xController->getValue(u"Pages"_ustr); if( pPagesVal )
{
OUString aPagesVal;
pPagesVal->Value >>= aPagesVal; if( !aPagesVal.isEmpty() )
{ // "Pages" attribute from API is now equivalent to "PageRange" // AND "PrintContent" = 1 except calc where it is "PrintRange" = 1 // Argh ! That sure needs cleaning up if( pContentVal )
{
pContentVal->Value <<= sal_Int32( 1 );
xController->setValue(u"PageRange"_ustr, pPagesVal->Value);
}
}
} // case 2: is "All" selected ? elseif( pContentVal )
{
sal_Int32 nContent = -1; if( pContentVal->Value >>= nContent )
{ if( nContent == 0 )
{ // do not overwrite PageRange if it is already set
css::beans::PropertyValue* pRangeVal = xController->getValue(u"PageRange"_ustr);
OUString aRange; if( pRangeVal )
pRangeVal->Value >>= aRange; if( aRange.isEmpty() )
{
sal_Int32 nPages = xController->getPageCount(); if( nPages > 0 )
{
OUStringBuffer aBuf( 32 );
aBuf.append( "1" ); if( nPages > 1 )
{
aBuf.append( "-" + OUString::number( nPages ) );
}
xController->setValue(u"PageRange"_ustr, css::uno::Any(aBuf.makeStringAndClear()));
}
}
}
}
}
// in direct print case check whether there is anything to print. // if not, show an errorbox (if appropriate) if( xController->isShowDialogs() && xController->isDirectPrint() )
{ if( xController->getFilteredPageCount() == 0 )
{
std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(xController->getWindow(), u"vcl/ui/errornocontentdialog.ui"_ustr));
std::unique_ptr<weld::MessageDialog> xBox(xBuilder->weld_message_dialog(u"ErrorNoContentDialog"_ustr));
xBox->run(); returnfalse;
}
}
// check if the printer brings up its own dialog // in that case leave the work to that dialog if( ! xController->getPrinter()->GetCapabilities( PrinterCapType::ExternalDialog ) &&
! xController->isDirectPrint() &&
xController->isShowDialogs()
)
{ try
{
PrintDialog aDlg(xController->getWindow(), xController); if (!aDlg.run())
{
xController->abortJob(); returnfalse;
} if (aDlg.isPrintToFile())
{
OUString aJobName;
css::beans::PropertyValue* pJobNameVal = xController->getValue( u"JobName"_ustr ); if( pJobNameVal )
pJobNameVal->Value >>= aJobName;
OUString aFile = queryFile( xController->getPrinter().get(), aJobName ); if( aFile.isEmpty() )
{
xController->abortJob(); returnfalse;
}
xController->setValue( u"LocalFileName"_ustr,
css::uno::Any( aFile ) );
} elseif (aDlg.isSingleJobs())
{
xController->getPrinter()->SetSinglePrintJobs(true);
}
} catch (const std::bad_alloc&)
{
}
}
mbPrinting = true; if( GetCapabilities( PrinterCapType::UsePullModel ) )
{
mbJobActive = true; // SAL layer does all necessary page printing // and also handles showing a dialog // that also means it must call jobStarted when the dialog is finished // it also must set the JobState of the Controller if( mpPrinter->StartJob( pPrintFile,
i_rJobName,
Application::GetDisplayName(),
&maJobSetup.ImplGetData(),
*i_xController) )
{
EndJob();
} else
{
mnError = ImplSalPrinterErrorCodeToVCL(mpPrinter->GetErrorCode()); if ( !mnError )
mnError = PRINTER_GENERALERROR;
mbPrinting = false;
mpPrinter.reset();
mbJobActive = false;
returnfalse;
}
} else
{ // possibly a dialog has been shown // now the real job starts
i_xController->setJobState( css::view::PrintableState_JOB_STARTED );
i_xController->jobStarted();
if (i_xController->getJobState() == css::view::PrintableState_JOB_STARTED)
i_xController->setJobState(css::view::PrintableState_JOB_SPOOLED);
}
// make last used printer persistent for UI jobs if (i_xController->isShowDialogs() && !i_xController->isDirectPrint())
{
SettingsConfigItem* pItem = SettingsConfigItem::get();
pItem->setValue( u"PrintDialog"_ustr,
u"LastPrinterUsed"_ustr,
GetName()
);
}
void PrinterController::dialogsParentClosing()
{
mpImplData->mpWindow = nullptr; if (mpImplData->mxProgress)
{ // close the dialog without doing anything, just get rid of it
mpImplData->mxProgress->response(RET_OK);
mpImplData->mxProgress.reset();
}
}
Size aPaperSize; // Save current paper size
Orientation eOrientation = Orientation::Portrait; // Save current paper orientation bool bSavedSizeOrientation = false;
// #tdf 126744 Transfer paper size and orientation settings to newly selected printer if ( xPrinter )
{
aPaperSize = xPrinter->GetPaperSize();
eOrientation = xPrinter->GetOrientation();
bSavedSizeOrientation = true;
}
// get current data
Size aPaperSize(xPrinter->GetPaperSize());
Orientation eOrientation = xPrinter->GetOrientation();
sal_uInt16 nPaperBin = xPrinter->GetPaperBin();
// reset paper size back to last configured size, not // whatever happens to be the current page // (but only if the printer config has changed, otherwise // don't override printer page auto-detection - tdf#91362) if (getPrinterModified() || getPapersizeFromSetup())
{
resetPaperToLastConfigured();
}
Size aNewPaperSize(xPrinter->GetPaperSize()); if (bRet)
{ bool bInvalidateCache = false;
setPapersizeFromSetup(xPrinter->GetPrinterSettingsPreferred());
// was papersize overridden ? if so we need to take action if we're // configured to use the driver papersize if (aNewPaperSize != mpImplData->maDefaultPageSize)
{
mpImplData->maDefaultPageSize = aNewPaperSize;
bInvalidateCache = getPapersizeFromSetup();
}
// was bin overridden ? if so we need to take action
sal_uInt16 nNewPaperBin = xPrinter->GetPaperBin(); if (nNewPaperBin != nPaperBin)
{
mpImplData->mnFixedPaperBin = nNewPaperBin;
bInvalidateCache = true;
}
if (bInvalidateCache)
invalidatePageCache();
} else
{ //restore to whatever it was before we entered this method
xPrinter->SetOrientation( eOrientation ); if (aPaperSize != aNewPaperSize)
xPrinter->SetPaperSizeUser(aPaperSize);
}
xPrinter->Pop();
}
//when printing is finished, set the paper size of the printer to either what //the user explicitly set as the desired paper size, or fallback to whatever //the printer had before printing started. That way it doesn't contain the last //paper size of a multiple paper size using document when we are in our normal //auto accept document paper size mode and end up overwriting the original //paper size setting for file->printer_settings just by pressing "ok" in the //print dialog void vcl::ImplPrinterControllerData::resetPaperToLastConfigured()
{
mxPrinter->Push();
mxPrinter->SetMapMode(MapMode(MapUnit::Map100thMM));
Size aCurSize(mxPrinter->GetPaperSize()); if (aCurSize != maDefaultPageSize)
mxPrinter->SetPaperSizeUser(maDefaultPageSize);
mxPrinter->Pop();
}
int PrinterController::getPageCountProtected() const
{ const MapMode aMapMode( MapUnit::Map100thMM );
// reverse sheet order if( mpImplData->mbReversePageOrder )
{ int nDocPages = getFilteredPageCount();
i_nFilteredPage = nDocPages - 1 - i_nFilteredPage;
}
// there is no filtering to be done (and possibly the page size of the // original page is to be set), when N-Up is "neutral" that is there is // only one subpage and the margins are 0 if( nSubPages == 1 &&
rMPS.nLeftMargin == 0 && rMPS.nRightMargin == 0 &&
rMPS.nTopMargin == 0 && rMPS.nBottomMargin == 0 )
{
PrinterController::PageSize aPageSize = getPageFile( i_nFilteredPage, o_rMtf, i_bMayUseCache ); if (mpImplData->meJobState != css::view::PrintableState_JOB_STARTED)
{ // rhbz#657394: check that we are still printing... return PrinterController::PageSize();
}
Size aPaperSize = mpImplData->getRealPaperSize( aPageSize.aSize, true );
mpImplData->mxPrinter->SetMapMode( MapMode( MapUnit::Map100thMM ) );
mpImplData->mxPrinter->SetPaperSizeUser( aPaperSize ); if( aPaperSize != aPageSize.aSize )
{ // user overridden page size, center Metafile
o_rMtf.WindStart();
tools::Long nDX = (aPaperSize.Width() - aPageSize.aSize.Width()) / 2;
tools::Long nDY = (aPaperSize.Height() - aPageSize.aSize.Height()) / 2;
o_rMtf.Move( nDX, nDY, mpImplData->mxPrinter->GetDPIX(), mpImplData->mxPrinter->GetDPIY() );
o_rMtf.WindStart();
o_rMtf.SetPrefSize( aPaperSize );
aPageSize.aSize = aPaperSize;
} return aPageSize;
}
// set last page property really only on the very last page to be rendered // that is on the last subpage of a NUp run bool bIsLastPage = mpImplData->mbLastPage;
mpImplData->mbLastPage = false;
// multi page area: page size minus margins + one time spacing right and down // the added spacing is so each subpage can be calculated including its spacing
Size aMPArea( aPaperSize );
aMPArea.AdjustWidth( -(rMPS.nLeftMargin + rMPS.nRightMargin) );
aMPArea.AdjustWidth(rMPS.nHorizontalSpacing );
aMPArea.AdjustHeight( -(rMPS.nTopMargin + rMPS.nBottomMargin) );
aMPArea.AdjustHeight(rMPS.nVerticalSpacing );
// determine size of a "cell" subpage, leave a little space around pages
Size aSubPageSize( nAdvX - rMPS.nHorizontalSpacing, nAdvY - rMPS.nVerticalSpacing );
// subsequent getPageFile calls have changed the paper, reset it to current value
mpImplData->mxPrinter->SetMapMode( MapMode( MapUnit::Map100thMM ) );
mpImplData->mxPrinter->SetPaperSizeUser( aPaperSize );
Color aBg( COL_TRANSPARENT ); // default: let RemoveTransparenciesFromMetaFile do its own background logic if( mpImplData->maMultiPage.nRows * mpImplData->maMultiPage.nColumns > 1 )
{ // in N-Up printing we have no "page" background operation // we also have no way to determine the paper color // so let's go for white, which will kill 99.9% of the real cases
aBg = COL_WHITE;
}
mpImplData->mxPrinter->RemoveTransparenciesFromMetaFile( i_rIn, o_rOut, nMaxBmpDPIX, nMaxBmpDPIY,
rPrinterOptions.IsReduceTransparency(),
rPrinterOptions.GetReducedTransparencyMode() == vcl::printer::TransparencyMode::Auto,
rPrinterOptions.IsReduceBitmaps() && rPrinterOptions.IsReducedBitmapIncludesTransparency(),
aBg
); return nRestoreDrawMode;
}
void PrinterController::printFilteredPage( int i_nPage )
{ if( mpImplData->meJobState != css::view::PrintableState_JOB_STARTED ) return; // rhbz#657394: check that we are still printing...
if( mpImplData->mxProgress )
{ // do nothing if printing is canceled if( mpImplData->mxProgress->isCanceled() )
{
setJobState( css::view::PrintableState_JOB_ABORTED ); return;
}
}
// in N-Up printing set the correct page size
mpImplData->mxPrinter->SetMapMode(MapMode(MapUnit::Map100thMM)); // aPageSize was filtered through mpImplData->getRealPaperSize already by getFilteredPageFile()
mpImplData->mxPrinter->SetPaperSizeUser( aPageSize.aSize ); if( mpImplData->mnFixedPaperBin != -1 &&
mpImplData->mxPrinter->GetPaperBin() != mpImplData->mnFixedPaperBin )
{
mpImplData->mxPrinter->SetPaperBin( mpImplData->mnFixedPaperBin );
}
// if full paper is meant to be used, move the output to accommodate for pageoffset if( aPageSize.bFullPaper )
{
Point aPageOffset( mpImplData->mxPrinter->GetPageOffset() );
aPageFile.WindStart();
aPageFile.Move( -aPageOffset.X(), -aPageOffset.Y(), mpImplData->mxPrinter->GetDPIX(), mpImplData->mxPrinter->GetDPIY() );
}
void PrinterController::abortJob()
{
setJobState( css::view::PrintableState_JOB_ABORTED ); // applications (well, sw) depend on a page request with "IsLastPage" = true // to free resources, else they (well, sw) will crash eventually
setLastPage( true );
if (mpImplData->mxProgress)
{
mpImplData->mxProgress->response(RET_CANCEL);
mpImplData->mxProgress.reset();
}
if( bEnabled )
{ // check control dependencies
vcl::ImplPrinterControllerData::ControlDependencyMap::const_iterator it =
mpImplData->maControlDependencies.find( i_rProperty ); if( it != mpImplData->maControlDependencies.end() )
{ // check if the dependency is enabled // if the dependency is disabled, we are too
bEnabled = isUIOptionEnabled( it->second.maDependsOnName );
if( bEnabled )
{ // does the dependency have the correct value ? const css::beans::PropertyValue* pVal = getValue( it->second.maDependsOnName );
OSL_ENSURE( pVal, "unknown property in dependency" ); if( pVal )
{
sal_Int32 nDepVal = 0; bool bDepVal = false; if( pVal->Value >>= nDepVal )
{
bEnabled = (nDepVal == it->second.mnDependsOnEntry) || (it->second.mnDependsOnEntry == -1);
} elseif( pVal->Value >>= bDepVal )
{ // could be a dependency on a checked boolean // in this case the dependency is on a non zero for checked value
bEnabled = ( bDepVal && it->second.mnDependsOnEntry != 0) ||
( ! bDepVal && it->second.mnDependsOnEntry == 0);
} else
{ // if the type does not match something is awry
OSL_FAIL( "strange type in control dependency" );
bEnabled = false;
}
}
}
}
}
} return bEnabled;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.