21 #include <config_crypto.h>
27 #include <string_view>
38 #include <com/sun/star/io/XOutputStream.hpp>
39 #include <com/sun/star/util/URL.hpp>
40 #include <com/sun/star/util/URLTransformer.hpp>
47 #include <officecfg/Office/Common.hxx>
48 #include <osl/file.hxx>
49 #include <osl/thread.h>
50 #include <rtl/digest.h>
51 #include <rtl/uri.hxx>
52 #include <rtl/ustrbuf.hxx>
80 #include <textlayout.hxx>
89 #include <config_eot.h>
92 #include <libeot/libeot.h>
95 using namespace::com::sun::star;
102 constexpr sal_Int32 nLog10Divisor = 3;
103 constexpr
double fDivisor = 1000.0;
105 constexpr
double pixelToPoint(
double px)
107 return px / fDivisor;
110 constexpr sal_Int32 pointToPixel(
double pt)
112 return sal_Int32(pt * fDivisor);
115 void appendHex(
sal_Int8 nInt, OStringBuffer& rBuffer)
117 static const char pHexDigits[] = {
'0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
118 '8',
'9',
'A',
'B',
'C',
'D',
'E',
'F' };
119 rBuffer.append( pHexDigits[ (nInt >> 4) & 15 ] );
120 rBuffer.append( pHexDigits[ nInt & 15 ] );
123 void appendName( std::u16string_view rStr, OStringBuffer& rBuffer )
128 int nLen =
aStr.getLength();
129 for(
int i = 0;
i < nLen;
i++ )
138 if( (aStr[i] >=
'A' && aStr[i] <=
'Z' ) ||
139 (aStr[i] >=
'a' && aStr[i] <=
'z' ) ||
140 (aStr[i] >=
'0' && aStr[i] <=
'9' ) ||
143 rBuffer.append( aStr[i] );
147 rBuffer.append(
'#' );
148 appendHex( static_cast<sal_Int8>(aStr[i]), rBuffer );
153 void appendName(
const char* pStr, OStringBuffer& rBuffer )
156 while( pStr && *pStr )
158 if( (*pStr >=
'A' && *pStr <=
'Z' ) ||
159 (*pStr >=
'a' && *pStr <=
'z' ) ||
160 (*pStr >=
'0' && *pStr <=
'9' ) ||
163 rBuffer.append( *pStr );
167 rBuffer.append(
'#' );
168 appendHex( static_cast<sal_Int8>(*pStr), rBuffer );
175 void appendLiteralString(
const char* pStr, sal_Int32 nLength, OStringBuffer& rBuffer )
182 rBuffer.append(
"\\n" );
185 rBuffer.append(
"\\r" );
188 rBuffer.append(
"\\t" );
191 rBuffer.append(
"\\b" );
194 rBuffer.append(
"\\f" );
199 rBuffer.append(
"\\" );
200 rBuffer.append( static_cast<char>(*pStr) );
203 rBuffer.append( static_cast<char>(*pStr) );
234 void appendDestinationName(
const OUString& rString, OStringBuffer& rBuffer )
237 sal_Int32 nLen = rString.getLength();
238 for(
int i = 0;
i < nLen;
i++ )
241 if( (aChar >=
'0' && aChar <=
'9' ) ||
242 (aChar >=
'a' && aChar <=
'z' ) ||
243 (aChar >=
'A' && aChar <=
'Z' ) ||
246 rBuffer.append(static_cast<char>(aChar));
252 appendHex( aValueHigh, rBuffer );
253 appendHex( static_cast<sal_Int8>(aChar & 255 ), rBuffer );
264 0x28, 0xBF, 0x4E, 0x5E, 0x4E, 0x75, 0x8A, 0x41, 0x64, 0x00, 0x4E, 0x56, 0xFF, 0xFA, 0x01, 0x08,
265 0x2E, 0x2E, 0x00, 0xB6, 0xD0, 0x68, 0x3E, 0x80, 0x2F, 0x0C, 0xA9, 0xFE, 0x64, 0x53, 0x69, 0x7A
271 template <
class GEOMETRY >
272 GEOMETRY lcl_convert(
const MapMode& _rSource,
const MapMode& _rDest,
OutputDevice* _pPixelConversion,
const GEOMETRY& _rObject )
275 if ( MapUnit::MapPixel == _rSource.
GetMapUnit() )
277 aPoint = _pPixelConversion->
PixelToLogic( _rObject, _rDest );
290 rBuffer.append(
"FEFF" );
292 sal_Int32 nLen = rString.getLength();
293 for(
int i = 0;
i < nLen;
i++ )
296 appendHex( static_cast<sal_Int8>(aChar >> 8), rBuffer );
297 appendHex( static_cast<sal_Int8>(aChar & 255 ), rBuffer );
309 int nLen =
aStr.getLength();
311 OStringBuffer
aBuffer( rName.getLength()+64 );
312 for(
int i = 0;
i < nLen;
i++ )
323 appendHex( static_cast<sal_Int8>(
aStr[i]),
aBuffer );
327 OString aFullName(
aBuffer.makeStringAndClear() );
330 sal_Int32 nTokenIndex = 0, nLastTokenIndex = 0;
331 OString aPartialName;
335 nLastTokenIndex = nTokenIndex;
336 aPartialName = aFullName.getToken( 0,
'.', nTokenIndex );
337 if( nTokenIndex != -1 )
341 aDomain = aFullName.copy( 0, nTokenIndex-1 );
342 std::unordered_map< OString, sal_Int32 >::const_iterator it =
m_aFieldNameMap.find( aDomain );
350 m_aWidgets[nNewWidget].m_aName = aPartialName;
354 if( nLastTokenIndex > 0 )
358 OString aParentDomain( aDomain.copy( 0, nLastTokenIndex-1 ) );
363 OSL_ENSURE( it->second < sal_Int32(
m_aWidgets.size()),
"invalid field number entry" );
364 if( it->second < sal_Int32(
m_aWidgets.size()) )
383 aPartialName = aFullName.copy( aFullName.lastIndexOf(
'.' )+1 );
384 if( nLastTokenIndex > 0 )
386 aDomain = aFullName.copy( 0, nLastTokenIndex-1 );
387 aFullName = aDomain +
"." + aPartialName;
390 aFullName = aPartialName;
394 }
while( nTokenIndex != -1 );
397 if( !aDomain.isEmpty() )
399 std::unordered_map< OString, sal_Int32 >::const_iterator it =
m_aFieldNameMap.find( aDomain );
407 m_aWidgets[it->second].m_aKidsIndex.push_back( i_nWidgetIndex );
412 if( aPartialName.isEmpty() )
417 aPartialName =
"RadioGroup" +
418 OString::number( static_cast<const PDFWriter::RadioButtonWidget&>(i_rControl).RadioGroup );
421 aPartialName = OString(
"Widget" );
426 std::unordered_map<OString, sal_Int32>::iterator it =
m_aFieldNameMap.find( aFullName );
430 std::unordered_map< OString, sal_Int32 >::const_iterator check_it;
435 OStringBuffer aUnique( aFullName.getLength() + 16 );
436 aUnique.append( aFullName );
437 aUnique.append(
'_' );
438 aUnique.append( nTry++ );
439 aTry = aUnique.makeStringAndClear();
444 aPartialName = aFullName.copy( aFullName.lastIndexOf(
'.' )+1 );
451 m_aWidgets[i_nWidgetIndex].m_aName = aPartialName;
457 void appendFixedInt( sal_Int32 nValue, OStringBuffer& rBuffer )
461 rBuffer.append(
'-' );
464 sal_Int32 nFactor = 1, nDiv = nLog10Divisor;
468 sal_Int32 nInt = nValue / nFactor;
469 rBuffer.append( nInt );
470 if (nFactor > 1 && nValue % nFactor)
472 rBuffer.append(
'.' );
476 rBuffer.append((nValue / nFactor) % 10);
478 while (nFactor > 1 && nValue % nFactor);
483 void appendDouble(
double fValue, OStringBuffer& rBuffer, sal_Int32 nPrecision = 10 )
492 sal_Int64 nInt =
static_cast<sal_Int64
>(fValue);
493 fValue -=
static_cast<double>(nInt);
495 if( rtl::math::approxEqual(fValue, 1.0) || log10( 1.0-fValue ) <= -nPrecision )
503 fValue *= pow( 10.0, static_cast<double>(nPrecision) );
504 nFrac =
static_cast<sal_Int64
>(fValue);
506 if( bNeg && ( nInt || nFrac ) )
507 rBuffer.append(
'-' );
508 rBuffer.append( nInt );
513 rBuffer.append(
'.' );
514 sal_Int64 nBound =
static_cast<sal_Int64
>(pow( 10.0, nPrecision - 1.0 )+0.5);
515 for ( i = 0; ( i < nPrecision ) && nFrac; i++ )
517 sal_Int64 nNumb = nFrac / nBound;
518 nFrac -= nNumb * nBound;
519 rBuffer.append( nNumb );
524 void appendColor(
const Color& rColor, OStringBuffer& rBuffer,
bool bConvertToGrey )
527 if( rColor == COL_TRANSPARENT )
533 appendDouble( static_cast<double>(cByte) / 255.0, rBuffer );
537 appendDouble( static_cast<double>(rColor.
GetRed()) / 255.0, rBuffer );
538 rBuffer.append(
' ' );
539 appendDouble( static_cast<double>(rColor.
GetGreen()) / 255.0, rBuffer );
540 rBuffer.append(
' ' );
541 appendDouble( static_cast<double>(rColor.
GetBlue()) / 255.0, rBuffer );
552 appendColor( rColor, rBuffer, bGrey );
553 rBuffer.append( bGrey ?
" G" :
" RG" );
562 appendColor( rColor, rBuffer, bGrey );
563 rBuffer.append( bGrey ?
" g" :
" rg" );
570 void appendPdfTimeDate(OStringBuffer & rBuffer,
571 sal_Int16 year, sal_uInt16 month, sal_uInt16 day, sal_uInt16 hours, sal_uInt16 minutes, sal_uInt16 seconds, sal_Int32 tzDelta)
573 rBuffer.append(
"D:");
574 rBuffer.append(
char(
'0' + ((year / 1000) % 10)));
575 rBuffer.append(
char(
'0' + ((year / 100) % 10)));
576 rBuffer.append(
char(
'0' + ((year / 10) % 10)));
577 rBuffer.append(
char(
'0' + (year % 10)));
578 rBuffer.append(
char(
'0' + ((month / 10) % 10)));
579 rBuffer.append(
char(
'0' + (month % 10)));
580 rBuffer.append(
char(
'0' + ((day / 10) % 10)));
581 rBuffer.append(
char(
'0' + (day % 10)));
582 rBuffer.append(
char(
'0' + ((hours / 10) % 10)));
583 rBuffer.append(
char(
'0' + (hours % 10)));
584 rBuffer.append(
char(
'0' + ((minutes / 10) % 10)));
585 rBuffer.append(
char(
'0' + (minutes % 10)));
586 rBuffer.append(
char(
'0' + ((seconds / 10) % 10)));
587 rBuffer.append(
char(
'0' + (seconds % 10)));
603 rBuffer.append(
char(
'0' + ((tzDelta / 36000) % 10)));
604 rBuffer.append(
char(
'0' + ((tzDelta / 3600) % 10)));
606 rBuffer.append(
char(
'0' + ((tzDelta / 600) % 6)));
607 rBuffer.append(
char(
'0' + ((tzDelta / 60) % 10)));
615 m_pWriter( pWriter ),
616 m_nPageWidth( nPageWidth ),
617 m_nPageHeight( nPageHeight ),
619 m_eOrientation( eOrientation ),
621 m_nStreamLengthObject( 0 ),
622 m_nBeginStreamPos( 0 ),
632 m_nUserUnit = std::ceil(std::max(nPageWidth, nPageHeight) / 14400.0);
644 m_pWriter->emitComment(
"PDFWriterImpl::PDFPage::beginStream, +");
654 aLine.append(
" 0 obj\n<</Length " );
656 aLine.append(
" 0 R" );
658 aLine.append(
"/Filter/FlateDecode" );
659 aLine.append(
">>\nstream\n" );
660 if( !
m_pWriter->writeBuffer( aLine.getStr(), aLine.getLength() ) )
676 sal_uInt64 nEndStreamPos;
677 if (osl::File::E_None !=
m_pWriter->m_aFile.getPos(nEndStreamPos))
684 if( !
m_pWriter->writeBuffer(
"\nendstream\nendobj\n\n", 19 ) )
694 m_pWriter->writeBuffer( aLine.getStr(), aLine.getLength() );
706 aLine.append(
" 0 obj\n"
707 "<</Type/Page/Parent " );
708 aLine.append( nParentObject );
709 aLine.append(
" 0 R" );
710 aLine.append(
"/Resources " );
711 aLine.append(
m_pWriter->getResourceDictObj() );
712 aLine.append(
" 0 R" );
715 aLine.append(
"/MediaBox[0 0 " );
722 aLine.append(
"\n/UserUnit ");
734 aLine.append(
"/Annots[\n" );
735 for(
int i = 0; i < nAnnots; i++ )
738 aLine.append(
" 0 R" );
739 aLine.append( ((i+1)%15) ?
" " :
"\n" );
741 aLine.append(
"]\n" );
745 OStringBuffer aStructParents( 1024 );
746 aStructParents.append(
"[ " );
748 for(
int i = 0; i < nParents; i++ )
751 aStructParents.append(
" 0 R" );
752 aStructParents.append( ((i%10) == 9) ?
"\n" :
" " );
754 aStructParents.append(
"]" );
755 m_pWriter->m_aStructParentTree.push_back( aStructParents.makeStringAndClear() );
757 aLine.append(
"/StructParents " );
758 aLine.append( sal_Int32(
m_pWriter->m_aStructParentTree.size()-1) );
759 aLine.append(
"\n" );
764 aLine.append(
"/Trans<</D " );
765 appendDouble( static_cast<double>(
m_nTransTime)/1000.0, aLine, 3 );
766 aLine.append(
"\n" );
767 const char *pStyle =
nullptr, *pDm =
nullptr, *pM =
nullptr, *pDi =
nullptr;
771 pStyle =
"Split"; pDm =
"H"; pM =
"I";
break;
773 pStyle =
"Split"; pDm =
"H"; pM =
"O";
break;
775 pStyle =
"Split"; pDm =
"V"; pM =
"I";
break;
777 pStyle =
"Split"; pDm =
"V"; pM =
"O";
break;
779 pStyle =
"Blinds"; pDm =
"H";
break;
781 pStyle =
"Blinds"; pDm =
"V";
break;
783 pStyle =
"Box"; pM =
"I";
break;
785 pStyle =
"Box"; pM =
"O";
break;
787 pStyle =
"Wipe"; pDi =
"0";
break;
789 pStyle =
"Wipe"; pDi =
"90";
break;
791 pStyle =
"Wipe"; pDi =
"180";
break;
793 pStyle =
"Wipe"; pDi =
"270";
break;
795 pStyle =
"Dissolve";
break;
802 aLine.append(
"/S/" );
803 aLine.append( pStyle );
804 aLine.append(
"\n" );
808 aLine.append(
"/Dm/" );
810 aLine.append(
"\n" );
814 aLine.append(
"/M/" );
816 aLine.append(
"\n" );
820 aLine.append(
"/Di " );
822 aLine.append(
"\n" );
824 aLine.append(
">>\n" );
827 aLine.append(
"/Contents" );
829 if( nStreamObjects > 1 )
835 aLine.append(
" 0 R" );
837 if( nStreamObjects > 1 )
839 aLine.append(
">>\nendobj\n\n" );
840 return m_pWriter->writeBuffer( aLine.getStr(), aLine.getLength() );
845 Point aPoint( lcl_convert(
m_pWriter->m_aGraphicsStack.front().m_aMapMode,
850 sal_Int32 nValue = aPoint.X();
852 appendFixedInt( nValue, rBuffer );
854 rBuffer.append(
' ' );
856 nValue = pointToPixel(
getHeight()) - aPoint.Y();
858 appendFixedInt( nValue, rBuffer );
863 double fValue = pixelToPoint(rPoint.
getX());
865 appendDouble( fValue, rBuffer, nLog10Divisor );
866 rBuffer.append(
' ' );
868 appendDouble( fValue, rBuffer, nLog10Divisor );
874 rBuffer.append(
' ' );
876 rBuffer.append(
' ' );
878 rBuffer.append(
" re" );
883 Point aLL = lcl_convert(
m_pWriter->m_aGraphicsStack.front().m_aMapMode,
888 Size aSize = lcl_convert(
m_pWriter->m_aGraphicsStack.front().m_aMapMode,
893 rRect.
SetRight( aLL.X() + aSize.Width() );
900 sal_uInt16 nPoints = rPoly.
GetSize();
904 sal_uInt32 nBufLen = rBuffer.getLength();
910 rBuffer.append(
" m\n" );
911 for( sal_uInt16 i = 1; i < nPoints; i++ )
913 if( pFlagArray && pFlagArray[i] == PolyFlags::Control && nPoints-i > 2 )
916 SAL_WARN_IF( pFlagArray[i+1] != PolyFlags::Control || pFlagArray[i+2] == PolyFlags::Control,
"vcl.pdfwriter",
"unexpected sequence of control points" );
918 rBuffer.append(
" " );
920 rBuffer.append(
" " );
922 rBuffer.append(
" c" );
929 rBuffer.append(
" l" );
931 if( (rBuffer.getLength() - nBufLen) > 65 )
933 rBuffer.append(
"\n" );
934 nBufLen = rBuffer.getLength();
937 rBuffer.append(
" " );
940 rBuffer.append(
"h\n" );
955 rBuffer.append(
' ' );
957 rBuffer.append(
' ' );
959 rBuffer.append(
" re\n" );
962 sal_uInt32 nPoints = aPoly.
count();
966 sal_uInt32 nBufLen = rBuffer.getLength();
969 rBuffer.append(
" m\n" );
970 for( sal_uInt32 i = 1; i <= nPoints; i++ )
972 if( i != nPoints || aPoly.
isClosed() )
975 sal_uInt32 nLastPoint = i-1;
981 rBuffer.append(
' ' );
983 rBuffer.append(
' ' );
985 rBuffer.append(
" c" );
990 rBuffer.append(
' ' );
992 rBuffer.append(
" y" );
997 rBuffer.append(
' ' );
999 rBuffer.append(
" v" );
1004 rBuffer.append(
" l" );
1006 if( (rBuffer.getLength() - nBufLen) > 65 )
1008 rBuffer.append(
"\n" );
1009 nBufLen = rBuffer.getLength();
1012 rBuffer.append(
" " );
1015 rBuffer.append(
"h\n" );
1020 sal_uInt16 nPolygons = rPolyPoly.
Count();
1021 for( sal_uInt16
n = 0;
n < nPolygons;
n++ )
1027 for(
auto const& rPolygon : rPolyPoly)
1033 sal_Int32 nValue = nLength;
1036 rBuffer.append(
'-' );
1039 Size aSize( lcl_convert(
m_pWriter->m_aGraphicsStack.front().m_aMapMode,
1042 Size( nValue, nValue ) ) );
1043 nValue = bVertical ? aSize.
Height() : aSize.
Width();
1045 *pOutLength = ((nLength < 0 ) ? -nValue : nValue);
1047 appendFixedInt( nValue, rBuffer );
1052 Size aSize( lcl_convert(
m_pWriter->m_aGraphicsStack.front().m_aMapMode,
1055 Size( 1000, 1000 ) ) );
1056 fLength *= pixelToPoint(static_cast<double>(bVertical ? aSize.
Height() : aSize.
Width()) / 1000.0);
1057 appendDouble( fLength, rBuffer, nPrecision );
1062 if(
LineStyle::Dash == rInfo.GetStyle() && rInfo.GetDashLen() != rInfo.GetDotLen())
1066 if(2 * (rInfo.GetDashCount() + rInfo.GetDotCount()) > 10)
1078 if(css::drawing::LineCap_BUTT != rInfo.GetLineCap())
1086 rBuffer.append(
"[ " );
1087 if( rInfo.GetDashLen() == rInfo.GetDotLen() )
1090 rBuffer.append(
' ' );
1092 rBuffer.append(
' ' );
1096 for(
int n = 0;
n < rInfo.GetDashCount();
n++ )
1099 rBuffer.append(
' ' );
1101 rBuffer.append(
' ' );
1103 for(
int m = 0;
m < rInfo.GetDotCount();
m++ )
1106 rBuffer.append(
' ' );
1108 rBuffer.append(
' ' );
1111 rBuffer.append(
"] 0 d\n" );
1114 if( rInfo.GetWidth() > 1 )
1117 rBuffer.append(
" w\n" );
1119 else if( rInfo.GetWidth() == 0 )
1122 appendDouble( 72.0/
double(
m_pWriter->GetDPIX()), rBuffer );
1123 rBuffer.append(
" w\n" );
1136 rBuffer.append(
"0 " );
1138 rBuffer.append(
" m\n" );
1139 for( sal_Int32
n = 0;
n < nWidth; )
1143 rBuffer.append(
' ' );
1145 rBuffer.append(
' ' );
1148 rBuffer.append(
' ' );
1150 rBuffer.append(
" v " );
1155 rBuffer.append(
' ' );
1157 rBuffer.append(
' ' );
1160 rBuffer.append(
' ' );
1162 rBuffer.append(
" v\n" );
1165 rBuffer.append(
"S\n" );
1170 appendDouble(rMatrix.
get(0), rBuffer);
1171 rBuffer.append(
' ');
1172 appendDouble(rMatrix.
get(1), rBuffer);
1173 rBuffer.append(
' ');
1174 appendDouble(rMatrix.
get(2), rBuffer);
1175 rBuffer.append(
' ');
1176 appendDouble(rMatrix.
get(3), rBuffer);
1177 rBuffer.append(
' ');
1194 const css::uno::Reference< css::beans::XMaterialHolder >& xEnc,
1198 m_nCurrentStructElement( 0 ),
1199 m_bEmitStructure( true ),
1202 officecfg::Office::Common::VCL::PDFExportImageCacheSize::
get() ),
1203 m_nCurrentPage( -1 ),
1204 m_nCatalogObject(0),
1205 m_nSignatureObject( -1 ),
1206 m_nSignatureContentOffset( 0 ),
1207 m_nSignatureLastByteRangeNoOffset( 0 ),
1208 m_nResourceDict( -1 ),
1209 m_nFontDictObject( -1 ),
1214 m_aCipher( nullptr ),
1217 m_bEncryptThisStream(
false ),
1218 m_nAccessPermissions(0),
1219 m_bIsPDF_A1(
false ),
1220 m_bIsPDF_A2(
false ),
1221 m_bIsPDF_UA(
false ),
1222 m_bIsPDF_A3(
false ),
1223 m_rOuterFace( i_rOuterFace )
1238 osl::File::RC aError =
m_aFile.open(osl_File_OpenFlag_Write | osl_File_OpenFlag_Create);
1239 if (aError != osl::File::E_None)
1241 if (aError == osl::File::E_EXIST)
1243 aError =
m_aFile.open(osl_File_OpenFlag_Write);
1244 if (aError == osl::File::E_None)
1248 if (aError != osl::File::E_None)
1257 m_aCipher = rtl_cipher_createARCFOUR( rtl_Cipher_ModeStream );
1274 OSL_ENSURE(
false,
"encryption data failed sanity check, encryption disabled" );
1282 aBuffer.append(
"%PDF-" );
1294 aBuffer.append(
"\n%\303\244\303\274\303\266\303\237\n" );
1295 if( !
writeBuffer( aBuffer.getStr(), aBuffer.getLength() ) )
1360 std::vector< sal_uInt8 >
aId;
1371 TimeValue aTVal, aGMT;
1373 osl_getSystemTime(&aGMT);
1374 osl_getLocalTimeFromSystemTime(&aGMT, &aTVal);
1375 osl_getDateTimeFromTimeValue(&aTVal, &aDT);
1377 sal_Int32 nDelta = aTVal.Seconds-aGMT.Seconds;
1379 appendPdfTimeDate(aRet, aDT.Year, aDT.Month, aDT.Day, aDT.Hours, aDT.Minutes, aDT.Seconds, nDelta);
1382 return aRet.makeStringAndClear();
1387 const OString& i_rCString1,
1388 OString& o_rCString2
1391 o_rIdentifier.clear();
1394 OString aInfoValuesOut;
1395 OStringBuffer aID( 1024 );
1396 if( !i_rDocInfo.
Title.isEmpty() )
1398 if( !i_rDocInfo.
Author.isEmpty() )
1400 if( !i_rDocInfo.
Subject.isEmpty() )
1402 if( !i_rDocInfo.
Keywords.isEmpty() )
1404 if( !i_rDocInfo.
Creator.isEmpty() )
1406 if( !i_rDocInfo.
Producer.isEmpty() )
1409 TimeValue aTVal, aGMT;
1411 osl_getSystemTime( &aGMT );
1412 osl_getLocalTimeFromSystemTime( &aGMT, &aTVal );
1413 osl_getDateTimeFromTimeValue( &aTVal, &aDT );
1414 OStringBuffer aCreationMetaDateString(64);
1422 aCreationMetaDateString.append( static_cast<char>(
'0' + ((aDT.Year/1000)%10)) );
1423 aCreationMetaDateString.append( static_cast<char>(
'0' + ((aDT.Year/100)%10)) );
1424 aCreationMetaDateString.append( static_cast<char>(
'0' + ((aDT.Year/10)%10)) );
1425 aCreationMetaDateString.append( static_cast<char>(
'0' + ((aDT.Year)%10)) );
1426 aCreationMetaDateString.append(
"-" );
1427 aCreationMetaDateString.append( static_cast<char>(
'0' + ((aDT.Month/10)%10)) );
1428 aCreationMetaDateString.append( static_cast<char>(
'0' + ((aDT.Month)%10)) );
1429 aCreationMetaDateString.append(
"-" );
1430 aCreationMetaDateString.append( static_cast<char>(
'0' + ((aDT.Day/10)%10)) );
1431 aCreationMetaDateString.append( static_cast<char>(
'0' + ((aDT.Day)%10)) );
1432 aCreationMetaDateString.append(
"T" );
1433 aCreationMetaDateString.append( static_cast<char>(
'0' + ((aDT.Hours/10)%10)) );
1434 aCreationMetaDateString.append( static_cast<char>(
'0' + ((aDT.Hours)%10)) );
1435 aCreationMetaDateString.append(
":" );
1436 aCreationMetaDateString.append( static_cast<char>(
'0' + ((aDT.Minutes/10)%10)) );
1437 aCreationMetaDateString.append( static_cast<char>(
'0' + ((aDT.Minutes)%10)) );
1438 aCreationMetaDateString.append(
":" );
1439 aCreationMetaDateString.append( static_cast<char>(
'0' + ((aDT.Seconds/10)%10)) );
1440 aCreationMetaDateString.append( static_cast<char>(
'0' + ((aDT.Seconds)%10)) );
1442 sal_uInt32 nDelta = 0;
1443 if( aGMT.Seconds > aTVal.Seconds )
1445 nDelta = aGMT.Seconds-aTVal.Seconds;
1446 aCreationMetaDateString.append(
"-" );
1448 else if( aGMT.Seconds < aTVal.Seconds )
1450 nDelta = aTVal.Seconds-aGMT.Seconds;
1451 aCreationMetaDateString.append(
"+" );
1455 aCreationMetaDateString.append(
"Z" );
1460 aCreationMetaDateString.append( static_cast<char>(
'0' + ((nDelta/36000)%10)) );
1461 aCreationMetaDateString.append( static_cast<char>(
'0' + ((nDelta/3600)%10)) );
1462 aCreationMetaDateString.append(
":" );
1463 aCreationMetaDateString.append( static_cast<char>(
'0' + ((nDelta/600)%6)) );
1464 aCreationMetaDateString.append( static_cast<char>(
'0' + ((nDelta/60)%10)) );
1466 aID.append( i_rCString1.getStr(), i_rCString1.getLength() );
1468 aInfoValuesOut = aID.makeStringAndClear();
1469 o_rCString2 = aCreationMetaDateString.makeStringAndClear();
1472 aDigest.
update(reinterpret_cast<unsigned char const*>(&aGMT),
sizeof(aGMT));
1473 aDigest.
update(reinterpret_cast<unsigned char const*>(aInfoValuesOut.getStr()), aInfoValuesOut.getLength());
1475 o_rIdentifier = aDigest.
finalize();
1485 rOutBuffer.append(
"<" );
1489 sal_Int32 nLen = rInString.getLength();
1493 sal_Int32 nChars = 2 + (nLen * 2);
1498 for(
int i = 0; i < nLen; i++ )
1501 *pCopy++ =
static_cast<sal_uInt8>( aUnChar >> 8 );
1502 *pCopy++ =
static_cast<sal_uInt8>( aUnChar & 255 );
1507 for(
int i = 0; i < nChars; i++)
1512 rOutBuffer.append(
">" );
1517 rOutBuffer.append(
"(" );
1518 sal_Int32 nChars = rInString.size();
1526 appendLiteralString( reinterpret_cast<char*>(
m_vEncryptionBuffer.data()), nChars, rOutBuffer );
1529 appendLiteralString( rInString.data(), nChars , rOutBuffer );
1530 rOutBuffer.append(
")" );
1536 sal_Int32 nLen = aBufferString.getLength();
1537 OStringBuffer
aBuf( nLen );
1538 const char* pT = aBufferString.getStr();
1540 for( sal_Int32 i = 0; i < nLen; i++, pT++ )
1542 if( (*pT & 0x80) == 0 )
1547 appendHex( *pT, aBuf );
1551 aBufferString = aBuf.makeStringAndClear();
1559 OString aLine = OString::Concat(
"% ") + pComment +
"\n";
1567 sal_uInt64 nEndPos = pStream->
TellEnd();
1569 ZCodec aCodec( 0x4000, 0x4000 );
1572 aCodec.
Write( aStream, static_cast<const sal_uInt8*>(pStream->
GetData()), nEndPos );
1574 nEndPos = aStream.
Tell();
1589 m_pCodec = std::make_unique<ZCodec>( 0x4000, 0x4000 );
1620 pBuffer, sal::static_int_cast<std::size_t>(nBytes));
1624 sal_uInt64 nWritten;
1627 m_pCodec->Write( *
m_pMemStream, static_cast<const sal_uInt8*>(pBuffer), static_cast<sal_uLong>(nBytes) );
1639 pBuffer, static_cast<sal_Size>(nBytes),
1644 m_DocDigest.
update(static_cast<unsigned char const*>(pWriteBuffer), static_cast<sal_uInt32>(nBytes));
1646 if (
m_aFile.write(pWriteBuffer, nBytes, nWritten) != osl::File::E_None)
1649 if( nWritten != nBytes )
1656 return nWritten == nBytes;
1663 m_aPages.emplace_back(
this, nPageWidth, nPageHeight, eOrientation );
1665 sal_Int32 nUserUnit =
m_aPages.back().m_nUserUnit;
1669 Fraction(nUserUnit, pointToPixel(1)));
1676 OStringBuffer
aBuf( 16 );
1677 appendDouble( 72.0/
double(
GetDPIX()), aBuf );
1678 aBuf.append(
" w\n" );
1693 OSL_FAIL(
"redirection across pages !!!" );
1716 if( ! bitmap.m_aBitmap.IsEmpty() )
1724 if( jpeg.m_pStream )
1727 jpeg.m_pStream.reset();
1733 if( item.m_pContentStream )
1736 item.m_pContentStream.reset();
1753 sal_uInt64 nOffset = ~0
U;
1754 osl::File::RC aError =
m_aFile.getPos(nOffset);
1755 SAL_WARN_IF( aError != osl::File::E_None,
"vcl.pdfwriter",
"could not register object" );
1756 if (aError != osl::File::E_None)
1762 return aError == osl::File::E_None;
1765 #define CHECK_RETURN( x ) if( !(x) ) return 0
1766 #define CHECK_RETURN2( x ) if( !(x) ) return
1772 OStringBuffer aLine( 1024 );
1774 aLine.append( nObject );
1775 aLine.append(
" 0 obj\n"
1778 for( sal_Int32
n = 0;
n < nTreeItems;
n++ )
1781 aLine.append(
' ' );
1783 aLine.append(
"\n" );
1785 aLine.append(
"]>>\nendobj\n\n" );
1794 static std::map< PDFWriter::StructAttribute, const char* > aAttributeStrings;
1796 if( aAttributeStrings.empty() )
1819 std::map< PDFWriter::StructAttribute, const char* >::const_iterator it =
1820 aAttributeStrings.find( eAttr );
1822 if( it == aAttributeStrings.end() )
1823 SAL_INFO(
"vcl.pdfwriter",
"invalid PDFWriter::StructAttribute " << eAttr);
1825 return it != aAttributeStrings.end() ? it->second :
"";
1830 static std::map< PDFWriter::StructAttributeValue, const char* > aValueStrings;
1832 if( aValueStrings.empty() )
1862 std::map< PDFWriter::StructAttributeValue, const char* >::const_iterator it =
1863 aValueStrings.find( eVal );
1865 if( it == aValueStrings.end() )
1866 SAL_INFO(
"vcl.pdfwriter",
"invalid PDFWriter::StructAttributeValue " << eVal);
1868 return it != aValueStrings.end() ? it->second :
"";
1873 o_rLine.append(
"/" );
1878 o_rLine.append(
"/" );
1884 o_rLine.append(
" " );
1886 appendFixedInt( i_rVal.
nValue, o_rLine );
1888 o_rLine.append( i_rVal.
nValue );
1890 o_rLine.append(
"\n" );
1896 OStringBuffer aLayout(256), aList(64), aTable(64);
1906 sal_Int32 nLink =
attribute.second.nValue;
1907 std::map< sal_Int32, sal_Int32 >::const_iterator link_it =
1910 nLink = link_it->second;
1914 OString aStructParentEntry =
1924 OString::number( nRefObject ) +
1926 "<</Type/OBJR/Obj " +
1927 OString::number(
m_aLinks[ nLink ].m_nObject ) +
1933 i_rEle.
m_aKids.emplace_back( nRefObject );
1937 OSL_FAIL(
"unresolved link id for Link structure" );
1938 SAL_INFO(
"vcl.pdfwriter",
"unresolved link id " << nLink <<
" for Link structure");
1941 OString aLine =
"unresolved link id " +
1942 OString::number( nLink ) +
1943 " for Link structure";
1953 aLayout.append(
"/BBox[" );
1955 aLayout.append(
" " );
1956 appendFixedInt( i_rEle.
m_aBBox.
Top(), aLayout );
1957 aLayout.append(
" " );
1959 aLayout.append(
" " );
1961 aLayout.append(
"]\n" );
1964 std::vector< sal_Int32 > aAttribObjects;
1965 if( !aLayout.isEmpty() )
1970 OStringBuffer aObj( 64 );
1971 aObj.append( aAttribObjects.back() );
1972 aObj.append(
" 0 obj\n"
1974 aLayout.append(
">>\nendobj\n\n" );
1976 writeBuffer( aLayout.getStr(), aLayout.getLength() );
1979 if( !aList.isEmpty() )
1984 OStringBuffer aObj( 64 );
1985 aObj.append( aAttribObjects.back() );
1986 aObj.append(
" 0 obj\n"
1988 aList.append(
">>\nendobj\n\n" );
1993 if( !aTable.isEmpty() )
1998 OStringBuffer aObj( 64 );
1999 aObj.append( aAttribObjects.back() );
2000 aObj.append(
" 0 obj\n"
2002 aTable.append(
">>\nendobj\n\n" );
2004 writeBuffer( aTable.getStr(), aTable.getLength() );
2008 OStringBuffer aRet( 64 );
2009 if( aAttribObjects.size() > 1 )
2010 aRet.append(
" [" );
2011 for (
auto const& attrib : aAttribObjects)
2014 aRet.append( attrib );
2015 aRet.append(
" 0 R" );
2017 if( aAttribObjects.size() > 1 )
2018 aRet.append(
" ]" );
2019 return aRet.makeStringAndClear();
2042 OSL_FAIL(
"PDFWriterImpl::emitStructure: invalid child structure element" );
2043 SAL_INFO(
"vcl.pdfwriter",
"PDFWriterImpl::emitStructure: invalid child structure element with id " << child);
2049 OSL_FAIL(
"PDFWriterImpl::emitStructure: invalid child structure id" );
2050 SAL_INFO(
"vcl.pdfwriter",
"PDFWriterImpl::emitStructure: invalid child structure id " << child);
2054 OStringBuffer aLine( 512 );
2056 aLine.append(
" 0 obj\n"
2058 sal_Int32 nParentTree = -1;
2063 aLine.append(
"/StructTreeRoot\n" );
2064 aLine.append(
"/ParentTree " );
2065 aLine.append( nParentTree );
2066 aLine.append(
" 0 R\n" );
2069 aLine.append(
"/RoleMap<<" );
2072 aLine.append(
'/' );
2073 aLine.append(role.first);
2074 aLine.append(
'/' );
2075 aLine.append( role.second );
2076 aLine.append(
'\n' );
2078 aLine.append(
">>\n" );
2083 aLine.append(
"/StructElem\n"
2092 aLine.append(
" 0 R\n"
2095 aLine.append(
" 0 R\n" );
2098 aLine.append(
"/ActualText" );
2100 aLine.append(
"\n" );
2104 aLine.append(
"/Alt" );
2106 aLine.append(
"\n" );
2112 if( !aAttribs.isEmpty() )
2114 aLine.append(
"/A" );
2115 aLine.append( aAttribs );
2116 aLine.append(
"\n" );
2119 if( !rEle.
m_aLocale.Language.isEmpty() )
2128 OUString aLanguage, aScript, aCountry;
2130 if (!aLanguage.isEmpty())
2132 OUStringBuffer aLocBuf( 16 );
2133 aLocBuf.append( aLanguage );
2134 if( !aCountry.isEmpty() )
2136 aLocBuf.append(
'-' );
2137 aLocBuf.append( aCountry );
2139 aLine.append(
"/Lang" );
2141 aLine.append(
"\n" );
2147 aLine.append(
"/K[" );
2148 for (
auto const& kid : rEle.
m_aKids)
2150 if( kid.nMCID == -1 )
2152 aLine.append( kid.nObject );
2153 aLine.append(
" 0 R" );
2154 aLine.append( ( (i & 15) == 15 ) ?
"\n" :
" " );
2160 aLine.append( kid.nMCID );
2161 aLine.append(
" " );
2165 aLine.append(
"<</Type/MCR/Pg " );
2166 aLine.append( kid.nObject );
2167 aLine.append(
" 0 R /MCID " );
2168 aLine.append( kid.nMCID );
2169 aLine.append(
">>\n" );
2174 aLine.append(
"]\n" );
2176 aLine.append(
">>\nendobj\n\n" );
2197 OStringBuffer aTilingObj( 1024 );
2201 SAL_WARN_IF( !tiling.m_pTilingStream,
"vcl.pdfwriter",
"tiling without stream" );
2202 if( ! tiling.m_pTilingStream )
2205 aTilingObj.setLength( 0 );
2212 sal_Int32 nX =
static_cast<sal_Int32
>(tiling.m_aRectangle.Left());
2213 sal_Int32 nY =
static_cast<sal_Int32
>(tiling.m_aRectangle.Top());
2214 sal_Int32 nW =
static_cast<sal_Int32
>(tiling.m_aRectangle.GetWidth());
2215 sal_Int32 nH =
static_cast<sal_Int32
>(tiling.m_aRectangle.GetHeight());
2216 if( tiling.m_aCellSize.Width() == 0 )
2217 tiling.m_aCellSize.setWidth( nW );
2218 if( tiling.m_aCellSize.Height() == 0 )
2219 tiling.m_aCellSize.setHeight( nH );
2222 sal_uInt64
const nTilingStreamSize = tiling.m_pTilingStream->TellEnd();
2226 aTilingObj.append( tiling.m_nObject );
2227 aTilingObj.append(
" 0 obj\n" );
2228 aTilingObj.append(
"<</Type/Pattern/PatternType 1\n"
2232 appendFixedInt( nX, aTilingObj );
2233 aTilingObj.append(
' ' );
2234 appendFixedInt( nY, aTilingObj );
2235 aTilingObj.append(
' ' );
2236 appendFixedInt( nX+nW, aTilingObj );
2237 aTilingObj.append(
' ' );
2238 appendFixedInt( nY+nH, aTilingObj );
2239 aTilingObj.append(
"]\n"
2241 appendFixedInt( tiling.m_aCellSize.Width(), aTilingObj );
2242 aTilingObj.append(
"\n"
2244 appendFixedInt( tiling.m_aCellSize.Height(), aTilingObj );
2245 aTilingObj.append(
"\n" );
2246 if( tiling.m_aTransform.matrix[0] != 1.0 ||
2247 tiling.m_aTransform.matrix[1] != 0.0 ||
2248 tiling.m_aTransform.matrix[3] != 0.0 ||
2249 tiling.m_aTransform.matrix[4] != 1.0 ||
2250 tiling.m_aTransform.matrix[2] != 0.0 ||
2251 tiling.m_aTransform.matrix[5] != 0.0 )
2253 aTilingObj.append(
"/Matrix [" );
2255 appendDouble( tiling.m_aTransform.matrix[0], aTilingObj );
2256 aTilingObj.append(
' ' );
2257 appendDouble( tiling.m_aTransform.matrix[1], aTilingObj );
2258 aTilingObj.append(
' ' );
2259 appendDouble( tiling.m_aTransform.matrix[3], aTilingObj );
2260 aTilingObj.append(
' ' );
2261 appendDouble( tiling.m_aTransform.matrix[4], aTilingObj );
2262 aTilingObj.append(
' ' );
2263 appendDouble( tiling.m_aTransform.matrix[2], aTilingObj );
2264 aTilingObj.append(
' ' );
2265 appendDouble( tiling.m_aTransform.matrix[5], aTilingObj );
2266 aTilingObj.append(
"]\n" );
2268 aTilingObj.append(
"/Resources" );
2271 aTilingObj.append(
"/Filter/FlateDecode" );
2272 aTilingObj.append(
"/Length " );
2273 aTilingObj.append( static_cast<sal_Int32>(nTilingStreamSize) );
2274 aTilingObj.append(
">>\nstream\n" );
2276 if ( !
writeBuffer( aTilingObj.getStr(), aTilingObj.getLength() ) )
return false;
2278 bool written =
writeBuffer( tiling.m_pTilingStream->GetData(), nTilingStreamSize );
2279 tiling.m_pTilingStream.reset();
2283 aTilingObj.setLength( 0 );
2284 aTilingObj.append(
"\nendstream\nendobj\n\n" );
2285 if ( !
writeBuffer( aTilingObj.getStr(), aTilingObj.getLength() ) )
return false;
2296 OStringBuffer aLine( 1024 );
2298 if( nFontObject <= 0 )
2301 aLine.append( nFontObject );
2302 aLine.append(
" 0 obj\n"
2303 "<</Type/Font/Subtype/Type1/BaseFont/" );
2304 appendName( rBuildinFont.
m_pPSName, aLine );
2305 aLine.append(
"\n" );
2306 if( rBuildinFont.
m_eCharSet == RTL_TEXTENCODING_MS_1252 )
2307 aLine.append(
"/Encoding/WinAnsiEncoding\n" );
2308 aLine.append(
">>\nendobj\n\n" );
2315 std::map< sal_Int32, sal_Int32 > aRet;
2317 sal_Int32 nFontDescriptor = 0;
2318 OString aSubType(
"/Type1" );
2326 sal_Int32 pWidths[256] = {};
2332 aSubType = OString(
"/TrueType" );
2333 std::vector< sal_Int32 > aGlyphWidths;
2335 pGraphics->
GetGlyphWidths( pFont,
false, aGlyphWidths, aUnicodeMap );
2338 osl_createTempFile(
nullptr,
nullptr, &aTmpName.pData );
2341 sal_Int32 pDuWidths[ 256 ] = {};
2343 for(
sal_Ucs c = 32; c < 256; c++ )
2347 if( aUnicodeMap.find( c ) != aUnicodeMap.end() )
2348 pWidths[ c ] = aGlyphWidths[ aUnicodeMap[ c ] ];
2354 pGraphics->
CreateFontSubset( aTmpName, pFont, aGlyphIds, pEncoding, pDuWidths, 256, aInfo );
2355 osl_removeFile( aTmpName.pData );
2359 if( nFontDescriptor )
2365 OStringBuffer aLine( 1024 );
2366 aLine.append( nObject );
2367 aLine.append(
" 0 obj\n"
2368 "<</Type/Font/Subtype" );
2369 aLine.append( aSubType );
2370 aLine.append(
"/BaseFont/" );
2372 aLine.append(
"\n" );
2374 aLine.append(
"/Encoding/WinAnsiEncoding\n" );
2375 aLine.append(
"/FirstChar 32 /LastChar 255\n"
2377 for(
int i = 32; i < 256; i++ )
2379 aLine.append( pWidths[i] );
2380 aLine.append( ((i&15) == 15) ?
"\n" :
" " );
2383 "/FontDescriptor " );
2384 aLine.append( nFontDescriptor );
2385 aLine.append(
" 0 R>>\n"
2398 ThreeInts& rSegmentLengths )
2400 if( !pFontBytes || (nByteLen < 0) )
2402 const unsigned char* pPtr = pFontBytes;
2403 const unsigned char* pEnd = pFontBytes + nByteLen;
2405 for(
int & rSegmentLength : rSegmentLengths) {
2407 if( pPtr+6 >= pEnd )
2409 if( (pPtr[0] != 0x80) || (pPtr[1] >= 0x03) )
2411 const int nLen = (pPtr[5]<<24) + (pPtr[4]<<16) + (pPtr[3]<<8) + pPtr[2];
2414 rSegmentLength = nLen;
2419 if( pPtr+2 >= pEnd )
2421 if( (pPtr[0] != 0x80) || (pPtr[1] != 0x03) )
2427 static void appendSubsetName(
int nSubsetID, std::u16string_view rPSName, OStringBuffer& rBuffer )
2431 for(
int i = 0; i < 6; i++ )
2433 int nOffset = nSubsetID % 26;
2435 rBuffer.append( static_cast<char>(
'A'+nOffset) );
2437 rBuffer.append(
'+' );
2439 appendName( rPSName, rBuffer );
2444 const sal_Int32* pCodeUnitsPerGlyph,
2445 const sal_Int32* pEncToUnicodeIndex,
2449 for (
int n = 0;
n < nGlyphs; ++
n)
2450 if( pCodeUnits[pEncToUnicodeIndex[
n]] && pCodeUnitsPerGlyph[
n] )
2459 OStringBuffer aContents( 1024 );
2461 "/CIDInit/ProcSet findresource begin\n"
2464 "/CIDSystemInfo<<\n"
2465 "/Registry (Adobe)\n"
2469 "/CMapName/Adobe-Identity-UCS def\n"
2471 "1 begincodespacerange\n"
2473 "endcodespacerange\n"
2476 for (
int n = 0; n < nGlyphs; ++n)
2478 if( pCodeUnits[pEncToUnicodeIndex[n]] && pCodeUnitsPerGlyph[n] )
2480 if( (nCount % 100) == 0 )
2483 aContents.append(
"endbfchar\n" );
2484 aContents.append( static_cast<sal_Int32>(std::min(nMapped-nCount, 100)) );
2485 aContents.append(
" beginbfchar\n" );
2487 aContents.append(
'<' );
2488 appendHex( static_cast<sal_Int8>(pEncoding[n]), aContents );
2489 aContents.append(
"> <" );
2491 sal_Int32
nIndex = pEncToUnicodeIndex[n];
2492 for( sal_Int32 j = 0; j < pCodeUnitsPerGlyph[n]; j++ )
2494 appendHex( static_cast<sal_Int8>(pCodeUnits[nIndex + j] / 256), aContents );
2495 appendHex( static_cast<sal_Int8>(pCodeUnits[nIndex + j] & 255), aContents );
2497 aContents.append(
">\n" );
2501 aContents.append(
"endbfchar\n"
2503 "CMapName currentdict /CMap defineresource pop\n"
2509 ZCodec aCodec( 0x4000, 0x4000 );
2511 aCodec.
Write( aStream, reinterpret_cast<const sal_uInt8*>(aContents.getStr()), aContents.getLength() );
2517 emitComment(
"PDFWriterImpl::createToUnicodeCMap" );
2519 OStringBuffer aLine( 40 );
2521 aLine.append( nStream );
2522 aLine.append(
" 0 obj\n<</Length " );
2526 nLen =
static_cast<sal_Int32
>(aStream.
Tell());
2528 aLine.append( nLen );
2529 aLine.append(
"/Filter/FlateDecode" );
2532 aLine.append( aContents.getLength() );
2533 aLine.append(
">>\nstream\n" );
2545 aLine.setLength( 0 );
2546 aLine.append(
"\nendstream\n"
2554 OStringBuffer aLine( 1024 );
2558 sal_Int32 nFontFlags = (1<<2);
2560 nFontFlags |= (1 << 6);
2564 nFontFlags |= (1 << 3);
2566 nFontFlags |= (1 << 1);
2570 aLine.setLength( 0 );
2571 aLine.append( nFontDescriptor );
2572 aLine.append(
" 0 obj\n"
2573 "<</Type/FontDescriptor/FontName/" );
2577 aLine.append( nFontFlags );
2582 aLine.append(
' ' );
2584 aLine.append(
' ' );
2586 aLine.append(
' ' );
2588 aLine.append(
"]/ItalicAngle " );
2590 aLine.append(
"-30" );
2592 aLine.append(
"0" );
2595 aLine.append( static_cast<sal_Int32>(rInfo.
m_nAscent) );
2598 aLine.append( static_cast<sal_Int32>(-rInfo.
m_nDescent) );
2601 aLine.append( static_cast<sal_Int32>(rInfo.
m_nCapHeight) );
2608 aLine.append(
"/FontFile" );
2612 aLine.append(
'2' );
2619 OSL_FAIL(
"unknown fonttype in PDF font descriptor" );
2622 aLine.append(
' ' );
2623 aLine.append( nFontStream );
2624 aLine.append(
" 0 R\n" );
2626 aLine.append(
">>\n"
2630 return nFontDescriptor;
2638 rDict.append(
' ' );
2639 rDict.append( item.second );
2640 rDict.append(
" 0 R" );
2651 OStringBuffer aLine( 1024 );
2653 std::map< sal_Int32, sal_Int32 > aFontIDToObject;
2656 osl_createTempFile(
nullptr,
nullptr, &aTmpName.pData );
2659 for (
auto & s_subset :subset.second.m_aSubsets)
2662 sal_Int32 pWidths[ 256 ];
2664 sal_Int32 pEncToUnicodeIndex[ 256 ] = {};
2665 sal_Int32 pCodeUnitsPerGlyph[ 256 ] = {};
2666 std::vector<sal_Ucs> aCodeUnits;
2667 aCodeUnits.reserve( 256 );
2670 sal_Int32 nToUnicodeStream = 0;
2672 for (
auto const& item : s_subset.m_aMapping)
2674 sal_uInt8 nEnc = item.second.getGlyphId();
2676 SAL_WARN_IF( aGlyphIds[nEnc] != 0 || pEncoding[nEnc] != 0,
"vcl.pdfwriter",
"duplicate glyph" );
2677 SAL_WARN_IF( nEnc > s_subset.m_aMapping.size(),
"vcl.pdfwriter",
"invalid glyph encoding" );
2679 aGlyphIds[ nEnc ] = item.first;
2680 pEncoding[ nEnc ] = nEnc;
2681 pEncToUnicodeIndex[ nEnc ] =
static_cast<sal_Int32
>(aCodeUnits.size());
2682 pCodeUnitsPerGlyph[ nEnc ] = item.second.countCodes();
2683 for( sal_Int32
n = 0;
n < pCodeUnitsPerGlyph[ nEnc ];
n++ )
2684 aCodeUnits.push_back( item.second.getCode(
n ) );
2685 if( item.second.getCode(0) )
2686 nToUnicodeStream = 1;
2691 OSL_FAIL(
"too many glyphs for subset" );
2695 if( pGraphics->
CreateFontSubset( aTmpName, subset.first, aGlyphIds, pEncoding, pWidths, nGlyphs, aSubsetInfo ) )
2698 osl::File aFontFile(aTmpName);
2699 if (osl::File::E_None != aFontFile.open(osl_File_OpenFlag_Read))
return false;
2701 sal_uInt64 nLength1;
2702 if ( osl::File::E_None != aFontFile.setPos(osl_Pos_End, 0) )
return false;
2703 if ( osl::File::E_None != aFontFile.getPos(nLength1) )
return false;
2704 if ( osl::File::E_None != aFontFile.setPos(osl_Pos_Absolut, 0) )
return false;
2713 aLine.setLength( 0 );
2714 aLine.append( nFontStream );
2715 aLine.append(
" 0 obj\n"
2717 aLine.append( nStreamLengthObject );
2719 aLine.append(
" 0 R"
2720 "/Filter/FlateDecode"
2723 aLine.append(
" 0 R"
2726 sal_uInt64 nStartPos = 0;
2729 aLine.append( static_cast<sal_Int32>(nLength1) );
2731 aLine.append(
">>\n"
2733 if ( !
writeBuffer( aLine.getStr(), aLine.getLength() ) )
return false;
2734 if ( osl::File::E_None !=
m_aFile.getPos(nStartPos) )
return false;
2744 if ( osl::File::E_None != aFontFile.read(buf,
sizeof(buf), nRead) )
return false;
2746 if ( osl::File::E_None != aFontFile.isEndOfFile(&bEOF) )
return false;
2752 OSL_FAIL(
"PDFWriterImpl does not support CFF-font subsets yet!" );
2756 std::unique_ptr<unsigned char[]> xBuffer(
new unsigned char[nLength1]);
2758 sal_uInt64 nBytesRead = 0;
2759 if ( osl::File::E_None != aFontFile.read(xBuffer.get(), nLength1, nBytesRead) )
return false;
2760 SAL_WARN_IF( nBytesRead!=nLength1,
"vcl.pdfwriter",
"PDF-FontSubset read incomplete!" );
2761 if ( osl::File::E_None != aFontFile.setPos(osl_Pos_Absolut, 0) )
return false;
2763 ThreeInts aSegmentLengths = {0,0,0};
2767 aLine.append( static_cast<sal_Int32>(aSegmentLengths[0]) );
2768 aLine.append(
"/Length2 " );
2769 aLine.append( static_cast<sal_Int32>(aSegmentLengths[1]) );
2770 aLine.append(
"/Length3 " );
2771 aLine.append( static_cast<sal_Int32>(aSegmentLengths[2]) );
2773 aLine.append(
">>\n"
2775 if ( !
writeBuffer( aLine.getStr(), aLine.getLength() ) )
return false;
2776 if ( osl::File::E_None !=
m_aFile.getPos(nStartPos) )
return false;
2781 if ( !
writeBuffer( &xBuffer[6], aSegmentLengths[0] ) )
return false;
2782 if ( !
writeBuffer( &xBuffer[12] + aSegmentLengths[0], aSegmentLengths[1] ) )
return false;
2783 if ( !
writeBuffer( &xBuffer[18] + aSegmentLengths[0] + aSegmentLengths[1], aSegmentLengths[2] ) )
return false;
2787 SAL_INFO(
"vcl.pdfwriter",
"PDF: CreateFontSubset result in not yet supported format=" << static_cast<int>(aSubsetInfo.
m_nFontType));
2788 aLine.append(
"0 >>\nstream\n" );
2796 sal_uInt64 nEndPos = 0;
2797 if ( osl::File::E_None !=
m_aFile.getPos(nEndPos) )
return false;
2799 aLine.setLength( 0 );
2800 aLine.append(
"\nendstream\nendobj\n\n" );
2801 if ( !
writeBuffer( aLine.getStr(), aLine.getLength() ) )
return false;
2804 if ( !
updateObject( nStreamLengthObject ) )
return false;
2805 aLine.setLength( 0 );
2806 aLine.append( nStreamLengthObject );
2807 aLine.append(
" 0 obj\n" );
2808 aLine.append( static_cast<sal_Int64>(nEndPos-nStartPos) );
2809 aLine.append(
"\nendobj\n\n" );
2810 if ( !
writeBuffer( aLine.getStr(), aLine.getLength() ) )
return false;
2813 sal_Int32 nFontDescriptor =
emitFontDescriptor( subset.first, aSubsetInfo, s_subset.m_nFontID, nFontStream );
2815 if( nToUnicodeStream )
2816 nToUnicodeStream =
createToUnicodeCMap( pEncoding, aCodeUnits.data(), pCodeUnitsPerGlyph, pEncToUnicodeIndex, nGlyphs );
2820 aLine.setLength( 0 );
2821 aLine.append( nFontObject );
2823 aLine.append(
" 0 obj\n" );
2825 "<</Type/Font/Subtype/Type1/BaseFont/" :
2826 "<</Type/Font/Subtype/TrueType/BaseFont/" );
2831 aLine.append( static_cast<sal_Int32>(nGlyphs-1) );
2834 for(
int i = 0; i < nGlyphs; i++ )
2836 aLine.append( pWidths[ i ] );
2837 aLine.append( ((i & 15) == 15) ?
"\n" :
" " );
2840 "/FontDescriptor " );
2841 aLine.append( nFontDescriptor );
2842 aLine.append(
" 0 R\n" );
2843 if( nToUnicodeStream )
2845 aLine.append(
"/ToUnicode " );
2846 aLine.append( nToUnicodeStream );
2847 aLine.append(
" 0 R\n" );
2849 aLine.append(
">>\n"
2851 if ( !
writeBuffer( aLine.getStr(), aLine.getLength() ) )
return false;
2853 aFontIDToObject[ s_subset.m_nFontID ] = nFontObject;
2858 OStringBuffer aErrorComment( 256 );
2859 aErrorComment.append(
"CreateFontSubset failed for font \"" );
2861 aErrorComment.append(
'\"' );
2863 aErrorComment.append(
" italic" );
2865 aErrorComment.append(
" oblique" );
2866 aErrorComment.append(
" weight=" );
2867 aErrorComment.append( sal_Int32(pFont->
GetWeight()) );
2872 osl_removeFile( aTmpName.pData );
2877 std::map< sal_Int32, sal_Int32 > aObjects =
emitSystemFont( systemFont.first, systemFont.second );
2878 for (
auto const& item : aObjects)
2880 if ( !item.second )
return false;
2881 aFontIDToObject[ item.first ] = item.second;
2885 OStringBuffer aFontDict( 1024 );
2887 aFontDict.append(
" 0 obj\n"
2890 for (
auto const& itemMap : aFontIDToObject)
2892 aFontDict.append(
"/F" );
2893 aFontDict.append( itemMap.first );
2894 aFontDict.append(
' ' );
2895 aFontDict.append( itemMap.second );
2896 aFontDict.append(
" 0 R" );
2897 if( ((++ni) & 7) == 0 )
2898 aFontDict.append(
'\n' );
2908 aFontDict.append(
"\n>>\nendobj\n\n" );
2911 if ( !
writeBuffer( aFontDict.getStr(), aFontDict.getLength() ) )
return false;
2928 OStringBuffer aLine( 512 );
2931 aLine.setLength( 0 );
2932 aLine.append( nResourceDict );
2933 aLine.append(
" 0 obj\n" );
2935 aLine.append(
"endobj\n\n" );
2937 return nResourceDict;
2941 sal_Int32 nItemLevel,
2942 sal_Int32 nCurrentItemId )
2959 for( sal_Int32 i = 0; i < nChildren; i++ )
2961 rCounts[nCurrentItemId] = nCount;
2972 rCounts[ nCurrentItemId ] = -sal_Int32(rItem.
m_aChildren.size());
2973 for( sal_Int32 i = 0; i < nChildren; i++ )
2990 for( i = 0; i < nItems; ++i )
2994 for( i = 0; i < nItems; ++i )
3001 for(
int n = 0;
n < nChildren; ++
n )
3014 std::vector< sal_Int32 > aCounts( nItems );
3018 for( i = 0; i < nItems; ++i )
3021 OStringBuffer aLine( 1024 );
3025 aLine.append(
" 0 obj\n" );
3026 aLine.append(
"<<" );
3028 if( i > 0 || aCounts[0] > 0 )
3030 aLine.append(
"/Count " );
3031 aLine.append( aCounts[i] );
3036 aLine.append(
"/First " );
3038 aLine.append(
" 0 R/Last " );
3040 aLine.append(
" 0 R\n" );
3045 aLine.append(
"/Title" );
3047 aLine.append(
"\n" );
3051 aLine.append(
"/Dest" );
3054 aLine.append(
"/Parent " );
3056 aLine.append(
" 0 R" );
3059 aLine.append(
"/Prev " );
3061 aLine.append(
" 0 R" );
3065 aLine.append(
"/Next " );
3067 aLine.append(
" 0 R" );
3070 aLine.append(
">>\nendobj\n\n" );
3078 #define CHECK_RETURN( x ) if( !x ) return false
3084 SAL_INFO(
"vcl.pdfwriter",
"ERROR: invalid dest " << static_cast<int>(nDestID) <<
" requested");
3091 rBuffer.append(
'[' );
3093 rBuffer.append(
" 0 R" );
3099 rBuffer.append(
"/XYZ " );
3101 rBuffer.append(
' ' );
3103 rBuffer.append(
" 0" );
3106 rBuffer.append(
"/FitR " );
3108 rBuffer.append(
' ' );
3109 appendFixedInt( rDest.
m_aRect.
Top(), rBuffer );
3110 rBuffer.append(
' ' );
3112 rBuffer.append(
' ' );
3116 rBuffer.append(
']' );
3124 for (
int i = 0; i < nAnnots; i++)
3128 OStringBuffer aLine;
3129 bool bEmbed =
false;
3141 aLine.append(
" 0 obj\n");
3142 aLine.append(
"<< /Type /EmbeddedFile /Length ");
3143 aLine.append(static_cast<sal_Int64>(aMemoryStream.
GetSize()));
3144 aLine.append(
" >>\nstream\n");
3150 aLine.append(
"\nendstream\nendobj\n\n");
3160 aLine.append(
" 0 obj\n");
3161 aLine.append(
"<</Type/Annot");
3162 aLine.append(
"/Subtype/Screen/Rect[");
3165 appendFixedInt(rScreen.
m_aRect.
Top(), aLine);
3173 aLine.append(
"/A<</Type/Action /S/Rendition /AN ");
3175 aLine.append(
" 0 R ");
3178 aLine.append(
"/R<</Type/Rendition /S/MR ");
3181 aLine.append(
"/C<</Type/MediaClip /S/MCD ");
3184 aLine.append(
"/D << /Type /Filespec /F (<embedded file>) /EF << /F ");
3186 aLine.append(
" 0 R >> >>");
3191 aLine.append(
"/D << /Type /Filespec /FS /URL /F ");
3193 aLine.append(
" >>");
3196 aLine.append(
"/P <</TF (TEMPACCESS)>>");
3198 aLine.append(
"/CT (video/mp4)");
3202 aLine.append(
"/P<</BE<</C true >>>>");
3206 aLine.append(
"/OP 0 >>");
3209 aLine.append(
"/P ");
3211 aLine.append(
" 0 R\n>>\nendobj\n\n");
3220 MARK(
"PDFWriterImpl::emitLinkAnnotations");
3222 for(
int i = 0; i < nAnnots; i++ )
3228 OStringBuffer aLine( 1024 );
3230 aLine.append(
" 0 obj\n" );
3233 aLine.append(
"<</Type/Annot" );
3235 aLine.append(
"/F 4" );
3236 aLine.append(
"/Subtype/Link/Border[0 0 0]/Rect[" );
3239 aLine.append(
' ' );
3240 appendFixedInt( rLink.
m_aRect.
Top(), aLine );
3241 aLine.append(
' ' );
3243 aLine.append(
' ' );
3245 aLine.append(
"]" );
3248 aLine.append(
"/Dest" );
3279 bool bSetGoToRMode =
false;
3280 bool bTargetHasPDFExtension =
false;
3282 bool bIsUNCPath =
false;
3283 bool bUnparsedURI =
false;
3288 if( eTargetProtocol == INetProtocol::NotValid )
3290 if( url.getLength() > 4 && url.startsWith(
"\\\\\\\\"))
3297 aTargetURL = aNewURL;
3303 bUnparsedURI = eTargetProtocol == INetProtocol::NotValid;
3315 if( !aFileExtension.isEmpty() )
3319 bool bChangeFileExtensionToPDF =
false;
3321 if( aFileExtension.equalsIgnoreAsciiCase(
"odm" ) )
3322 bChangeFileExtensionToPDF =
true;
3323 if( aFileExtension.equalsIgnoreAsciiCase(
"odt" ) )
3324 bChangeFileExtensionToPDF =
true;
3325 else if( aFileExtension.equalsIgnoreAsciiCase(
"odp" ) )
3326 bChangeFileExtensionToPDF =
true;
3327 else if( aFileExtension.equalsIgnoreAsciiCase(
"odg" ) )
3328 bChangeFileExtensionToPDF =
true;
3329 else if( aFileExtension.equalsIgnoreAsciiCase(
"ods" ) )
3330 bChangeFileExtensionToPDF =
true;
3331 if( bChangeFileExtensionToPDF )
3335 bTargetHasPDFExtension = aTargetURL.
GetFileExtension().equalsIgnoreAsciiCase(
"pdf" );
3337 bSetGoToRMode =
true;
3342 aLine.append(
"/A<</Type/Action/S");
3345 aLine.append(
"/Launch/Win<</F" );
3348 aLine.append(
">>" );
3352 bool bSetRelative =
false;
3353 bool bFileSpec =
false;
3355 if(
m_aContext.
RelFsys && eBaseProtocol == eTargetProtocol && eTargetProtocol == INetProtocol::File )
3356 bSetRelative =
true;
3359 if( !bSetGoToRMode )
3366 aLine.append(
"/URI/URI" );
3376 if( (!aFragment.isEmpty() && !bTargetHasPDFExtension) ||
3377 eTargetProtocol != INetProtocol::File )
3379 aLine.append(
"/URI/URI" );
3383 aLine.append(
"/Launch/F" );
3395 aLine.append(
"/GoToR");
3400 aURLNoMark, rLink.
m_nObject, aLine, osl_getThreadTextEncoding() );
3401 if( !aFragment.isEmpty() )
3403 aLine.append(
"/D/");
3404 appendDestinationName( aFragment , aLine );
3412 bTargetHasPDFExtension && !aFragment.isEmpty() )
3414 OStringBuffer aLineLoc( 1024 );
3415 appendDestinationName( aFragment , aLineLoc );
3417 aTargetURL.
SetMark( OStringToOUString(aLineLoc.makeStringAndClear(), RTL_TEXTENCODING_ASCII_US) );
3419 OUString
aURL = bUnparsedURI ? url :
3426 aURL , rLink.
m_nObject, aLine, osl_getThreadTextEncoding() );
3429 aLine.append(
">>\n" );
3433 aLine.append(
"/StructParent " );
3436 aLine.append(
">>\nendobj\n\n" );
3446 void appendAnnotationRect(
tools::Rectangle const & rRectangle, OStringBuffer & aLine)
3448 aLine.append(
"/Rect[");
3449 appendFixedInt(rRectangle.
Left(), aLine);
3451 appendFixedInt(rRectangle.
Top(), aLine);
3453 appendFixedInt(rRectangle.
Right(), aLine);
3455 appendFixedInt(rRectangle.
Bottom(), aLine);
3459 void appendObjectID(sal_Int32 nObjectID, OStringBuffer & aLine)
3461 aLine.append(nObjectID);
3462 aLine.append(
" 0 obj\n");
3465 void appendObjectReference(sal_Int32 nObjectID, OStringBuffer & aLine)
3467 aLine.append(nObjectID);
3468 aLine.append(
" 0 R ");
3477 aLine.append(
"<</Type /Annot /Subtype /Text ");
3482 aLine.append(
"/F 4 ");
3484 appendAnnotationRect(rNote.
m_aRect, aLine);
3486 aLine.append(
"/Popup ");
3491 aLine.append(
"/M (");
3492 appendPdfTimeDate(aLine, rDateTime.Year, rDateTime.Month, rDateTime.Day, rDateTime.Hours, rDateTime.Minutes, rDateTime.Seconds, 0);
3496 aLine.append(
"/Contents ");
3503 aLine.append(
"/T ");
3507 aLine.append(
">>\n");
3508 aLine.append(
"endobj\n\n");
3513 appendObjectID(rPopUp.
m_nObject, aLine);
3514 aLine.append(
"<</Type /Annot /Subtype /Popup ");
3515 aLine.append(
"/Parent ");
3517 aLine.append(
">>\n");
3518 aLine.append(
"endobj\n\n");
3525 for(
int i = 0; i < nAnnots; i++ )
3534 OStringBuffer aLine(1024);
3538 if (!
writeBuffer(aLine.getStr(), aLine.getLength()))
3547 OStringBuffer aLine(1024);
3551 if (!
writeBuffer(aLine.getStr(), aLine.getLength()))
3560 bool bAdjustSize =
false;
3562 Font aFont( rControlFont );
3565 aFont = rAppSetFont;
3592 sal_Int32 nBest = 4;
3601 aFontName = aFontName.toAsciiLowerCase();
3603 if( aFontName.indexOf(
"times" ) != -1 )
3605 else if( aFontName.indexOf(
"courier" ) != -1 )
3607 else if( aFontName.indexOf(
"dingbats" ) != -1 )
3609 else if( aFontName.indexOf(
"symbol" ) != -1 )
3641 if( rWidget.Background || rWidget.Border )
3656 OStringBuffer aDA( 256 );
3664 aDA.append(
" Tf" );
3683 rButton.
m_aMKDict =
"/BC [] /BG [] /CA";
3688 const PDFWriter::AnyWidget& rWidget,
3693 if( rWidget.Background || rWidget.Border )
3697 sal_Int32 nDelta =
GetDPIX() / 500;
3722 if( rWidget.Border )
3750 OStringBuffer aDA( 32 );
3755 OStringBuffer aDR( 32 );
3756 aDR.append(
"/Font " );
3758 aDR.append(
" 0 R" );
3759 rEdit.
m_aDRDict = aDR.makeStringAndClear();
3762 aDA.append(
" Tf" );
3772 OString aAppearance =
"/Tx BMC\nEMC\n";
3773 writeBuffer( aAppearance.getStr(), aAppearance.getLength() );
3801 OString aAppearance =
"/Tx BMC\nEMC\n";
3802 writeBuffer( aAppearance.getStr(), aAppearance.getLength() );
3810 OStringBuffer aDA( 256 );
3815 aDA.append( nBest );
3817 OStringBuffer aDR( 32 );
3818 aDR.append(
"/Font " );
3820 aDR.append(
" 0 R" );
3821 rBox.
m_aDRDict = aDR.makeStringAndClear();
3824 aDA.append(
" Tf" );
3835 if( rWidget.Background || rWidget.Border )
3847 sal_Int32 nDelta = aFontSize.
Height()/10;
3873 OStringBuffer aLW( 32 );
3876 aLW.append(
" w " );
3885 OStringBuffer aDA( 256 );
3902 const std::vector<sal_Ucs> aCodeUnits={ cMark };
3904 sal_Int32 nMappedFontObject;
3905 registerGlyph(&aItem, pDevFont, aCodeUnits, nMappedGlyph, nMappedFontObject);
3910 aDA.append( nMappedFontObject );
3911 aDA.append(
" 0 Tf" );
3913 OStringBuffer aDR( 32 );
3914 aDR.append(
"/Font " );
3916 aDR.append(
" 0 R" );
3917 rBox.
m_aDRDict = aDR.makeStringAndClear();
3924 sal_Int32 nCharXOffset = 1000 - 787;
3926 nCharXOffset /= 2000;
3927 sal_Int32 nCharYOffset = 1000 - (820-143);
3929 nCharYOffset /= 2000;
3934 aDA.append(
"/Tx BMC\nq BT\n" );
3938 aDA.append( nMappedFontObject );
3941 aDA.append(
" Tf\n" );
3945 aDA.append(
" Td <" );
3946 appendHex( nMappedGlyph, aDA );
3947 aDA.append(
"> Tj\nET\nQ\nEMC\n" );
3967 if( rWidget.Background || rWidget.Border )
3979 sal_Int32 nDelta = aFontSize.
Height()/10;
4005 OStringBuffer aLW( 32 );
4008 aLW.append(
" w " );
4029 OStringBuffer aDA( 256 );
4030 aDA.append(
"/Tx BMC\nq BT\n" );
4034 aDA.append(
" 0 0 Td\nET\nQ\n" );
4059 OString aStandardAppearance;
4071 rAnnotDict.append(
"/AP<<\n" );
4074 rAnnotDict.append(
"/" );
4075 rAnnotDict.append( dict_item.first );
4076 bool bUseSubDict = (dict_item.second.size() > 1);
4090 rAnnotDict.append( bUseSubDict ?
"<<" :
" " );
4092 for (
auto const& stream_item : dict_item.second)
4095 dict_item.second[ stream_item.first ] =
nullptr;
4099 sal_Int64 nStreamLen = pAppearanceStream->
TellEnd();
4107 OStringBuffer aLine;
4108 aLine.append( nObject );
4110 aLine.append(
" 0 obj\n"
4115 aLine.append(
" " );
4120 aLine.append(
" 0 R\n"
4122 aLine.append( nStreamLen );
4123 aLine.append(
"\n" );
4125 aLine.append(
"/Filter/FlateDecode\n" );
4126 aLine.append(
">>\nstream\n" );
4135 rAnnotDict.append(
" /" );
4136 rAnnotDict.append( stream_item.first );
4137 rAnnotDict.append(
" " );
4139 rAnnotDict.append( nObject );
4140 rAnnotDict.append(
" 0 R" );
4142 delete pAppearanceStream;
4145 rAnnotDict.append( bUseSubDict ?
">>\n" :
"\n" );
4147 rAnnotDict.append(
">>\n" );
4148 if( !aStandardAppearance.isEmpty() )
4150 rAnnotDict.append(
"/AS /" );
4151 rAnnotDict.append( aStandardAppearance );
4152 rAnnotDict.append(
"\n" );
4164 for(
int a = 0;
a < nAnnots;
a++ )
4175 auto stream_it = app_it->second.find(
"Yes" );
4176 if( stream_it != app_it->second.end() )
4179 app_it->second.erase( stream_it );
4182 (app_it->second)[
aBuf.makeStringAndClear() ] = pStream;
4185 SAL_INFO(
"vcl.pdfwriter",
"error: CheckBox without \"Yes\" stream" );
4194 auto stream_it = app_it->second.find(
"Off" );
4195 if( stream_it != app_it->second.end() )
4198 app_it->second.erase( stream_it );
4201 (app_it->second)[
aBuf.makeStringAndClear() ] = pStream;
4204 SAL_INFO(
"vcl.pdfwriter",
"error: CheckBox without \"Off\" stream" );
4209 OStringBuffer aLine( 1024 );
4210 OStringBuffer aValue( 256 );
4212 aLine.append(
" 0 obj\n"
4221 aLine.append(
"/Type/Annot/Subtype/Widget/F " );
4225 aLine.append(
"132\n" );
4230 aLine.append(
"4\n" );
4234 aLine.append(
"/Rect[" );
4235 appendFixedInt( rWidget.
m_aRect.
Left()-iRectMargin, aLine );
4236 aLine.append(
' ' );
4237 appendFixedInt( rWidget.
m_aRect.
Top()+iRectMargin, aLine );
4238 aLine.append(
' ' );
4239 appendFixedInt( rWidget.
m_aRect.
Right()+iRectMargin, aLine );
4240 aLine.append(
' ' );
4241 appendFixedInt( rWidget.
m_aRect.
Bottom()-iRectMargin, aLine );
4242 aLine.append(
"]\n" );
4244 aLine.append(
"/FT/" );
4256 aValue.append(
"/" );
4259 aValue.append(
"Off" );
4261 appendName( rWidget.
m_aValue, aValue );
4265 aLine.append(
"Btn" );
4270 aValue.append(
"[" );
4278 aValue.append(
"]" );
4288 aLine.append(
"Ch" );
4292 aLine.append(
"Ch" );
4295 aLine.append(
"Tx" );
4299 aLine.append(
"Sig" );
4305 aLine.append(
"\n" );
4306 aLine.append(
"/P " );
4308 aLine.append(
" 0 R\n" );
4312 aLine.append(
"/Parent " );
4314 aLine.append(
" 0 R\n" );
4316 if( !rWidget.
m_aKids.empty() )
4318 aLine.append(
"/Kids[" );
4319 for(
size_t i = 0; i < rWidget.
m_aKids.size(); i++ )
4321 aLine.append( rWidget.
m_aKids[i] );
4322 aLine.append(
" 0 R" );
4323 aLine.append( ( (i&15) == 15 ) ?
"\n" :
" " );
4325 aLine.append(
"]\n" );
4327 if( !rWidget.
m_aName.isEmpty() )
4329 aLine.append(
"/T" );
4331 aLine.append(
"\n" );
4337 aLine.append(
"/TU" );
4339 aLine.append(
"\n" );
4344 aLine.append(
"/Ff " );
4346 aLine.append(
"\n" );
4348 if( !aValue.isEmpty() )
4350 OString aVal = aValue.makeStringAndClear();
4351 aLine.append(
"/V " );
4352 aLine.append( aVal );
4355 aLine.append( aVal );
4356 aLine.append(
"\n" );
4361 aLine.append(
"/Opt[\n" );
4366 aLine.append(
"\n" );
4371 aLine.append(
"]\n" );
4374 aLine.append(
"/TI " );
4375 aLine.append( nTI );
4376 aLine.append(
"\n" );
4379 aLine.append(
"/I [" );
4380 aLine.append( nTI );
4381 aLine.append(
"]\n" );
4387 aLine.append(
"/MaxLen " );
4389 aLine.append(
"\n" );
4395 OStringBuffer aDest;
4398 aLine.append(
"/AA<</D<</Type/Action/S/GoTo/D " );
4399 aLine.append( aDest.makeStringAndClear() );
4400 aLine.append(
">>>>\n" );
4407 aLine.append(
"/AA<</D<</Type/Action/S/ResetForm>>>>\n" );
4413 aLine.append(
"/AA<</D<</Type/Action/S/SubmitForm/F" );
4415 aLine.append(
"/Flags " );
4417 sal_Int32 nFlags = 0;
4437 aLine.append( nFlags );
4438 aLine.append(
">>>>\n" );
4443 aLine.append(
"/AA<</D<</Type/Action/S/URI/URI(" );
4445 aLine.append(
")>>>>\n" );
4455 aLine.append(
"/DR<<" );
4457 aLine.append(
">>\n" );
4461 aLine.append(
"/DR<</Font<<" );
4463 aLine.append(
">>>>\n" );
4465 aLine.append(
"/DA" );
4467 aLine.append(
"\n" );
4469 aLine.append(
"/Q 1\n" );
4471 aLine.append(
"/Q 2\n" );
4478 aLine.append(
"/MK<<" );
4482 aLine.append(
">>\n" );
4487 aLine.append(
">>\n"
4515 OStringBuffer aLine;
4516 aLine.append(rEmbeddedFile.m_nObject);
4517 aLine.append(
" 0 obj\n");
4518 aLine.append(
"<< /Type /EmbeddedFile /Length ");
4519 aLine.append(static_cast<sal_Int64>(rEmbeddedFile.m_aDataContainer.getSize()));
4520 aLine.append(
" >>\nstream\n");
4524 CHECK_RETURN(
writeBuffer(rEmbeddedFile.m_aDataContainer.getData(), rEmbeddedFile.m_aDataContainer.getSize()));
4526 aLine.append(
"\nendstream\nendobj\n\n");
4533 #define CHECK_RETURN( x ) if( !x ) return false
4548 if( ! page.emit( nTreeNode ) )
4561 sal_Int32 nStructureDict = 0;
4575 OStringBuffer aLine( 2048 );
4576 aLine.append( nTreeNode );
4577 aLine.append(
" 0 obj\n" );
4578 aLine.append(
"<</Type/Pages\n" );
4579 aLine.append(
"/Resources " );
4581 aLine.append(
" 0 R\n" );
4583 double nMediaBoxWidth = 0;
4584 double nMediaBoxHeight = 0;
4585 sal_Int32 nUserUnit = 1;
4586 if( m_aPages.empty() )
4593 for (
auto const& page : m_aPages)
4595 if( page.m_nPageWidth > nMediaBoxWidth )
4597 nMediaBoxWidth = page.m_nPageWidth;
4598 nUserUnit = page.m_nUserUnit;
4600 if( page.m_nPageHeight > nMediaBoxHeight )
4602 nMediaBoxHeight = page.m_nPageHeight;
4603 nUserUnit = page.m_nUserUnit;
4607 aLine.append(
"/MediaBox[ 0 0 " );
4608 aLine.append(nMediaBoxWidth / nUserUnit);
4609 aLine.append(
' ' );
4610 aLine.append(nMediaBoxHeight / nUserUnit);
4611 aLine.append(
" ]\n");
4614 aLine.append(
"/UserUnit ");
4615 aLine.append(nUserUnit);
4618 aLine.append(
"/Kids[ ");
4620 for (
const auto & page : m_aPages)
4622 aLine.append( page.m_nPageObject );
4623 aLine.append(
" 0 R" );
4624 aLine.append( ( (i&15) == 15 ) ?
"\n" :
" " );
4629 aLine.append( static_cast<sal_Int32>(m_aPages.size()) );
4630 aLine.append(
">>\n"
4642 aLine.setLength( 0 );
4644 aLine.append(
" 0 obj\n"
4645 "<</Type/Catalog/Pages " );
4646 aLine.append( nTreeNode );
4647 aLine.append(
" 0 R\n" );
4650 if( nNamedDestinationsDictionary )
4652 aLine.append(
"/Dests ");
4653 aLine.append( nNamedDestinationsDictionary );
4654 aLine.append(
" 0 R\n" );
4662 aLine.append(
"/PageLayout/SinglePage\n" );
4665 aLine.append(
"/PageLayout/OneColumn\n" );
4669 aLine.append(
"/PageLayout/TwoColumnRight\n" );
4676 aLine.append(
"/PageMode/UseNone\n" );
4679 aLine.append(
"/PageMode/UseOutlines\n" );
4682 aLine.append(
"/PageMode/UseThumbs\n" );
4686 aLine.append(
"/PageMode/FullScreen\n" );
4688 OStringBuffer aInitPageRef;
4692 aInitPageRef.append(
" 0 R" );
4695 aInitPageRef.append(
"0" );
4701 if( aInitPageRef.getLength() > 1 )
4703 aLine.append(
"/OpenAction[" );
4704 aLine.append( aInitPageRef.makeStringAndClear() );
4705 aLine.append(
" /XYZ null null 0]\n" );
4709 aLine.append(
"/OpenAction[" );
4710 aLine.append( aInitPageRef.makeStringAndClear() );
4711 aLine.append(
" /Fit]\n" );
4714 aLine.append(
"/OpenAction[" );
4715 aLine.append( aInitPageRef.makeStringAndClear() );
4716 aLine.append(
" /FitH " );
4718 aLine.append(
"]\n" );
4721 aLine.append(
"/OpenAction[" );
4722 aLine.append( aInitPageRef.makeStringAndClear() );
4723 aLine.append(
" /FitBH " );
4725 aLine.append(
"]\n" );
4728 aLine.append(
"/OpenAction[" );
4729 aLine.append( aInitPageRef.makeStringAndClear() );
4730 aLine.append(
" /XYZ null null " );
4734 aLine.append(
"0" );
4735 aLine.append(
"]\n" );
4747 aLine.append(
"/ViewerPreferences<<" );
4749 aLine.append(
"/HideToolbar true\n" );
4751 aLine.append(
"/HideMenubar true\n" );
4753 aLine.append(
"/HideWindowUI true\n" );
4755 aLine.append(
"/FitWindow true\n" );
4757 aLine.append(
"/CenterWindow true\n" );
4759 aLine.append(
"/DisplayDocTitle true\n" );
4761 aLine.append(
"/Direction/R2L\n" );
4767 aLine.append(
"/NonFullScreenPageMode/UseNone\n" );
4770 aLine.append(
"/NonFullScreenPageMode/UseOutlines\n" );
4773 aLine.append(
"/NonFullScreenPageMode/UseThumbs\n" );
4776 aLine.append(
">>\n" );
4781 aLine.append(
"/Outlines " );
4782 aLine.append( nOutlineDict );
4783 aLine.append(
" 0 R\n" );
4785 if( nStructureDict )
4787 aLine.append(
"/StructTreeRoot " );
4788 aLine.append( nStructureDict );
4789 aLine.append(
" 0 R\n" );
4795 OUString aLanguage, aScript, aCountry;
4797 if (!aLanguage.isEmpty())
4799 OUStringBuffer aLocBuf( 16 );
4800 aLocBuf.append( aLanguage );
4801 if( !aCountry.isEmpty() )
4803 aLocBuf.append(
'-' );
4804 aLocBuf.append( aCountry );
4806 aLine.append(
"/Lang" );
4808 aLine.append(
"\n" );
4813 aLine.append(
"/MarkInfo<</Marked true>>\n" );
4817 aLine.append(
"/AcroForm<</Fields[\n" );
4820 for(
int j = 0; j < nWidgets; j++ )
4826 aLine.append( (nOut++ % 5)==4 ?
" 0 R\n" :
" 0 R " );
4829 aLine.append(
"\n]" );
4831 #if HAVE_FEATURE_NSS
4833 aLine.append(
"/SigFlags 3");
4836 aLine.append(
"/DR " );
4838 aLine.append(
" 0 R" );
4841 #
if HAVE_FEATURE_NSS
4845 aLine.append(
">>\n" );
4847 aLine.append(
"/NeedAppearances true>>\n" );
4851 if( nOutputIntentObject )
4853 aLine.append(
"/OutputIntents[");
4854 aLine.append( nOutputIntentObject );
4855 aLine.append(
" 0 R]" );
4858 if( nMetadataObject )
4860 aLine.append(
"/Metadata ");
4861 aLine.append( nMetadataObject );
4862 aLine.append(
" 0 R" );
4865 aLine.append(
">>\n"
4867 return writeBuffer( aLine.getStr(), aLine.getLength() );
4870 #if HAVE_FEATURE_NSS
4877 OStringBuffer aLine( 0x5000 );
4879 aLine.append(
" 0 obj\n" );
4880 aLine.append(
"<</Contents <" );
4882 sal_uInt64 nOffset = ~0
U;
4888 OStringBuffer aContentFiller( MAX_SIGNATURE_CONTENT_LENGTH );
4890 aLine.append( aContentFiller.makeStringAndClear() );
4891 aLine.append(
">\n/Type/Sig/SubFilter/adbe.pkcs7.detached");
4895 aLine.append(
"/Name" );
4899 aLine.append(
" /M ");
4902 aLine.append(
" /ByteRange [ 0 ");
4904 aLine.append(
" " );
4906 aLine.append(
" " );
4913 OStringBuffer aByteRangeFiller( 100 );
4915 aLine.append( aByteRangeFiller.makeStringAndClear() );
4916 aLine.append(
" /Filter/Adobe.PPKMS");
4921 aLine.append(
"/Reason");
4927 aLine.append(
"/Location");
4933 aLine.append(
"/ContactInfo");
4937 aLine.append(
" >>\nendobj\n\n" );
4939 return writeBuffer( aLine.getStr(), aLine.getLength() );
4948 sal_uInt64 nOffset = ~0
U;
4954 sal_uInt64 nWritten = 0;
4956 OString aByteRangeNo = OString::number( nLastByteRangeNo ) +
" ]";
4958 if (
m_aFile.write(aByteRangeNo.getStr(), aByteRangeNo.getLength(), nWritten) != osl::File::E_None)
4970 sal_uInt64 bytesRead1;
4976 SAL_WARN(
"vcl.pdfwriter",
"First buffer read failed");
4980 std::unique_ptr<char[]> buffer2(
new char[nLastByteRangeNo + 1]);
4981 sal_uInt64 bytesRead2;
4984 osl::File::E_None !=
m_aFile.read(buffer2.get(), nLastByteRangeNo, bytesRead2) ||
4985 bytesRead2 != static_cast<sal_uInt64>(nLastByteRangeNo))
4987 SAL_WARN(
"vcl.pdfwriter",
"Second buffer read failed");
4991 OStringBuffer aCMSHexBuffer;
4993 aSigning.AddDataRange(buffer1.get(), bytesRead1);
4994 aSigning.AddDataRange(buffer2.get(), bytesRead2);
4997 if (!aSigning.Sign(aCMSHexBuffer))
4999 SAL_WARN(
"vcl.pdfwriter",
"PDFWriter::Sign() failed");
5008 m_aFile.write(aCMSHexBuffer.getStr(), aCMSHexBuffer.getLength(), nWritten);
5010 return osl::File::E_None ==
m_aFile.setPos(osl_Pos_Absolut, nOffset);
5013 #endif //HAVE_FEATURE_NSS
5021 OStringBuffer aLine( 1024 );
5022 aLine.append( nObject );
5023 aLine.append(
" 0 obj\n"
5027 aLine.append(
"/Title" );
5029 aLine.append(
"\n" );
5033 aLine.append(
"/Author" );
5035 aLine.append(
"\n" );
5039 aLine.append(
"/Subject" );
5041 aLine.append(
"\n" );
5045 aLine.append(
"/Keywords" );
5047 aLine.append(
"\n" );
5051 aLine.append(
"/Creator" );
5053 aLine.append(
"\n" );
5057 aLine.append(
"/Producer" );
5059 aLine.append(
"\n" );
5062 aLine.append(
"/CreationDate" );
5064 aLine.append(
">>\nendobj\n\n" );
5065 if( !
writeBuffer( aLine.getStr(), aLine.getLength() ) )
5087 OStringBuffer aLine( 1024 );
5088 aLine.append( nObject );
5089 aLine.append(
" 0 obj\n"
5093 for( nDestID = 0; nDestID < nCount; nDestID++ )
5107 aLine.append(
'/' );
5108 appendDestinationName( aName, aLine );
5109 aLine.append(
'[' );
5112 aLine.append(
" 0 R" );
5118 aLine.append(
"/XYZ " );
5120 aLine.append(
' ' );
5122 aLine.append(
" 0" );
5125 aLine.append(
"/FitR " );
5127 aLine.append(
' ' );
5128 appendFixedInt( rDest.
m_aRect.
Top(), aLine );
5129 aLine.append(
' ' );
5131 aLine.append(
' ' );
5135 aLine.append(
"]\n" );
5139 aLine.append(
">>\nendobj\n\n" );
5140 if( !
writeBuffer( aLine.getStr(), aLine.getLength() ) )
5157 OStringBuffer aLine( 1024 );
5161 aLine.append( nICCObject );
5163 aLine.append(
" 0 obj\n<</N 3/Length " );
5164 aLine.append( nStreamLengthObject );
5165 aLine.append(
" 0 R" );
5167 aLine.append(
"/Filter/FlateDecode" );
5168 aLine.append(
">>\nstream\n" );
5170 if ( !
writeBuffer( aLine.getStr(), aLine.getLength() ) )
return 0;
5172 sal_uInt64 nBeginStreamPos = 0;
5173 if (osl::File::E_None !=
m_aFile.getPos(nBeginStreamPos))
5177 cmsHPROFILE hProfile = cmsCreate_sRGBProfile();
5179 cmsSetProfileVersion(hProfile, 2.1);
5180 cmsUInt32Number nBytesNeeded = 0;
5181 cmsSaveProfileToMem(hProfile,
nullptr, &nBytesNeeded);
5184 std::vector<unsigned char>
aBuffer(nBytesNeeded);
5185 cmsSaveProfileToMem(hProfile, aBuffer.data(), &nBytesNeeded);
5186 cmsCloseProfile(hProfile);
5187 bool written =
writeBuffer( aBuffer.data(),
static_cast<sal_Int32
>(aBuffer.size()) );
5191 sal_uInt64 nEndStreamPos = 0;
5192 if (
m_aFile.getPos(nEndStreamPos) != osl::File::E_None)
5197 if( !
writeBuffer(
"\nendstream\nendobj\n\n", 19 ) )