LibreOffice Module vcl (master)  1
fontcharmap.cxx
Go to the documentation of this file.
1 /*
2  * This file is part of the LibreOffice project.
3  *
4  * This Source Code Form is subject to the terms of the Mozilla Public
5  * License, v. 2.0. If a copy of the MPL was not distributed with this
6  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
7  *
8  * This file incorporates work covered by the following license notice:
9  *
10  * Licensed to the Apache Software Foundation (ASF) under one or more
11  * contributor license agreements. See the NOTICE file distributed
12  * with this work for additional information regarding copyright
13  * ownership. The ASF licenses this file to you under the Apache
14  * License, Version 2.0 (the "License"); you may not use this file
15  * except in compliance with the License. You may obtain a copy of
16  * the License at http://www.apache.org/licenses/LICENSE-2.0 .
17  */
18 #include <vcl/fontcharmap.hxx>
19 #include <impfontcharmap.hxx>
20 #include <rtl/textcvt.h>
21 #include <rtl/textenc.h>
22 #include <sal/log.hxx>
23 
24 #include <algorithm>
25 #include <vector>
26 #include <o3tl/sorted_vector.hxx>
27 
28 CmapResult::CmapResult( bool bSymbolic,
29  const sal_UCS4* pRangeCodes, int nRangeCount )
30 : mpRangeCodes( pRangeCodes)
31 , mpStartGlyphs( nullptr)
32 , mpGlyphIds( nullptr)
33 , mnRangeCount( nRangeCount)
34 , mbSymbolic( bSymbolic)
35 , mbRecoded( false)
36 {}
37 
39 const sal_UCS4 aDefaultUnicodeRanges[] = {0x0020,0xD800, 0xE000,0xFFF0};
40 const sal_UCS4 aDefaultSymbolRanges[] = {0x0020,0x0100, 0xF020,0xF100};
41 
43 {
44  if( !isDefaultMap() )
45  {
46  delete[] mpRangeCodes;
47  delete[] mpStartGlyphs;
48  delete[] mpGlyphIds;
49  }
50 }
51 
53 : mpRangeCodes( rCR.mpRangeCodes )
54 , mpStartGlyphs( rCR.mpStartGlyphs )
55 , mpGlyphIds( rCR.mpGlyphIds )
56 , mnRangeCount( rCR.mnRangeCount )
57 , mnCharCount( 0 )
58  , m_bSymbolic(rCR.mbSymbolic)
59 {
60  const sal_UCS4* pRangePtr = mpRangeCodes;
61  for( int i = mnRangeCount; --i >= 0; pRangePtr += 2 )
62  {
63  sal_UCS4 cFirst = pRangePtr[0];
64  sal_UCS4 cLast = pRangePtr[1];
65  mnCharCount += cLast - cFirst;
66  }
67 }
68 
70 {
71  const sal_UCS4* pRangeCodes = aDefaultUnicodeRanges;
72  int nCodesCount = SAL_N_ELEMENTS(aDefaultUnicodeRanges);
73  if( bSymbols )
74  {
75  pRangeCodes = aDefaultSymbolRanges;
76  nCodesCount = SAL_N_ELEMENTS(aDefaultSymbolRanges);
77  }
78 
79  CmapResult aDefaultCR( bSymbols, pRangeCodes, nCodesCount/2 );
80  g_pDefaultImplFontCharMap = ImplFontCharMapRef(new ImplFontCharMap(aDefaultCR));
81 
83 }
84 
86 {
87  const bool bIsDefault = (mpRangeCodes == aDefaultUnicodeRanges) || (mpRangeCodes == aDefaultSymbolRanges);
88  return bIsDefault;
89 }
90 
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]);}
94 
95 // TODO: move CMAP parsing directly into the ImplFontCharMap class
96 bool ParseCMAP( const unsigned char* pCmap, int nLength, CmapResult& rResult )
97 {
98  rResult.mpRangeCodes = nullptr;
99  rResult.mpStartGlyphs= nullptr;
100  rResult.mpGlyphIds = nullptr;
101  rResult.mnRangeCount = 0;
102  rResult.mbRecoded = false;
103  rResult.mbSymbolic = false;
104 
105  // parse the table header and check for validity
106  if( !pCmap || (nLength < 24) )
107  return false;
108 
109  if( GetUShort( pCmap ) != 0x0000 ) // simple check for CMAP corruption
110  return false;
111 
112  int nSubTables = GetUShort( pCmap + 2 );
113  if( (nSubTables <= 0) || (nLength < (24 + 8*nSubTables)) )
114  return false;
115 
116  const unsigned char* pEndValidArea = pCmap + nLength;
117 
118  // find the most interesting subtable in the CMAP
119  rtl_TextEncoding eRecodeFrom = RTL_TEXTENCODING_UNICODE;
120  int nOffset = 0;
121  int nFormat = -1;
122  int nBestVal = 0;
123  for( const unsigned char* p = pCmap + 4; --nSubTables >= 0; p += 8 )
124  {
125  int nPlatform = GetUShort( p );
126  int nEncoding = GetUShort( p+2 );
127  int nPlatformEncoding = (nPlatform << 8) + nEncoding;
128 
129  int nValue;
130  rtl_TextEncoding eTmpEncoding = RTL_TEXTENCODING_UNICODE;
131  switch( nPlatformEncoding )
132  {
133  case 0x000: nValue = 20; break; // Unicode 1.0
134  case 0x001: nValue = 21; break; // Unicode 1.1
135  case 0x002: nValue = 22; break; // iso10646_1993
136  case 0x003: nValue = 23; break; // UCS-2
137  case 0x004: nValue = 24; break; // UCS-4
138  case 0x100: nValue = 22; break; // Mac Unicode<2.0
139  case 0x103: nValue = 23; break; // Mac Unicode>2.0
140  case 0x300: nValue = 5; rResult.mbSymbolic = true; break; // Win Symbol
141  case 0x301: nValue = 28; break; // Win UCS-2
142  case 0x30A: nValue = 29; break; // Win-UCS-4
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;
149  }
150 
151  if( nValue <= 0 ) // ignore unknown encodings
152  continue;
153 
154  int nTmpOffset = GetUInt( p+4 );
155 
156  if (nTmpOffset > nLength - 2 || nTmpOffset < 0)
157  continue;
158 
159  int nTmpFormat = GetUShort( pCmap + nTmpOffset );
160  if( nTmpFormat == 12 ) // 32bit code -> glyph map format
161  nValue += 3;
162  else if( nTmpFormat != 4 ) // 16bit code -> glyph map format
163  continue; // ignore other formats
164 
165  if( nBestVal < nValue )
166  {
167  nBestVal = nValue;
168  nOffset = nTmpOffset;
169  nFormat = nTmpFormat;
170  eRecodeFrom = eTmpEncoding;
171  }
172  }
173 
174  // parse the best CMAP subtable
175  int nRangeCount = 0;
176  sal_UCS4* pCodePairs = nullptr;
177  int* pStartGlyphs = nullptr;
178 
179  std::vector<sal_uInt16> aGlyphIdArray;
180  aGlyphIdArray.reserve( 0x1000 );
181  aGlyphIdArray.push_back( 0 );
182 
183  // format 4, the most common 16bit char mapping table
184  if( (nFormat == 4) && ((nOffset+16) < nLength) )
185  {
186  int nSegCountX2 = GetUShort( pCmap + nOffset + 6 );
187  nRangeCount = nSegCountX2/2 - 1;
188  if (nRangeCount < 0)
189  {
190  SAL_WARN("vcl.gdi", "negative RangeCount");
191  nRangeCount = 0;
192  }
193 
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;
198 
199  const int nOffsetBaseStart = pOffsetBase - pCmap;
200  const int nRemainingLen = nLength - nOffsetBaseStart;
201  const int nMaxPossibleRangeOffsets = nRemainingLen / 2;
202  if (nRangeCount > nMaxPossibleRangeOffsets)
203  {
204  SAL_WARN("vcl.gdi", "more range offsets requested then space available");
205  nRangeCount = std::max(0, nMaxPossibleRangeOffsets);
206  }
207 
208  pCodePairs = new sal_UCS4[ nRangeCount * 2 ];
209  pStartGlyphs = new int[ nRangeCount ];
210 
211  sal_UCS4* pCP = pCodePairs;
212  for( int i = 0; i < nRangeCount; ++i )
213  {
214  const sal_UCS4 cMinChar = GetUShort( pBeginBase + 2*i );
215  const sal_UCS4 cMaxChar = GetUShort( pLimitBase + 2*i );
216  const int nGlyphDelta = GetSShort( pDeltaBase + 2*i );
217  const int nRangeOffset = GetUShort( pOffsetBase + 2*i );
218  if( cMinChar > cMaxChar ) { // no sane font should trigger this
219  SAL_WARN("vcl.gdi", "Min char should never be more than the max char!");
220  break;
221  }
222  if( cMaxChar == 0xFFFF ) {
223  SAL_WARN("vcl.gdi", "Format 4 char should not be 0xFFFF");
224  break;
225  }
226  if( !nRangeOffset ) {
227  // glyphid can be calculated directly
228  pStartGlyphs[i] = (cMinChar + nGlyphDelta) & 0xFFFF;
229  } else {
230  // update the glyphid-array with the glyphs in this range
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) { // no sane font should trigger this
236  SAL_WARN("vcl.gdi", "More indexes claimed that space available in font!");
237  break;
238  }
239  const size_t nMaxLegalChar = cMinChar + nMaxPossibleRecords-1;
240  if (cMaxChar > nMaxLegalChar) { // no sane font should trigger this
241  SAL_WARN("vcl.gdi", "More indexes claimed that space available in font!");
242  break;
243  }
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) );
247  }
248  }
249  *(pCP++) = cMinChar;
250  *(pCP++) = cMaxChar + 1;
251  }
252  nRangeCount = (pCP - pCodePairs) / 2;
253  }
254  // format 12, the most common 32bit char mapping table
255  else if( (nFormat == 12) && ((nOffset+16) < nLength) )
256  {
257  nRangeCount = GetUInt( pCmap + nOffset + 12 );
258  if (nRangeCount < 0)
259  {
260  SAL_WARN("vcl.gdi", "negative RangeCount");
261  nRangeCount = 0;
262  }
263 
264  const int nGroupOffset = nOffset + 16;
265  const int nRemainingLen = nLength - nGroupOffset;
266  const int nMaxPossiblePairs = nRemainingLen / 12;
267  if (nRangeCount > nMaxPossiblePairs)
268  {
269  SAL_WARN("vcl.gdi", "more code pairs requested then space available");
270  nRangeCount = std::max(0, nMaxPossiblePairs);
271  }
272 
273  pCodePairs = new sal_UCS4[ nRangeCount * 2 ];
274  pStartGlyphs = new int[ nRangeCount ];
275 
276  const unsigned char* pGroup = pCmap + nGroupOffset;
277  sal_UCS4* pCP = pCodePairs;
278  for( int i = 0; i < nRangeCount; ++i )
279  {
280  sal_UCS4 cMinChar = GetUInt( pGroup + 0 );
281  sal_UCS4 cMaxChar = GetUInt( pGroup + 4 );
282  int nGlyphId = GetUInt( pGroup + 8 );
283  pGroup += 12;
284 
285  if( cMinChar > cMaxChar ) { // no sane font should trigger this
286  SAL_WARN("vcl.gdi", "Min char should never be more than the max char!");
287  break;
288  }
289 
290  *(pCP++) = cMinChar;
291  *(pCP++) = cMaxChar + 1;
292  pStartGlyphs[i] = nGlyphId;
293  }
294  nRangeCount = (pCP - pCodePairs) / 2;
295  }
296 
297  // check if any subtable resulted in something usable
298  if( nRangeCount <= 0 )
299  {
300  delete[] pCodePairs;
301  delete[] pStartGlyphs;
302 
303  // even when no CMAP is available we know it for symbol fonts
304  if( rResult.mbSymbolic )
305  {
306  pCodePairs = new sal_UCS4[4];
307  pCodePairs[0] = 0x0020; // aliased symbols
308  pCodePairs[1] = 0x0100;
309  pCodePairs[2] = 0xF020; // original symbols
310  pCodePairs[3] = 0xF100;
311  rResult.mpRangeCodes = pCodePairs;
312  rResult.mnRangeCount = 2;
313  return true;
314  }
315 
316  return false;
317  }
318 
319  // recode the code ranges to their unicode encoded ranges if needed
320  rtl_TextToUnicodeConverter aConverter = nullptr;
321  rtl_UnicodeToTextContext aCvtContext = nullptr;
322 
323  rResult.mbRecoded = ( eRecodeFrom != RTL_TEXTENCODING_UNICODE );
324  if( rResult.mbRecoded )
325  {
326  aConverter = rtl_createTextToUnicodeConverter( eRecodeFrom );
327  aCvtContext = rtl_createTextToUnicodeContext( aConverter );
328  }
329 
330  if( aConverter && aCvtContext )
331  {
332  // determine the set of supported code points from encoded ranges
333  o3tl::sorted_vector<sal_UCS4> aSupportedCodePoints;
334  aSupportedCodePoints.reserve(256);
335 
336  static const int NINSIZE = 64;
337  static const int NOUTSIZE = 64;
338  std::vector<char> cCharsInp;
339  cCharsInp.reserve(NINSIZE);
340  sal_Unicode cCharsOut[ NOUTSIZE ];
341  sal_UCS4* pCP = pCodePairs;
342  for( int i = 0; i < nRangeCount; ++i )
343  {
344  sal_UCS4 cMin = *(pCP++);
345  sal_UCS4 cEnd = *(pCP++);
346  // ofz#25868 the conversion only makes sense with
347  // input codepoints in 0..SAL_MAX_UINT16 range
348  while (cMin < cEnd && cMin <= SAL_MAX_UINT16)
349  {
350  for (int j = 0; (cMin < cEnd) && (j < NINSIZE); ++cMin, ++j)
351  {
352  if( cMin >= 0x0100 )
353  cCharsInp.push_back(static_cast<char>(cMin >> 8));
354  if( (cMin >= 0x0100) || (cMin < 0x00A0) )
355  cCharsInp.push_back(static_cast<char>(cMin));
356  }
357 
358  sal_uInt32 nCvtInfo;
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 );
366 
367  cCharsInp.clear();
368 
369  for (int j = 0; j < nOutLen; ++j)
370  aSupportedCodePoints.insert( cCharsOut[j] );
371  }
372  }
373 
374  rtl_destroyTextToUnicodeConverter( aCvtContext );
375  rtl_destroyTextToUnicodeConverter( aConverter );
376 
377  // convert the set of supported code points to ranges
378  std::vector<sal_UCS4> aSupportedRanges;
379 
380  for (auto const& supportedPoint : aSupportedCodePoints)
381  {
382  if( aSupportedRanges.empty()
383  || (aSupportedRanges.back() != supportedPoint) )
384  {
385  // add new range beginning with current unicode
386  aSupportedRanges.push_back(supportedPoint);
387  aSupportedRanges.push_back( 0 );
388  }
389 
390  // extend existing range to include current unicode
391  aSupportedRanges.back() = supportedPoint + 1;
392  }
393 
394  // glyph mapping for non-unicode fonts not implemented
395  delete[] pStartGlyphs;
396  pStartGlyphs = nullptr;
397  aGlyphIdArray.clear();
398 
399  // make a pCodePairs array using the vector from above
400  delete[] pCodePairs;
401  nRangeCount = aSupportedRanges.size() / 2;
402  if( nRangeCount <= 0 )
403  return false;
404  pCodePairs = new sal_UCS4[ nRangeCount * 2 ];
405  pCP = pCodePairs;
406  for (auto const& supportedRange : aSupportedRanges)
407  *(pCP++) = supportedRange;
408  }
409 
410  // prepare the glyphid-array if needed
411  // TODO: merge ranges if they are close enough?
412  sal_uInt16* pGlyphIds = nullptr;
413  if( !aGlyphIdArray.empty())
414  {
415  pGlyphIds = new sal_uInt16[ aGlyphIdArray.size() ];
416  sal_uInt16* pOut = pGlyphIds;
417  for (auto const& glyphId : aGlyphIdArray)
418  *(pOut++) = glyphId;
419  }
420 
421  // update the result struct
422  rResult.mpRangeCodes = pCodePairs;
423  rResult.mpStartGlyphs = pStartGlyphs;
424  rResult.mnRangeCount = nRangeCount;
425  rResult.mpGlyphIds = pGlyphIds;
426  return true;
427 }
428 
430  : mpImplFontCharMap( ImplFontCharMap::getDefaultMap() )
431 {
432 }
433 
435  : mpImplFontCharMap( pIFCMap )
436 {
437 }
438 
440  : mpImplFontCharMap(new ImplFontCharMap(rCR))
441 {
442 }
443 
445 {
446  mpImplFontCharMap = nullptr;
447 }
448 
450 {
451  FontCharMapRef xFontCharMap( new FontCharMap( ImplFontCharMap::getDefaultMap( bSymbol ) ) );
452  return xFontCharMap;
453 }
454 
456 {
458 }
459 
461 
463 {
465 }
466 
468 {
469  int nCount = 0;
470 
471  // find and adjust range and char count for cMin
472  int nRangeMin = findRangeIndex( cMin );
473  if( nRangeMin & 1 )
474  ++nRangeMin;
475  else if( cMin > mpImplFontCharMap->mpRangeCodes[ nRangeMin ] )
476  nCount -= cMin - mpImplFontCharMap->mpRangeCodes[ nRangeMin ];
477 
478  // find and adjust range and char count for cMax
479  int nRangeMax = findRangeIndex( cMax );
480  if( nRangeMax & 1 )
481  --nRangeMax;
482  else
483  nCount -= mpImplFontCharMap->mpRangeCodes[ nRangeMax+1 ] - cMax - 1;
484 
485  // count chars in complete ranges between cMin and cMax
486  for( int i = nRangeMin; i <= nRangeMax; i+=2 )
488 
489  return nCount;
490 }
491 
492 bool FontCharMap::HasChar( sal_UCS4 cChar ) const
493 {
494  bool bHasChar = false;
495 
496  if( mpImplFontCharMap->mpStartGlyphs == nullptr ) { // only the char-ranges are known
497  const int nRange = findRangeIndex( cChar );
498  if( nRange==0 && cChar < mpImplFontCharMap->mpRangeCodes[0] )
499  return false;
500  bHasChar = ((nRange & 1) == 0); // inside a range
501  } else { // glyph mapping is available
502  const int nGlyphIndex = GetGlyphIndex( cChar );
503  bHasChar = (nGlyphIndex != 0); // not the notdef-glyph
504  }
505 
506  return bHasChar;
507 }
508 
510 {
511  return mpImplFontCharMap->mpRangeCodes[0];
512 }
513 
515 {
517 }
518 
520 {
521  if( cChar < GetFirstChar() )
522  return GetFirstChar();
523  if( cChar >= GetLastChar() )
524  return GetLastChar();
525 
526  int nRange = findRangeIndex( cChar + 1 );
527  if( nRange & 1 ) // outside of range?
528  return mpImplFontCharMap->mpRangeCodes[ nRange + 1 ]; // => first in next range
529  return (cChar + 1);
530 }
531 
533 {
534  if( cChar <= GetFirstChar() )
535  return GetFirstChar();
536  if( cChar > GetLastChar() )
537  return GetLastChar();
538 
539  int nRange = findRangeIndex( cChar - 1 );
540  if( nRange & 1 ) // outside a range?
541  return (mpImplFontCharMap->mpRangeCodes[ nRange ] - 1); // => last in prev range
542  return (cChar - 1);
543 }
544 
546 {
547  // TODO: improve linear walk?
548  int nCharIndex = 0;
549  const sal_UCS4* pRange = &mpImplFontCharMap->mpRangeCodes[0];
550  for( int i = 0; i < mpImplFontCharMap->mnRangeCount; ++i )
551  {
552  sal_UCS4 cFirst = *(pRange++);
553  sal_UCS4 cLast = *(pRange++);
554  if( cChar >= cLast )
555  nCharIndex += cLast - cFirst;
556  else if( cChar >= cFirst )
557  return nCharIndex + (cChar - cFirst);
558  else
559  break;
560  }
561 
562  return -1;
563 }
564 
566 {
567  // TODO: improve linear walk?
568  const sal_UCS4* pRange = &mpImplFontCharMap->mpRangeCodes[0];
569  for( int i = 0; i < mpImplFontCharMap->mnRangeCount; ++i )
570  {
571  sal_UCS4 cFirst = *(pRange++);
572  sal_UCS4 cLast = *(pRange++);
573  nIndex -= cLast - cFirst;
574  if( nIndex < 0 )
575  return (cLast + nIndex);
576  }
577 
578  // we can only get here with an out-of-bounds charindex
579  return mpImplFontCharMap->mpRangeCodes[0];
580 }
581 
583 {
584  int nLower = 0;
585  int nMid = mpImplFontCharMap->mnRangeCount;
586  int nUpper = 2 * mpImplFontCharMap->mnRangeCount - 1;
587  while( nLower < nUpper )
588  {
589  if( cChar >= mpImplFontCharMap->mpRangeCodes[ nMid ] )
590  nLower = nMid;
591  else
592  nUpper = nMid - 1;
593  nMid = (nLower + nUpper + 1) / 2;
594  }
595 
596  return nMid;
597 }
598 
600 {
601  // return -1 if the object doesn't know the glyph ids
603  return -1;
604 
605  // return 0 if the unicode doesn't have a matching glyph
606  int nRange = findRangeIndex( cChar );
607  // check that we are inside any range
608  if( (nRange == 0) && (cChar < mpImplFontCharMap->mpRangeCodes[0]) ) {
609  // symbol aliasing gives symbol fonts a second chance
610  const bool bSymbolic = cChar <= 0xFF && (mpImplFontCharMap->mpRangeCodes[0]>=0xF000) &&
611  (mpImplFontCharMap->mpRangeCodes[1]<=0xF0FF);
612  if( !bSymbolic )
613  return 0;
614  // check for symbol aliasing (U+F0xx -> U+00xx)
615  cChar |= 0xF000;
616  nRange = findRangeIndex( cChar );
617  if( (nRange == 0) && (cChar < mpImplFontCharMap->mpRangeCodes[0]) ) {
618  return 0;
619  }
620  }
621  // check that we are inside a range
622  if( (nRange & 1) != 0 )
623  return 0;
624 
625  // get glyph index directly or indirectly
626  int nGlyphIndex = cChar - mpImplFontCharMap->mpRangeCodes[ nRange ];
627  const int nStartIndex = mpImplFontCharMap->mpStartGlyphs[ nRange/2 ];
628  if( nStartIndex >= 0 ) {
629  // the glyph index can be calculated
630  nGlyphIndex += nStartIndex;
631  } else {
632  // the glyphid array has the glyph index
633  nGlyphIndex = mpImplFontCharMap->mpGlyphIds[ nGlyphIndex - nStartIndex];
634  }
635 
636  return nGlyphIndex;
637 }
638 
639 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
bool HasChar(sal_UCS4) const
Does the font character map include the UCS4 character?
const sal_UCS4 aDefaultUnicodeRanges[]
Definition: fontcharmap.cxx:39
sal_uInt32 sal_UCS4
Definition: vclenum.hxx:196
bool IsDefaultMap() const
Determines if the font character map is the "default".
const sal_uInt32 * mpRangeCodes
sal_uInt16 sal_Unicode
ImplFontCharMapRef mpImplFontCharMap
virtual ~ImplFontCharMap() override
Definition: fontcharmap.cxx:42
#define SAL_MAX_UINT16
bool isDefaultMap() const
Definition: fontcharmap.cxx:85
int nCount
oslFileHandle & pOut
void reserve(size_type amount)
sal_UCS4 GetPrevChar(sal_UCS4 cChar) const
Get the previous character in the font character map.
const bool m_bSymbolic
int GetCharCount() const
Get the number of characters in the font character map.
static unsigned GetUInt(const unsigned char *p)
Definition: fontcharmap.cxx:91
static unsigned GetUShort(const unsigned char *p)
Definition: fontcharmap.cxx:92
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 i
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)
Definition: fontcharmap.cxx:28
const sal_UCS4 * mpRangeCodes
sal_UCS4 GetNextChar(sal_UCS4 cChar) const
Get the next character in the font character map.
const sal_UCS4 aDefaultSymbolRanges[]
Definition: fontcharmap.cxx:40
bool isSymbolic() const
sal_UCS4 GetLastChar() const
Get the last character in the font character map.
void * p
const int * mpStartGlyphs
static ImplFontCharMapRef const & getDefaultMap(bool bSymbols=false)
Definition: fontcharmap.cxx:69
sal_UCS4 GetCharFromIndex(int nCharIndex) const
Get the character at a particular index in the font character map.
ImplFontCharMap(const CmapResult &)
Definition: fontcharmap.cxx:52
#define SAL_WARN(area, stream)
static ImplFontCharMapRef g_pDefaultImplFontCharMap
Definition: fontcharmap.cxx:38
int findRangeIndex(sal_UCS4) const
bool ParseCMAP(const unsigned char *pCmap, int nLength, CmapResult &rResult)
Definition: fontcharmap.cxx:96
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)
Definition: fontcharmap.cxx:93
sal_Int16 nValue
static FontCharMapRef GetDefaultMap(bool bSymbols)
Get the default font character map.