20 #include <rtl/textcvt.h>
21 #include <rtl/textenc.h>
29 const sal_UCS4* pRangeCodes,
int nRangeCount )
30 : mpRangeCodes( pRangeCodes)
31 , mpStartGlyphs( nullptr)
32 , mpGlyphIds( nullptr)
33 , mnRangeCount( nRangeCount)
34 , mbSymbolic( bSymbolic)
53 : mpRangeCodes( rCR.mpRangeCodes )
54 , mpStartGlyphs( rCR.mpStartGlyphs )
55 , mpGlyphIds( rCR.mpGlyphIds )
56 , mnRangeCount( rCR.mnRangeCount )
58 , m_bSymbolic(rCR.mbSymbolic)
79 CmapResult aDefaultCR( bSymbols, pRangeCodes, nCodesCount/2 );
91 static unsigned GetUInt(
const unsigned char* p ) {
return((p[0]<<24)+(p[1]<<16)+(p[2]<<8)+p[3]);}
92 static unsigned GetUShort(
const unsigned char* p ){
return((p[0]<<8) | p[1]);}
93 static int GetSShort(
const unsigned char* p ){
return static_cast<sal_Int16
>((p[0]<<8)|p[1]);}
106 if( !pCmap || (nLength < 24) )
113 if( (nSubTables <= 0) || (nSubTables > (nLength - 24) / 8) )
116 const unsigned char* pEndValidArea = pCmap + nLength;
119 rtl_TextEncoding eRecodeFrom = RTL_TEXTENCODING_UNICODE;
123 for(
const unsigned char*
p = pCmap + 4; --nSubTables >= 0;
p += 8 )
127 int nPlatformEncoding = (nPlatform << 8) + nEncoding;
130 rtl_TextEncoding eTmpEncoding = RTL_TEXTENCODING_UNICODE;
131 switch( nPlatformEncoding )
133 case 0x000: nValue = 20;
break;
134 case 0x001: nValue = 21;
break;
135 case 0x002: nValue = 22;
break;
136 case 0x003: nValue = 23;
break;
137 case 0x004: nValue = 24;
break;
138 case 0x100: nValue = 22;
break;
139 case 0x103: nValue = 23;
break;
140 case 0x300: nValue = 5; rResult.
mbSymbolic =
true;
break;
141 case 0x301: nValue = 28;
break;
142 case 0x30A: nValue = 29;
break;
143 case 0x302: nValue = 11; eTmpEncoding = RTL_TEXTENCODING_SHIFT_JIS;
break;
144 case 0x303: nValue = 12; eTmpEncoding = RTL_TEXTENCODING_GB_18030;
break;
145 case 0x304: nValue = 11; eTmpEncoding = RTL_TEXTENCODING_BIG5;
break;
146 case 0x305: nValue = 11; eTmpEncoding = RTL_TEXTENCODING_MS_949;
break;
147 case 0x306: nValue = 11; eTmpEncoding = RTL_TEXTENCODING_MS_1361;
break;
148 default: nValue = 0;
break;
156 if (nTmpOffset > nLength - 2 || nTmpOffset < 0)
159 int nTmpFormat =
GetUShort( pCmap + nTmpOffset );
160 if( nTmpFormat == 12 )
162 else if( nTmpFormat != 4 )
165 if( nBestVal < nValue )
168 nOffset = nTmpOffset;
169 nFormat = nTmpFormat;
170 eRecodeFrom = eTmpEncoding;
177 int* pStartGlyphs =
nullptr;
179 std::vector<sal_uInt16> aGlyphIdArray;
180 aGlyphIdArray.reserve( 0x1000 );
181 aGlyphIdArray.push_back( 0 );
184 if( (nFormat == 4) && ((nOffset+16) < nLength) )
186 int nSegCountX2 =
GetUShort( pCmap + nOffset + 6 );
187 nRangeCount = nSegCountX2/2 - 1;
190 SAL_WARN(
"vcl.gdi",
"negative RangeCount");
194 const unsigned char* pLimitBase = pCmap + nOffset + 14;
195 const unsigned char* pBeginBase = pLimitBase + nSegCountX2 + 2;
196 const unsigned char* pDeltaBase = pBeginBase + nSegCountX2;
197 const unsigned char* pOffsetBase = pDeltaBase + nSegCountX2;
199 const int nOffsetBaseStart = pOffsetBase - pCmap;
200 const int nRemainingLen = nLength - nOffsetBaseStart;
201 const int nMaxPossibleRangeOffsets = nRemainingLen / 2;
202 if (nRangeCount > nMaxPossibleRangeOffsets)
204 SAL_WARN(
"vcl.gdi",
"more range offsets requested then space available");
205 nRangeCount = std::max(0, nMaxPossibleRangeOffsets);
208 pCodePairs =
new sal_UCS4[ nRangeCount * 2 ];
209 pStartGlyphs =
new int[ nRangeCount ];
212 for(
int i = 0;
i < nRangeCount; ++
i )
216 const int nGlyphDelta =
GetSShort( pDeltaBase + 2*
i );
217 const int nRangeOffset =
GetUShort( pOffsetBase + 2*
i );
218 if( cMinChar > cMaxChar ) {
219 SAL_WARN(
"vcl.gdi",
"Min char should never be more than the max char!");
222 if( cMaxChar == 0xFFFF ) {
223 SAL_WARN(
"vcl.gdi",
"Format 4 char should not be 0xFFFF");
226 if( !nRangeOffset ) {
228 pStartGlyphs[
i] = (cMinChar + nGlyphDelta) & 0xFFFF;
231 pStartGlyphs[
i] = -
static_cast<int>(aGlyphIdArray.size());
232 const unsigned char* pGlyphIdPtr = pOffsetBase + 2*
i + nRangeOffset;
233 const size_t nRemainingSize = pEndValidArea >= pGlyphIdPtr ? pEndValidArea - pGlyphIdPtr : 0;
234 const size_t nMaxPossibleRecords = nRemainingSize/2;
235 if (nMaxPossibleRecords == 0) {
236 SAL_WARN(
"vcl.gdi",
"More indexes claimed that space available in font!");
239 const size_t nMaxLegalChar = cMinChar + nMaxPossibleRecords-1;
240 if (cMaxChar > nMaxLegalChar) {
241 SAL_WARN(
"vcl.gdi",
"More indexes claimed that space available in font!");
244 for(
sal_UCS4 c = cMinChar; c <= cMaxChar; ++c, pGlyphIdPtr+=2 ) {
245 const int nGlyphIndex =
GetUShort( pGlyphIdPtr ) + nGlyphDelta;
246 aGlyphIdArray.push_back( static_cast<sal_uInt16>(nGlyphIndex) );
250 *(pCP++) = cMaxChar + 1;
252 nRangeCount = (pCP - pCodePairs) / 2;
255 else if( (nFormat == 12) && ((nOffset+16) < nLength) )
257 nRangeCount =
GetUInt( pCmap + nOffset + 12 );
260 SAL_WARN(
"vcl.gdi",
"negative RangeCount");
264 const int nGroupOffset = nOffset + 16;
265 const int nRemainingLen = nLength - nGroupOffset;
266 const int nMaxPossiblePairs = nRemainingLen / 12;
267 if (nRangeCount > nMaxPossiblePairs)
269 SAL_WARN(
"vcl.gdi",
"more code pairs requested then space available");
270 nRangeCount = std::max(0, nMaxPossiblePairs);
273 pCodePairs =
new sal_UCS4[ nRangeCount * 2 ];
274 pStartGlyphs =
new int[ nRangeCount ];
276 const unsigned char* pGroup = pCmap + nGroupOffset;
278 for(
int i = 0;
i < nRangeCount; ++
i )
282 int nGlyphId =
GetUInt( pGroup + 8 );
285 if( cMinChar > cMaxChar ) {
286 SAL_WARN(
"vcl.gdi",
"Min char should never be more than the max char!");
291 *(pCP++) = cMaxChar + 1;
292 pStartGlyphs[
i] = nGlyphId;
294 nRangeCount = (pCP - pCodePairs) / 2;
298 if( nRangeCount <= 0 )
301 delete[] pStartGlyphs;
307 pCodePairs[0] = 0x0020;
308 pCodePairs[1] = 0x0100;
309 pCodePairs[2] = 0xF020;
310 pCodePairs[3] = 0xF100;
320 rtl_TextToUnicodeConverter aConverter =
nullptr;
321 rtl_UnicodeToTextContext aCvtContext =
nullptr;
323 rResult.
mbRecoded = ( eRecodeFrom != RTL_TEXTENCODING_UNICODE );
326 aConverter = rtl_createTextToUnicodeConverter( eRecodeFrom );
327 aCvtContext = rtl_createTextToUnicodeContext( aConverter );
330 if( aConverter && aCvtContext )
334 aSupportedCodePoints.
reserve(256);
336 static const int NINSIZE = 64;
337 static const int NOUTSIZE = 64;
338 std::vector<char> cCharsInp;
339 cCharsInp.reserve(NINSIZE);
342 for(
int i = 0;
i < nRangeCount; ++
i )
350 for (
int j = 0; (cMin < cEnd) && (j < NINSIZE); ++cMin, ++j)
353 cCharsInp.push_back(static_cast<char>(cMin >> 8));
354 if( (cMin >= 0x0100) || (cMin < 0x00A0) )
355 cCharsInp.push_back(static_cast<char>(cMin));
359 sal_Size nSrcCvtBytes;
360 int nOutLen = rtl_convertTextToUnicode(
361 aConverter, aCvtContext,
362 cCharsInp.data(), cCharsInp.size(), cCharsOut, NOUTSIZE,
363 RTL_TEXTTOUNICODE_FLAGS_INVALID_IGNORE
364 | RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_IGNORE,
365 &nCvtInfo, &nSrcCvtBytes );
369 for (
int j = 0; j < nOutLen; ++j)
370 aSupportedCodePoints.
insert( cCharsOut[j] );
374 rtl_destroyTextToUnicodeConverter( aCvtContext );
375 rtl_destroyTextToUnicodeConverter( aConverter );
378 std::vector<sal_UCS4> aSupportedRanges;
380 for (
auto const& supportedPoint : aSupportedCodePoints)
382 if( aSupportedRanges.empty()
383 || (aSupportedRanges.back() != supportedPoint) )
386 aSupportedRanges.push_back(supportedPoint);
387 aSupportedRanges.push_back( 0 );
391 aSupportedRanges.back() = supportedPoint + 1;
395 delete[] pStartGlyphs;
396 pStartGlyphs =
nullptr;
397 aGlyphIdArray.clear();
401 nRangeCount = aSupportedRanges.size() / 2;
402 if( nRangeCount <= 0 )
404 pCodePairs =
new sal_UCS4[ nRangeCount * 2 ];
406 for (
auto const& supportedRange : aSupportedRanges)
407 *(pCP++) = supportedRange;
412 sal_uInt16* pGlyphIds =
nullptr;
413 if( !aGlyphIdArray.empty())
415 pGlyphIds =
new sal_uInt16[ aGlyphIdArray.size() ];
416 sal_uInt16*
pOut = pGlyphIds;
417 for (
auto const& glyphId : aGlyphIdArray)
435 : mpImplFontCharMap( pIFCMap )
486 for(
int i = nRangeMin;
i <= nRangeMax;
i+=2 )
494 bool bHasChar =
false;
498 if( nRange==0 && cChar < mpImplFontCharMap->mpRangeCodes[0] )
500 bHasChar = ((nRange & 1) == 0);
503 bHasChar = (nGlyphIndex != 0);
555 nCharIndex += cLast - cFirst;
556 else if( cChar >= cFirst )
557 return nCharIndex + (cChar - cFirst);
573 nIndex -= cLast - cFirst;
575 return (cLast + nIndex);
587 while( nLower < nUpper )
593 nMid = (nLower + nUpper + 1) / 2;
608 if( (nRange == 0) && (cChar < mpImplFontCharMap->mpRangeCodes[0]) ) {
617 if( (nRange == 0) && (cChar < mpImplFontCharMap->mpRangeCodes[0]) ) {
622 if( (nRange & 1) != 0 )
628 if( nStartIndex >= 0 ) {
630 nGlyphIndex += nStartIndex;
bool HasChar(sal_UCS4) const
Does the font character map include the UCS4 character?
const sal_UCS4 aDefaultUnicodeRanges[]
bool IsDefaultMap() const
Determines if the font character map is the "default".
const sal_uInt32 * mpRangeCodes
ImplFontCharMapRef mpImplFontCharMap
virtual ~ImplFontCharMap() override
bool isDefaultMap() const
void reserve(size_type amount)
sal_UCS4 GetPrevChar(sal_UCS4 cChar) const
Get the previous character in the font character map.
int GetCharCount() const
Get the number of characters in the font character map.
static unsigned GetUInt(const unsigned char *p)
static unsigned GetUShort(const unsigned char *p)
tools::SvRef< ImplFontCharMap > ImplFontCharMapRef
#define SAL_N_ELEMENTS(arr)
sal_UCS4 GetFirstChar() const
Get the first character in the font character map.
const sal_uInt16 * mpGlyphIds
int CountCharsInRange(sal_UCS4 cMin, sal_UCS4 cMax) const
Returns the number of chars supported by the font, which are inside the unicode range from cMin to cM...
int GetGlyphIndex(sal_UCS4) const
const sal_uInt16 * mpGlyphIds
FontCharMap()
A new FontCharMap is created based on a "default" map, which includes all codepoints in the Unicode B...
virtual ~FontCharMap() override
CmapResult(bool bSymbolic=false, const sal_UCS4 *pRangeCodes=nullptr, int nRangeCount=0)
const sal_UCS4 * mpRangeCodes
sal_UCS4 GetNextChar(sal_UCS4 cChar) const
Get the next character in the font character map.
const sal_UCS4 aDefaultSymbolRanges[]
sal_UCS4 GetLastChar() const
Get the last character in the font character map.
const int * mpStartGlyphs
static ImplFontCharMapRef const & getDefaultMap(bool bSymbols=false)
sal_UCS4 GetCharFromIndex(int nCharIndex) const
Get the character at a particular index in the font character map.
ImplFontCharMap(const CmapResult &)
#define SAL_WARN(area, stream)
static ImplFontCharMapRef g_pDefaultImplFontCharMap
int findRangeIndex(sal_UCS4) const
bool ParseCMAP(const unsigned char *pCmap, int nLength, CmapResult &rResult)
std::pair< const_iterator, bool > insert(Value &&x)
const int * mpStartGlyphs
int GetIndexFromChar(sal_UCS4 cChar) const
Get the index of a particular character in the font character map.
static int GetSShort(const unsigned char *p)
static FontCharMapRef GetDefaultMap(bool bSymbols)
Get the default font character map.
bool m_bDetectedRangeSegmentation false