summaryrefslogtreecommitdiff
path: root/vcl/source/gdi
diff options
context:
space:
mode:
Diffstat (limited to 'vcl/source/gdi')
-rw-r--r--vcl/source/gdi/outdev3.cxx2
-rw-r--r--vcl/source/gdi/pdfwriter_impl.cxx1272
-rw-r--r--vcl/source/gdi/pdfwriter_impl.hxx55
3 files changed, 699 insertions, 630 deletions
diff --git a/vcl/source/gdi/outdev3.cxx b/vcl/source/gdi/outdev3.cxx
index 51aad0790a26..28fa4f8f5461 100644
--- a/vcl/source/gdi/outdev3.cxx
+++ b/vcl/source/gdi/outdev3.cxx
@@ -5601,6 +5601,8 @@ void OutputDevice::DrawTextArray( const Point& rStartPt, const String& rStr,
if ( !IsDeviceOutputNecessary() )
return;
+ if( !mpGraphics && !ImplGetGraphics() )
+ return;
if( mbInitClipRegion )
ImplInitClipRegion();
if( mbOutputClipped )
diff --git a/vcl/source/gdi/pdfwriter_impl.cxx b/vcl/source/gdi/pdfwriter_impl.cxx
index c0205f1f325d..d42e736960d2 100644
--- a/vcl/source/gdi/pdfwriter_impl.cxx
+++ b/vcl/source/gdi/pdfwriter_impl.cxx
@@ -2814,37 +2814,6 @@ sal_Int32 PDFWriterImpl::emitBuiltinFont( const ImplFontData* pFont, sal_Int32 n
return nFontObject;
}
-typedef int ThreeInts[3];
-static bool getPfbSegmentLengths( const unsigned char* pFontBytes, int nByteLen,
- ThreeInts& rSegmentLengths )
-{
- if( !pFontBytes || (nByteLen < 0) )
- return false;
- const unsigned char* pPtr = pFontBytes;
- const unsigned char* pEnd = pFontBytes + nByteLen;
-
- for( int i = 0; i < 3; ++i) {
- // read segment1 header
- if( pPtr+6 >= pEnd )
- return false;
- if( (pPtr[0] != 0x80) || (pPtr[1] >= 0x03) )
- return false;
- const int nLen = (pPtr[5]<<24) + (pPtr[4]<<16) + (pPtr[3]<<8) + pPtr[2];
- if( nLen <= 0)
- return false;
- rSegmentLengths[i] = nLen;
- pPtr += nLen + 6;
- }
-
- // read segment-end header
- if( pPtr+2 >= pEnd )
- return false;
- if( (pPtr[0] != 0x80) || (pPtr[1] != 0x03) )
- return false;
-
- return true;
-}
-
std::map< sal_Int32, sal_Int32 > PDFWriterImpl::emitSystemFont( const ImplFontData* pFont, EmbedFont& rEmbed )
{
std::map< sal_Int32, sal_Int32 > aRet;
@@ -2960,6 +2929,41 @@ std::map< sal_Int32, sal_Int32 > PDFWriterImpl::emitSystemFont( const ImplFontDa
return aRet;
}
+typedef int ThreeInts[3];
+static bool getPfbSegmentLengths( const unsigned char* pFontBytes, int nByteLen,
+ ThreeInts& rSegmentLengths )
+{
+ if( !pFontBytes || (nByteLen < 0) )
+ return false;
+ const unsigned char* pPtr = pFontBytes;
+ const unsigned char* pEnd = pFontBytes + nByteLen;
+
+ for( int i = 0; i < 3; ++i) {
+ // read segment1 header
+ if( pPtr+6 >= pEnd )
+ return false;
+ if( (pPtr[0] != 0x80) || (pPtr[1] >= 0x03) )
+ return false;
+ const int nLen = (pPtr[5]<<24) + (pPtr[4]<<16) + (pPtr[3]<<8) + pPtr[2];
+ if( nLen <= 0)
+ return false;
+ rSegmentLengths[i] = nLen;
+ pPtr += nLen + 6;
+ }
+
+ // read segment-end header
+ if( pPtr+2 >= pEnd )
+ return false;
+ if( (pPtr[0] != 0x80) || (pPtr[1] != 0x03) )
+ return false;
+
+ return true;
+}
+
+struct FontException : public std::exception
+{
+};
+
// TODO: always subset instead of embedding the full font => this method becomes obsolete then
std::map< sal_Int32, sal_Int32 > PDFWriterImpl::emitEmbeddedFont( const ImplFontData* pFont, EmbedFont& rEmbed )
{
@@ -2979,10 +2983,16 @@ std::map< sal_Int32, sal_Int32 > PDFWriterImpl::emitEmbeddedFont( const ImplFont
sal_Int32 nToUnicodeStream = 0;
sal_uInt8 nEncoding[256];
sal_Ucs nEncodedCodes[256];
+ std::vector<sal_Ucs> aUnicodes;
+ aUnicodes.reserve( 256 );
+ sal_Int32 pUnicodesPerGlyph[256];
+ sal_Int32 pEncToUnicodeIndex[256];
if( pEncoding )
{
- memset( nEncodedCodes, 0, sizeof(nEncodedCodes) );
- memset( nEncoding, 0, sizeof(nEncoding) );
+ rtl_zeroMemory( nEncoding, sizeof(nEncoding) );
+ rtl_zeroMemory( nEncodedCodes, sizeof(nEncodedCodes) );
+ rtl_zeroMemory( pUnicodesPerGlyph, sizeof(pUnicodesPerGlyph) );
+ rtl_zeroMemory( pEncToUnicodeIndex, sizeof(pEncToUnicodeIndex) );
for( Ucs2SIntMap::const_iterator it = pEncoding->begin(); it != pEncoding->end(); ++it )
{
if( it->second != -1 )
@@ -2990,6 +3000,9 @@ std::map< sal_Int32, sal_Int32 > PDFWriterImpl::emitEmbeddedFont( const ImplFont
sal_Int32 nCode = (sal_Int32)(it->second & 0x000000ff);
nEncoding[ nCode ] = static_cast<sal_uInt8>( nCode );
nEncodedCodes[ nCode ] = it->first;
+ pEncToUnicodeIndex[ nCode ] = static_cast<sal_Int32>(aUnicodes.size());
+ aUnicodes.push_back( it->first );
+ pUnicodesPerGlyph[ nCode ] = 1;
}
}
}
@@ -2999,553 +3012,525 @@ std::map< sal_Int32, sal_Int32 > PDFWriterImpl::emitEmbeddedFont( const ImplFont
const unsigned char* pFontData = NULL;
long nFontLen = 0;
sal_Int32 nLength1, nLength2;
- if( (pFontData = (const unsigned char*)m_pReferenceDevice->mpGraphics->GetEmbedFontData( pFont, nEncodedCodes, pWidths, aInfo, &nFontLen )) != NULL )
- {
- if( (aInfo.m_nFontType & FontSubsetInfo::ANY_TYPE1) == 0 )
- goto streamend;
- // see whether it is pfb or pfa; if it is a pfb, fill ranges
- // of 6 bytes that are not part of the font program
- std::list< int > aSections;
- std::list< int >::const_iterator it;
- int nIndex = 0;
- while( pFontData[nIndex] == 0x80 && nIndex < nFontLen-1 )
- {
- aSections.push_back( nIndex );
- if( pFontData[nIndex+1] == 0x03 )
- break;
- sal_Int32 nBytes =
+ try
+ {
+ if( (pFontData = (const unsigned char*)m_pReferenceDevice->mpGraphics->GetEmbedFontData( pFont, nEncodedCodes, pWidths, aInfo, &nFontLen )) != NULL )
+ {
+ if( (aInfo.m_nFontType & FontSubsetInfo::ANY_TYPE1) == 0 )
+ throw FontException();
+ // see whether it is pfb or pfa; if it is a pfb, fill ranges
+ // of 6 bytes that are not part of the font program
+ std::list< int > aSections;
+ std::list< int >::const_iterator it;
+ int nIndex = 0;
+ while( pFontData[nIndex] == 0x80 && nIndex < nFontLen-1 )
+ {
+ aSections.push_back( nIndex );
+ if( pFontData[nIndex+1] == 0x03 )
+ break;
+ sal_Int32 nBytes =
((sal_Int32)pFontData[nIndex+2]) |
((sal_Int32)pFontData[nIndex+3]) << 8 |
((sal_Int32)pFontData[nIndex+4]) << 16 |
((sal_Int32)pFontData[nIndex+5]) << 24;
- nIndex += nBytes+6;
- }
-
- // search for eexec
- // TODO: use getPfbSegmentLengths() if possible to skip the search thingies below
- nIndex = 0;
- int nEndAsciiIndex;
- int nBeginBinaryIndex;
- int nEndBinaryIndex;
- do
- {
- while( nIndex < nFontLen-4 &&
- ( pFontData[nIndex] != 'e' ||
- pFontData[nIndex+1] != 'e' ||
- pFontData[nIndex+2] != 'x' ||
- pFontData[nIndex+3] != 'e' ||
- pFontData[nIndex+4] != 'c'
- )
- )
- nIndex++;
- // check whether we are in a excluded section
- for( it = aSections.begin(); it != aSections.end() && (nIndex < *it || nIndex > ((*it) + 5) ); ++it )
- ;
- } while( it != aSections.end() && nIndex < nFontLen-4 );
- // this should end the ascii part
- if( nIndex > nFontLen-5 )
- goto streamend;
-
- nEndAsciiIndex = nIndex+4;
- // now count backwards until we can account for 512 '0'
- // which is the endmarker of the (hopefully) binary data
- // do not count the pfb header sections
- int nFound = 0;
- nIndex = nFontLen-1;
- while( nIndex > 0 && nFound < 512 )
- {
- for( it = aSections.begin(); it != aSections.end() && (nIndex < *it || nIndex > ((*it) + 5) ); ++it )
- ;
- if( it == aSections.end() )
- {
- // inside the 512 '0' block there may only be whitespace
- // according to T1 spec; probably it would be to simple
- // if all fonts complied
- if( pFontData[nIndex] == '0' )
- nFound++;
- else if( nFound > 0 &&
- pFontData[nIndex] != '\r' &&
- pFontData[nIndex] != '\t' &&
- pFontData[nIndex] != '\n' &&
- pFontData[nIndex] != ' ' )
- break;
+ nIndex += nBytes+6;
}
- nIndex--;
- }
-
- if( nIndex < 1 || nIndex <= nEndAsciiIndex )
- goto streamend;
- // there may be whitespace to ignore before the 512 '0'
- while( pFontData[nIndex] == '\r' || pFontData[nIndex] == '\n' )
- {
- nIndex--;
- for( it = aSections.begin(); it != aSections.end() && (nIndex < *it || nIndex > ((*it) + 5) ); ++it )
- ;
- if( it != aSections.end() )
- {
- nIndex = (*it)-1;
- break; // this is surely a binary boundary, in ascii case it wouldn't matter
- }
- }
- nEndBinaryIndex = nIndex;
- // and count forward again to the point where we have nFound '0'
- // to get the corect value for nLength3
- sal_Int32 nLength3 = 0;
- sal_Int32 nL3Index = nIndex;
- while( nFound && nL3Index < nFontLen )
- {
- for( it = aSections.begin(); it != aSections.end() && (nL3Index < *it || nL3Index > ((*it) + 5) ); ++it )
- ;
- if( it == aSections.end() )
+ // search for eexec
+ // TODO: use getPfbSegmentLengths() if possible to skip the search thingies below
+ nIndex = 0;
+ int nEndAsciiIndex;
+ int nBeginBinaryIndex;
+ int nEndBinaryIndex;
+ do
{
- // inside the 512 '0' block there may only be whitespace
- // according to T1 spec; probably it would be to simple
- // if all fonts complied
- if( pFontData[nL3Index] == '0' )
- nFound--;
- nLength3++;
- }
- nL3Index++;
- }
-
- // search for beginning of binary section
- nBeginBinaryIndex = nEndAsciiIndex;
- do
- {
- nBeginBinaryIndex++;
- for( it = aSections.begin(); it != aSections.end() && (nBeginBinaryIndex < *it || nBeginBinaryIndex > ((*it) + 5) ); ++it )
- ;
- } while( nBeginBinaryIndex < nEndBinaryIndex &&
- ( pFontData[nBeginBinaryIndex] == '\r' ||
- pFontData[nBeginBinaryIndex] == '\n' ||
- it != aSections.end() ) );
-
- // it seems to be vital to copy the exact whitespace between binary data
- // and eexec, else a invalid font results. so make nEndAsciiIndex
- // always immediate in front of nBeginBinaryIndex
- nEndAsciiIndex = nBeginBinaryIndex-1;
- for( it = aSections.begin(); it != aSections.end() && (nEndAsciiIndex < *it || nEndAsciiIndex > ((*it)+5)); ++it )
- ;
- if( it != aSections.end() )
- nEndAsciiIndex = (*it)-1;
-
- nLength1 = nEndAsciiIndex+1; // including the last character
- for( it = aSections.begin(); it != aSections.end() && *it < nEndAsciiIndex; ++it )
- nLength1 -= 6; // decrease by pfb section size
-
- // if the first four bytes are all ascii hex characters, then binary data
- // has to be converted to real binary data
- for( nIndex = 0; nIndex < 4 &&
- ( ( pFontData[ nBeginBinaryIndex+nIndex ] >= '0' && pFontData[ nBeginBinaryIndex+nIndex ] <= '9' ) ||
- ( pFontData[ nBeginBinaryIndex+nIndex ] >= 'a' && pFontData[ nBeginBinaryIndex+nIndex ] <= 'f' ) ||
- ( pFontData[ nBeginBinaryIndex+nIndex ] >= 'A' && pFontData[ nBeginBinaryIndex+nIndex ] <= 'F' )
- ); ++nIndex )
- ;
- bool bConvertHexData = true;
- if( nIndex < 4 )
- {
- bConvertHexData = false;
- nLength2 = nEndBinaryIndex - nBeginBinaryIndex + 1; // include the last byte
- for( it = aSections.begin(); it != aSections.end(); ++it )
- if( *it > nBeginBinaryIndex && *it < nEndBinaryIndex )
- nLength2 -= 6;
- }
- else
- {
- // count the hex ascii characters to get nLength2
- nLength2 = 0;
- int nNextSectionIndex = 0;
- for( it = aSections.begin(); it != aSections.end() && *it < nBeginBinaryIndex; ++it )
- ;
- if( it != aSections.end() )
- nNextSectionIndex = *it;
- for( nIndex = nBeginBinaryIndex; nIndex <= nEndBinaryIndex; nIndex++ )
+ while( nIndex < nFontLen-4 &&
+ ( pFontData[nIndex] != 'e' ||
+ pFontData[nIndex+1] != 'e' ||
+ pFontData[nIndex+2] != 'x' ||
+ pFontData[nIndex+3] != 'e' ||
+ pFontData[nIndex+4] != 'c'
+ )
+ )
+ nIndex++;
+ // check whether we are in a excluded section
+ for( it = aSections.begin(); it != aSections.end() && (nIndex < *it || nIndex > ((*it) + 5) ); ++it )
+ ;
+ } while( it != aSections.end() && nIndex < nFontLen-4 );
+ // this should end the ascii part
+ if( nIndex > nFontLen-5 )
+ throw FontException();
+
+ nEndAsciiIndex = nIndex+4;
+ // now count backwards until we can account for 512 '0'
+ // which is the endmarker of the (hopefully) binary data
+ // do not count the pfb header sections
+ int nFound = 0;
+ nIndex = nFontLen-1;
+ while( nIndex > 0 && nFound < 512 )
{
- if( nIndex == nNextSectionIndex )
+ for( it = aSections.begin(); it != aSections.end() && (nIndex < *it || nIndex > ((*it) + 5) ); ++it )
+ ;
+ if( it == aSections.end() )
{
- nIndex += 6;
- ++it;
- nNextSectionIndex = (it == aSections.end() ? 0 : *it );
+ // inside the 512 '0' block there may only be whitespace
+ // according to T1 spec; probably it would be to simple
+ // if all fonts complied
+ if( pFontData[nIndex] == '0' )
+ nFound++;
+ else if( nFound > 0 &&
+ pFontData[nIndex] != '\r' &&
+ pFontData[nIndex] != '\t' &&
+ pFontData[nIndex] != '\n' &&
+ pFontData[nIndex] != ' ' )
+ break;
}
- if( ( pFontData[ nIndex ] >= '0' && pFontData[ nIndex ] <= '9' ) ||
- ( pFontData[ nIndex ] >= 'a' && pFontData[ nIndex ] <= 'f' ) ||
- ( pFontData[ nIndex ] >= 'A' && pFontData[ nIndex ] <= 'F' ) )
- nLength2++;
+ nIndex--;
}
- DBG_ASSERT( !(nLength2 & 1), "uneven number of hex chars in binary pfa section" );
- nLength2 /= 2;
- }
-
- // now we can actually write the font stream !
-#if OSL_DEBUG_LEVEL > 1
- {
- OStringBuffer aLine( " PDFWriterImpl::emitEmbeddedFont" );
- emitComment( aLine.getStr() );
- }
-#endif
- OStringBuffer aLine( 512 );
- nStreamObject = createObject();
- if( !updateObject(nStreamObject))
- goto streamend;
- sal_Int32 nStreamLengthObject = createObject();
- aLine.append( nStreamObject );
- aLine.append( " 0 obj\n"
- "<</Length " );
- aLine.append( nStreamLengthObject );
- aLine.append( " 0 R"
-#ifndef DEBUG_DISABLE_PDFCOMPRESSION
- "/Filter/FlateDecode"
-#endif
- "/Length1 " );
- aLine.append( nLength1 );
- aLine.append( " /Length2 " );
- aLine.append( nLength2 );
- aLine.append( " /Length3 ");
- aLine.append( nLength3 );
- aLine.append( ">>\n"
- "stream\n" );
- if( !writeBuffer( aLine.getStr(), aLine.getLength() ) )
- goto streamend;
- sal_uInt64 nBeginStreamPos = 0;
- osl_getFilePos( m_aFile, &nBeginStreamPos );
+ if( nIndex < 1 || nIndex <= nEndAsciiIndex )
+ throw FontException();
- beginCompression();
- checkAndEnableStreamEncryption( nStreamObject );
-
- // write ascii section
- if( aSections.begin() == aSections.end() )
- {
- if( ! writeBuffer( pFontData, nEndAsciiIndex+1 ) )
- {
- endCompression();
- disableStreamEncryption();
- goto streamend;
- }
- }
- else
- {
- // first section always starts at 0
- it = aSections.begin();
- nIndex = (*it)+6;
- ++it;
- while( *it < nEndAsciiIndex )
+ // nLength3 is the rest of the file - excluding any section headers
+ // nIndex now points to the first of the 512 '0' characters marking the
+ // fixed content portion
+ sal_Int32 nLength3 = nFontLen - nIndex;
+ for( it = aSections.begin(); it != aSections.end(); ++it )
{
- if( ! writeBuffer( pFontData+nIndex, (*it)-nIndex ) )
+ if( *it >= nIndex )
{
- endCompression();
- disableStreamEncryption();
- goto streamend;
+ // special case: nIndex inside a section marker
+ if( nIndex >= (*it) && (*it)+5 > nIndex )
+ nLength3 -= (*it)+5 - nIndex;
+ else
+ {
+ if( *it < nFontLen - 6 )
+ nLength3 -= 6;
+ else // the last section 0x8003 is only 2 bytes after all
+ nLength3 -= (nFontLen - *it);
+ }
}
- nIndex = (*it)+6;
- ++it;
}
- // write partial last section
- if( ! writeBuffer( pFontData+nIndex, nEndAsciiIndex-nIndex+1 ) )
- {
- endCompression();
- disableStreamEncryption();
- goto streamend;
- }
- }
- // write binary section
- if( ! bConvertHexData )
- {
- if( aSections.begin() == aSections.end() )
+ // there may be whitespace to ignore before the 512 '0'
+ while( pFontData[nIndex] == '\r' || pFontData[nIndex] == '\n' )
{
- if( ! writeBuffer( pFontData+nBeginBinaryIndex, nFontLen-nBeginBinaryIndex ) )
+ nIndex--;
+ for( it = aSections.begin(); it != aSections.end() && (nIndex < *it || nIndex > ((*it) + 5) ); ++it )
+ ;
+ if( it != aSections.end() )
{
- endCompression();
- disableStreamEncryption();
- goto streamend;
+ nIndex = (*it)-1;
+ break; // this is surely a binary boundary, in ascii case it wouldn't matter
}
}
- else
+ nEndBinaryIndex = nIndex;
+
+ // search for beginning of binary section
+ nBeginBinaryIndex = nEndAsciiIndex;
+ do
{
- for( it = aSections.begin(); *it < nBeginBinaryIndex; ++it )
+ nBeginBinaryIndex++;
+ for( it = aSections.begin(); it != aSections.end() && (nBeginBinaryIndex < *it || nBeginBinaryIndex > ((*it) + 5) ); ++it )
;
- // write first partial section
- if( ! writeBuffer( pFontData+nBeginBinaryIndex, (*it) - nBeginBinaryIndex ) )
- {
- endCompression();
- disableStreamEncryption();
- goto streamend;
- }
- // write following sections
- while( it != aSections.end() )
- {
- nIndex = (*it)+6;
- ++it;
- if( nIndex < nFontLen ) // last section marker is usually the EOF which has only 2 bytes
+ } while( nBeginBinaryIndex < nEndBinaryIndex &&
+ ( pFontData[nBeginBinaryIndex] == '\r' ||
+ pFontData[nBeginBinaryIndex] == '\n' ||
+ it != aSections.end() ) );
+
+ // it seems to be vital to copy the exact whitespace between binary data
+ // and eexec, else a invalid font results. so make nEndAsciiIndex
+ // always immediate in front of nBeginBinaryIndex
+ nEndAsciiIndex = nBeginBinaryIndex-1;
+ for( it = aSections.begin(); it != aSections.end() && (nEndAsciiIndex < *it || nEndAsciiIndex > ((*it)+5)); ++it )
+ ;
+ if( it != aSections.end() )
+ nEndAsciiIndex = (*it)-1;
+
+ nLength1 = nEndAsciiIndex+1; // including the last character
+ for( it = aSections.begin(); it != aSections.end() && *it < nEndAsciiIndex; ++it )
+ nLength1 -= 6; // decrease by pfb section size
+
+ // if the first four bytes are all ascii hex characters, then binary data
+ // has to be converted to real binary data
+ for( nIndex = 0; nIndex < 4 &&
+ ( ( pFontData[ nBeginBinaryIndex+nIndex ] >= '0' && pFontData[ nBeginBinaryIndex+nIndex ] <= '9' ) ||
+ ( pFontData[ nBeginBinaryIndex+nIndex ] >= 'a' && pFontData[ nBeginBinaryIndex+nIndex ] <= 'f' ) ||
+ ( pFontData[ nBeginBinaryIndex+nIndex ] >= 'A' && pFontData[ nBeginBinaryIndex+nIndex ] <= 'F' )
+ ); ++nIndex )
+ ;
+ bool bConvertHexData = true;
+ if( nIndex < 4 )
+ {
+ bConvertHexData = false;
+ nLength2 = nEndBinaryIndex - nBeginBinaryIndex + 1; // include the last byte
+ for( it = aSections.begin(); it != aSections.end(); ++it )
+ if( *it > nBeginBinaryIndex && *it < nEndBinaryIndex )
+ nLength2 -= 6;
+ }
+ else
{
- sal_Int32 nSectionLen = (it == aSections.end()) ? nFontLen - nIndex : (*it) - nIndex;
- if( ! writeBuffer( pFontData+nIndex, nSectionLen ) )
+ // count the hex ascii characters to get nLength2
+ nLength2 = 0;
+ int nNextSectionIndex = 0;
+ for( it = aSections.begin(); it != aSections.end() && *it < nBeginBinaryIndex; ++it )
+ ;
+ if( it != aSections.end() )
+ nNextSectionIndex = *it;
+ for( nIndex = nBeginBinaryIndex; nIndex <= nEndBinaryIndex; nIndex++ )
{
- endCompression();
- disableStreamEncryption();
- goto streamend;
+ if( nIndex == nNextSectionIndex )
+ {
+ nIndex += 6;
+ ++it;
+ nNextSectionIndex = (it == aSections.end() ? 0 : *it );
+ }
+ if( ( pFontData[ nIndex ] >= '0' && pFontData[ nIndex ] <= '9' ) ||
+ ( pFontData[ nIndex ] >= 'a' && pFontData[ nIndex ] <= 'f' ) ||
+ ( pFontData[ nIndex ] >= 'A' && pFontData[ nIndex ] <= 'F' ) )
+ nLength2++;
}
+ DBG_ASSERT( !(nLength2 & 1), "uneven number of hex chars in binary pfa section" );
+ nLength2 /= 2;
}
- }
- }
- }
- else
- {
- unsigned char* pWriteBuffer = (unsigned char*)rtl_allocateMemory( nLength2 );
- memset( pWriteBuffer, 0, nLength2 );
- int nWriteIndex = 0;
-
- int nNextSectionIndex = 0;
- for( it = aSections.begin(); it != aSections.end() && *it < nBeginBinaryIndex; ++it )
- ;
- if( it != aSections.end() )
- nNextSectionIndex = *it;
- for( nIndex = nBeginBinaryIndex; nIndex <= nEndBinaryIndex; nIndex++ )
- {
- if( nIndex == nNextSectionIndex )
- {
- nIndex += 6;
- ++it;
- nNextSectionIndex = (it == aSections.end() ? nFontLen : *it );
- }
- unsigned char cNibble = 0x80;
- if( pFontData[ nIndex ] >= '0' && pFontData[ nIndex ] <= '9' )
- cNibble = pFontData[nIndex] - '0';
- else if( pFontData[ nIndex ] >= 'a' && pFontData[ nIndex ] <= 'f' )
- cNibble = pFontData[nIndex] - 'a' + 10;
- else if( pFontData[ nIndex ] >= 'A' && pFontData[ nIndex ] <= 'F' )
- cNibble = pFontData[nIndex] - 'A' + 10;
- if( cNibble != 0x80 )
- {
- if( !(nWriteIndex & 1 ) )
- cNibble <<= 4;
- pWriteBuffer[ nWriteIndex/2 ] |= cNibble;
- nWriteIndex++;
- }
- }
- if( ! writeBuffer( pWriteBuffer, nLength2 ) )
- {
- endCompression();
- disableStreamEncryption();
- goto streamend;
- }
- rtl_freeMemory( pWriteBuffer );
- if( aSections.empty() )
- {
- if( ! writeBuffer( pFontData+nIndex, nFontLen-nIndex ) )
- {
- endCompression();
- disableStreamEncryption();
- goto streamend;
- }
- }
- else
- {
- // write rest of this section
- if( nIndex < nNextSectionIndex )
- {
- if( ! writeBuffer( pFontData+nIndex, nNextSectionIndex - nIndex ) )
+ // now we can actually write the font stream !
+ #if OSL_DEBUG_LEVEL > 1
{
- endCompression();
- disableStreamEncryption();
- goto streamend;
+ OStringBuffer aLine( " PDFWriterImpl::emitEmbeddedFont" );
+ emitComment( aLine.getStr() );
}
- }
- // write following sections
- while( it != aSections.end() )
- {
- nIndex = (*it)+6;
- ++it;
- if( nIndex < nFontLen ) // last section marker is usually the EOF which has only 2 bytes
+ #endif
+ OStringBuffer aLine( 512 );
+ nStreamObject = createObject();
+ if( !updateObject(nStreamObject))
+ throw FontException();
+ sal_Int32 nStreamLengthObject = createObject();
+ aLine.append( nStreamObject );
+ aLine.append( " 0 obj\n"
+ "<</Length " );
+ aLine.append( nStreamLengthObject );
+ aLine.append( " 0 R"
+ #ifndef DEBUG_DISABLE_PDFCOMPRESSION
+ "/Filter/FlateDecode"
+ #endif
+ "/Length1 " );
+ aLine.append( nLength1 );
+ aLine.append( " /Length2 " );
+ aLine.append( nLength2 );
+ aLine.append( " /Length3 ");
+ aLine.append( nLength3 );
+ aLine.append( ">>\n"
+ "stream\n" );
+ if( !writeBuffer( aLine.getStr(), aLine.getLength() ) )
+ throw FontException();
+
+ sal_uInt64 nBeginStreamPos = 0;
+ osl_getFilePos( m_aFile, &nBeginStreamPos );
+
+ beginCompression();
+ checkAndEnableStreamEncryption( nStreamObject );
+
+ // write ascii section
+ if( aSections.begin() == aSections.end() )
+ {
+ if( ! writeBuffer( pFontData, nEndAsciiIndex+1 ) )
+ throw FontException();
+ }
+ else
{
- sal_Int32 nSectionLen = (it == aSections.end()) ? nFontLen - nIndex : (*it) - nIndex;
- if( ! writeBuffer( pFontData+nIndex, nSectionLen ) )
+ // first section always starts at 0
+ it = aSections.begin();
+ nIndex = (*it)+6;
+ ++it;
+ while( *it < nEndAsciiIndex )
{
- endCompression();
- disableStreamEncryption();
- goto streamend;
+ if( ! writeBuffer( pFontData+nIndex, (*it)-nIndex ) )
+ throw FontException();
+ nIndex = (*it)+6;
+ ++it;
}
+ // write partial last section
+ if( ! writeBuffer( pFontData+nIndex, nEndAsciiIndex-nIndex+1 ) )
+ throw FontException();
}
- }
- }
- }
- endCompression();
- disableStreamEncryption();
-
-
- sal_uInt64 nEndStreamPos = 0;
- osl_getFilePos( m_aFile, &nEndStreamPos );
- // and finally close the stream
- aLine.setLength( 0 );
- aLine.append( "\nendstream\nendobj\n\n" );
- if( ! writeBuffer( aLine.getStr(), aLine.getLength() ) )
- goto streamend;
+ // write binary section
+ if( ! bConvertHexData )
+ {
+ if( aSections.begin() == aSections.end() )
+ {
+ if( ! writeBuffer( pFontData+nBeginBinaryIndex, nFontLen-nBeginBinaryIndex ) )
+ throw FontException();
+ }
+ else
+ {
+ for( it = aSections.begin(); *it < nBeginBinaryIndex; ++it )
+ ;
+ // write first partial section
+ if( ! writeBuffer( pFontData+nBeginBinaryIndex, (*it) - nBeginBinaryIndex ) )
+ throw FontException();
+ // write following sections
+ while( it != aSections.end() )
+ {
+ nIndex = (*it)+6;
+ ++it;
+ if( nIndex < nFontLen ) // last section marker is usually the EOF which has only 2 bytes
+ {
+ sal_Int32 nSectionLen = (it == aSections.end()) ? nFontLen - nIndex : (*it) - nIndex;
+ if( ! writeBuffer( pFontData+nIndex, nSectionLen ) )
+ throw FontException();
+ }
+ }
+ }
+ }
+ else
+ {
+ boost::shared_array<unsigned char> pWriteBuffer( new unsigned char[ nLength2 ] );
+ rtl_zeroMemory( pWriteBuffer.get(), nLength2 );
+ int nWriteIndex = 0;
+
+ int nNextSectionIndex = 0;
+ for( it = aSections.begin(); it != aSections.end() && *it < nBeginBinaryIndex; ++it )
+ ;
+ if( it != aSections.end() )
+ nNextSectionIndex = *it;
+ for( nIndex = nBeginBinaryIndex; nIndex <= nEndBinaryIndex; nIndex++ )
+ {
+ if( nIndex == nNextSectionIndex )
+ {
+ nIndex += 6;
+ ++it;
+ nNextSectionIndex = (it == aSections.end() ? nFontLen : *it );
+ }
+ unsigned char cNibble = 0x80;
+ if( pFontData[ nIndex ] >= '0' && pFontData[ nIndex ] <= '9' )
+ cNibble = pFontData[nIndex] - '0';
+ else if( pFontData[ nIndex ] >= 'a' && pFontData[ nIndex ] <= 'f' )
+ cNibble = pFontData[nIndex] - 'a' + 10;
+ else if( pFontData[ nIndex ] >= 'A' && pFontData[ nIndex ] <= 'F' )
+ cNibble = pFontData[nIndex] - 'A' + 10;
+ if( cNibble != 0x80 )
+ {
+ if( !(nWriteIndex & 1 ) )
+ cNibble <<= 4;
+ pWriteBuffer.get()[ nWriteIndex/2 ] |= cNibble;
+ nWriteIndex++;
+ }
+ }
+ if( ! writeBuffer( pWriteBuffer.get(), nLength2 ) )
+ throw FontException();
+ if( aSections.empty() )
+ {
+ if( ! writeBuffer( pFontData+nIndex, nFontLen-nIndex ) )
+ throw FontException();
+ }
+ else
+ {
+ // write rest of this section
+ if( nIndex < nNextSectionIndex )
+ {
+ if( ! writeBuffer( pFontData+nIndex, nNextSectionIndex - nIndex ) )
+ throw FontException();
+ }
+ // write following sections
+ while( it != aSections.end() )
+ {
+ nIndex = (*it)+6;
+ ++it;
+ if( nIndex < nFontLen ) // last section marker is usually the EOF which has only 2 bytes
+ {
+ sal_Int32 nSectionLen = (it == aSections.end()) ? nFontLen - nIndex : (*it) - nIndex;
+ if( ! writeBuffer( pFontData+nIndex, nSectionLen ) )
+ throw FontException();
+ }
+ }
+ }
+ }
+ endCompression();
+ disableStreamEncryption();
- // write stream length object
- aLine.setLength( 0 );
- if( ! updateObject( nStreamLengthObject ) )
- goto streamend;
- aLine.append( nStreamLengthObject );
- aLine.append( " 0 obj\n" );
- aLine.append( (sal_Int64)(nEndStreamPos-nBeginStreamPos ) );
- aLine.append( "\nendobj\n\n" );
- if( ! writeBuffer( aLine.getStr(), aLine.getLength() ) )
- goto streamend;
- }
- else
- {
- rtl::OStringBuffer aErrorComment( 256 );
- aErrorComment.append( "GetEmbedFontData failed for font \"" );
- aErrorComment.append( OUStringToOString( pFont->GetFamilyName(), RTL_TEXTENCODING_UTF8 ) );
- aErrorComment.append( '\"' );
- if( pFont->GetSlant() == ITALIC_NORMAL )
- aErrorComment.append( " italic" );
- else if( pFont->GetSlant() == ITALIC_OBLIQUE )
- aErrorComment.append( " oblique" );
- aErrorComment.append( " weight=" );
- aErrorComment.append( sal_Int32(pFont->GetWeight()) );
- emitComment( aErrorComment.getStr() );
- }
-
- if( nStreamObject )
- // write font descriptor
- nFontDescriptor = emitFontDescriptor( pFont, aInfo, 0, nStreamObject );
- if( nFontDescriptor )
- {
- if( pEncoding )
- nToUnicodeStream = createToUnicodeCMap( nEncoding, nEncodedCodes, sizeof(nEncoding)/sizeof(nEncoding[0]) );
+ sal_uInt64 nEndStreamPos = 0;
+ osl_getFilePos( m_aFile, &nEndStreamPos );
- // write font object
- sal_Int32 nObject = createObject();
- if( ! updateObject( nObject ) )
- goto streamend;
+ // and finally close the stream
+ aLine.setLength( 0 );
+ aLine.append( "\nendstream\nendobj\n\n" );
+ if( ! writeBuffer( aLine.getStr(), aLine.getLength() ) )
+ throw FontException();
- OStringBuffer aLine( 1024 );
- aLine.append( nObject );
- aLine.append( " 0 obj\n"
- "<</Type/Font/Subtype/Type1/BaseFont/" );
- appendName( aInfo.m_aPSName, aLine );
- aLine.append( "\n" );
- if( !pFont->mbSymbolFlag && pEncoding == 0 )
- aLine.append( "/Encoding/WinAnsiEncoding\n" );
- if( nToUnicodeStream )
- {
- aLine.append( "/ToUnicode " );
- aLine.append( nToUnicodeStream );
- aLine.append( " 0 R\n" );
+ // write stream length object
+ aLine.setLength( 0 );
+ if( ! updateObject( nStreamLengthObject ) )
+ throw FontException();
+ aLine.append( nStreamLengthObject );
+ aLine.append( " 0 obj\n" );
+ aLine.append( (sal_Int64)(nEndStreamPos-nBeginStreamPos ) );
+ aLine.append( "\nendobj\n\n" );
+ if( ! writeBuffer( aLine.getStr(), aLine.getLength() ) )
+ throw FontException();
}
- aLine.append( "/FirstChar 0 /LastChar 255\n"
- "/Widths[" );
- for( int i = 0; i < 256; i++ )
+ else
{
- aLine.append( pWidths[i] );
- aLine.append( ((i&15) == 15) ? "\n" : " " );
- }
- aLine.append( "]\n"
- "/FontDescriptor " );
- aLine.append( nFontDescriptor );
- aLine.append( " 0 R>>\n"
- "endobj\n\n" );
- if( ! writeBuffer( aLine.getStr(), aLine.getLength() ) )
- goto streamend;
-
- nFontObject = nObject;
-
- aRet[ rEmbed.m_nNormalFontID ] = nObject;
+ rtl::OStringBuffer aErrorComment( 256 );
+ aErrorComment.append( "GetEmbedFontData failed for font \"" );
+ aErrorComment.append( OUStringToOString( pFont->GetFamilyName(), RTL_TEXTENCODING_UTF8 ) );
+ aErrorComment.append( '\"' );
+ if( pFont->GetSlant() == ITALIC_NORMAL )
+ aErrorComment.append( " italic" );
+ else if( pFont->GetSlant() == ITALIC_OBLIQUE )
+ aErrorComment.append( " oblique" );
+ aErrorComment.append( " weight=" );
+ aErrorComment.append( sal_Int32(pFont->GetWeight()) );
+ emitComment( aErrorComment.getStr() );
+ }
+
+ if( nStreamObject )
+ // write font descriptor
+ nFontDescriptor = emitFontDescriptor( pFont, aInfo, 0, nStreamObject );
- // write additional encodings
- for( std::list< EmbedEncoding >::iterator enc_it = rEmbed.m_aExtendedEncodings.begin(); enc_it != rEmbed.m_aExtendedEncodings.end(); ++enc_it )
+ if( nFontDescriptor )
{
- sal_Int32 aEncWidths[ 256 ];
- // emit encoding dict
- sal_Int32 nEncObject = createObject();
- if( ! updateObject( nEncObject ) )
- goto streamend;
-
- OutputDevice* pRef = getReferenceDevice();
- pRef->Push( PUSH_FONT | PUSH_MAPMODE );
- pRef->SetMapMode( MapMode( MAP_PIXEL ) );
- Font aFont( pFont->GetFamilyName(), pFont->GetStyleName(), Size( 0, 1000 ) );
- aFont.SetWeight( pFont->GetWeight() );
- aFont.SetItalic( pFont->GetSlant() );
- aFont.SetPitch( pFont->GetPitch() );
- pRef->SetFont( aFont );
- pRef->ImplNewFont();
-
- aLine.setLength( 0 );
- aLine.append( nEncObject );
- aLine.append( " 0 obj\n"
- "<</Type/Encoding/Differences[ 0\n" );
- int nEncoded = 0;
- for( std::vector< EmbedCode >::iterator str_it = enc_it->m_aEncVector.begin(); str_it != enc_it->m_aEncVector.end(); ++str_it )
- {
- String aStr( str_it->m_aUnicode );
- aEncWidths[nEncoded] = pRef->GetTextWidth( aStr );
- nEncodedCodes[nEncoded] = str_it->m_aUnicode;
- nEncoding[nEncoded] = sal::static_int_cast<sal_uInt8>(nEncoded);
-
- aLine.append( " /" );
- aLine.append( str_it->m_aName );
- if( !((++nEncoded) & 15) )
- aLine.append( "\n" );
- }
- aLine.append( "]>>\n"
- "endobj\n\n" );
-
- pRef->Pop();
-
- if( ! writeBuffer( aLine.getStr(), aLine.getLength() ) )
- goto streamend;
-
- nToUnicodeStream = createToUnicodeCMap( nEncoding, nEncodedCodes, nEncoded );
+ if( pEncoding )
+ nToUnicodeStream = createToUnicodeCMap( nEncoding, &aUnicodes[0], pUnicodesPerGlyph, pEncToUnicodeIndex, sizeof(nEncoding)/sizeof(nEncoding[0]) );
- nObject = createObject();
+ // write font object
+ sal_Int32 nObject = createObject();
if( ! updateObject( nObject ) )
- goto streamend;
+ throw FontException();
- aLine.setLength( 0 );
+ OStringBuffer aLine( 1024 );
aLine.append( nObject );
aLine.append( " 0 obj\n"
- "<</Type/Font/Subtype/Type1/BaseFont/" );
+ "<</Type/Font/Subtype/Type1/BaseFont/" );
appendName( aInfo.m_aPSName, aLine );
aLine.append( "\n" );
- aLine.append( "/Encoding " );
- aLine.append( nEncObject );
- aLine.append( " 0 R\n" );
+ if( !pFont->mbSymbolFlag && pEncoding == 0 )
+ aLine.append( "/Encoding/WinAnsiEncoding\n" );
if( nToUnicodeStream )
{
aLine.append( "/ToUnicode " );
aLine.append( nToUnicodeStream );
aLine.append( " 0 R\n" );
}
- aLine.append( "/FirstChar 0\n"
- "/LastChar " );
- aLine.append( (sal_Int32)(nEncoded-1) );
- aLine.append( "\n"
- "/Widths[" );
- for( int i = 0; i < nEncoded; i++ )
+ aLine.append( "/FirstChar 0 /LastChar 255\n"
+ "/Widths[" );
+ for( int i = 0; i < 256; i++ )
{
- aLine.append( aEncWidths[i] );
+ aLine.append( pWidths[i] );
aLine.append( ((i&15) == 15) ? "\n" : " " );
}
- aLine.append( " ]\n"
- "/FontDescriptor " );
+ aLine.append( "]\n"
+ "/FontDescriptor " );
aLine.append( nFontDescriptor );
aLine.append( " 0 R>>\n"
- "endobj\n\n" );
+ "endobj\n\n" );
if( ! writeBuffer( aLine.getStr(), aLine.getLength() ) )
- goto streamend;
+ throw FontException();
- aRet[ enc_it->m_nFontID ] = nObject;
+ nFontObject = nObject;
+
+ aRet[ rEmbed.m_nNormalFontID ] = nObject;
+
+ // write additional encodings
+ for( std::list< EmbedEncoding >::iterator enc_it = rEmbed.m_aExtendedEncodings.begin(); enc_it != rEmbed.m_aExtendedEncodings.end(); ++enc_it )
+ {
+ sal_Int32 aEncWidths[ 256 ];
+ // emit encoding dict
+ sal_Int32 nEncObject = createObject();
+ if( ! updateObject( nEncObject ) )
+ throw FontException();
+
+ OutputDevice* pRef = getReferenceDevice();
+ pRef->Push( PUSH_FONT | PUSH_MAPMODE );
+ pRef->SetMapMode( MapMode( MAP_PIXEL ) );
+ Font aFont( pFont->GetFamilyName(), pFont->GetStyleName(), Size( 0, 1000 ) );
+ aFont.SetWeight( pFont->GetWeight() );
+ aFont.SetItalic( pFont->GetSlant() );
+ aFont.SetPitch( pFont->GetPitch() );
+ pRef->SetFont( aFont );
+ pRef->ImplNewFont();
+
+ aLine.setLength( 0 );
+ aLine.append( nEncObject );
+ aLine.append( " 0 obj\n"
+ "<</Type/Encoding/Differences[ 0\n" );
+ int nEncoded = 0;
+ aUnicodes.clear();
+ for( std::vector< EmbedCode >::iterator str_it = enc_it->m_aEncVector.begin(); str_it != enc_it->m_aEncVector.end(); ++str_it )
+ {
+ String aStr( str_it->m_aUnicode );
+ aEncWidths[nEncoded] = pRef->GetTextWidth( aStr );
+ nEncodedCodes[nEncoded] = str_it->m_aUnicode;
+ nEncoding[nEncoded] = sal::static_int_cast<sal_uInt8>(nEncoded);
+ pEncToUnicodeIndex[nEncoded] = static_cast<sal_Int32>(aUnicodes.size());
+ aUnicodes.push_back( nEncodedCodes[nEncoded] );
+ pUnicodesPerGlyph[nEncoded] = 1;
+
+ aLine.append( " /" );
+ aLine.append( str_it->m_aName );
+ if( !((++nEncoded) & 15) )
+ aLine.append( "\n" );
+ }
+ aLine.append( "]>>\n"
+ "endobj\n\n" );
+
+ pRef->Pop();
+
+ if( ! writeBuffer( aLine.getStr(), aLine.getLength() ) )
+ throw FontException();
+
+ nToUnicodeStream = createToUnicodeCMap( nEncoding, &aUnicodes[0], pUnicodesPerGlyph, pEncToUnicodeIndex, nEncoded );
+
+ nObject = createObject();
+ if( ! updateObject( nObject ) )
+ throw FontException();
+
+ aLine.setLength( 0 );
+ aLine.append( nObject );
+ aLine.append( " 0 obj\n"
+ "<</Type/Font/Subtype/Type1/BaseFont/" );
+ appendName( aInfo.m_aPSName, aLine );
+ aLine.append( "\n" );
+ aLine.append( "/Encoding " );
+ aLine.append( nEncObject );
+ aLine.append( " 0 R\n" );
+ if( nToUnicodeStream )
+ {
+ aLine.append( "/ToUnicode " );
+ aLine.append( nToUnicodeStream );
+ aLine.append( " 0 R\n" );
+ }
+ aLine.append( "/FirstChar 0\n"
+ "/LastChar " );
+ aLine.append( (sal_Int32)(nEncoded-1) );
+ aLine.append( "\n"
+ "/Widths[" );
+ for( int i = 0; i < nEncoded; i++ )
+ {
+ aLine.append( aEncWidths[i] );
+ aLine.append( ((i&15) == 15) ? "\n" : " " );
+ }
+ aLine.append( " ]\n"
+ "/FontDescriptor " );
+ aLine.append( nFontDescriptor );
+ aLine.append( " 0 R>>\n"
+ "endobj\n\n" );
+ if( ! writeBuffer( aLine.getStr(), aLine.getLength() ) )
+ throw FontException();
+
+ aRet[ enc_it->m_nFontID ] = nObject;
+ }
}
}
+ catch( FontException& )
+ {
+ // these do nothing in case there was no compression or encryption ongoing
+ endCompression();
+ disableStreamEncryption();
+ }
- streamend:
if( pFontData )
m_pReferenceDevice->mpGraphics->FreeEmbedFontData( pFontData, nFontLen );
@@ -3567,11 +3552,15 @@ static void appendSubsetName( int nSubsetID, const OUString& rPSName, OStringBuf
appendName( rPSName, rBuffer );
}
-sal_Int32 PDFWriterImpl::createToUnicodeCMap( sal_uInt8* pEncoding, sal_Ucs* pUnicodes, int nGlyphs )
+sal_Int32 PDFWriterImpl::createToUnicodeCMap( sal_uInt8* pEncoding,
+ sal_Ucs* pUnicodes,
+ sal_Int32* pUnicodesPerGlyph,
+ sal_Int32* pEncToUnicodeIndex,
+ int nGlyphs )
{
int nMapped = 0, n = 0;
for( n = 0; n < nGlyphs; n++ )
- if( pUnicodes[n] )
+ if( pUnicodes[pEncToUnicodeIndex[n]] && pUnicodesPerGlyph[n] )
nMapped++;
if( nMapped == 0 )
@@ -3599,7 +3588,7 @@ sal_Int32 PDFWriterImpl::createToUnicodeCMap( sal_uInt8* pEncoding, sal_Ucs* pUn
int nCount = 0;
for( n = 0; n < nGlyphs; n++ )
{
- if( pUnicodes[n] )
+ if( pUnicodes[pEncToUnicodeIndex[n]] && pUnicodesPerGlyph[n] )
{
if( (nCount % 100) == 0 )
{
@@ -3611,9 +3600,13 @@ sal_Int32 PDFWriterImpl::createToUnicodeCMap( sal_uInt8* pEncoding, sal_Ucs* pUn
aContents.append( '<' );
appendHex( (sal_Int8)pEncoding[n], aContents );
aContents.append( "> <" );
- // TODO: handle unicodes>U+FFFF
- appendHex( (sal_Int8)(pUnicodes[n] / 256), aContents );
- appendHex( (sal_Int8)(pUnicodes[n] & 255), aContents );
+ // TODO: handle unicodes>U+FFFF
+ sal_Int32 nIndex = pEncToUnicodeIndex[n];
+ for( sal_Int32 j = 0; j < pUnicodesPerGlyph[n]; j++ )
+ {
+ appendHex( (sal_Int8)(pUnicodes[nIndex + j] / 256), aContents );
+ appendHex( (sal_Int8)(pUnicodes[nIndex + j] & 255), aContents );
+ }
aContents.append( ">\n" );
nCount++;
}
@@ -3777,25 +3770,32 @@ bool PDFWriterImpl::emitFonts()
sal_Int32 pGlyphIDs[ 256 ];
sal_Int32 pWidths[ 256 ];
sal_uInt8 pEncoding[ 256 ];
- sal_Ucs pUnicodes[ 256 ];
+ sal_Int32 pEncToUnicodeIndex[ 256 ];
+ sal_Int32 pUnicodesPerGlyph[ 256 ];
+ std::vector<sal_Ucs> aUnicodes;
+ aUnicodes.reserve( 256 );
int nGlyphs = 1;
// fill arrays and prepare encoding index map
sal_Int32 nToUnicodeStream = 0;
- memset( pGlyphIDs, 0, sizeof( pGlyphIDs ) );
- memset( pEncoding, 0, sizeof( pEncoding ) );
- memset( pUnicodes, 0, sizeof( pUnicodes ) );
+ rtl_zeroMemory( pGlyphIDs, sizeof( pGlyphIDs ) );
+ rtl_zeroMemory( pEncoding, sizeof( pEncoding ) );
+ rtl_zeroMemory( pUnicodesPerGlyph, sizeof( pUnicodesPerGlyph ) );
+ rtl_zeroMemory( pEncToUnicodeIndex, sizeof( pEncToUnicodeIndex ) );
for( FontEmitMapping::iterator fit = lit->m_aMapping.begin(); fit != lit->m_aMapping.end();++fit )
{
- sal_uInt8 nEnc = fit->second.m_nSubsetGlyphID;
+ sal_uInt8 nEnc = fit->second.getGlyphId();
DBG_ASSERT( pGlyphIDs[nEnc] == 0 && pEncoding[nEnc] == 0, "duplicate glyph" );
DBG_ASSERT( nEnc <= lit->m_aMapping.size(), "invalid glyph encoding" );
pGlyphIDs[ nEnc ] = fit->first;
pEncoding[ nEnc ] = nEnc;
- pUnicodes[ nEnc ] = fit->second.m_aUnicode;
- if( pUnicodes[ nEnc ] )
+ pEncToUnicodeIndex[ nEnc ] = static_cast<sal_Int32>(aUnicodes.size());
+ pUnicodesPerGlyph[ nEnc ] = fit->second.countCodes();
+ for( sal_Int32 n = 0; n < pUnicodesPerGlyph[ nEnc ]; n++ )
+ aUnicodes.push_back( fit->second.getCode( n ) );
+ if( fit->second.getCode(0) )
nToUnicodeStream = 1;
if( nGlyphs < 256 )
nGlyphs++;
@@ -3816,92 +3816,92 @@ bool PDFWriterImpl::emitFonts()
CHECK_RETURN( (osl_File_E_None == osl_getFilePos( aFontFile, &nLength1 ) ) );
CHECK_RETURN( (osl_File_E_None == osl_setFilePos( aFontFile, osl_Pos_Absolut, 0 ) ) );
-#if OSL_DEBUG_LEVEL > 1
+ #if OSL_DEBUG_LEVEL > 1
{
OStringBuffer aLine1( " PDFWriterImpl::emitFonts" );
emitComment( aLine1.getStr() );
}
-#endif
+ #endif
sal_Int32 nFontStream = createObject();
sal_Int32 nStreamLengthObject = createObject();
CHECK_RETURN( updateObject( nFontStream ) );
aLine.setLength( 0 );
aLine.append( nFontStream );
aLine.append( " 0 obj\n"
- "<</Length " );
+ "<</Length " );
aLine.append( (sal_Int32)nStreamLengthObject );
aLine.append( " 0 R"
-#ifndef DEBUG_DISABLE_PDFCOMPRESSION
- "/Filter/FlateDecode"
-#endif
- "/Length1 " );
-
- sal_uInt64 nStartPos = 0;
- if( aSubsetInfo.m_nFontType == FontSubsetInfo::SFNT_TTF )
- {
- aLine.append( (sal_Int32)nLength1 );
+ #ifndef DEBUG_DISABLE_PDFCOMPRESSION
+ "/Filter/FlateDecode"
+ #endif
+ "/Length1 " );
- aLine.append( ">>\n"
- "stream\n" );
- CHECK_RETURN( writeBuffer( aLine.getStr(), aLine.getLength() ) );
- CHECK_RETURN( (osl_File_E_None == osl_getFilePos( m_aFile, &nStartPos ) ) );
-
- // copy font file
- beginCompression();
- checkAndEnableStreamEncryption( nFontStream );
- sal_Bool bEOF = sal_False;
- do
+ sal_uInt64 nStartPos = 0;
+ if( aSubsetInfo.m_nFontType == FontSubsetInfo::SFNT_TTF )
{
- char buf[8192];
- sal_uInt64 nRead;
- CHECK_RETURN( (osl_File_E_None == osl_readFile( aFontFile, buf, sizeof( buf ), &nRead ) ) );
- CHECK_RETURN( writeBuffer( buf, nRead ) );
- CHECK_RETURN( (osl_File_E_None == osl_isEndOfFile( aFontFile, &bEOF ) ) );
- } while( ! bEOF );
- }
- else if( (aSubsetInfo.m_nFontType & FontSubsetInfo::CFF_FONT) != 0 )
- {
- // TODO: implement
- DBG_ERROR( "PDFWriterImpl does not support CFF-font subsets yet!" );
- }
- else if( (aSubsetInfo.m_nFontType & FontSubsetInfo::TYPE1_PFB) != 0 ) // TODO: also support PFA?
- {
- unsigned char* pBuffer = new unsigned char[ (int)nLength1 ];
-
- sal_uInt64 nBytesRead = 0;
- CHECK_RETURN( (osl_File_E_None == osl_readFile( aFontFile, pBuffer, nLength1, &nBytesRead ) ) );
- DBG_ASSERT( nBytesRead==nLength1, "PDF-FontSubset read incomplete!" );
- CHECK_RETURN( (osl_File_E_None == osl_setFilePos( aFontFile, osl_Pos_Absolut, 0 ) ) );
- // get the PFB-segment lengths
- ThreeInts aSegmentLengths = {0,0,0};
- getPfbSegmentLengths( pBuffer, (int)nBytesRead, aSegmentLengths );
- // the lengths below are mandatory for PDF-exported Type1 fonts
- // because the PFB segment headers get stripped! WhyOhWhy.
- aLine.append( (sal_Int32)aSegmentLengths[0] );
- aLine.append( "/Length2 " );
- aLine.append( (sal_Int32)aSegmentLengths[1] );
- aLine.append( "/Length3 " );
- aLine.append( (sal_Int32)aSegmentLengths[2] );
-
- aLine.append( ">>\n"
- "stream\n" );
- CHECK_RETURN( writeBuffer( aLine.getStr(), aLine.getLength() ) );
- CHECK_RETURN( (osl_File_E_None == osl_getFilePos( m_aFile, &nStartPos ) ) );
-
- // emit PFB-sections without section headers
- beginCompression();
- checkAndEnableStreamEncryption( nFontStream );
- CHECK_RETURN( writeBuffer( pBuffer+ 6, aSegmentLengths[0] ) );
- CHECK_RETURN( writeBuffer( pBuffer+12 + aSegmentLengths[0], aSegmentLengths[1] ) );
- CHECK_RETURN( writeBuffer( pBuffer+18 + aSegmentLengths[0] + aSegmentLengths[1], aSegmentLengths[2] ) );
-
- delete[] pBuffer;
- }
- else
- {
- fprintf( stderr, "PDF: CreateFontSubset result in not yet supported format=%d\n",aSubsetInfo.m_nFontType);
- aLine.append( "0 >>\nstream\n" );
- }
+ aLine.append( (sal_Int32)nLength1 );
+
+ aLine.append( ">>\n"
+ "stream\n" );
+ CHECK_RETURN( writeBuffer( aLine.getStr(), aLine.getLength() ) );
+ CHECK_RETURN( (osl_File_E_None == osl_getFilePos( m_aFile, &nStartPos ) ) );
+
+ // copy font file
+ beginCompression();
+ checkAndEnableStreamEncryption( nFontStream );
+ sal_Bool bEOF = sal_False;
+ do
+ {
+ char buf[8192];
+ sal_uInt64 nRead;
+ CHECK_RETURN( (osl_File_E_None == osl_readFile( aFontFile, buf, sizeof( buf ), &nRead ) ) );
+ CHECK_RETURN( writeBuffer( buf, nRead ) );
+ CHECK_RETURN( (osl_File_E_None == osl_isEndOfFile( aFontFile, &bEOF ) ) );
+ } while( ! bEOF );
+ }
+ else if( (aSubsetInfo.m_nFontType & FontSubsetInfo::CFF_FONT) != 0 )
+ {
+ // TODO: implement
+ DBG_ERROR( "PDFWriterImpl does not support CFF-font subsets yet!" );
+ }
+ else if( (aSubsetInfo.m_nFontType & FontSubsetInfo::TYPE1_PFB) != 0 ) // TODO: also support PFA?
+ {
+ unsigned char* pBuffer = new unsigned char[ (int)nLength1 ];
+
+ sal_uInt64 nBytesRead = 0;
+ CHECK_RETURN( (osl_File_E_None == osl_readFile( aFontFile, pBuffer, nLength1, &nBytesRead ) ) );
+ DBG_ASSERT( nBytesRead==nLength1, "PDF-FontSubset read incomplete!" );
+ CHECK_RETURN( (osl_File_E_None == osl_setFilePos( aFontFile, osl_Pos_Absolut, 0 ) ) );
+ // get the PFB-segment lengths
+ ThreeInts aSegmentLengths = {0,0,0};
+ getPfbSegmentLengths( pBuffer, (int)nBytesRead, aSegmentLengths );
+ // the lengths below are mandatory for PDF-exported Type1 fonts
+ // because the PFB segment headers get stripped! WhyOhWhy.
+ aLine.append( (sal_Int32)aSegmentLengths[0] );
+ aLine.append( "/Length2 " );
+ aLine.append( (sal_Int32)aSegmentLengths[1] );
+ aLine.append( "/Length3 " );
+ aLine.append( (sal_Int32)aSegmentLengths[2] );
+
+ aLine.append( ">>\n"
+ "stream\n" );
+ CHECK_RETURN( writeBuffer( aLine.getStr(), aLine.getLength() ) );
+ CHECK_RETURN( (osl_File_E_None == osl_getFilePos( m_aFile, &nStartPos ) ) );
+
+ // emit PFB-sections without section headers
+ beginCompression();
+ checkAndEnableStreamEncryption( nFontStream );
+ CHECK_RETURN( writeBuffer( pBuffer+ 6, aSegmentLengths[0] ) );
+ CHECK_RETURN( writeBuffer( pBuffer+12 + aSegmentLengths[0], aSegmentLengths[1] ) );
+ CHECK_RETURN( writeBuffer( pBuffer+18 + aSegmentLengths[0] + aSegmentLengths[1], aSegmentLengths[2] ) );
+
+ delete[] pBuffer;
+ }
+ else
+ {
+ fprintf( stderr, "PDF: CreateFontSubset result in not yet supported format=%d\n",aSubsetInfo.m_nFontType);
+ aLine.append( "0 >>\nstream\n" );
+ }
endCompression();
disableStreamEncryption();
@@ -3928,7 +3928,7 @@ bool PDFWriterImpl::emitFonts()
sal_Int32 nFontDescriptor = emitFontDescriptor( it->first, aSubsetInfo, lit->m_nFontID, nFontStream );
if( nToUnicodeStream )
- nToUnicodeStream = createToUnicodeCMap( pEncoding, pUnicodes, nGlyphs );
+ nToUnicodeStream = createToUnicodeCMap( pEncoding, &aUnicodes[0], pUnicodesPerGlyph, pEncToUnicodeIndex, nGlyphs );
sal_Int32 nFontObject = createObject();
CHECK_RETURN( updateObject( nFontObject ) );
@@ -3937,22 +3937,22 @@ bool PDFWriterImpl::emitFonts()
aLine.append( " 0 obj\n" );
aLine.append( ((aSubsetInfo.m_nFontType & FontSubsetInfo::ANY_TYPE1) != 0) ?
- "<</Type/Font/Subtype/Type1/BaseFont/" :
- "<</Type/Font/Subtype/TrueType/BaseFont/" );
+ "<</Type/Font/Subtype/Type1/BaseFont/" :
+ "<</Type/Font/Subtype/TrueType/BaseFont/" );
appendSubsetName( lit->m_nFontID, aSubsetInfo.m_aPSName, aLine );
aLine.append( "\n"
- "/FirstChar 0\n"
- "/LastChar " );
+ "/FirstChar 0\n"
+ "/LastChar " );
aLine.append( (sal_Int32)(nGlyphs-1) );
aLine.append( "\n"
- "/Widths[" );
+ "/Widths[" );
for( int i = 0; i < nGlyphs; i++ )
{
aLine.append( pWidths[ i ] );
aLine.append( ((i & 15) == 15) ? "\n" : " " );
}
aLine.append( "]\n"
- "/FontDescriptor " );
+ "/FontDescriptor " );
aLine.append( nFontDescriptor );
aLine.append( " 0 R\n" );
if( nToUnicodeStream )
@@ -3962,7 +3962,7 @@ bool PDFWriterImpl::emitFonts()
aLine.append( " 0 R\n" );
}
aLine.append( ">>\n"
- "endobj\n\n" );
+ "endobj\n\n" );
CHECK_RETURN( writeBuffer( aLine.getStr(), aLine.getLength() ) );
aFontIDToObject[ lit->m_nFontID ] = nFontObject;
@@ -4011,7 +4011,7 @@ bool PDFWriterImpl::emitFonts()
OStringBuffer aFontDict( 1024 );
aFontDict.append( getFontDictObject() );
aFontDict.append( " 0 obj\n"
- "<<" );
+ "<<" );
int ni = 0;
for( std::map< sal_Int32, sal_Int32 >::iterator mit = aFontIDToObject.begin(); mit != aFontIDToObject.end(); ++mit )
{
@@ -4020,12 +4020,12 @@ bool PDFWriterImpl::emitFonts()
aFontDict.append( ' ' );
aFontDict.append( mit->second );
aFontDict.append( " 0 R" );
- if( ((++ni) & 7) == 0 )
- aFontDict.append( '\n' );
+ if( ((++ni) & 7) == 0 )
+ aFontDict.append( '\n' );
}
// emit builtin font for widget apperances / variable text
for( std::map< sal_Int32, sal_Int32 >::iterator it = m_aBuiltinFontToObjectMap.begin();
- it != m_aBuiltinFontToObjectMap.end(); ++it )
+ it != m_aBuiltinFontToObjectMap.end(); ++it )
{
ImplPdfBuiltinFontData aData(m_aBuiltinFonts[it->first]);
it->second = emitBuiltinFont( &aData, it->second );
@@ -6580,12 +6580,14 @@ void PDFWriterImpl::registerGlyphs( int nGlyphs,
sal_GlyphId* pGlyphs,
sal_Int32* pGlyphWidths,
sal_Ucs* pUnicodes,
+ sal_Int32* pUnicodesPerGlyph,
sal_uInt8* pMappedGlyphs,
sal_Int32* pMappedFontObjects,
const ImplFontData* pFallbackFonts[] )
{
const ImplFontData* pDevFont = m_pReferenceDevice->mpFontEntry->maFontSelData.mpFontData;
- for( int i = 0; i < nGlyphs; i++ )
+ sal_Ucs* pCurUnicode = pUnicodes;
+ for( int i = 0; i < nGlyphs; pCurUnicode += pUnicodesPerGlyph[i] , i++ )
{
const int nFontGlyphId = pGlyphs[i] & (GF_IDXMASK | GF_ISCHAR | GF_GSUB);
const ImplFontData* pCurrentFont = pFallbackFonts[i] ? pFallbackFonts[i] : pDevFont;
@@ -6640,8 +6642,9 @@ void PDFWriterImpl::registerGlyphs( int nGlyphs,
// add new glyph to emitted font subset
GlyphEmit& rNewGlyphEmit = rSubset.m_aSubsets.back().m_aMapping[ nFontGlyphId ];
- rNewGlyphEmit.m_nSubsetGlyphID = nNewId;
- rNewGlyphEmit.m_aUnicode = (pUnicodes ? pUnicodes[i] : 0);
+ rNewGlyphEmit.setGlyphId( nNewId );
+ for( sal_Int32 n = 0; n < pUnicodesPerGlyph[i]; n++ )
+ rNewGlyphEmit.addCode( pCurUnicode[n] );
// add new glyph to font mapping
Glyph& rNewGlyph = rSubset.m_aMapping[ nFontGlyphId ];
@@ -6678,7 +6681,7 @@ void PDFWriterImpl::registerGlyphs( int nGlyphs,
Ucs2OStrMap::const_iterator nonenc_it;
sal_Int32 nCurFontID = nFontID;
- sal_Ucs cChar = pUnicodes[i];
+ sal_Ucs cChar = *pCurUnicode;
if( pEncoding )
{
enc_it = pEncoding->find( cChar );
@@ -6740,7 +6743,7 @@ void PDFWriterImpl::registerGlyphs( int nGlyphs,
pMappedGlyphs[ i ] = (sal_Int8)cChar;
pMappedFontObjects[ i ] = nCurFontID;
pGlyphWidths[ i ] = m_aFontCache.getGlyphWidth( pCurrentFont,
- (pEncoding ? pUnicodes[i] : cChar) | GF_ISCHAR,
+ (pEncoding ? *pCurUnicode : cChar) | GF_ISCHAR,
false,
m_pReferenceDevice->mpGraphics );
}
@@ -7020,7 +7023,9 @@ void PDFWriterImpl::drawLayout( SalLayout& rLayout, const String& rText, bool bT
sal_Int32 pGlyphWidths[nMaxGlyphs];
sal_uInt8 pMappedGlyphs[nMaxGlyphs];
sal_Int32 pMappedFontObjects[nMaxGlyphs];
- sal_Ucs pUnicodes[nMaxGlyphs];
+ std::vector<sal_Ucs> aUnicodes;
+ aUnicodes.reserve( nMaxGlyphs );
+ sal_Int32 pUnicodesPerGlyph[nMaxGlyphs];
int pCharPosAry[nMaxGlyphs];
sal_Int32 nAdvanceWidths[nMaxGlyphs];
const ImplFontData* pFallbackFonts[nMaxGlyphs];
@@ -7153,15 +7158,29 @@ void PDFWriterImpl::drawLayout( SalLayout& rLayout, const String& rText, bool bT
Point aGNGlyphPos;
while( (nGlyphs = rLayout.GetNextGlyphs( nTmpMaxGlyphs, pGlyphs, aGNGlyphPos, nIndex, nAdvanceWidths, pCharPosAry )) != 0 )
{
+ aUnicodes.clear();
for( int i = 0; i < nGlyphs; i++ )
{
pFallbackFonts[i] = rLayout.GetFallbackFontData( pGlyphs[i] );
+ // default case: 1 glyph is one unicode
+ pUnicodesPerGlyph[i] = 1;
if( (pGlyphs[i] & GF_ISCHAR) )
- pUnicodes[i] = static_cast<sal_Ucs>(pGlyphs[i] & GF_IDXMASK);
+ {
+ aUnicodes.push_back( static_cast<sal_Ucs>(pGlyphs[i] & GF_IDXMASK) );
+ }
else if( pCharPosAry[i] >= nMinCharPos && pCharPosAry[i] <= nMaxCharPos )
{
- pUnicodes[i] = rText.GetChar( sal::static_int_cast<xub_StrLen>(pCharPosAry[i]) );
+ int nChars = 1;
+ aUnicodes.push_back( rText.GetChar( sal::static_int_cast<xub_StrLen>(pCharPosAry[i]) ) );
+ pUnicodesPerGlyph[i] = 1;
+ // try to handle ligatures and such
+ if( i < nGlyphs-1 )
+ {
+ pUnicodesPerGlyph[i] = nChars = pCharPosAry[i+1] - pCharPosAry[i];
+ for( int n = 1; n < nChars; n++ )
+ aUnicodes.push_back( rText.GetChar( sal::static_int_cast<xub_StrLen>(pCharPosAry[i]+n) ) );
+ }
// #i36691# hack that is needed because currently the pGlyphs[]
// argument is ignored for embeddable fonts and so the layout
// engine's glyph work is ignored (i.e. char mirroring)
@@ -7169,17 +7188,21 @@ void PDFWriterImpl::drawLayout( SalLayout& rLayout, const String& rText, bool bT
// glyphid (i.e. FreeType's synthetic glyphid for a Type1 font)
// back to unicode and then to embeddable font's encoding
if( getReferenceDevice()->GetLayoutMode() & TEXT_LAYOUT_BIDI_RTL )
- pUnicodes[i] = static_cast<sal_Ucs>(GetMirroredChar(pUnicodes[i]));
+ {
+ size_t nI = aUnicodes.size()-1;
+ for( int n = 0; n < nChars; n++, nI-- )
+ aUnicodes[nI] = static_cast<sal_Ucs>(GetMirroredChar(aUnicodes[nI]));
+ }
}
else
- pUnicodes[i] = 0;
+ aUnicodes.push_back( 0 );
// note: in case of ctl one character may result
// in multiple glyphs. The current SalLayout
// implementations set -1 then to indicate that no direct
// mapping is possible
}
- registerGlyphs( nGlyphs, pGlyphs, pGlyphWidths, pUnicodes, pMappedGlyphs, pMappedFontObjects, pFallbackFonts );
+ registerGlyphs( nGlyphs, pGlyphs, pGlyphWidths, &aUnicodes[0], pUnicodesPerGlyph, pMappedGlyphs, pMappedFontObjects, pFallbackFonts );
for( int i = 0; i < nGlyphs; i++ )
{
@@ -9513,7 +9536,7 @@ bool PDFWriterImpl::writeBitmapObject( BitmapEmit& rObject, bool bMask )
sal_uInt64 nStartPos = 0;
CHECK_RETURN( (osl_File_E_None == osl_getFilePos( m_aFile, &nStartPos )) );
- checkAndEnableStreamEncryption( rObject.m_nObject );
+ checkAndEnableStreamEncryption( rObject.m_nObject );
beginCompression();
if( ! bTrueColor || pAccess->GetScanlineFormat() == BMP_FORMAT_24BIT_TC_RGB )
{
@@ -9527,7 +9550,7 @@ bool PDFWriterImpl::writeBitmapObject( BitmapEmit& rObject, bool bMask )
else
{
const int nScanLineBytes = pAccess->Width()*3;
- sal_uInt8 *pCol = (sal_uInt8*)rtl_allocateMemory( nScanLineBytes );
+ boost::shared_array<sal_uInt8> pCol( new sal_uInt8[ nScanLineBytes ] );
for( int y = 0; y < pAccess->Height(); y++ )
{
for( int x = 0; x < pAccess->Width(); x++ )
@@ -9537,9 +9560,8 @@ bool PDFWriterImpl::writeBitmapObject( BitmapEmit& rObject, bool bMask )
pCol[3*x+1] = aColor.GetGreen();
pCol[3*x+2] = aColor.GetBlue();
}
- CHECK_RETURN( writeBuffer( pCol, nScanLineBytes ) );
+ CHECK_RETURN( writeBuffer( pCol.get(), nScanLineBytes ) );
}
- rtl_freeMemory( pCol );
}
endCompression();
disableStreamEncryption();
diff --git a/vcl/source/gdi/pdfwriter_impl.hxx b/vcl/source/gdi/pdfwriter_impl.hxx
index e058cfa487db..d54aecf35788 100644
--- a/vcl/source/gdi/pdfwriter_impl.hxx
+++ b/vcl/source/gdi/pdfwriter_impl.hxx
@@ -52,6 +52,8 @@
#include <hash_map>
#include <list>
+#include <boost/shared_array.hpp>
+
class ImplFontSelectData;
class ImplFontMetricData;
class FontSubsetInfo;
@@ -270,10 +272,53 @@ public:
};
// font subsets
- struct GlyphEmit
+ class GlyphEmit
{
- sal_Ucs m_aUnicode;
- sal_uInt8 m_nSubsetGlyphID;
+ // performance: actually this should probably a vector;
+ sal_Ucs m_aBufferedUnicodes[3];
+ sal_Int32 m_nUnicodes;
+ sal_Int32 m_nMaxUnicodes;
+ boost::shared_array<sal_Ucs> m_pUnicodes;
+ sal_uInt8 m_nSubsetGlyphID;
+
+ public:
+ GlyphEmit() : m_nUnicodes(0), m_nSubsetGlyphID(0)
+ {
+ rtl_zeroMemory( m_aBufferedUnicodes, sizeof( m_aBufferedUnicodes ) );
+ m_nMaxUnicodes = sizeof(m_aBufferedUnicodes)/sizeof(m_aBufferedUnicodes[0]);
+ }
+ ~GlyphEmit()
+ {
+ }
+
+ void setGlyphId( sal_uInt8 i_nId ) { m_nSubsetGlyphID = i_nId; }
+ sal_uInt8 getGlyphId() const { return m_nSubsetGlyphID; }
+
+ void addCode( sal_Ucs i_cCode )
+ {
+ if( m_nUnicodes == m_nMaxUnicodes )
+ {
+ sal_Ucs* pNew = new sal_Ucs[ 2 * m_nMaxUnicodes];
+ if( m_pUnicodes.get() )
+ rtl_copyMemory( pNew, m_pUnicodes.get(), m_nMaxUnicodes * sizeof(sal_Ucs) );
+ else
+ rtl_copyMemory( pNew, m_aBufferedUnicodes, m_nMaxUnicodes * sizeof(sal_Ucs) );
+ m_pUnicodes.reset( pNew );
+ m_nMaxUnicodes *= 2;
+ }
+ if( m_pUnicodes.get() )
+ m_pUnicodes[ m_nUnicodes++ ] = i_cCode;
+ else
+ m_aBufferedUnicodes[ m_nUnicodes++ ] = i_cCode;
+ }
+ sal_Int32 countCodes() const { return m_nUnicodes; }
+ sal_Ucs getCode( sal_Int32 i_nIndex ) const
+ {
+ sal_Ucs nRet = 0;
+ if( i_nIndex < m_nUnicodes )
+ nRet = m_pUnicodes.get() ? m_pUnicodes[ i_nIndex ] : m_aBufferedUnicodes[ i_nIndex ];
+ return nRet;
+ }
};
typedef std::map< sal_GlyphId, GlyphEmit > FontEmitMapping;
struct FontEmit
@@ -860,7 +905,7 @@ i12626
void appendLiteralStringEncrypt( rtl::OStringBuffer& rInString, const sal_Int32 nInObjectNumber, rtl::OStringBuffer& rOutBuffer );
/* creates fonts and subsets that will be emitted later */
- void registerGlyphs( int nGlyphs, sal_GlyphId* pGlyphs, sal_Int32* pGlpyhWidths, sal_Ucs* pUnicodes, sal_uInt8* pMappedGlyphs, sal_Int32* pMappedFontObjects, const ImplFontData* pFallbackFonts[] );
+ void registerGlyphs( int nGlyphs, sal_GlyphId* pGlyphs, sal_Int32* pGlpyhWidths, sal_Ucs* pUnicodes, sal_Int32* pUnicodesPerGlyph, sal_uInt8* pMappedGlyphs, sal_Int32* pMappedFontObjects, const ImplFontData* pFallbackFonts[] );
/* emits a text object according to the passed layout */
/* TODO: remove rText as soon as SalLayout will change so that rText is not necessary anymore */
@@ -909,7 +954,7 @@ i12626
/* writes a font descriptor and returns its object id (or 0) */
sal_Int32 emitFontDescriptor( const ImplFontData*, FontSubsetInfo&, sal_Int32 nSubsetID, sal_Int32 nStream );
/* writes a ToUnicode cmap, returns the corresponding stream object */
- sal_Int32 createToUnicodeCMap( sal_uInt8* pEncoding, sal_Ucs* pUnicodes, int nGlyphs );
+ sal_Int32 createToUnicodeCMap( sal_uInt8* pEncoding, sal_Ucs* pUnicodes, sal_Int32* pUnicodesPerGlyph, sal_Int32* pEncToUnicodeIndex, int nGlyphs );
/* get resource dict object number */
sal_Int32 getResourceDictObj()