summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAshod Nakashian <ashod.nakashian@collabora.co.uk>2018-04-07 15:22:06 -0400
committerJan Holesovsky <kendy@collabora.com>2018-06-06 12:46:00 +0200
commit745afeac6a067ce9cd84b6ea64dde56e2a0089bf (patch)
tree0d0b6d30073efa8dfe07a5b940c6b1d733f8ad81
parent953d81b7eb72b4e50ab1a0c2a6a70aa5e9847134 (diff)
svx: support breaking PDFs imported as images
Change-Id: I990c2b3c3055fbffddedc407c34beb5824277b38
-rw-r--r--sd/source/filter/pdf/sdpdffilter.cxx2
-rw-r--r--svx/Library_svxcore.mk2
-rw-r--r--svx/source/svdraw/svdedtv.cxx14
-rw-r--r--svx/source/svdraw/svdedtv2.cxx28
-rw-r--r--svx/source/svdraw/svdograf.cxx1
-rw-r--r--svx/source/svdraw/svdpdf.cxx1022
-rw-r--r--svx/source/svdraw/svdpdf.hxx120
-rw-r--r--vcl/source/gdi/impgraph.cxx4
8 files changed, 1178 insertions, 15 deletions
diff --git a/sd/source/filter/pdf/sdpdffilter.cxx b/sd/source/filter/pdf/sdpdffilter.cxx
index 6d45eb0a953f..a9ccb82633c0 100644
--- a/sd/source/filter/pdf/sdpdffilter.cxx
+++ b/sd/source/filter/pdf/sdpdffilter.cxx
@@ -124,7 +124,7 @@ bool SdPdfFilter::Import()
Graphic aGraphic(aBitmap);
aGraphic.setPdfData(std::make_shared<uno::Sequence<sal_Int8>>(aPdfData));
aGraphic.setPageNumber(nPageNumber);
- aGraphic.SetLink(aGfxLink);
+ aGraphic.SetGfxLink(aGfxLink);
// Create the page and insert the Graphic.
SdPage* pPage = mrDocument.GetSdPage(nPageNumber++, PageKind::Standard);
diff --git a/svx/Library_svxcore.mk b/svx/Library_svxcore.mk
index 603860d7f11b..6c39be7cf742 100644
--- a/svx/Library_svxcore.mk
+++ b/svx/Library_svxcore.mk
@@ -84,6 +84,7 @@ $(eval $(call gb_Library_use_externals,svxcore,\
icuuc \
icu_headers \
libxml2 \
+ $(if $(filter PDFIUM,$(BUILD_TYPE)),pdfium) \
))
ifeq ($(ENABLE_HEADLESS),)
$(eval $(call gb_Library_use_externals,svxcore,\
@@ -338,6 +339,7 @@ $(eval $(call gb_Library_add_exception_objects,svxcore,\
svx/source/svdraw/svdovirt \
svx/source/svdraw/svdpage \
svx/source/svdraw/svdpagv \
+ svx/source/svdraw/svdpdf \
svx/source/svdraw/svdpntv \
svx/source/svdraw/svdpoev \
svx/source/svdraw/svdsnpv \
diff --git a/svx/source/svdraw/svdedtv.cxx b/svx/source/svdraw/svdedtv.cxx
index 6db2aeb45d9c..a5dc2ec795b9 100644
--- a/svx/source/svdraw/svdedtv.cxx
+++ b/svx/source/svdraw/svdedtv.cxx
@@ -607,14 +607,18 @@ void SdrEditView::CheckPossibilities()
if (!bImportMtfPossible)
{
const SdrGrafObj* pSdrGrafObj = dynamic_cast< const SdrGrafObj* >(pObj);
- const SdrOle2Obj* pSdrOle2Obj = dynamic_cast< const SdrOle2Obj* >(pObj);
-
- if(pSdrGrafObj && ((pSdrGrafObj->HasGDIMetaFile() && !pSdrGrafObj->IsEPS()) || pSdrGrafObj->isEmbeddedVectorGraphicData()))
+ if (pSdrGrafObj != nullptr)
{
- bImportMtfPossible = true;
+ if ((pSdrGrafObj->HasGDIMetaFile() && !pSdrGrafObj->IsEPS()) ||
+ pSdrGrafObj->isEmbeddedVectorGraphicData() ||
+ pSdrGrafObj->isEmbeddedPdfData())
+ {
+ bImportMtfPossible = true;
+ }
}
- if(pSdrOle2Obj)
+ const SdrOle2Obj* pSdrOle2Obj = dynamic_cast< const SdrOle2Obj* >(pObj);
+ if (pSdrOle2Obj)
{
bImportMtfPossible = pSdrOle2Obj->GetObjRef().is();
}
diff --git a/svx/source/svdraw/svdedtv2.cxx b/svx/source/svdraw/svdedtv2.cxx
index 8d2fe58b611a..ae7fa5414fec 100644
--- a/svx/source/svdraw/svdedtv2.cxx
+++ b/svx/source/svdraw/svdedtv2.cxx
@@ -30,6 +30,7 @@
#include <svx/svdoole2.hxx>
#include <svx/dialmgr.hxx>
#include "svdfmtf.hxx"
+#include "svdpdf.hxx"
#include <svx/svdetc.hxx>
#include <sfx2/basedlgs.hxx>
#include <editeng/outlobj.hxx>
@@ -2038,22 +2039,35 @@ void SdrEditView::DoImportMarkedMtf(SvdProgressInfo *pProgrInfo)
SdrPageView* pPV=pM->GetPageView();
SdrObjList* pOL=pObj->getParentOfSdrObject();
const size_t nInsPos=pObj->GetOrdNum()+1;
- SdrGrafObj* pGraf= dynamic_cast<SdrGrafObj*>( pObj );
- SdrOle2Obj* pOle2= dynamic_cast<SdrOle2Obj*>( pObj );
sal_uIntPtr nInsAnz=0;
tools::Rectangle aLogicRect;
- if (pGraf && (pGraf->HasGDIMetaFile() || pGraf->isEmbeddedVectorGraphicData()))
+ SdrGrafObj* pGraf = dynamic_cast<SdrGrafObj*>( pObj );
+ if (pGraf != nullptr)
{
- GDIMetaFile aMetaFile(GetMetaFile(pGraf));
- if (aMetaFile.GetActionSize())
+ if (pGraf->HasGDIMetaFile() || pGraf->isEmbeddedVectorGraphicData())
+ {
+ GDIMetaFile aMetaFile(GetMetaFile(pGraf));
+ if (aMetaFile.GetActionSize())
+ {
+ aLogicRect = pGraf->GetLogicRect();
+ ImpSdrGDIMetaFileImport aFilter(*mpModel, pObj->GetLayer(), aLogicRect);
+ nInsAnz = aFilter.DoImport(aMetaFile, *pOL, nInsPos, pProgrInfo);
+ }
+ }
+ else if (pGraf->isEmbeddedPdfData())
{
aLogicRect = pGraf->GetLogicRect();
- ImpSdrGDIMetaFileImport aFilter(*mpModel, pObj->GetLayer(), aLogicRect);
- nInsAnz = aFilter.DoImport(aMetaFile, *pOL, nInsPos, pProgrInfo);
+ ImpSdrPdfImport aFilter(*mpModel, pObj->GetLayer(), aLogicRect, pGraf->getEmbeddedPdfData());
+ if (pGraf->getEmbeddedPageNumber() < aFilter.GetPageCount())
+ {
+ nInsAnz = aFilter.DoImport(*pOL, nInsPos, pGraf->getEmbeddedPageNumber(), pProgrInfo);
+ }
+
}
}
+ SdrOle2Obj* pOle2 = dynamic_cast<SdrOle2Obj*>(pObj);
if (pOle2 != nullptr && pOle2->GetGraphic())
{
aLogicRect = pOle2->GetLogicRect();
diff --git a/svx/source/svdraw/svdograf.cxx b/svx/source/svdraw/svdograf.cxx
index 0dc387891990..7c0f9336ea2c 100644
--- a/svx/source/svdraw/svdograf.cxx
+++ b/svx/source/svdraw/svdograf.cxx
@@ -50,6 +50,7 @@
#include <svx/xflbmtit.hxx>
#include <svx/svdundo.hxx>
#include "svdfmtf.hxx"
+#include "svdpdf.hxx"
#include <svx/sdgcpitm.hxx>
#include <editeng/eeitem.hxx>
#include <sdr/properties/graphicproperties.hxx>
diff --git a/svx/source/svdraw/svdpdf.cxx b/svx/source/svdraw/svdpdf.cxx
new file mode 100644
index 000000000000..d5ee381ffd0f
--- /dev/null
+++ b/svx/source/svdraw/svdpdf.cxx
@@ -0,0 +1,1022 @@
+/* -*- 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 "svdpdf.hxx"
+
+#include <config_features.h>
+
+#if HAVE_FEATURE_PDFIUM
+#include <fpdfview.h>
+#include <fpdf_edit.h>
+#include <fpdf_save.h>
+#include <fpdf_text.h>
+#endif
+
+#include <vcl/bitmapaccess.hxx>
+#include <vcl/graph.hxx>
+
+#include <editeng/editdata.hxx>
+#include <o3tl/make_unique.hxx>
+#include <math.h>
+#include <svx/xpoly.hxx>
+#include <vcl/svapp.hxx>
+#include <editeng/eeitem.hxx>
+#include <editeng/fhgtitem.hxx>
+#include <editeng/wghtitem.hxx>
+#include <editeng/postitem.hxx>
+#include <editeng/udlnitem.hxx>
+#include <editeng/crossedoutitem.hxx>
+#include <editeng/shdditem.hxx>
+#include <svx/xlnclit.hxx>
+#include <svx/xlncapit.hxx>
+#include <svx/xlnwtit.hxx>
+#include <svx/xflclit.hxx>
+#include <svx/xgrad.hxx>
+#include <svx/xflgrit.hxx>
+#include <editeng/fontitem.hxx>
+#include <editeng/autokernitem.hxx>
+#include <editeng/wrlmitem.hxx>
+#include <editeng/contouritem.hxx>
+#include <editeng/colritem.hxx>
+#include <vcl/metric.hxx>
+#include <editeng/charscaleitem.hxx>
+#include <svx/xflhtit.hxx>
+#include <svx/svdattr.hxx>
+#include <svx/svdmodel.hxx>
+#include <svx/svdpage.hxx>
+#include <svx/svdobj.hxx>
+#include <svx/svdotext.hxx>
+#include <svx/svdorect.hxx>
+#include <svx/svdocirc.hxx>
+#include <svx/svdograf.hxx>
+#include <svx/svdopath.hxx>
+#include <svx/svdetc.hxx>
+#include <svl/itemset.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <tools/helpers.hxx>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
+#include <svx/xlinjoit.hxx>
+#include <svx/xlndsit.hxx>
+#include <basegfx/polygon/b2dpolygonclipper.hxx>
+#include <svx/xbtmpit.hxx>
+#include <svx/xfltrit.hxx>
+#include <vcl/bitmapaccess.hxx>
+#include <svx/xflbmtit.hxx>
+#include <svx/xflbstit.hxx>
+#include <svx/svdpntv.hxx>
+#include <basegfx/polygon/b2dpolypolygontools.hxx>
+#include <svx/svditer.hxx>
+#include <svx/svdogrp.hxx>
+#include <vcl/BitmapTools.hxx>
+#include <com/sun/star/geometry/Matrix2D.hpp>
+
+using namespace com::sun::star;
+
+ImpSdrPdfImport::ImpSdrPdfImport(SdrModel& rModel, SdrLayerID nLay, const tools::Rectangle& rRect,
+ const std::shared_ptr<uno::Sequence<sal_Int8>>& pPdfData)
+ : maTmpList()
+ , mpVD(VclPtr<VirtualDevice>::Create())
+ , maScaleRect(rRect)
+ , mpPdfData(pPdfData)
+ , mnMapScalingOfs(0)
+ , mpLineAttr(nullptr)
+ , mpFillAttr(nullptr)
+ , mpTextAttr(nullptr)
+ , mpModel(&rModel)
+ , mnLayer(nLay)
+ , maOldLineColor()
+ , mnLineWidth(0)
+ , maLineJoin(basegfx::B2DLineJoin::NONE)
+ , maLineCap(css::drawing::LineCap_BUTT)
+ , maDash(css::drawing::DashStyle_RECT, 0, 0, 0, 0, 0)
+ , mbMov(false)
+ , mbSize(false)
+ , maOfs(0, 0)
+ , mfScaleX(1.0)
+ , mfScaleY(1.0)
+ , maScaleX(1.0)
+ , maScaleY(1.0)
+ , mbFntDirty(true)
+ , mbLastObjWasPolyWithoutLine(false)
+ , mbNoLine(false)
+ , mbNoFill(false)
+ , mbLastObjWasLine(false)
+ , maClip()
+{
+ mpVD->EnableOutput(false);
+ mpVD->SetLineColor();
+ mpVD->SetFillColor();
+ maOldLineColor.SetRed(mpVD->GetLineColor().GetRed() + 1);
+ mpLineAttr = o3tl::make_unique<SfxItemSet>(rModel.GetItemPool(),
+ svl::Items<XATTR_LINE_FIRST, XATTR_LINE_LAST>{});
+ mpFillAttr = o3tl::make_unique<SfxItemSet>(rModel.GetItemPool(),
+ svl::Items<XATTR_FILL_FIRST, XATTR_FILL_LAST>{});
+ mpTextAttr = o3tl::make_unique<SfxItemSet>(rModel.GetItemPool(),
+ svl::Items<EE_ITEMS_START, EE_ITEMS_END>{});
+ checkClip();
+
+ FPDF_LIBRARY_CONFIG aConfig;
+ aConfig.version = 2;
+ aConfig.m_pUserFontPaths = nullptr;
+ aConfig.m_pIsolate = nullptr;
+ aConfig.m_v8EmbedderSlot = 0;
+ FPDF_InitLibraryWithConfig(&aConfig);
+
+ // Load the buffer using pdfium.
+ mpPdfDocument = FPDF_LoadMemDocument(mpPdfData->getConstArray(), mpPdfData->getLength(),
+ /*password=*/nullptr);
+ if (!mpPdfDocument)
+ {
+ //TODO: Handle failure to load.
+ switch (FPDF_GetLastError())
+ {
+ case FPDF_ERR_SUCCESS:
+ break;
+ case FPDF_ERR_UNKNOWN:
+ break;
+ case FPDF_ERR_FILE:
+ break;
+ case FPDF_ERR_FORMAT:
+ break;
+ case FPDF_ERR_PASSWORD:
+ break;
+ case FPDF_ERR_SECURITY:
+ break;
+ case FPDF_ERR_PAGE:
+ break;
+ default:
+ break;
+ }
+
+ return;
+ }
+
+ mnPageCount = FPDF_GetPageCount(mpPdfDocument);
+}
+
+ImpSdrPdfImport::~ImpSdrPdfImport()
+{
+ FPDF_CloseDocument(mpPdfDocument);
+ FPDF_DestroyLibrary();
+}
+
+void ImpSdrPdfImport::DoLoopActions(SvdProgressInfo* pProgrInfo, sal_uInt32* pActionsToReport)
+{
+ const int nPageCount = FPDF_GetPageCount(mpPdfDocument);
+ SAL_WARN("sd.filter", "Pages: " << nPageCount);
+ for (size_t nPageIndex = 0; nPageIndex <= 0; ++nPageIndex)
+ {
+ // Render next page.
+ FPDF_PAGE pPdfPage = FPDF_LoadPage(mpPdfDocument, nPageIndex);
+ if (pPdfPage == nullptr)
+ break;
+
+ const double dPageWidth = FPDF_GetPageWidth(pPdfPage);
+ const double dPageHeight = FPDF_GetPageWidth(pPdfPage);
+ SAL_WARN("sd.filter", "Loaded page: " << nPageIndex << ", width: " << dPageWidth
+ << ", height: " << dPageHeight);
+
+ const int nPageObjectCount = FPDFPage_CountObject(pPdfPage);
+ for (int nPageObjectIndex = 0; nPageObjectIndex < nPageObjectCount; ++nPageObjectIndex)
+ {
+ FPDF_PAGEOBJECT pPageObject = FPDFPage_GetObject(pPdfPage, nPageObjectIndex);
+ if (pPageObject == nullptr)
+ continue;
+
+ SAL_WARN("sd.filter", "Got page object number: " << nPageObjectIndex);
+
+ // Process everything but text, which is done separately below.
+ const int nPageObjectType = FPDFPageObj_GetType(pPageObject);
+ switch (nPageObjectType)
+ {
+ case FPDF_PAGEOBJ_TEXT:
+ SAL_WARN("sd.filter", "Got page object TEXT");
+ break;
+ case FPDF_PAGEOBJ_PATH:
+ SAL_WARN("sd.filter", "Got page object PATH");
+ break;
+ case FPDF_PAGEOBJ_IMAGE:
+ SAL_WARN("sd.filter", "Got page object IMAGE");
+ break;
+ case FPDF_PAGEOBJ_SHADING:
+ SAL_WARN("sd.filter", "Got page object SHADING");
+ break;
+ case FPDF_PAGEOBJ_FORM:
+ SAL_WARN("sd.filter", "Got page object FORM");
+ break;
+ default:
+ SAL_WARN("sd.filter", "Unknown PDF page object type: " << nPageObjectType);
+ break;
+ }
+ }
+
+ // Now do the text.
+ FPDF_TEXTPAGE pTextPage = FPDFText_LoadPage(pPdfPage);
+ if (pTextPage != nullptr)
+ {
+ const int nChars = FPDFText_CountChars(pTextPage);
+ SAL_WARN("sd.filter", "Got page chars: " << nChars);
+
+ const int nRects = FPDFText_CountRects(pTextPage, 0, nChars);
+ SAL_WARN("sd.filter", "Got Rects: " << nRects);
+
+ std::unique_ptr<sal_Unicode[]> pText(new sal_Unicode[nChars]);
+ for (int nRectIndex = 0; nRectIndex < nRects; ++nRectIndex)
+ {
+ double left = 0;
+ double top = 0;
+ double right = 0;
+ double bottom = 0;
+ FPDFText_GetRect(pTextPage, nRectIndex, &left, &top, &right, &bottom);
+ if (right < left)
+ std::swap(right, left);
+ if (bottom < top)
+ std::swap(bottom, top);
+
+ SAL_WARN("sd.filter", "Got Text Rect: " << left << ", " << top << ", " << right
+ << ", " << bottom);
+ const int nBoundedChars = FPDFText_GetBoundedText(
+ pTextPage, left, top, right, bottom,
+ reinterpret_cast<unsigned short*>(pText.get()), nChars);
+ OUString sText(pText.get(), nBoundedChars);
+ SAL_WARN("sd.filter", "Got Text #" << nRectIndex + 1 << " (" << nBoundedChars
+ << "): [" << sText << "].");
+
+ const double dHalfCharWidth = (right - left) / nBoundedChars / 2.0;
+ SAL_WARN("sd.filter", "Half Char Width: " << dHalfCharWidth);
+ const int nCharIndex = FPDFText_GetCharIndexAtPos(pTextPage, left + dHalfCharWidth,
+ top + dHalfCharWidth,
+ dHalfCharWidth, dHalfCharWidth);
+ SAL_WARN("sd.filter", "Got Char Index: " << nCharIndex);
+
+ // FPDF_FONT pFont = FPDFText_GetFont(pTextPage, nCharIndex);
+ // const int nFontAscent = FPDFFont_GetAscent(pFont);
+ // const int nFontDescent = FPDFFont_GetDescent(pFont);
+ // FPDF_BYTESTRING sFontName = FPDFFont_GetName(pFont);
+ // SAL_WARN("sd.filter", "Char #" << nCharIndex << ", Got Font [" << sFontName <<
+ // "], Ascent: "<< nFontAscent << ", Descent: " << nFontDescent);
+
+ // FontMetric aFontMetric = mpVD->GetFontMetric();
+ // aFontMetric.SetAscent(nFontAscent);
+ // aFontMetric.SetDescent(nFontDescent);
+
+ const double dFontSize = FPDFText_GetFontSize(pTextPage, nCharIndex) * 140;
+ SAL_WARN("sd.filter", "Got Font Size: " << dFontSize);
+ vcl::Font aFnt = mpVD->GetFont();
+ aFnt.SetFontSize(Size(dFontSize, dFontSize));
+ mpVD->SetFont(aFnt);
+
+ double x = 0;
+ double y = 0;
+ FPDFText_GetCharOrigin(pTextPage, nCharIndex, &x, &y);
+ SAL_WARN("sd.filter", "Got Char Origin: " << x << ", " << y);
+
+ // geometry::RealRectangle2D aRect;
+ // aRect.X1 = left;
+ // aRect.Y1 = top;
+ // aRect.X2 = right;
+ // aRect.Y2 = bottom;
+
+ // geometry::Matrix2D aMatrix;
+ // FPDFText_GetMatrix(pTextPage, nCharIndex, &aMatrix.m00, &aMatrix.m01, &aMatrix.m10, &aMatrix.m11);
+
+ // basegfx::B2DHomMatrix fontMatrix(
+ // aMatrix.m00, aMatrix.m01, 0.0,
+ // aMatrix.m10, aMatrix.m11, 0.0);
+ // fontMatrix.scale(dFontSize, dFontSize);
+
+ // x = fontMatrix.get(0, 0) * x + fontMatrix.get(1, 0) * y + x;
+ // y = fontMatrix.get(0, 1) * x + fontMatrix.get(1, 1) * y + y;
+ // SAL_WARN("sd.filter", "Char Origin after xform: " << x << ", " << y);
+
+ // basegfx::B2DHomMatrix totalTextMatrix1(fontMatrix);
+ // basegfx::B2DHomMatrix totalTextMatrix2(fontMatrix);
+ // totalTextMatrix1.translate(rRect.X1, rRect.Y1);
+ // totalTextMatrix2.translate(rRect.X2, rRect.Y2);
+
+ // basegfx::B2DHomMatrix corrMatrix;
+ // corrMatrix.scale(1.0, -1.0);
+ // // corrMatrix.translate(0.0, ascent);
+ // totalTextMatrix1 = totalTextMatrix1 * corrMatrix;
+ // totalTextMatrix2 = totalTextMatrix2 * corrMatrix;
+
+ // totalTextMatrix1 *= getCurrentContext().Transformation;
+ // totalTextMatrix2 *= getCurrentContext().Transformation;
+
+ // basegfx::B2DHomMatrix invMatrix(totalTextMatrix1);
+ // basegfx::B2DHomMatrix invPrevMatrix(prevTextMatrix);
+ // invMatrix.invert();
+ // invPrevMatrix.invert();
+ // basegfx::B2DHomMatrix offsetMatrix1(totalTextMatrix1);
+ // basegfx::B2DHomMatrix offsetMatrix2(totalTextMatrix2);
+ // offsetMatrix1 *= invPrevMatrix;
+ // offsetMatrix2 *= invMatrix;
+
+ // double charWidth = offsetMatrix2.get(0, 2);
+ // double prevSpaceWidth = offsetMatrix1.get(0, 2) - prevCharWidth;
+
+ ImportText(Point(x, y), sText);
+ }
+
+ FPDFText_ClosePage(pTextPage);
+ }
+
+ FPDF_ClosePage(pPdfPage);
+ }
+
+ // const sal_uLong nCount(rMtf.GetActionSize());
+
+ for (sal_uLong a(0); a < 0; a++)
+ {
+ if (pProgrInfo && pActionsToReport)
+ {
+ (*pActionsToReport)++;
+
+ if (*pActionsToReport >= 16) // update all 16 actions
+ {
+ if (!pProgrInfo->ReportActions(*pActionsToReport))
+ break;
+
+ *pActionsToReport = 0;
+ }
+ }
+ }
+}
+
+size_t ImpSdrPdfImport::DoImport(SdrObjList& rOL, size_t nInsPos, size_t nPageNumber,
+ SvdProgressInfo* pProgrInfo)
+{
+ // setup some global scale parameter
+ // mfScaleX, mfScaleY, maScaleX, maScaleY, mbMov, mbSize
+ mfScaleX = mfScaleY = 10;
+ /*
+ mfScaleX = mfScaleY = 1.0;
+ const Size aMtfSize(rMtf.GetPrefSize());
+
+ if (aMtfSize.Width() & aMtfSize.Height() && (!maScaleRect.IsEmpty()))
+ {
+ maOfs = maScaleRect.TopLeft();
+
+ if (aMtfSize.Width() != (maScaleRect.GetWidth() - 1))
+ {
+ mfScaleX = static_cast<double>(maScaleRect.GetWidth() - 1)
+ / static_cast<double>(aMtfSize.Width());
+ }
+
+ if (aMtfSize.Height() != (maScaleRect.GetHeight() - 1))
+ {
+ mfScaleY = static_cast<double>(maScaleRect.GetHeight() - 1)
+ / static_cast<double>(aMtfSize.Height());
+ }
+ }
+
+ mbMov = maOfs.X() != 0 || maOfs.Y() != 0;
+ mbSize = false;
+ maScaleX = Fraction(1, 1);
+ maScaleY = Fraction(1, 1);
+
+ if (aMtfSize.Width() != (maScaleRect.GetWidth() - 1))
+ {
+ maScaleX = Fraction(maScaleRect.GetWidth() - 1, aMtfSize.Width());
+ mbSize = true;
+ }
+
+ if (aMtfSize.Height() != (maScaleRect.GetHeight() - 1))
+ {
+ maScaleY = Fraction(maScaleRect.GetHeight() - 1, aMtfSize.Height());
+ mbSize = true;
+ }
+ */
+
+ if (pProgrInfo)
+ {
+ // pProgrInfo->SetActionCount(rMtf.GetActionSize());
+ }
+
+ sal_uInt32 nActionsToReport(0);
+
+ // execute
+ DoLoopActions(pProgrInfo, &nActionsToReport);
+
+ if (pProgrInfo)
+ {
+ pProgrInfo->ReportActions(nActionsToReport);
+ nActionsToReport = 0;
+ }
+
+ // MapMode scaling
+ MapScaling();
+
+ // To calculate the progress meter, we use GetActionSize()*3.
+ // However, maTmpList has a lower entry count limit than GetActionSize(),
+ // so the actions that were assumed were too much have to be re-added.
+ // nActionsToReport = (rMtf.GetActionSize() - maTmpList.size()) * 2;
+
+ // announce all currently unannounced rescales
+ if (pProgrInfo)
+ {
+ pProgrInfo->ReportRescales(nActionsToReport);
+ pProgrInfo->SetInsertCount(maTmpList.size());
+ }
+
+ nActionsToReport = 0;
+
+ // insert all objects cached in aTmpList now into rOL from nInsPos
+ nInsPos = std::min(nInsPos, rOL.GetObjCount());
+
+ for (SdrObject* pObj : maTmpList)
+ {
+ rOL.NbcInsertObject(pObj, nInsPos);
+ nInsPos++;
+
+ if (pProgrInfo)
+ {
+ nActionsToReport++;
+
+ if (nActionsToReport >= 32) // update all 32 actions
+ {
+ pProgrInfo->ReportInserts(nActionsToReport);
+ nActionsToReport = 0;
+ }
+ }
+ }
+
+ // report all remaining inserts for the last time
+ if (pProgrInfo)
+ {
+ pProgrInfo->ReportInserts(nActionsToReport);
+ }
+
+ return maTmpList.size();
+}
+
+void ImpSdrPdfImport::SetAttributes(SdrObject* pObj, bool bForceTextAttr)
+{
+ mbNoLine = false;
+ mbNoFill = false;
+ bool bLine(!bForceTextAttr);
+ bool bFill(!pObj || (pObj->IsClosedObj() && !bForceTextAttr));
+ bool bText(bForceTextAttr || (pObj && pObj->GetOutlinerParaObject()));
+
+ if (bLine)
+ {
+ if (mnLineWidth)
+ {
+ mpLineAttr->Put(XLineWidthItem(mnLineWidth));
+ }
+ else
+ {
+ mpLineAttr->Put(XLineWidthItem(0));
+ }
+
+ maOldLineColor = mpVD->GetLineColor();
+
+ if (mpVD->IsLineColor())
+ {
+ mpLineAttr->Put(XLineStyleItem(drawing::LineStyle_SOLID));
+ mpLineAttr->Put(XLineColorItem(OUString(), mpVD->GetLineColor()));
+ }
+ else
+ {
+ mpLineAttr->Put(XLineStyleItem(drawing::LineStyle_NONE));
+ }
+
+ switch (maLineJoin)
+ {
+ case basegfx::B2DLineJoin::NONE:
+ mpLineAttr->Put(XLineJointItem(css::drawing::LineJoint_NONE));
+ break;
+ case basegfx::B2DLineJoin::Bevel:
+ mpLineAttr->Put(XLineJointItem(css::drawing::LineJoint_BEVEL));
+ break;
+ case basegfx::B2DLineJoin::Miter:
+ mpLineAttr->Put(XLineJointItem(css::drawing::LineJoint_MITER));
+ break;
+ case basegfx::B2DLineJoin::Round:
+ mpLineAttr->Put(XLineJointItem(css::drawing::LineJoint_ROUND));
+ break;
+ }
+
+ // Add LineCap support
+ mpLineAttr->Put(XLineCapItem(maLineCap));
+
+ if (((maDash.GetDots() && maDash.GetDotLen())
+ || (maDash.GetDashes() && maDash.GetDashLen()))
+ && maDash.GetDistance())
+ {
+ mpLineAttr->Put(XLineDashItem(OUString(), maDash));
+ }
+ else
+ {
+ mpLineAttr->Put(XLineDashItem(OUString(), XDash(css::drawing::DashStyle_RECT)));
+ }
+ }
+ else
+ {
+ mbNoLine = true;
+ }
+
+ if (bFill)
+ {
+ if (mpVD->IsFillColor())
+ {
+ mpFillAttr->Put(XFillStyleItem(drawing::FillStyle_SOLID));
+ mpFillAttr->Put(XFillColorItem(OUString(), mpVD->GetFillColor()));
+ }
+ else
+ {
+ mpFillAttr->Put(XFillStyleItem(drawing::FillStyle_NONE));
+ }
+ }
+ else
+ {
+ mbNoFill = true;
+ }
+
+ if (bText && mbFntDirty)
+ {
+ vcl::Font aFnt(mpVD->GetFont());
+ const sal_uInt32 nHeight(FRound(aFnt.GetFontSize().Height() * mfScaleY));
+ SAL_WARN("sd.filter", "Font Height: " << nHeight);
+
+ mpTextAttr->Put(SvxFontItem(aFnt.GetFamilyType(), aFnt.GetFamilyName(), aFnt.GetStyleName(),
+ aFnt.GetPitch(), aFnt.GetCharSet(), EE_CHAR_FONTINFO));
+ mpTextAttr->Put(SvxFontItem(aFnt.GetFamilyType(), aFnt.GetFamilyName(), aFnt.GetStyleName(),
+ aFnt.GetPitch(), aFnt.GetCharSet(), EE_CHAR_FONTINFO_CJK));
+ mpTextAttr->Put(SvxFontItem(aFnt.GetFamilyType(), aFnt.GetFamilyName(), aFnt.GetStyleName(),
+ aFnt.GetPitch(), aFnt.GetCharSet(), EE_CHAR_FONTINFO_CTL));
+ mpTextAttr->Put(SvxPostureItem(aFnt.GetItalic(), EE_CHAR_ITALIC));
+ mpTextAttr->Put(SvxWeightItem(aFnt.GetWeight(), EE_CHAR_WEIGHT));
+ mpTextAttr->Put(SvxFontHeightItem(nHeight, 100, EE_CHAR_FONTHEIGHT));
+ mpTextAttr->Put(SvxFontHeightItem(nHeight, 100, EE_CHAR_FONTHEIGHT_CJK));
+ mpTextAttr->Put(SvxFontHeightItem(nHeight, 100, EE_CHAR_FONTHEIGHT_CTL));
+ mpTextAttr->Put(SvxCharScaleWidthItem(100, EE_CHAR_FONTWIDTH));
+ mpTextAttr->Put(SvxUnderlineItem(aFnt.GetUnderline(), EE_CHAR_UNDERLINE));
+ mpTextAttr->Put(SvxOverlineItem(aFnt.GetOverline(), EE_CHAR_OVERLINE));
+ mpTextAttr->Put(SvxCrossedOutItem(aFnt.GetStrikeout(), EE_CHAR_STRIKEOUT));
+ mpTextAttr->Put(SvxShadowedItem(aFnt.IsShadow(), EE_CHAR_SHADOW));
+
+ // #i118485# Setting this item leads to problems (written #i118498# for this)
+ // mpTextAttr->Put(SvxAutoKernItem(aFnt.IsKerning(), EE_CHAR_KERNING));
+
+ mpTextAttr->Put(SvxWordLineModeItem(aFnt.IsWordLineMode(), EE_CHAR_WLM));
+ mpTextAttr->Put(SvxContourItem(aFnt.IsOutline(), EE_CHAR_OUTLINE));
+ mpTextAttr->Put(SvxColorItem(mpVD->GetTextColor(), EE_CHAR_COLOR));
+ //... svxfont textitem svditext
+ mbFntDirty = false;
+ }
+
+ if (pObj)
+ {
+ pObj->SetLayer(mnLayer);
+
+ if (bLine)
+ {
+ pObj->SetMergedItemSet(*mpLineAttr);
+ }
+
+ if (bFill)
+ {
+ pObj->SetMergedItemSet(*mpFillAttr);
+ }
+
+ if (bText)
+ {
+ pObj->SetMergedItemSet(*mpTextAttr);
+ pObj->SetMergedItem(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_LEFT));
+ }
+ }
+}
+
+void ImpSdrPdfImport::InsertObj(SdrObject* pObj, bool bScale)
+{
+ if (bScale && !maScaleRect.IsEmpty())
+ {
+ if (mbSize)
+ {
+ pObj->NbcResize(Point(), maScaleX, maScaleY);
+ }
+
+ if (mbMov)
+ {
+ pObj->NbcMove(Size(maOfs.X(), maOfs.Y()));
+ }
+ }
+
+ if (isClip())
+ {
+ const basegfx::B2DPolyPolygon aPoly(pObj->TakeXorPoly());
+ const basegfx::B2DRange aOldRange(aPoly.getB2DRange());
+ const SdrLayerID aOldLayer(pObj->GetLayer());
+ const SfxItemSet aOldItemSet(pObj->GetMergedItemSet());
+ const SdrGrafObj* pSdrGrafObj = dynamic_cast<SdrGrafObj*>(pObj);
+ const SdrTextObj* pSdrTextObj = dynamic_cast<SdrTextObj*>(pObj);
+
+ if (pSdrTextObj && pSdrTextObj->HasText())
+ {
+ // all text objects are created from ImportText and have no line or fill attributes, so
+ // it is okay to concentrate on the text itself
+ while (true)
+ {
+ const basegfx::B2DPolyPolygon aTextContour(pSdrTextObj->TakeContour());
+ const basegfx::B2DRange aTextRange(aTextContour.getB2DRange());
+ const basegfx::B2DRange aClipRange(maClip.getB2DRange());
+
+ // no overlap -> completely outside
+ if (!aClipRange.overlaps(aTextRange))
+ {
+ SdrObject::Free(pObj);
+ break;
+ }
+
+ // when the clip is a rectangle fast check for inside is possible
+ if (basegfx::utils::isRectangle(maClip) && aClipRange.isInside(aTextRange))
+ {
+ // completely inside ClipRect
+ break;
+ }
+
+ // here text needs to be clipped; to do so, convert to SdrObjects with polygons
+ // and add these recursively. Delete original object, do not add in this run
+ SdrObject* pConverted = pSdrTextObj->ConvertToPolyObj(true, true);
+ SdrObject::Free(pObj);
+
+ if (pConverted)
+ {
+ // recursively add created conversion; per definition this shall not
+ // contain further SdrTextObjs. Visit only non-group objects
+ SdrObjListIter aIter(*pConverted, SdrIterMode::DeepNoGroups);
+
+ // work with clones; the created conversion may contain group objects
+ // and when working with the original objects the loop itself could
+ // break and the cleanup later would be pretty complicated (only delete group
+ // objects, are these empty, ...?)
+ while (aIter.IsMore())
+ {
+ SdrObject* pCandidate = aIter.Next();
+ OSL_ENSURE(pCandidate && dynamic_cast<SdrObjGroup*>(pCandidate) == nullptr,
+ "SdrObjListIter with SdrIterMode::DeepNoGroups error (!)");
+ SdrObject* pNewClone = pCandidate->Clone();
+
+ if (pNewClone)
+ {
+ InsertObj(pNewClone, false);
+ }
+ else
+ {
+ OSL_ENSURE(false, "SdrObject::Clone() failed (!)");
+ }
+ }
+
+ // cleanup temporary conversion objects
+ SdrObject::Free(pConverted);
+ }
+
+ break;
+ }
+ }
+ else
+ {
+ BitmapEx aBitmapEx;
+
+ if (pSdrGrafObj)
+ {
+ aBitmapEx = pSdrGrafObj->GetGraphic().GetBitmapEx();
+ }
+
+ SdrObject::Free(pObj);
+
+ if (!aOldRange.isEmpty())
+ {
+ // clip against ClipRegion
+ const basegfx::B2DPolyPolygon aNewPoly(basegfx::utils::clipPolyPolygonOnPolyPolygon(
+ aPoly, maClip, true, !aPoly.isClosed()));
+ const basegfx::B2DRange aNewRange(aNewPoly.getB2DRange());
+
+ if (!aNewRange.isEmpty())
+ {
+ pObj = new SdrPathObj(*mpModel, aNewPoly.isClosed() ? OBJ_POLY : OBJ_PLIN,
+ aNewPoly);
+
+ pObj->SetLayer(aOldLayer);
+ pObj->SetMergedItemSet(aOldItemSet);
+
+ if (!!aBitmapEx)
+ {
+ // aNewRange is inside of aOldRange and defines which part of aBitmapEx is used
+ const double fScaleX(aBitmapEx.GetSizePixel().Width()
+ / (aOldRange.getWidth() ? aOldRange.getWidth() : 1.0));
+ const double fScaleY(
+ aBitmapEx.GetSizePixel().Height()
+ / (aOldRange.getHeight() ? aOldRange.getHeight() : 1.0));
+ basegfx::B2DRange aPixel(aNewRange);
+ basegfx::B2DHomMatrix aTrans;
+
+ aTrans.translate(-aOldRange.getMinX(), -aOldRange.getMinY());
+ aTrans.scale(fScaleX, fScaleY);
+ aPixel.transform(aTrans);
+
+ const Size aOrigSizePixel(aBitmapEx.GetSizePixel());
+ const Point aClipTopLeft(
+ basegfx::fround(floor(std::max(0.0, aPixel.getMinX()))),
+ basegfx::fround(floor(std::max(0.0, aPixel.getMinY()))));
+ const Size aClipSize(
+ basegfx::fround(ceil(std::min(
+ static_cast<double>(aOrigSizePixel.Width()), aPixel.getWidth()))),
+ basegfx::fround(
+ ceil(std::min(static_cast<double>(aOrigSizePixel.Height()),
+ aPixel.getHeight()))));
+ const BitmapEx aClippedBitmap(aBitmapEx, aClipTopLeft, aClipSize);
+
+ pObj->SetMergedItem(XFillStyleItem(drawing::FillStyle_BITMAP));
+ pObj->SetMergedItem(XFillBitmapItem(OUString(), Graphic(aClippedBitmap)));
+ pObj->SetMergedItem(XFillBmpTileItem(false));
+ pObj->SetMergedItem(XFillBmpStretchItem(true));
+ }
+ }
+ }
+ }
+ }
+
+ if (pObj)
+ {
+ // #i111954# check object for visibility
+ // used are SdrPathObj, SdrRectObj, SdrCircObj, SdrGrafObj
+ bool bVisible(false);
+
+ if (pObj->HasLineStyle())
+ {
+ bVisible = true;
+ }
+
+ if (!bVisible && pObj->HasFillStyle())
+ {
+ bVisible = true;
+ }
+
+ if (!bVisible)
+ {
+ SdrTextObj* pTextObj = dynamic_cast<SdrTextObj*>(pObj);
+
+ if (pTextObj && pTextObj->HasText())
+ {
+ bVisible = true;
+ }
+ }
+
+ if (!bVisible)
+ {
+ SdrGrafObj* pGrafObj = dynamic_cast<SdrGrafObj*>(pObj);
+
+ if (pGrafObj)
+ {
+ // this may be refined to check if the graphic really is visible. It
+ // is here to ensure that graphic objects without fill, line and text
+ // get created
+ bVisible = true;
+ }
+ }
+
+ if (!bVisible)
+ {
+ SdrObject::Free(pObj);
+ }
+ else
+ {
+ maTmpList.push_back(pObj);
+
+ if (dynamic_cast<SdrPathObj*>(pObj))
+ {
+ const bool bClosed(pObj->IsClosedObj());
+
+ mbLastObjWasPolyWithoutLine = mbNoLine && bClosed;
+ mbLastObjWasLine = !bClosed;
+ }
+ else
+ {
+ mbLastObjWasPolyWithoutLine = false;
+ mbLastObjWasLine = false;
+ }
+ }
+ }
+}
+
+bool ImpSdrPdfImport::CheckLastLineMerge(const basegfx::B2DPolygon& rSrcPoly)
+{
+ // #i102706# Do not merge closed polygons
+ if (rSrcPoly.isClosed())
+ {
+ return false;
+ }
+
+ // #i73407# reformulation to use new B2DPolygon classes
+ if (mbLastObjWasLine && (maOldLineColor == mpVD->GetLineColor()) && rSrcPoly.count())
+ {
+ SdrObject* pTmpObj = maTmpList.size() ? maTmpList[maTmpList.size() - 1] : nullptr;
+ SdrPathObj* pLastPoly = dynamic_cast<SdrPathObj*>(pTmpObj);
+
+ if (pLastPoly)
+ {
+ if (1 == pLastPoly->GetPathPoly().count())
+ {
+ bool bOk(false);
+ basegfx::B2DPolygon aDstPoly(pLastPoly->GetPathPoly().getB2DPolygon(0));
+
+ // #i102706# Do not merge closed polygons
+ if (aDstPoly.isClosed())
+ {
+ return false;
+ }
+
+ if (aDstPoly.count())
+ {
+ const sal_uInt32 nMaxDstPnt(aDstPoly.count() - 1);
+ const sal_uInt32 nMaxSrcPnt(rSrcPoly.count() - 1);
+
+ if (aDstPoly.getB2DPoint(nMaxDstPnt) == rSrcPoly.getB2DPoint(0))
+ {
+ aDstPoly.append(rSrcPoly, 1, rSrcPoly.count() - 1);
+ bOk = true;
+ }
+ else if (aDstPoly.getB2DPoint(0) == rSrcPoly.getB2DPoint(nMaxSrcPnt))
+ {
+ basegfx::B2DPolygon aNew(rSrcPoly);
+ aNew.append(aDstPoly, 1, aDstPoly.count() - 1);
+ aDstPoly = aNew;
+ bOk = true;
+ }
+ else if (aDstPoly.getB2DPoint(0) == rSrcPoly.getB2DPoint(0))
+ {
+ aDstPoly.flip();
+ aDstPoly.append(rSrcPoly, 1, rSrcPoly.count() - 1);
+ bOk = true;
+ }
+ else if (aDstPoly.getB2DPoint(nMaxDstPnt) == rSrcPoly.getB2DPoint(nMaxSrcPnt))
+ {
+ basegfx::B2DPolygon aNew(rSrcPoly);
+ aNew.flip();
+ aDstPoly.append(aNew, 1, aNew.count() - 1);
+ bOk = true;
+ }
+ }
+
+ if (bOk)
+ {
+ pLastPoly->NbcSetPathPoly(basegfx::B2DPolyPolygon(aDstPoly));
+ }
+
+ return bOk;
+ }
+ }
+ }
+
+ return false;
+}
+
+bool ImpSdrPdfImport::CheckLastPolyLineAndFillMerge(const basegfx::B2DPolyPolygon& rPolyPolygon)
+{
+ // #i73407# reformulation to use new B2DPolygon classes
+ if (mbLastObjWasPolyWithoutLine)
+ {
+ SdrObject* pTmpObj = maTmpList.size() ? maTmpList[maTmpList.size() - 1] : nullptr;
+ SdrPathObj* pLastPoly = dynamic_cast<SdrPathObj*>(pTmpObj);
+
+ if (pLastPoly)
+ {
+ if (pLastPoly->GetPathPoly() == rPolyPolygon)
+ {
+ SetAttributes(nullptr);
+
+ if (!mbNoLine && mbNoFill)
+ {
+ pLastPoly->SetMergedItemSet(*mpLineAttr);
+
+ return true;
+ }
+ }
+ }
+ }
+
+ return false;
+}
+
+void ImpSdrPdfImport::checkClip()
+{
+ if (mpVD->IsClipRegion())
+ {
+ maClip = mpVD->GetClipRegion().GetAsB2DPolyPolygon();
+
+ if (isClip())
+ {
+ const basegfx::B2DHomMatrix aTransform(basegfx::utils::createScaleTranslateB2DHomMatrix(
+ mfScaleX, mfScaleY, maOfs.X(), maOfs.Y()));
+
+ maClip.transform(aTransform);
+ }
+ }
+}
+
+bool ImpSdrPdfImport::isClip() const { return !maClip.getB2DRange().isEmpty(); }
+
+void ImpSdrPdfImport::ImportText(const Point& rPos, const OUString& rStr)
+{
+ // calc text box size, add 5% to make it fit safely
+
+ FontMetric aFontMetric(mpVD->GetFontMetric());
+ vcl::Font aFnt(mpVD->GetFont());
+ FontAlign eAlg(aFnt.GetAlignment());
+
+ sal_Int32 nTextWidth = static_cast<sal_Int32>(mpVD->GetTextWidth(rStr) * mfScaleX);
+ sal_Int32 nTextHeight = static_cast<sal_Int32>(mpVD->GetTextHeight() * mfScaleY);
+ SAL_WARN("sd.filter", "TextWidth: " << nTextWidth << ", TextHeight: " << nTextHeight);
+
+ Point aPos(FRound(rPos.X() * mfScaleX + maOfs.X()), FRound(rPos.Y() * mfScaleY + maOfs.Y()));
+ Size aSize(nTextWidth, nTextHeight);
+
+ if (eAlg == ALIGN_BASELINE)
+ aPos.AdjustY(-(FRound(aFontMetric.GetAscent() * mfScaleY)));
+ else if (eAlg == ALIGN_BOTTOM)
+ aPos.AdjustY(-nTextHeight);
+
+ tools::Rectangle aTextRect(aPos, aSize);
+ SdrRectObj* pText = new SdrRectObj(*mpModel, OBJ_TEXT, aTextRect);
+
+ pText->SetMergedItem(makeSdrTextUpperDistItem(0));
+ pText->SetMergedItem(makeSdrTextLowerDistItem(0));
+ pText->SetMergedItem(makeSdrTextRightDistItem(0));
+ pText->SetMergedItem(makeSdrTextLeftDistItem(0));
+
+ if (aFnt.GetAverageFontWidth())
+ {
+ pText->ClearMergedItem(SDRATTR_TEXT_AUTOGROWWIDTH);
+ pText->SetMergedItem(makeSdrTextAutoGrowHeightItem(false));
+ // don't let the margins eat the space needed for the text
+ pText->SetMergedItem(SdrTextFitToSizeTypeItem(drawing::TextFitToSizeType_ALLLINES));
+ }
+ else
+ {
+ pText->SetMergedItem(makeSdrTextAutoGrowWidthItem(true));
+ }
+
+ pText->SetLayer(mnLayer);
+ pText->NbcSetText(rStr);
+ SetAttributes(pText, true);
+ pText->SetSnapRect(aTextRect);
+
+ if (!aFnt.IsTransparent())
+ {
+ SfxItemSet aAttr(*mpFillAttr->GetPool(), svl::Items<XATTR_FILL_FIRST, XATTR_FILL_LAST>{});
+ aAttr.Put(XFillStyleItem(drawing::FillStyle_SOLID));
+ aAttr.Put(XFillColorItem(OUString(), aFnt.GetFillColor()));
+ pText->SetMergedItemSet(aAttr);
+ }
+ sal_uInt32 nAngle = aFnt.GetOrientation();
+ if (nAngle)
+ {
+ nAngle *= 10;
+ double a = nAngle * nPi180;
+ double nSin = sin(a);
+ double nCos = cos(a);
+ pText->NbcRotate(aPos, nAngle, nSin, nCos);
+ }
+ InsertObj(pText, false);
+}
+
+void ImpSdrPdfImport::MapScaling()
+{
+ const size_t nCount(maTmpList.size());
+ const MapMode& rMap = mpVD->GetMapMode();
+ Point aMapOrg(rMap.GetOrigin());
+ bool bMov2(aMapOrg.X() != 0 || aMapOrg.Y() != 0);
+
+ if (bMov2)
+ {
+ for (size_t i = mnMapScalingOfs; i < nCount; i++)
+ {
+ SdrObject* pObj = maTmpList[i];
+
+ pObj->NbcMove(Size(aMapOrg.X(), aMapOrg.Y()));
+ }
+ }
+
+ mnMapScalingOfs = nCount;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/source/svdraw/svdpdf.hxx b/svx/source/svdraw/svdpdf.hxx
new file mode 100644
index 000000000000..4f382a14a015
--- /dev/null
+++ b/svx/source/svdraw/svdpdf.hxx
@@ -0,0 +1,120 @@
+/* -*- 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 .
+ */
+
+#ifndef INCLUDED_SVX_SOURCE_SVDRAW_SVDPDF_HXX
+#define INCLUDED_SVX_SOURCE_SVDRAW_SVDPDF_HXX
+
+#include <sal/config.h>
+
+#include <memory>
+
+#include <tools/contnr.hxx>
+#include <tools/fract.hxx>
+#include <vcl/metaact.hxx>
+#include <vcl/virdev.hxx>
+#include <svx/svdobj.hxx>
+#include <svx/xdash.hxx>
+#include <com/sun/star/uno/Sequence.hxx>
+
+// Forward Declarations
+
+class SfxItemSet;
+class SdrObjList;
+class SdrModel;
+class SdrPage;
+class SdrObject;
+class SvdProgressInfo;
+typedef void* FPDF_DOCUMENT;
+
+// Helper Class to import PDF
+class ImpSdrPdfImport final
+{
+ ::std::vector<SdrObject*> maTmpList;
+ ScopedVclPtr<VirtualDevice> mpVD;
+ tools::Rectangle maScaleRect;
+ const std::shared_ptr<css::uno::Sequence<sal_Int8>> mpPdfData;
+ size_t mnMapScalingOfs; // from here on, not edited with MapScaling
+ std::unique_ptr<SfxItemSet> mpLineAttr;
+ std::unique_ptr<SfxItemSet> mpFillAttr;
+ std::unique_ptr<SfxItemSet> mpTextAttr;
+ SdrModel* mpModel;
+ SdrLayerID mnLayer;
+ Color maOldLineColor;
+ sal_Int32 mnLineWidth;
+ basegfx::B2DLineJoin maLineJoin;
+ css::drawing::LineCap maLineCap;
+ XDash maDash;
+
+ bool mbMov;
+ bool mbSize;
+ Point maOfs;
+ double mfScaleX;
+ double mfScaleY;
+ Fraction maScaleX;
+ Fraction maScaleY;
+
+ bool mbFntDirty;
+
+ // to optimize (PenNULL,Brush,DrawPoly),(Pen,BrushNULL,DrawPoly) -> two-in-one
+ bool mbLastObjWasPolyWithoutLine;
+ bool mbNoLine;
+ bool mbNoFill;
+
+ // to optimize multiple lines into a Polyline
+ bool mbLastObjWasLine;
+
+ // clipregion
+ basegfx::B2DPolyPolygon maClip;
+
+ FPDF_DOCUMENT mpPdfDocument;
+ int mnPageCount;
+
+ // check for clip and evtl. fill maClip
+ void checkClip();
+ bool isClip() const;
+
+ void ImportText(const Point& rPos, const OUString& rStr);
+ void SetAttributes(SdrObject* pObj, bool bForceTextAttr = false);
+ void InsertObj(SdrObject* pObj, bool bScale = true);
+ void MapScaling();
+
+ // #i73407# reformulation to use new B2DPolygon classes
+ bool CheckLastLineMerge(const basegfx::B2DPolygon& rSrcPoly);
+ bool CheckLastPolyLineAndFillMerge(const basegfx::B2DPolyPolygon& rPolyPolygon);
+
+ void DoLoopActions(SvdProgressInfo* pProgrInfo, sal_uInt32* pActionsToReport);
+
+ // Copy assignment is forbidden and not implemented.
+ ImpSdrPdfImport(const ImpSdrPdfImport&) = delete;
+ ImpSdrPdfImport& operator=(const ImpSdrPdfImport&) = delete;
+
+public:
+ ImpSdrPdfImport(SdrModel& rModel, SdrLayerID nLay, const tools::Rectangle& rRect,
+ const std::shared_ptr<css::uno::Sequence<sal_Int8>>& pPdfData);
+ ~ImpSdrPdfImport();
+
+ int GetPageCount() const { return mnPageCount; }
+
+ size_t DoImport(SdrObjList& rDestList, size_t nInsPos, size_t nPageNumber,
+ SvdProgressInfo* pProgrInfo = nullptr);
+};
+
+#endif // INCLUDED_SVX_SOURCE_SVDRAW_SVDFMTF_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/gdi/impgraph.cxx b/vcl/source/gdi/impgraph.cxx
index 0ad7dcb59b3f..6c727a322f81 100644
--- a/vcl/source/gdi/impgraph.cxx
+++ b/vcl/source/gdi/impgraph.cxx
@@ -195,12 +195,12 @@ ImpGraphic::ImpGraphic(const ImpGraphic& rImpGraphic)
, mnSizeBytes(rImpGraphic.mnSizeBytes)
, mbSwapOut(rImpGraphic.mbSwapOut)
, mbDummyContext(rImpGraphic.mbDummyContext)
- , mnPageNumber(-1)
, maVectorGraphicData(rImpGraphic.maVectorGraphicData)
, mpPdfData(rImpGraphic.mpPdfData)
, maGraphicExternalLink(rImpGraphic.maGraphicExternalLink)
, maLastUsed (std::chrono::high_resolution_clock::now())
, mbPrepared (rImpGraphic.mbPrepared)
+ , mnPageNumber(-1)
{
if( rImpGraphic.mpGfxLink )
mpGfxLink = o3tl::make_unique<GfxLink>( *rImpGraphic.mpGfxLink );
@@ -224,12 +224,12 @@ ImpGraphic::ImpGraphic(ImpGraphic&& rImpGraphic)
, mnSizeBytes(rImpGraphic.mnSizeBytes)
, mbSwapOut(rImpGraphic.mbSwapOut)
, mbDummyContext(rImpGraphic.mbDummyContext)
- , mnPageNumber(-1)
, maVectorGraphicData(std::move(rImpGraphic.maVectorGraphicData))
, mpPdfData(std::move(rImpGraphic.mpPdfData))
, maGraphicExternalLink(rImpGraphic.maGraphicExternalLink)
, maLastUsed (std::chrono::high_resolution_clock::now())
, mbPrepared (rImpGraphic.mbPrepared)
+ , mnPageNumber(-1)
{
rImpGraphic.ImplClear();
rImpGraphic.mbDummyContext = false;