nss: upgrade to release 3.73
[LibreOffice.git] / basic / source / classes / image.cxx
blob6ce3b8894ca9061b990eb556e905ee085e05fa24
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <tools/stream.hxx>
21 #include <tools/tenccvt.hxx>
22 #include <osl/thread.h>
23 #include <sal/log.hxx>
24 #include <basic/sbx.hxx>
25 #include <sb.hxx>
26 #include <sbxprop.hxx>
27 #include <string.h>
28 #include <image.hxx>
29 #include <codegen.hxx>
30 #include <memory>
32 SbiImage::SbiImage()
34 nFlags = SbiImageFlags::NONE;
35 nStringSize= 0;
36 nCodeSize = 0;
37 nLegacyCodeSize =
38 nDimBase = 0;
39 bInit =
40 bError = false;
41 bFirstInit = true;
42 eCharSet = osl_getThreadTextEncoding();
43 nStringIdx = 0;
44 nStringOff = 0;
47 SbiImage::~SbiImage()
51 void SbiImage::Clear()
53 mvStringOffsets.clear();
54 pStrings.reset();
55 pCode.reset();
56 pLegacyPCode.reset();
57 nFlags = SbiImageFlags::NONE;
58 nStringSize= 0;
59 nLegacyCodeSize = 0;
60 nCodeSize = 0;
61 eCharSet = osl_getThreadTextEncoding();
62 nDimBase = 0;
63 bError = false;
66 static bool SbiGood( SvStream const & r )
68 return r.good();
71 // Open Record
72 static sal_uInt64 SbiOpenRecord( SvStream& r, FileOffset nSignature, sal_uInt16 nElem )
74 sal_uInt64 nPos = r.Tell();
75 r.WriteUInt16( static_cast<sal_uInt16>( nSignature ) )
76 .WriteInt32( 0 ).WriteUInt16( nElem );
77 return nPos;
80 // Close Record
81 static void SbiCloseRecord( SvStream& r, sal_uInt64 nOff )
83 sal_uInt64 nPos = r.Tell();
84 r.Seek( nOff + 2 );
85 r.WriteInt32(nPos - nOff - 8 );
86 r.Seek( nPos );
89 constexpr sal_uInt32 nUnicodeDataMagicNumber = 0x556E6920; // "Uni " BE
91 static bool GetToUnicodePoolData(SvStream& r, sal_uInt64 nLen, sal_uInt64 nNext)
93 const auto nPos = r.Tell();
94 // Check space for legacy data, magic number and Unicode data
95 bool bResult = nPos + nLen + sizeof(sal_uInt32) + nLen * sizeof(sal_Unicode) <= nNext;
96 if (bResult)
98 r.SeekRel(nLen); // Skip legacy data
99 sal_uInt32 nMagic = 0;
100 r.ReadUInt32(nMagic);
101 if (nMagic != nUnicodeDataMagicNumber)
103 r.Seek(nPos); // return
104 bResult = false;
107 return bResult;
110 bool SbiImage::Load( SvStream& r, sal_uInt32& nVersion )
113 sal_uInt16 nSign, nCount;
114 sal_uInt32 nLen, nOff;
116 Clear();
117 // Read Master-Record
118 r.ReadUInt16( nSign ).ReadUInt32( nLen ).ReadUInt16( nCount );
119 sal_uInt64 nLast = r.Tell() + nLen;
120 bool bBadVer = false;
121 if( nSign == static_cast<sal_uInt16>( FileOffset::Module ) )
123 sal_uInt32 nCharSet; // System charset
124 sal_uInt32 lDimBase;
125 sal_uInt16 nTmpFlags;
126 sal_uInt16 nReserved1;
127 sal_uInt32 nReserved2;
128 sal_uInt32 nReserved3;
129 r.ReadUInt32( nVersion ).ReadUInt32( nCharSet ).ReadUInt32( lDimBase )
130 .ReadUInt16( nTmpFlags ).ReadUInt16( nReserved1 ).ReadUInt32( nReserved2 ).ReadUInt32( nReserved3 );
131 nFlags = static_cast<SbiImageFlags>(nTmpFlags);
132 eCharSet = nCharSet;
133 eCharSet = GetSOLoadTextEncoding( eCharSet );
134 bBadVer = ( nVersion > B_CURVERSION );
135 nDimBase = static_cast<sal_uInt16>(lDimBase);
138 bool bLegacy = ( nVersion < B_EXT_IMG_VERSION );
140 sal_uInt64 nNext;
141 while( ( nNext = r.Tell() ) < nLast )
144 r.ReadUInt16( nSign ).ReadUInt32( nLen ).ReadUInt16( nCount );
145 nNext += nLen + 8;
146 if( r.GetError() == ERRCODE_NONE )
148 switch( static_cast<FileOffset>( nSign ) )
150 case FileOffset::Name:
151 aName = r.ReadUniOrByteString(eCharSet);
152 break;
153 case FileOffset::Comment:
154 aComment = r.ReadUniOrByteString(eCharSet );
155 break;
156 case FileOffset::Source:
158 aOUSource = r.ReadUniOrByteString(eCharSet);
159 break;
161 case FileOffset::ExtSource:
163 //assuming an empty string with just the lead 32bit/16bit len indicator
164 const size_t nMinStringSize = (eCharSet == RTL_TEXTENCODING_UNICODE) ? 4 : 2;
165 const sal_uInt64 nMaxStrings = r.remainingSize() / nMinStringSize;
166 if (nCount > nMaxStrings)
168 SAL_WARN("basic", "Parsing error: " << nMaxStrings <<
169 " max possible entries, but " << nCount << " claimed, truncating");
170 nCount = nMaxStrings;
172 for( sal_uInt16 j = 0; j < nCount; ++j)
174 aOUSource += r.ReadUniOrByteString(eCharSet);
176 break;
178 case FileOffset::PCode:
179 if( bBadVer ) break;
180 pCode.reset(new char[ nLen ]);
181 nCodeSize = nLen;
182 r.ReadBytes(pCode.get(), nCodeSize);
183 if ( bLegacy )
185 nLegacyCodeSize = static_cast<sal_uInt16>(nCodeSize);
186 pLegacyPCode = std::move(pCode);
188 PCodeBuffConvertor< sal_uInt16, sal_uInt32 > aLegacyToNew( reinterpret_cast<sal_uInt8*>(pLegacyPCode.get()), nLegacyCodeSize );
189 aLegacyToNew.convert();
190 pCode.reset(reinterpret_cast<char*>(aLegacyToNew.GetBuffer()));
191 nCodeSize = aLegacyToNew.GetSize();
192 // we don't release the legacy buffer
193 // right now, that's because the module
194 // needs it to fix up the method
195 // nStart members. When that is done
196 // the module can release the buffer
197 // or it can wait until this routine
198 // is called again or when this class // destructs all of which will trigger
199 // release of the buffer.
201 break;
202 case FileOffset::Publics:
203 case FileOffset::PoolDir:
204 case FileOffset::SymPool:
205 case FileOffset::LineRanges:
206 break;
207 case FileOffset::StringPool:
209 // the data layout is: nCount of 32-bit offsets into both legacy 1-byte char stream
210 // and resulting char buffer (1:1 correspondence assumed; 16 of 32 bits used);
211 // 32-bit length N of following 1-byte char stream (16 bits used); N bytes of 1-byte
212 // char stream; then optional magic number and stream of N sal_Unicode characters.
214 if( bBadVer ) break;
215 //assuming an empty string with just the lead 32bit len indicator
216 const sal_uInt64 nMinStringSize = 4;
217 const sal_uInt64 nMaxStrings = r.remainingSize() / nMinStringSize;
218 if (nCount > nMaxStrings)
220 SAL_WARN("basic", "Parsing error: " << nMaxStrings <<
221 " max possible entries, but " << nCount << " claimed, truncating");
222 nCount = nMaxStrings;
224 MakeStrings( nCount );
225 for( size_t i = 0; i < mvStringOffsets.size() && SbiGood( r ); i++ )
227 r.ReadUInt32( nOff );
228 mvStringOffsets[ i ] = static_cast<sal_uInt16>(nOff);
230 r.ReadUInt32( nLen );
231 if( SbiGood( r ) )
233 pStrings.reset(new sal_Unicode[ nLen ]);
234 nStringSize = static_cast<sal_uInt16>(nLen);
236 if (GetToUnicodePoolData(r, nLen, nNext))
238 OUString s = read_uInt16s_ToOUString(r, nLen);
239 memcpy(pStrings.get(), s.getStr(), s.getLength() * sizeof(sal_Unicode));
241 else
243 std::unique_ptr<char[]> pByteStrings(new char[nLen]);
244 r.ReadBytes(pByteStrings.get(), nLen);
245 for (size_t j = 0; j < mvStringOffsets.size(); j++)
247 sal_uInt16 nOff2 = static_cast<sal_uInt16>(mvStringOffsets[j]);
248 OUString aStr(pByteStrings.get() + nOff2, strlen(pByteStrings.get() + nOff2), eCharSet);
249 memcpy(pStrings.get() + nOff2, aStr.getStr(), (aStr.getLength() + 1) * sizeof(sal_Unicode));
253 break;
255 case FileOffset::UserTypes:
257 //assuming an empty string with just the lead 32bit/16bit len indicator
258 const size_t nMinStringSize = (eCharSet == RTL_TEXTENCODING_UNICODE) ? 4 : 2;
259 const sal_uInt64 nMinRecordSize = nMinStringSize + sizeof(sal_Int16);
260 const sal_uInt64 nMaxRecords = r.remainingSize() / nMinRecordSize;
261 if (nCount > nMaxRecords)
263 SAL_WARN("basic", "Parsing error: " << nMaxRecords <<
264 " max possible entries, but " << nCount << " claimed, truncating");
265 nCount = nMaxRecords;
268 // User defined types; ref.: SbiParser::DefType
269 for (sal_uInt16 i = 0; i < nCount; i++)
271 OUString aTypeName = r.ReadUniOrByteString(eCharSet);
273 sal_uInt16 nTypeMembers;
274 r.ReadUInt16(nTypeMembers);
276 const sal_uInt64 nMaxTypeMembers = r.remainingSize() / 8;
277 if (nTypeMembers > nMaxTypeMembers)
279 SAL_WARN("basic", "Parsing error: " << nMaxTypeMembers <<
280 " max possible entries, but " << nTypeMembers << " claimed, truncating");
281 nTypeMembers = nMaxTypeMembers;
284 SbxObject *pType = new SbxObject(aTypeName);
285 SbxArray *pTypeMembers = pType->GetProperties();
287 for (sal_uInt16 j = 0; j < nTypeMembers; j++)
289 OUString aMemberName = r.ReadUniOrByteString(eCharSet);
291 sal_Int16 aIntMemberType;
292 r.ReadInt16(aIntMemberType);
293 SbxDataType aMemberType = static_cast< SbxDataType > ( aIntMemberType );
295 SbxProperty *pTypeElem = new SbxProperty( aMemberName, aMemberType );
297 sal_uInt32 aIntFlag;
298 r.ReadUInt32(aIntFlag);
299 SbxFlagBits nElemFlags = static_cast< SbxFlagBits > ( aIntFlag );
301 pTypeElem->SetFlags(nElemFlags);
303 sal_Int16 hasObject;
304 r.ReadInt16(hasObject);
306 if (hasObject == 1)
308 if(aMemberType == SbxOBJECT)
310 // nested user defined types
311 // declared before use, so it is ok to reference it by name on load
312 OUString aNestedTypeName = r.ReadUniOrByteString(eCharSet);
313 SbxObject* pNestedTypeObj = static_cast< SbxObject* >( rTypes->Find( aNestedTypeName, SbxClassType::Object ) );
314 if (pNestedTypeObj)
316 SbxObject* pCloneObj = cloneTypeObjectImpl( *pNestedTypeObj );
317 pTypeElem->PutObject( pCloneObj );
320 else
322 // an array
323 SbxDimArray* pArray = new SbxDimArray(
324 static_cast<SbxDataType>(aMemberType & 0x0FFF));
326 sal_Int16 isFixedSize;
327 r.ReadInt16(isFixedSize);
328 if (isFixedSize == 1)
329 pArray->setHasFixedSize( true );
331 sal_Int32 nDims;
332 r.ReadInt32(nDims);
333 for (sal_Int32 d = 0; d < nDims; d++)
335 sal_Int32 lBound;
336 sal_Int32 uBound;
337 r.ReadInt32(lBound).ReadInt32(uBound);
338 pArray->unoAddDim32(lBound, uBound);
341 const SbxFlagBits nSavFlags = pTypeElem->GetFlags();
342 // need to reset the FIXED flag
343 // when calling PutObject ( because the type will not match Object )
344 pTypeElem->ResetFlag(SbxFlagBits::Fixed);
345 pTypeElem->PutObject( pArray );
346 pTypeElem->SetFlags(nSavFlags);
350 pTypeMembers->Insert32( pTypeElem, pTypeMembers->Count32() );
354 pType->Remove( "Name", SbxClassType::DontCare );
355 pType->Remove( "Parent", SbxClassType::DontCare );
357 AddType(pType);
359 break;
361 case FileOffset::ModEnd:
362 goto done;
363 default:
364 break;
367 else
369 break;
371 r.Seek( nNext );
373 done:
374 r.Seek( nLast );
375 if( !SbiGood( r ) )
377 bError = true;
379 return !bError;
382 bool SbiImage::Save( SvStream& r, sal_uInt32 nVer )
384 bool bLegacy = ( nVer < B_EXT_IMG_VERSION );
386 // detect if old code exceeds legacy limits
387 // if so, then disallow save
388 if ( bLegacy && ExceedsLegacyLimits() )
390 SbiImage aEmptyImg;
391 aEmptyImg.aName = aName;
392 aEmptyImg.Save( r, B_LEGACYVERSION );
393 return true;
395 // First of all the header
396 sal_uInt64 nStart = SbiOpenRecord( r, FileOffset::Module, 1 );
397 sal_uInt64 nPos;
399 eCharSet = GetSOStoreTextEncoding( eCharSet );
400 if ( bLegacy )
402 r.WriteInt32( B_LEGACYVERSION );
404 else
406 r.WriteInt32( B_CURVERSION );
408 r .WriteInt32( eCharSet )
409 .WriteInt32( nDimBase )
410 .WriteInt16( static_cast<sal_uInt16>(nFlags) )
411 .WriteInt16( 0 )
412 .WriteInt32( 0 )
413 .WriteInt32( 0 );
415 // Name?
416 if( !aName.isEmpty() && SbiGood( r ) )
418 nPos = SbiOpenRecord( r, FileOffset::Name, 1 );
419 r.WriteUniOrByteString( aName, eCharSet );
420 SbiCloseRecord( r, nPos );
422 // Comment?
423 if( !aComment.isEmpty() && SbiGood( r ) )
425 nPos = SbiOpenRecord( r, FileOffset::Comment, 1 );
426 r.WriteUniOrByteString( aComment, eCharSet );
427 SbiCloseRecord( r, nPos );
429 // Source?
430 if( !aOUSource.isEmpty() && SbiGood( r ) )
432 nPos = SbiOpenRecord( r, FileOffset::Source, 1 );
433 r.WriteUniOrByteString( aOUSource, eCharSet );
434 SbiCloseRecord( r, nPos );
436 // Binary data?
437 if( pCode && SbiGood( r ) )
439 nPos = SbiOpenRecord( r, FileOffset::PCode, 1 );
440 if ( bLegacy )
442 PCodeBuffConvertor< sal_uInt32, sal_uInt16 > aNewToLegacy( reinterpret_cast<sal_uInt8*>(pCode.get()), nCodeSize );
443 aNewToLegacy.convert();
444 pLegacyPCode.reset(reinterpret_cast<char*>(aNewToLegacy.GetBuffer()));
445 nLegacyCodeSize = aNewToLegacy.GetSize();
446 r.WriteBytes(pLegacyPCode.get(), nLegacyCodeSize);
448 else
450 r.WriteBytes(pCode.get(), nCodeSize);
452 SbiCloseRecord( r, nPos );
454 // String-Pool?
455 if( !mvStringOffsets.empty() )
457 nPos = SbiOpenRecord( r, FileOffset::StringPool, mvStringOffsets.size() );
458 // For every String:
459 // sal_uInt32 Offset of the Strings in the Stringblock
460 for( size_t i = 0; i < mvStringOffsets.size() && SbiGood( r ); i++ )
462 r.WriteUInt32( mvStringOffsets[ i ] );
464 // Then the String-Block
465 std::unique_ptr<char[]> pByteStrings(new char[ nStringSize ]);
466 for( size_t i = 0; i < mvStringOffsets.size(); i++ )
468 sal_uInt16 nOff = static_cast<sal_uInt16>(mvStringOffsets[ i ]);
469 OString aStr(OUStringToOString(OUString(pStrings.get() + nOff), eCharSet));
470 memcpy( pByteStrings.get() + nOff, aStr.getStr(), (aStr.getLength() + 1) * sizeof( char ) );
472 r.WriteUInt32( nStringSize );
473 r.WriteBytes(pByteStrings.get(), nStringSize);
474 pByteStrings.reset();
476 // Now write magic number and store the same data in UTF-16; this is backward compatible:
477 // old readers will not read this data after having read legacy data, and will proceed
478 // straight to the end of the record. So no version restriction here.
479 r.WriteUInt32(nUnicodeDataMagicNumber);
480 write_uInt16s_FromOUString(r, OUString(pStrings.get(), nStringSize));
482 SbiCloseRecord( r, nPos );
484 // User defined types
485 if ( rTypes.is() )
487 sal_uInt32 nTypes = rTypes->Count32();
488 assert(nTypes <= std::numeric_limits<sal_uInt16>::max());
489 if (nTypes > 0 )
491 nPos = SbiOpenRecord( r, FileOffset::UserTypes, sal::static_int_cast<sal_uInt16>(nTypes) );
493 for (sal_uInt32 i = 0; i < nTypes; i++)
495 SbxObject* pType = static_cast< SbxObject* > ( rTypes->Get32(i) );
496 OUString aTypeName = pType->GetClassName();
498 r.WriteUniOrByteString( aTypeName, eCharSet );
500 SbxArray *pTypeMembers = pType->GetProperties();
501 sal_uInt32 nTypeMembers = pTypeMembers->Count32();
502 assert(nTypeMembers <= std::numeric_limits<sal_uInt16>::max());
504 r.WriteInt16(sal::static_int_cast<sal_uInt16>(nTypeMembers));
506 for (sal_uInt32 j = 0; j < nTypeMembers; j++)
509 SbxProperty* pTypeElem = static_cast< SbxProperty* > ( pTypeMembers->Get32(j) );
511 const OUString& aElemName = pTypeElem->GetName();
512 r.WriteUniOrByteString( aElemName, eCharSet );
514 SbxDataType dataType = pTypeElem->GetType();
515 r.WriteInt16(dataType);
517 SbxFlagBits nElemFlags = pTypeElem->GetFlags();
518 r.WriteUInt32(static_cast< sal_uInt32 > (nElemFlags) );
520 SbxBase* pElemObject = pTypeElem->GetObject();
522 if (pElemObject)
524 r.WriteInt16(1); // has elem Object
526 if( dataType == SbxOBJECT )
528 // nested user defined types
529 // declared before use, so it is ok to reference it by name on load
530 SbxObject* pNestedType = static_cast< SbxObject* > ( pElemObject );
531 r.WriteUniOrByteString( pNestedType->GetClassName(), eCharSet );
533 else
535 // an array
536 SbxDimArray* pArray = static_cast< SbxDimArray* > ( pElemObject );
538 bool bFixedSize = pArray->hasFixedSize();
539 if (bFixedSize)
540 r.WriteInt16(1);
541 else
542 r.WriteInt16(0);
544 sal_Int32 nDims = pArray->GetDims32();
545 r.WriteInt32(nDims);
547 for (sal_Int32 d = 1; d <= nDims; d++)
549 sal_Int32 lBound;
550 sal_Int32 uBound;
551 pArray->GetDim32(d, lBound, uBound);
552 r.WriteInt32(lBound).WriteInt32(uBound);
556 else
557 r.WriteInt16(0); // no elem Object
561 SbiCloseRecord( r, nPos );
564 // Set overall length
565 SbiCloseRecord( r, nStart );
566 if( !SbiGood( r ) )
568 bError = true;
570 return !bError;
573 void SbiImage::MakeStrings( short nSize )
575 nStringIdx = 0;
576 nStringOff = 0;
577 nStringSize = 1024;
578 pStrings.reset( new sal_Unicode[ nStringSize ]);
579 mvStringOffsets.resize(nSize);
580 if (nSize != 0) {
581 memset( mvStringOffsets.data(), 0, nSize * sizeof( sal_uInt32 ) );
583 memset( pStrings.get(), 0, nStringSize * sizeof( sal_Unicode ) );
586 // Add a string to StringPool. The String buffer is dynamically
587 // growing in 1K-Steps
588 void SbiImage::AddString( const OUString& r )
590 if( nStringIdx >= short(mvStringOffsets.size()) )
592 bError = true;
594 if( bError )
595 return;
597 sal_Int32 len = r.getLength() + 1;
598 sal_uInt32 needed = nStringOff + len;
599 if( needed > 0xFFFFFF00 )
601 bError = true; // out of mem!
603 else if( needed > nStringSize )
605 sal_uInt32 nNewLen = needed + 1024;
606 nNewLen &= 0xFFFFFC00; // trim to 1K border
607 std::unique_ptr<sal_Unicode[]> p(new sal_Unicode[nNewLen]);
608 memcpy( p.get(), pStrings.get(), nStringSize * sizeof( sal_Unicode ) );
609 pStrings = std::move(p);
610 nStringSize = sal::static_int_cast< sal_uInt16 >(nNewLen);
612 if( !bError )
614 mvStringOffsets[ nStringIdx++ ] = nStringOff;
615 memcpy( pStrings.get() + nStringOff, r.getStr(), len * sizeof( sal_Unicode ) );
616 nStringOff = nStringOff + len;
617 // Last String? The update the size of the buffer
618 if( nStringIdx >= short(mvStringOffsets.size()) )
620 nStringSize = nStringOff;
625 // Add code block
626 // The block was fetched by the compiler from class SbBuffer and
627 // is already created with new. Additionally it contains all Integers
628 // in Big Endian format, so can be directly read/written.
629 void SbiImage::AddCode( std::unique_ptr<char[]> p, sal_uInt32 s )
631 pCode = std::move(p);
632 nCodeSize = s;
635 // Add user type
636 void SbiImage::AddType(SbxObject const * pObject)
638 if( !rTypes.is() )
640 rTypes = new SbxArray;
642 SbxObject *pCopyObject = new SbxObject(*pObject);
643 rTypes->Insert32 (pCopyObject,rTypes->Count32());
646 void SbiImage::AddEnum(SbxObject* pObject) // Register enum type
648 if( !rEnums.is() )
650 rEnums = new SbxArray;
652 rEnums->Insert32( pObject, rEnums->Count32() );
655 // Note: IDs start with 1
656 OUString SbiImage::GetString( short nId ) const
658 if( nId && nId <= short(mvStringOffsets.size()) )
660 sal_uInt32 nOff = mvStringOffsets[ nId - 1 ];
661 sal_Unicode* pStr = pStrings.get() + nOff;
663 // #i42467: Special treatment for vbNullChar
664 if( *pStr == 0 )
666 sal_uInt32 nNextOff = (nId < short(mvStringOffsets.size())) ? mvStringOffsets[ nId ] : nStringOff;
667 sal_uInt32 nLen = nNextOff - nOff - 1;
668 if( nLen == 1 )
670 return OUString( u'\0');
673 else
675 return OUString(pStr);
678 return OUString();
681 const SbxObject* SbiImage::FindType (const OUString& aTypeName) const
683 return rTypes.is() ? static_cast<SbxObject*>(rTypes->Find(aTypeName,SbxClassType::Object)) : nullptr;
686 sal_uInt16 SbiImage::CalcLegacyOffset( sal_Int32 nOffset )
688 return SbiCodeGen::calcLegacyOffSet( reinterpret_cast<sal_uInt8*>(pCode.get()), nOffset ) ;
691 sal_uInt32 SbiImage::CalcNewOffset( sal_Int16 nOffset )
693 return SbiCodeGen::calcNewOffSet( reinterpret_cast<sal_uInt8*>(pLegacyPCode.get()), nOffset ) ;
696 void SbiImage::ReleaseLegacyBuffer()
698 pLegacyPCode.reset();
699 nLegacyCodeSize = 0;
702 bool SbiImage::ExceedsLegacyLimits()
704 return ( nStringSize > 0xFF00 ) || ( CalcLegacyOffset( nCodeSize ) > 0xFF00 );
707 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */