xref: /aoo41x/main/vcl/source/gdi/impfont.cxx (revision ff5c5583)
143ad51ffSHerbert Dürr /**************************************************************
243ad51ffSHerbert Dürr  *
343ad51ffSHerbert Dürr  * Licensed to the Apache Software Foundation (ASF) under one
443ad51ffSHerbert Dürr  * or more contributor license agreements.  See the NOTICE file
543ad51ffSHerbert Dürr  * distributed with this work for additional information
643ad51ffSHerbert Dürr  * regarding copyright ownership.  The ASF licenses this file
743ad51ffSHerbert Dürr  * to you under the Apache License, Version 2.0 (the
843ad51ffSHerbert Dürr  * "License"); you may not use this file except in compliance
943ad51ffSHerbert Dürr  * with the License.  You may obtain a copy of the License at
1043ad51ffSHerbert Dürr  *
1143ad51ffSHerbert Dürr  *   http://www.apache.org/licenses/LICENSE-2.0
1243ad51ffSHerbert Dürr  *
1343ad51ffSHerbert Dürr  * Unless required by applicable law or agreed to in writing,
1443ad51ffSHerbert Dürr  * software distributed under the License is distributed on an
1543ad51ffSHerbert Dürr  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
1643ad51ffSHerbert Dürr  * KIND, either express or implied.  See the License for the
1743ad51ffSHerbert Dürr  * specific language governing permissions and limitations
1843ad51ffSHerbert Dürr  * under the License.
1943ad51ffSHerbert Dürr  *
2043ad51ffSHerbert Dürr  *************************************************************/
2143ad51ffSHerbert Dürr 
2243ad51ffSHerbert Dürr // MARKER(update_precomp.py): autogen include statement, do not remove
2343ad51ffSHerbert Dürr #include "precompiled_vcl.hxx"
2443ad51ffSHerbert Dürr 
2543ad51ffSHerbert Dürr #include <vcl/metric.hxx>
2643ad51ffSHerbert Dürr #include <outfont.hxx>
2743ad51ffSHerbert Dürr #include <impfont.hxx>
2843ad51ffSHerbert Dürr 
2943ad51ffSHerbert Dürr #include <vector>
3043ad51ffSHerbert Dürr #include <set>
3143ad51ffSHerbert Dürr 
3243ad51ffSHerbert Dürr // =======================================================================
3343ad51ffSHerbert Dürr 
CmapResult(bool bSymbolic,const sal_UCS4 * pRangeCodes,int nRangeCount,const int * pStartGlyphs,const sal_uInt16 * pExtraGlyphIds)3443ad51ffSHerbert Dürr CmapResult::CmapResult( bool bSymbolic,
3543ad51ffSHerbert Dürr 	const sal_UCS4* pRangeCodes, int nRangeCount,
3643ad51ffSHerbert Dürr 	const int* pStartGlyphs, const sal_uInt16* pExtraGlyphIds )
3743ad51ffSHerbert Dürr :	mpRangeCodes( pRangeCodes)
3843ad51ffSHerbert Dürr ,	mpStartGlyphs( pStartGlyphs)
3943ad51ffSHerbert Dürr ,	mpGlyphIds( pExtraGlyphIds)
4043ad51ffSHerbert Dürr ,	mnRangeCount( nRangeCount)
4143ad51ffSHerbert Dürr ,	mbSymbolic( bSymbolic)
4243ad51ffSHerbert Dürr ,	mbRecoded( false)
4343ad51ffSHerbert Dürr {}
4443ad51ffSHerbert Dürr 
4543ad51ffSHerbert Dürr // =======================================================================
4643ad51ffSHerbert Dürr 
ImplFontCharMap(const CmapResult & rCR)4743ad51ffSHerbert Dürr ImplFontCharMap::ImplFontCharMap( const CmapResult& rCR )
4843ad51ffSHerbert Dürr :	mpRangeCodes( rCR.mpRangeCodes )
4943ad51ffSHerbert Dürr ,	mpStartGlyphs( rCR.mpStartGlyphs )
5043ad51ffSHerbert Dürr ,	mpGlyphIds( rCR.mpGlyphIds )
5143ad51ffSHerbert Dürr ,	mnRangeCount( rCR.mnRangeCount )
5243ad51ffSHerbert Dürr ,	mnCharCount( 0 )
5343ad51ffSHerbert Dürr ,	mnRefCount( 1 )
5443ad51ffSHerbert Dürr {
5543ad51ffSHerbert Dürr 	const sal_UCS4* pRangePtr = mpRangeCodes;
5643ad51ffSHerbert Dürr 	for( int i = mnRangeCount; --i >= 0; pRangePtr += 2 )
5743ad51ffSHerbert Dürr 	{
5843ad51ffSHerbert Dürr 		sal_UCS4 cFirst = pRangePtr[0];
5943ad51ffSHerbert Dürr 		sal_UCS4 cLast  = pRangePtr[1];
6043ad51ffSHerbert Dürr 		mnCharCount += cLast - cFirst;
6143ad51ffSHerbert Dürr 	}
6243ad51ffSHerbert Dürr }
6343ad51ffSHerbert Dürr 
6443ad51ffSHerbert Dürr static ImplFontCharMap* pDefaultImplFontCharMap = NULL;
6543ad51ffSHerbert Dürr static const sal_UCS4 aDefaultUnicodeRanges[] = {0x0020,0xD800, 0xE000,0xFFF0};
6643ad51ffSHerbert Dürr static const sal_UCS4 aDefaultSymbolRanges[] = {0x0020,0x0100, 0xF020,0xF100};
6743ad51ffSHerbert Dürr 
6843ad51ffSHerbert Dürr // -----------------------------------------------------------------------
6943ad51ffSHerbert Dürr 
IsDefaultMap() const7043ad51ffSHerbert Dürr bool ImplFontCharMap::IsDefaultMap() const
7143ad51ffSHerbert Dürr {
7243ad51ffSHerbert Dürr 	const bool bIsDefault = (mpRangeCodes == aDefaultUnicodeRanges) || (mpRangeCodes == aDefaultSymbolRanges);
7343ad51ffSHerbert Dürr 	return bIsDefault;
7443ad51ffSHerbert Dürr }
7543ad51ffSHerbert Dürr 
7643ad51ffSHerbert Dürr // -----------------------------------------------------------------------
7743ad51ffSHerbert Dürr 
~ImplFontCharMap()7843ad51ffSHerbert Dürr ImplFontCharMap::~ImplFontCharMap()
7943ad51ffSHerbert Dürr {
8043ad51ffSHerbert Dürr 	if( IsDefaultMap() )
8143ad51ffSHerbert Dürr 		return;
8243ad51ffSHerbert Dürr 	delete[] mpRangeCodes;
8343ad51ffSHerbert Dürr 	delete[] mpStartGlyphs;
8443ad51ffSHerbert Dürr 	delete[] mpGlyphIds;
8543ad51ffSHerbert Dürr }
8643ad51ffSHerbert Dürr 
8743ad51ffSHerbert Dürr // -----------------------------------------------------------------------
8843ad51ffSHerbert Dürr 
GetDefaultMap(bool bSymbols)8943ad51ffSHerbert Dürr ImplFontCharMap* ImplFontCharMap::GetDefaultMap( bool bSymbols)
9043ad51ffSHerbert Dürr {
9143ad51ffSHerbert Dürr 	if( pDefaultImplFontCharMap )
9243ad51ffSHerbert Dürr 		pDefaultImplFontCharMap->AddReference();
9343ad51ffSHerbert Dürr 	else
9443ad51ffSHerbert Dürr 	{
9543ad51ffSHerbert Dürr 		const sal_UCS4* pRangeCodes = aDefaultUnicodeRanges;
9643ad51ffSHerbert Dürr 		int nCodesCount = sizeof(aDefaultUnicodeRanges) / sizeof(*pRangeCodes);
9743ad51ffSHerbert Dürr 		if( bSymbols )
9843ad51ffSHerbert Dürr 		{
9943ad51ffSHerbert Dürr 			pRangeCodes	= aDefaultSymbolRanges;
10043ad51ffSHerbert Dürr 			nCodesCount	= sizeof(aDefaultSymbolRanges) / sizeof(*pRangeCodes);
10143ad51ffSHerbert Dürr 		}
10243ad51ffSHerbert Dürr 
10343ad51ffSHerbert Dürr 		CmapResult aDefaultCR( bSymbols, pRangeCodes, nCodesCount/2 );
10443ad51ffSHerbert Dürr 		pDefaultImplFontCharMap = new ImplFontCharMap( aDefaultCR );
10543ad51ffSHerbert Dürr 	}
10643ad51ffSHerbert Dürr 
10743ad51ffSHerbert Dürr 	return pDefaultImplFontCharMap;
10843ad51ffSHerbert Dürr }
10943ad51ffSHerbert Dürr 
11043ad51ffSHerbert Dürr // -----------------------------------------------------------------------
11143ad51ffSHerbert Dürr 
AddReference(void) const11243ad51ffSHerbert Dürr void ImplFontCharMap::AddReference( void) const
11343ad51ffSHerbert Dürr {
11443ad51ffSHerbert Dürr 	++mnRefCount;
11543ad51ffSHerbert Dürr }
11643ad51ffSHerbert Dürr 
11743ad51ffSHerbert Dürr // -----------------------------------------------------------------------
11843ad51ffSHerbert Dürr 
DeReference(void) const11943ad51ffSHerbert Dürr void ImplFontCharMap::DeReference( void) const
12043ad51ffSHerbert Dürr {
12143ad51ffSHerbert Dürr 	if( --mnRefCount <= 0 )
12243ad51ffSHerbert Dürr 		if( this != pDefaultImplFontCharMap )
12343ad51ffSHerbert Dürr 			delete this;
12443ad51ffSHerbert Dürr }
12543ad51ffSHerbert Dürr 
12643ad51ffSHerbert Dürr // -----------------------------------------------------------------------
12743ad51ffSHerbert Dürr 
GetCharCount() const12843ad51ffSHerbert Dürr int ImplFontCharMap::GetCharCount() const
12943ad51ffSHerbert Dürr {
13043ad51ffSHerbert Dürr 	return mnCharCount;
13143ad51ffSHerbert Dürr }
13243ad51ffSHerbert Dürr 
13343ad51ffSHerbert Dürr // -----------------------------------------------------------------------
13443ad51ffSHerbert Dürr 
ImplFindRangeIndex(sal_UCS4 cChar) const13543ad51ffSHerbert Dürr int ImplFontCharMap::ImplFindRangeIndex( sal_UCS4 cChar ) const
13643ad51ffSHerbert Dürr {
13743ad51ffSHerbert Dürr 	int nLower = 0;
13843ad51ffSHerbert Dürr 	int nMid   = mnRangeCount;
13943ad51ffSHerbert Dürr 	int nUpper = 2 * mnRangeCount - 1;
14043ad51ffSHerbert Dürr 	while( nLower < nUpper )
14143ad51ffSHerbert Dürr 	{
14243ad51ffSHerbert Dürr 		if( cChar >= mpRangeCodes[ nMid ] )
14343ad51ffSHerbert Dürr 			nLower = nMid;
14443ad51ffSHerbert Dürr 		else
14543ad51ffSHerbert Dürr 			nUpper = nMid - 1;
14643ad51ffSHerbert Dürr 		nMid = (nLower + nUpper + 1) / 2;
14743ad51ffSHerbert Dürr 	}
14843ad51ffSHerbert Dürr 
14943ad51ffSHerbert Dürr 	return nMid;
15043ad51ffSHerbert Dürr }
15143ad51ffSHerbert Dürr 
15243ad51ffSHerbert Dürr // -----------------------------------------------------------------------
15343ad51ffSHerbert Dürr 
HasChar(sal_UCS4 cChar) const15443ad51ffSHerbert Dürr bool ImplFontCharMap::HasChar( sal_UCS4 cChar ) const
15543ad51ffSHerbert Dürr {
15643ad51ffSHerbert Dürr 	bool bHasChar = false;
15743ad51ffSHerbert Dürr 
15843ad51ffSHerbert Dürr 	if( mpStartGlyphs  == NULL ) { // only the char-ranges are known
15943ad51ffSHerbert Dürr 		const int nRange = ImplFindRangeIndex( cChar );
16043ad51ffSHerbert Dürr 		if( nRange==0 && cChar<mpRangeCodes[0] )
16143ad51ffSHerbert Dürr 			return false;
16243ad51ffSHerbert Dürr 		bHasChar = ((nRange & 1) == 0); // inside a range
16343ad51ffSHerbert Dürr 	} else { // glyph mapping is available
16443ad51ffSHerbert Dürr 		const int nGlyphIndex = GetGlyphIndex( cChar );
16543ad51ffSHerbert Dürr 		bHasChar = (nGlyphIndex != 0); // not the notdef-glyph
16643ad51ffSHerbert Dürr 	}
16743ad51ffSHerbert Dürr 
16843ad51ffSHerbert Dürr 	return bHasChar;
16943ad51ffSHerbert Dürr }
17043ad51ffSHerbert Dürr 
17143ad51ffSHerbert Dürr // -----------------------------------------------------------------------
17243ad51ffSHerbert Dürr 
GetGlyphIndex(sal_UCS4 cChar) const17343ad51ffSHerbert Dürr int ImplFontCharMap::GetGlyphIndex( sal_UCS4 cChar ) const
17443ad51ffSHerbert Dürr {
17543ad51ffSHerbert Dürr 	// return -1 if the object doesn't know the glyph ids
17643ad51ffSHerbert Dürr 	if( !mpStartGlyphs )
17743ad51ffSHerbert Dürr 		return -1;
17843ad51ffSHerbert Dürr 
17943ad51ffSHerbert Dürr 	// return 0 if the unicode doesn't have a matching glyph
18043ad51ffSHerbert Dürr 	int nRange = ImplFindRangeIndex( cChar );
18143ad51ffSHerbert Dürr 	// check that we are inside any range
18243ad51ffSHerbert Dürr 	if( (nRange == 0) && (cChar < mpRangeCodes[0]) ) {
18343ad51ffSHerbert Dürr 		// symbol aliasing gives symbol fonts a second chance
18443ad51ffSHerbert Dürr 		const bool bSymbolic = (mpRangeCodes[0]>=0xF000) & (mpRangeCodes[1]<=0xF0FF);
18543ad51ffSHerbert Dürr 		if( !bSymbolic )
18643ad51ffSHerbert Dürr 			return 0;
18743ad51ffSHerbert Dürr 		// check for symbol aliasing (U+F0xx -> U+00xx)
18843ad51ffSHerbert Dürr 		nRange = ImplFindRangeIndex( cChar | 0xF000 );
18943ad51ffSHerbert Dürr 	}
19043ad51ffSHerbert Dürr 	// check that we are inside a range
19143ad51ffSHerbert Dürr 	if( (nRange & 1) != 0 )
19243ad51ffSHerbert Dürr 		return 0;
19343ad51ffSHerbert Dürr 
19443ad51ffSHerbert Dürr 	// get glyph index directly or indirectly
19543ad51ffSHerbert Dürr 	int nGlyphIndex = cChar - mpRangeCodes[ nRange ];
19643ad51ffSHerbert Dürr 	const int nStartIndex = mpStartGlyphs[ nRange/2 ];
19743ad51ffSHerbert Dürr 	if( nStartIndex >= 0 ) {
19843ad51ffSHerbert Dürr 		// the glyph index can be calculated
19943ad51ffSHerbert Dürr 		nGlyphIndex += nStartIndex;
20043ad51ffSHerbert Dürr 	} else {
20143ad51ffSHerbert Dürr 		// the glyphid array has the glyph index
20243ad51ffSHerbert Dürr 		nGlyphIndex = mpGlyphIds[ nGlyphIndex - nStartIndex];
20343ad51ffSHerbert Dürr 	}
20443ad51ffSHerbert Dürr 
20543ad51ffSHerbert Dürr 	return nGlyphIndex;
20643ad51ffSHerbert Dürr }
20743ad51ffSHerbert Dürr 
20843ad51ffSHerbert Dürr // -----------------------------------------------------------------------
20943ad51ffSHerbert Dürr 
21043ad51ffSHerbert Dürr // returns the number of chars supported by the font, which
21143ad51ffSHerbert Dürr // are inside the unicode range from cMin to cMax (inclusive)
CountCharsInRange(sal_UCS4 cMin,sal_UCS4 cMax) const21243ad51ffSHerbert Dürr int ImplFontCharMap::CountCharsInRange( sal_UCS4 cMin, sal_UCS4 cMax ) const
21343ad51ffSHerbert Dürr {
21443ad51ffSHerbert Dürr 	int nCount = 0;
21543ad51ffSHerbert Dürr 
21643ad51ffSHerbert Dürr 	// find and adjust range and char count for cMin
21743ad51ffSHerbert Dürr 	int nRangeMin = ImplFindRangeIndex( cMin );
21843ad51ffSHerbert Dürr 	if( nRangeMin & 1 )
21943ad51ffSHerbert Dürr 		++nRangeMin;
22043ad51ffSHerbert Dürr 	else if( cMin > mpRangeCodes[ nRangeMin ] )
22143ad51ffSHerbert Dürr 		nCount -= cMin - mpRangeCodes[ nRangeMin ];
22243ad51ffSHerbert Dürr 
22343ad51ffSHerbert Dürr 	// find and adjust range and char count for cMax
22443ad51ffSHerbert Dürr 	int nRangeMax = ImplFindRangeIndex( cMax );
22543ad51ffSHerbert Dürr 	if( nRangeMax & 1 )
22643ad51ffSHerbert Dürr 		--nRangeMax;
22743ad51ffSHerbert Dürr 	else
22843ad51ffSHerbert Dürr 		nCount -= mpRangeCodes[ nRangeMax+1 ] - cMax - 1;
22943ad51ffSHerbert Dürr 
23043ad51ffSHerbert Dürr 	// count chars in complete ranges between cMin and cMax
23143ad51ffSHerbert Dürr 	for( int i = nRangeMin; i <= nRangeMax; i+=2 )
23243ad51ffSHerbert Dürr 		nCount += mpRangeCodes[i+1] - mpRangeCodes[i];
23343ad51ffSHerbert Dürr 
23443ad51ffSHerbert Dürr 	return nCount;
23543ad51ffSHerbert Dürr }
23643ad51ffSHerbert Dürr 
23743ad51ffSHerbert Dürr // -----------------------------------------------------------------------
23843ad51ffSHerbert Dürr 
GetFirstChar() const23943ad51ffSHerbert Dürr sal_UCS4 ImplFontCharMap::GetFirstChar() const
24043ad51ffSHerbert Dürr {
24143ad51ffSHerbert Dürr 	return mpRangeCodes[0];
24243ad51ffSHerbert Dürr }
24343ad51ffSHerbert Dürr 
24443ad51ffSHerbert Dürr // -----------------------------------------------------------------------
24543ad51ffSHerbert Dürr 
GetLastChar() const24643ad51ffSHerbert Dürr sal_UCS4 ImplFontCharMap::GetLastChar() const
24743ad51ffSHerbert Dürr {
24843ad51ffSHerbert Dürr 	return (mpRangeCodes[ 2*mnRangeCount-1 ] - 1);
24943ad51ffSHerbert Dürr }
25043ad51ffSHerbert Dürr 
25143ad51ffSHerbert Dürr // -----------------------------------------------------------------------
25243ad51ffSHerbert Dürr 
GetNextChar(sal_UCS4 cChar) const25343ad51ffSHerbert Dürr sal_UCS4 ImplFontCharMap::GetNextChar( sal_UCS4 cChar ) const
25443ad51ffSHerbert Dürr {
25543ad51ffSHerbert Dürr 	if( cChar < GetFirstChar() )
25643ad51ffSHerbert Dürr 		return GetFirstChar();
25743ad51ffSHerbert Dürr 	if( cChar >= GetLastChar() )
25843ad51ffSHerbert Dürr 		return GetLastChar();
25943ad51ffSHerbert Dürr 
26043ad51ffSHerbert Dürr 	int nRange = ImplFindRangeIndex( cChar + 1 );
26143ad51ffSHerbert Dürr 	if( nRange & 1 )                       // outside of range?
26243ad51ffSHerbert Dürr 		return mpRangeCodes[ nRange + 1 ]; // => first in next range
26343ad51ffSHerbert Dürr 	return (cChar + 1);
26443ad51ffSHerbert Dürr }
26543ad51ffSHerbert Dürr 
26643ad51ffSHerbert Dürr // -----------------------------------------------------------------------
26743ad51ffSHerbert Dürr 
GetPrevChar(sal_UCS4 cChar) const26843ad51ffSHerbert Dürr sal_UCS4 ImplFontCharMap::GetPrevChar( sal_UCS4 cChar ) const
26943ad51ffSHerbert Dürr {
27043ad51ffSHerbert Dürr 	if( cChar <= GetFirstChar() )
27143ad51ffSHerbert Dürr 		return GetFirstChar();
27243ad51ffSHerbert Dürr 	if( cChar > GetLastChar() )
27343ad51ffSHerbert Dürr 		return GetLastChar();
27443ad51ffSHerbert Dürr 
27543ad51ffSHerbert Dürr 	int nRange = ImplFindRangeIndex( cChar - 1 );
27643ad51ffSHerbert Dürr 	if( nRange & 1 )                            // outside a range?
27743ad51ffSHerbert Dürr 		return (mpRangeCodes[ nRange ] - 1);    // => last in prev range
27843ad51ffSHerbert Dürr 	return (cChar - 1);
27943ad51ffSHerbert Dürr }
28043ad51ffSHerbert Dürr 
28143ad51ffSHerbert Dürr // -----------------------------------------------------------------------
28243ad51ffSHerbert Dürr 
GetIndexFromChar(sal_UCS4 cChar) const28343ad51ffSHerbert Dürr int ImplFontCharMap::GetIndexFromChar( sal_UCS4 cChar ) const
28443ad51ffSHerbert Dürr {
28543ad51ffSHerbert Dürr 	// TODO: improve linear walk?
28643ad51ffSHerbert Dürr 	int nCharIndex = 0;
28743ad51ffSHerbert Dürr 	const sal_UCS4* pRange = &mpRangeCodes[0];
28843ad51ffSHerbert Dürr 	for( int i = 0; i < mnRangeCount; ++i )
28943ad51ffSHerbert Dürr 	{
29043ad51ffSHerbert Dürr 		sal_UCS4 cFirst = *(pRange++);
29143ad51ffSHerbert Dürr 		sal_UCS4 cLast  = *(pRange++);
29243ad51ffSHerbert Dürr 		if( cChar >= cLast )
29343ad51ffSHerbert Dürr 			nCharIndex += cLast - cFirst;
29443ad51ffSHerbert Dürr 		else if( cChar >= cFirst )
29543ad51ffSHerbert Dürr 			return nCharIndex + (cChar - cFirst);
29643ad51ffSHerbert Dürr 		else
29743ad51ffSHerbert Dürr 			break;
29843ad51ffSHerbert Dürr 	}
29943ad51ffSHerbert Dürr 
30043ad51ffSHerbert Dürr 	return -1;
30143ad51ffSHerbert Dürr }
30243ad51ffSHerbert Dürr 
30343ad51ffSHerbert Dürr // -----------------------------------------------------------------------
30443ad51ffSHerbert Dürr 
GetCharFromIndex(int nCharIndex) const30543ad51ffSHerbert Dürr sal_UCS4 ImplFontCharMap::GetCharFromIndex( int nCharIndex ) const
30643ad51ffSHerbert Dürr {
30743ad51ffSHerbert Dürr 	// TODO: improve linear walk?
30843ad51ffSHerbert Dürr 	const sal_UCS4* pRange = &mpRangeCodes[0];
30943ad51ffSHerbert Dürr 	for( int i = 0; i < mnRangeCount; ++i )
31043ad51ffSHerbert Dürr 	{
31143ad51ffSHerbert Dürr 		sal_UCS4 cFirst = *(pRange++);
31243ad51ffSHerbert Dürr 		sal_UCS4 cLast  = *(pRange++);
31343ad51ffSHerbert Dürr 		nCharIndex -= cLast - cFirst;
31443ad51ffSHerbert Dürr 		if( nCharIndex < 0 )
31543ad51ffSHerbert Dürr 			return (cLast + nCharIndex);
31643ad51ffSHerbert Dürr 	}
31743ad51ffSHerbert Dürr 
31843ad51ffSHerbert Dürr 	// we can only get here with an out-of-bounds charindex
31943ad51ffSHerbert Dürr 	return mpRangeCodes[0];
32043ad51ffSHerbert Dürr }
32143ad51ffSHerbert Dürr 
32243ad51ffSHerbert Dürr // =======================================================================
32343ad51ffSHerbert Dürr 
GetUInt(const unsigned char * p)32443ad51ffSHerbert Dürr static unsigned GetUInt( const unsigned char* p ) { return((p[0]<<24)+(p[1]<<16)+(p[2]<<8)+p[3]);}
Getsal_uInt16(const unsigned char * p)32543ad51ffSHerbert Dürr static unsigned Getsal_uInt16( const unsigned char* p ){ return((p[0]<<8) | p[1]);}
GetSShort(const unsigned char * p)32643ad51ffSHerbert Dürr static int GetSShort( const unsigned char* p ){ return((static_cast<signed char>(p[0])<<8)|p[1]);}
32743ad51ffSHerbert Dürr 
32843ad51ffSHerbert Dürr // TODO: move CMAP parsing directly into the ImplFontCharMap class
ParseCMAP(const unsigned char * pCmap,int nLength,CmapResult & rResult)32943ad51ffSHerbert Dürr bool ParseCMAP( const unsigned char* pCmap, int nLength, CmapResult& rResult )
33043ad51ffSHerbert Dürr {
33143ad51ffSHerbert Dürr     rResult.mpRangeCodes = NULL;
33243ad51ffSHerbert Dürr     rResult.mpStartGlyphs= NULL;
33343ad51ffSHerbert Dürr     rResult.mpGlyphIds	 = NULL;
33443ad51ffSHerbert Dürr     rResult.mnRangeCount = 0;
33543ad51ffSHerbert Dürr     rResult.mbRecoded    = false;
33643ad51ffSHerbert Dürr     rResult.mbSymbolic   = false;
33743ad51ffSHerbert Dürr 
33843ad51ffSHerbert Dürr     // parse the table header and check for validity
33943ad51ffSHerbert Dürr     if( !pCmap || (nLength < 24) )
34043ad51ffSHerbert Dürr         return false;
34143ad51ffSHerbert Dürr 
34243ad51ffSHerbert Dürr     if( Getsal_uInt16( pCmap ) != 0x0000 ) // simple check for CMAP corruption
34343ad51ffSHerbert Dürr         return false;
34443ad51ffSHerbert Dürr 
34543ad51ffSHerbert Dürr     int nSubTables = Getsal_uInt16( pCmap + 2 );
34643ad51ffSHerbert Dürr     if( (nSubTables <= 0) || (nLength < (24 + 8*nSubTables)) )
34743ad51ffSHerbert Dürr         return false;
34843ad51ffSHerbert Dürr 
34943ad51ffSHerbert Dürr     // find the most interesting subtable in the CMAP
35043ad51ffSHerbert Dürr     rtl_TextEncoding eRecodeFrom = RTL_TEXTENCODING_UNICODE;
35143ad51ffSHerbert Dürr     int nOffset = 0;
35243ad51ffSHerbert Dürr     int nFormat = -1;
35343ad51ffSHerbert Dürr     int nBestVal = 0;
35443ad51ffSHerbert Dürr     for( const unsigned char* p = pCmap + 4; --nSubTables >= 0; p += 8 )
35543ad51ffSHerbert Dürr     {
35643ad51ffSHerbert Dürr         int nPlatform = Getsal_uInt16( p );
35743ad51ffSHerbert Dürr         int nEncoding = Getsal_uInt16( p+2 );
35843ad51ffSHerbert Dürr         int nPlatformEncoding = (nPlatform << 8) + nEncoding;
35943ad51ffSHerbert Dürr 
36043ad51ffSHerbert Dürr         int nValue;
36143ad51ffSHerbert Dürr         rtl_TextEncoding eTmpEncoding = RTL_TEXTENCODING_UNICODE;
36243ad51ffSHerbert Dürr         switch( nPlatformEncoding )
36343ad51ffSHerbert Dürr         {
36443ad51ffSHerbert Dürr             case 0x000: nValue = 20; break;                             // Unicode 1.0
36543ad51ffSHerbert Dürr             case 0x001: nValue = 21; break;                             // Unicode 1.1
36643ad51ffSHerbert Dürr             case 0x002: nValue = 22; break;                             // iso10646_1993
36743ad51ffSHerbert Dürr             case 0x003: nValue = 23; break;                             // UCS-2
36843ad51ffSHerbert Dürr             case 0x004: nValue = 24; break;                             // UCS-4
36943ad51ffSHerbert Dürr             case 0x100: nValue = 22; break;                             // Mac Unicode<2.0
37043ad51ffSHerbert Dürr             case 0x103: nValue = 23; break;                             // Mac Unicode>2.0
37143ad51ffSHerbert Dürr             case 0x300: nValue =  5; rResult.mbSymbolic = true; break;  // Win Symbol
37243ad51ffSHerbert Dürr             case 0x301: nValue = 28; break;                             // Win UCS-2
37343ad51ffSHerbert Dürr             case 0x30A: nValue = 29; break;                             // Win-UCS-4
37443ad51ffSHerbert Dürr             case 0x302: nValue = 11; eTmpEncoding = RTL_TEXTENCODING_SHIFT_JIS; break;
37543ad51ffSHerbert Dürr             case 0x303: nValue = 12; eTmpEncoding = RTL_TEXTENCODING_GB_18030; break;
37643ad51ffSHerbert Dürr             case 0x304: nValue = 11; eTmpEncoding = RTL_TEXTENCODING_BIG5; break;
37743ad51ffSHerbert Dürr             case 0x305: nValue = 11; eTmpEncoding = RTL_TEXTENCODING_MS_949; break;
37843ad51ffSHerbert Dürr             case 0x306: nValue = 11; eTmpEncoding = RTL_TEXTENCODING_MS_1361; break;
37943ad51ffSHerbert Dürr             default:    nValue = 0; break;
38043ad51ffSHerbert Dürr         }
38143ad51ffSHerbert Dürr 
38243ad51ffSHerbert Dürr         if( nValue <= 0 )   // ignore unknown encodings
38343ad51ffSHerbert Dürr             continue;
38443ad51ffSHerbert Dürr 
38543ad51ffSHerbert Dürr         int nTmpOffset = GetUInt( p+4 );
38643ad51ffSHerbert Dürr         int nTmpFormat = Getsal_uInt16( pCmap + nTmpOffset );
38743ad51ffSHerbert Dürr         if( nTmpFormat == 12 )                  // 32bit code -> glyph map format
38843ad51ffSHerbert Dürr             nValue += 3;
38943ad51ffSHerbert Dürr         else if( nTmpFormat != 4 )              // 16bit code -> glyph map format
39043ad51ffSHerbert Dürr             continue;                           // ignore other formats
39143ad51ffSHerbert Dürr 
39243ad51ffSHerbert Dürr         if( nBestVal < nValue )
39343ad51ffSHerbert Dürr         {
39443ad51ffSHerbert Dürr             nBestVal = nValue;
39543ad51ffSHerbert Dürr             nOffset = nTmpOffset;
39643ad51ffSHerbert Dürr             nFormat = nTmpFormat;
39743ad51ffSHerbert Dürr             eRecodeFrom = eTmpEncoding;
39843ad51ffSHerbert Dürr         }
39943ad51ffSHerbert Dürr     }
40043ad51ffSHerbert Dürr 
40143ad51ffSHerbert Dürr     // parse the best CMAP subtable
40243ad51ffSHerbert Dürr     int nRangeCount = 0;
40343ad51ffSHerbert Dürr     sal_UCS4* pCodePairs = NULL;
40443ad51ffSHerbert Dürr     int* pStartGlyphs = NULL;
40543ad51ffSHerbert Dürr 
40643ad51ffSHerbert Dürr     typedef std::vector<sal_uInt16> U16Vector;
40743ad51ffSHerbert Dürr     U16Vector aGlyphIdArray;
40843ad51ffSHerbert Dürr     aGlyphIdArray.reserve( 0x1000 );
40943ad51ffSHerbert Dürr     aGlyphIdArray.push_back( 0 );
41043ad51ffSHerbert Dürr 
41143ad51ffSHerbert Dürr     // format 4, the most common 16bit char mapping table
41243ad51ffSHerbert Dürr     if( (nFormat == 4) && ((nOffset+16) < nLength) )
41343ad51ffSHerbert Dürr     {
41443ad51ffSHerbert Dürr         int nSegCountX2 = Getsal_uInt16( pCmap + nOffset + 6 );
41543ad51ffSHerbert Dürr         nRangeCount = nSegCountX2/2 - 1;
41643ad51ffSHerbert Dürr         pCodePairs = new sal_UCS4[ nRangeCount * 2 ];
41743ad51ffSHerbert Dürr         pStartGlyphs = new int[ nRangeCount ];
41843ad51ffSHerbert Dürr         const unsigned char* pLimitBase = pCmap + nOffset + 14;
41943ad51ffSHerbert Dürr         const unsigned char* pBeginBase = pLimitBase + nSegCountX2 + 2;
42043ad51ffSHerbert Dürr         const unsigned char* pDeltaBase = pBeginBase + nSegCountX2;
42143ad51ffSHerbert Dürr         const unsigned char* pOffsetBase = pDeltaBase + nSegCountX2;
42243ad51ffSHerbert Dürr         sal_UCS4* pCP = pCodePairs;
42343ad51ffSHerbert Dürr         for( int i = 0; i < nRangeCount; ++i )
42443ad51ffSHerbert Dürr         {
42543ad51ffSHerbert Dürr             const sal_UCS4 cMinChar = Getsal_uInt16( pBeginBase + 2*i );
42643ad51ffSHerbert Dürr             const sal_UCS4 cMaxChar = Getsal_uInt16( pLimitBase + 2*i );
42743ad51ffSHerbert Dürr             const int nGlyphDelta  = GetSShort( pDeltaBase + 2*i );
42843ad51ffSHerbert Dürr             const int nRangeOffset = Getsal_uInt16( pOffsetBase + 2*i );
42943ad51ffSHerbert Dürr             if( cMinChar > cMaxChar )   // no sane font should trigger this
43043ad51ffSHerbert Dürr                 break;
43143ad51ffSHerbert Dürr             if( cMaxChar == 0xFFFF )
43243ad51ffSHerbert Dürr                 break;
43343ad51ffSHerbert Dürr             *(pCP++) = cMinChar;
43443ad51ffSHerbert Dürr             *(pCP++) = cMaxChar + 1;
43543ad51ffSHerbert Dürr             if( !nRangeOffset ) {
43643ad51ffSHerbert Dürr                 // glyphid can be calculated directly
43743ad51ffSHerbert Dürr                 pStartGlyphs[i] = (cMinChar + nGlyphDelta) & 0xFFFF;
43843ad51ffSHerbert Dürr             } else {
43943ad51ffSHerbert Dürr                 // update the glyphid-array with the glyphs in this range
44043ad51ffSHerbert Dürr                 pStartGlyphs[i] = -(int)aGlyphIdArray.size();
44143ad51ffSHerbert Dürr                 const unsigned char* pGlyphIdPtr = pOffsetBase + 2*i + nRangeOffset;
44243ad51ffSHerbert Dürr                 for( sal_UCS4 c = cMinChar; c <= cMaxChar; ++c, pGlyphIdPtr+=2 ) {
44343ad51ffSHerbert Dürr                     const int nGlyphIndex = Getsal_uInt16( pGlyphIdPtr ) + nGlyphDelta;
44443ad51ffSHerbert Dürr                     aGlyphIdArray.push_back( static_cast<sal_uInt16>(nGlyphIndex) );
44543ad51ffSHerbert Dürr                 }
44643ad51ffSHerbert Dürr             }
44743ad51ffSHerbert Dürr         }
44843ad51ffSHerbert Dürr         nRangeCount = (pCP - pCodePairs) / 2;
44943ad51ffSHerbert Dürr     }
45043ad51ffSHerbert Dürr     // format 12, the most common 32bit char mapping table
45143ad51ffSHerbert Dürr     else if( (nFormat == 12) && ((nOffset+16) < nLength) )
45243ad51ffSHerbert Dürr     {
45343ad51ffSHerbert Dürr         nRangeCount = GetUInt( pCmap + nOffset + 12 );
45443ad51ffSHerbert Dürr         pCodePairs = new sal_UCS4[ nRangeCount * 2 ];
45543ad51ffSHerbert Dürr         pStartGlyphs = new int[ nRangeCount ];
45643ad51ffSHerbert Dürr         const unsigned char* pGroup = pCmap + nOffset + 16;
45743ad51ffSHerbert Dürr         sal_UCS4* pCP = pCodePairs;
45843ad51ffSHerbert Dürr         for( int i = 0; i < nRangeCount; ++i )
45943ad51ffSHerbert Dürr         {
46043ad51ffSHerbert Dürr             sal_UCS4 cMinChar = GetUInt( pGroup + 0 );
46143ad51ffSHerbert Dürr             sal_UCS4 cMaxChar = GetUInt( pGroup + 4 );
46243ad51ffSHerbert Dürr             int nGlyphId = GetUInt( pGroup + 8 );
46343ad51ffSHerbert Dürr             pGroup += 12;
46443ad51ffSHerbert Dürr #if 0       // TODO: remove unicode baseplane clipping for UCS-4 support
46543ad51ffSHerbert Dürr             if( cMinChar > 0xFFFF )
46643ad51ffSHerbert Dürr                 continue;
46743ad51ffSHerbert Dürr             if( cMaxChar > 0xFFFF )
46843ad51ffSHerbert Dürr                 cMaxChar = 0xFFFF;
46943ad51ffSHerbert Dürr #else
47043ad51ffSHerbert Dürr             if( cMinChar > cMaxChar )   // no sane font should trigger this
47143ad51ffSHerbert Dürr                 break;
47243ad51ffSHerbert Dürr #endif
47343ad51ffSHerbert Dürr             *(pCP++) = cMinChar;
47443ad51ffSHerbert Dürr             *(pCP++) = cMaxChar + 1;
47543ad51ffSHerbert Dürr             pStartGlyphs[i] = nGlyphId;
47643ad51ffSHerbert Dürr         }
47743ad51ffSHerbert Dürr         nRangeCount = (pCP - pCodePairs) / 2;
47843ad51ffSHerbert Dürr     }
47943ad51ffSHerbert Dürr 
48043ad51ffSHerbert Dürr     // check if any subtable resulted in something usable
48143ad51ffSHerbert Dürr     if( nRangeCount <= 0 )
48243ad51ffSHerbert Dürr     {
48343ad51ffSHerbert Dürr         delete[] pCodePairs;
48443ad51ffSHerbert Dürr         delete[] pStartGlyphs;
48543ad51ffSHerbert Dürr 
48643ad51ffSHerbert Dürr         // even when no CMAP is available we know it for symbol fonts
48743ad51ffSHerbert Dürr         if( rResult.mbSymbolic )
48843ad51ffSHerbert Dürr         {
48943ad51ffSHerbert Dürr             pCodePairs = new sal_UCS4[4];
49043ad51ffSHerbert Dürr             pCodePairs[0] = 0x0020;    // aliased symbols
49143ad51ffSHerbert Dürr             pCodePairs[1] = 0x0100;
49243ad51ffSHerbert Dürr             pCodePairs[2] = 0xF020;    // original symbols
49343ad51ffSHerbert Dürr             pCodePairs[3] = 0xF100;
49443ad51ffSHerbert Dürr             rResult.mpRangeCodes = pCodePairs;
49543ad51ffSHerbert Dürr             rResult.mnRangeCount = 2;
49643ad51ffSHerbert Dürr             return true;
49743ad51ffSHerbert Dürr         }
49843ad51ffSHerbert Dürr 
49943ad51ffSHerbert Dürr         return false;
50043ad51ffSHerbert Dürr     }
50143ad51ffSHerbert Dürr 
50243ad51ffSHerbert Dürr     // recode the code ranges to their unicode encoded ranges if needed
50343ad51ffSHerbert Dürr     rtl_TextToUnicodeConverter aConverter = NULL;
50443ad51ffSHerbert Dürr     rtl_UnicodeToTextContext aCvtContext = NULL;
50543ad51ffSHerbert Dürr 
50643ad51ffSHerbert Dürr     rResult.mbRecoded = ( eRecodeFrom != RTL_TEXTENCODING_UNICODE );
50743ad51ffSHerbert Dürr     if( rResult.mbRecoded )
50843ad51ffSHerbert Dürr     {
50943ad51ffSHerbert Dürr         aConverter = rtl_createTextToUnicodeConverter( eRecodeFrom );
51043ad51ffSHerbert Dürr         aCvtContext = rtl_createTextToUnicodeContext( aConverter );
51143ad51ffSHerbert Dürr     }
51243ad51ffSHerbert Dürr 
51343ad51ffSHerbert Dürr     if( aConverter && aCvtContext )
51443ad51ffSHerbert Dürr     {
51543ad51ffSHerbert Dürr         // determine the set of supported unicodes from encoded ranges
51643ad51ffSHerbert Dürr         typedef std::set<sal_UCS4> Ucs4Set;
51743ad51ffSHerbert Dürr         Ucs4Set aSupportedUnicodes;
51843ad51ffSHerbert Dürr 
51943ad51ffSHerbert Dürr         static const int NINSIZE = 64;
52043ad51ffSHerbert Dürr         static const int NOUTSIZE = 64;
52143ad51ffSHerbert Dürr         sal_Char    cCharsInp[ NINSIZE ];
52243ad51ffSHerbert Dürr         sal_Unicode cCharsOut[ NOUTSIZE ];
52343ad51ffSHerbert Dürr         sal_UCS4* pCP = pCodePairs;
52443ad51ffSHerbert Dürr         for( int i = 0; i < nRangeCount; ++i )
52543ad51ffSHerbert Dürr         {
52643ad51ffSHerbert Dürr             sal_UCS4 cMin = *(pCP++);
52743ad51ffSHerbert Dürr             sal_UCS4 cEnd = *(pCP++);
52843ad51ffSHerbert Dürr             while( cMin < cEnd )
52943ad51ffSHerbert Dürr             {
53043ad51ffSHerbert Dürr                 int j = 0;
53143ad51ffSHerbert Dürr                 for(; (cMin < cEnd) && (j < NINSIZE); ++cMin )
53243ad51ffSHerbert Dürr                 {
53343ad51ffSHerbert Dürr                     if( cMin >= 0x0100 )
53443ad51ffSHerbert Dürr                         cCharsInp[ j++ ] = static_cast<sal_Char>(cMin >> 8);
53543ad51ffSHerbert Dürr                     if( (cMin >= 0x0100) || (cMin < 0x00A0)  )
53643ad51ffSHerbert Dürr                         cCharsInp[ j++ ] = static_cast<sal_Char>(cMin);
53743ad51ffSHerbert Dürr                 }
53843ad51ffSHerbert Dürr 
53943ad51ffSHerbert Dürr                 sal_uInt32 nCvtInfo;
54043ad51ffSHerbert Dürr                 sal_Size nSrcCvtBytes;
54143ad51ffSHerbert Dürr                 int nOutLen = rtl_convertTextToUnicode(
54243ad51ffSHerbert Dürr                     aConverter, aCvtContext,
54343ad51ffSHerbert Dürr                     cCharsInp, j, cCharsOut, NOUTSIZE,
54443ad51ffSHerbert Dürr                     RTL_TEXTTOUNICODE_FLAGS_INVALID_IGNORE
54543ad51ffSHerbert Dürr                     | RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_IGNORE,
54643ad51ffSHerbert Dürr                     &nCvtInfo, &nSrcCvtBytes );
54743ad51ffSHerbert Dürr 
54843ad51ffSHerbert Dürr                 for( j = 0; j < nOutLen; ++j )
54943ad51ffSHerbert Dürr                     aSupportedUnicodes.insert( cCharsOut[j] );
55043ad51ffSHerbert Dürr             }
55143ad51ffSHerbert Dürr         }
55243ad51ffSHerbert Dürr 
553*ff5c5583SDamjan Jovanovic         rtl_destroyTextToUnicodeContext( aConverter, aCvtContext );
55443ad51ffSHerbert Dürr         rtl_destroyTextToUnicodeConverter( aConverter );
55543ad51ffSHerbert Dürr 
55643ad51ffSHerbert Dürr         // convert the set of supported unicodes to ranges
55743ad51ffSHerbert Dürr         typedef std::vector<sal_UCS4> Ucs4Vector;
55843ad51ffSHerbert Dürr         Ucs4Vector aSupportedRanges;
55943ad51ffSHerbert Dürr 
56043ad51ffSHerbert Dürr         Ucs4Set::const_iterator itChar = aSupportedUnicodes.begin();
56143ad51ffSHerbert Dürr         for(; itChar != aSupportedUnicodes.end(); ++itChar )
56243ad51ffSHerbert Dürr         {
56343ad51ffSHerbert Dürr             if( aSupportedRanges.empty()
56443ad51ffSHerbert Dürr             || (aSupportedRanges.back() != *itChar) )
56543ad51ffSHerbert Dürr             {
56643ad51ffSHerbert Dürr                 // add new range beginning with current unicode
56743ad51ffSHerbert Dürr                 aSupportedRanges.push_back( *itChar );
56843ad51ffSHerbert Dürr                 aSupportedRanges.push_back( 0 );
56943ad51ffSHerbert Dürr             }
57043ad51ffSHerbert Dürr 
57143ad51ffSHerbert Dürr             // extend existing range to include current unicode
57243ad51ffSHerbert Dürr             aSupportedRanges.back() = *itChar + 1;
57343ad51ffSHerbert Dürr         }
57443ad51ffSHerbert Dürr 
57543ad51ffSHerbert Dürr         // glyph mapping for non-unicode fonts not implemented
57643ad51ffSHerbert Dürr         delete[] pStartGlyphs;
57743ad51ffSHerbert Dürr         pStartGlyphs = NULL;
57843ad51ffSHerbert Dürr         aGlyphIdArray.clear();
57943ad51ffSHerbert Dürr 
58043ad51ffSHerbert Dürr         // make a pCodePairs array using the vector from above
58143ad51ffSHerbert Dürr         delete[] pCodePairs;
58243ad51ffSHerbert Dürr         nRangeCount = aSupportedRanges.size() / 2;
58343ad51ffSHerbert Dürr         if( nRangeCount <= 0 )
58443ad51ffSHerbert Dürr             return false;
58543ad51ffSHerbert Dürr         pCodePairs = new sal_UCS4[ nRangeCount * 2 ];
58643ad51ffSHerbert Dürr         Ucs4Vector::const_iterator itInt = aSupportedRanges.begin();
58743ad51ffSHerbert Dürr         for( pCP = pCodePairs; itInt != aSupportedRanges.end(); ++itInt )
58843ad51ffSHerbert Dürr             *(pCP++) = *itInt;
58943ad51ffSHerbert Dürr     }
59043ad51ffSHerbert Dürr 
59143ad51ffSHerbert Dürr     // prepare the glyphid-array if needed
59243ad51ffSHerbert Dürr     // TODO: merge ranges if they are close enough?
59343ad51ffSHerbert Dürr     sal_uInt16* pGlyphIds = NULL;
59443ad51ffSHerbert Dürr     if( !aGlyphIdArray.empty())
59543ad51ffSHerbert Dürr     {
59643ad51ffSHerbert Dürr         pGlyphIds = new sal_uInt16[ aGlyphIdArray.size() ];
59743ad51ffSHerbert Dürr         sal_uInt16* pOut = pGlyphIds;
59843ad51ffSHerbert Dürr         U16Vector::const_iterator it = aGlyphIdArray.begin();
59943ad51ffSHerbert Dürr         while( it != aGlyphIdArray.end() )
60043ad51ffSHerbert Dürr             *(pOut++) = *(it++);
60143ad51ffSHerbert Dürr     }
60243ad51ffSHerbert Dürr 
60343ad51ffSHerbert Dürr     // update the result struct
60443ad51ffSHerbert Dürr     rResult.mpRangeCodes = pCodePairs;
60543ad51ffSHerbert Dürr     rResult.mpStartGlyphs = pStartGlyphs;
60643ad51ffSHerbert Dürr     rResult.mnRangeCount = nRangeCount;
60743ad51ffSHerbert Dürr     rResult.mpGlyphIds = pGlyphIds;
60843ad51ffSHerbert Dürr     return true;
60943ad51ffSHerbert Dürr }
61043ad51ffSHerbert Dürr 
61143ad51ffSHerbert Dürr // =======================================================================
61243ad51ffSHerbert Dürr 
FontCharMap()61343ad51ffSHerbert Dürr FontCharMap::FontCharMap()
61443ad51ffSHerbert Dürr :   mpImpl( ImplFontCharMap::GetDefaultMap() )
61543ad51ffSHerbert Dürr {}
61643ad51ffSHerbert Dürr 
61743ad51ffSHerbert Dürr // -----------------------------------------------------------------------
61843ad51ffSHerbert Dürr 
~FontCharMap()61943ad51ffSHerbert Dürr FontCharMap::~FontCharMap()
62043ad51ffSHerbert Dürr {
62143ad51ffSHerbert Dürr 	mpImpl->DeReference();
62243ad51ffSHerbert Dürr 	mpImpl = NULL;
62343ad51ffSHerbert Dürr }
62443ad51ffSHerbert Dürr 
62543ad51ffSHerbert Dürr // -----------------------------------------------------------------------
62643ad51ffSHerbert Dürr 
GetCharCount() const62743ad51ffSHerbert Dürr int FontCharMap::GetCharCount() const
62843ad51ffSHerbert Dürr {
62943ad51ffSHerbert Dürr 	return mpImpl->GetCharCount();
63043ad51ffSHerbert Dürr }
63143ad51ffSHerbert Dürr 
63243ad51ffSHerbert Dürr // -----------------------------------------------------------------------
63343ad51ffSHerbert Dürr 
CountCharsInRange(sal_UCS4 cMin,sal_UCS4 cMax) const63443ad51ffSHerbert Dürr int FontCharMap::CountCharsInRange( sal_UCS4 cMin, sal_UCS4 cMax ) const
63543ad51ffSHerbert Dürr {
63643ad51ffSHerbert Dürr 	return mpImpl->CountCharsInRange( cMin, cMax );
63743ad51ffSHerbert Dürr }
63843ad51ffSHerbert Dürr 
63943ad51ffSHerbert Dürr // -----------------------------------------------------------------------
64043ad51ffSHerbert Dürr 
Reset(const ImplFontCharMap * pNewMap)64143ad51ffSHerbert Dürr void FontCharMap::Reset( const ImplFontCharMap* pNewMap )
64243ad51ffSHerbert Dürr {
64343ad51ffSHerbert Dürr 	if( pNewMap == NULL )
64443ad51ffSHerbert Dürr 	{
64543ad51ffSHerbert Dürr 		mpImpl->DeReference();
64643ad51ffSHerbert Dürr 		mpImpl = ImplFontCharMap::GetDefaultMap();
64743ad51ffSHerbert Dürr 	}
64843ad51ffSHerbert Dürr 	else if( pNewMap != mpImpl )
64943ad51ffSHerbert Dürr 	{
65043ad51ffSHerbert Dürr 		mpImpl->DeReference();
65143ad51ffSHerbert Dürr 		mpImpl = pNewMap;
65243ad51ffSHerbert Dürr 		mpImpl->AddReference();
65343ad51ffSHerbert Dürr 	}
65443ad51ffSHerbert Dürr }
65543ad51ffSHerbert Dürr 
65643ad51ffSHerbert Dürr // -----------------------------------------------------------------------
65743ad51ffSHerbert Dürr 
IsDefaultMap() const65843ad51ffSHerbert Dürr bool FontCharMap::IsDefaultMap() const
65943ad51ffSHerbert Dürr {
66043ad51ffSHerbert Dürr 	return mpImpl->IsDefaultMap();
66143ad51ffSHerbert Dürr }
66243ad51ffSHerbert Dürr 
66343ad51ffSHerbert Dürr // -----------------------------------------------------------------------
66443ad51ffSHerbert Dürr 
HasChar(sal_UCS4 cChar) const66543ad51ffSHerbert Dürr bool FontCharMap::HasChar( sal_UCS4 cChar ) const
66643ad51ffSHerbert Dürr {
66743ad51ffSHerbert Dürr 	return mpImpl->HasChar( cChar );
66843ad51ffSHerbert Dürr }
66943ad51ffSHerbert Dürr 
67043ad51ffSHerbert Dürr // -----------------------------------------------------------------------
67143ad51ffSHerbert Dürr 
GetFirstChar() const67243ad51ffSHerbert Dürr sal_UCS4 FontCharMap::GetFirstChar() const
67343ad51ffSHerbert Dürr {
67443ad51ffSHerbert Dürr 	return mpImpl->GetFirstChar();
67543ad51ffSHerbert Dürr }
67643ad51ffSHerbert Dürr 
67743ad51ffSHerbert Dürr // -----------------------------------------------------------------------
67843ad51ffSHerbert Dürr 
GetLastChar() const67943ad51ffSHerbert Dürr sal_UCS4 FontCharMap::GetLastChar() const
68043ad51ffSHerbert Dürr {
68143ad51ffSHerbert Dürr 	return mpImpl->GetLastChar();
68243ad51ffSHerbert Dürr }
68343ad51ffSHerbert Dürr 
68443ad51ffSHerbert Dürr // -----------------------------------------------------------------------
68543ad51ffSHerbert Dürr 
GetNextChar(sal_UCS4 cChar) const68643ad51ffSHerbert Dürr sal_UCS4 FontCharMap::GetNextChar( sal_UCS4 cChar ) const
68743ad51ffSHerbert Dürr {
68843ad51ffSHerbert Dürr 	return mpImpl->GetNextChar( cChar );
68943ad51ffSHerbert Dürr }
69043ad51ffSHerbert Dürr 
69143ad51ffSHerbert Dürr // -----------------------------------------------------------------------
69243ad51ffSHerbert Dürr 
GetPrevChar(sal_UCS4 cChar) const69343ad51ffSHerbert Dürr sal_UCS4 FontCharMap::GetPrevChar( sal_UCS4 cChar ) const
69443ad51ffSHerbert Dürr {
69543ad51ffSHerbert Dürr 	return mpImpl->GetPrevChar( cChar );
69643ad51ffSHerbert Dürr }
69743ad51ffSHerbert Dürr 
69843ad51ffSHerbert Dürr // -----------------------------------------------------------------------
69943ad51ffSHerbert Dürr 
GetIndexFromChar(sal_UCS4 cChar) const70043ad51ffSHerbert Dürr int FontCharMap::GetIndexFromChar( sal_UCS4 cChar ) const
70143ad51ffSHerbert Dürr {
70243ad51ffSHerbert Dürr 	return mpImpl->GetIndexFromChar( cChar );
70343ad51ffSHerbert Dürr }
70443ad51ffSHerbert Dürr 
70543ad51ffSHerbert Dürr // -----------------------------------------------------------------------
70643ad51ffSHerbert Dürr 
GetCharFromIndex(int nIndex) const70743ad51ffSHerbert Dürr sal_UCS4 FontCharMap::GetCharFromIndex( int nIndex ) const
70843ad51ffSHerbert Dürr {
70943ad51ffSHerbert Dürr 	return mpImpl->GetCharFromIndex( nIndex );
71043ad51ffSHerbert Dürr }
71143ad51ffSHerbert Dürr 
71243ad51ffSHerbert Dürr // =======================================================================
71343ad51ffSHerbert Dürr 
71443ad51ffSHerbert Dürr // on some systems we have to get the font attributes from the name table
71543ad51ffSHerbert Dürr // since neither head's macStyle nor OS/2's panose are easily available
71643ad51ffSHerbert Dürr // during font enumeration. macStyle bits would be not sufficient anyway
71743ad51ffSHerbert Dürr // and SFNT fonts on Mac usually do not contain an OS/2 table.
UpdateAttributesFromPSName(const String & rPSName,ImplDevFontAttributes & rDFA)71843ad51ffSHerbert Dürr void UpdateAttributesFromPSName( const String& rPSName, ImplDevFontAttributes& rDFA )
71943ad51ffSHerbert Dürr {
72043ad51ffSHerbert Dürr 	ByteString aPSName( rPSName, RTL_TEXTENCODING_UTF8 );
72143ad51ffSHerbert Dürr 	aPSName.ToLowerAscii();
72243ad51ffSHerbert Dürr 
72343ad51ffSHerbert Dürr 	// TODO: use a multi-string ignore-case matcher once it becomes available
72443ad51ffSHerbert Dürr 	if( (aPSName.Search("regular") != STRING_NOTFOUND)
72543ad51ffSHerbert Dürr 	||  (aPSName.Search("normal") != STRING_NOTFOUND)
72643ad51ffSHerbert Dürr 	||  (aPSName.Search("roman") != STRING_NOTFOUND)
72743ad51ffSHerbert Dürr 	||  (aPSName.Search("medium") != STRING_NOTFOUND)
72843ad51ffSHerbert Dürr 	||  (aPSName.Search("plain") != STRING_NOTFOUND)
72943ad51ffSHerbert Dürr 	||  (aPSName.Search("standard") != STRING_NOTFOUND)
73043ad51ffSHerbert Dürr 	||  (aPSName.Search("std") != STRING_NOTFOUND) )
73143ad51ffSHerbert Dürr 	{
73243ad51ffSHerbert Dürr 		rDFA.meWidthType = WIDTH_NORMAL;
73343ad51ffSHerbert Dürr 		rDFA.meWeight    = WEIGHT_NORMAL;
73443ad51ffSHerbert Dürr 		rDFA.meItalic    = ITALIC_NONE;
73543ad51ffSHerbert Dürr 	}
73643ad51ffSHerbert Dürr 
73743ad51ffSHerbert Dürr 	// heuristics for font weight
73843ad51ffSHerbert Dürr 	if (aPSName.Search("extrablack") != STRING_NOTFOUND)
73943ad51ffSHerbert Dürr 		rDFA.meWeight = WEIGHT_BLACK;
74043ad51ffSHerbert Dürr 	else if (aPSName.Search("black") != STRING_NOTFOUND)
74143ad51ffSHerbert Dürr 		rDFA.meWeight = WEIGHT_BLACK;
74243ad51ffSHerbert Dürr #if 1
74343ad51ffSHerbert Dürr 	else if (aPSName.Search("book") != STRING_NOTFOUND)
74443ad51ffSHerbert Dürr 		rDFA.meWeight = WEIGHT_NORMAL;
74543ad51ffSHerbert Dürr #endif
74643ad51ffSHerbert Dürr 	else if( (aPSName.Search("semibold") != STRING_NOTFOUND)
74743ad51ffSHerbert Dürr 	||       (aPSName.Search("smbd") != STRING_NOTFOUND))
74843ad51ffSHerbert Dürr 		rDFA.meWeight = WEIGHT_SEMIBOLD;
74943ad51ffSHerbert Dürr 	else if( aPSName.Search("ultrabold") != STRING_NOTFOUND)
75043ad51ffSHerbert Dürr 		rDFA.meWeight = WEIGHT_ULTRABOLD;
75143ad51ffSHerbert Dürr 	else if( aPSName.Search("extrabold") != STRING_NOTFOUND)
75243ad51ffSHerbert Dürr 		rDFA.meWeight = WEIGHT_BLACK;
75343ad51ffSHerbert Dürr 	else if( (aPSName.Search("bold") != STRING_NOTFOUND)
75443ad51ffSHerbert Dürr 	||       (aPSName.Search("-bd") != STRING_NOTFOUND))
75543ad51ffSHerbert Dürr 		rDFA.meWeight = WEIGHT_BOLD;
75643ad51ffSHerbert Dürr 	else if( aPSName.Search("extralight") != STRING_NOTFOUND)
75743ad51ffSHerbert Dürr 		rDFA.meWeight = WEIGHT_ULTRALIGHT;
75843ad51ffSHerbert Dürr 	else if( aPSName.Search("ultralight") != STRING_NOTFOUND)
75943ad51ffSHerbert Dürr 		rDFA.meWeight = WEIGHT_ULTRALIGHT;
76043ad51ffSHerbert Dürr 	else if( aPSName.Search("light") != STRING_NOTFOUND)
76143ad51ffSHerbert Dürr 		rDFA.meWeight = WEIGHT_LIGHT;
76243ad51ffSHerbert Dürr 	else if( aPSName.Search("thin") != STRING_NOTFOUND)
76343ad51ffSHerbert Dürr 		rDFA.meWeight = WEIGHT_THIN;
76443ad51ffSHerbert Dürr 	else if( aPSName.Search("-w3") != STRING_NOTFOUND)
76543ad51ffSHerbert Dürr 		rDFA.meWeight = WEIGHT_LIGHT;
76643ad51ffSHerbert Dürr 	else if( aPSName.Search("-w4") != STRING_NOTFOUND)
76743ad51ffSHerbert Dürr 		rDFA.meWeight = WEIGHT_SEMILIGHT;
76843ad51ffSHerbert Dürr 	else if( aPSName.Search("-w5") != STRING_NOTFOUND)
76943ad51ffSHerbert Dürr 		rDFA.meWeight = WEIGHT_NORMAL;
77043ad51ffSHerbert Dürr 	else if( aPSName.Search("-w6") != STRING_NOTFOUND)
77143ad51ffSHerbert Dürr 		rDFA.meWeight = WEIGHT_SEMIBOLD;
77243ad51ffSHerbert Dürr 	else if( aPSName.Search("-w7") != STRING_NOTFOUND)
77343ad51ffSHerbert Dürr 		rDFA.meWeight = WEIGHT_BOLD;
77443ad51ffSHerbert Dürr 	else if( aPSName.Search("-w8") != STRING_NOTFOUND)
77543ad51ffSHerbert Dürr 		rDFA.meWeight = WEIGHT_ULTRABOLD;
77643ad51ffSHerbert Dürr 	else if( aPSName.Search("-w9") != STRING_NOTFOUND)
77743ad51ffSHerbert Dürr 		rDFA.meWeight = WEIGHT_BLACK;
77843ad51ffSHerbert Dürr 
77943ad51ffSHerbert Dürr     // heuristics for font slant
78043ad51ffSHerbert Dürr     if( (aPSName.Search("italic") != STRING_NOTFOUND)
78143ad51ffSHerbert Dürr     ||  (aPSName.Search(" ital") != STRING_NOTFOUND)
78243ad51ffSHerbert Dürr     ||  (aPSName.Search("cursive") != STRING_NOTFOUND)
78343ad51ffSHerbert Dürr     ||  (aPSName.Search("-it") != STRING_NOTFOUND)
78443ad51ffSHerbert Dürr     ||  (aPSName.Search("lightit") != STRING_NOTFOUND)
78543ad51ffSHerbert Dürr     ||  (aPSName.Search("mediumit") != STRING_NOTFOUND)
78643ad51ffSHerbert Dürr     ||  (aPSName.Search("boldit") != STRING_NOTFOUND)
78743ad51ffSHerbert Dürr     ||  (aPSName.Search("cnit") != STRING_NOTFOUND)
78843ad51ffSHerbert Dürr     ||  (aPSName.Search("bdcn") != STRING_NOTFOUND)
78943ad51ffSHerbert Dürr     ||  (aPSName.Search("bdit") != STRING_NOTFOUND)
79043ad51ffSHerbert Dürr     ||  (aPSName.Search("condit") != STRING_NOTFOUND)
79143ad51ffSHerbert Dürr     ||  (aPSName.Search("bookit") != STRING_NOTFOUND)
79243ad51ffSHerbert Dürr     ||  (aPSName.Search("blackit") != STRING_NOTFOUND) )
79343ad51ffSHerbert Dürr 	    rDFA.meItalic = ITALIC_NORMAL;
79443ad51ffSHerbert Dürr     if( (aPSName.Search("oblique") != STRING_NOTFOUND)
79543ad51ffSHerbert Dürr     ||  (aPSName.Search("inclined") != STRING_NOTFOUND)
79643ad51ffSHerbert Dürr     ||  (aPSName.Search("slanted") != STRING_NOTFOUND) )
79743ad51ffSHerbert Dürr 	    rDFA.meItalic = ITALIC_OBLIQUE;
79843ad51ffSHerbert Dürr 
79943ad51ffSHerbert Dürr     // heuristics for font width
80043ad51ffSHerbert Dürr     if( (aPSName.Search("condensed") != STRING_NOTFOUND)
80143ad51ffSHerbert Dürr     ||  (aPSName.Search("-cond") != STRING_NOTFOUND)
80243ad51ffSHerbert Dürr     ||  (aPSName.Search("boldcond") != STRING_NOTFOUND)
80343ad51ffSHerbert Dürr     ||  (aPSName.Search("boldcn") != STRING_NOTFOUND)
80443ad51ffSHerbert Dürr     ||  (aPSName.Search("cnit") != STRING_NOTFOUND) )
80543ad51ffSHerbert Dürr 	    rDFA.meWidthType = WIDTH_CONDENSED;
80643ad51ffSHerbert Dürr     else if (aPSName.Search("narrow") != STRING_NOTFOUND)
80743ad51ffSHerbert Dürr 	    rDFA.meWidthType = WIDTH_SEMI_CONDENSED;
80843ad51ffSHerbert Dürr     else if (aPSName.Search("expanded") != STRING_NOTFOUND)
80943ad51ffSHerbert Dürr 	    rDFA.meWidthType = WIDTH_EXPANDED;
81043ad51ffSHerbert Dürr     else if (aPSName.Search("wide") != STRING_NOTFOUND)
81143ad51ffSHerbert Dürr 	    rDFA.meWidthType = WIDTH_EXPANDED;
81243ad51ffSHerbert Dürr 
81343ad51ffSHerbert Dürr     // heuristics for font pitch
81443ad51ffSHerbert Dürr     if( (aPSName.Search("mono") != STRING_NOTFOUND)
81543ad51ffSHerbert Dürr     ||  (aPSName.Search("courier") != STRING_NOTFOUND)
81643ad51ffSHerbert Dürr     ||  (aPSName.Search("monaco") != STRING_NOTFOUND)
81743ad51ffSHerbert Dürr     ||  (aPSName.Search("typewriter") != STRING_NOTFOUND) )
81843ad51ffSHerbert Dürr 	    rDFA.mePitch = PITCH_FIXED;
81943ad51ffSHerbert Dürr 
82043ad51ffSHerbert Dürr     // heuristics for font family type
82143ad51ffSHerbert Dürr     if( (aPSName.Search("script") != STRING_NOTFOUND)
82243ad51ffSHerbert Dürr     ||  (aPSName.Search("chancery") != STRING_NOTFOUND)
82343ad51ffSHerbert Dürr     ||  (aPSName.Search("zapfino") != STRING_NOTFOUND))
82443ad51ffSHerbert Dürr 	    rDFA.meFamily = FAMILY_SCRIPT;
82543ad51ffSHerbert Dürr     else if( (aPSName.Search("comic") != STRING_NOTFOUND)
82643ad51ffSHerbert Dürr     ||  (aPSName.Search("outline") != STRING_NOTFOUND)
82743ad51ffSHerbert Dürr     ||  (aPSName.Search("pinpoint") != STRING_NOTFOUND) )
82843ad51ffSHerbert Dürr 	    rDFA.meFamily = FAMILY_DECORATIVE;
82943ad51ffSHerbert Dürr     else if( (aPSName.Search("sans") != STRING_NOTFOUND)
83043ad51ffSHerbert Dürr     ||  (aPSName.Search("arial") != STRING_NOTFOUND) )
83143ad51ffSHerbert Dürr 	    rDFA.meFamily = FAMILY_SWISS;
83243ad51ffSHerbert Dürr     else if( (aPSName.Search("roman") != STRING_NOTFOUND)
83343ad51ffSHerbert Dürr     ||  (aPSName.Search("times") != STRING_NOTFOUND) )
83443ad51ffSHerbert Dürr 	    rDFA.meFamily = FAMILY_ROMAN;
83543ad51ffSHerbert Dürr 
83643ad51ffSHerbert Dürr     // heuristics for codepoint semantic
83743ad51ffSHerbert Dürr     if( (aPSName.Search("symbol") != STRING_NOTFOUND)
83843ad51ffSHerbert Dürr     ||  (aPSName.Search("dings") != STRING_NOTFOUND)
83943ad51ffSHerbert Dürr     ||  (aPSName.Search("dingbats") != STRING_NOTFOUND)
84043ad51ffSHerbert Dürr     ||  (aPSName.Search("braille") != STRING_NOTFOUND)
84143ad51ffSHerbert Dürr     ||  (aPSName.Search("ornaments") != STRING_NOTFOUND)
84243ad51ffSHerbert Dürr     ||  (aPSName.Search("embellishments") != STRING_NOTFOUND) )
84343ad51ffSHerbert Dürr         rDFA.mbSymbolFlag  = true;
84443ad51ffSHerbert Dürr 
84543ad51ffSHerbert Dürr    // #i100020# special heuristic for names with single-char styles
84643ad51ffSHerbert Dürr    // NOTE: we are checking name that hasn't been lower-cased
84743ad51ffSHerbert Dürr    if( rPSName.Len() > 3 )
84843ad51ffSHerbert Dürr    {
84943ad51ffSHerbert Dürr         int i = rPSName.Len();
85043ad51ffSHerbert Dürr         sal_Unicode c = rPSName.GetChar( --i );
85143ad51ffSHerbert Dürr         if( c == 'C' ) { // "capitals"
85243ad51ffSHerbert Dürr             rDFA.meFamily = FAMILY_DECORATIVE;
85343ad51ffSHerbert Dürr             c = rPSName.GetChar( --i );
85443ad51ffSHerbert Dürr         }
85543ad51ffSHerbert Dürr         if( c == 'O' ) { // CFF-based OpenType
85643ad51ffSHerbert Dürr             c = rPSName.GetChar( --i );
85743ad51ffSHerbert Dürr         }
85843ad51ffSHerbert Dürr         if( c == 'I' ) { // "italic"
85943ad51ffSHerbert Dürr             rDFA.meItalic = ITALIC_NORMAL;
86043ad51ffSHerbert Dürr             c = rPSName.GetChar( --i );
86143ad51ffSHerbert Dürr         }
86243ad51ffSHerbert Dürr         if( c == 'B' )   // "bold"
86343ad51ffSHerbert Dürr             rDFA.meWeight = WEIGHT_BOLD;
86443ad51ffSHerbert Dürr         if( c == 'C' )   // "capitals"
86543ad51ffSHerbert Dürr             rDFA.meFamily = FAMILY_DECORATIVE;
86643ad51ffSHerbert Dürr         // TODO: check that all single-char styles have been resolved?
86743ad51ffSHerbert Dürr     }
86843ad51ffSHerbert Dürr }
86943ad51ffSHerbert Dürr 
87043ad51ffSHerbert Dürr // =======================================================================
87143ad51ffSHerbert Dürr 
872