21#include <config_crypto.h>
38#include <com/sun/star/io/XOutputStream.hpp>
39#include <com/sun/star/util/URL.hpp>
40#include <com/sun/star/util/URLTransformer.hpp>
48#include <officecfg/Office/Common.hxx>
49#include <osl/file.hxx>
50#include <osl/thread.h>
51#include <rtl/digest.h>
53#include <rtl/ustrbuf.hxx>
85#include <textlayout.hxx>
94using namespace::com::sun::star;
101constexpr sal_Int32 nLog10Divisor = 3;
102constexpr double fDivisor = 1000.0;
104constexpr double pixelToPoint(
double px)
106 return px / fDivisor;
111 return sal_Int32(pt * fDivisor);
114void appendHex(
sal_Int8 nInt, OStringBuffer& rBuffer)
116 static const char pHexDigits[] = {
'0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
117 '8',
'9',
'A',
'B',
'C',
'D',
'E',
'F' };
118 rBuffer.append( pHexDigits[ (nInt >> 4) & 15 ] );
119 rBuffer.append( pHexDigits[ nInt & 15 ] );
122void appendName( std::u16string_view rStr, OStringBuffer& rBuffer )
127 int nLen =
aStr.getLength();
128 for(
int i = 0;
i < nLen;
i++ )
137 if( (aStr[i] >=
'A' && aStr[i] <=
'Z' ) ||
138 (aStr[i] >=
'a' && aStr[i] <=
'z' ) ||
139 (aStr[i] >=
'0' && aStr[i] <=
'9' ) ||
142 rBuffer.append( aStr[i] );
146 rBuffer.append(
'#' );
147 appendHex(
static_cast<sal_Int8>(aStr[i]), rBuffer );
152void appendName(
const char* pStr, OStringBuffer& rBuffer )
155 while( pStr && *pStr )
157 if( (*pStr >=
'A' && *pStr <=
'Z' ) ||
158 (*pStr >=
'a' && *pStr <=
'z' ) ||
159 (*pStr >=
'0' && *pStr <=
'9' ) ||
162 rBuffer.append( *pStr );
166 rBuffer.append(
'#' );
167 appendHex(
static_cast<sal_Int8>(*pStr), rBuffer );
174void appendLiteralString(
const char* pStr, sal_Int32 nLength, OStringBuffer& rBuffer )
181 rBuffer.append(
"\\n" );
184 rBuffer.append(
"\\r" );
187 rBuffer.append(
"\\t" );
190 rBuffer.append(
"\\b" );
193 rBuffer.append(
"\\f" );
198 rBuffer.append(
"\\" );
199 rBuffer.append(
static_cast<char>(*pStr) );
202 rBuffer.append(
static_cast<char>(*pStr) );
233void appendDestinationName(
const OUString& rString, OStringBuffer& rBuffer )
236 sal_Int32 nLen = rString.getLength();
237 for(
int i = 0;
i < nLen;
i++ )
240 if( (aChar >=
'0' && aChar <=
'9' ) ||
241 (aChar >=
'a' && aChar <=
'z' ) ||
242 (aChar >=
'A' && aChar <=
'Z' ) ||
245 rBuffer.append(
static_cast<char>(aChar));
251 appendHex( aValueHigh, rBuffer );
252 appendHex(
static_cast<sal_Int8>(aChar & 255 ), rBuffer );
263 0x28, 0xBF, 0x4E, 0x5E, 0x4E, 0x75, 0x8A, 0x41, 0x64, 0x00, 0x4E, 0x56, 0xFF, 0xFA, 0x01, 0x08,
264 0x2E, 0x2E, 0x00, 0xB6, 0xD0, 0x68, 0x3E, 0x80, 0x2F, 0x0C, 0xA9, 0xFE, 0x64, 0x53, 0x69, 0x7A
270template <
class GEOMETRY >
271GEOMETRY lcl_convert(
const MapMode& _rSource,
const MapMode& _rDest,
OutputDevice* _pPixelConversion,
const GEOMETRY& _rObject )
274 if ( MapUnit::MapPixel == _rSource.
GetMapUnit() )
276 aPoint = _pPixelConversion->
PixelToLogic( _rObject, _rDest );
289 rBuffer.append(
"FEFF" );
291 sal_Int32 nLen = rString.getLength();
292 for(
int i = 0;
i < nLen;
i++ )
295 appendHex(
static_cast<sal_Int8>(aChar >> 8), rBuffer );
296 appendHex(
static_cast<sal_Int8>(aChar & 255 ), rBuffer );
308 int nLen =
aStr.getLength();
310 OStringBuffer
aBuffer( rName.getLength()+64 );
311 for(
int i = 0;
i < nLen;
i++ )
326 OString aFullName(
aBuffer.makeStringAndClear() );
329 sal_Int32 nTokenIndex = 0, nLastTokenIndex = 0;
330 OString aPartialName;
334 nLastTokenIndex = nTokenIndex;
335 aPartialName = aFullName.getToken( 0,
'.', nTokenIndex );
336 if( nTokenIndex != -1 )
340 aDomain = aFullName.copy( 0, nTokenIndex-1 );
341 std::unordered_map< OString, sal_Int32 >::const_iterator it =
m_aFieldNameMap.find( aDomain );
349 m_aWidgets[nNewWidget].m_aName = aPartialName;
353 if( nLastTokenIndex > 0 )
357 OString aParentDomain( aDomain.copy( 0, nLastTokenIndex-1 ) );
362 OSL_ENSURE( it->second < sal_Int32(
m_aWidgets.size()),
"invalid field number entry" );
363 if( it->second < sal_Int32(
m_aWidgets.size()) )
382 aPartialName = aFullName.copy( aFullName.lastIndexOf(
'.' )+1 );
383 if( nLastTokenIndex > 0 )
385 aDomain = aFullName.copy( 0, nLastTokenIndex-1 );
386 aFullName = aDomain +
"." + aPartialName;
389 aFullName = aPartialName;
393 }
while( nTokenIndex != -1 );
396 if( !aDomain.isEmpty() )
398 std::unordered_map< OString, sal_Int32 >::const_iterator it =
m_aFieldNameMap.find( aDomain );
406 m_aWidgets[it->second].m_aKidsIndex.push_back( i_nWidgetIndex );
411 if( aPartialName.isEmpty() )
416 aPartialName =
"RadioGroup" +
420 aPartialName = OString(
"Widget" );
425 std::unordered_map<OString, sal_Int32>::iterator it =
m_aFieldNameMap.find( aFullName );
429 std::unordered_map< OString, sal_Int32 >::const_iterator check_it;
434 OStringBuffer aUnique( aFullName.getLength() + 16 );
435 aUnique.append( aFullName );
436 aUnique.append(
'_' );
437 aUnique.append( nTry++ );
438 aTry = aUnique.makeStringAndClear();
443 aPartialName = aFullName.copy( aFullName.lastIndexOf(
'.' )+1 );
450 m_aWidgets[i_nWidgetIndex].m_aName = aPartialName;
456void appendFixedInt( sal_Int32 nValue, OStringBuffer& rBuffer )
460 rBuffer.append(
'-' );
463 sal_Int32 nFactor = 1, nDiv = nLog10Divisor;
467 sal_Int32 nInt =
nValue / nFactor;
468 rBuffer.append( nInt );
469 if (nFactor > 1 && nValue % nFactor)
471 rBuffer.append(
'.' );
475 rBuffer.append((nValue / nFactor) % 10);
477 while (nFactor > 1 && nValue % nFactor);
482void appendDouble(
double fValue, OStringBuffer& rBuffer, sal_Int32 nPrecision = 10 )
491 sal_Int64 nInt =
static_cast<sal_Int64
>(fValue);
492 fValue -=
static_cast<double>(nInt);
494 if( rtl::math::approxEqual(fValue, 1.0) || log10( 1.0-fValue ) <= -nPrecision )
502 fValue *= pow( 10.0,
static_cast<double>(nPrecision) );
503 nFrac =
static_cast<sal_Int64
>(fValue);
505 if( bNeg && ( nInt || nFrac ) )
506 rBuffer.append(
'-' );
507 rBuffer.append( nInt );
512 rBuffer.append(
'.' );
513 sal_Int64 nBound =
static_cast<sal_Int64
>(pow( 10.0, nPrecision - 1.0 )+0.5);
514 for ( i = 0; (
i < nPrecision ) && nFrac;
i++ )
516 sal_Int64 nNumb = nFrac / nBound;
517 nFrac -= nNumb * nBound;
518 rBuffer.append( nNumb );
523void appendColor(
const Color& rColor, OStringBuffer& rBuffer,
bool bConvertToGrey )
526 if( rColor == COL_TRANSPARENT )
532 appendDouble(
static_cast<double>(cByte) / 255.0, rBuffer );
536 appendDouble(
static_cast<double>(rColor.
GetRed()) / 255.0, rBuffer );
537 rBuffer.append(
' ' );
538 appendDouble(
static_cast<double>(rColor.
GetGreen()) / 255.0, rBuffer );
539 rBuffer.append(
' ' );
540 appendDouble(
static_cast<double>(rColor.
GetBlue()) / 255.0, rBuffer );
551 appendColor( rColor, rBuffer, bGrey );
552 rBuffer.append( bGrey ?
" G" :
" RG" );
561 appendColor( rColor, rBuffer, bGrey );
562 rBuffer.append( bGrey ?
" g" :
" rg" );
569void appendPdfTimeDate(OStringBuffer & rBuffer,
570 sal_Int16 year, sal_uInt16 month, sal_uInt16 day, sal_uInt16 hours, sal_uInt16 minutes, sal_uInt16 seconds, sal_Int32 tzDelta)
572 rBuffer.append(
"D:");
573 rBuffer.append(
char(
'0' + ((year / 1000) % 10)));
574 rBuffer.append(
char(
'0' + ((year / 100) % 10)));
575 rBuffer.append(
char(
'0' + ((year / 10) % 10)));
576 rBuffer.append(
char(
'0' + (year % 10)));
577 rBuffer.append(
char(
'0' + ((month / 10) % 10)));
578 rBuffer.append(
char(
'0' + (month % 10)));
579 rBuffer.append(
char(
'0' + ((day / 10) % 10)));
580 rBuffer.append(
char(
'0' + (day % 10)));
581 rBuffer.append(
char(
'0' + ((hours / 10) % 10)));
582 rBuffer.append(
char(
'0' + (hours % 10)));
583 rBuffer.append(
char(
'0' + ((minutes / 10) % 10)));
584 rBuffer.append(
char(
'0' + (minutes % 10)));
585 rBuffer.append(
char(
'0' + ((seconds / 10) % 10)));
586 rBuffer.append(
char(
'0' + (seconds % 10)));
602 rBuffer.append(
char(
'0' + ((tzDelta / 36000) % 10)));
603 rBuffer.append(
char(
'0' + ((tzDelta / 3600) % 10)));
605 rBuffer.append(
char(
'0' + ((tzDelta / 600) % 6)));
606 rBuffer.append(
char(
'0' + ((tzDelta / 60) % 10)));
614 m_pWriter( pWriter ),
615 m_nPageWidth( nPageWidth ),
616 m_nPageHeight( nPageHeight ),
618 m_eOrientation( eOrientation ),
620 m_nStreamLengthObject( 0 ),
621 m_nBeginStreamPos( 0 ),
631 m_nUserUnit = std::ceil(std::max(nPageWidth, nPageHeight) / 14400.0);
643 m_pWriter->emitComment(
"PDFWriterImpl::PDFPage::beginStream, +");
653 aLine.append(
" 0 obj\n<</Length " );
655 aLine.append(
" 0 R" );
657 aLine.append(
"/Filter/FlateDecode" );
658 aLine.append(
">>\nstream\n" );
659 if( !
m_pWriter->writeBuffer( aLine.getStr(), aLine.getLength() ) )
675 sal_uInt64 nEndStreamPos;
676 if (osl::File::E_None !=
m_pWriter->m_aFile.getPos(nEndStreamPos))
683 if( !
m_pWriter->writeBuffer(
"\nendstream\nendobj\n\n", 19 ) )
693 m_pWriter->writeBuffer( aLine.getStr(), aLine.getLength() );
705 aLine.append(
" 0 obj\n"
706 "<</Type/Page/Parent " );
707 aLine.append( nParentObject );
708 aLine.append(
" 0 R" );
709 aLine.append(
"/Resources " );
710 aLine.append(
m_pWriter->getResourceDictObj() );
711 aLine.append(
" 0 R" );
714 aLine.append(
"/MediaBox[0 0 " );
721 aLine.append(
"\n/UserUnit ");
733 aLine.append(
"/Annots[\n" );
734 for(
int i = 0;
i < nAnnots;
i++ )
737 aLine.append(
" 0 R" );
738 aLine.append( ((
i+1)%15) ?
" " :
"\n" );
740 aLine.append(
"]\n" );
742 && PDFWriter::PDFVersion::PDF_1_5 <= m_pWriter->
m_aContext.Version)
745 aLine.append(
"/Tabs(S)\n" );
750 OStringBuffer aStructParents( 1024 );
751 aStructParents.append(
"[ " );
753 for(
int i = 0;
i < nParents;
i++ )
756 aStructParents.append(
" 0 R" );
757 aStructParents.append( ((
i%10) == 9) ?
"\n" :
" " );
759 aStructParents.append(
"]" );
760 m_pWriter->m_aStructParentTree.push_back( aStructParents.makeStringAndClear() );
762 aLine.append(
"/StructParents " );
763 aLine.append( sal_Int32(
m_pWriter->m_aStructParentTree.size()-1) );
764 aLine.append(
"\n" );
769 aLine.append(
"/Trans<</D " );
770 appendDouble(
static_cast<double>(
m_nTransTime)/1000.0, aLine, 3 );
771 aLine.append(
"\n" );
772 const char *pStyle =
nullptr, *pDm =
nullptr, *pM =
nullptr, *pDi =
nullptr;
776 pStyle =
"Split"; pDm =
"H"; pM =
"I";
break;
778 pStyle =
"Split"; pDm =
"H"; pM =
"O";
break;
780 pStyle =
"Split"; pDm =
"V"; pM =
"I";
break;
782 pStyle =
"Split"; pDm =
"V"; pM =
"O";
break;
784 pStyle =
"Blinds"; pDm =
"H";
break;
786 pStyle =
"Blinds"; pDm =
"V";
break;
788 pStyle =
"Box"; pM =
"I";
break;
790 pStyle =
"Box"; pM =
"O";
break;
792 pStyle =
"Wipe"; pDi =
"0";
break;
794 pStyle =
"Wipe"; pDi =
"90";
break;
796 pStyle =
"Wipe"; pDi =
"180";
break;
798 pStyle =
"Wipe"; pDi =
"270";
break;
800 pStyle =
"Dissolve";
break;
807 aLine.append(
"/S/" );
808 aLine.append( pStyle );
809 aLine.append(
"\n" );
813 aLine.append(
"/Dm/" );
815 aLine.append(
"\n" );
819 aLine.append(
"/M/" );
821 aLine.append(
"\n" );
825 aLine.append(
"/Di " );
827 aLine.append(
"\n" );
829 aLine.append(
">>\n" );
832 aLine.append(
"/Contents" );
834 if( nStreamObjects > 1 )
840 aLine.append(
" 0 R" );
842 if( nStreamObjects > 1 )
844 aLine.append(
">>\nendobj\n\n" );
845 return m_pWriter->writeBuffer( aLine.getStr(), aLine.getLength() );
850 Point aPoint( lcl_convert(
m_pWriter->m_aGraphicsStack.front().m_aMapMode,
855 sal_Int32
nValue = aPoint.X();
857 appendFixedInt(
nValue, rBuffer );
859 rBuffer.append(
' ' );
863 appendFixedInt(
nValue, rBuffer );
868 double fValue = pixelToPoint(rPoint.
getX());
870 appendDouble( fValue, rBuffer, nLog10Divisor );
871 rBuffer.append(
' ' );
873 appendDouble( fValue, rBuffer, nLog10Divisor );
879 rBuffer.append(
' ' );
881 rBuffer.append(
' ' );
883 rBuffer.append(
" re" );
888 Point aLL = lcl_convert(
m_pWriter->m_aGraphicsStack.front().m_aMapMode,
893 Size aSize = lcl_convert(
m_pWriter->m_aGraphicsStack.front().m_aMapMode,
905 sal_uInt16 nPoints = rPoly.
GetSize();
909 sal_uInt32 nBufLen = rBuffer.getLength();
915 rBuffer.append(
" m\n" );
916 for( sal_uInt16
i = 1;
i < nPoints;
i++ )
918 if( pFlagArray && pFlagArray[
i] == PolyFlags::Control && nPoints-
i > 2 )
921 SAL_WARN_IF( pFlagArray[
i+1] != PolyFlags::Control || pFlagArray[
i+2] == PolyFlags::Control,
"vcl.pdfwriter",
"unexpected sequence of control points" );
923 rBuffer.append(
" " );
925 rBuffer.append(
" " );
927 rBuffer.append(
" c" );
934 rBuffer.append(
" l" );
936 if( (rBuffer.getLength() - nBufLen) > 65 )
938 rBuffer.append(
"\n" );
939 nBufLen = rBuffer.getLength();
942 rBuffer.append(
" " );
945 rBuffer.append(
"h\n" );
960 rBuffer.append(
' ' );
962 rBuffer.append(
' ' );
964 rBuffer.append(
" re\n" );
967 sal_uInt32 nPoints = aPoly.
count();
971 sal_uInt32 nBufLen = rBuffer.getLength();
974 rBuffer.append(
" m\n" );
975 for( sal_uInt32
i = 1;
i <= nPoints;
i++ )
980 sal_uInt32 nLastPoint =
i-1;
986 rBuffer.append(
' ' );
988 rBuffer.append(
' ' );
990 rBuffer.append(
" c" );
995 rBuffer.append(
' ' );
997 rBuffer.append(
" y" );
1002 rBuffer.append(
' ' );
1004 rBuffer.append(
" v" );
1009 rBuffer.append(
" l" );
1011 if( (rBuffer.getLength() - nBufLen) > 65 )
1013 rBuffer.append(
"\n" );
1014 nBufLen = rBuffer.getLength();
1017 rBuffer.append(
" " );
1020 rBuffer.append(
"h\n" );
1025 sal_uInt16 nPolygons = rPolyPoly.
Count();
1026 for( sal_uInt16
n = 0;
n < nPolygons;
n++ )
1032 for(
auto const& rPolygon : rPolyPoly)
1041 rBuffer.append(
'-' );
1044 Size aSize( lcl_convert(
m_pWriter->m_aGraphicsStack.front().m_aMapMode,
1052 appendFixedInt(
nValue, rBuffer );
1057 Size aSize( lcl_convert(
m_pWriter->m_aGraphicsStack.front().m_aMapMode,
1060 Size( 1000, 1000 ) ) );
1061 fLength *= pixelToPoint(
static_cast<double>(bVertical ? aSize.
Height() : aSize.
Width()) / 1000.0);
1062 appendDouble( fLength, rBuffer, nPrecision );
1067 if(
LineStyle::Dash == rInfo.GetStyle() && rInfo.GetDashLen() != rInfo.GetDotLen())
1071 if(2 * (rInfo.GetDashCount() + rInfo.GetDotCount()) > 10)
1083 if(css::drawing::LineCap_BUTT != rInfo.GetLineCap())
1091 rBuffer.append(
"[ " );
1092 if( rInfo.GetDashLen() == rInfo.GetDotLen() )
1095 rBuffer.append(
' ' );
1097 rBuffer.append(
' ' );
1101 for(
int n = 0;
n < rInfo.GetDashCount();
n++ )
1104 rBuffer.append(
' ' );
1106 rBuffer.append(
' ' );
1108 for(
int m = 0;
m < rInfo.GetDotCount();
m++ )
1111 rBuffer.append(
' ' );
1113 rBuffer.append(
' ' );
1116 rBuffer.append(
"] 0 d\n" );
1119 if( rInfo.GetWidth() > 1 )
1122 rBuffer.append(
" w\n" );
1124 else if( rInfo.GetWidth() == 0 )
1127 appendDouble( 72.0/
double(
m_pWriter->GetDPIX()), rBuffer );
1128 rBuffer.append(
" w\n" );
1141 rBuffer.append(
"0 " );
1143 rBuffer.append(
" m\n" );
1144 for( sal_Int32
n = 0;
n < nWidth; )
1148 rBuffer.append(
' ' );
1150 rBuffer.append(
' ' );
1153 rBuffer.append(
' ' );
1155 rBuffer.append(
" v " );
1160 rBuffer.append(
' ' );
1162 rBuffer.append(
' ' );
1165 rBuffer.append(
' ' );
1167 rBuffer.append(
" v\n" );
1170 rBuffer.append(
"S\n" );
1175 appendDouble(rMatrix.
get(0), rBuffer);
1176 rBuffer.append(
' ');
1177 appendDouble(rMatrix.
get(1), rBuffer);
1178 rBuffer.append(
' ');
1179 appendDouble(rMatrix.
get(2), rBuffer);
1180 rBuffer.append(
' ');
1181 appendDouble(rMatrix.
get(3), rBuffer);
1182 rBuffer.append(
' ');
1199 const css::uno::Reference< css::beans::XMaterialHolder >& xEnc,
1203 m_aWidgetStyleSettings(
Application::GetSettings().GetStyleSettings()),
1204 m_nCurrentStructElement( 0 ),
1205 m_bEmitStructure( true ),
1208 officecfg::Office::Common::VCL::PDFExportImageCacheSize::
get() ),
1209 m_nCurrentPage( -1 ),
1210 m_nCatalogObject(0),
1211 m_nSignatureObject( -1 ),
1212 m_nSignatureContentOffset( 0 ),
1213 m_nSignatureLastByteRangeNoOffset( 0 ),
1214 m_nResourceDict( -1 ),
1215 m_nFontDictObject( -1 ),
1220 m_aCipher( nullptr ),
1223 m_bEncryptThisStream( false ),
1224 m_nAccessPermissions(0),
1225 m_bIsPDF_A1( false ),
1226 m_bIsPDF_A2( false ),
1227 m_bIsPDF_UA( false ),
1228 m_bIsPDF_A3( false ),
1229 m_rOuterFace( i_rOuterFace )
1247 osl::File::RC aError =
m_aFile.open(osl_File_OpenFlag_Write | osl_File_OpenFlag_Create);
1248 if (aError != osl::File::E_None)
1250 if (aError == osl::File::E_EXIST)
1252 aError =
m_aFile.open(osl_File_OpenFlag_Write);
1253 if (aError == osl::File::E_None)
1257 if (aError != osl::File::E_None)
1266 m_aCipher = rtl_cipher_createARCFOUR( rtl_Cipher_ModeStream );
1283 OSL_ENSURE(
false,
"encryption data failed sanity check, encryption disabled" );
1303 aBuffer.append(
"\n%\303\244\303\274\303\266\303\237\n" );
1369 std::vector< sal_uInt8 > aId;
1380 TimeValue aTVal, aGMT;
1382 osl_getSystemTime(&aGMT);
1383 osl_getLocalTimeFromSystemTime(&aGMT, &aTVal);
1384 osl_getDateTimeFromTimeValue(&aTVal, &aDT);
1386 sal_Int32 nDelta = aTVal.Seconds-aGMT.Seconds;
1388 appendPdfTimeDate(aRet, aDT.Year, aDT.Month, aDT.Day, aDT.Hours, aDT.Minutes, aDT.Seconds, nDelta);
1391 return aRet.makeStringAndClear();
1396 const OString& i_rCString1,
1397 OString& o_rCString2
1400 o_rIdentifier.clear();
1403 OString aInfoValuesOut;
1404 OStringBuffer aID( 1024 );
1405 if( !i_rDocInfo.
Title.isEmpty() )
1407 if( !i_rDocInfo.
Author.isEmpty() )
1409 if( !i_rDocInfo.
Subject.isEmpty() )
1411 if( !i_rDocInfo.
Keywords.isEmpty() )
1413 if( !i_rDocInfo.
Creator.isEmpty() )
1415 if( !i_rDocInfo.
Producer.isEmpty() )
1418 TimeValue aTVal, aGMT;
1420 osl_getSystemTime( &aGMT );
1421 osl_getLocalTimeFromSystemTime( &aGMT, &aTVal );
1422 osl_getDateTimeFromTimeValue( &aTVal, &aDT );
1423 OStringBuffer aCreationMetaDateString(64);
1431 aCreationMetaDateString.append(
static_cast<char>(
'0' + ((aDT.Year/1000)%10)) );
1432 aCreationMetaDateString.append(
static_cast<char>(
'0' + ((aDT.Year/100)%10)) );
1433 aCreationMetaDateString.append(
static_cast<char>(
'0' + ((aDT.Year/10)%10)) );
1434 aCreationMetaDateString.append(
static_cast<char>(
'0' + ((aDT.Year)%10)) );
1435 aCreationMetaDateString.append(
"-" );
1436 aCreationMetaDateString.append(
static_cast<char>(
'0' + ((aDT.Month/10)%10)) );
1437 aCreationMetaDateString.append(
static_cast<char>(
'0' + ((aDT.Month)%10)) );
1438 aCreationMetaDateString.append(
"-" );
1439 aCreationMetaDateString.append(
static_cast<char>(
'0' + ((aDT.Day/10)%10)) );
1440 aCreationMetaDateString.append(
static_cast<char>(
'0' + ((aDT.Day)%10)) );
1441 aCreationMetaDateString.append(
"T" );
1442 aCreationMetaDateString.append(
static_cast<char>(
'0' + ((aDT.Hours/10)%10)) );
1443 aCreationMetaDateString.append(
static_cast<char>(
'0' + ((aDT.Hours)%10)) );
1444 aCreationMetaDateString.append(
":" );
1445 aCreationMetaDateString.append(
static_cast<char>(
'0' + ((aDT.Minutes/10)%10)) );
1446 aCreationMetaDateString.append(
static_cast<char>(
'0' + ((aDT.Minutes)%10)) );
1447 aCreationMetaDateString.append(
":" );
1448 aCreationMetaDateString.append(
static_cast<char>(
'0' + ((aDT.Seconds/10)%10)) );
1449 aCreationMetaDateString.append(
static_cast<char>(
'0' + ((aDT.Seconds)%10)) );
1451 sal_uInt32 nDelta = 0;
1452 if( aGMT.Seconds > aTVal.Seconds )
1454 nDelta = aGMT.Seconds-aTVal.Seconds;
1455 aCreationMetaDateString.append(
"-" );
1457 else if( aGMT.Seconds < aTVal.Seconds )
1459 nDelta = aTVal.Seconds-aGMT.Seconds;
1460 aCreationMetaDateString.append(
"+" );
1464 aCreationMetaDateString.append(
"Z" );
1469 aCreationMetaDateString.append(
static_cast<char>(
'0' + ((nDelta/36000)%10)) );
1470 aCreationMetaDateString.append(
static_cast<char>(
'0' + ((nDelta/3600)%10)) );
1471 aCreationMetaDateString.append(
":" );
1472 aCreationMetaDateString.append(
static_cast<char>(
'0' + ((nDelta/600)%6)) );
1473 aCreationMetaDateString.append(
static_cast<char>(
'0' + ((nDelta/60)%10)) );
1475 aID.append( i_rCString1.getStr(), i_rCString1.getLength() );
1477 aInfoValuesOut = aID.makeStringAndClear();
1478 o_rCString2 = aCreationMetaDateString.makeStringAndClear();
1481 aDigest.
update(
reinterpret_cast<unsigned char const*
>(&aGMT),
sizeof(aGMT));
1482 aDigest.
update(
reinterpret_cast<unsigned char const*
>(aInfoValuesOut.getStr()), aInfoValuesOut.getLength());
1484 o_rIdentifier = aDigest.
finalize();
1494 rOutBuffer.append(
"<" );
1498 sal_Int32 nLen = rInString.getLength();
1502 sal_Int32 nChars = 2 + (nLen * 2);
1507 for(
int i = 0;
i < nLen;
i++ )
1510 *pCopy++ =
static_cast<sal_uInt8>( aUnChar >> 8 );
1511 *pCopy++ =
static_cast<sal_uInt8>( aUnChar & 255 );
1516 for(
int i = 0;
i < nChars;
i++)
1521 rOutBuffer.append(
">" );
1526 rOutBuffer.append(
"(" );
1527 sal_Int32 nChars = rInString.size();
1535 appendLiteralString(
reinterpret_cast<char*
>(
m_vEncryptionBuffer.data()), nChars, rOutBuffer );
1538 appendLiteralString( rInString.data(), nChars , rOutBuffer );
1539 rOutBuffer.append(
")" );
1545 sal_Int32 nLen = aBufferString.getLength();
1546 OStringBuffer
aBuf( nLen );
1547 const char* pT = aBufferString.getStr();
1549 for( sal_Int32
i = 0;
i < nLen;
i++, pT++ )
1551 if( (*pT & 0x80) == 0 )
1556 appendHex( *pT,
aBuf );
1560 aBufferString =
aBuf.makeStringAndClear();
1568 OString aLine = OString::Concat(
"% ") + pComment +
"\n";
1576 sal_uInt64 nEndPos = pStream->
TellEnd();
1578 ZCodec aCodec( 0x4000, 0x4000 );
1583 nEndPos = aStream.
Tell();
1598 m_pCodec = std::make_unique<ZCodec>( 0x4000, 0x4000 );
1629 pBuffer, sal::static_int_cast<std::size_t>(nBytes));
1633 sal_uInt64 nWritten;
1648 pBuffer,
static_cast<sal_Size
>(nBytes),
1653 m_DocDigest.
update(
static_cast<unsigned char const*
>(pWriteBuffer),
static_cast<sal_uInt32
>(nBytes));
1655 if (
m_aFile.write(pWriteBuffer, nBytes, nWritten) != osl::File::E_None)
1658 if( nWritten != nBytes )
1665 return nWritten == nBytes;
1672 m_aPages.emplace_back(
this, nPageWidth, nPageHeight, eOrientation );
1674 sal_Int32 nUserUnit =
m_aPages.back().m_nUserUnit;
1685 OStringBuffer
aBuf( 16 );
1687 aBuf.append(
" w\n" );
1702 OSL_FAIL(
"redirection across pages !!!" );
1725 if( ! bitmap.m_aBitmap.IsEmpty() )
1733 if( jpeg.m_pStream )
1736 jpeg.m_pStream.reset();
1742 if( item.m_pContentStream )
1745 item.m_pContentStream.reset();
1762 sal_uInt64 nOffset = ~0
U;
1763 osl::File::RC aError =
m_aFile.getPos(nOffset);
1764 SAL_WARN_IF( aError != osl::File::E_None,
"vcl.pdfwriter",
"could not register object" );
1765 if (aError != osl::File::E_None)
1771 return aError == osl::File::E_None;
1774#define CHECK_RETURN( x ) if( !(x) ) return 0
1775#define CHECK_RETURN2( x ) if( !(x) ) return
1781 OStringBuffer aLine( 1024 );
1783 aLine.append( nObject );
1784 aLine.append(
" 0 obj\n"
1787 for( sal_Int32
n = 0;
n < nTreeItems;
n++ )
1790 aLine.append(
' ' );
1792 aLine.append(
"\n" );
1794 aLine.append(
"]>>\nendobj\n\n" );
1803 static std::map< PDFWriter::StructAttribute, const char* > aAttributeStrings;
1805 if( aAttributeStrings.empty() )
1829 std::map< PDFWriter::StructAttribute, const char* >::const_iterator it =
1830 aAttributeStrings.find( eAttr );
1832 if( it == aAttributeStrings.end() )
1833 SAL_INFO(
"vcl.pdfwriter",
"invalid PDFWriter::StructAttribute " << eAttr);
1835 return it != aAttributeStrings.end() ? it->second :
"";
1840 static std::map< PDFWriter::StructAttributeValue, const char* > aValueStrings;
1842 if( aValueStrings.empty() )
1875 std::map< PDFWriter::StructAttributeValue, const char* >::const_iterator it =
1876 aValueStrings.find( eVal );
1878 if( it == aValueStrings.end() )
1879 SAL_INFO(
"vcl.pdfwriter",
"invalid PDFWriter::StructAttributeValue " << eVal);
1881 return it != aValueStrings.end() ? it->second :
"";
1886 o_rLine.append(
"/" );
1891 o_rLine.append(
"/" );
1897 o_rLine.append(
" " );
1899 appendFixedInt( i_rVal.
nValue, o_rLine );
1901 o_rLine.append( i_rVal.
nValue );
1903 o_rLine.append(
"\n" );
1909 OStringBuffer aLayout(256), aList(64), aTable(64);
1922 sal_Int32 nLink =
attribute.second.nValue;
1923 std::map< sal_Int32, sal_Int32 >::const_iterator link_it =
1926 nLink = link_it->second;
1930 OString aStructParentEntry =
1940 OString::number( nRefObject ) +
1942 "<</Type/OBJR/Obj " +
1943 OString::number(
m_aLinks[ nLink ].m_nObject ) +
1949 i_rEle.
m_aKids.emplace_back( nRefObject );
1953 OSL_FAIL(
"unresolved link id for Link structure" );
1954 SAL_INFO(
"vcl.pdfwriter",
"unresolved link id " << nLink <<
" for Link structure");
1957 OString aLine =
"unresolved link id " +
1958 OString::number( nLink ) +
1959 " for Link structure";
1969 aLayout.append(
"/BBox[" );
1971 aLayout.append(
" " );
1972 appendFixedInt( i_rEle.
m_aBBox.
Top(), aLayout );
1973 aLayout.append(
" " );
1975 aLayout.append(
" " );
1977 aLayout.append(
"]\n" );
1980 std::vector< sal_Int32 > aAttribObjects;
1981 if( !aLayout.isEmpty() )
1986 OStringBuffer aObj( 64 );
1987 aObj.append( aAttribObjects.back() );
1988 aObj.append(
" 0 obj\n"
1990 aLayout.append(
">>\nendobj\n\n" );
1992 writeBuffer( aLayout.getStr(), aLayout.getLength() );
1995 if( !aList.isEmpty() )
2000 OStringBuffer aObj( 64 );
2001 aObj.append( aAttribObjects.back() );
2002 aObj.append(
" 0 obj\n"
2004 aList.append(
">>\nendobj\n\n" );
2009 if( !aTable.isEmpty() )
2014 OStringBuffer aObj( 64 );
2015 aObj.append( aAttribObjects.back() );
2016 aObj.append(
" 0 obj\n"
2018 aTable.append(
">>\nendobj\n\n" );
2020 writeBuffer( aTable.getStr(), aTable.getLength() );
2024 OStringBuffer aRet( 64 );
2025 if( aAttribObjects.size() > 1 )
2026 aRet.append(
" [" );
2027 for (
auto const& attrib : aAttribObjects)
2030 aRet.append( attrib );
2031 aRet.append(
" 0 R" );
2033 if( aAttribObjects.size() > 1 )
2034 aRet.append(
" ]" );
2035 return aRet.makeStringAndClear();
2058 OSL_FAIL(
"PDFWriterImpl::emitStructure: invalid child structure element" );
2059 SAL_INFO(
"vcl.pdfwriter",
"PDFWriterImpl::emitStructure: invalid child structure element with id " << child);
2065 OSL_FAIL(
"PDFWriterImpl::emitStructure: invalid child structure id" );
2066 SAL_INFO(
"vcl.pdfwriter",
"PDFWriterImpl::emitStructure: invalid child structure id " << child);
2070 OStringBuffer aLine( 512 );
2072 aLine.append(
" 0 obj\n"
2074 sal_Int32 nParentTree = -1;
2079 aLine.append(
"/StructTreeRoot\n" );
2080 aLine.append(
"/ParentTree " );
2081 aLine.append( nParentTree );
2082 aLine.append(
" 0 R\n" );
2085 aLine.append(
"/RoleMap<<" );
2088 aLine.append(
'/' );
2089 aLine.append(role.first);
2090 aLine.append(
'/' );
2091 aLine.append( role.second );
2092 aLine.append(
'\n' );
2094 aLine.append(
">>\n" );
2099 aLine.append(
"/StructElem\n"
2108 aLine.append(
" 0 R\n"
2111 aLine.append(
" 0 R\n" );
2114 aLine.append(
"/ActualText" );
2116 aLine.append(
"\n" );
2120 aLine.append(
"/Alt" );
2122 aLine.append(
"\n" );
2128 if( !aAttribs.isEmpty() )
2130 aLine.append(
"/A" );
2131 aLine.append( aAttribs );
2132 aLine.append(
"\n" );
2135 if( !rEle.
m_aLocale.Language.isEmpty() )
2144 OUString aLanguage, aScript, aCountry;
2146 if (!aLanguage.isEmpty())
2148 OUStringBuffer aLocBuf( 16 );
2149 aLocBuf.append( aLanguage );
2150 if( !aCountry.isEmpty() )
2152 aLocBuf.append(
'-' );
2153 aLocBuf.append( aCountry );
2155 aLine.append(
"/Lang" );
2157 aLine.append(
"\n" );
2163 aLine.append(
"/K[" );
2164 for (
auto const& kid : rEle.
m_aKids)
2166 if( kid.nMCID == -1 )
2168 aLine.append( kid.nObject );
2169 aLine.append(
" 0 R" );
2170 aLine.append( ( (
i & 15) == 15 ) ?
"\n" :
" " );
2176 aLine.append( kid.nMCID );
2177 aLine.append(
" " );
2181 aLine.append(
"<</Type/MCR/Pg " );
2182 aLine.append( kid.nObject );
2183 aLine.append(
" 0 R /MCID " );
2184 aLine.append( kid.nMCID );
2185 aLine.append(
">>\n" );
2190 aLine.append(
"]\n" );
2192 aLine.append(
">>\nendobj\n\n" );
2213 OStringBuffer aTilingObj( 1024 );
2217 SAL_WARN_IF( !tiling.m_pTilingStream,
"vcl.pdfwriter",
"tiling without stream" );
2218 if( ! tiling.m_pTilingStream )
2221 aTilingObj.setLength( 0 );
2228 sal_Int32 nX =
static_cast<sal_Int32
>(tiling.m_aRectangle.Left());
2229 sal_Int32 nY =
static_cast<sal_Int32
>(tiling.m_aRectangle.Top());
2230 sal_Int32 nW =
static_cast<sal_Int32
>(tiling.m_aRectangle.GetWidth());
2231 sal_Int32 nH =
static_cast<sal_Int32
>(tiling.m_aRectangle.GetHeight());
2232 if( tiling.m_aCellSize.Width() == 0 )
2233 tiling.m_aCellSize.setWidth( nW );
2234 if( tiling.m_aCellSize.Height() == 0 )
2235 tiling.m_aCellSize.setHeight( nH );
2238 sal_uInt64
const nTilingStreamSize = tiling.m_pTilingStream->TellEnd();
2242 aTilingObj.append( tiling.m_nObject );
2243 aTilingObj.append(
" 0 obj\n" );
2244 aTilingObj.append(
"<</Type/Pattern/PatternType 1\n"
2248 appendFixedInt( nX, aTilingObj );
2249 aTilingObj.append(
' ' );
2250 appendFixedInt( nY, aTilingObj );
2251 aTilingObj.append(
' ' );
2252 appendFixedInt( nX+nW, aTilingObj );
2253 aTilingObj.append(
' ' );
2254 appendFixedInt( nY+nH, aTilingObj );
2255 aTilingObj.append(
"]\n"
2257 appendFixedInt( tiling.m_aCellSize.Width(), aTilingObj );
2258 aTilingObj.append(
"\n"
2260 appendFixedInt( tiling.m_aCellSize.Height(), aTilingObj );
2261 aTilingObj.append(
"\n" );
2262 if( tiling.m_aTransform.matrix[0] != 1.0 ||
2263 tiling.m_aTransform.matrix[1] != 0.0 ||
2264 tiling.m_aTransform.matrix[3] != 0.0 ||
2265 tiling.m_aTransform.matrix[4] != 1.0 ||
2266 tiling.m_aTransform.matrix[2] != 0.0 ||
2267 tiling.m_aTransform.matrix[5] != 0.0 )
2269 aTilingObj.append(
"/Matrix [" );
2271 appendDouble( tiling.m_aTransform.matrix[0], aTilingObj );
2272 aTilingObj.append(
' ' );
2273 appendDouble( tiling.m_aTransform.matrix[1], aTilingObj );
2274 aTilingObj.append(
' ' );
2275 appendDouble( tiling.m_aTransform.matrix[3], aTilingObj );
2276 aTilingObj.append(
' ' );
2277 appendDouble( tiling.m_aTransform.matrix[4], aTilingObj );
2278 aTilingObj.append(
' ' );
2279 appendDouble( tiling.m_aTransform.matrix[2], aTilingObj );
2280 aTilingObj.append(
' ' );
2281 appendDouble( tiling.m_aTransform.matrix[5], aTilingObj );
2282 aTilingObj.append(
"]\n" );
2284 aTilingObj.append(
"/Resources" );
2287 aTilingObj.append(
"/Filter/FlateDecode" );
2288 aTilingObj.append(
"/Length " );
2289 aTilingObj.append(
static_cast<sal_Int32
>(nTilingStreamSize) );
2290 aTilingObj.append(
">>\nstream\n" );
2292 if ( !
writeBuffer( aTilingObj.getStr(), aTilingObj.getLength() ) )
return false;
2294 bool written =
writeBuffer( tiling.m_pTilingStream->GetData(), nTilingStreamSize );
2295 tiling.m_pTilingStream.reset();
2299 aTilingObj.setLength( 0 );
2300 aTilingObj.append(
"\nendstream\nendobj\n\n" );
2301 if ( !
writeBuffer( aTilingObj.getStr(), aTilingObj.getLength() ) )
return false;
2312 OStringBuffer aLine( 1024 );
2314 if( nFontObject <= 0 )
2317 aLine.append( nFontObject );
2318 aLine.append(
" 0 obj\n"
2319 "<</Type/Font/Subtype/Type1/BaseFont/" );
2320 appendName( rBuildinFont.
m_pPSName, aLine );
2321 aLine.append(
"\n" );
2322 if( rBuildinFont.
m_eCharSet == RTL_TEXTENCODING_MS_1252 )
2323 aLine.append(
"/Encoding/WinAnsiEncoding\n" );
2324 aLine.append(
">>\nendobj\n\n" );
2332int XUnits(
int nUPEM,
int n) {
return (n * 1000) / nUPEM; }
2337 std::map< sal_Int32, sal_Int32 > aRet;
2350 sal_Int32 pWidths[256] = { 0 };
2353 for(
sal_Ucs c = 32; c < 256; c++ )
2362 std::vector<sal_uInt8>
aBuffer;
2367 if( nFontDescriptor )
2373 OStringBuffer aLine( 1024 );
2374 aLine.append( nObject );
2375 aLine.append(
" 0 obj\n"
2376 "<</Type/Font/Subtype/TrueType" );
2377 aLine.append(
"/BaseFont/" );
2379 aLine.append(
"\n" );
2381 aLine.append(
"/Encoding/WinAnsiEncoding\n" );
2382 aLine.append(
"/FirstChar 32 /LastChar 255\n"
2384 for(
int i = 32;
i < 256;
i++ )
2386 aLine.append( pWidths[
i] );
2387 aLine.append( ((
i&15) == 15) ?
"\n" :
" " );
2390 "/FontDescriptor " );
2391 aLine.append( nFontDescriptor );
2392 aLine.append(
" 0 R>>\n"
2405uint32_t fillSubsetArrays(
const FontEmit& rSubset,
sal_GlyphId* pGlyphIds, sal_Int32* pWidths,
2406 sal_uInt8* pEncoding, sal_Int32* pEncToUnicodeIndex,
2407 sal_Int32* pCodeUnitsPerGlyph, std::vector<sal_Ucs>& rCodeUnits,
2408 sal_Int32& nToUnicodeStream)
2410 rCodeUnits.reserve(256);
2415 uint32_t nGlyphs = 1;
2418 sal_uInt8 nEnc = item.second.getGlyphId();
2420 SAL_WARN_IF(pGlyphIds[nEnc] != 0 || pEncoding[nEnc] != 0,
"vcl.pdfwriter",
2424 pGlyphIds[nEnc] = item.first;
2425 pEncoding[nEnc] = nEnc;
2426 pEncToUnicodeIndex[nEnc] =
static_cast<sal_Int32
>(rCodeUnits.size());
2427 pCodeUnitsPerGlyph[nEnc] = item.second.countCodes();
2428 pWidths[nEnc] = item.second.getGlyphWidth();
2429 for (sal_Int32 n = 0;
n < pCodeUnitsPerGlyph[nEnc];
n++)
2430 rCodeUnits.push_back(item.second.getCode(n));
2431 if (item.second.getCode(0))
2432 nToUnicodeStream = 1;
2436 OSL_FAIL(
"too many glyphs for subset");
2445 std::map<sal_Int32, sal_Int32>& rFontIDToObject)
2455 std::vector<sal_uInt8>
aBuffer;
2461 sal_Int32 pWidths[256];
2463 sal_Int32 pEncToUnicodeIndex[256] = {};
2464 sal_Int32 pCodeUnitsPerGlyph[256] = {};
2465 std::vector<sal_Ucs> aCodeUnits;
2466 sal_Int32 nToUnicodeStream = 0;
2469 auto nGlyphs = fillSubsetArrays(rSubset, pGlyphIds, pWidths, pEncoding, pEncToUnicodeIndex,
2470 pCodeUnitsPerGlyph, aCodeUnits, nToUnicodeStream);
2473 sal_Int32 nFontDescriptor = 0;
2477 if (nToUnicodeStream)
2479 pEncToUnicodeIndex, nGlyphs);
2486 OStringBuffer aLine(1024);
2487 aLine.append(nFontObject);
2488 aLine.append(
" 0 obj\n"
2489 "<</Type/Font/Subtype/Type3/Name/");
2490 appendName(aSubsetInfo.
m_aPSName, aLine);
2492 aLine.append(
"\n/FontBBox[");
2501 aLine.append(
"]\n");
2504 aLine.append(
"/FontMatrix[");
2505 aLine.append(nScale);
2506 aLine.append(
" 0 0 ");
2507 aLine.append(nScale);
2508 aLine.append(
" 0 0]\n");
2510 sal_Int32 pGlyphStreams[256] = {};
2511 aLine.append(
"/CharProcs<<\n");
2512 for (
auto i = 1u;
i < nGlyphs;
i++)
2518 aLine.append(nStream);
2519 aLine.append(
" 0 R\n");
2520 pGlyphStreams[
i] = nStream;
2522 aLine.append(
">>\n");
2524 aLine.append(
"/Encoding<</Type/Encoding/Differences[1");
2525 for (
auto i = 1u;
i < nGlyphs;
i++)
2526 aLine.append(
" /" + pFace->
GetGlyphName(pGlyphIds[
i],
true));
2527 aLine.append(
"]>>\n");
2529 aLine.append(
"/FirstChar 0\n"
2531 aLine.append(OString::number(nGlyphs));
2534 aLine.append(
"/Widths[");
2535 for (
auto i = 0
u;
i < nGlyphs;
i++)
2537 aLine.append(pWidths[
i]);
2540 aLine.append(
"]\n");
2544 aLine.append(
"/FontDescriptor ");
2545 aLine.append(nFontDescriptor);
2546 aLine.append(
" 0 R\n");
2550 aLine.append(
"/Resources ");
2551 aLine.append(nResources);
2552 aLine.append(
" 0 R\n");
2554 if (nToUnicodeStream)
2556 aLine.append(
"/ToUnicode ");
2557 aLine.append(nToUnicodeStream);
2558 aLine.append(
" 0 R\n");
2564 if (!
writeBuffer(aLine.getStr(), aLine.getLength()))
2567 std::set<sal_Int32> aUsedFonts;
2568 std::list<BitmapEmit> aUsedBitmaps;
2569 std::map<sal_uInt8, sal_Int32> aUsedAlpha;
2571 std::list<StreamRedirect> aOutputStreams;
2573 for (
auto i = 1u;
i < nGlyphs;
i++)
2575 auto nStream = pGlyphStreams[
i];
2578 OStringBuffer aContents(1024);
2579 aContents.append(pWidths[
i]);
2580 aContents.append(
" 0 d0\n");
2582 const auto& rGlyph = rSubset.
m_aMapping.find(pGlyphIds[
i])->second;
2583 const auto& rLayers = rGlyph.getColorLayers();
2584 for (
const auto& rLayer : rLayers)
2586 aUsedFonts.insert(rLayer.m_nFontID);
2588 aContents.append(
"q ");
2590 if (rLayer.m_nColorIndex != 0xFFFF)
2592 auto& rPalette = rColorPalettes[0];
2593 auto aColor(rPalette[rLayer.m_nColorIndex]);
2595 aContents.append(
" ");
2596 if (aColor.GetAlpha() != 0xFF
2599 auto nAlpha = aColor.GetAlpha();
2600 OStringBuffer
aName(16);
2602 appendHex(nAlpha,
aName);
2604 aContents.append(
"/" +
aName +
" gs ");
2606 if (aUsedAlpha.find(nAlpha) == aUsedAlpha.end())
2609 aUsedAlpha[nAlpha] = nObject;
2611 nObject, aResourceDict, aOutputStreams);
2615 aContents.append(
"BT ");
2616 aContents.append(
"/F" + OString::number(rLayer.m_nFontID) +
" ");
2617 aContents.append(OString::number(pFace->
UnitsPerEm()) +
" Tf ");
2618 aContents.append(
"<");
2619 appendHex(rLayer.m_nSubsetGlyphID, aContents);
2620 aContents.append(
">Tj ");
2621 aContents.append(
"ET ");
2622 aContents.append(
"Q\n");
2626 const auto& rBitmapData = rGlyph.getColorBitmap(aRect);
2627 if (!rBitmapData.empty())
2629 SvMemoryStream aStream(
const_cast<uint8_t*
>(rBitmapData.data()), rBitmapData.size(),
2633 aUsedBitmaps, aResourceDict, aOutputStreams);
2635 auto nObject = aBitmapEmit.m_aReferenceXObject.getObject();
2636 aContents.append(
"q ");
2637 aContents.append(aRect.
GetWidth());
2638 aContents.append(
" 0 0 ");
2640 aContents.append(
" ");
2641 aContents.append(aRect.
getX());
2642 aContents.append(
" ");
2643 aContents.append(aRect.
getY());
2644 aContents.append(
" cm ");
2645 aContents.append(
"/Im");
2646 aContents.append(nObject);
2647 aContents.append(
" Do Q\n");
2650 const auto& rOutline = rGlyph.getOutline();
2651 if (rOutline.count())
2654 aContents.append(
"q 10 0 0 10 0 ");
2655 appendDouble(
m_aPages.back().getHeight() * -10, aContents, 3);
2656 aContents.append(
" cm\n");
2657 m_aPages.back().appendPolyPolygon(rOutline, aContents);
2658 aContents.append(
"f\n");
2659 aContents.append(
"Q\n");
2663 aLine.append(nStream);
2664 aLine.append(
" 0 obj\n<</Length ");
2665 aLine.append(aContents.getLength());
2666 aLine.append(
">>\nstream\n");
2667 if (!
writeBuffer(aLine.getStr(), aLine.getLength()))
2669 if (!
writeBuffer(aContents.getStr(), aContents.getLength()))
2672 aLine.append(
"endstream\nendobj\n\n");
2673 if (!
writeBuffer(aLine.getStr(), aLine.getLength()))
2680 aLine.append(nFontDict);
2681 aLine.append(
" 0 obj\n<<");
2682 for (
auto nFontID : aUsedFonts)
2685 aLine.append(nFontID);
2687 aLine.append(rFontIDToObject[nFontID]);
2688 aLine.append(
" 0 R");
2690 aLine.append(
">>\nendobj\n\n");
2693 if (!
writeBuffer(aLine.getStr(), aLine.getLength()))
2697 if (!aUsedAlpha.empty())
2699 for (
const auto & [ nAlpha, nObject ] : aUsedAlpha)
2702 aLine.append(nObject);
2703 aLine.append(
" 0 obj\n<<");
2706 aLine.append(
"/CA 1.0/ca 1.0");
2711 aLine.append(
"/CA ");
2712 appendDouble(nAlpha / 255., aLine);
2713 aLine.append(
"/ca ");
2714 appendDouble(nAlpha / 255., aLine);
2716 aLine.append(
">>\nendobj\n\n");
2719 if (!
writeBuffer(aLine.getStr(), aLine.getLength()))
2725 for (
auto& aBitmap : aUsedBitmaps)
2730 aLine.append(nResources);
2731 aLine.append(
" 0 obj\n");
2732 aResourceDict.
append(aLine, nFontDict);
2733 aLine.append(
"endobj\n\n");
2736 if (!
writeBuffer(aLine.getStr(), aLine.getLength()))
2739 rFontIDToObject[rSubset.
m_nFontID] = nFontObject;
2749 if( !pFontBytes || (nByteLen < 0) )
2751 const unsigned char* pPtr = pFontBytes;
2752 const unsigned char* pEnd = pFontBytes + nByteLen;
2754 for(
int & rSegmentLength : rSegmentLengths) {
2756 if( pPtr+6 >= pEnd )
2758 if( (pPtr[0] != 0x80) || (pPtr[1] >= 0x03) )
2760 const int nLen = (pPtr[5]<<24) + (pPtr[4]<<16) + (pPtr[3]<<8) + pPtr[2];
2763 rSegmentLength = nLen;
2768 if( pPtr+2 >= pEnd )
2770 if( (pPtr[0] != 0x80) || (pPtr[1] != 0x03) )
2776static void appendSubsetName(
int nSubsetID, std::u16string_view rPSName, OStringBuffer& rBuffer )
2780 for(
int i = 0;
i < 6;
i++ )
2782 int nOffset = nSubsetID % 26;
2784 rBuffer.append(
static_cast<char>(
'A'+nOffset) );
2786 rBuffer.append(
'+' );
2788 appendName( rPSName, rBuffer );
2793 const sal_Int32* pCodeUnitsPerGlyph,
2794 const sal_Int32* pEncToUnicodeIndex,
2798 for (
auto n = 0
u;
n < nGlyphs; ++
n)
2799 if( pCodeUnits[pEncToUnicodeIndex[
n]] && pCodeUnitsPerGlyph[
n] )
2808 OStringBuffer aContents( 1024 );
2810 "/CIDInit/ProcSet findresource begin\n"
2813 "/CIDSystemInfo<<\n"
2814 "/Registry (Adobe)\n"
2818 "/CMapName/Adobe-Identity-UCS def\n"
2820 "1 begincodespacerange\n"
2822 "endcodespacerange\n"
2825 for (
auto n = 0
u;
n < nGlyphs; ++
n)
2827 if( pCodeUnits[pEncToUnicodeIndex[
n]] && pCodeUnitsPerGlyph[
n] )
2829 if( (
nCount % 100) == 0 )
2832 aContents.append(
"endbfchar\n" );
2833 aContents.append(
static_cast<sal_Int32
>(std::min(nMapped-
nCount, 100)) );
2834 aContents.append(
" beginbfchar\n" );
2836 aContents.append(
'<' );
2837 appendHex(
static_cast<sal_Int8>(pEncoding[
n]), aContents );
2838 aContents.append(
"> <" );
2840 sal_Int32
nIndex = pEncToUnicodeIndex[
n];
2841 for( sal_Int32 j = 0; j < pCodeUnitsPerGlyph[
n]; j++ )
2843 appendHex(
static_cast<sal_Int8>(pCodeUnits[
nIndex + j] / 256), aContents );
2844 appendHex(
static_cast<sal_Int8>(pCodeUnits[
nIndex + j] & 255), aContents );
2846 aContents.append(
">\n" );
2850 aContents.append(
"endbfchar\n"
2852 "CMapName currentdict /CMap defineresource pop\n"
2858 ZCodec aCodec( 0x4000, 0x4000 );
2860 aCodec.
Write( aStream,
reinterpret_cast<const sal_uInt8*
>(aContents.getStr()), aContents.getLength() );
2866 emitComment(
"PDFWriterImpl::createToUnicodeCMap" );
2868 OStringBuffer aLine( 40 );
2870 aLine.append( nStream );
2871 aLine.append(
" 0 obj\n<</Length " );
2875 nLen =
static_cast<sal_Int32
>(aStream.
Tell());
2877 aLine.append( nLen );
2878 aLine.append(
"/Filter/FlateDecode" );
2881 aLine.append( aContents.getLength() );
2882 aLine.append(
">>\nstream\n" );
2894 aLine.setLength( 0 );
2895 aLine.append(
"\nendstream\n"
2903 OStringBuffer aLine( 1024 );
2907 sal_Int32 nFontFlags = (1<<2);
2909 nFontFlags |= (1 << 6);
2913 nFontFlags |= (1 << 3);
2915 nFontFlags |= (1 << 1);
2919 aLine.setLength( 0 );
2920 aLine.append( nFontDescriptor );
2921 aLine.append(
" 0 obj\n"
2922 "<</Type/FontDescriptor/FontName/" );
2926 aLine.append( nFontFlags );
2931 aLine.append(
' ' );
2933 aLine.append(
' ' );
2935 aLine.append(
' ' );
2937 aLine.append(
"]/ItalicAngle " );
2939 aLine.append(
"-30" );
2941 aLine.append(
"0" );
2944 aLine.append(
static_cast<sal_Int32
>(rInfo.
m_nAscent) );
2947 aLine.append(
static_cast<sal_Int32
>(-rInfo.
m_nDescent) );
2950 aLine.append(
static_cast<sal_Int32
>(rInfo.
m_nCapHeight) );
2957 aLine.append(
"/FontFile" );
2961 aLine.append(
'2' );
2968 OSL_FAIL(
"unknown fonttype in PDF font descriptor" );
2971 aLine.append(
' ' );
2972 aLine.append( nFontStream );
2973 aLine.append(
" 0 R\n" );
2975 aLine.append(
">>\n"
2979 return nFontDescriptor;
2987 rDict.append(
' ' );
2988 rDict.append( item.second );
2989 rDict.append(
" 0 R" );
2995 OStringBuffer aLine( 1024 );
2997 std::map< sal_Int32, sal_Int32 > aFontIDToObject;
3001 for (
auto & s_subset :subset.second.m_aSubsets)
3004 sal_Int32 pWidths[ 256 ];
3006 sal_Int32 pEncToUnicodeIndex[ 256 ] = {};
3007 sal_Int32 pCodeUnitsPerGlyph[ 256 ] = {};
3008 std::vector<sal_Ucs> aCodeUnits;
3009 sal_Int32 nToUnicodeStream = 0;
3012 auto nGlyphs = fillSubsetArrays(s_subset, pGlyphIds, pWidths, pEncoding, pEncToUnicodeIndex,
3013 pCodeUnitsPerGlyph, aCodeUnits, nToUnicodeStream);
3015 std::vector<sal_uInt8>
aBuffer;
3017 const auto* pFace = subset.first;
3018 if (pFace->CreateFontSubset(
aBuffer, pGlyphIds, pEncoding, nGlyphs, aSubsetInfo))
3028 aLine.setLength( 0 );
3029 aLine.append( nFontStream );
3030 aLine.append(
" 0 obj\n"
3032 aLine.append( nStreamLengthObject );
3034 aLine.append(
" 0 R"
3035 "/Filter/FlateDecode"
3038 aLine.append(
" 0 R"
3041 sal_uInt64 nStartPos = 0;
3044 aLine.append(
static_cast<sal_Int32
>(
aBuffer.size()) );
3046 aLine.append(
">>\n"
3048 if ( !
writeBuffer( aLine.getStr(), aLine.getLength() ) )
return false;
3049 if ( osl::File::E_None !=
m_aFile.getPos(nStartPos) )
return false;
3060 OSL_FAIL(
"PDFWriterImpl does not support CFF-font subsets yet!" );
3069 aLine.append(
static_cast<sal_Int32
>(aSegmentLengths[0]) );
3070 aLine.append(
"/Length2 " );
3071 aLine.append(
static_cast<sal_Int32
>(aSegmentLengths[1]) );
3072 aLine.append(
"/Length3 " );
3073 aLine.append(
static_cast<sal_Int32
>(aSegmentLengths[2]) );
3075 aLine.append(
">>\n"
3077 if ( !
writeBuffer( aLine.getStr(), aLine.getLength() ) )
return false;
3078 if ( osl::File::E_None !=
m_aFile.getPos(nStartPos) )
return false;
3084 if ( !
writeBuffer( &
aBuffer[12] + aSegmentLengths[0], aSegmentLengths[1] ) )
return false;
3085 if ( !
writeBuffer( &
aBuffer[18] + aSegmentLengths[0] + aSegmentLengths[1], aSegmentLengths[2] ) )
return false;
3089 SAL_INFO(
"vcl.pdfwriter",
"PDF: CreateFontSubset result in not yet supported format=" <<
static_cast<int>(aSubsetInfo.
m_nFontType));
3090 aLine.append(
"0 >>\nstream\n" );
3096 sal_uInt64 nEndPos = 0;
3097 if ( osl::File::E_None !=
m_aFile.getPos(nEndPos) )
return false;
3099 aLine.setLength( 0 );
3100 aLine.append(
"\nendstream\nendobj\n\n" );
3101 if ( !
writeBuffer( aLine.getStr(), aLine.getLength() ) )
return false;
3104 if ( !
updateObject( nStreamLengthObject ) )
return false;
3105 aLine.setLength( 0 );
3106 aLine.append( nStreamLengthObject );
3107 aLine.append(
" 0 obj\n" );
3108 aLine.append(
static_cast<sal_Int64
>(nEndPos-nStartPos) );
3109 aLine.append(
"\nendobj\n\n" );
3110 if ( !
writeBuffer( aLine.getStr(), aLine.getLength() ) )
return false;
3113 sal_Int32 nFontDescriptor =
emitFontDescriptor( subset.first, aSubsetInfo, s_subset.m_nFontID, nFontStream );
3115 if( nToUnicodeStream )
3116 nToUnicodeStream =
createToUnicodeCMap( pEncoding, aCodeUnits.data(), pCodeUnitsPerGlyph, pEncToUnicodeIndex, nGlyphs );
3120 aLine.setLength( 0 );
3121 aLine.append( nFontObject );
3123 aLine.append(
" 0 obj\n" );
3125 "<</Type/Font/Subtype/Type1/BaseFont/" :
3126 "<</Type/Font/Subtype/TrueType/BaseFont/" );
3131 aLine.append(
static_cast<sal_Int32
>(nGlyphs-1) );
3134 for (
auto i = 0
u;
i < nGlyphs;
i++)
3136 aLine.append( pWidths[
i ] );
3137 aLine.append( ((
i & 15) == 15) ?
"\n" :
" " );
3140 "/FontDescriptor " );
3141 aLine.append( nFontDescriptor );
3142 aLine.append(
" 0 R\n" );
3143 if( nToUnicodeStream )
3145 aLine.append(
"/ToUnicode " );
3146 aLine.append( nToUnicodeStream );
3147 aLine.append(
" 0 R\n" );
3149 aLine.append(
">>\n"
3151 if ( !
writeBuffer( aLine.getStr(), aLine.getLength() ) )
return false;
3153 aFontIDToObject[ s_subset.m_nFontID ] = nFontObject;
3157 OStringBuffer aErrorComment( 256 );
3158 aErrorComment.append(
"CreateFontSubset failed for font \"" );
3159 aErrorComment.append(
OUStringToOString( pFace->GetFamilyName(), RTL_TEXTENCODING_UTF8 ) );
3160 aErrorComment.append(
'\"' );
3162 aErrorComment.append(
" italic" );
3164 aErrorComment.append(
" oblique" );
3165 aErrorComment.append(
" weight=" );
3166 aErrorComment.append( sal_Int32(pFace->GetWeight()) );
3175 std::map< sal_Int32, sal_Int32 > aObjects =
emitSystemFont( systemFont.first, systemFont.second );
3176 for (
auto const& item : aObjects)
3178 if ( !item.second )
return false;
3179 aFontIDToObject[ item.first ] = item.second;
3190 OStringBuffer aFontDict( 1024 );
3192 aFontDict.append(
" 0 obj\n"
3195 for (
auto const& itemMap : aFontIDToObject)
3197 aFontDict.append(
"/F" );
3198 aFontDict.append( itemMap.first );
3199 aFontDict.append(
' ' );
3200 aFontDict.append( itemMap.second );
3201 aFontDict.append(
" 0 R" );
3202 if( ((++ni) & 7) == 0 )
3203 aFontDict.append(
'\n' );
3213 aFontDict.append(
"\n>>\nendobj\n\n" );
3216 if ( !
writeBuffer( aFontDict.getStr(), aFontDict.getLength() ) )
return false;
3233 OStringBuffer aLine( 512 );
3236 aLine.setLength( 0 );
3237 aLine.append( nResourceDict );
3238 aLine.append(
" 0 obj\n" );
3240 aLine.append(
"endobj\n\n" );
3242 return nResourceDict;
3246 sal_Int32 nItemLevel,
3247 sal_Int32 nCurrentItemId )
3264 for( sal_Int32
i = 0;
i < nChildren;
i++ )
3266 rCounts[nCurrentItemId] =
nCount;
3277 rCounts[ nCurrentItemId ] = -sal_Int32(rItem.
m_aChildren.size());
3278 for( sal_Int32
i = 0;
i < nChildren;
i++ )
3295 for(
i = 0;
i < nItems; ++
i )
3299 for(
i = 0;
i < nItems; ++
i )
3306 for(
int n = 0;
n < nChildren; ++
n )
3319 std::vector< sal_Int32 > aCounts( nItems );
3323 for(
i = 0;
i < nItems; ++
i )
3326 OStringBuffer aLine( 1024 );
3330 aLine.append(
" 0 obj\n" );
3331 aLine.append(
"<<" );
3333 if(
i > 0 || aCounts[0] > 0 )
3335 aLine.append(
"/Count " );
3336 aLine.append( aCounts[
i] );
3341 aLine.append(
"/First " );
3343 aLine.append(
" 0 R/Last " );
3345 aLine.append(
" 0 R\n" );
3350 aLine.append(
"/Title" );
3352 aLine.append(
"\n" );
3356 aLine.append(
"/Dest" );
3359 aLine.append(
"/Parent " );
3361 aLine.append(
" 0 R" );
3364 aLine.append(
"/Prev " );
3366 aLine.append(
" 0 R" );
3370 aLine.append(
"/Next " );
3372 aLine.append(
" 0 R" );
3375 aLine.append(
">>\nendobj\n\n" );
3383#define CHECK_RETURN( x ) if( !x ) return false
3389 SAL_INFO(
"vcl.pdfwriter",
"ERROR: invalid dest " <<
static_cast<int>(nDestID) <<
" requested");
3396 rBuffer.append(
'[' );
3398 rBuffer.append(
" 0 R" );
3404 rBuffer.append(
"/XYZ " );
3406 rBuffer.append(
' ' );
3408 rBuffer.append(
" 0" );
3411 rBuffer.append(
"/FitR " );
3413 rBuffer.append(
' ' );
3414 appendFixedInt( rDest.
m_aRect.
Top(), rBuffer );
3415 rBuffer.append(
' ' );
3417 rBuffer.append(
' ' );
3421 rBuffer.append(
']' );
3430 rAttachedFile.maFilename = rFileName;
3431 rAttachedFile.maMimeType = rMimeType;
3432 rAttachedFile.mnEmbeddedFileObjectId = nObjectID;
3440 rEmbedded.m_nObject = aObjectID;
3441 rEmbedded.m_aSubType = rMimeType;
3442 rEmbedded.m_pStream = std::move(rStream);
3458 for (
int i = 0;
i < nAnnots;
i++)
3462 OStringBuffer aLine;
3463 bool bEmbed =
false;
3475 aLine.append(
" 0 obj\n");
3476 aLine.append(
"<< /Type /EmbeddedFile /Length ");
3477 aLine.append(
static_cast<sal_Int64
>(aMemoryStream.
GetSize()));
3478 aLine.append(
" >>\nstream\n");
3484 aLine.append(
"\nendstream\nendobj\n\n");
3494 aLine.append(
" 0 obj\n");
3495 aLine.append(
"<</Type/Annot");
3496 aLine.append(
"/Subtype/Screen/Rect[");
3499 appendFixedInt(rScreen.
m_aRect.
Top(), aLine);
3507 aLine.append(
"/A<</Type/Action /S/Rendition /AN ");
3509 aLine.append(
" 0 R ");
3512 aLine.append(
"/R<</Type/Rendition /S/MR ");
3515 aLine.append(
"/C<</Type/MediaClip /S/MCD ");
3518 aLine.append(
"/D << /Type /Filespec /F (<embedded file>) /EF << /F ");
3520 aLine.append(
" 0 R >> >>");
3525 aLine.append(
"/D << /Type /Filespec /FS /URL /F ");
3527 aLine.append(
" >>");
3530 aLine.append(
"/P <</TF (TEMPACCESS)>>");
3532 aLine.append(
"/CT (video/mp4)");
3536 aLine.append(
"/P<</BE<</C true >>>>");
3540 aLine.append(
"/OP 0 >>");
3543 aLine.append(
"/P ");
3545 aLine.append(
" 0 R\n>>\nendobj\n\n");
3554 MARK(
"PDFWriterImpl::emitLinkAnnotations");
3556 for(
int i = 0;
i < nAnnots;
i++ )
3562 OStringBuffer aLine( 1024 );
3564 aLine.append(
" 0 obj\n" );
3567 aLine.append(
"<</Type/Annot" );
3569 aLine.append(
"/F 4" );
3570 aLine.append(
"/Subtype/Link/Border[0 0 0]/Rect[" );
3573 aLine.append(
' ' );
3574 appendFixedInt( rLink.
m_aRect.
Top(), aLine );
3575 aLine.append(
' ' );
3577 aLine.append(
' ' );
3579 aLine.append(
"]" );
3581 aLine.append(
"/Contents");
3585 aLine.append(
"/Dest" );
3616 bool bSetGoToRMode =
false;
3617 bool bTargetHasPDFExtension =
false;
3619 bool bIsUNCPath =
false;
3620 bool bUnparsedURI =
false;
3625 if( eTargetProtocol == INetProtocol::NotValid )
3627 if( url.getLength() > 4 && url.startsWith(
"\\\\\\\\"))
3640 bUnparsedURI = eTargetProtocol == INetProtocol::NotValid;
3644 OUString aFileExtension =
aTargetURL.GetFileExtension();
3652 if( !aFileExtension.isEmpty() )
3656 bool bChangeFileExtensionToPDF =
false;
3658 if( aFileExtension.equalsIgnoreAsciiCase(
"odm" ) )
3659 bChangeFileExtensionToPDF =
true;
3660 if( aFileExtension.equalsIgnoreAsciiCase(
"odt" ) )
3661 bChangeFileExtensionToPDF =
true;
3662 else if( aFileExtension.equalsIgnoreAsciiCase(
"odp" ) )
3663 bChangeFileExtensionToPDF =
true;
3664 else if( aFileExtension.equalsIgnoreAsciiCase(
"odg" ) )
3665 bChangeFileExtensionToPDF =
true;
3666 else if( aFileExtension.equalsIgnoreAsciiCase(
"ods" ) )
3667 bChangeFileExtensionToPDF =
true;
3668 if( bChangeFileExtensionToPDF )
3672 bTargetHasPDFExtension =
aTargetURL.GetFileExtension().equalsIgnoreAsciiCase(
"pdf" );
3674 bSetGoToRMode =
true;
3679 aLine.append(
"/A<</Type/Action/S");
3682 aLine.append(
"/Launch/Win<</F" );
3685 aLine.append(
">>" );
3689 bool bSetRelative =
false;
3690 bool bFileSpec =
false;
3692 if(
m_aContext.
RelFsys && eBaseProtocol == eTargetProtocol && eTargetProtocol == INetProtocol::File )
3693 bSetRelative =
true;
3696 if( !bSetGoToRMode )
3703 aLine.append(
"/URI/URI" );
3713 if( (!aFragment.isEmpty() && !bTargetHasPDFExtension) ||
3714 eTargetProtocol != INetProtocol::File )
3716 aLine.append(
"/URI/URI" );
3720 aLine.append(
"/Launch/F" );
3732 aLine.append(
"/GoToR");
3737 aURLNoMark, rLink.
m_nObject, aLine, osl_getThreadTextEncoding() );
3738 if( !aFragment.isEmpty() )
3740 aLine.append(
"/D/");
3741 appendDestinationName( aFragment , aLine );
3749 bTargetHasPDFExtension && !aFragment.isEmpty() )
3751 OStringBuffer aLineLoc( 1024 );
3752 appendDestinationName( aFragment , aLineLoc );
3754 aTargetURL.SetMark( OStringToOUString(aLineLoc, RTL_TEXTENCODING_ASCII_US) );
3756 OUString
aURL = bUnparsedURI ? url :
3763 aURL , rLink.
m_nObject, aLine, osl_getThreadTextEncoding() );
3766 aLine.append(
">>\n" );
3770 aLine.append(
"/StructParent " );
3773 aLine.append(
">>\nendobj\n\n" );
3783void appendAnnotationRect(
tools::Rectangle const & rRectangle, OStringBuffer & aLine)
3785 aLine.append(
"/Rect[");
3786 appendFixedInt(rRectangle.
Left(), aLine);
3788 appendFixedInt(rRectangle.
Top(), aLine);
3790 appendFixedInt(rRectangle.
Right(), aLine);
3792 appendFixedInt(rRectangle.
Bottom(), aLine);
3796void appendObjectID(sal_Int32 nObjectID, OStringBuffer & aLine)
3798 aLine.append(nObjectID);
3799 aLine.append(
" 0 obj\n");
3802void appendObjectReference(sal_Int32 nObjectID, OStringBuffer & aLine)
3804 aLine.append(nObjectID);
3805 aLine.append(
" 0 R ");
3814 aLine.append(
"<</Type /Annot /Subtype /Text ");
3819 aLine.append(
"/F 4 ");
3821 appendAnnotationRect(rNote.
m_aRect, aLine);
3823 aLine.append(
"/Popup ");
3828 aLine.append(
"/M (");
3829 appendPdfTimeDate(aLine, rDateTime.Year, rDateTime.Month, rDateTime.Day, rDateTime.Hours, rDateTime.Minutes, rDateTime.Seconds, 0);
3833 aLine.append(
"/Contents ");
3840 aLine.append(
"/T ");
3844 aLine.append(
">>\n");
3845 aLine.append(
"endobj\n\n");
3850 appendObjectID(rPopUp.
m_nObject, aLine);
3851 aLine.append(
"<</Type /Annot /Subtype /Popup ");
3852 aLine.append(
"/Parent ");
3854 aLine.append(
">>\n");
3855 aLine.append(
"endobj\n\n");
3862 for(
int i = 0;
i < nAnnots;
i++ )
3871 OStringBuffer aLine(1024);
3875 if (!
writeBuffer(aLine.getStr(), aLine.getLength()))
3884 OStringBuffer aLine(1024);
3888 if (!
writeBuffer(aLine.getStr(), aLine.getLength()))
3897 bool bAdjustSize =
false;
3899 Font aFont( rControlFont );
3902 aFont = rAppSetFont;
3929 sal_Int32 nBest = 4;
3938 aFontName = aFontName.toAsciiLowerCase();
3940 if( aFontName.indexOf(
"times" ) != -1 )
3942 else if( aFontName.indexOf(
"courier" ) != -1 )
3944 else if( aFontName.indexOf(
"dingbats" ) != -1 )
3946 else if( aFontName.indexOf(
"symbol" ) != -1 )
3993 OStringBuffer aDA( 256 );
4001 aDA.append(
" Tf" );
4020 rButton.
m_aMKDict =
"/BC [] /BG [] /CA";
4034 sal_Int32 nDelta =
GetDPIX() / 500;
4087 OStringBuffer aDA( 32 );
4092 OStringBuffer aDR( 32 );
4093 aDR.append(
"/Font " );
4095 aDR.append(
" 0 R" );
4096 rEdit.
m_aDRDict = aDR.makeStringAndClear();
4099 aDA.append(
" Tf" );
4109 OString aAppearance =
"/Tx BMC\nEMC\n";
4110 writeBuffer( aAppearance.getStr(), aAppearance.getLength() );
4138 OString aAppearance =
"/Tx BMC\nEMC\n";
4139 writeBuffer( aAppearance.getStr(), aAppearance.getLength() );
4147 OStringBuffer aDA( 256 );
4152 aDA.append( nBest );
4154 OStringBuffer aDR( 32 );
4155 aDR.append(
"/Font " );
4157 aDR.append(
" 0 R" );
4158 rBox.
m_aDRDict = aDR.makeStringAndClear();
4161 aDA.append(
" Tf" );
4184 sal_Int32 nDelta = aFontSize.
Height()/10;
4210 OStringBuffer aLW( 32 );
4213 aLW.append(
" w " );
4222 OStringBuffer aDA( 256 );
4236 const auto nGlyphWidth = pFontInstance->
GetGlyphWidth(nGlyphId,
false,
false);
4239 sal_Int32 nMappedFontObject;
4240 registerGlyph(nGlyphId, pFace, pFontInstance, { cMark }, nGlyphWidth, nMappedGlyph, nMappedFontObject);
4245 aDA.append( nMappedFontObject );
4246 aDA.append(
" 0 Tf" );
4248 OStringBuffer aDR( 32 );
4249 aDR.append(
"/Font " );
4251 aDR.append(
" 0 R" );
4252 rBox.
m_aDRDict = aDR.makeStringAndClear();
4259 sal_Int32 nCharXOffset = 1000 - 787;
4261 nCharXOffset /= 2000;
4262 sal_Int32 nCharYOffset = 1000 - (820-143);
4264 nCharYOffset /= 2000;
4269 aDA.append(
"/Tx BMC\nq BT\n" );
4273 aDA.append( nMappedFontObject );
4276 aDA.append(
" Tf\n" );
4280 aDA.append(
" Td <" );
4281 appendHex( nMappedGlyph, aDA );
4282 aDA.append(
"> Tj\nET\nQ\nEMC\n" );
4314 sal_Int32 nDelta = aFontSize.
Height()/10;
4340 OStringBuffer aLW( 32 );
4343 aLW.append(
" w " );
4364 OStringBuffer aDA( 256 );
4365 aDA.append(
"/Tx BMC\nq BT\n" );
4369 aDA.append(
" 0 0 Td\nET\nQ\n" );
4394 OString aStandardAppearance;
4406 rAnnotDict.append(
"/AP<<\n" );
4409 rAnnotDict.append(
"/" );
4410 rAnnotDict.append( dict_item.first );
4411 bool bUseSubDict = (dict_item.second.size() > 1);
4425 rAnnotDict.append( bUseSubDict ?
"<<" :
" " );
4427 for (
auto const& stream_item : dict_item.second)
4430 dict_item.second[ stream_item.first ] =
nullptr;
4434 sal_Int64 nStreamLen = pAppearanceStream->
TellEnd();
4442 OStringBuffer aLine;
4443 aLine.append( nObject );
4445 aLine.append(
" 0 obj\n"
4450 aLine.append(
" " );
4455 aLine.append(
" 0 R\n"
4457 aLine.append( nStreamLen );
4458 aLine.append(
"\n" );
4460 aLine.append(
"/Filter/FlateDecode\n" );
4461 aLine.append(
">>\nstream\n" );
4470 rAnnotDict.append(
" /" );
4471 rAnnotDict.append( stream_item.first );
4472 rAnnotDict.append(
" " );
4474 rAnnotDict.append( nObject );
4475 rAnnotDict.append(
" 0 R" );
4477 delete pAppearanceStream;
4480 rAnnotDict.append( bUseSubDict ?
">>\n" :
"\n" );
4482 rAnnotDict.append(
">>\n" );
4483 if( !aStandardAppearance.isEmpty() )
4485 rAnnotDict.append(
"/AS /" );
4486 rAnnotDict.append( aStandardAppearance );
4487 rAnnotDict.append(
"\n" );
4499 for(
int a = 0;
a < nAnnots;
a++ )
4510 auto stream_it = app_it->second.find(
"Yes" );
4511 if( stream_it != app_it->second.end() )
4514 app_it->second.erase( stream_it );
4517 (app_it->second)[
aBuf.makeStringAndClear() ] = pStream;
4520 SAL_INFO(
"vcl.pdfwriter",
"error: CheckBox without \"Yes\" stream" );
4529 auto stream_it = app_it->second.find(
"Off" );
4530 if( stream_it != app_it->second.end() )
4533 app_it->second.erase( stream_it );
4536 (app_it->second)[
aBuf.makeStringAndClear() ] = pStream;
4539 SAL_INFO(
"vcl.pdfwriter",
"error: CheckBox without \"Off\" stream" );
4544 OStringBuffer aLine( 1024 );
4545 OStringBuffer aValue( 256 );
4547 aLine.append(
" 0 obj\n"
4556 aLine.append(
"/Type/Annot/Subtype/Widget/F " );
4560 aLine.append(
"132\n" );
4565 aLine.append(
"4\n" );
4569 aLine.append(
"/Rect[" );
4570 appendFixedInt( rWidget.
m_aRect.
Left()-iRectMargin, aLine );
4571 aLine.append(
' ' );
4572 appendFixedInt( rWidget.
m_aRect.
Top()+iRectMargin, aLine );
4573 aLine.append(
' ' );
4574 appendFixedInt( rWidget.
m_aRect.
Right()+iRectMargin, aLine );
4575 aLine.append(
' ' );
4576 appendFixedInt( rWidget.
m_aRect.
Bottom()-iRectMargin, aLine );
4577 aLine.append(
"]\n" );
4579 aLine.append(
"/FT/" );
4591 aValue.append(
"/" );
4594 aValue.append(
"Off" );
4596 appendName( rWidget.
m_aValue, aValue );
4600 aLine.append(
"Btn" );
4605 aValue.append(
"[" );
4613 aValue.append(
"]" );
4623 aLine.append(
"Ch" );
4627 aLine.append(
"Ch" );
4630 aLine.append(
"Tx" );
4634 aLine.append(
"Sig" );
4640 aLine.append(
"\n" );
4641 aLine.append(
"/P " );
4643 aLine.append(
" 0 R\n" );
4647 aLine.append(
"/Parent " );
4649 aLine.append(
" 0 R\n" );
4651 if( !rWidget.
m_aKids.empty() )
4653 aLine.append(
"/Kids[" );
4654 for(
size_t i = 0;
i < rWidget.
m_aKids.size();
i++ )
4656 aLine.append( rWidget.
m_aKids[
i] );
4657 aLine.append(
" 0 R" );
4658 aLine.append( ( (
i&15) == 15 ) ?
"\n" :
" " );
4660 aLine.append(
"]\n" );
4662 if( !rWidget.
m_aName.isEmpty() )
4664 aLine.append(
"/T" );
4666 aLine.append(
"\n" );
4672 aLine.append(
"/TU" );
4674 aLine.append(
"\n" );
4679 aLine.append(
"/Ff " );
4681 aLine.append(
"\n" );
4683 if( !aValue.isEmpty() )
4685 OString aVal = aValue.makeStringAndClear();
4686 aLine.append(
"/V " );
4687 aLine.append( aVal );
4690 aLine.append( aVal );
4691 aLine.append(
"\n" );
4696 aLine.append(
"/Opt[\n" );
4701 aLine.append(
"\n" );
4706 aLine.append(
"]\n" );
4709 aLine.append(
"/TI " );
4710 aLine.append( nTI );
4711 aLine.append(
"\n" );
4714 aLine.append(
"/I [" );
4715 aLine.append( nTI );
4716 aLine.append(
"]\n" );
4724 aLine.append(
"/MaxLen " );
4726 aLine.append(
"\n" );
4737 aHexText =
"\\\\u" + OString::number(cChar, 16);
4740 aLine.append(
"/AA<<\n");
4741 aLine.append(
"/F<</JS(AFNumber_Format\\(");
4743 aLine.append(
", 0, 0, 0, \"");
4744 aLine.append( aHexText );
4745 aLine.append(
"\",");
4747 aLine.append(
"\\);)");
4748 aLine.append(
"/S/JavaScript>>\n");
4749 aLine.append(
"/K<</JS(AFNumber_Keystroke\\(");
4751 aLine.append(
", 0, 0, 0, \"");
4752 aLine.append( aHexText );
4753 aLine.append(
"\",");
4755 aLine.append(
"\\);)");
4756 aLine.append(
"/S/JavaScript>>\n");
4757 aLine.append(
">>\n");
4761 aLine.append(
"/AA<<\n");
4762 aLine.append(
"/F<</JS(AFTime_FormatEx\\(\"");
4764 aLine.append(
"\"\\);)");
4765 aLine.append(
"/S/JavaScript>>\n");
4766 aLine.append(
"/K<</JS(AFTime_KeystrokeEx\\(\"");
4768 aLine.append(
"\"\\);)");
4769 aLine.append(
"/S/JavaScript>>\n");
4770 aLine.append(
">>\n");
4774 aLine.append(
"/AA<<\n");
4775 aLine.append(
"/F<</JS(AFDate_FormatEx\\(\"");
4777 aLine.append(
"\"\\);)");
4778 aLine.append(
"/S/JavaScript>>\n");
4779 aLine.append(
"/K<</JS(AFDate_KeystrokeEx\\(\"");
4781 aLine.append(
"\"\\);)");
4782 aLine.append(
"/S/JavaScript>>\n");
4783 aLine.append(
">>\n");
4790 OStringBuffer aDest;
4793 aLine.append(
"/AA<</D<</Type/Action/S/GoTo/D " );
4794 aLine.append( aDest );
4795 aLine.append(
">>>>\n" );
4802 aLine.append(
"/AA<</D<</Type/Action/S/ResetForm>>>>\n" );
4808 aLine.append(
"/AA<</D<</Type/Action/S/SubmitForm/F" );
4810 aLine.append(
"/Flags " );
4812 sal_Int32 nFlags = 0;
4832 aLine.append( nFlags );
4833 aLine.append(
">>>>\n" );
4838 aLine.append(
"/AA<</D<</Type/Action/S/URI/URI(" );
4840 aLine.append(
")>>>>\n" );
4850 aLine.append(
"/DR<<" );
4852 aLine.append(
">>\n" );
4856 aLine.append(
"/DR<</Font<<" );
4858 aLine.append(
">>>>\n" );
4860 aLine.append(
"/DA" );
4862 aLine.append(
"\n" );
4864 aLine.append(
"/Q 1\n" );
4866 aLine.append(
"/Q 2\n" );
4873 aLine.append(
"/MK<<" );
4877 aLine.append(
">>\n" );
4882 aLine.append(
">>\n"
4903class PDFStreamIf :
public cppu::WeakImplHelper< css::io::XOutputStream >
4910 virtual void SAL_CALL
writeBytes(
const css::uno::Sequence< sal_Int8 >& aData )
override
4914 sal_Int32 nBytes =
aData.getLength();
4918 virtual void SAL_CALL
flush()
override {}
4934 OStringBuffer aLine;
4935 aLine.append(rEmbeddedFile.m_nObject);
4936 aLine.append(
" 0 obj\n");
4937 aLine.append(
"<< /Type /EmbeddedFile");
4938 if (!rEmbeddedFile.m_aSubType.isEmpty())
4940 aLine.append(
"/Subtype /");
4941 appendName(rEmbeddedFile.m_aSubType, aLine);
4943 aLine.append(
" /Length ");
4944 appendObjectReference(nSizeObject, aLine);
4945 aLine.append(
">>\nstream\n");
4952 if (!rEmbeddedFile.m_aDataContainer.isEmpty())
4954 nSize = rEmbeddedFile.m_aDataContainer.getSize();
4955 CHECK_RETURN(
writeBuffer(rEmbeddedFile.m_aDataContainer.getData(), rEmbeddedFile.m_aDataContainer.getSize()));
4957 else if (rEmbeddedFile.m_pStream)
4961 rEmbeddedFile.m_pStream->write(
xStream);
4962 rEmbeddedFile.m_pStream.reset();
4966 aLine.append(
"\nendstream\nendobj\n\n");
4972 aLine.append(nSizeObject);
4973 aLine.append(
" 0 obj\n");
4974 aLine.append(nSize);
4975 aLine.append(
"\nendobj\n\n");
4976 if (!
writeBuffer(aLine.getStr(), aLine.getLength()))
4983#define CHECK_RETURN( x ) if( !x ) return false
4998 if( ! page.emit( nTreeNode ) )
5011 sal_Int32 nStructureDict = 0;
5025 OStringBuffer aLine( 2048 );
5026 aLine.append( nTreeNode );
5027 aLine.append(
" 0 obj\n" );
5028 aLine.append(
"<</Type/Pages\n" );
5029 aLine.append(
"/Resources " );
5031 aLine.append(
" 0 R\n" );
5033 double nMediaBoxWidth = 0;
5034 double nMediaBoxHeight = 0;
5035 sal_Int32 nUserUnit = 1;
5045 if( page.m_nPageWidth > nMediaBoxWidth )
5047 nMediaBoxWidth = page.m_nPageWidth;
5048 nUserUnit = page.m_nUserUnit;
5050 if( page.m_nPageHeight > nMediaBoxHeight )
5052 nMediaBoxHeight = page.m_nPageHeight;
5053 nUserUnit = page.m_nUserUnit;
5057 aLine.append(
"/MediaBox[ 0 0 " );
5058 aLine.append(nMediaBoxWidth / nUserUnit);