Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/LibreOffice/svx/source/core/   (Office von Apache Version 25.8.3.2©)  Datei vom 5.10.2025 mit Größe 17 kB image not shown  

Quelle  graphichelper.cxx   Sprache: 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 <vcl/graphicfilter.hxx>
#include <sfx2/docfile.hxx>
#include <sfx2/filedlghelper.hxx>
#include <svx/xoutbmp.hxx>
#include <svx/dialmgr.hxx>
#include <svx/graphichelper.hxx>
#include <svx/strings.hrc>
#include <comphelper/diagnose_ex.hxx>
#include <vcl/svapp.hxx>
#include <vcl/weld.hxx>

#include <comphelper/processfactory.hxx>
#include <comphelper/propertyvalue.hxx>

#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/beans/PropertyValue.hpp>
#include <com/sun/star/container/NoSuchElementException.hpp>
#include <com/sun/star/document/XExporter.hpp>
#include <com/sun/star/drawing/GraphicExportFilter.hpp>
#include <com/sun/star/drawing/XShape.hpp>
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#include <com/sun/star/lang/XComponent.hpp>
#include <com/sun/star/io/XInputStream.hpp>
#include <com/sun/star/ucb/SimpleFileAccess.hpp>
#include <com/sun/star/ui/dialogs/XFilePicker3.hpp>
#include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
#include <com/sun/star/beans/XPropertyAccess.hpp>
#include <com/sun/star/task/ErrorCodeIOException.hpp>
#include <com/sun/star/graphic/XGraphic.hpp>
#include <com/sun/star/drawing/ShapeCollection.hpp>

#include <map>
#include <frozen/bits/defines.h>
#include <frozen/bits/elsa_std.h>
#include <frozen/unordered_map.h>

#include <unotools/streamwrap.hxx>

using namespace css;

