1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_vcl.hxx"
31 #include <vcl/impfont.hxx>
32 #include <vcl/metric.hxx>
37 // =======================================================================
39 ImplFontMetric::ImplFontMetric()
50 // -----------------------------------------------------------------------
52 inline void ImplFontMetric::AddReference()
57 // -----------------------------------------------------------------------
59 inline void ImplFontMetric::DeReference()
61 if( --mnRefCount
<= 0 )
65 // -----------------------------------------------------------------------
67 bool ImplFontMetric::operator==( const ImplFontMetric
& r
) const
69 if( mnMiscFlags
!= r
.mnMiscFlags
)
71 if( mnAscent
!= r
.mnAscent
)
73 if( mnDescent
!= r
.mnDescent
)
75 if( mnIntLeading
!= r
.mnIntLeading
)
77 if( mnExtLeading
!= r
.mnExtLeading
)
79 if( mnSlant
!= r
.mnSlant
)
85 // =======================================================================
88 : mpImplMetric( new ImplFontMetric
)
91 // -----------------------------------------------------------------------
93 FontInfo::FontInfo( const FontInfo
& rInfo
)
96 mpImplMetric
= rInfo
.mpImplMetric
;
97 mpImplMetric
->AddReference();
100 // -----------------------------------------------------------------------
102 FontInfo::~FontInfo()
104 mpImplMetric
->DeReference();
107 // -----------------------------------------------------------------------
109 FontInfo
& FontInfo::operator=( const FontInfo
& rInfo
)
111 Font::operator=( rInfo
);
113 if( mpImplMetric
!= rInfo
.mpImplMetric
)
115 mpImplMetric
->DeReference();
116 mpImplMetric
= rInfo
.mpImplMetric
;
117 mpImplMetric
->AddReference();
123 // -----------------------------------------------------------------------
125 BOOL
FontInfo::operator==( const FontInfo
& rInfo
) const
127 if( !Font::operator==( rInfo
) )
129 if( mpImplMetric
== rInfo
.mpImplMetric
)
131 if( *mpImplMetric
== *rInfo
.mpImplMetric
)
136 // -----------------------------------------------------------------------
138 FontType
FontInfo::GetType() const
140 return (mpImplMetric
->IsScalable() ? TYPE_SCALABLE
: TYPE_RASTER
);
143 // -----------------------------------------------------------------------
145 BOOL
FontInfo::IsDeviceFont() const
147 return mpImplMetric
->IsDeviceFont();
150 // -----------------------------------------------------------------------
152 BOOL
FontInfo::SupportsLatin() const
154 return mpImplMetric
->SupportsLatin();
157 // -----------------------------------------------------------------------
159 BOOL
FontInfo::SupportsCJK() const
161 return mpImplMetric
->SupportsCJK();
164 // -----------------------------------------------------------------------
166 BOOL
FontInfo::SupportsCTL() const
168 return mpImplMetric
->SupportsCTL();
171 // =======================================================================
173 FontMetric::FontMetric( const FontMetric
& rMetric
)
174 : FontInfo( rMetric
)
177 // -----------------------------------------------------------------------
179 long FontMetric::GetAscent() const
181 return mpImplMetric
->GetAscent();
184 // -----------------------------------------------------------------------
186 long FontMetric::GetDescent() const
188 return mpImplMetric
->GetDescent();
191 // -----------------------------------------------------------------------
193 long FontMetric::GetIntLeading() const
195 return mpImplMetric
->GetIntLeading();
198 // -----------------------------------------------------------------------
200 long FontMetric::GetExtLeading() const
202 return mpImplMetric
->GetExtLeading();
205 // -----------------------------------------------------------------------
207 long FontMetric::GetLineHeight() const
209 return mpImplMetric
->GetLineHeight();
212 // -----------------------------------------------------------------------
214 long FontMetric::GetSlant() const
216 return mpImplMetric
->GetSlant();
219 // -----------------------------------------------------------------------
221 FontMetric
& FontMetric::operator =( const FontMetric
& rMetric
)
223 FontInfo::operator=( rMetric
);
227 // -----------------------------------------------------------------------
229 BOOL
FontMetric::operator==( const FontMetric
& rMetric
) const
231 return FontInfo::operator==( rMetric
);
234 // =======================================================================
236 CmapResult::CmapResult( bool bSymbolic
,
237 const sal_uInt32
* pRangeCodes
, int nRangeCount
,
238 const int* pStartGlyphs
, const USHORT
* pExtraGlyphIds
)
239 : mpRangeCodes( pRangeCodes
)
240 , mpStartGlyphs( pStartGlyphs
)
241 , mpGlyphIds( pExtraGlyphIds
)
242 , mnRangeCount( nRangeCount
)
243 , mbSymbolic( bSymbolic
)
247 // =======================================================================
249 ImplFontCharMap::ImplFontCharMap( const CmapResult
& rCR
)
250 : mpRangeCodes( rCR
.mpRangeCodes
)
251 , mpStartGlyphs( rCR
.mpStartGlyphs
)
252 , mpGlyphIds( rCR
.mpGlyphIds
)
253 , mnRangeCount( rCR
.mnRangeCount
)
257 const sal_uInt32
* pRangePtr
= mpRangeCodes
;
258 for( int i
= mnRangeCount
; --i
>= 0; pRangePtr
+= 2 )
260 sal_uInt32 cFirst
= pRangePtr
[0];
261 sal_uInt32 cLast
= pRangePtr
[1];
262 mnCharCount
+= cLast
- cFirst
;
266 static ImplFontCharMap
* pDefaultImplFontCharMap
= NULL
;
267 static const sal_uInt32 aDefaultUnicodeRanges
[] = {0x0020,0xD800, 0xE000,0xFFF0};
268 static const sal_uInt32 aDefaultSymbolRanges
[] = {0x0020,0x0100, 0xF020,0xF100};
270 // -----------------------------------------------------------------------
272 bool ImplFontCharMap::IsDefaultMap() const
274 const bool bIsDefault
= (mpRangeCodes
== aDefaultUnicodeRanges
) || (mpRangeCodes
== aDefaultSymbolRanges
);
278 // -----------------------------------------------------------------------
280 ImplFontCharMap::~ImplFontCharMap()
284 delete[] mpRangeCodes
;
285 delete[] mpStartGlyphs
;
289 // -----------------------------------------------------------------------
291 ImplFontCharMap
* ImplFontCharMap::GetDefaultMap( bool bSymbols
)
293 if( pDefaultImplFontCharMap
)
294 pDefaultImplFontCharMap
->AddReference();
297 const sal_uInt32
* pRangeCodes
= aDefaultUnicodeRanges
;
298 int nCodesCount
= sizeof(aDefaultUnicodeRanges
) / sizeof(*pRangeCodes
);
301 pRangeCodes
= aDefaultSymbolRanges
;
302 nCodesCount
= sizeof(aDefaultSymbolRanges
) / sizeof(*pRangeCodes
);
305 CmapResult
aDefaultCR( bSymbols
, pRangeCodes
, nCodesCount
/2 );
306 pDefaultImplFontCharMap
= new ImplFontCharMap( aDefaultCR
);
309 return pDefaultImplFontCharMap
;
312 // -----------------------------------------------------------------------
314 void ImplFontCharMap::AddReference()
319 // -----------------------------------------------------------------------
321 void ImplFontCharMap::DeReference()
323 if( --mnRefCount
<= 0 )
324 if( this != pDefaultImplFontCharMap
)
328 // -----------------------------------------------------------------------
330 int ImplFontCharMap::GetCharCount() const
335 // -----------------------------------------------------------------------
337 int ImplFontCharMap::ImplFindRangeIndex( sal_uInt32 cChar
) const
340 int nMid
= mnRangeCount
;
341 int nUpper
= 2 * mnRangeCount
- 1;
342 while( nLower
< nUpper
)
344 if( cChar
>= mpRangeCodes
[ nMid
] )
348 nMid
= (nLower
+ nUpper
+ 1) / 2;
354 // -----------------------------------------------------------------------
356 bool ImplFontCharMap::HasChar( sal_uInt32 cChar
) const
358 bool bHasChar
= false;
360 if( mpStartGlyphs
== NULL
) { // only the char-ranges are known
361 const int nRange
= ImplFindRangeIndex( cChar
);
362 if( nRange
==0 && cChar
<mpRangeCodes
[0] )
364 bHasChar
= ((nRange
& 1) == 0); // inside a range
365 } else { // glyph mapping is available
366 const int nGlyphIndex
= GetGlyphIndex( cChar
);
367 bHasChar
= (nGlyphIndex
!= 0); // not the notdef-glyph
373 // -----------------------------------------------------------------------
375 int ImplFontCharMap::GetGlyphIndex( sal_uInt32 cChar
) const
377 // return -1 if the object doesn't know the glyph ids
381 // return 0 if the unicode doesn't have a matching glyph
382 int nRange
= ImplFindRangeIndex( cChar
);
383 // check that we are inside any range
384 if( (nRange
== 0) && (cChar
< mpRangeCodes
[0]) ) {
385 // symbol aliasing gives symbol fonts a second chance
386 const bool bSymbolic
= (mpRangeCodes
[0]>=0xF000) & (mpRangeCodes
[1]<=0xF0FF);
389 // check for symbol aliasing (U+F0xx -> U+00xx)
390 nRange
= ImplFindRangeIndex( cChar
| 0xF000 );
392 // check that we are inside a range
393 if( (nRange
& 1) != 0 )
396 // get glyph index directly or indirectly
397 int nGlyphIndex
= cChar
- mpRangeCodes
[ nRange
];
398 const int nStartIndex
= mpStartGlyphs
[ nRange
/2 ];
399 if( nStartIndex
>= 0 ) {
400 // the glyph index can be calculated
401 nGlyphIndex
+= nStartIndex
;
403 // the glyphid array has the glyph index
404 nGlyphIndex
= mpGlyphIds
[ nGlyphIndex
- nStartIndex
];
410 // -----------------------------------------------------------------------
412 // returns the number of chars supported by the font, which
413 // are inside the unicode range from cMin to cMax (inclusive)
414 int ImplFontCharMap::CountCharsInRange( sal_uInt32 cMin
, sal_uInt32 cMax
) const
418 // find and adjust range and char count for cMin
419 int nRangeMin
= ImplFindRangeIndex( cMin
);
422 else if( cMin
> mpRangeCodes
[ nRangeMin
] )
423 nCount
-= cMin
- mpRangeCodes
[ nRangeMin
];
425 // find and adjust range and char count for cMax
426 int nRangeMax
= ImplFindRangeIndex( cMax
);
430 nCount
-= mpRangeCodes
[ nRangeMax
+1 ] - cMax
- 1;
432 // count chars in complete ranges between cMin and cMax
433 for( int i
= nRangeMin
; i
<= nRangeMax
; i
+=2 )
434 nCount
+= mpRangeCodes
[i
+1] - mpRangeCodes
[i
];
439 // -----------------------------------------------------------------------
441 sal_uInt32
ImplFontCharMap::GetFirstChar() const
443 return mpRangeCodes
[0];
446 // -----------------------------------------------------------------------
448 sal_uInt32
ImplFontCharMap::GetLastChar() const
450 return (mpRangeCodes
[ 2*mnRangeCount
-1 ] - 1);
453 // -----------------------------------------------------------------------
455 sal_uInt32
ImplFontCharMap::GetNextChar( sal_uInt32 cChar
) const
457 if( cChar
< GetFirstChar() )
458 return GetFirstChar();
459 if( cChar
>= GetLastChar() )
460 return GetLastChar();
462 int nRange
= ImplFindRangeIndex( cChar
+ 1 );
463 if( nRange
& 1 ) // outside of range?
464 return mpRangeCodes
[ nRange
+ 1 ]; // => first in next range
468 // -----------------------------------------------------------------------
470 sal_uInt32
ImplFontCharMap::GetPrevChar( sal_uInt32 cChar
) const
472 if( cChar
<= GetFirstChar() )
473 return GetFirstChar();
474 if( cChar
> GetLastChar() )
475 return GetLastChar();
477 int nRange
= ImplFindRangeIndex( cChar
- 1 );
478 if( nRange
& 1 ) // outside a range?
479 return (mpRangeCodes
[ nRange
] - 1); // => last in prev range
483 // -----------------------------------------------------------------------
485 int ImplFontCharMap::GetIndexFromChar( sal_uInt32 cChar
) const
487 // TODO: improve linear walk?
489 const sal_uInt32
* pRange
= &mpRangeCodes
[0];
490 for( int i
= 0; i
< mnRangeCount
; ++i
)
492 sal_uInt32 cFirst
= *(pRange
++);
493 sal_uInt32 cLast
= *(pRange
++);
495 nCharIndex
+= cLast
- cFirst
;
496 else if( cChar
>= cFirst
)
497 return nCharIndex
+ (cChar
- cFirst
);
505 // -----------------------------------------------------------------------
507 sal_uInt32
ImplFontCharMap::GetCharFromIndex( int nCharIndex
) const
509 // TODO: improve linear walk?
510 const sal_uInt32
* pRange
= &mpRangeCodes
[0];
511 for( int i
= 0; i
< mnRangeCount
; ++i
)
513 sal_uInt32 cFirst
= *(pRange
++);
514 sal_uInt32 cLast
= *(pRange
++);
515 nCharIndex
-= cLast
- cFirst
;
517 return (cLast
+ nCharIndex
);
520 // we can only get here with an out-of-bounds charindex
521 return mpRangeCodes
[0];
524 // =======================================================================
526 static unsigned GetUInt( const unsigned char* p
) { return((p
[0]<<24)+(p
[1]<<16)+(p
[2]<<8)+p
[3]);}
527 static unsigned GetUShort( const unsigned char* p
){ return((p
[0]<<8) | p
[1]);}
528 static int GetSShort( const unsigned char* p
){ return((static_cast<signed char>(p
[0])<<8)|p
[1]);}
530 // TODO: move CMAP parsing directly into the ImplFontCharMap class
531 bool ParseCMAP( const unsigned char* pCmap
, int nLength
, CmapResult
& rResult
)
533 rResult
.mpRangeCodes
= NULL
;
534 rResult
.mpStartGlyphs
= NULL
;
535 rResult
.mpGlyphIds
= NULL
;
536 rResult
.mnRangeCount
= 0;
537 rResult
.mbRecoded
= false;
538 rResult
.mbSymbolic
= false;
540 // parse the table header and check for validity
541 if( !pCmap
|| (nLength
< 24) )
544 if( GetUShort( pCmap
) != 0x0000 ) // simple check for CMAP corruption
547 int nSubTables
= GetUShort( pCmap
+ 2 );
548 if( (nSubTables
<= 0) || (nLength
< (24 + 8*nSubTables
)) )
551 // find the most interesting subtable in the CMAP
552 rtl_TextEncoding eRecodeFrom
= RTL_TEXTENCODING_UNICODE
;
556 for( const unsigned char* p
= pCmap
+ 4; --nSubTables
>= 0; p
+= 8 )
558 int nPlatform
= GetUShort( p
);
559 int nEncoding
= GetUShort( p
+2 );
560 int nPlatformEncoding
= (nPlatform
<< 8) + nEncoding
;
563 rtl_TextEncoding eTmpEncoding
= RTL_TEXTENCODING_UNICODE
;
564 switch( nPlatformEncoding
)
566 case 0x000: nValue
= 20; break; // Unicode 1.0
567 case 0x001: nValue
= 21; break; // Unicode 1.1
568 case 0x002: nValue
= 22; break; // iso10646_1993
569 case 0x003: nValue
= 23; break; // UCS-2
570 case 0x004: nValue
= 24; break; // UCS-4
571 case 0x100: nValue
= 22; break; // Mac Unicode<2.0
572 case 0x103: nValue
= 23; break; // Mac Unicode>2.0
573 case 0x300: nValue
= 5; rResult
.mbSymbolic
= true; break; // Win Symbol
574 case 0x301: nValue
= 28; break; // Win UCS-2
575 case 0x30A: nValue
= 29; break; // Win-UCS-4
576 case 0x302: nValue
= 11; eTmpEncoding
= RTL_TEXTENCODING_SHIFT_JIS
; break;
577 case 0x303: nValue
= 12; eTmpEncoding
= RTL_TEXTENCODING_GB_18030
; break;
578 case 0x304: nValue
= 11; eTmpEncoding
= RTL_TEXTENCODING_BIG5
; break;
579 case 0x305: nValue
= 11; eTmpEncoding
= RTL_TEXTENCODING_MS_949
; break;
580 case 0x306: nValue
= 11; eTmpEncoding
= RTL_TEXTENCODING_MS_1361
; break;
581 default: nValue
= 0; break;
584 if( nValue
<= 0 ) // ignore unknown encodings
587 int nTmpOffset
= GetUInt( p
+4 );
588 int nTmpFormat
= GetUShort( pCmap
+ nTmpOffset
);
589 if( nTmpFormat
== 12 ) // 32bit code -> glyph map format
591 else if( nTmpFormat
!= 4 ) // 16bit code -> glyph map format
592 continue; // ignore other formats
594 if( nBestVal
< nValue
)
597 nOffset
= nTmpOffset
;
598 nFormat
= nTmpFormat
;
599 eRecodeFrom
= eTmpEncoding
;
603 // parse the best CMAP subtable
605 sal_uInt32
* pCodePairs
= NULL
;
606 int* pStartGlyphs
= NULL
;
608 typedef std::vector
<USHORT
> U16Vector
;
609 U16Vector aGlyphIdArray
;
610 aGlyphIdArray
.reserve( 0x1000 );
611 aGlyphIdArray
.push_back( 0 );
613 // format 4, the most common 16bit char mapping table
614 if( (nFormat
== 4) && ((nOffset
+16) < nLength
) )
616 int nSegCountX2
= GetUShort( pCmap
+ nOffset
+ 6 );
617 nRangeCount
= nSegCountX2
/2 - 1;
618 pCodePairs
= new sal_uInt32
[ nRangeCount
* 2 ];
619 pStartGlyphs
= new int[ nRangeCount
];
620 const unsigned char* pLimitBase
= pCmap
+ nOffset
+ 14;
621 const unsigned char* pBeginBase
= pLimitBase
+ nSegCountX2
+ 2;
622 const unsigned char* pDeltaBase
= pBeginBase
+ nSegCountX2
;
623 const unsigned char* pOffsetBase
= pDeltaBase
+ nSegCountX2
;
624 sal_uInt32
* pCP
= pCodePairs
;
625 for( int i
= 0; i
< nRangeCount
; ++i
)
627 const sal_uInt32 cMinChar
= GetUShort( pBeginBase
+ 2*i
);
628 const sal_uInt32 cMaxChar
= GetUShort( pLimitBase
+ 2*i
);
629 const int nGlyphDelta
= GetSShort( pDeltaBase
+ 2*i
);
630 const int nRangeOffset
= GetUShort( pOffsetBase
+ 2*i
);
631 if( cMinChar
> cMaxChar
) // no sane font should trigger this
633 if( cMaxChar
== 0xFFFF )
636 *(pCP
++) = cMaxChar
+ 1;
637 if( !nRangeOffset
) {
638 // glyphid can be calculated directly
639 pStartGlyphs
[i
] = (cMinChar
+ nGlyphDelta
) & 0xFFFF;
641 // update the glyphid-array with the glyphs in this range
642 pStartGlyphs
[i
] = -(int)aGlyphIdArray
.size();
643 const unsigned char* pGlyphIdPtr
= pOffsetBase
+ 2*i
+ nRangeOffset
;
644 for( sal_uInt32 c
= cMinChar
; c
<= cMaxChar
; ++c
, pGlyphIdPtr
+=2 ) {
645 const int nGlyphIndex
= GetUShort( pGlyphIdPtr
) + nGlyphDelta
;
646 aGlyphIdArray
.push_back( static_cast<USHORT
>(nGlyphIndex
) );
650 nRangeCount
= (pCP
- pCodePairs
) / 2;
652 // format 12, the most common 32bit char mapping table
653 else if( (nFormat
== 12) && ((nOffset
+16) < nLength
) )
655 nRangeCount
= GetUInt( pCmap
+ nOffset
+ 12 );
656 pCodePairs
= new sal_uInt32
[ nRangeCount
* 2 ];
657 pStartGlyphs
= new int[ nRangeCount
];
658 const unsigned char* pGroup
= pCmap
+ nOffset
+ 16;
659 sal_uInt32
* pCP
= pCodePairs
;
660 for( int i
= 0; i
< nRangeCount
; ++i
)
662 sal_uInt32 cMinChar
= GetUInt( pGroup
+ 0 );
663 sal_uInt32 cMaxChar
= GetUInt( pGroup
+ 4 );
664 int nGlyphId
= GetUInt( pGroup
+ 8 );
666 #if 0 // TODO: remove unicode baseplane clipping for UCS-4 support
667 if( cMinChar
> 0xFFFF )
669 if( cMaxChar
> 0xFFFF )
672 if( cMinChar
> cMaxChar
) // no sane font should trigger this
676 *(pCP
++) = cMaxChar
+ 1;
677 pStartGlyphs
[i
] = nGlyphId
;
679 nRangeCount
= (pCP
- pCodePairs
) / 2;
682 // check if any subtable resulted in something usable
683 if( nRangeCount
<= 0 )
686 delete[] pStartGlyphs
;
688 // even when no CMAP is available we know it for symbol fonts
689 if( rResult
.mbSymbolic
)
691 pCodePairs
= new sal_uInt32
[4];
692 pCodePairs
[0] = 0x0020; // aliased symbols
693 pCodePairs
[1] = 0x0100;
694 pCodePairs
[2] = 0xF020; // original symbols
695 pCodePairs
[3] = 0xF100;
696 rResult
.mpRangeCodes
= pCodePairs
;
697 rResult
.mnRangeCount
= 2;
704 // recode the code ranges to their unicode encoded ranges if needed
705 rtl_TextToUnicodeConverter aConverter
= NULL
;
706 rtl_UnicodeToTextContext aCvtContext
= NULL
;
708 rResult
.mbRecoded
= ( eRecodeFrom
!= RTL_TEXTENCODING_UNICODE
);
709 if( rResult
.mbRecoded
)
711 aConverter
= rtl_createTextToUnicodeConverter( eRecodeFrom
);
712 aCvtContext
= rtl_createTextToUnicodeContext( aConverter
);
715 if( aConverter
&& aCvtContext
)
717 // determine the set of supported unicodes from encoded ranges
718 typedef std::set
<sal_uInt32
> IntSet
;
719 IntSet aSupportedUnicodes
;
721 static const int NINSIZE
= 64;
722 static const int NOUTSIZE
= 64;
723 sal_Char cCharsInp
[ NINSIZE
];
724 sal_Unicode cCharsOut
[ NOUTSIZE
];
725 sal_uInt32
* pCP
= pCodePairs
;
726 for( int i
= 0; i
< nRangeCount
; ++i
)
728 sal_uInt32 cMin
= *(pCP
++);
729 sal_uInt32 cEnd
= *(pCP
++);
733 for(; (cMin
< cEnd
) && (j
< NINSIZE
); ++cMin
)
736 cCharsInp
[ j
++ ] = static_cast<sal_Char
>(cMin
>> 8);
737 if( (cMin
>= 0x0100) || (cMin
< 0x00A0) )
738 cCharsInp
[ j
++ ] = static_cast<sal_Char
>(cMin
);
742 sal_Size nSrcCvtBytes
;
743 int nOutLen
= rtl_convertTextToUnicode(
744 aConverter
, aCvtContext
,
745 cCharsInp
, j
, cCharsOut
, NOUTSIZE
,
746 RTL_TEXTTOUNICODE_FLAGS_INVALID_IGNORE
747 | RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_IGNORE
,
748 &nCvtInfo
, &nSrcCvtBytes
);
750 for( j
= 0; j
< nOutLen
; ++j
)
751 aSupportedUnicodes
.insert( cCharsOut
[j
] );
755 rtl_destroyTextToUnicodeConverter( aCvtContext
);
756 rtl_destroyTextToUnicodeConverter( aConverter
);
758 // convert the set of supported unicodes to ranges
759 typedef std::vector
<sal_uInt32
> IntVector
;
760 IntVector aSupportedRanges
;
762 IntSet::const_iterator itChar
= aSupportedUnicodes
.begin();
763 for(; itChar
!= aSupportedUnicodes
.end(); ++itChar
)
765 if( aSupportedRanges
.empty()
766 || (aSupportedRanges
.back() != *itChar
) )
768 // add new range beginning with current unicode
769 aSupportedRanges
.push_back( *itChar
);
770 aSupportedRanges
.push_back( 0 );
773 // extend existing range to include current unicode
774 aSupportedRanges
.back() = *itChar
+ 1;
777 // glyph mapping for non-unicode fonts not implemented
778 delete[] pStartGlyphs
;
780 aGlyphIdArray
.clear();
782 // make a pCodePairs array using the vector from above
784 nRangeCount
= aSupportedRanges
.size() / 2;
785 if( nRangeCount
<= 0 )
787 pCodePairs
= new sal_uInt32
[ nRangeCount
* 2 ];
788 IntVector::const_iterator itInt
= aSupportedRanges
.begin();
789 for( pCP
= pCodePairs
; itInt
!= aSupportedRanges
.end(); ++itInt
)
793 // prepare the glyphid-array if needed
794 // TODO: merge ranges if they are close enough?
795 USHORT
* pGlyphIds
= NULL
;
796 if( !aGlyphIdArray
.empty())
798 pGlyphIds
= new USHORT
[ aGlyphIdArray
.size() ];
799 USHORT
* pOut
= pGlyphIds
;
800 U16Vector::const_iterator it
= aGlyphIdArray
.begin();
801 while( it
!= aGlyphIdArray
.end() )
805 // update the result struct
806 rResult
.mpRangeCodes
= pCodePairs
;
807 rResult
.mpStartGlyphs
= pStartGlyphs
;
808 rResult
.mnRangeCount
= nRangeCount
;
809 rResult
.mpGlyphIds
= pGlyphIds
;
813 // =======================================================================
815 FontCharMap::FontCharMap()
816 : mpImpl( ImplFontCharMap::GetDefaultMap() )
819 // -----------------------------------------------------------------------
821 FontCharMap::~FontCharMap()
823 mpImpl
->DeReference();
827 // -----------------------------------------------------------------------
829 int FontCharMap::GetCharCount() const
831 return mpImpl
->GetCharCount();
834 // -----------------------------------------------------------------------
836 int FontCharMap::CountCharsInRange( sal_uInt32 cMin
, sal_uInt32 cMax
) const
838 return mpImpl
->CountCharsInRange( cMin
, cMax
);
841 // -----------------------------------------------------------------------
843 void FontCharMap::Reset( ImplFontCharMap
* pNewMap
)
845 if( pNewMap
== NULL
)
847 mpImpl
->DeReference();
848 mpImpl
= ImplFontCharMap::GetDefaultMap();
850 else if( pNewMap
!= mpImpl
)
852 mpImpl
->DeReference();
854 mpImpl
->AddReference();
858 // -----------------------------------------------------------------------
860 BOOL
FontCharMap::IsDefaultMap() const
862 return mpImpl
->IsDefaultMap();
865 // -----------------------------------------------------------------------
867 BOOL
FontCharMap::HasChar( sal_uInt32 cChar
) const
869 return mpImpl
->HasChar( cChar
);
872 // -----------------------------------------------------------------------
874 sal_uInt32
FontCharMap::GetFirstChar() const
876 return mpImpl
->GetFirstChar();
879 // -----------------------------------------------------------------------
881 sal_uInt32
FontCharMap::GetLastChar() const
883 return mpImpl
->GetLastChar();
886 // -----------------------------------------------------------------------
888 sal_uInt32
FontCharMap::GetNextChar( sal_uInt32 cChar
) const
890 return mpImpl
->GetNextChar( cChar
);
893 // -----------------------------------------------------------------------
895 sal_uInt32
FontCharMap::GetPrevChar( sal_uInt32 cChar
) const
897 return mpImpl
->GetPrevChar( cChar
);
900 // -----------------------------------------------------------------------
902 int FontCharMap::GetIndexFromChar( sal_uInt32 cChar
) const
904 return mpImpl
->GetIndexFromChar( cChar
);
907 // -----------------------------------------------------------------------
909 sal_uInt32
FontCharMap::GetCharFromIndex( int nIndex
) const
911 return mpImpl
->GetCharFromIndex( nIndex
);
914 // =======================================================================