/* -*- 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: */