From ed5640d8b587fbcfed7dd7967f3de04b37a76f26 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 11:06:44 +0200 Subject: Adding upstream version 4:7.4.7. Signed-off-by: Daniel Baumann --- .../source/filter/DocumentToGraphicRenderer.cxx | 340 +++++++++++++++++++++ 1 file changed, 340 insertions(+) create mode 100644 svtools/source/filter/DocumentToGraphicRenderer.cxx (limited to 'svtools/source/filter/DocumentToGraphicRenderer.cxx') diff --git a/svtools/source/filter/DocumentToGraphicRenderer.cxx b/svtools/source/filter/DocumentToGraphicRenderer.cxx new file mode 100644 index 000000000..c2858a1da --- /dev/null +++ b/svtools/source/filter/DocumentToGraphicRenderer.cxx @@ -0,0 +1,340 @@ +/* -*- 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 + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +using namespace css; +using namespace css::uno; +using namespace css::lang; +using namespace css::beans; + +DocumentToGraphicRenderer::DocumentToGraphicRenderer( const Reference& rxDocument, bool bSelectionOnly ) : + mxDocument(rxDocument), + mxModel( mxDocument, uno::UNO_QUERY ), + mxController( mxModel->getCurrentController() ), + mxRenderable (mxDocument, uno::UNO_QUERY ), + mxToolkit( VCLUnoHelper::CreateToolkit() ), + meDocType( UNKNOWN ) +{ + try + { + uno::Reference< lang::XServiceInfo > xServiceInfo( mxDocument, uno::UNO_QUERY); + if (xServiceInfo.is()) + { + if (xServiceInfo->supportsService("com.sun.star.text.TextDocument")) + meDocType = WRITER; + else if (xServiceInfo->supportsService("com.sun.star.sheet.SpreadsheetDocument")) + meDocType = CALC; + else if (xServiceInfo->supportsService("com.sun.star.presentation.PresentationDocument")) + meDocType = IMPRESS; + else + meDocType = UNKNOWN; + } + } + catch (const uno::Exception&) + { + } + + if (!(bSelectionOnly && mxController.is())) + return; + + try + { + uno::Reference< view::XSelectionSupplier > xSelSup( mxController, uno::UNO_QUERY); + if (xSelSup.is()) + { + uno::Any aViewSelection( xSelSup->getSelection()); + if (aViewSelection.hasValue()) + { + /* FIXME: Writer always has a selection even if nothing is + * selected, but passing a selection to + * XRenderable::render() it always renders an empty page. + * So disable the selection already here. The current page + * the cursor is on is rendered. */ + if (!isWriter()) + maSelection = aViewSelection; + } + } + } + catch (const uno::Exception&) + { + } +} + +DocumentToGraphicRenderer::~DocumentToGraphicRenderer() +{ +} + +Size DocumentToGraphicRenderer::getDocumentSizeInPixels(sal_Int32 nCurrentPage) +{ + Size aSize100mm = getDocumentSizeIn100mm(nCurrentPage); + return Application::GetDefaultDevice()->LogicToPixel(aSize100mm, MapMode(MapUnit::Map100thMM)); +} + +bool DocumentToGraphicRenderer::hasSelection() const +{ + return maSelection.hasValue(); +} + +uno::Any DocumentToGraphicRenderer::getSelection() const +{ + uno::Any aSelection; + if (hasSelection()) + aSelection = maSelection; + else + aSelection <<= mxDocument; // default: render whole document + return aSelection; +} + +Size DocumentToGraphicRenderer::getDocumentSizeIn100mm(sal_Int32 nCurrentPage, + Point* pDocumentPosition, Point* pCalcPagePosition, Size* pCalcPageSize) +{ + Reference< awt::XDevice > xDevice(mxToolkit->createScreenCompatibleDevice( 32, 32 ) ); + + uno::Any selection( getSelection()); + + PropertyValues renderProperties{ comphelper::makePropertyValue("IsPrinter", true), + comphelper::makePropertyValue("RenderDevice", xDevice), + comphelper::makePropertyValue("View", mxController), + comphelper::makePropertyValue("RenderToGraphic", true) }; + + awt::Size aSize; + awt::Size aCalcPageSize; + awt::Point aPos; + awt::Point aCalcPos; + + sal_Int32 nPages = mxRenderable->getRendererCount( selection, renderProperties ); + if (nPages >= nCurrentPage) + { + const Sequence< beans::PropertyValue > aResult = mxRenderable->getRenderer(nCurrentPage - 1, selection, renderProperties ); + for( const auto& rProperty : aResult ) + { + if ( rProperty.Name == "PageSize" ) + { + rProperty.Value >>= aSize; + } + else if (rProperty.Name == "PagePos") + { + rProperty.Value >>= aPos; + } + else if (rProperty.Name == "CalcPagePos") + { + rProperty.Value >>= aCalcPos; + } + else if (rProperty.Name == "CalcPageContentSize") + { + rProperty.Value >>= aCalcPageSize; + } + } + } + + if (pDocumentPosition) + { + *pDocumentPosition = Point(aPos.X, aPos.Y); + } + if (pCalcPagePosition) + { + *pCalcPagePosition = Point(aCalcPos.X, aCalcPos.Y); + } + if (pCalcPageSize) + { + *pCalcPageSize = Size(aCalcPageSize.Width, aCalcPageSize.Height); + } + + return Size( aSize.Width, aSize.Height ); +} + +Graphic DocumentToGraphicRenderer::renderToGraphic( + sal_Int32 nCurrentPage, + Size aDocumentSizePixel, + Size aTargetSizePixel, + Color aPageColor, + bool bExtOutDevData) + +{ + if (!mxModel.is() || !mxController.is() || !mxRenderable.is()) + return Graphic(); + + Reference< awt::XDevice > xDevice(mxToolkit->createScreenCompatibleDevice( aTargetSizePixel.Width(), aTargetSizePixel.Height() ) ); + if (!xDevice.is()) + return Graphic(); + + assert( !aDocumentSizePixel.IsEmpty() && !aTargetSizePixel.IsEmpty()); + + double fScaleX = aTargetSizePixel.Width() / static_cast(aDocumentSizePixel.Width()); + double fScaleY = aTargetSizePixel.Height() / static_cast(aDocumentSizePixel.Height()); + + PropertyValues renderProps{ + comphelper::makePropertyValue("IsPrinter", true), + comphelper::makePropertyValue("RenderDevice", xDevice), + comphelper::makePropertyValue("View", mxController), + comphelper::makePropertyValue("RenderToGraphic", true), + comphelper::makePropertyValue("HasPDFExtOutDevData", bExtOutDevData), + comphelper::makePropertyValue("PageRange", OUString::number(nCurrentPage)) + }; + + GDIMetaFile aMtf; + + OutputDevice* pOutputDev = VCLUnoHelper::GetOutputDevice( xDevice ); + + vcl::PDFExtOutDevData aPDFExtOutDevData(*pOutputDev); + if (bExtOutDevData) + { + aPDFExtOutDevData.SetIsExportBookmarks(true); + pOutputDev->SetExtOutDevData(&aPDFExtOutDevData); + } + + pOutputDev->SetAntialiasing(pOutputDev->GetAntialiasing() | AntialiasingFlags::Enable); + MapMode mm = pOutputDev->GetMapMode(); + mm.SetScaleX( Fraction(fScaleX) ); + mm.SetScaleY( Fraction(fScaleY) ); + pOutputDev->SetMapMode( mm ); + + aMtf.Record( pOutputDev ); + + if (aPageColor != COL_TRANSPARENT) + { + pOutputDev->SetBackground(Wallpaper(aPageColor)); + pOutputDev->Erase(); + } + + uno::Any aSelection( getSelection()); + mxRenderable->render(nCurrentPage - 1, aSelection, renderProps ); + + aMtf.Stop(); + aMtf.WindStart(); + aMtf.SetPrefSize( aTargetSizePixel ); + + if (bExtOutDevData) + maChapterNames = aPDFExtOutDevData.GetChapterNames(); + + return Graphic(aMtf); +} + +const std::vector& DocumentToGraphicRenderer::getChapterNames() const +{ + return maChapterNames; +} + +sal_Int32 DocumentToGraphicRenderer::getCurrentPage() +{ + if (hasSelection()) + return 1; + + if (isWriter()) + return getCurrentPageWriter(); + + /* TODO: other application specific page detection? */ + return 1; +} + +sal_Int32 DocumentToGraphicRenderer::getPageCount() +{ + Reference< awt::XDevice > xDevice(mxToolkit->createScreenCompatibleDevice( 32, 32 ) ); + + uno::Any selection( getSelection() ); + + PropertyValues renderProperties{ comphelper::makePropertyValue("IsPrinter", true), + comphelper::makePropertyValue("RenderDevice", xDevice), + comphelper::makePropertyValue("View", mxController), + comphelper::makePropertyValue("RenderToGraphic", true) }; + + sal_Int32 nPages = mxRenderable->getRendererCount( selection, renderProperties ); + + return nPages; +} + +sal_Int32 DocumentToGraphicRenderer::getCurrentPageWriter() +{ + Reference xTextViewCursorSupplier(mxModel->getCurrentController(), UNO_QUERY); + if (!xTextViewCursorSupplier.is()) + return 1; + Reference xCursor(xTextViewCursorSupplier->getViewCursor(), UNO_QUERY); + return xCursor.is() ? xCursor->getPage() : 1; +} + +// static +bool DocumentToGraphicRenderer::isShapeSelected( + css::uno::Reference< css::drawing::XShapes > & rxShapes, + css::uno::Reference< css::drawing::XShape > & rxShape, + const css::uno::Reference< css::frame::XController > & rxController ) +{ + bool bShape = false; + if (rxController.is()) + { + uno::Reference< view::XSelectionSupplier > xSelectionSupplier( rxController, uno::UNO_QUERY); + if (xSelectionSupplier.is()) + { + uno::Any aAny( xSelectionSupplier->getSelection()); + if (aAny >>= rxShapes) + bShape = true; + else if (aAny >>= rxShape) + bShape = true; + } + } + return bShape; +} + +bool DocumentToGraphicRenderer::isWriter() const +{ + if (meDocType == WRITER) + return true; + else + return false; +} + +bool DocumentToGraphicRenderer::isCalc() const +{ + if (meDocType == CALC) + return true; + else + return false; +} + +bool DocumentToGraphicRenderer::isImpress() const +{ + if (meDocType == IMPRESS) + return true; + else + return false; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ -- cgit v1.2.3