namespace
{

const auto constGfxTypeToExtension = frozen::make_unordered_map<GfxLinkType, OUString>(
{
    { GfxLinkType::NativePng, u"png"_ustr },
    { GfxLinkType::NativeGif, u"gif"_ustr },
    { GfxLinkType::NativeTif, u"tif"_ustr },
    { GfxLinkType::NativeWmf, u"wmf"_ustr },
    { GfxLinkType::NativeMet, u"met"_ustr },
    { GfxLinkType::NativePct, u"pct"_ustr },
    { GfxLinkType::NativeJpg, u"jpg"_ustr },
    { GfxLinkType::NativeBmp, u"bmp"_ustr },
    { GfxLinkType::NativeSvg, u"svg"_ustr },
    { GfxLinkType::NativePdf, u"pdf"_ustr },
    { GfxLinkType::NativeWebp, u"webp"_ustr },
});

const auto constVectorGraphicTypeToExtension = frozen::make_unordered_map<VectorGraphicDataType, OUString>(
{
    { VectorGraphicDataType::Wmf, u"wmf"_ustr },
    { VectorGraphicDataType::Emf, u"emf"_ustr },
    { VectorGraphicDataType::Svg, u"svg"_ustr },
});

const auto constGfxTypeToString = frozen::make_unordered_map<GfxLinkType, TranslateId>(
{
    { GfxLinkType::NativePng, STR_IMAGE_PNG },
    { GfxLinkType::NativeGif, STR_IMAGE_GIF },
    { GfxLinkType::NativeTif, STR_IMAGE_TIFF },
    { GfxLinkType::NativeWmf, STR_IMAGE_WMF },
    { GfxLinkType::NativeMet, STR_IMAGE_MET },
    { GfxLinkType::NativePct, STR_IMAGE_PCT },
    { GfxLinkType::NativeJpg, STR_IMAGE_JPEG },
    { GfxLinkType::NativeBmp, STR_IMAGE_BMP },
    { GfxLinkType::NativeSvg, STR_IMAGE_SVG },
    { GfxLinkType::NativePdf, STR_IMAGE_PNG },
    { GfxLinkType::NativeWebp, STR_IMAGE_WEBP },
});

// end anonymous ns

void GraphicHelper::GetPreferredExtension( OUString& rExtension, const Graphic&&nbsp;rGraphic )
{
    auto const & rVectorGraphicDataPtr(rGraphic.getVectorGraphicData());

    if (rVectorGraphicDataPtr && !rVectorGraphicDataPtr->getBinaryDataContainer().isEmpty())
    {
        auto eType = rVectorGraphicDataPtr->getType();
        const auto iter = constVectorGraphicTypeToExtension.find(eType);
        if (iter != constVectorGraphicTypeToExtension.end())
            rExtension = iter->second;
        else
            rExtension = u"svg"_ustr; // not sure this makes sense but it is like this for a long time
    }
    else
    {
        auto eType = rGraphic.GetGfxLink().GetType();
        const auto iter = constGfxTypeToExtension.find(eType);
        if (iter != constGfxTypeToExtension.end())
            rExtension = iter->second;
        else
            rExtension = u"png"_ustr; // not sure this makes sense but it is like this for a long time
    }
}

OUString GraphicHelper::GetImageType(const Graphic& rGraphic)
{
    const auto& pGfxLink = rGraphic.GetSharedGfxLink();
    if (pGfxLink)
    {
        auto iter = constGfxTypeToString.find(pGfxLink->GetType());
        if (iter != constGfxTypeToString.end())
            return SvxResId(iter->second);
    }
    return SvxResId(STR_IMAGE_UNKNOWN);
}

namespace {


bool lcl_ExecuteFilterDialog(const uno::Sequence<beans::PropertyValue>& rPropsForDialog,
                             uno::Sequence<beans::PropertyValue>& rFilterData)
{
    bool bStatus = false;
    try
    {
        uno::Reference<ui::dialogs::XExecutableDialog> xFilterDialog(
                comphelper::getProcessServiceFactory()->createInstance( u"com.sun.star.svtools.SvFilterOptionsDialog"_ustr ), uno::UNO_QUERY);
        uno::Reference<beans::XPropertyAccess> xFilterProperties( xFilterDialog, uno::UNO_QUERY);

        if( xFilterDialog.is() && xFilterProperties.is() )
        {
            xFilterProperties->setPropertyValues( rPropsForDialog );
            if( xFilterDialog->execute() )
            {
                bStatus = true;
                const uno::Sequence<beans::PropertyValue> aPropsFromDialog = xFilterProperties->getPropertyValues();
                for ( const auto& rProp : aPropsFromDialog )
                {
                    if (rProp.Name == "FilterData")
                    {
                        rProp.Value >>= rFilterData;
                    }
                }
            }
        }
    }
    catch (container::NoSuchElementException const& exception)
    {
        // the filter name is unknown
        throw task::ErrorCodeIOException(
            ("lcl_ExecuteFilterDialog: NoSuchElementException"
             " \"" + exception.Message + "\": ERRCODE_IO_ABORT"),
            uno::Reference<uno::XInterface>(), sal_uInt32(ERRCODE_IO_INVALIDPARAMETER));
    }
    catch (const task::ErrorCodeIOException&)
    {
        throw;
    }
    catch (const uno::Exception&)
    {
        TOOLS_WARN_EXCEPTION("sfx.doc""ignoring");
    }

    return bStatus;
}
// anonymous ns

OUString GraphicHelper::ExportGraphic(weld::Window* pParent, const Graphic& rGraphic, const OUString& rGraphicName)
{
    sfx2::FileDialogHelper aDialogHelper(ui::dialogs::TemplateDescription::FILESAVE_AUTOEXTENSION, FileDialogFlags::NONE, pParent);
    uno::Reference<ui::dialogs::XFilePicker3> xFilePicker = aDialogHelper.GetFilePicker();

    // fish out the graphic's name
    aDialogHelper.SetContext(sfx2::FileDialogHelper::ExportImage);
    aDialogHelper.SetTitle( SvxResId(RID_SVXSTR_EXPORT_GRAPHIC_TITLE));
    INetURLObject aURL;
    aURL.SetSmartURL( rGraphicName );
    aDialogHelper.SetFileName(aURL.GetLastName());

    GraphicFilter& rGraphicFilter = GraphicFilter::GetGraphicFilter();
    const sal_uInt16 nCount = rGraphicFilter.GetExportFormatCount();

    OUString aExtension(aURL.GetFileExtension());
    if( aExtension.isEmpty() )
    {
        GetPreferredExtension( aExtension, rGraphic );
    }

    aExtension = aExtension.toAsciiLowerCase();
    sal_uInt16 nDefaultFilter = USHRT_MAX;

    for ( sal_uInt16 i = 0; i < nCount; i++ )
    {
        xFilePicker->appendFilter( rGraphicFilter.GetExportFormatName( i ), rGraphicFilter.GetExportWildcard( i ) );
        OUString aFormatShortName = rGraphicFilter.GetExportFormatShortName( i );
        if ( aFormatShortName.equalsIgnoreAsciiCase( aExtension ) )
        {
            nDefaultFilter = i;
        }
    }
    if ( USHRT_MAX == nDefaultFilter )
    {
        // "wrong" extension?
        GetPreferredExtension( aExtension, rGraphic );
        for ( sal_uInt16 i = 0; i < nCount; ++i )
            if ( aExtension == rGraphicFilter.GetExportFormatShortName( i ).toAsciiLowerCase() )
            {
                nDefaultFilter =  i;
                break;
            }
    }

    if( USHRT_MAX != nDefaultFilter )
    {
        xFilePicker->setCurrentFilter( rGraphicFilter.GetExportFormatName( nDefaultFilter ) ) ;

        if( aDialogHelper.Execute() == ERRCODE_NONE )
        {
            OUString sPath(xFilePicker->getSelectedFiles()[0]);
            if( !rGraphicName.isEmpty() &&
                nDefaultFilter == rGraphicFilter.GetExportFormatNumber( xFilePicker->getCurrentFilter()))
            {
                // try to save the original graphic
                SfxMedium aIn( rGraphicName, StreamMode::READ | StreamMode::NOCREATE );
                if( aIn.GetInStream() && !aIn.GetInStream()->GetError() )
                {
                    SfxMedium aOut( sPath, StreamMode::WRITE | StreamMode::SHARE_DENYNONE);
                    if( aOut.GetOutStream() && !aOut.GetOutStream()->GetError())
                    {
                        aOut.GetOutStream()->WriteStream( *aIn.GetInStream() );
                        if ( ERRCODE_NONE == aIn.GetErrorIgnoreWarning() )
                        {
                            aOut.Close();
                            aOut.Commit();
                            if ( ERRCODE_NONE == aOut.GetErrorIgnoreWarning() )
                                return sPath;
                        }
                    }
                }
            }

            sal_uInt16 nFilter;
            if ( !xFilePicker->getCurrentFilter().isEmpty() && rGraphicFilter.GetExportFormatCount() )
            {
                nFilter = rGraphicFilter.GetExportFormatNumber( xFilePicker->getCurrentFilter() );
            }
            else
            {
                nFilter = GRFILTER_FORMAT_DONTKNOW;
            }
            OUString aFilter( rGraphicFilter.GetExportFormatShortName( nFilter ) );

            if ( rGraphic.GetType() == GraphicType::Bitmap )
            {
                Graphic aGraphic = rGraphic;
                uno::Reference<graphic::XGraphic> xGraphic = aGraphic.GetXGraphic();

                OUString aExportFilter = rGraphicFilter.GetExportInternalFilterName(nFilter);

                uno::Sequence<beans::PropertyValue> aPropsForDialog
                {
                    comphelper::makePropertyValue(u"Graphic"_ustr, xGraphic),
                    comphelper::makePropertyValue(u"FilterName"_ustr, aExportFilter)
                };

                uno::Sequence<beans::PropertyValue> aFilterData;
                bool bStatus = lcl_ExecuteFilterDialog(aPropsForDialog, aFilterData);
                if (bStatus)
                {
                    sal_Int32 nWidth = 0;
                    sal_Int32 nHeight = 0;

                    for (const auto& rProp : aFilterData)
                    {
                        if (rProp.Name == "PixelWidth")
                        {
                            rProp.Value >>= nWidth;
                        }
                        else if (rProp.Name == "PixelHeight")
                        {
                            rProp.Value >>= nHeight;
                        }
                    }

                    // scaling must performed here because png/jpg writer s
                    // do not take care of that.
                    Size aSizePixel( aGraphic.GetSizePixel() );
                    if( nWidth && nHeight &&
                        ( ( nWidth != aSizePixel.Width() ) ||
                          ( nHeight != aSizePixel.Height() ) ) )
                    {
                        BitmapEx aBmpEx( aGraphic.GetBitmapEx() );
                        // export: use highest quality
                        aBmpEx.Scale( Size( nWidth, nHeight ), BmpScaleFlag::Lanczos );
                        aGraphic = aBmpEx;
                    }

                    XOutBitmap::WriteGraphic( aGraphic, sPath, aFilter,
                                                XOutFlags::DontExpandFilename |
                                                XOutFlags::DontAddExtension |
                                                XOutFlags::UseNativeIfPossible,
                                                nullptr, &aFilterData );
                    return sPath;
                }
            }
            else
            {
                XOutBitmap::WriteGraphic( rGraphic, sPath, aFilter,
                                            XOutFlags::DontExpandFilename |
                                            XOutFlags::DontAddExtension |
                                            XOutFlags::UseNativeIfPossible );
            }
        }
    }
    return OUString();
}

void GraphicHelper::SaveShapeAsGraphicToPath(
    const uno::Reference<lang::XComponent>& xComponent,
    const uno::Reference<drawing::XShape>& xShape, const OUString& aExportMimeType,
    const OUString& sPath)
{
    const uno::Reference<uno::XComponentContext>& xContext(::comphelper::getProcessComponentContext());
    uno::Reference<io::XInputStream> xGraphStream;

    if (xGraphStream.is())
    {
        uno::Reference<ucb::XSimpleFileAccess3> xFileAccess = ucb::SimpleFileAccess::create(xContext);
        xFileAccess->writeFile(sPath, xGraphStream);
    }
    else if (xComponent.is() && aExportMimeType == "application/pdf")
    {
        uno::Reference<lang::XMultiServiceFactory> xMSF(xContext->getServiceManager(), uno::UNO_QUERY);
        uno::Reference<document::XExporter> xExporter(
            xMSF->createInstance(u"com.sun.star.comp.PDF.PDFFilter"_ustr), uno::UNO_QUERY);
        xExporter->setSourceDocument(xComponent);

        uno::Reference<drawing::XShapes> xShapes
            = drawing::ShapeCollection::create(comphelper::getProcessComponentContext());
        xShapes->add(xShape);
        uno::Sequence<beans::PropertyValue> aFilterData{
            comphelper::makePropertyValue(u"Selection"_ustr, xShapes),
        };
        SvFileStream aStream(sPath, StreamMode::READWRITE | StreamMode::TRUNC);
        uno::Reference<io::XOutputStream> xStream(new utl::OStreamWrapper(aStream));
        uno::Sequence<beans::PropertyValue> aDescriptor
        {
            comphelper::makePropertyValue(u"FilterData"_ustr, aFilterData),
            comphelper::makePropertyValue(u"OutputStream"_ustr, xStream)
        };
        uno::Reference<document::XFilter> xFilter(xExporter, uno::UNO_QUERY);
        xFilter->filter(aDescriptor);
    }
    else
    {
        uno::Reference<drawing::XGraphicExportFilter> xGraphicExporter = drawing::GraphicExportFilter::create(xContext);

        uno::Sequence<beans::PropertyValue> aDescriptor{ comphelper::makePropertyValue(u"MediaType"_ustr,
                                                                           aExportMimeType),
                                             comphelper::makePropertyValue(u"URL"_ustr, sPath) };

        uno::Reference<lang::XComponent> xSourceDocument(xShape, uno::UNO_QUERY_THROW);
        xGraphicExporter->setSourceDocument(xSourceDocument);
        xGraphicExporter->filter(aDescriptor);
    }
}

void GraphicHelper::SaveShapeAsGraphic(weld::Window* pParent,
                                       const uno::Reference<lang::XComponent>& xComponent,
                                       const uno::Reference<drawing::XShape>& xShape)
{
    try
    {
        uno::Reference<beans::XPropertySet> xShapeSet(xShape, uno::UNO_QUERY_THROW);

        sfx2::FileDialogHelper aDialogHelper(ui::dialogs::TemplateDescription::FILESAVE_AUTOEXTENSION, FileDialogFlags::NONE, pParent);
        uno::Reference<ui::dialogs::XFilePicker3> xFilePicker = aDialogHelper.GetFilePicker();
        aDialogHelper.SetContext(sfx2::FileDialogHelper::ExportImage);
        aDialogHelper.SetTitle( SvxResId(RID_SVXSTR_SAVEAS_IMAGE) );

        // populate filter dialog filter list and select default filter to match graphic mime type

        GraphicFilter& rGraphicFilter = GraphicFilter::GetGraphicFilter();
        static constexpr OUStringLiteral aDefaultMimeType(u"image/png");
        OUString aDefaultFormatName;
        sal_uInt16 nCount = rGraphicFilter.GetExportFormatCount();

        std::map< OUString, OUString > aMimeTypeMap;

        for ( sal_uInt16 i = 0; i < nCount; i++ )
        {
            const OUString aExportFormatName( rGraphicFilter.GetExportFormatName( i ) );
            const OUString aFilterMimeType( rGraphicFilter.GetExportFormatMediaType( i ) );
            xFilePicker->appendFilter( aExportFormatName, rGraphicFilter.GetExportWildcard( i ) );
            aMimeTypeMap[ aExportFormatName ] = aFilterMimeType;
            if( aDefaultMimeType == aFilterMimeType )
                aDefaultFormatName = aExportFormatName;
        }

        if( !aDefaultFormatName.isEmpty() )
            xFilePicker->setCurrentFilter( aDefaultFormatName );

        // execute dialog

        if( aDialogHelper.Execute() == ERRCODE_NONE )
        {
            OUString sPath(xFilePicker->getSelectedFiles()[0]);
            OUString aExportMimeType( aMimeTypeMap[xFilePicker->getCurrentFilter()] );

            GraphicHelper::SaveShapeAsGraphicToPath(xComponent, xShape, aExportMimeType, sPath);
        }
    }
    catch (uno::Exception&)
    {
    }
}

short GraphicHelper::HasToSaveTransformedImage(weld::Widget* pWin)
{
    OUString aMsg(SvxResId(RID_SVXSTR_SAVE_MODIFIED_IMAGE));
    std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(pWin,
                                              VclMessageType::Question, VclButtonsType::YesNo, aMsg));
    return xBox->run();
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Messung V0.5
C=89 H=95 G=91

¤ Dauer der Verarbeitung: 0.7 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

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.