diff options
27 files changed, 628 insertions, 708 deletions
diff --git a/codemaker/source/cppumaker/cpputype.cxx b/codemaker/source/cppumaker/cpputype.cxx index 5f6d47ac6c70..aa332fb026e7 100644 --- a/codemaker/source/cppumaker/cpputype.cxx +++ b/codemaker/source/cppumaker/cpputype.cxx @@ -2819,16 +2819,7 @@ void ExceptionType::dumpHdlFile( if (name_ == "com.sun.star.uno.Exception") { includes.addCustom(u"#if defined(LIBO_INTERNAL_ONLY) && !defined(NDEBUG)"_ustr); - includes.addCustom(u"#if __has_include(<version>)"_ustr); - includes.addCustom(u"#include <version>"_ustr); - includes.addCustom(u"#endif"_ustr); - includes.addCustom(u"#if defined(__cpp_lib_source_location) && __cpp_lib_source_location >= 201907"_ustr); - includes.addCustom(u"#include <source_location>"_ustr); - includes.addCustom(u"#define LIBO_USE_SOURCE_LOCATION std"_ustr); - includes.addCustom(u"#elif __has_include(<experimental/source_location>)"_ustr); - includes.addCustom(u"#include <experimental/source_location>"_ustr); - includes.addCustom(u"#define LIBO_USE_SOURCE_LOCATION std::experimental"_ustr); - includes.addCustom(u"#endif"_ustr); + includes.addCustom(u"#include <o3tl/source_location.hxx>"_ustr); includes.addCustom(u"#endif"_ustr); includes.addCustom(u"#if defined LIBO_USE_SOURCE_LOCATION"_ustr); includes.addCustom(u"#include <o3tl/runtimetooustring.hxx>"_ustr); @@ -2870,9 +2861,9 @@ void ExceptionType::dumpHppFile( // default constructor out << "\ninline " << id_ << "::" << id_ << "(\n"; out << "#if defined LIBO_USE_SOURCE_LOCATION\n"; - out << " LIBO_USE_SOURCE_LOCATION::source_location location\n"; + out << " o3tl::source_location location\n"; out << "#endif\n"; - out << " )\n"; + out << ")\n"; inc(); OUString base(entity_->getDirectBase()); bool bFirst = true; @@ -2925,7 +2916,7 @@ void ExceptionType::dumpHppFile( bFirst = false; } out << "\n#if defined LIBO_USE_SOURCE_LOCATION\n"; - out << " " << (bFirst ? "" : ", ") << "LIBO_USE_SOURCE_LOCATION::source_location location\n"; + out << " " << (bFirst ? "" : ", ") << "o3tl::source_location location\n"; out << "#endif\n"; out << ")\n"; inc(); @@ -3186,9 +3177,9 @@ void ExceptionType::dumpDeclaration(FileStream & out) // default constructor out << indent() << "inline CPPU_GCC_DLLPRIVATE " << id_ << "(\n"; out << "#if defined LIBO_USE_SOURCE_LOCATION\n"; - out << " LIBO_USE_SOURCE_LOCATION::source_location location = LIBO_USE_SOURCE_LOCATION::source_location::current()\n"; - out << "#endif\n\n"; - out << " );\n"; + out << " o3tl::source_location location = o3tl::source_location::current()\n"; + out << "#endif\n"; + out << " );\n\n"; // constructor that initializes data members if (!entity_->getDirectMembers().empty() || getInheritedMemberCount() > 0) { @@ -3204,7 +3195,7 @@ void ExceptionType::dumpDeclaration(FileStream & out) bFirst = false; } out << "\n#if defined LIBO_USE_SOURCE_LOCATION\n"; - out << ", LIBO_USE_SOURCE_LOCATION::source_location location = LIBO_USE_SOURCE_LOCATION::source_location::current()\n"; + out << " , o3tl::source_location location = o3tl::source_location::current()\n"; out << "#endif\n"; out << " );\n\n"; } diff --git a/filter/source/pdf/impdialog.cxx b/filter/source/pdf/impdialog.cxx index 8584dd1a698e..fa1d634d6192 100644 --- a/filter/source/pdf/impdialog.cxx +++ b/filter/source/pdf/impdialog.cxx @@ -491,12 +491,11 @@ ImpPDFTabGeneralPage::ImpPDFTabGeneralPage(weld::Container* pPage, weld::DialogC , mxNfQuality(m_xBuilder->weld_metric_spin_button(u"quality"_ustr, FieldUnit::PERCENT)) , mxCbReduceImageResolution(m_xBuilder->weld_check_button(u"changeresolution"_ustr)) , mxCoReduceImageResolution(m_xBuilder->weld_combo_box(u"resolution"_ustr)) - , mxCbPDFA(m_xBuilder->weld_check_button(u"pdfa"_ustr)) , mxCbPDFUA(m_xBuilder->weld_check_button(u"pdfua"_ustr)) - , mxRbPDFAVersion(m_xBuilder->weld_combo_box(u"pdfaversion"_ustr)) + , mxRbPDFVersion(m_xBuilder->weld_combo_box(u"pdf_version"_ustr)) , mxCbTaggedPDF(m_xBuilder->weld_check_button(u"tagged"_ustr)) , mxCbExportFormFields(m_xBuilder->weld_check_button(u"forms"_ustr)) - , mxFormsFrame(m_xBuilder->weld_widget(u"formsframe"_ustr)) + , mxFormsFrame(m_xBuilder->weld_widget(u"forms_frame"_ustr)) , mxLbFormsFormat(m_xBuilder->weld_combo_box(u"format"_ustr)) , mxCbAllowDuplicateFieldNames(m_xBuilder->weld_check_button(u"allowdups"_ustr)) , mxCbExportBookmarks(m_xBuilder->weld_check_button(u"bookmarks"_ustr)) @@ -525,6 +524,24 @@ ImpPDFTabGeneralPage::~ImpPDFTabGeneralPage() mxPasswordUnusedWarnDialog->response(RET_CANCEL); } +bool ImpPDFTabGeneralPage::IsPdfaSelected() const +{ + OUString aVersion = mxRbPDFVersion->get_active_id(); + + return + aVersion == u"1"_ustr || + aVersion == u"2"_ustr || + aVersion == u"3"_ustr || + aVersion == u"4"_ustr; +} + +bool ImpPDFTabGeneralPage::IsPDFAVersionSelected(sal_Int32 nInputVersion) const +{ + OUString aVersion = mxRbPDFVersion->get_active_id(); + sal_Int32 nSelectedVersion = aVersion.toInt32(); + return nSelectedVersion == nInputVersion; +} + void ImpPDFTabGeneralPage::SetFilterConfigItem(ImpPDFTabDialog* pParent) { mpParent = pParent; @@ -572,38 +589,57 @@ void ImpPDFTabGeneralPage::SetFilterConfigItem(ImpPDFTabDialog* pParent) mxCbWatermark->connect_toggled( LINK( this, ImpPDFTabGeneralPage, ToggleWatermarkHdl ) ); mxFtWatermark->set_sensitive(false ); mxEdWatermark->set_sensitive( false ); - mxCbPDFA->connect_toggled(LINK(this, ImpPDFTabGeneralPage, TogglePDFVersionOrUniversalAccessibilityHandle)); - const bool bIsPDFA = (pParent->mnPDFTypeSelection>=1) && (pParent->mnPDFTypeSelection <= 3); - mxCbPDFA->set_active(bIsPDFA); - switch( pParent->mnPDFTypeSelection ) + bool bIsPDFA = false; + switch (pParent->mnPDFTypeSelection) { case 1: // PDF/A-1 - mxRbPDFAVersion->set_active_id(u"1"_ustr); + bIsPDFA = true; + mxRbPDFVersion->set_active_id(u"1"_ustr); break; case 2: // PDF/A-2 - mxRbPDFAVersion->set_active_id(u"2"_ustr); + bIsPDFA = true; + mxRbPDFVersion->set_active_id(u"2"_ustr); break; case 3: // PDF/A-3 + bIsPDFA = true; + mxRbPDFVersion->set_active_id(u"3"_ustr); + break; + case 4: // PDF/A-4 + bIsPDFA = true; + mxRbPDFVersion->set_active_id(u"4"_ustr); + break; + case 20: // PDF 2.0 + mxRbPDFVersion->set_active_id(u"20"_ustr); + break; + case 17: default: // PDF 1.x - mxRbPDFAVersion->set_active_id(u"3"_ustr); + mxRbPDFVersion->set_active_id(u"17"_ustr); break; } + mxRbPDFVersion->connect_changed(LINK(this, ImpPDFTabGeneralPage, SelectPDFVersion)); + const bool bIsPDFUA = pParent->mbPDFUACompliance; mxCbPDFUA->set_active(bIsPDFUA); - mxCbPDFUA->connect_toggled(LINK(this, ImpPDFTabGeneralPage, TogglePDFVersionOrUniversalAccessibilityHandle)); + mxCbPDFUA->connect_toggled(LINK(this, ImpPDFTabGeneralPage, TogglePDFUniversalAccessibilityHandle)); mxCbPDFUA->set_sensitive(!pParent->maConfigItem.IsReadOnly(u"PDFUACompliance"_ustr)); - // the TogglePDFVersionOrUniversalAccessibilityHandle handler will read or write the *UserSelection based - // on the mxCbPDFA (= bIsPDFA) state, so we have to prepare the correct input state. + // the thePDFVersionChanged will read or write the *UserSelection based on widget state, + // so we have to prepare the correct input state. if (bIsPDFA || bIsPDFUA) mxCbTaggedPDF->set_active(pParent->mbUseTaggedPDFUserSelection); else mbUseTaggedPDFUserSelection = pParent->mbUseTaggedPDFUserSelection; mxCbExportBookmarks->set_active(pParent->mbExportBookmarksUserSelection); - TogglePDFVersionOrUniversalAccessibilityHandle(*mxCbPDFA); + + mxCbAddStream->show(); + mxCbAddStream->set_active(pParent->mbAddStream); + mxCbAddStream->connect_toggled(LINK(this, ImpPDFTabGeneralPage, ToggleAddStreamHdl)); + ToggleAddStreamHdl(*mxCbAddStream); // init addstream dependencies + + thePDFVersionChanged(); mxCbExportFormFields->set_active(pParent->mbExportFormFields); mxCbExportFormFields->connect_toggled( LINK( this, ImpPDFTabGeneralPage, ToggleExportFormFieldsHdl ) ); @@ -695,13 +731,6 @@ void ImpPDFTabGeneralPage::SetFilterConfigItem(ImpPDFTabDialog* pParent) mxCbExportPlaceholders->set_active(pParent->mbIsExportPlaceholders); mxCbExportPlaceholders->set_sensitive( mbIsWriter && !pParent->maConfigItem.IsReadOnly(u"ExportPlaceholders"_ustr)); - - mxCbAddStream->show(); - mxCbAddStream->set_active(pParent->mbAddStream); - mxCbAddStream->set_sensitive(!pParent->maConfigItem.IsReadOnly(u"IsAddStream"_ustr)); - - mxCbAddStream->connect_toggled(LINK(this, ImpPDFTabGeneralPage, ToggleAddStreamHdl)); - ToggleAddStreamHdl(*mxCbAddStream); // init addstream dependencies } void ImpPDFTabGeneralPage::GetFilterConfigItem( ImpPDFTabDialog* pParent ) @@ -751,23 +780,23 @@ void ImpPDFTabGeneralPage::GetFilterConfigItem( ImpPDFTabDialog* pParent ) pParent->mnPDFTypeSelection = 0; pParent->mbUseTaggedPDF = mxCbTaggedPDF->get_active(); - const bool bIsPDFA = mxCbPDFA->get_active(); + const bool bIsPDFA = IsPdfaSelected(); const bool bIsPDFUA = mxCbPDFUA->get_active(); - if (bIsPDFA) - { - pParent->mnPDFTypeSelection = 3; - OUString currentPDFAMode = mxRbPDFAVersion->get_active_id(); - if( currentPDFAMode == "1" ) - pParent->mnPDFTypeSelection = 1; - else if(currentPDFAMode == "2") - pParent->mnPDFTypeSelection = 2; - } + OUString sCurrentPDFVersion = mxRbPDFVersion->get_active_id(); + sal_Int32 nValue = sCurrentPDFVersion.toInt32(); + + static constexpr const auto constValidValues = std::to_array<sal_Int32>({1, 2, 3, 4, 17, 20}); + if (std::find(constValidValues.begin(), constValidValues.end(), nValue) != constValidValues.end()) + pParent->mnPDFTypeSelection = nValue; + else + pParent->mnPDFTypeSelection = 17; pParent->mbPDFUACompliance = bIsPDFUA; if (!bIsPDFA && !bIsPDFUA) mbUseTaggedPDFUserSelection = pParent->mbUseTaggedPDF; + if (!bIsPDFUA) { pParent->mbExportBookmarksUserSelection = pParent->mbExportBookmarks; @@ -907,9 +936,9 @@ IMPL_LINK_NOARG(ImpPDFTabGeneralPage, ToggleAddStreamHdl, weld::Toggleable&, voi } } -IMPL_LINK_NOARG(ImpPDFTabGeneralPage, TogglePDFVersionOrUniversalAccessibilityHandle, weld::Toggleable&, void) +void ImpPDFTabGeneralPage::thePDFVersionChanged() { - const bool bIsPDFA = mxCbPDFA->get_active(); + const bool bIsPDFA = IsPdfaSelected(); const bool bIsPDFUA = mxCbPDFUA->get_active(); // set the security page status (and its controls as well) @@ -917,16 +946,14 @@ IMPL_LINK_NOARG(ImpPDFTabGeneralPage, TogglePDFVersionOrUniversalAccessibilityHa if (pSecPage) pSecPage->ImplPDFASecurityControl(); - mxCbTaggedPDF->set_sensitive( - !bIsPDFA && !bIsPDFUA && !IsReadOnlyProperty(u"UseTaggedPDF"_ustr)); - mxRbPDFAVersion->set_sensitive( - bIsPDFA && !IsReadOnlyProperty(u"SelectPdfVersion"_ustr)); + mxRbPDFVersion->set_sensitive(!IsReadOnlyProperty(u"SelectPdfVersion"_ustr)); if (bIsPDFA || bIsPDFUA) { // store the users selection of subordinate controls and set required PDF/A values mbUseTaggedPDFUserSelection = mxCbTaggedPDF->get_active(); mxCbTaggedPDF->set_active(true); + mxCbTaggedPDF->set_sensitive(false); // if a password was set, inform the user that this will not be used if (bIsPDFA && pSecPage && pSecPage->hasPassword()) @@ -942,6 +969,24 @@ IMPL_LINK_NOARG(ImpPDFTabGeneralPage, TogglePDFVersionOrUniversalAccessibilityHa { // restore the users values of subordinate controls mxCbTaggedPDF->set_active(mbUseTaggedPDFUserSelection); + mxCbTaggedPDF->set_sensitive(!IsReadOnlyProperty(u"UseTaggedPDF"_ustr)); + } + + if (IsPDFAVersionSelected(1) || IsPDFAVersionSelected(2)) + { + if (mxCbAddStream->get_sensitive()) + { + if (mpParent) + mpParent->mbAddStream = mxCbAddStream->get_active(); + + mxCbAddStream->set_active(false); + mxCbAddStream->set_sensitive(false); + } + } + else if (mpParent && !mxCbAddStream->get_sensitive()) + { + mxCbAddStream->set_active(mpParent->mbAddStream); + mxCbAddStream->set_sensitive(!mpParent->maConfigItem.IsReadOnly(u"IsAddStream"_ustr)); } if (bIsPDFUA) @@ -968,8 +1013,7 @@ IMPL_LINK_NOARG(ImpPDFTabGeneralPage, TogglePDFVersionOrUniversalAccessibilityHa mxCbExportBookmarks->set_active(mpParent->mbExportBookmarksUserSelection); mxCbUseReferenceXObject->set_active(mpParent->mbUseReferenceXObjectUserSelection); } - mxCbExportBookmarks->set_sensitive( - !bIsPDFUA && !IsReadOnlyProperty(u"ExportBookmarks"_ustr)); + mxCbExportBookmarks->set_sensitive(!bIsPDFUA && !IsReadOnlyProperty(u"ExportBookmarks"_ustr)); mxCbUseReferenceXObject->set_sensitive(!bIsPDFUA); ImpPDFTabOpnFtrPage *const pOpenPage(mpParent ? mpParent->getOpenPage() : nullptr); @@ -984,6 +1028,16 @@ IMPL_LINK_NOARG(ImpPDFTabGeneralPage, TogglePDFVersionOrUniversalAccessibilityHa pLinksPage->ImplPDFALinkControl(!bIsPDFA); } +IMPL_LINK_NOARG(ImpPDFTabGeneralPage, TogglePDFUniversalAccessibilityHandle, weld::Toggleable&, void) +{ + thePDFVersionChanged(); +} + +IMPL_LINK_NOARG(ImpPDFTabGeneralPage, SelectPDFVersion, weld::ComboBox&, void) +{ + thePDFVersionChanged(); +} + /// The option features tab page ImpPDFTabOpnFtrPage::ImpPDFTabOpnFtrPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rCoreSet) : SfxTabPage(pPage, pController, u"filter/ui/pdfviewpage.ui"_ustr, u"PdfViewPage"_ustr, &rCoreSet) @@ -1604,7 +1658,7 @@ void ImpPDFTabLinksPage::SetFilterConfigItem( const ImpPDFTabDialog* pParent ) ImpPDFTabGeneralPage* pGeneralPage = pParent->getGeneralPage(); if (pGeneralPage) - ImplPDFALinkControl(!pGeneralPage->mxCbPDFA->get_active()); + ImplPDFALinkControl(!pGeneralPage->IsPdfaSelected()); } diff --git a/filter/source/pdf/impdialog.hxx b/filter/source/pdf/impdialog.hxx index 0db3c4e66ed5..fba49c8f0301 100644 --- a/filter/source/pdf/impdialog.hxx +++ b/filter/source/pdf/impdialog.hxx @@ -197,9 +197,8 @@ class ImpPDFTabGeneralPage : public SfxTabPage std::unique_ptr<weld::MetricSpinButton> mxNfQuality; std::unique_ptr<weld::CheckButton> mxCbReduceImageResolution; std::unique_ptr<weld::ComboBox> mxCoReduceImageResolution; - std::unique_ptr<weld::CheckButton> mxCbPDFA; std::unique_ptr<weld::CheckButton> mxCbPDFUA; - std::unique_ptr<weld::ComboBox> mxRbPDFAVersion; + std::unique_ptr<weld::ComboBox> mxRbPDFVersion; std::unique_ptr<weld::CheckButton> mxCbTaggedPDF; std::unique_ptr<weld::CheckButton> mxCbExportFormFields; std::unique_ptr<weld::Widget> mxFormsFrame; @@ -238,7 +237,8 @@ class ImpPDFTabGeneralPage : public SfxTabPage void ToggleSheetsHdl(); void EnableExportNotesPages(); - DECL_LINK(TogglePDFVersionOrUniversalAccessibilityHandle, weld::Toggleable&, void); + DECL_LINK(TogglePDFUniversalAccessibilityHandle, weld::Toggleable&, void); + DECL_LINK(SelectPDFVersion, weld::ComboBox&, void); std::shared_ptr<weld::MessageDialog> mxPasswordUnusedWarnDialog; @@ -247,6 +247,8 @@ class ImpPDFTabGeneralPage : public SfxTabPage return mpParent && mpParent->maConfigItem.IsReadOnly(rPropertyName); } + void thePDFVersionChanged(); + public: ImpPDFTabGeneralPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet); @@ -256,7 +258,8 @@ public: void GetFilterConfigItem(ImpPDFTabDialog* paParent); void SetFilterConfigItem(ImpPDFTabDialog* paParent); - bool IsPdfaSelected() const { return mxCbPDFA->get_active(); } + bool IsPdfaSelected() const; + bool IsPDFAVersionSelected(sal_Int32 nVersion) const; bool IsPdfUaSelected() const { return mxCbPDFUA->get_active(); } }; diff --git a/filter/source/pdf/pdfexport.cxx b/filter/source/pdf/pdfexport.cxx index cca7703c50c8..8827971fcda5 100644 --- a/filter/source/pdf/pdfexport.cxx +++ b/filter/source/pdf/pdfexport.cxx @@ -752,7 +752,7 @@ bool PDFExport::Export( const OUString& rFile, const Sequence< PropertyValue >& { default: case 0: - aContext.Version = vcl::PDFWriter::PDFVersion::PDF_1_7; + aContext.Version = vcl::PDFWriter::PDFVersion::Default; break; case 1: aContext.Version = vcl::PDFWriter::PDFVersion::PDF_A_1; diff --git a/filter/uiconfig/ui/pdfgeneralpage.ui b/filter/uiconfig/ui/pdfgeneralpage.ui index ef6d9767b06b..212631e6c2de 100644 --- a/filter/uiconfig/ui/pdfgeneralpage.ui +++ b/filter/uiconfig/ui/pdfgeneralpage.ui @@ -527,15 +527,15 @@ <property name="orientation">vertical</property> <property name="spacing">12</property> <child> - <object class="GtkFrame" id="frame4"> + <object class="GtkFrame" id="general_frame"> <property name="visible">True</property> <property name="can-focus">False</property> <property name="margin-end">6</property> <property name="label-xalign">0</property> <property name="shadow-type">none</property> <child> - <!-- n-columns=1 n-rows=6 --> - <object class="GtkGrid" id="grid10"> + <!-- n-columns=1 n-rows=3 --> + <object class="GtkGrid" id="general_grid"> <property name="visible">True</property> <property name="can-focus">False</property> <property name="margin-start">12</property> @@ -547,68 +547,167 @@ <property name="visible">True</property> <property name="can-focus">True</property> <property name="receives-default">False</property> - <property name="tooltip-text" translatable="yes" context="pdfgeneralpage|embed|tooltip_text">Creates a PDF that is easily editable in %PRODUCTNAME</property> + <property name="tooltip-text" translatable="yes" context="pdfgeneralpage|embed|tooltip_text">Creates a PDF that embeds the original ODF file as an attachment.</property> <property name="halign">start</property> <property name="use-underline">True</property> <property name="draw-indicator">True</property> <child internal-child="accessible"> <object class="AtkObject" id="embed-atkobject"> - <property name="AtkObject::accessible-description" translatable="yes" context="pdfgeneralpage|extended_tip|embed">This setting enables you to export the document as a .pdf file containing two file formats: PDF and ODF.</property> + <property name="AtkObject::accessible-description" translatable="yes" context="pdfgeneralpage|extended_tip|embed">This setting enables you to export the document as a .pdf file containing two file formats: PDF and ODF as an attachment. </property> </object> </child> </object> <packing> <property name="left-attach">0</property> - <property name="top-attach">0</property> + <property name="top-attach">2</property> </packing> </child> <child> - <object class="GtkCheckButton" id="tagged"> - <property name="label" translatable="yes" context="pdfgeneralpage|tagged">_Tagged PDF (add document structure)</property> + <!-- n-columns=1 n-rows=1 --> + <object class="GtkGrid"> <property name="visible">True</property> - <property name="can-focus">True</property> - <property name="receives-default">False</property> - <property name="tooltip-text" translatable="yes" context="pdfgeneralpage|tagged|tooltip_text">Includes a document's content structure information in a PDF</property> - <property name="halign">start</property> - <property name="use-underline">True</property> - <property name="draw-indicator">True</property> - <child internal-child="accessible"> - <object class="AtkObject" id="tagged-atkobject"> - <property name="AtkObject::accessible-description" translatable="yes" context="pdfgeneralpage|extended_tip|tagged">Select to write PDF tags. This can increase file size by huge amounts.</property> + <property name="can-focus">False</property> + <property name="row-spacing">6</property> + <child> + <!-- n-columns=2 n-rows=1 --> + <object class="GtkGrid" id="pdfagrid"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="margin-start">18</property> + <property name="hexpand">True</property> + <property name="column-spacing">14</property> + <child> + <object class="GtkComboBoxText" id="pdf_version"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="tooltip-text" translatable="yes" context="pdfgeneralpage|pdf_version|tooltip_text">Select the PDF version. PDF/A version variants creates an ISO 19005 compliant PDF file, ideal for long-term document preservation.</property> + <property name="hexpand">True</property> + <property name="active">3</property> + <items> + <item id="17" translatable="yes" context="pdfgeneralpage|pdf_version">PDF 1.7</item> + <item id="20" translatable="yes" context="pdfgeneralpage|pdf_version">PDF 2.0</item> + <item id="1" context="pdfgeneralpage|pdf_version">PDF/A-1b (PDF 1.4 base)</item> + <item id="2" context="pdfgeneralpage|pdf_version">PDF/A-2b (PDF 1.7 base)</item> + <item id="3" context="pdfgeneralpage|pdf_version">PDF/A-3b (PDF 1.7 base)</item> + <item id="4" translatable="yes" context="pdfgeneralpage|pdf_version">PDF/A-4 (PDF 2.0 base)</item> + </items> + <accessibility> + <relation type="labelled-by" target="pdf_version_label"/> + </accessibility> + <child internal-child="accessible"> + <object class="AtkObject" id="pdf_version-atkobject"> + <property name="AtkObject::accessible-description" translatable="yes" context="pdfgeneralpage|extended_tip|pdf_version">Versions can be either the "classic" PDF (i.e. PDF 1.7, PDF 2.0) or PDF/A conformant. PDF/A is defined as an electronic document file format for long term preservation and archiving. It allows only a subset of PDF features that are compatible with that use case. For example: All fonts that were used in the source document will be embedded into the generated PDF file. PDF tags will be written.</property> + </object> + </child> + </object> + <packing> + <property name="left-attach">1</property> + <property name="top-attach">0</property> + </packing> + </child> + <child> + <object class="GtkBox" id="pdfabox"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="orientation">vertical</property> + <child> + <object class="GtkLabel" id="pdf_version_label"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="halign">start</property> + <property name="valign">baseline</property> + <property name="vexpand">True</property> + <property name="label" translatable="yes" context="pdfgeneralpage|pdf_version">PDF_ Version:</property> + <property name="use-underline">True</property> + <accessibility> + <relation type="label-for" target="pdf_version"/> + </accessibility> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + </object> + <packing> + <property name="left-attach">0</property> + <property name="top-attach">0</property> + </packing> + </child> </object> + <packing> + <property name="left-attach">0</property> + <property name="top-attach">0</property> + </packing> </child> </object> <packing> <property name="left-attach">0</property> - <property name="top-attach">3</property> + <property name="top-attach">0</property> </packing> </child> <child> - <object class="GtkCheckButton" id="forms"> - <property name="label" translatable="yes" context="pdfgeneralpage|forms">Create PDF for_m</property> + <object class="GtkCheckButton" id="pdfua"> + <property name="label" translatable="yes" context="pdfgeneralpage|pdfua">Universal Accessibilit_y (PDF/UA)</property> <property name="visible">True</property> <property name="can-focus">True</property> <property name="receives-default">False</property> - <property name="tooltip-text" translatable="yes" context="pdfgeneralpage|forms|tooltip_text">Creates a PDF with fields that can be filled out</property> + <property name="tooltip-text" translatable="yes" context="pdfgeneralpage|pdfua|tooltip_text">Creates a universal accessibility-compliant PDF file that follows the requirements of PDF/UA (ISO 14289) specifications.</property> <property name="halign">start</property> <property name="use-underline">True</property> <property name="draw-indicator">True</property> <child internal-child="accessible"> - <object class="AtkObject" id="forms-atkobject"> - <property name="AtkObject::accessible-description" translatable="yes" context="pdfgeneralpage|extended_tip|forms">Choose to create a PDF form. This can be filled out and printed by the user of the PDF document.</property> + <object class="AtkObject" id="pdfua-atkobject"> + <property name="AtkObject::accessible-description" translatable="yes" context="pdfgeneralpage|extended_tip|pdfua">Creates a universal accessibility-complying PDF file that follows the requirements of PDF/UA (ISO 14289) specifications.</property> </object> </child> </object> <packing> <property name="left-attach">0</property> - <property name="top-attach">4</property> + <property name="top-attach">1</property> </packing> </child> + </object> + </child> + <child type="label"> + <object class="GtkLabel" id="general_label"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="label" translatable="yes" context="pdfgeneralpage|general_label">General</property> + <attributes> + <attribute name="weight" value="bold"/> + </attributes> + </object> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkFrame" id="forms_frame"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="label-xalign">0</property> + <property name="shadow-type">none</property> + <child> + <!-- n-columns=1 n-rows=2 --> + <object class="GtkGrid" id="forms_grid"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="double-buffered">False</property> + <property name="margin-start">12</property> + <property name="margin-top">6</property> + <property name="row-spacing">3</property> <child> <!-- n-columns=2 n-rows=2 --> - <object class="GtkGrid" id="formsframe"> + <object class="GtkGrid" id="forms_options_grid"> <property name="visible">True</property> <property name="can-focus">False</property> + <property name="double-buffered">False</property> <property name="margin-start">18</property> <property name="hexpand">True</property> <property name="row-spacing">6</property> @@ -657,12 +756,12 @@ </packing> </child> <child> - <object class="GtkBox" id="submitformatbox"> + <object class="GtkBox" id="submitformatbox1"> <property name="visible">True</property> <property name="can-focus">False</property> <property name="orientation">vertical</property> <child> - <object class="GtkLabel" id="label7"> + <object class="GtkLabel" id="submit_format_label"> <property name="visible">True</property> <property name="can-focus">False</property> <property name="halign">start</property> @@ -689,134 +788,37 @@ </object> <packing> <property name="left-attach">0</property> - <property name="top-attach">5</property> - </packing> - </child> - <child> - <!-- n-columns=1 n-rows=2 --> - <object class="GtkGrid"> - <property name="visible">True</property> - <property name="can-focus">False</property> - <property name="row-spacing">6</property> - <child> - <object class="GtkCheckButton" id="pdfa"> - <property name="label" translatable="yes" context="pdfgeneralpage|pdfa">Archival (P_DF/A, ISO 19005)</property> - <property name="visible">True</property> - <property name="can-focus">True</property> - <property name="receives-default">False</property> - <property name="tooltip-text" translatable="yes" context="pdfgeneralpage|pdfa|tooltip_text">Creates an ISO 19005-2 compliant PDF file, ideal for long-term document preservation</property> - <property name="halign">start</property> - <property name="use-underline">True</property> - <property name="draw-indicator">True</property> - <child internal-child="accessible"> - <object class="AtkObject" id="pdfa-atkobject"> - <property name="AtkObject::accessible-description" translatable="yes" context="pdfgeneralpage|extended_tip|pdfa">Converts to the PDF/A-2b or PDF/A-1b format. This is defined as an electronic document file format for long term preservation. All fonts that were used in the source document will be embedded into the generated PDF file. PDF tags will be written.</property> - </object> - </child> - </object> - <packing> - <property name="left-attach">0</property> - <property name="top-attach">0</property> - </packing> - </child> - <child> - <!-- n-columns=2 n-rows=1 --> - <object class="GtkGrid" id="pdfagrid"> - <property name="visible">True</property> - <property name="can-focus">False</property> - <property name="margin-start">18</property> - <property name="hexpand">True</property> - <property name="column-spacing">14</property> - <child> - <object class="GtkComboBoxText" id="pdfaversion"> - <property name="visible">True</property> - <property name="can-focus">False</property> - <property name="hexpand">True</property> - <property name="active">3</property> - <items> - <item id="1" context="pdfgeneralpage|pdfaversion">PDF/A-1b</item> - <item id="2" context="pdfgeneralpage|pdfaversion">PDF/A-2b</item> - <item id="3" context="pdfgeneralpage|pdfaversion">PDF/A-3b</item> - </items> - <accessibility> - <relation type="labelled-by" target="pdfaversionlabel"/> - </accessibility> - </object> - <packing> - <property name="left-attach">1</property> - <property name="top-attach">0</property> - </packing> - </child> - <child> - <object class="GtkBox" id="pdfabox"> - <property name="visible">True</property> - <property name="can-focus">False</property> - <property name="orientation">vertical</property> - <child> - <object class="GtkLabel" id="pdfaversionlabel"> - <property name="visible">True</property> - <property name="can-focus">False</property> - <property name="halign">start</property> - <property name="valign">baseline</property> - <property name="vexpand">True</property> - <property name="label" translatable="yes" context="pdfgeneralpage|pdfaversion">PDF_/A version:</property> - <property name="use-underline">True</property> - <accessibility> - <relation type="label-for" target="pdfaversion"/> - </accessibility> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">0</property> - </packing> - </child> - </object> - <packing> - <property name="left-attach">0</property> - <property name="top-attach">0</property> - </packing> - </child> - </object> - <packing> - <property name="left-attach">0</property> - <property name="top-attach">1</property> - </packing> - </child> - </object> - <packing> - <property name="left-attach">0</property> <property name="top-attach">1</property> </packing> </child> <child> - <object class="GtkCheckButton" id="pdfua"> - <property name="label" translatable="yes" context="pdfgeneralpage|pdfua">Universal Accessibilit_y (PDF/UA)</property> + <object class="GtkCheckButton" id="forms"> + <property name="label" translatable="yes" context="pdfgeneralpage|forms">Create PDF for_m</property> <property name="visible">True</property> <property name="can-focus">True</property> <property name="receives-default">False</property> - <property name="tooltip-text" translatable="yes" context="pdfgeneralpage|pdfua|tooltip_text">Creates a universal accessibility-compliant PDF file that follows the requirements of PDF/UA (ISO 14289) specifications.</property> + <property name="tooltip-text" translatable="yes" context="pdfgeneralpage|forms|tooltip_text">Creates a PDF with fields that can be filled out</property> <property name="halign">start</property> <property name="use-underline">True</property> <property name="draw-indicator">True</property> <child internal-child="accessible"> - <object class="AtkObject" id="pdfua-atkobject"> - <property name="AtkObject::accessible-description" translatable="yes" context="pdfgeneralpage|extended_tip|pdfua">Creates a universal accessibility-complying PDF file that follows the requirements of PDF/UA (ISO 14289) specifications.</property> + <object class="AtkObject" id="forms-atkobject"> + <property name="AtkObject::accessible-description" translatable="yes" context="pdfgeneralpage|extended_tip|forms">Choose to create a PDF form. This can be filled out and printed by the user of the PDF document.</property> </object> </child> </object> <packing> <property name="left-attach">0</property> - <property name="top-attach">2</property> + <property name="top-attach">0</property> </packing> </child> </object> </child> <child type="label"> - <object class="GtkLabel" id="label4"> + <object class="GtkLabel" id="forms_label"> <property name="visible">True</property> <property name="can-focus">False</property> - <property name="label" translatable="yes" context="pdfgeneralpage|label4">General</property> + <property name="label" translatable="yes" context="pdfgeneralpage|forms_label">Forms</property> <attributes> <attribute name="weight" value="bold"/> </attributes> @@ -826,18 +828,18 @@ <packing> <property name="expand">False</property> <property name="fill">True</property> - <property name="position">0</property> + <property name="position">1</property> </packing> </child> <child> - <object class="GtkFrame" id="frame7"> + <object class="GtkFrame" id="structure_frame"> <property name="visible">True</property> <property name="can-focus">False</property> <property name="label-xalign">0</property> <property name="shadow-type">none</property> <child> - <!-- n-columns=1 n-rows=10 --> - <object class="GtkGrid" id="grid2"> + <!-- n-columns=1 n-rows=11 --> + <object class="GtkGrid" id="structure_grid"> <property name="visible">True</property> <property name="can-focus">False</property> <property name="margin-start">12</property> @@ -849,10 +851,10 @@ <property name="visible">True</property> <property name="can-focus">True</property> <property name="receives-default">False</property> + <property name="tooltip-text" translatable="yes" context="pdfgeneralpage|bookmarks|tooltip_text">Export headings along with hyperlinked entries in Table of Contents as PDF bookmarks.</property> <property name="halign">start</property> <property name="use-underline">True</property> <property name="draw-indicator">True</property> - <property name="tooltip-text" translatable="yes" context="pdfgeneralpage|bookmarks|tooltip_text">Export headings along with hyperlinked entries in Table of Contents as PDF bookmarks.</property> <child internal-child="accessible"> <object class="AtkObject" id="bookmarks-atkobject"> <property name="AtkObject::accessible-description" translatable="yes" context="pdfgeneralpage|extended_tip|bookmarks">PDF bookmarks are created for all paragraphs with outline level 1 or greater and for all “Table of Contents” entries with hyperlinks.</property> @@ -861,7 +863,7 @@ </object> <packing> <property name="left-attach">0</property> - <property name="top-attach">0</property> + <property name="top-attach">1</property> </packing> </child> <child> @@ -881,7 +883,7 @@ </object> <packing> <property name="left-attach">0</property> - <property name="top-attach">1</property> + <property name="top-attach">2</property> </packing> </child> <child> @@ -901,7 +903,7 @@ </object> <packing> <property name="left-attach">0</property> - <property name="top-attach">2</property> + <property name="top-attach">3</property> </packing> </child> <child> @@ -921,7 +923,7 @@ </object> <packing> <property name="left-attach">0</property> - <property name="top-attach">8</property> + <property name="top-attach">9</property> </packing> </child> <child> @@ -941,7 +943,7 @@ </object> <packing> <property name="left-attach">0</property> - <property name="top-attach">9</property> + <property name="top-attach">10</property> </packing> </child> <child> @@ -961,7 +963,7 @@ </object> <packing> <property name="left-attach">0</property> - <property name="top-attach">6</property> + <property name="top-attach">7</property> </packing> </child> <child> @@ -981,7 +983,7 @@ </object> <packing> <property name="left-attach">0</property> - <property name="top-attach">4</property> + <property name="top-attach">5</property> </packing> </child> <child> @@ -1002,7 +1004,7 @@ </object> <packing> <property name="left-attach">0</property> - <property name="top-attach">5</property> + <property name="top-attach">6</property> </packing> </child> <child> @@ -1022,7 +1024,7 @@ </object> <packing> <property name="left-attach">0</property> - <property name="top-attach">7</property> + <property name="top-attach">8</property> </packing> </child> <child> @@ -1042,16 +1044,37 @@ </object> <packing> <property name="left-attach">0</property> - <property name="top-attach">3</property> + <property name="top-attach">4</property> + </packing> + </child> + <child> + <object class="GtkCheckButton" id="tagged"> + <property name="label" translatable="yes" context="pdfgeneralpage|tagged">_Tagged PDF (add document structure)</property> + <property name="visible">True</property> + <property name="can-focus">True</property> + <property name="receives-default">False</property> + <property name="tooltip-text" translatable="yes" context="pdfgeneralpage|tagged|tooltip_text">Includes a document's content structure information in a PDF</property> + <property name="halign">start</property> + <property name="use-underline">True</property> + <property name="draw-indicator">True</property> + <child internal-child="accessible"> + <object class="AtkObject" id="tagged-atkobject"> + <property name="AtkObject::accessible-description" translatable="yes" context="pdfgeneralpage|extended_tip|tagged">Select to write PDF tags. This can increase file size by huge amounts.</property> + </object> + </child> + </object> + <packing> + <property name="left-attach">0</property> + <property name="top-attach">0</property> </packing> </child> </object> </child> <child type="label"> - <object class="GtkLabel" id="label9"> + <object class="GtkLabel" id="structure_label"> <property name="visible">True</property> <property name="can-focus">False</property> - <property name="label" translatable="yes" context="pdfgeneralpage|label9">Structure</property> + <property name="label" translatable="yes" context="pdfgeneralpage|structure_label">Structure</property> <attributes> <attribute name="weight" value="bold"/> </attributes> @@ -1061,7 +1084,7 @@ <packing> <property name="expand">False</property> <property name="fill">True</property> - <property name="position">1</property> + <property name="position">2</property> </packing> </child> </object> @@ -1071,15 +1094,8 @@ </packing> </child> </object> - <object class="GtkSizeGroup" id="comboBoxSizegroup"> - <widgets> - <widget name="format"/> - <widget name="pdfaversion"/> - </widgets> - </object> <object class="GtkSizeGroup" id="pdfSizeGroup"> <widgets> - <widget name="submitformatbox"/> <widget name="pdfabox"/> </widgets> </object> @@ -1104,4 +1120,5 @@ <widget name="watermarkentry"/> </widgets> </object> + <object class="GtkSizeGroup" id="comboBoxSizegroup"/> </interface> diff --git a/include/o3tl/source_location.hxx b/include/o3tl/source_location.hxx new file mode 100644 index 000000000000..919e9403f87b --- /dev/null +++ b/include/o3tl/source_location.hxx @@ -0,0 +1,34 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * 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/. + */ + +#ifndef INCLUDED_O3TL_SOURCE_LOCATION_HXX +#define INCLUDED_O3TL_SOURCE_LOCATION_HXX + +#if __has_include(<version>) +#include <version> +#endif + +#if defined(__cpp_lib_source_location) && __cpp_lib_source_location >= 201907 +#include <source_location> +#define LIBO_USE_SOURCE_LOCATION std +#elif __has_include(<experimental/source_location>) +#include <experimental/source_location> +#define LIBO_USE_SOURCE_LOCATION std::experimental +#endif + +#if defined LIBO_USE_SOURCE_LOCATION +namespace o3tl +{ +using source_location = LIBO_USE_SOURCE_LOCATION::source_location; +} +#endif + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/include/svx/nbdtmg.hxx b/include/svx/nbdtmg.hxx index bccb905a21a2..dcba2e89d1f6 100644 --- a/include/svx/nbdtmg.hxx +++ b/include/svx/nbdtmg.hxx @@ -161,7 +161,7 @@ class SVX_DLLPUBLIC BulletsTypeMgr final : public NBOTypeMgrBase virtual sal_uInt16 GetNBOIndexForNumRule(SvxNumRule& aNum,sal_uInt16 mLevel,sal_uInt16 nFromIndex=0) override; virtual void ReplaceNumRule(SvxNumRule& aNum, sal_uInt16 nIndex, sal_uInt16 mLevel) override; virtual void ApplyNumRule(SvxNumRule& aNum, sal_uInt16 nIndex, sal_uInt16 mLevel, bool isDefault=false,bool isResetSize=false) override; - void ApplyCustomRule(SvxNumRule& aNum, std::u16string_view sBullet, std::u16string_view sFont, sal_uInt16 mLevel); + void ApplyCustomRule(SvxNumRule& aNum, std::u16string_view sBullet, const OUString& sFont, sal_uInt16 mLevel); virtual OUString GetDescription(sal_uInt16 nIndex, bool isDefault) override; virtual bool IsCustomized(sal_uInt16 nIndex) override; static BulletsTypeMgr& GetInstance(); diff --git a/sc/qa/uitest/calc_tests4/exportToPDF.py b/sc/qa/uitest/calc_tests4/exportToPDF.py index 35e96a044df6..6993702b5734 100644 --- a/sc/qa/uitest/calc_tests4/exportToPDF.py +++ b/sc/qa/uitest/calc_tests4/exportToPDF.py @@ -41,7 +41,7 @@ class exportToPDF(UITestCase): self.assertEqual("true", get_state_as_dict(xDialog.getChild(child))['Selected']) nonSelectedChildren = ['allowdups', 'center', 'comments', 'convert', 'embed', 'emptypages', 'export', 'exportplaceholders', - 'firstonleft', 'forms', 'hiddenpages', 'menubar', 'notes', 'onlynotes', 'open', 'pdfa', 'pdfua', 'resize', 'singlepagesheets', + 'firstonleft', 'forms', 'hiddenpages', 'menubar', 'notes', 'onlynotes', 'open', 'pdfua', 'resize', 'singlepagesheets', 'toolbar', 'usereferencexobject', 'viewpdf', 'watermark', 'window'] for child in nonSelectedChildren: diff --git a/sc/source/filter/excel/xestream.cxx b/sc/source/filter/excel/xestream.cxx index d9e7a6cf57ea..b97720902f15 100644 --- a/sc/source/filter/excel/xestream.cxx +++ b/sc/source/filter/excel/xestream.cxx @@ -955,14 +955,14 @@ sax_fastparser::FSHelperPtr XclExpXmlStream::CreateOutputStream ( std::u16string_view sRelativeStream, const uno::Reference< XOutputStream >& xParentRelation, const char* sContentType, - std::u16string_view sRelationshipType, + const OUString& sRelationshipType, OUString* pRelationshipId ) { OUString sRelationshipId; if (xParentRelation.is()) - sRelationshipId = addRelation( xParentRelation, OUString(sRelationshipType), sRelativeStream ); + sRelationshipId = addRelation( xParentRelation, sRelationshipType, sRelativeStream ); else - sRelationshipId = addRelation( OUString(sRelationshipType), sRelativeStream ); + sRelationshipId = addRelation( sRelationshipType, sRelativeStream ); if( pRelationshipId ) *pRelationshipId = sRelationshipId; diff --git a/sc/source/filter/inc/xestream.hxx b/sc/source/filter/inc/xestream.hxx index 202e70a0e65d..d0318848ecba 100644 --- a/sc/source/filter/inc/xestream.hxx +++ b/sc/source/filter/inc/xestream.hxx @@ -312,7 +312,7 @@ public: std::u16string_view sRelativeStream, const css::uno::Reference< css::io::XOutputStream >& xParentRelation, const char* sContentType, - std::u16string_view sRelationshipType, + const OUString& sRelationshipType, OUString* pRelationshipId = nullptr ); // ignore diff --git a/sd/qa/uitest/impress_tests/exportToPDF.py b/sd/qa/uitest/impress_tests/exportToPDF.py index b9cdc9934faf..4a1f1800f649 100644 --- a/sd/qa/uitest/impress_tests/exportToPDF.py +++ b/sd/qa/uitest/impress_tests/exportToPDF.py @@ -43,7 +43,7 @@ class exportToPDF(UITestCase): self.assertEqual("true", get_state_as_dict(xDialog.getChild(child))['Selected']) nonSelectedChildren = ['allowdups', 'center', 'comments', 'convert', 'embed', 'emptypages', 'export', 'exportplaceholders', - 'firstonleft', 'forms', 'hiddenpages', 'menubar', 'notes', 'onlynotes', 'open', 'pdfa', 'pdfua', 'resize', 'singlepagesheets', + 'firstonleft', 'forms', 'hiddenpages', 'menubar', 'notes', 'onlynotes', 'open', 'pdfua', 'resize', 'singlepagesheets', 'toolbar', 'usereferencexobject', 'viewpdf', 'watermark', 'window'] for child in nonSelectedChildren: diff --git a/svx/source/sidebar/nbdtmg.cxx b/svx/source/sidebar/nbdtmg.cxx index a2eb811c4ffd..c3aa9bce4324 100644 --- a/svx/source/sidebar/nbdtmg.cxx +++ b/svx/source/sidebar/nbdtmg.cxx @@ -349,11 +349,11 @@ void BulletsTypeMgr::ApplyNumRule(SvxNumRule& aNum, sal_uInt16 nIndex, sal_uInt1 } void BulletsTypeMgr::ApplyCustomRule(SvxNumRule& aNum, std::u16string_view sBullet, - std::u16string_view sFont, sal_uInt16 mLevel) + const OUString& sFont, sal_uInt16 mLevel) { sal_uInt16 nMask = 1; OUString sBulletCharFormatName = GetBulletCharFmtName(); - const vcl::Font aFont(OUString(sFont), Size(1, 1)); + const vcl::Font aFont(sFont, Size(1, 1)); for (sal_uInt16 i = 0; i < aNum.GetLevelCount(); i++) { if (mLevel & nMask) diff --git a/sw/qa/uitest/writer_tests4/exportToPDF.py b/sw/qa/uitest/writer_tests4/exportToPDF.py index 76e2e0420700..84105bd1e750 100644 --- a/sw/qa/uitest/writer_tests4/exportToPDF.py +++ b/sw/qa/uitest/writer_tests4/exportToPDF.py @@ -39,7 +39,7 @@ class exportToPDF(UITestCase): self.assertEqual("true", get_state_as_dict(xDialog.getChild(child))['Selected']) nonSelectedChildren = ['allowdups', 'center', 'comments', 'convert', 'embed', 'emptypages', 'export', 'exportplaceholders', - 'firstonleft', 'forms', 'hiddenpages', 'menubar', 'notes', 'onlynotes', 'open', 'pdfa', 'pdfua', 'resize', 'singlepagesheets', + 'firstonleft', 'forms', 'hiddenpages', 'menubar', 'notes', 'onlynotes', 'open', 'pdfua', 'resize', 'singlepagesheets', 'toolbar', 'usereferencexobject', 'viewpdf', 'watermark', 'window'] for child in nonSelectedChildren: diff --git a/unotools/source/i18n/resmgr.cxx b/unotools/source/i18n/resmgr.cxx index 6d66728f415f..f93e943b628a 100644 --- a/unotools/source/i18n/resmgr.cxx +++ b/unotools/source/i18n/resmgr.cxx @@ -200,10 +200,12 @@ namespace Translate assert(!strchr(sContextAndId.getId(), '\004') && "should be using nget, not get"); //if it's a key id locale, generate it here - if (std::use_facet<boost::locale::info>(loc).language() == "qtz") - { - OString sKeyId(genKeyId(OString::Concat(sContextAndId.mpContext) + "|" + std::string_view(sContextAndId.getId()))); - return OUString::fromUtf8(sKeyId) + u"\u2016" + OUString::fromUtf8(sContextAndId.getId()); + if (std::has_facet<boost::locale::info>(loc)) { + if (std::use_facet<boost::locale::info>(loc).language() == "qtz") + { + OString sKeyId(genKeyId(OString::Concat(sContextAndId.mpContext) + "|" + std::string_view(sContextAndId.getId()))); + return OUString::fromUtf8(sKeyId) + u"\u2016" + OUString::fromUtf8(sContextAndId.getId()); + } } //otherwise translate it diff --git a/vcl/inc/osx/salframe.h b/vcl/inc/osx/salframe.h index fa2a5bcb3cbb..ee7afe053cab 100644 --- a/vcl/inc/osx/salframe.h +++ b/vcl/inc/osx/salframe.h @@ -96,7 +96,9 @@ public: int mnBlinkCursorDelay; // tdf#155266 force flush after scrolling - bool mbForceFlush; + bool mbForceFlushScrolling; + // tdf#164428 force flush after drawing a progress bar + bool mbForceFlushProgressBar; // Is window in LibreOffice full screen mode bool mbInternalFullScreen; @@ -225,6 +227,8 @@ private: // methods void doResetClipRegion(); + bool doFlush(); + private: // data static AquaSalFrame* s_pCaptureFrame; diff --git a/vcl/inc/pdf/COSWriter.hxx b/vcl/inc/pdf/COSWriter.hxx index 2142de1f846e..b80f0f84f424 100644 --- a/vcl/inc/pdf/COSWriter.hxx +++ b/vcl/inc/pdf/COSWriter.hxx @@ -29,20 +29,6 @@ class COSWriter void appendLiteralString(const char* pStr, sal_Int32 nLength); - template <typename T> static void appendHex(T nValue, OStringBuffer& rBuffer) - { - static constexpr const auto constHexDigits = std::to_array<char>( - { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }); - rBuffer.append(constHexDigits[(nValue >> 4) & 15]); - rBuffer.append(constHexDigits[nValue & 15]); - } - - void appendHexArray(sal_uInt8* pArray, size_t nSize) - { - for (size_t i = 0; i < nSize; i++) - appendHex(pArray[i], mrBuffer); - } - public: COSWriter(EncryptionParams aParams = EncryptionParams(), std::shared_ptr<IPDFEncryptor> const& pPDFEncryptor = nullptr) @@ -72,6 +58,11 @@ public: OStringBuffer& getLine() { return mrBuffer; } void startDict() { mrBuffer.append("<<"); } + void startDictWithKey(std::string_view key) + { + mrBuffer.append(key); + mrBuffer.append("<<"); + } void endDict() { mrBuffer.append(">>\n"); } void startStream() { mrBuffer.append("stream\n"); } @@ -129,6 +120,14 @@ public: void writeLiteralEncrypt(std::u16string_view value, sal_Int32 nObject, rtl_TextEncoding nEncoding = RTL_TEXTENCODING_ASCII_US); + void writeKeyAndLiteralEncrypt(std::string_view key, std::u16string_view value, + sal_Int32 nObject, + rtl_TextEncoding nEncoding = RTL_TEXTENCODING_ASCII_US) + { + mrBuffer.append(key); + writeLiteralEncrypt(value, nObject, nEncoding); + } + void writeLiteralEncrypt(std::string_view value, sal_Int32 nObject); void writeKeyAndLiteralEncrypt(std::string_view key, std::string_view value, sal_Int32 nObject) @@ -141,11 +140,27 @@ public: { mrBuffer.append(key); mrBuffer.append("<"); - appendHexArray(pData, nSize); + COSWriter::appendHexArray(pData, nSize, mrBuffer); mrBuffer.append(">"); } + template <typename T> static void appendHex(T nValue, OStringBuffer& rBuffer) + { + static constexpr const auto constHexDigits = std::to_array<char>( + { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }); + rBuffer.append(constHexDigits[(nValue >> 4) & 15]); + rBuffer.append(constHexDigits[nValue & 15]); + } + + static void appendHexArray(sal_uInt8* pArray, size_t nSize, OStringBuffer& rBuffer) + { + for (size_t i = 0; i < nSize; i++) + appendHex(pArray[i], rBuffer); + } + static void appendUnicodeTextString(const OUString& rString, OStringBuffer& rBuffer); + static void appendName(std::u16string_view rString, OStringBuffer& rBuffer); + static void appendName(const char* pString, OStringBuffer& rBuffer); }; } diff --git a/vcl/inc/pdf/pdfwriter_impl.hxx b/vcl/inc/pdf/pdfwriter_impl.hxx index 0a30fb363be6..6781d0f935fd 100644 --- a/vcl/inc/pdf/pdfwriter_impl.hxx +++ b/vcl/inc/pdf/pdfwriter_impl.hxx @@ -866,13 +866,6 @@ private: /* */ void enableStringEncryption( sal_Int32 nObject ); -public: // Temporary for PDFStructureWriter - // test if the encryption is active, if yes than encrypt the unicode string and add to the OStringBuffer parameter - void appendUnicodeTextStringEncrypt( const OUString& rInString, const sal_Int32 nInObjectNumber, OStringBuffer& rOutBuffer ); - - void appendLiteralStringEncrypt( std::u16string_view rInString, const sal_Int32 nInObjectNumber, OStringBuffer& rOutBuffer, rtl_TextEncoding nEnc = RTL_TEXTENCODING_ASCII_US ); - void appendLiteralStringEncrypt( std::string_view rInString, const sal_Int32 nInObjectNumber, OStringBuffer& rOutBuffer ); - private: /* creates fonts and subsets that will be emitted later */ void registerGlyph(const sal_GlyphId, const vcl::font::PhysicalFontFace*, const LogicalFontInstance* pFont, const std::vector<sal_Ucs>&, sal_Int32, sal_uInt8&, sal_Int32&); diff --git a/vcl/inc/qt5/QtInstanceDialog.hxx b/vcl/inc/qt5/QtInstanceDialog.hxx index 82acf2d6c1dd..76d3558369d9 100644 --- a/vcl/inc/qt5/QtInstanceDialog.hxx +++ b/vcl/inc/qt5/QtInstanceDialog.hxx @@ -17,7 +17,7 @@ class QtInstanceDialog : public QtInstanceWindow, public virtual weld::Dialog { Q_OBJECT - std::unique_ptr<QDialog> m_pDialog; + QDialog* m_pDialog; QWidget* m_pContentArea; // the DialogController/Dialog/function passed to the runAsync variants diff --git a/vcl/osx/salframe.cxx b/vcl/osx/salframe.cxx index 98ea5a72c718..4e1266234f1f 100644 --- a/vcl/osx/salframe.cxx +++ b/vcl/osx/salframe.cxx @@ -91,7 +91,8 @@ AquaSalFrame::AquaSalFrame( SalFrame* pParent, SalFrameStyleFlags salFrameStyle mrClippingPath( nullptr ), mnICOptions( InputContextFlags::NONE ), mnBlinkCursorDelay( nMinBlinkCursorDelay ), - mbForceFlush( false ), + mbForceFlushScrolling( false ), + mbForceFlushProgressBar( false ), mbInternalFullScreen( false ), maInternalFullScreenRestoreRect( NSZeroRect ), maInternalFullScreenExpectedRect( NSZeroRect ), @@ -1107,15 +1108,6 @@ void AquaSalFrame::SetPointerPos( tools::Long nX, tools::Long nY ) CGDisplayMoveCursorToPoint( mainDisplayID, aPoint ); } -static bool lcl_ShouldDisplayInsteadOFFlush() -{ - bool bRet = false; -#if HAVE_FEATURE_SKIA - bRet = SkiaHelper::isVCLSkiaEnabled() && SkiaHelper::renderMethodToUse() != SkiaHelper::RenderRaster; -#endif - return bRet; -} - void AquaSalFrame::Flush() { if( !(mbGraphics && mpGraphics && mpNSView && mbShown) ) @@ -1128,36 +1120,8 @@ void AquaSalFrame::Flush() // outside of the application's event loop (e.g. IntroWindow) // nothing would trigger paint event handling // => fall back to synchronous painting - if( mbForceFlush || ImplGetSVData()->maAppData.mnDispatchLevel <= 0 ) - { - mbForceFlush = false; - - // Related: tdf#163945 don't directly flush graphics with Skia/Metal - // When dragging a selection box on an empty background in - // Impress and only with Skia/Metal, the selection box - // would not keep up with the pointer. The selection box - // would repaint sporadically or not at all if the pointer - // was dragged rapidly and the status bar was visible. - // Apparently, flushing a graphics doesn't actually do much - // of anything with Skia/Raster and Skia disabled so the - // selection box repaints without any noticeable delay. - // However, with Skia/Metal every flush of a graphics - // creates and queues a new CAMetalLayer drawable. During - // rapid dragging, this can lead to creating and queueing - // up to 200 drawables per second leaving no spare time for - // the Impress selection box painting timer to fire. - // So with Skia/Metal, throttle the rate of flushing by - // calling display on the view. - bool bDisplay = lcl_ShouldDisplayInsteadOFFlush(); - if (!bDisplay) - mpGraphics->Flush(); - - // Related: tdf#155266 skip redisplay of the view when forcing flush - // It appears that calling -[NSView display] overwhelms some Intel Macs - // so only flush the graphics and skip immediate redisplay of the view. - if( bDisplay || ImplGetSVData()->maAppData.mnDispatchLevel <= 0 ) - [mpNSView display]; - } + if( doFlush() ) + [mpNSView display]; } void AquaSalFrame::Flush( const tools::Rectangle& rRect ) @@ -1174,10 +1138,16 @@ void AquaSalFrame::Flush( const tools::Rectangle& rRect ) // outside of the application's event loop (e.g. IntroWindow) // nothing would trigger paint event handling // => fall back to synchronous painting - if( mbForceFlush || ImplGetSVData()->maAppData.mnDispatchLevel <= 0 ) - { - mbForceFlush = false; + if( doFlush() ) + [mpNSView displayRect: aNSRect]; +} +bool AquaSalFrame::doFlush() +{ + bool bRet = false; + + if( mbForceFlushScrolling || mbForceFlushProgressBar || ImplGetSVData()->maAppData.mnDispatchLevel <= 0 ) + { // Related: tdf#163945 don't directly flush graphics with Skia/Metal // When dragging a selection box on an empty background in // Impress and only with Skia/Metal, the selection box @@ -1194,16 +1164,24 @@ void AquaSalFrame::Flush( const tools::Rectangle& rRect ) // the Impress selection box painting timer to fire. // So with Skia/Metal, throttle the rate of flushing by // calling display on the view. - bool bDisplay = lcl_ShouldDisplayInsteadOFFlush(); + bool bDisplay = false; +#if HAVE_FEATURE_SKIA + // tdf#164428 Skia/Metal needs flush after drawing progress bar + bDisplay = !mbForceFlushProgressBar && SkiaHelper::isVCLSkiaEnabled() && SkiaHelper::renderMethodToUse() != SkiaHelper::RenderRaster; +#endif if (!bDisplay) mpGraphics->Flush(); // Related: tdf#155266 skip redisplay of the view when forcing flush // It appears that calling -[NSView display] overwhelms some Intel Macs // so only flush the graphics and skip immediate redisplay of the view. - if( bDisplay || ImplGetSVData()->maAppData.mnDispatchLevel <= 0 ) - [mpNSView displayRect: aNSRect]; + bRet = bDisplay || ImplGetSVData()->maAppData.mnDispatchLevel <= 0; + + mbForceFlushScrolling = false; + mbForceFlushProgressBar = false; } + + return bRet; } void AquaSalFrame::SetInputContext( SalInputContext* pContext ) diff --git a/vcl/osx/salframeview.mm b/vcl/osx/salframeview.mm index ad868d396d59..a5cb9270600b 100644 --- a/vcl/osx/salframeview.mm +++ b/vcl/osx/salframeview.mm @@ -1094,7 +1094,7 @@ static void updateMenuBarVisibility( const AquaSalFrame *pFrame ) // tdf#155266 force flush after scrolling if (nButton == MOUSE_LEFT && nEvent == SalEvent::MouseMove) - mpFrame->mbForceFlush = true; + mpFrame->mbForceFlushScrolling = true; } } @@ -1337,7 +1337,7 @@ static void updateMenuBarVisibility( const AquaSalFrame *pFrame ) } // tdf#155266 force flush after scrolling - mpFrame->mbForceFlush = true; + mpFrame->mbForceFlushScrolling = true; } } @@ -1417,7 +1417,7 @@ static void updateMenuBarVisibility( const AquaSalFrame *pFrame ) } // tdf#155266 force flush after scrolling - mpFrame->mbForceFlush = true; + mpFrame->mbForceFlushScrolling = true; } } diff --git a/vcl/osx/salnativewidgets.cxx b/vcl/osx/salnativewidgets.cxx index d0ebad835f3d..07f26c51171a 100644 --- a/vcl/osx/salnativewidgets.cxx +++ b/vcl/osx/salnativewidgets.cxx @@ -36,6 +36,10 @@ #include <Carbon/Carbon.h> #include <postmac.h> +#if HAVE_FEATURE_SKIA +#include <vcl/skia/SkiaHelper.hxx> +#endif + #include "cuidraw.hxx" // presentation of native widgets consists of two important methods: @@ -694,6 +698,12 @@ bool AquaGraphicsBackendBase::performDrawNativeControl(ControlType nType, [pBox release]; +#if HAVE_FEATURE_SKIA + // tdf#164428 Skia/Metal needs flush after drawing progress bar + if (SkiaHelper::isVCLSkiaEnabled() && SkiaHelper::renderMethodToUse() != SkiaHelper::RenderRaster) + mpFrame->mbForceFlushProgressBar = true; +#endif + bOK = true; } break; diff --git a/vcl/qa/cppunit/GraphicTest.cxx b/vcl/qa/cppunit/GraphicTest.cxx index 3821c31dcf8e..f6828ea7d8c7 100644 --- a/vcl/qa/cppunit/GraphicTest.cxx +++ b/vcl/qa/cppunit/GraphicTest.cxx @@ -526,7 +526,8 @@ CPPUNIT_TEST_FIXTURE(GraphicTest, testSwappingGraphic_PNG_WithGfxLink) BitmapChecksum aChecksumBeforeSwapping = aGraphic.GetChecksum(); CPPUNIT_ASSERT_EQUAL(true, aGraphic.IsGfxLink()); - CPPUNIT_ASSERT_EQUAL(sal_uInt32(319), aGraphic.GetGfxLink().GetDataSize()); + // Expect the the compressed png is be at least W * H / 2 + CPPUNIT_ASSERT_LESS(sal_uInt32(120 * 100 / 2), aGraphic.GetGfxLink().GetDataSize()); // We loaded the Graphic and made it available CPPUNIT_ASSERT_EQUAL(false, aGraphic.ImplGetImpGraphic()->isSwappedOut()); diff --git a/vcl/qt5/QtInstanceDialog.cxx b/vcl/qt5/QtInstanceDialog.cxx index a975403fbda4..0a622728fb79 100644 --- a/vcl/qt5/QtInstanceDialog.cxx +++ b/vcl/qt5/QtInstanceDialog.cxx @@ -22,12 +22,17 @@ QtInstanceDialog::QtInstanceDialog(QDialog* pDialog) , m_pContentArea(nullptr) , m_aRunAsyncFunc(nullptr) { + assert(m_pDialog); } QtInstanceDialog::~QtInstanceDialog() { SolarMutexGuard g; - GetQtInstance().RunInMainThread([&] { m_pDialog.reset(); }); + + GetQtInstance().RunInMainThread([&] { + m_pDialog->hide(); + m_pDialog->deleteLater(); + }); } bool QtInstanceDialog::runAsync(const std::shared_ptr<weld::DialogController>& rxOwner, @@ -46,7 +51,7 @@ bool QtInstanceDialog::runAsync(const std::shared_ptr<weld::DialogController>& r m_xRunAsyncDialogController = rxOwner; m_aRunAsyncFunc = func; - connect(m_pDialog.get(), &QDialog::finished, this, &QtInstanceDialog::dialogFinished); + connect(m_pDialog, &QDialog::finished, this, &QtInstanceDialog::dialogFinished); m_pDialog->open(); return true; @@ -69,7 +74,7 @@ bool QtInstanceDialog::runAsync(std::shared_ptr<Dialog> const& rxSelf, m_xRunAsyncDialog = rxSelf; m_aRunAsyncFunc = func; - connect(m_pDialog.get(), &QDialog::finished, this, &QtInstanceDialog::dialogFinished); + connect(m_pDialog, &QDialog::finished, this, &QtInstanceDialog::dialogFinished); m_pDialog->open(); return true; @@ -182,7 +187,7 @@ void QtInstanceDialog::dialogFinished(int nResult) return; } - disconnect(m_pDialog.get(), &QDialog::finished, this, &QtInstanceDialog::dialogFinished); + disconnect(m_pDialog, &QDialog::finished, this, &QtInstanceDialog::dialogFinished); // use local variables for these, as members might have got de-allocated by the time they're reset std::shared_ptr<weld::Dialog> xRunAsyncDialog = m_xRunAsyncDialog; diff --git a/vcl/source/gdi/pdfwriter_impl.cxx b/vcl/source/gdi/pdfwriter_impl.cxx index ec3d5ca549b0..84e40b463fe9 100644 --- a/vcl/source/gdi/pdfwriter_impl.cxx +++ b/vcl/source/gdi/pdfwriter_impl.cxx @@ -136,108 +136,6 @@ void appendObjectReference(sal_Int32 nObjectID, OStringBuffer & aLine) aLine.append(" 0 R "); } -void appendHex(sal_Int8 nInt, OStringBuffer& rBuffer) -{ - static const char pHexDigits[] = { '0', '1', '2', '3', '4', '5', '6', '7', - '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; - rBuffer.append( pHexDigits[ (nInt >> 4) & 15 ] ); - rBuffer.append( pHexDigits[ nInt & 15 ] ); -} - -void appendHexArray(sal_uInt8* pArray, size_t nSize, OStringBuffer& rBuffer) -{ - for (size_t i = 0; i < nSize; i++) - appendHex(pArray[i], rBuffer); -} - -void appendName( std::u16string_view rStr, OStringBuffer& rBuffer ) -{ -// FIXME i59651 add a check for max length of 127 chars? Per PDF spec 1.4, appendix C.1 -// I guess than when reading the #xx sequence it will count for a single character. - OString aStr( OUStringToOString( rStr, RTL_TEXTENCODING_UTF8 ) ); - int nLen = aStr.getLength(); - for( int i = 0; i < nLen; i++ ) - { - /* #i16920# PDF recommendation: output UTF8, any byte - * outside the interval [33(=ASCII'!');126(=ASCII'~')] - * should be escaped hexadecimal - * for the sake of ghostscript which also reads PDF - * but has a narrower acceptance rate we only pass - * alphanumerics and '-' literally. - */ - if( (aStr[i] >= 'A' && aStr[i] <= 'Z' ) || - (aStr[i] >= 'a' && aStr[i] <= 'z' ) || - (aStr[i] >= '0' && aStr[i] <= '9' ) || - aStr[i] == '-' ) - { - rBuffer.append( aStr[i] ); - } - else - { - rBuffer.append( '#' ); - appendHex( static_cast<sal_Int8>(aStr[i]), rBuffer ); - } - } -} - -void appendName( const char* pStr, OStringBuffer& rBuffer ) -{ - // FIXME i59651 see above - while( pStr && *pStr ) - { - if( (*pStr >= 'A' && *pStr <= 'Z' ) || - (*pStr >= 'a' && *pStr <= 'z' ) || - (*pStr >= '0' && *pStr <= '9' ) || - *pStr == '-' ) - { - rBuffer.append( *pStr ); - } - else - { - rBuffer.append( '#' ); - appendHex( static_cast<sal_Int8>(*pStr), rBuffer ); - } - pStr++; - } -} - -//used only to emit encoded passwords -void appendLiteralString( const char* pStr, sal_Int32 nLength, OStringBuffer& rBuffer ) -{ - while( nLength ) - { - switch( *pStr ) - { - case '\n' : - rBuffer.append( "\\n" ); - break; - case '\r' : - rBuffer.append( "\\r" ); - break; - case '\t' : - rBuffer.append( "\\t" ); - break; - case '\b' : - rBuffer.append( "\\b" ); - break; - case '\f' : - rBuffer.append( "\\f" ); - break; - case '(' : - case ')' : - case '\\' : - rBuffer.append( "\\" ); - rBuffer.append( static_cast<char>(*pStr) ); - break; - default: - rBuffer.append( static_cast<char>(*pStr) ); - break; - } - pStr++; - nLength--; - } -} - /* * Convert a string before using it. * @@ -279,8 +177,8 @@ void appendDestinationName( const OUString& rString, OStringBuffer& rBuffer ) { sal_Int8 aValueHigh = sal_Int8(aChar >> 8); if(aValueHigh > 0) - appendHex( aValueHigh, rBuffer ); - appendHex( static_cast<sal_Int8>(aChar & 255 ), rBuffer ); + vcl::COSWriter::appendHex(aValueHigh, rBuffer); + vcl::COSWriter::appendHex(static_cast<sal_Int8>(aChar & 255 ), rBuffer); } } } @@ -333,7 +231,7 @@ void PDFWriterImpl::createWidgetFieldName( sal_Int32 i_nWidgetIndex, const PDFWr else { aBuffer.append( '#' ); - appendHex( static_cast<sal_Int8>(aStr[i]), aBuffer ); + COSWriter::appendHex(static_cast<sal_Int8>(aStr[i]), aBuffer); } } @@ -1510,86 +1408,6 @@ OString PDFWriter::GetDateTime(svl::crypto::SigningContext* pSigningContext) return aRet.makeStringAndClear(); } - -/* i12626 methods */ -/* -check if the Unicode string must be encrypted or not, perform the requested task, -append the string as unicode hex, encrypted if needed - */ -inline void PDFWriterImpl::appendUnicodeTextStringEncrypt( const OUString& rInString, const sal_Int32 nInObjectNumber, OStringBuffer& rOutBuffer ) -{ - rOutBuffer.append( "<" ); - if (m_aContext.Encryption.canEncrypt()) - { - const sal_Unicode* pStr = rInString.getStr(); - sal_Int32 nLen = rInString.getLength(); - //prepare a unicode string, encrypt it - enableStringEncryption( nInObjectNumber ); - sal_Int32 nChars = 2 + (nLen * 2); - m_vEncryptionBuffer.resize(nChars); - sal_uInt8 *pCopy = m_vEncryptionBuffer.data(); - *pCopy++ = 0xFE; - *pCopy++ = 0xFF; - // we need to prepare a byte stream from the unicode string buffer - for( int i = 0; i < nLen; i++ ) - { - sal_Unicode aUnChar = pStr[i]; - *pCopy++ = static_cast<sal_uInt8>( aUnChar >> 8 ); - *pCopy++ = static_cast<sal_uInt8>( aUnChar & 255 ); - } - //encrypt in place - std::vector<sal_uInt8> aNewBuffer(nChars); - m_pPDFEncryptor->encrypt(m_vEncryptionBuffer.data(), nChars, aNewBuffer, nChars); - //now append, hexadecimal (appendHex), the encrypted result - appendHexArray(aNewBuffer.data(), aNewBuffer.size(), rOutBuffer); - } - else - COSWriter::appendUnicodeTextString(rInString, rOutBuffer); - rOutBuffer.append( ">" ); -} - -inline void PDFWriterImpl::appendLiteralStringEncrypt( std::string_view rInString, const sal_Int32 nInObjectNumber, OStringBuffer& rOutBuffer ) -{ - rOutBuffer.append( "(" ); - sal_Int32 nChars = rInString.size(); - //check for encryption, if ok, encrypt the string, then convert with appndLiteralString - if (m_aContext.Encryption.canEncrypt()) - { - m_vEncryptionBuffer.resize(nChars); - //encrypt the string in a buffer, then append it - enableStringEncryption(nInObjectNumber); - m_pPDFEncryptor->encrypt(rInString.data(), nChars, m_vEncryptionBuffer, nChars); - appendLiteralString(reinterpret_cast<char*>(m_vEncryptionBuffer.data()), m_vEncryptionBuffer.size(), rOutBuffer); - } - else - appendLiteralString( rInString.data(), nChars , rOutBuffer ); - rOutBuffer.append( ")" ); -} - -void PDFWriterImpl::appendLiteralStringEncrypt( std::u16string_view rInString, const sal_Int32 nInObjectNumber, OStringBuffer& rOutBuffer, rtl_TextEncoding nEnc ) -{ - OString aBufferString( OUStringToOString( rInString, nEnc ) ); - sal_Int32 nLen = aBufferString.getLength(); - OStringBuffer aBuf( nLen ); - const char* pT = aBufferString.getStr(); - - for( sal_Int32 i = 0; i < nLen; i++, pT++ ) - { - if( (*pT & 0x80) == 0 ) - aBuf.append( *pT ); - else - { - aBuf.append( '<' ); - appendHex( *pT, aBuf ); - aBuf.append( '>' ); - } - } - aBufferString = aBuf.makeStringAndClear(); - appendLiteralStringEncrypt( aBufferString, nInObjectNumber, rOutBuffer); -} - -/* end i12626 methods */ - void PDFWriterImpl::emitComment( const char* pComment ) { OString aLine = OString::Concat("% ") + pComment + "\n"; @@ -2206,13 +2024,13 @@ sal_Int32 PDFWriterImpl::emitStructure( PDFStructureElement& rEle ) if( !rEle.m_aActualText.isEmpty() ) { aLine.append( "/ActualText" ); - appendUnicodeTextStringEncrypt( rEle.m_aActualText, rEle.m_nObject, aLine ); + aWriter.writeUnicodeEncrypt(rEle.m_aActualText, rEle.m_nObject); aLine.append( "\n" ); } if( !rEle.m_aAltText.isEmpty() ) { aLine.append( "/Alt" ); - appendUnicodeTextStringEncrypt( rEle.m_aAltText, rEle.m_nObject, aLine ); + aWriter.writeUnicodeEncrypt(rEle.m_aAltText, rEle.m_nObject); aLine.append( "\n" ); } } @@ -2437,7 +2255,7 @@ sal_Int32 PDFWriterImpl::emitBuildinFont(const pdf::BuildinFontFace* pFD, sal_In OString::number(nFontObject) + " 0 obj\n" "<</Type/Font/Subtype/Type1/BaseFont/" ); - appendName( rBuildinFont.m_pPSName, aLine ); + COSWriter::appendName( rBuildinFont.m_pPSName, aLine ); aLine.append( "\n" ); if( rBuildinFont.m_eCharSet == RTL_TEXTENCODING_MS_1252 ) aLine.append( "/Encoding/WinAnsiEncoding\n" ); @@ -2497,7 +2315,7 @@ std::map< sal_Int32, sal_Int32 > PDFWriterImpl::emitSystemFont( const vcl::font: + " 0 obj\n" "<</Type/Font/Subtype/TrueType" "/BaseFont/" ); - appendName( aInfo.m_aPSName, aLine ); + COSWriter::appendName( aInfo.m_aPSName, aLine ); aLine.append( "\n" ); if (!pFace->IsMicrosoftSymbolEncoded()) aLine.append( "/Encoding/WinAnsiEncoding\n" ); @@ -2610,7 +2428,7 @@ bool PDFWriterImpl::emitType3Font(const vcl::font::PhysicalFontFace* pFace, OString::number(nFontObject) + " 0 obj\n" "<</Type/Font/Subtype/Type3/Name/"); - appendName(aSubsetInfo.m_aPSName, aLine); + COSWriter::appendName(aSubsetInfo.m_aPSName, aLine); aLine.append( "\n/FontBBox[" @@ -2723,7 +2541,7 @@ bool PDFWriterImpl::emitType3Font(const vcl::font::PhysicalFontFace* pFace, auto nAlpha = aColor.GetAlpha(); OStringBuffer aName(16); aName.append("GS"); - appendHex(nAlpha, aName); + COSWriter::appendHex(nAlpha, aName); aContents.append("/" + aName + " gs "); @@ -2743,7 +2561,7 @@ bool PDFWriterImpl::emitType3Font(const vcl::font::PhysicalFontFace* pFace, aContents.append( " Tf " "<"); - appendHex(rLayer.m_nSubsetGlyphID, aContents); + COSWriter::appendHex(rLayer.m_nSubsetGlyphID, aContents); aContents.append( ">Tj " "ET " @@ -2926,7 +2744,7 @@ static void appendSubsetName( int nSubsetID, std::u16string_view rPSName, OStrin } rBuffer.append( '+' ); } - appendName( rPSName, rBuffer ); + COSWriter::appendName( rPSName, rBuffer ); } sal_Int32 PDFWriterImpl::createToUnicodeCMap( sal_uInt8 const * pEncoding, @@ -2975,14 +2793,14 @@ sal_Int32 PDFWriterImpl::createToUnicodeCMap( sal_uInt8 const * pEncoding, + " beginbfchar\n" ); } aContents.append( '<' ); - appendHex( static_cast<sal_Int8>(pEncoding[n]), aContents ); + COSWriter::appendHex(static_cast<sal_Int8>(pEncoding[n]), aContents); aContents.append( "> <" ); // TODO: handle code points>U+FFFF sal_Int32 nIndex = pEncToUnicodeIndex[n]; for( sal_Int32 j = 0; j < pCodeUnitsPerGlyph[n]; j++ ) { - appendHex( static_cast<sal_Int8>(rCodeUnits[nIndex + j] / 256), aContents ); - appendHex( static_cast<sal_Int8>(rCodeUnits[nIndex + j] & 255), aContents ); + COSWriter::appendHex(static_cast<sal_Int8>(rCodeUnits[nIndex + j] / 256), aContents); + COSWriter::appendHex(static_cast<sal_Int8>(rCodeUnits[nIndex + j] & 255), aContents); } aContents.append( ">\n" ); nCount++; @@ -3462,6 +3280,7 @@ sal_Int32 PDFWriterImpl::emitOutline() { PDFOutlineEntry& rItem = m_aOutline[i]; OStringBuffer aLine( 1024 ); + COSWriter aWriter(aLine, m_aContext.Encryption.getParams(), m_pPDFEncryptor); if (!updateObject(rItem.m_nObject)) return 0; @@ -3486,7 +3305,7 @@ sal_Int32 PDFWriterImpl::emitOutline() { // Title, Dest, Parent, Prev, Next aLine.append( "/Title" ); - appendUnicodeTextStringEncrypt( rItem.m_aTitle, rItem.m_nObject, aLine ); + aWriter.writeUnicodeEncrypt(rItem.m_aTitle, rItem.m_nObject); aLine.append( "\n" ); // Dest is not required if( rItem.m_nDestID >= 0 && o3tl::make_unsigned(rItem.m_nDestID) < m_aDests.size() ) @@ -3561,6 +3380,9 @@ bool PDFWriterImpl::appendDest( sal_Int32 nDestID, OStringBuffer& rBuffer ) void PDFWriterImpl::addDocumentAttachedFile(OUString const& rFileName, OUString const& rMimeType, OUString const& rDescription, std::unique_ptr<PDFOutputStream> rStream) { + if (m_nPDFA_Version == 1 || m_nPDFA_Version == 2) + return; + sal_Int32 nObjectID = addEmbeddedFile(std::move(rStream), rMimeType); auto& rAttachedFile = m_aDocumentAttachedFiles.emplace_back(); rAttachedFile.maFilename = rFileName; @@ -3673,14 +3495,14 @@ bool PDFWriterImpl::emitScreenAnnotations() if (PDFWriter::PDFVersion::PDF_1_7 <= m_aContext.Version) { // ISO 14289-1:2014, Clause: 7.11 aLine.append("/UF "); - appendUnicodeTextStringEncrypt(rScreen.m_aURL, rScreen.m_nObject, aLine); + aWriter.writeUnicodeEncrypt(rScreen.m_aURL, rScreen.m_nObject); } } if (PDFWriter::PDFVersion::PDF_1_6 <= m_aContext.Version && !rScreen.m_AltText.isEmpty()) { // ISO 14289-1:2014, Clause: 7.11 aLine.append("/Desc "); - appendUnicodeTextStringEncrypt(rScreen.m_AltText, rScreen.m_nObject, aLine); + aWriter.writeUnicodeEncrypt(rScreen.m_AltText, rScreen.m_nObject); } aLine.append(" >>\n"); // end of /D // Allow playing the video via a tempfile. @@ -3691,7 +3513,7 @@ bool PDFWriterImpl::emitScreenAnnotations() // ISO 14289-1:2014, Clause: 7.18.6.2 // Alt text is a "Multi-language Text Array" aLine.append(" /Alt [ () "); - appendUnicodeTextStringEncrypt(rScreen.m_AltText, rScreen.m_nObject, aLine); + aWriter.writeUnicodeEncrypt(rScreen.m_AltText, rScreen.m_nObject); aLine.append(" ] " ">>"); @@ -3751,7 +3573,7 @@ bool PDFWriterImpl::emitLinkAnnotations() aLine.append( "]" ); // ISO 14289-1:2014, Clause: 7.18.5 aLine.append("/Contents"); - appendUnicodeTextStringEncrypt(rLink.m_AltText, rLink.m_nObject, aLine); + aWriter.writeUnicodeEncrypt(rLink.m_AltText, rLink.m_nObject); if( rLink.m_nDest >= 0 ) { aLine.append( "/Dest" ); @@ -3856,10 +3678,21 @@ we check in the following sequence: aLine.append( "/A<</Type/Action/S"); if( bIsUNCPath ) // handle Win UNC paths { - aLine.append( "/Launch/Win<</F" ); - // INetURLObject is not good with UNC paths, use original path - aWriter.writeLiteralEncrypt(url, rLink.m_nObject, osl_getThreadTextEncoding()); - aLine.append( ">>" ); + aLine.append("/Launch"); + // Entry /Win is deprecated in PDF 2.0 + if (m_aContext.Version >= PDFWriter::PDFVersion::PDF_2_0) + { + // So write /F directly. AFAICS it's up to PDF viewer to resolve this correctly + aWriter.writeKeyAndLiteralEncrypt("/F", url, rLink.m_nObject, osl_getThreadTextEncoding()); + } + else + { + aLine.append("/Win"); + aWriter.startDict(); + // INetURLObject is not good with UNC paths, use original path + aWriter.writeKeyAndLiteralEncrypt("/F", url, rLink.m_nObject, osl_getThreadTextEncoding()); + aWriter.endDict(); + } } else { @@ -4015,6 +3848,8 @@ void appendAnnotationBorder(float fBorderWidth, OStringBuffer & aLine) void PDFWriterImpl::emitTextAnnotationLine(OStringBuffer & aLine, PDFNoteEntry const & rNote) { + COSWriter aWriter(aLine, m_aContext.Encryption.getParams(), m_pPDFEncryptor); + appendObjectID(rNote.m_nObject, aLine); double fPageHeight = m_aPages[rNote.m_nPage].getHeight(); @@ -4097,14 +3932,14 @@ void PDFWriterImpl::emitTextAnnotationLine(OStringBuffer & aLine, PDFNoteEntry c // contents of the note (type text string) aLine.append("/Contents "); - appendUnicodeTextStringEncrypt(rNote.m_aContents.maContents, rNote.m_nObject, aLine); + aWriter.writeUnicodeEncrypt(rNote.m_aContents.maContents, rNote.m_nObject); aLine.append("\n"); // optional title if (!rNote.m_aContents.maTitle.isEmpty()) { aLine.append("/T "); - appendUnicodeTextStringEncrypt(rNote.m_aContents.maTitle, rNote.m_nObject, aLine); + aWriter.writeUnicodeEncrypt(rNote.m_aContents.maTitle, rNote.m_nObject); aLine.append("\n"); } @@ -4558,7 +4393,7 @@ void PDFWriterImpl::createDefaultCheckBoxAppearance( PDFWidget& rBox, const PDFW aDA.append( " " ); m_aPages[ m_nCurrentPage ].appendMappedLength( nCharYOffset, aDA ); aDA.append( " Td <" ); - appendHex( nMappedGlyph, aDA ); + COSWriter::appendHex( nMappedGlyph, aDA ); aDA.append( "> Tj\nET\nQ\nEMC\n" ); writeBuffer( aDA ); endRedirect(); @@ -4794,7 +4629,7 @@ bool PDFWriterImpl::emitWidgetAnnotations() SvMemoryStream* pStream = stream_it->second; app_it->second.erase( stream_it ); OStringBuffer aBuf( rWidget.m_aOnValue.getLength()*2 ); - appendName( rWidget.m_aOnValue, aBuf ); + COSWriter::appendName( rWidget.m_aOnValue, aBuf ); (app_it->second)[ aBuf.makeStringAndClear() ] = pStream; } else @@ -4813,7 +4648,7 @@ bool PDFWriterImpl::emitWidgetAnnotations() SvMemoryStream* pStream = stream_it->second; app_it->second.erase( stream_it ); OStringBuffer aBuf( rWidget.m_aOffValue.getLength()*2 ); - appendName( rWidget.m_aOffValue, aBuf ); + COSWriter::appendName( rWidget.m_aOffValue, aBuf ); (app_it->second)[ aBuf.makeStringAndClear() ] = pStream; } else @@ -4825,6 +4660,7 @@ bool PDFWriterImpl::emitWidgetAnnotations() OStringBuffer aLine( 1024 ); COSWriter aWriter(aLine, m_aContext.Encryption.getParams(), m_pPDFEncryptor); OStringBuffer aValue( 256 ); + COSWriter aValueWriter(aValue, m_aContext.Encryption.getParams(), m_pPDFEncryptor); aLine.append( rWidget.m_nObject ); aLine.append( " 0 obj\n" "<<" ); @@ -4882,7 +4718,7 @@ bool PDFWriterImpl::emitWidgetAnnotations() if( rWidget.m_aValue.isEmpty() ) aValue.append( "Off" ); else - appendName( rWidget.m_aValue, aValue ); + COSWriter::appendName( rWidget.m_aValue, aValue ); } [[fallthrough]]; case PDFWriter::PushButton: @@ -4897,7 +4733,9 @@ bool PDFWriterImpl::emitWidgetAnnotations() sal_Int32 nEntry = rWidget.m_aSelectedEntries[i]; if( nEntry >= 0 && o3tl::make_unsigned(nEntry) < rWidget.m_aListEntries.size() ) - appendUnicodeTextStringEncrypt( rWidget.m_aListEntries[ nEntry ], rWidget.m_nObject, aValue ); + { + aValueWriter.writeUnicodeEncrypt(rWidget.m_aListEntries[ nEntry ], rWidget.m_nObject); + } } aValue.append( "]" ); } @@ -4905,19 +4743,19 @@ bool PDFWriterImpl::emitWidgetAnnotations() rWidget.m_aSelectedEntries[0] >= 0 && o3tl::make_unsigned(rWidget.m_aSelectedEntries[0]) < rWidget.m_aListEntries.size() ) { - appendUnicodeTextStringEncrypt( rWidget.m_aListEntries[ rWidget.m_aSelectedEntries[0] ], rWidget.m_nObject, aValue ); + aValueWriter.writeUnicodeEncrypt(rWidget.m_aListEntries[ rWidget.m_aSelectedEntries[0] ], rWidget.m_nObject); } else - appendUnicodeTextStringEncrypt( OUString(), rWidget.m_nObject, aValue ); + aValueWriter.writeUnicodeEncrypt( OUString(), rWidget.m_nObject); aLine.append( "Ch" ); break; case PDFWriter::ComboBox: - appendUnicodeTextStringEncrypt( rWidget.m_aValue, rWidget.m_nObject, aValue ); + aValueWriter.writeUnicodeEncrypt( rWidget.m_aValue, rWidget.m_nObject); aLine.append( "Ch" ); break; case PDFWriter::Edit: aLine.append( "Tx" ); - appendUnicodeTextStringEncrypt( rWidget.m_aValue, rWidget.m_nObject, aValue ); + aValueWriter.writeUnicodeEncrypt( rWidget.m_aValue, rWidget.m_nObject); break; case PDFWriter::Signature: aLine.append( "Sig" ); @@ -5226,33 +5064,35 @@ bool PDFWriterImpl::emitEmbeddedFiles() if (!rEmbeddedFile.m_aSubType.isEmpty()) { aLine.append("/Subtype /"); - appendName(rEmbeddedFile.m_aSubType, aLine); + COSWriter::appendName(rEmbeddedFile.m_aSubType, aLine); } aLine.append(" /Length "); appendObjectReference(nSizeObject, aLine); aLine.append(" /Params "); appendObjectReference(nParamsObject, aLine); aLine.append(">>\nstream\n"); - checkAndEnableStreamEncryption(rEmbeddedFile.m_nObject); if (!writeBuffer(aLine)) return false; - disableStreamEncryption(); aLine.setLength(0); sal_Int64 nSize{}; if (!rEmbeddedFile.m_aDataContainer.isEmpty()) { nSize = rEmbeddedFile.m_aDataContainer.getSize(); + checkAndEnableStreamEncryption(rEmbeddedFile.m_nObject); if (!writeBufferBytes(rEmbeddedFile.m_aDataContainer.getData(), rEmbeddedFile.m_aDataContainer.getSize())) return false; + disableStreamEncryption(); } else if (rEmbeddedFile.m_pStream) { + checkAndEnableStreamEncryption(rEmbeddedFile.m_nObject); sal_uInt64 nBegin = getCurrentFilePosition(); css::uno::Reference<css::io::XOutputStream> xStream(new PDFStreamIf(this)); rEmbeddedFile.m_pStream->write(xStream); rEmbeddedFile.m_pStream.reset(); xStream.clear(); nSize = sal_Int64(getCurrentFilePosition() - nBegin); + disableStreamEncryption(); } aLine.append("\nendstream\nendobj\n\n"); if (!writeBuffer(aLine)) return false; @@ -5361,29 +5201,26 @@ bool PDFWriterImpl::emitCatalog() { if (!updateObject(rAttachedFile.mnObjectId)) return false; - aLine.setLength( 0 ); + aLine.setLength(0); - appendObjectID(rAttachedFile.mnObjectId, aLine); - aLine.append("<</Type /Filespec"); - aLine.append("/F<"); - COSWriter::appendUnicodeTextString(rAttachedFile.maFilename, aLine); - aLine.append("> "); + aWriter.startObject(rAttachedFile.mnObjectId); + aWriter.startDict(); + aWriter.write("/Type", "/Filespec"); + aWriter.writeKeyAndUnicodeEncrypt("/F", rAttachedFile.maFilename, rAttachedFile.mnObjectId); if (PDFWriter::PDFVersion::PDF_1_7 <= m_aContext.Version) { - aLine.append("/UF<"); - COSWriter::appendUnicodeTextString(rAttachedFile.maFilename, aLine); - aLine.append("> "); + aWriter.writeKeyAndUnicodeEncrypt("/UF", rAttachedFile.maFilename, rAttachedFile.mnObjectId); } if (!rAttachedFile.maDescription.isEmpty()) { - aLine.append("/Desc <"); - COSWriter::appendUnicodeTextString(rAttachedFile.maDescription, aLine); - aLine.append("> "); + aWriter.writeKeyAndUnicodeEncrypt("/Desc", rAttachedFile.maDescription, rAttachedFile.mnObjectId); } - aLine.append("/EF <</F "); - appendObjectReference(rAttachedFile.mnEmbeddedFileObjectId, aLine); - aLine.append(">>"); - aLine.append(">>\nendobj\n\n"); + aLine.append("/EF"); + aWriter.startDict(); + aWriter.writeKeyAndReference("/F", rAttachedFile.mnEmbeddedFileObjectId); + aWriter.endDict(); + aWriter.endDict(); + aWriter.endObject(); if (!writeBuffer(aLine)) return false; } @@ -5408,18 +5245,17 @@ bool PDFWriterImpl::emitCatalog() if (!m_aDocumentAttachedFiles.empty()) { - aLine.append("/Names "); - aLine.append("<</EmbeddedFiles <</Names ["); + aWriter.startDictWithKey("/Names"); + aWriter.startDictWithKey("/EmbeddedFiles"); + aLine.append("/Names ["); for (auto & rAttachedFile : m_aDocumentAttachedFiles) { - aLine.append('<'); - COSWriter::appendUnicodeTextString(rAttachedFile.maFilename, aLine); - aLine.append('>'); - aLine.append(' '); - appendObjectReference(rAttachedFile.mnObjectId, aLine); + aWriter.writeUnicodeEncrypt(rAttachedFile.maFilename, m_nCatalogObject); + aWriter.writeReference(rAttachedFile.mnObjectId); } - aLine.append("]>>>>"); - aLine.append("\n" ); + aLine.append("]"); + aWriter.endDict(); + aWriter.endDict(); } if( m_aContext.PageLayout != PDFWriter::DefaultLayout ) @@ -6194,7 +6030,7 @@ bool PDFWriterImpl::emitTrailer() OStringBuffer aDocChecksum( 2*RTL_DIGEST_LENGTH_MD5+1 ); ::std::vector<unsigned char> const nMD5Sum(m_DocDigest.finalize()); for (sal_uInt8 i : nMD5Sum) - appendHex( i, aDocChecksum ); + COSWriter::appendHex( i, aDocChecksum ); // document id set in setDocInfo method // emit trailer aLine.setLength( 0 ); @@ -6221,31 +6057,38 @@ bool PDFWriterImpl::emitTrailer() aLine.append( "/ID [ <" ); for (auto const& item : m_aContext.Encryption.DocumentIdentifier) { - appendHex( sal_Int8(item), aLine ); + COSWriter::appendHex( sal_Int8(item), aLine ); } aLine.append( ">\n" "<" ); for (auto const& item : m_aContext.Encryption.DocumentIdentifier) { - appendHex( sal_Int8(item), aLine ); + COSWriter::appendHex( sal_Int8(item), aLine ); } aLine.append( "> ]\n" ); } - if( !aDocChecksum.isEmpty() ) + // Writes the /DocChecksum - hash off the PDF stream + // This entry is not defined in the standard, so don't write it if we + // are using PDF/UA or PDF/A as the compliance checkers will complain. + // Actually we shouldn't write it at all... + if (!aDocChecksum.isEmpty() && !m_bIsPDF_UA && m_nPDFA_Version == 0) { aLine.append( "/DocChecksum /" ); aLine.append( aDocChecksum ); aLine.append( "\n" ); } - if (!m_aDocumentAttachedFiles.empty()) + // Writes the /AdditionalStreams - writes the embedded / attached files into the PDF + // This entry is not defined in the standard, so don't write it if we + // are using PDF/UA or PDF/A as the compliance checkers will complain. + if (!m_aDocumentAttachedFiles.empty() && !m_bIsPDF_UA && m_nPDFA_Version == 0) { aLine.append( "/AdditionalStreams [" ); for (auto const& rAttachedFile : m_aDocumentAttachedFiles) { aLine.append( "/" ); - appendName(rAttachedFile.maMimeType, aLine); + COSWriter::appendName(rAttachedFile.maMimeType, aLine); aLine.append(" "); appendObjectReference(rAttachedFile.mnEmbeddedFileObjectId, aLine); aLine.append("\n"); @@ -6725,7 +6568,7 @@ void PDFWriterImpl::drawVerticalGlyphs( rLine.append( " Tf" ); } rLine.append( "<" ); - appendHex( rGlyphs[i].m_nMappedGlyphId, rLine ); + COSWriter::appendHex( rGlyphs[i].m_nMappedGlyphId, rLine ); rLine.append( ">Tj\n" ); } } @@ -6803,14 +6646,14 @@ void PDFWriterImpl::drawHorizontalGlyphs( OStringBuffer aKernedLine( 256 ), aUnkernedLine( 256 ); aKernedLine.append( "[<" ); aUnkernedLine.append( '<' ); - appendHex( rGlyphs[nBeginRun].m_nMappedGlyphId, aKernedLine ); - appendHex( rGlyphs[nBeginRun].m_nMappedGlyphId, aUnkernedLine ); + COSWriter::appendHex( rGlyphs[nBeginRun].m_nMappedGlyphId, aKernedLine ); + COSWriter::appendHex( rGlyphs[nBeginRun].m_nMappedGlyphId, aUnkernedLine ); aMat.invert(); bool bNeedKern = false; for( sal_uInt32 nPos = nBeginRun+1; nPos < aRunEnds[nRun]; nPos++ ) { - appendHex( rGlyphs[nPos].m_nMappedGlyphId, aUnkernedLine ); + COSWriter::appendHex( rGlyphs[nPos].m_nMappedGlyphId, aUnkernedLine ); // check if default glyph positioning is sufficient const basegfx::B2DPoint aThisPos = aMat.transform( rGlyphs[nPos].m_aPos ); const basegfx::B2DPoint aPrevPos = aMat.transform( rGlyphs[nPos-1].m_aPos ); @@ -6830,7 +6673,7 @@ void PDFWriterImpl::drawHorizontalGlyphs( aKernedLine.append( nAdjustment ); aKernedLine.append( "<" ); } - appendHex( rGlyphs[nPos].m_nMappedGlyphId, aKernedLine ); + COSWriter::appendHex( rGlyphs[nPos].m_nMappedGlyphId, aKernedLine ); } aKernedLine.append( ">]TJ\n" ); aUnkernedLine.append( ">Tj\n" ); @@ -7123,8 +6966,8 @@ void PDFWriterImpl::drawLayout( SalLayout& rLayout, const OUString& rText, bool for (int i = 0; i < nCharCount; i++) { sal_Unicode aChar = rText[nCharPos + i]; - appendHex(static_cast<sal_Int8>(aChar >> 8), aLine); - appendHex(static_cast<sal_Int8>(aChar & 255), aLine); + COSWriter::appendHex(static_cast<sal_Int8>(aChar >> 8), aLine); + COSWriter::appendHex(static_cast<sal_Int8>(aChar & 255), aLine); } aLine.append( ">>>\nBDC\n" ); } @@ -9796,16 +9639,16 @@ bool PDFWriterImpl::writeBitmapObject( const BitmapEmit& rObject, bool bMask ) std::vector<sal_uInt8> aOutputBuffer(nChar); m_pPDFEncryptor->encrypt(m_vEncryptionBuffer.data(), nChar, aOutputBuffer, nChar); //now queue the data for output - appendHexArray(aOutputBuffer.data(), aOutputBuffer.size(), aLine); + COSWriter::appendHexArray(aOutputBuffer.data(), aOutputBuffer.size(), aLine); } else //no encryption requested (PDF/A-1a program flow drops here) { for( sal_uInt16 i = 0; i < pAccess->GetPaletteEntryCount(); i++ ) { const BitmapColor& rColor = pAccess->GetPaletteColor( i ); - appendHex( rColor.GetRed(), aLine ); - appendHex( rColor.GetGreen(), aLine ); - appendHex( rColor.GetBlue(), aLine ); + COSWriter::appendHex( rColor.GetRed(), aLine ); + COSWriter::appendHex( rColor.GetGreen(), aLine ); + COSWriter::appendHex( rColor.GetBlue(), aLine ); } } aLine.append( ">\n]\n" ); @@ -11090,7 +10933,7 @@ void PDFWriterImpl::initStructureElement(sal_Int32 const id, if( !rAlias.empty() && eType != PDFWriter::NonStructElement ) { OStringBuffer aNameBuf( rAlias.size() ); - appendName( rAlias, aNameBuf ); + COSWriter::appendName( rAlias, aNameBuf ); OString aAliasName( aNameBuf.makeStringAndClear() ); rEle.m_aAlias = aAliasName; addRoleMap(aAliasName, eType); @@ -11885,7 +11728,7 @@ void PDFWriterImpl::ensureUniqueRadioOnValues() SvMemoryStream* pStream = stream_it->second; app_it->second.erase( stream_it ); OStringBuffer aBuf( rKid.m_aOnValue.getLength()*2 ); - appendName( rKid.m_aOnValue, aBuf ); + COSWriter::appendName( rKid.m_aOnValue, aBuf ); (app_it->second)[ aBuf.makeStringAndClear() ] = pStream; } else @@ -11904,7 +11747,7 @@ void PDFWriterImpl::ensureUniqueRadioOnValues() SvMemoryStream* pStream = stream_it->second; app_it->second.erase( stream_it ); OStringBuffer aBuf( rKid.m_aOffValue.getLength()*2 ); - appendName( rKid.m_aOffValue, aBuf ); + COSWriter::appendName( rKid.m_aOffValue, aBuf ); (app_it->second)[ aBuf.makeStringAndClear() ] = pStream; } else diff --git a/vcl/source/pdf/COSWriter.cxx b/vcl/source/pdf/COSWriter.cxx index 100da2e243aa..bc9f49448a34 100644 --- a/vcl/source/pdf/COSWriter.cxx +++ b/vcl/source/pdf/COSWriter.cxx @@ -79,7 +79,7 @@ void COSWriter::writeUnicodeEncrypt(OUString const& rString, sal_Int32 nObject) std::vector<sal_uInt8> aNewBuffer(nChars); mpPDFEncryptor->encrypt(aEncryptionBuffer.data(), nChars, aNewBuffer, nChars); //now append, hexadecimal (appendHex), the encrypted result - appendHexArray(aNewBuffer.data(), aNewBuffer.size()); + COSWriter::appendHexArray(aNewBuffer.data(), aNewBuffer.size(), mrBuffer); mrBuffer.append(">"); } else @@ -142,6 +142,53 @@ void COSWriter::appendUnicodeTextString(const OUString& rString, OStringBuffer& } } +void COSWriter::appendName(std::u16string_view rStr, OStringBuffer& rBuffer) +{ + // FIXME i59651 add a check for max length of 127 chars? Per PDF spec 1.4, appendix C.1 + // I guess than when reading the #xx sequence it will count for a single character. + OString aStr(OUStringToOString(rStr, RTL_TEXTENCODING_UTF8)); + int nLen = aStr.getLength(); + for (int i = 0; i < nLen; i++) + { + /* #i16920# PDF recommendation: output UTF8, any byte + * outside the interval [33(=ASCII'!');126(=ASCII'~')] + * should be escaped hexadecimal + * for the sake of ghostscript which also reads PDF + * but has a narrower acceptance rate we only pass + * alphanumerics and '-' literally. + */ + if ((aStr[i] >= 'A' && aStr[i] <= 'Z') || (aStr[i] >= 'a' && aStr[i] <= 'z') + || (aStr[i] >= '0' && aStr[i] <= '9') || aStr[i] == '-') + { + rBuffer.append(aStr[i]); + } + else + { + rBuffer.append('#'); + appendHex(static_cast<sal_Int8>(aStr[i]), rBuffer); + } + } +} + +void COSWriter::appendName(const char* pStr, OStringBuffer& rBuffer) +{ + // FIXME i59651 see above + while (pStr && *pStr) + { + if ((*pStr >= 'A' && *pStr <= 'Z') || (*pStr >= 'a' && *pStr <= 'z') + || (*pStr >= '0' && *pStr <= '9') || *pStr == '-') + { + rBuffer.append(*pStr); + } + else + { + rBuffer.append('#'); + appendHex(static_cast<sal_Int8>(*pStr), rBuffer); + } + pStr++; + } +} + } //end vcl::pdf /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/source/pdf/PDFiumLibrary.cxx b/vcl/source/pdf/PDFiumLibrary.cxx index c665ce006d9e..a1552e9ca1bf 100644 --- a/vcl/source/pdf/PDFiumLibrary.cxx +++ b/vcl/source/pdf/PDFiumLibrary.cxx @@ -31,6 +31,7 @@ #include <vcl/BitmapWriteAccess.hxx> #include <vcl/bitmapex.hxx> #include <vcl/dibtools.hxx> +#include <functional> using namespace com::sun::star; @@ -220,6 +221,35 @@ int CompatibleWriterCallback(FPDF_FILEWRITE* pFileWrite, const void* pData, unsi pImpl->m_rStream.WriteBytes(pData, nSize); return 1; } + +OUString getUnicodeString(std::function<int(FPDF_WCHAR*, unsigned long)> aPDFiumFunctionCall) +{ + OUString sReturnText; + + int nBytes = aPDFiumFunctionCall(nullptr, 0); + if (nBytes == 0) + return sReturnText; + assert(nBytes % 2 == 0); + nBytes /= 2; + + std::vector<sal_Unicode> pText(nBytes, 0); + + int nActualBytes = aPDFiumFunctionCall(reinterpret_cast<FPDF_WCHAR*>(pText.data()), nBytes * 2); + assert(nActualBytes % 2 == 0); + nActualBytes /= 2; + if (nActualBytes > 1) + { +#ifdef OSL_BIGENDIAN + for (int i = 0; i != nActualBytes; ++i) + { + pText[i] = OSL_SWAPWORD(pText[i]); + } +#endif + sReturnText = OUString(pText.data()); + } + + return sReturnText; +} } namespace vcl::pdf @@ -910,32 +940,10 @@ PDFiumPageObjectImpl::PDFiumPageObjectImpl(FPDF_PAGEOBJECT pPageObject) OUString PDFiumPageObjectImpl::getText(std::unique_ptr<PDFiumTextPage> const& rTextPage) { - OUString sReturnText; - auto pTextPage = static_cast<PDFiumTextPageImpl*>(rTextPage.get()); - int nBytes = FPDFTextObj_GetText(mpPageObject, pTextPage->getPointer(), nullptr, 0); - assert(nBytes % 2 == 0); - nBytes /= 2; - - std::unique_ptr<sal_Unicode[]> pText(new sal_Unicode[nBytes]); - - int nActualBytes = FPDFTextObj_GetText(mpPageObject, pTextPage->getPointer(), - reinterpret_cast<FPDF_WCHAR*>(pText.get()), nBytes * 2); - assert(nActualBytes % 2 == 0); - nActualBytes /= 2; - if (nActualBytes > 1) - { -#if defined OSL_BIGENDIAN - // The data returned by FPDFTextObj_GetText is documented to always be UTF-16LE: - for (int i = 0; i != nActualBytes; ++i) - { - pText[i] = OSL_SWAPWORD(pText[i]); - } -#endif - sReturnText = OUString(pText.get()); - } - - return sReturnText; + return getUnicodeString([this, pTextPage](FPDF_WCHAR* buffer, unsigned long length) { + return FPDFTextObj_GetText(mpPageObject, pTextPage->getPointer(), buffer, length); + }); } PDFPageObjectType PDFiumPageObjectImpl::getType() @@ -1390,98 +1398,36 @@ Color PDFiumAnnotationImpl::getFontColor(PDFiumDocument* pDoc) OUString PDFiumAnnotationImpl::getFormFieldAlternateName(PDFiumDocument* pDoc) { - auto pDocImpl = static_cast<PDFiumDocumentImpl*>(pDoc); - OUString aString; - unsigned long nSize = FPDFAnnot_GetFormFieldAlternateName(pDocImpl->getFormHandlePointer(), - mpAnnotation, nullptr, 0); - assert(nSize % 2 == 0); - nSize /= 2; - if (nSize > 1) - { - std::unique_ptr<sal_Unicode[]> pText(new sal_Unicode[nSize]); - unsigned long nStringSize = FPDFAnnot_GetFormFieldAlternateName( - pDocImpl->getFormHandlePointer(), mpAnnotation, - reinterpret_cast<FPDF_WCHAR*>(pText.get()), nSize * 2); - assert(nStringSize % 2 == 0); - nStringSize /= 2; - if (nStringSize > 0) - { -#if defined OSL_BIGENDIAN - for (unsigned long i = 0; i != nStringSize; ++i) - { - pText[i] = OSL_SWAPWORD(pText[i]); - } -#endif - aString = OUString(pText.get()); - } - } - return aString; + auto* pDocImpl = static_cast<PDFiumDocumentImpl*>(pDoc); + return getUnicodeString([this, pDocImpl](FPDF_WCHAR* buffer, unsigned long length) { + return FPDFAnnot_GetFormFieldAlternateName(pDocImpl->getFormHandlePointer(), mpAnnotation, + buffer, length); + }); } OUString PDFiumAnnotationImpl::getFormFieldValue(PDFiumDocument* pDoc) { - auto pDocImpl = static_cast<PDFiumDocumentImpl*>(pDoc); - OUString aString; - unsigned long nSize - = FPDFAnnot_GetFormFieldValue(pDocImpl->getFormHandlePointer(), mpAnnotation, nullptr, 0); - assert(nSize % 2 == 0); - nSize /= 2; - if (nSize > 1) - { - std::unique_ptr<sal_Unicode[]> pText(new sal_Unicode[nSize]); - unsigned long nStringSize - = FPDFAnnot_GetFormFieldValue(pDocImpl->getFormHandlePointer(), mpAnnotation, - reinterpret_cast<FPDF_WCHAR*>(pText.get()), nSize * 2); - assert(nStringSize % 2 == 0); - nStringSize /= 2; - if (nStringSize > 0) - { -#if defined OSL_BIGENDIAN - for (unsigned long i = 0; i != nStringSize; ++i) - { - pText[i] = OSL_SWAPWORD(pText[i]); - } -#endif - aString = OUString(pText.get()); - } - } - return aString; + auto* pDocImpl = static_cast<PDFiumDocumentImpl*>(pDoc); + return getUnicodeString([this, pDocImpl](FPDF_WCHAR* buffer, unsigned long length) { + return FPDFAnnot_GetFormFieldValue(pDocImpl->getFormHandlePointer(), mpAnnotation, buffer, + length); + }); } int PDFiumAnnotationImpl::getOptionCount(PDFiumDocument* pDoc) { - auto pDocImpl = static_cast<PDFiumDocumentImpl*>(pDoc); + auto* pDocImpl = static_cast<PDFiumDocumentImpl*>(pDoc); return FPDFAnnot_GetOptionCount(pDocImpl->getFormHandlePointer(), mpAnnotation); } OUString PDFiumAnnotationImpl::getFormAdditionalActionJavaScript(PDFiumDocument* pDoc, PDFAnnotAActionType eEvent) { - auto pDocImpl = static_cast<PDFiumDocumentImpl*>(pDoc); - OUString aString; - unsigned long nSize = FPDFAnnot_GetFormAdditionalActionJavaScript( - pDocImpl->getFormHandlePointer(), mpAnnotation, static_cast<int>(eEvent), nullptr, 0); - assert(nSize % 2 == 0); - nSize /= 2; - if (nSize > 1) - { - std::unique_ptr<sal_Unicode[]> pText(new sal_Unicode[nSize]); - unsigned long nStringSize = FPDFAnnot_GetFormAdditionalActionJavaScript( - pDocImpl->getFormHandlePointer(), mpAnnotation, static_cast<int>(eEvent), - reinterpret_cast<FPDF_WCHAR*>(pText.get()), nSize * 2); - assert(nStringSize % 2 == 0); - nStringSize /= 2; - if (nStringSize > 0) - { -#if defined OSL_BIGENDIAN - for (unsigned long i = 0; i != nStringSize; ++i) - { - pText[i] = OSL_SWAPWORD(pText[i]); - } -#endif - aString = OUString(pText.get()); - } - } - return aString; + auto* pDocImpl = static_cast<PDFiumDocumentImpl*>(pDoc); + return getUnicodeString([this, pDocImpl, eEvent](FPDF_WCHAR* buffer, unsigned long length) { + return FPDFAnnot_GetFormAdditionalActionJavaScript(pDocImpl->getFormHandlePointer(), + mpAnnotation, static_cast<int>(eEvent), + buffer, length); + }); } namespace @@ -1539,30 +1485,9 @@ PDFObjectType PDFiumAnnotationImpl::getValueType(OString const& rKey) OUString PDFiumAnnotationImpl::getString(OString const& rKey) { - OUString rString; - unsigned long nSize = FPDFAnnot_GetStringValue(mpAnnotation, rKey.getStr(), nullptr, 0); - assert(nSize % 2 == 0); - nSize /= 2; - if (nSize > 1) - { - std::unique_ptr<sal_Unicode[]> pText(new sal_Unicode[nSize]); - unsigned long nStringSize = FPDFAnnot_GetStringValue( - mpAnnotation, rKey.getStr(), reinterpret_cast<FPDF_WCHAR*>(pText.get()), nSize * 2); - assert(nStringSize % 2 == 0); - nStringSize /= 2; - if (nStringSize > 0) - { -#if defined OSL_BIGENDIAN - // The data returned by FPDFAnnot_GetStringValue is documented to always be UTF-16LE: - for (unsigned long i = 0; i != nStringSize; ++i) - { - pText[i] = OSL_SWAPWORD(pText[i]); - } -#endif - rString = OUString(pText.get()); - } - } - return rString; + return getUnicodeString([this, rKey](FPDF_WCHAR* buffer, unsigned long length) { + return FPDFAnnot_GetStringValue(mpAnnotation, rKey.getStr(), buffer, length); + }); } std::vector<std::vector<basegfx::B2DPoint>> PDFiumAnnotationImpl::getInkStrokes() diff --git a/writerperfect/source/common/WPFTEncodingDialog.cxx b/writerperfect/source/common/WPFTEncodingDialog.cxx index dc440929dcea..e0a4f8490582 100644 --- a/writerperfect/source/common/WPFTEncodingDialog.cxx +++ b/writerperfect/source/common/WPFTEncodingDialog.cxx @@ -79,12 +79,10 @@ std::pair<std::u16string_view, std::u16string_view> const s_encodings[] { u"CP865", u"Western Europe (DOS/OS2-865/Nordic)" }, { u"CP1252", u"Western Europe (Windows-1252/WinLatin 1)" } }; -std::size_t const numEncodings = SAL_N_ELEMENTS(s_encodings); - void insertEncodings(weld::ComboBox& box) { - for (std::size_t i = 0; i < numEncodings; ++i) - box.append(OUString(s_encodings[i].first), OUString(s_encodings[i].second)); + for (const auto& rEncoding : s_encodings) + box.append(OUString(rEncoding.first), OUString(rEncoding.second)); } void selectEncoding(weld::ComboBox& box, const OUString& encoding) { box.set_active_id(encoding); } |