summaryrefslogtreecommitdiff
path: root/vcl/source/gdi/pdfwriter_impl.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'vcl/source/gdi/pdfwriter_impl.cxx')
-rw-r--r--vcl/source/gdi/pdfwriter_impl.cxx115
1 files changed, 64 insertions, 51 deletions
diff --git a/vcl/source/gdi/pdfwriter_impl.cxx b/vcl/source/gdi/pdfwriter_impl.cxx
index 3cf733449d31..5d2fbf6a6b13 100644
--- a/vcl/source/gdi/pdfwriter_impl.cxx
+++ b/vcl/source/gdi/pdfwriter_impl.cxx
@@ -45,6 +45,7 @@
#include <osl/thread.h>
#include <rtl/digest.h>
#include <rtl/ustrbuf.hxx>
+#include <rtl/xmlencode.hxx>
#include <sal/log.hxx>
#include <svl/urihelper.hxx>
#include <tools/fract.hxx>
@@ -75,6 +76,7 @@
#include <bitmapwriteaccess.hxx>
#include <impglyphitem.hxx>
#include <pdf/objectcopier.hxx>
+#include <pdf/PdfConfig.hxx>
#include "pdfwriter_impl.hxx"
@@ -4155,9 +4157,6 @@ void PDFWriterImpl::createDefaultRadioButtonAppearance( PDFWidget& rBox, const P
pop();
- OStringBuffer aDA( 256 );
- appendNonStrokingColor( replaceColor( rWidget.TextColor, rSettings.GetRadioCheckTextColor() ), aDA );
- rBox.m_aDAString = aDA.makeStringAndClear();
//to encrypt this (el)
rBox.m_aMKDict = "/CA";
//after this assignment, to m_aMKDic cannot be added anything
@@ -4170,6 +4169,7 @@ void PDFWriterImpl::createDefaultRadioButtonAppearance( PDFWidget& rBox, const P
SvMemoryStream* pCheckStream = new SvMemoryStream( 256, 256 );
beginRedirect( pCheckStream, aCheckRect );
+ OStringBuffer aDA( 256 );
aDA.append( "/Tx BMC\nq BT\n" );
appendNonStrokingColor( replaceColor( rWidget.TextColor, rSettings.GetRadioCheckTextColor() ), aDA );
aDA.append( ' ' );
@@ -5326,37 +5326,6 @@ sal_Int32 PDFWriterImpl::emitOutputIntent()
return nOIObject;
}
-// formats the string for the XML stream
-static void escapeStringXML( const OUString& rStr, OUString &rValue)
-{
- const sal_Unicode* pUni = rStr.getStr();
- int nLen = rStr.getLength();
- for( ; nLen; nLen--, pUni++ )
- {
- switch( *pUni )
- {
- case u'&':
- rValue += "&amp;";
- break;
- case u'<':
- rValue += "&lt;";
- break;
- case u'>':
- rValue += "&gt;";
- break;
- case u'\'':
- rValue += "&apos;";
- break;
- case u'"':
- rValue += "&quot;";
- break;
- default:
- rValue += OUStringChar( *pUni );
- break;
- }
- }
-}
-
// emits the document metadata
sal_Int32 PDFWriterImpl::emitDocumentMetadata()
{
@@ -5405,8 +5374,7 @@ sal_Int32 PDFWriterImpl::emitDocumentMetadata()
aMetadataStream.append( " <dc:title>\n" );
aMetadataStream.append( " <rdf:Alt>\n" );
aMetadataStream.append( " <rdf:li xml:lang=\"x-default\">" );
- OUString aTitle;
- escapeStringXML( m_aContext.DocumentInfo.Title, aTitle );
+ OUString aTitle = rtl::encodeForXml( m_aContext.DocumentInfo.Title );
aMetadataStream.append( OUStringToOString( aTitle, RTL_TEXTENCODING_UTF8 ) );
aMetadataStream.append( "</rdf:li>\n" );
aMetadataStream.append( " </rdf:Alt>\n" );
@@ -5417,8 +5385,7 @@ sal_Int32 PDFWriterImpl::emitDocumentMetadata()
aMetadataStream.append( " <dc:creator>\n" );
aMetadataStream.append( " <rdf:Seq>\n" );
aMetadataStream.append( " <rdf:li>" );
- OUString aAuthor;
- escapeStringXML( m_aContext.DocumentInfo.Author, aAuthor );
+ OUString aAuthor = rtl::encodeForXml( m_aContext.DocumentInfo.Author );
aMetadataStream.append( OUStringToOString( aAuthor , RTL_TEXTENCODING_UTF8 ) );
aMetadataStream.append( "</rdf:li>\n" );
aMetadataStream.append( " </rdf:Seq>\n" );
@@ -5430,8 +5397,7 @@ sal_Int32 PDFWriterImpl::emitDocumentMetadata()
aMetadataStream.append( " <dc:description>\n" );
aMetadataStream.append( " <rdf:Alt>\n" );
aMetadataStream.append( " <rdf:li xml:lang=\"x-default\">" );
- OUString aSubject;
- escapeStringXML( m_aContext.DocumentInfo.Subject, aSubject );
+ OUString aSubject = rtl::encodeForXml( m_aContext.DocumentInfo.Subject );
aMetadataStream.append( OUStringToOString( aSubject , RTL_TEXTENCODING_UTF8 ) );
aMetadataStream.append( "</rdf:li>\n" );
aMetadataStream.append( " </rdf:Alt>\n" );
@@ -5449,16 +5415,14 @@ sal_Int32 PDFWriterImpl::emitDocumentMetadata()
if( !m_aContext.DocumentInfo.Producer.isEmpty() )
{
aMetadataStream.append( " <pdf:Producer>" );
- OUString aProducer;
- escapeStringXML( m_aContext.DocumentInfo.Producer, aProducer );
+ OUString aProducer = rtl::encodeForXml( m_aContext.DocumentInfo.Producer );
aMetadataStream.append( OUStringToOString( aProducer , RTL_TEXTENCODING_UTF8 ) );
aMetadataStream.append( "</pdf:Producer>\n" );
}
if( !m_aContext.DocumentInfo.Keywords.isEmpty() )
{
aMetadataStream.append( " <pdf:Keywords>" );
- OUString aKeywords;
- escapeStringXML( m_aContext.DocumentInfo.Keywords, aKeywords );
+ OUString aKeywords = rtl::encodeForXml( m_aContext.DocumentInfo.Keywords );
aMetadataStream.append( OUStringToOString( aKeywords , RTL_TEXTENCODING_UTF8 ) );
aMetadataStream.append( "</pdf:Keywords>\n" );
}
@@ -5470,8 +5434,7 @@ sal_Int32 PDFWriterImpl::emitDocumentMetadata()
if( !m_aContext.DocumentInfo.Creator.isEmpty() )
{
aMetadataStream.append( " <xmp:CreatorTool>" );
- OUString aCreator;
- escapeStringXML( m_aContext.DocumentInfo.Creator, aCreator );
+ OUString aCreator = rtl::encodeForXml( m_aContext.DocumentInfo.Creator );
aMetadataStream.append( OUStringToOString( aCreator , RTL_TEXTENCODING_UTF8 ) );
aMetadataStream.append( "</xmp:CreatorTool>\n" );
}
@@ -8668,11 +8631,14 @@ void PDFWriterImpl::writeReferenceXObject(ReferenceXObjectEmit& rEmit)
return;
// Count /Matrix and /BBox.
- // vcl::ImportPDF() works with 96 DPI so use the same values here, too.
+ // vcl::ImportPDF() uses getDefaultPdfResolutionDpi to set the desired
+ // rendering DPI so we have to take into account that here too.
+ static const double fResolutionDPI = vcl::pdf::getDefaultPdfResolutionDpi();
+
sal_Int32 nOldDPIX = GetDPIX();
- SetDPIX(96);
sal_Int32 nOldDPIY = GetDPIY();
- SetDPIY(96);
+ SetDPIX(fResolutionDPI);
+ SetDPIY(fResolutionDPI);
Size aSize = PixelToLogic(rEmit.m_aPixelSize, MapMode(m_aMapMode.GetMapUnit()));
SetDPIX(nOldDPIX);
SetDPIY(nOldDPIY);
@@ -8736,6 +8702,53 @@ void PDFWriterImpl::writeReferenceXObject(ReferenceXObjectEmit& rEmit)
return;
}
+ // Merge link annotations from pPage to our page.
+ std::vector<filter::PDFObjectElement*> aAnnots;
+ if (auto pArray = dynamic_cast<filter::PDFArrayElement*>(pPage->Lookup("Annots")))
+ {
+ for (const auto pElement : pArray->GetElements())
+ {
+ auto pReference = dynamic_cast<filter::PDFReferenceElement*>(pElement);
+ if (!pReference)
+ {
+ continue;
+ }
+
+ filter::PDFObjectElement* pObject = pReference->LookupObject();
+ if (!pObject)
+ {
+ continue;
+ }
+
+ auto pType = dynamic_cast<filter::PDFNameElement*>(pObject->Lookup("Type"));
+ if (!pType || pType->GetValue() != "Annot")
+ {
+ continue;
+ }
+
+ auto pSubtype = dynamic_cast<filter::PDFNameElement*>(pObject->Lookup("Subtype"));
+ if (!pSubtype || pSubtype->GetValue() != "Link")
+ {
+ continue;
+ }
+
+ // Reference to a link annotation object, remember it.
+ aAnnots.push_back(pObject);
+ }
+ }
+ if (!aAnnots.empty())
+ {
+ PDFObjectCopier aCopier(*this);
+ SvMemoryStream& rDocBuffer = pPage->GetDocument().GetEditBuffer();
+ std::map<sal_Int32, sal_Int32> aMap;
+ for (const auto& pAnnot : aAnnots)
+ {
+ // Copy over the annotation and refer to its new id.
+ sal_Int32 nNewId = aCopier.copyExternalResource(rDocBuffer, *pAnnot, aMap);
+ m_aPages.back().m_aAnnotations.push_back(nNewId);
+ }
+ }
+
nWrappedFormObject = createObject();
// Write the form XObject wrapped below. This is a separate object from
// the wrapper, this way there is no need to alter the stream contents.
@@ -8833,9 +8846,9 @@ void PDFWriterImpl::writeReferenceXObject(ReferenceXObjectEmit& rEmit)
aLine.append(">> >>");
aLine.append(" /Matrix [ ");
- appendDouble(fScaleX, aLine);
+ appendDouble(fScaleX, aLine, /*nPrecision=*/10);
aLine.append(" 0 0 ");
- appendDouble(fScaleY, aLine);
+ appendDouble(fScaleY, aLine, /*nPrecision=*/10);
aLine.append(" 0 0 ]");
aLine.append(" /BBox [ 0 0 ");
aLine.append(aSize.Width());