xref: /aoo41x/main/vcl/source/gdi/impfont.cxx (revision 43ad51ff)
1*43ad51ffSHerbert Dürr /**************************************************************
2*43ad51ffSHerbert Dürr  *
3*43ad51ffSHerbert Dürr  * Licensed to the Apache Software Foundation (ASF) under one
4*43ad51ffSHerbert Dürr  * or more contributor license agreements.  See the NOTICE file
5*43ad51ffSHerbert Dürr  * distributed with this work for additional information
6*43ad51ffSHerbert Dürr  * regarding copyright ownership.  The ASF licenses this file
7*43ad51ffSHerbert Dürr  * to you under the Apache License, Version 2.0 (the
8*43ad51ffSHerbert Dürr  * "License"); you may not use this file except in compliance
9*43ad51ffSHerbert Dürr  * with the License.  You may obtain a copy of the License at
10*43ad51ffSHerbert Dürr  *
11*43ad51ffSHerbert Dürr  *   http://www.apache.org/licenses/LICENSE-2.0
12*43ad51ffSHerbert Dürr  *
13*43ad51ffSHerbert Dürr  * Unless required by applicable law or agreed to in writing,
14*43ad51ffSHerbert Dürr  * software distributed under the License is distributed on an
15*43ad51ffSHerbert Dürr  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*43ad51ffSHerbert Dürr  * KIND, either express or implied.  See the License for the
17*43ad51ffSHerbert Dürr  * specific language governing permissions and limitations
18*43ad51ffSHerbert Dürr  * under the License.
19*43ad51ffSHerbert Dürr  *
20*43ad51ffSHerbert Dürr  *************************************************************/
21*43ad51ffSHerbert Dürr 
22*43ad51ffSHerbert Dürr // MARKER(update_precomp.py): autogen include statement, do not remove
23*43ad51ffSHerbert Dürr #include "precompiled_vcl.hxx"
24*43ad51ffSHerbert Dürr 
25*43ad51ffSHerbert Dürr #include <vcl/metric.hxx>
26*43ad51ffSHerbert Dürr #include <outfont.hxx>
27*43ad51ffSHerbert Dürr #include <impfont.hxx>
28*43ad51ffSHerbert Dürr 
29*43ad51ffSHerbert Dürr #include <vector>
30*43ad51ffSHerbert Dürr #include <set>
31*43ad51ffSHerbert Dürr 
32*43ad51ffSHerbert Dürr // =======================================================================
33*43ad51ffSHerbert Dürr 
34*43ad51ffSHerbert Dürr CmapResult::CmapResult( bool bSymbolic,
35*43ad51ffSHerbert Dürr 	const sal_UCS4* pRangeCodes, int nRangeCount,
36*43ad51ffSHerbert Dürr 	const int* pStartGlyphs, const sal_uInt16* pExtraGlyphIds )
37*43ad51ffSHerbert Dürr :	mpRangeCodes( pRangeCodes)
38*43ad51ffSHerbert Dürr ,	mpStartGlyphs( pStartGlyphs)
39*43ad51ffSHerbert Dürr ,	mpGlyphIds( pExtraGlyphIds)
40*43ad51ffSHerbert Dürr ,	mnRangeCount( nRangeCount)
41*43ad51ffSHerbert Dürr ,	mbSymbolic( bSymbolic)
42*43ad51ffSHerbert Dürr ,	mbRecoded( false)
43*43ad51ffSHerbert Dürr {}
44*43ad51ffSHerbert Dürr 
45*43ad51ffSHerbert Dürr // =======================================================================
46*43ad51ffSHerbert Dürr 
47*43ad51ffSHerbert Dürr ImplFontCharMap::ImplFontCharMap( const CmapResult& rCR )
48*43ad51ffSHerbert Dürr :	mpRangeCodes( rCR.mpRangeCodes )
49*43ad51ffSHerbert Dürr ,	mpStartGlyphs( rCR.mpStartGlyphs )
50*43ad51ffSHerbert Dürr ,	mpGlyphIds( rCR.mpGlyphIds )
51*43ad51ffSHerbert Dürr ,	mnRangeCount( rCR.mnRangeCount )
52*43ad51ffSHerbert Dürr ,	mnCharCount( 0 )
53*43ad51ffSHerbert Dürr ,	mnRefCount( 1 )
54*43ad51ffSHerbert Dürr {
55*43ad51ffSHerbert Dürr 	const sal_UCS4* pRangePtr = mpRangeCodes;
56*43ad51ffSHerbert Dürr 	for( int i = mnRangeCount; --i >= 0; pRangePtr += 2 )
57*43ad51ffSHerbert Dürr 	{
58*43ad51ffSHerbert Dürr 		sal_UCS4 cFirst = pRangePtr[0];
59*43ad51ffSHerbert Dürr 		sal_UCS4 cLast  = pRangePtr[1];
60*43ad51ffSHerbert Dürr 		mnCharCount += cLast - cFirst;
61*43ad51ffSHerbert Dürr 	}
62*43ad51ffSHerbert Dürr }
63*43ad51ffSHerbert Dürr 
64*43ad51ffSHerbert Dürr static ImplFontCharMap* pDefaultImplFontCharMap = NULL;
65*43ad51ffSHerbert Dürr static const sal_UCS4 aDefaultUnicodeRanges[] = {0x0020,0xD800, 0xE000,0xFFF0};
66*43ad51ffSHerbert Dürr static const sal_UCS4 aDefaultSymbolRanges[] = {0x0020,0x0100, 0xF020,0xF100};
67*43ad51ffSHerbert Dürr 
68*43ad51ffSHerbert Dürr // -----------------------------------------------------------------------
69*43ad51ffSHerbert Dürr 
70*43ad51ffSHerbert Dürr bool ImplFontCharMap::IsDefaultMap() const
71*43ad51ffSHerbert Dürr {
72*43ad51ffSHerbert Dürr 	const bool bIsDefault = (mpRangeCodes == aDefaultUnicodeRanges) || (mpRangeCodes == aDefaultSymbolRanges);
73*43ad51ffSHerbert Dürr 	return bIsDefault;
74*43ad51ffSHerbert Dürr }
75*43ad51ffSHerbert Dürr 
76*43ad51ffSHerbert Dürr // -----------------------------------------------------------------------
77*43ad51ffSHerbert Dürr 
78*43ad51ffSHerbert Dürr ImplFontCharMap::~ImplFontCharMap()
79*43ad51ffSHerbert Dürr {
80*43ad51ffSHerbert Dürr 	if( IsDefaultMap() )
81*43ad51ffSHerbert Dürr 		return;
82*43ad51ffSHerbert Dürr 	delete[] mpRangeCodes;
83*43ad51ffSHerbert Dürr 	delete[] mpStartGlyphs;
84*43ad51ffSHerbert Dürr 	delete[] mpGlyphIds;
85*43ad51ffSHerbert Dürr }
86*43ad51ffSHerbert Dürr 
87*43ad51ffSHerbert Dürr // -----------------------------------------------------------------------
88*43ad51ffSHerbert Dürr 
89*43ad51ffSHerbert Dürr ImplFontCharMap* ImplFontCharMap::GetDefaultMap( bool bSymbols)
90*43ad51ffSHerbert Dürr {
91*43ad51ffSHerbert Dürr 	if( pDefaultImplFontCharMap )
92*43ad51ffSHerbert Dürr 		pDefaultImplFontCharMap->AddReference();
93*43ad51ffSHerbert Dürr 	else
94*43ad51ffSHerbert Dürr 	{
95*43ad51ffSHerbert Dürr 		const sal_UCS4* pRangeCodes = aDefaultUnicodeRanges;
96*43ad51ffSHerbert Dürr 		int nCodesCount = sizeof(aDefaultUnicodeRanges) / sizeof(*pRangeCodes);
97*43ad51ffSHerbert Dürr 		if( bSymbols )
98*43ad51ffSHerbert Dürr 		{
99*43ad51ffSHerbert Dürr 			pRangeCodes	= aDefaultSymbolRanges;
100*43ad51ffSHerbert Dürr 			nCodesCount	= sizeof(aDefaultSymbolRanges) / sizeof(*pRangeCodes);
101*43ad51ffSHerbert Dürr 		}
102*43ad51ffSHerbert Dürr 
103*43ad51ffSHerbert Dürr 		CmapResult aDefaultCR( bSymbols, pRangeCodes, nCodesCount/2 );
104*43ad51ffSHerbert Dürr 		pDefaultImplFontCharMap = new ImplFontCharMap( aDefaultCR );
105*43ad51ffSHerbert Dürr 	}
106*43ad51ffSHerbert Dürr 
107*43ad51ffSHerbert Dürr 	return pDefaultImplFontCharMap;
108*43ad51ffSHerbert Dürr }
109*43ad51ffSHerbert Dürr 
110*43ad51ffSHerbert Dürr // -----------------------------------------------------------------------
111*43ad51ffSHerbert Dürr 
112*43ad51ffSHerbert Dürr void ImplFontCharMap::AddReference( void) const
113*43ad51ffSHerbert Dürr {
114*43ad51ffSHerbert Dürr 	++mnRefCount;
115*43ad51ffSHerbert Dürr }
116*43ad51ffSHerbert Dürr 
117*43ad51ffSHerbert Dürr // -----------------------------------------------------------------------
118*43ad51ffSHerbert Dürr 
119*43ad51ffSHerbert Dürr void ImplFontCharMap::DeReference( void) const
120*43ad51ffSHerbert Dürr {
121*43ad51ffSHerbert Dürr 	if( --mnRefCount <= 0 )
122*43ad51ffSHerbert Dürr 		if( this != pDefaultImplFontCharMap )
123*43ad51ffSHerbert Dürr 			delete this;
124*43ad51ffSHerbert Dürr }
125*43ad51ffSHerbert Dürr 
126*43ad51ffSHerbert Dürr // -----------------------------------------------------------------------
127*43ad51ffSHerbert Dürr 
128*43ad51ffSHerbert Dürr int ImplFontCharMap::GetCharCount() const
129*43ad51ffSHerbert Dürr {
130*43ad51ffSHerbert Dürr 	return mnCharCount;
131*43ad51ffSHerbert Dürr }
132*43ad51ffSHerbert Dürr 
133*43ad51ffSHerbert Dürr // -----------------------------------------------------------------------
134*43ad51ffSHerbert Dürr 
135*43ad51ffSHerbert Dürr int ImplFontCharMap::ImplFindRangeIndex( sal_UCS4 cChar ) const
136*43ad51ffSHerbert Dürr {
137*43ad51ffSHerbert Dürr 	int nLower = 0;
138*43ad51ffSHerbert Dürr 	int nMid   = mnRangeCount;
139*43ad51ffSHerbert Dürr 	int nUpper = 2 * mnRangeCount - 1;
140*43ad51ffSHerbert Dürr 	while( nLower < nUpper )
141*43ad51ffSHerbert Dürr 	{
142*43ad51ffSHerbert Dürr 		if( cChar >= mpRangeCodes[ nMid ] )
143*43ad51ffSHerbert Dürr 			nLower = nMid;
144*43ad51ffSHerbert Dürr 		else
145*43ad51ffSHerbert Dürr 			nUpper = nMid - 1;
146*43ad51ffSHerbert Dürr 		nMid = (nLower + nUpper + 1) / 2;
147*43ad51ffSHerbert Dürr 	}
148*43ad51ffSHerbert Dürr 
149*43ad51ffSHerbert Dürr 	return nMid;
150*43ad51ffSHerbert Dürr }
151*43ad51ffSHerbert Dürr 
152*43ad51ffSHerbert Dürr // -----------------------------------------------------------------------
153*43ad51ffSHerbert Dürr 
154*43ad51ffSHerbert Dürr bool ImplFontCharMap::HasChar( sal_UCS4 cChar ) const
155*43ad51ffSHerbert Dürr {
156*43ad51ffSHerbert Dürr 	bool bHasChar = false;
157*43ad51ffSHerbert Dürr 
158*43ad51ffSHerbert Dürr 	if( mpStartGlyphs  == NULL ) { // only the char-ranges are known
159*43ad51ffSHerbert Dürr 		const int nRange = ImplFindRangeIndex( cChar );
160*43ad51ffSHerbert Dürr 		if( nRange==0 && cChar<mpRangeCodes[0] )
161*43ad51ffSHerbert Dürr 			return false;
162*43ad51ffSHerbert Dürr 		bHasChar = ((nRange & 1) == 0); // inside a range
163*43ad51ffSHerbert Dürr 	} else { // glyph mapping is available
164*43ad51ffSHerbert Dürr 		const int nGlyphIndex = GetGlyphIndex( cChar );
165*43ad51ffSHerbert Dürr 		bHasChar = (nGlyphIndex != 0); // not the notdef-glyph
166*43ad51ffSHerbert Dürr 	}
167*43ad51ffSHerbert Dürr 
168*43ad51ffSHerbert Dürr 	return bHasChar;
169*43ad51ffSHerbert Dürr }
170*43ad51ffSHerbert Dürr 
171*43ad51ffSHerbert Dürr // -----------------------------------------------------------------------
172*43ad51ffSHerbert Dürr 
173*43ad51ffSHerbert Dürr int ImplFontCharMap::GetGlyphIndex( sal_UCS4 cChar ) const
174*43ad51ffSHerbert Dürr {
175*43ad51ffSHerbert Dürr 	// return -1 if the object doesn't know the glyph ids
176*43ad51ffSHerbert Dürr 	if( !mpStartGlyphs )
177*43ad51ffSHerbert Dürr 		return -1;
178*43ad51ffSHerbert Dürr 
179*43ad51ffSHerbert Dürr 	// return 0 if the unicode doesn't have a matching glyph
180*43ad51ffSHerbert Dürr 	int nRange = ImplFindRangeIndex( cChar );
181*43ad51ffSHerbert Dürr 	// check that we are inside any range
182*43ad51ffSHerbert Dürr 	if( (nRange == 0) && (cChar < mpRangeCodes[0]) ) {
183*43ad51ffSHerbert Dürr 		// symbol aliasing gives symbol fonts a second chance
184*43ad51ffSHerbert Dürr 		const bool bSymbolic = (mpRangeCodes[0]>=0xF000) & (mpRangeCodes[1]<=0xF0FF);
185*43ad51ffSHerbert Dürr 		if( !bSymbolic )
186*43ad51ffSHerbert Dürr 			return 0;
187*43ad51ffSHerbert Dürr 		// check for symbol aliasing (U+F0xx -> U+00xx)
188*43ad51ffSHerbert Dürr 		nRange = ImplFindRangeIndex( cChar | 0xF000 );
189*43ad51ffSHerbert Dürr 	}
190*43ad51ffSHerbert Dürr 	// check that we are inside a range
191*43ad51ffSHerbert Dürr 	if( (nRange & 1) != 0 )
192*43ad51ffSHerbert Dürr 		return 0;
193*43ad51ffSHerbert Dürr 
194*43ad51ffSHerbert Dürr 	// get glyph index directly or indirectly
195*43ad51ffSHerbert Dürr 	int nGlyphIndex = cChar - mpRangeCodes[ nRange ];
196*43ad51ffSHerbert Dürr 	const int nStartIndex = mpStartGlyphs[ nRange/2 ];
197*43ad51ffSHerbert Dürr 	if( nStartIndex >= 0 ) {
198*43ad51ffSHerbert Dürr 		// the glyph index can be calculated
199*43ad51ffSHerbert Dürr 		nGlyphIndex += nStartIndex;
200*43ad51ffSHerbert Dürr 	} else {
201*43ad51ffSHerbert Dürr 		// the glyphid array has the glyph index
202*43ad51ffSHerbert Dürr 		nGlyphIndex = mpGlyphIds[ nGlyphIndex - nStartIndex];
203*43ad51ffSHerbert Dürr 	}
204*43ad51ffSHerbert Dürr 
205*43ad51ffSHerbert Dürr 	return nGlyphIndex;
206*43ad51ffSHerbert Dürr }
207*43ad51ffSHerbert Dürr 
208*43ad51ffSHerbert Dürr // -----------------------------------------------------------------------
209*43ad51ffSHerbert Dürr 
210*43ad51ffSHerbert Dürr // returns the number of chars supported by the font, which
211*43ad51ffSHerbert Dürr // are inside the unicode range from cMin to cMax (inclusive)
212*43ad51ffSHerbert Dürr int ImplFontCharMap::CountCharsInRange( sal_UCS4 cMin, sal_UCS4 cMax ) const
213*43ad51ffSHerbert Dürr {
214*43ad51ffSHerbert Dürr 	int nCount = 0;
215*43ad51ffSHerbert Dürr 
216*43ad51ffSHerbert Dürr 	// find and adjust range and char count for cMin
217*43ad51ffSHerbert Dürr 	int nRangeMin = ImplFindRangeIndex( cMin );
218*43ad51ffSHerbert Dürr 	if( nRangeMin & 1 )
219*43ad51ffSHerbert Dürr 		++nRangeMin;
220*43ad51ffSHerbert Dürr 	else if( cMin > mpRangeCodes[ nRangeMin ] )
221*43ad51ffSHerbert Dürr 		nCount -= cMin - mpRangeCodes[ nRangeMin ];
222*43ad51ffSHerbert Dürr 
223*43ad51ffSHerbert Dürr 	// find and adjust range and char count for cMax
224*43ad51ffSHerbert Dürr 	int nRangeMax = ImplFindRangeIndex( cMax );
225*43ad51ffSHerbert Dürr 	if( nRangeMax & 1 )
226*43ad51ffSHerbert Dürr 		--nRangeMax;
227*43ad51ffSHerbert Dürr 	else
228*43ad51ffSHerbert Dürr 		nCount -= mpRangeCodes[ nRangeMax+1 ] - cMax - 1;
229*43ad51ffSHerbert Dürr 
230*43ad51ffSHerbert Dürr 	// count chars in complete ranges between cMin and cMax
231*43ad51ffSHerbert Dürr 	for( int i = nRangeMin; i <= nRangeMax; i+=2 )
232*43ad51ffSHerbert Dürr 		nCount += mpRangeCodes[i+1] - mpRangeCodes[i];
233*43ad51ffSHerbert Dürr 
234*43ad51ffSHerbert Dürr 	return nCount;
235*43ad51ffSHerbert Dürr }
236*43ad51ffSHerbert Dürr 
237*43ad51ffSHerbert Dürr // -----------------------------------------------------------------------
238*43ad51ffSHerbert Dürr 
239*43ad51ffSHerbert Dürr sal_UCS4 ImplFontCharMap::GetFirstChar() const
240*43ad51ffSHerbert Dürr {
241*43ad51ffSHerbert Dürr 	return mpRangeCodes[0];
242*43ad51ffSHerbert Dürr }
243*43ad51ffSHerbert Dürr 
244*43ad51ffSHerbert Dürr // -----------------------------------------------------------------------
245*43ad51ffSHerbert Dürr 
246*43ad51ffSHerbert Dürr sal_UCS4 ImplFontCharMap::GetLastChar() const
247*43ad51ffSHerbert Dürr {
248*43ad51ffSHerbert Dürr 	return (mpRangeCodes[ 2*mnRangeCount-1 ] - 1);
249*43ad51ffSHerbert Dürr }
250*43ad51ffSHerbert Dürr 
251*43ad51ffSHerbert Dürr // -----------------------------------------------------------------------
252*43ad51ffSHerbert Dürr 
253*43ad51ffSHerbert Dürr sal_UCS4 ImplFontCharMap::GetNextChar( sal_UCS4 cChar ) const
254*43ad51ffSHerbert Dürr {
255*43ad51ffSHerbert Dürr 	if( cChar < GetFirstChar() )
256*43ad51ffSHerbert Dürr 		return GetFirstChar();
257*43ad51ffSHerbert Dürr 	if( cChar >= GetLastChar() )
258*43ad51ffSHerbert Dürr 		return GetLastChar();
259*43ad51ffSHerbert Dürr 
260*43ad51ffSHerbert Dürr 	int nRange = ImplFindRangeIndex( cChar + 1 );
261*43ad51ffSHerbert Dürr 	if( nRange & 1 )                       // outside of range?
262*43ad51ffSHerbert Dürr 		return mpRangeCodes[ nRange + 1 ]; // => first in next range
263*43ad51ffSHerbert Dürr 	return (cChar + 1);
264*43ad51ffSHerbert Dürr }
265*43ad51ffSHerbert Dürr 
266*43ad51ffSHerbert Dürr // -----------------------------------------------------------------------
267*43ad51ffSHerbert Dürr 
268*43ad51ffSHerbert Dürr sal_UCS4 ImplFontCharMap::GetPrevChar( sal_UCS4 cChar ) const
269*43ad51ffSHerbert Dürr {
270*43ad51ffSHerbert Dürr 	if( cChar <= GetFirstChar() )
271*43ad51ffSHerbert Dürr 		return GetFirstChar();
272*43ad51ffSHerbert Dürr 	if( cChar > GetLastChar() )
273*43ad51ffSHerbert Dürr 		return GetLastChar();
274*43ad51ffSHerbert Dürr 
275*43ad51ffSHerbert Dürr 	int nRange = ImplFindRangeIndex( cChar - 1 );
276*43ad51ffSHerbert Dürr 	if( nRange & 1 )                            // outside a range?
277*43ad51ffSHerbert Dürr 		return (mpRangeCodes[ nRange ] - 1);    // => last in prev range
278*43ad51ffSHerbert Dürr 	return (cChar - 1);
279*43ad51ffSHerbert Dürr }
280*43ad51ffSHerbert Dürr 
281*43ad51ffSHerbert Dürr // -----------------------------------------------------------------------
282*43ad51ffSHerbert Dürr 
283*43ad51ffSHerbert Dürr int ImplFontCharMap::GetIndexFromChar( sal_UCS4 cChar ) const
284*43ad51ffSHerbert Dürr {
285*43ad51ffSHerbert Dürr 	// TODO: improve linear walk?
286*43ad51ffSHerbert Dürr 	int nCharIndex = 0;
287*43ad51ffSHerbert Dürr 	const sal_UCS4* pRange = &mpRangeCodes[0];
288*43ad51ffSHerbert Dürr 	for( int i = 0; i < mnRangeCount; ++i )
289*43ad51ffSHerbert Dürr 	{
290*43ad51ffSHerbert Dürr 		sal_UCS4 cFirst = *(pRange++);
291*43ad51ffSHerbert Dürr 		sal_UCS4 cLast  = *(pRange++);
292*43ad51ffSHerbert Dürr 		if( cChar >= cLast )
293*43ad51ffSHerbert Dürr 			nCharIndex += cLast - cFirst;
294*43ad51ffSHerbert Dürr 		else if( cChar >= cFirst )
295*43ad51ffSHerbert Dürr 			return nCharIndex + (cChar - cFirst);
296*43ad51ffSHerbert Dürr 		else
297*43ad51ffSHerbert Dürr 			break;
298*43ad51ffSHerbert Dürr 	}
299*43ad51ffSHerbert Dürr 
300*43ad51ffSHerbert Dürr 	return -1;
301*43ad51ffSHerbert Dürr }
302*43ad51ffSHerbert Dürr 
303*43ad51ffSHerbert Dürr // -----------------------------------------------------------------------
304*43ad51ffSHerbert Dürr 
305*43ad51ffSHerbert Dürr sal_UCS4 ImplFontCharMap::GetCharFromIndex( int nCharIndex ) const
306*43ad51ffSHerbert Dürr {
307*43ad51ffSHerbert Dürr 	// TODO: improve linear walk?
308*43ad51ffSHerbert Dürr 	const sal_UCS4* pRange = &mpRangeCodes[0];
309*43ad51ffSHerbert Dürr 	for( int i = 0; i < mnRangeCount; ++i )
310*43ad51ffSHerbert Dürr 	{
311*43ad51ffSHerbert Dürr 		sal_UCS4 cFirst = *(pRange++);
312*43ad51ffSHerbert Dürr 		sal_UCS4 cLast  = *(pRange++);
313*43ad51ffSHerbert Dürr 		nCharIndex -= cLast - cFirst;
314*43ad51ffSHerbert Dürr 		if( nCharIndex < 0 )
315*43ad51ffSHerbert Dürr 			return (cLast + nCharIndex);
316*43ad51ffSHerbert Dürr 	}
317*43ad51ffSHerbert Dürr 
318*43ad51ffSHerbert Dürr 	// we can only get here with an out-of-bounds charindex
319*43ad51ffSHerbert Dürr 	return mpRangeCodes[0];
320*43ad51ffSHerbert Dürr }
321*43ad51ffSHerbert Dürr 
322*43ad51ffSHerbert Dürr // =======================================================================
323*43ad51ffSHerbert Dürr 
324*43ad51ffSHerbert Dürr static unsigned GetUInt( const unsigned char* p ) { return((p[0]<<24)+(p[1]<<16)+(p[2]<<8)+p[3]);}
325*43ad51ffSHerbert Dürr static unsigned Getsal_uInt16( const unsigned char* p ){ return((p[0]<<8) | p[1]);}
326*43ad51ffSHerbert Dürr static int GetSShort( const unsigned char* p ){ return((static_cast<signed char>(p[0])<<8)|p[1]);}
327*43ad51ffSHerbert Dürr 
328*43ad51ffSHerbert Dürr // TODO: move CMAP parsing directly into the ImplFontCharMap class
329*43ad51ffSHerbert Dürr bool ParseCMAP( const unsigned char* pCmap, int nLength, CmapResult& rResult )
330*43ad51ffSHerbert Dürr {
331*43ad51ffSHerbert Dürr     rResult.mpRangeCodes = NULL;
332*43ad51ffSHerbert Dürr     rResult.mpStartGlyphs= NULL;
333*43ad51ffSHerbert Dürr     rResult.mpGlyphIds	 = NULL;
334*43ad51ffSHerbert Dürr     rResult.mnRangeCount = 0;
335*43ad51ffSHerbert Dürr     rResult.mbRecoded    = false;
336*43ad51ffSHerbert Dürr     rResult.mbSymbolic   = false;
337*43ad51ffSHerbert Dürr 
338*43ad51ffSHerbert Dürr     // parse the table header and check for validity
339*43ad51ffSHerbert Dürr     if( !pCmap || (nLength < 24) )
340*43ad51ffSHerbert Dürr         return false;
341*43ad51ffSHerbert Dürr 
342*43ad51ffSHerbert Dürr     if( Getsal_uInt16( pCmap ) != 0x0000 ) // simple check for CMAP corruption
343*43ad51ffSHerbert Dürr         return false;
344*43ad51ffSHerbert Dürr 
345*43ad51ffSHerbert Dürr     int nSubTables = Getsal_uInt16( pCmap + 2 );
346*43ad51ffSHerbert Dürr     if( (nSubTables <= 0) || (nLength < (24 + 8*nSubTables)) )
347*43ad51ffSHerbert Dürr         return false;
348*43ad51ffSHerbert Dürr 
349*43ad51ffSHerbert Dürr     // find the most interesting subtable in the CMAP
350*43ad51ffSHerbert Dürr     rtl_TextEncoding eRecodeFrom = RTL_TEXTENCODING_UNICODE;
351*43ad51ffSHerbert Dürr     int nOffset = 0;
352*43ad51ffSHerbert Dürr     int nFormat = -1;
353*43ad51ffSHerbert Dürr     int nBestVal = 0;
354*43ad51ffSHerbert Dürr     for( const unsigned char* p = pCmap + 4; --nSubTables >= 0; p += 8 )
355*43ad51ffSHerbert Dürr     {
356*43ad51ffSHerbert Dürr         int nPlatform = Getsal_uInt16( p );
357*43ad51ffSHerbert Dürr         int nEncoding = Getsal_uInt16( p+2 );
358*43ad51ffSHerbert Dürr         int nPlatformEncoding = (nPlatform << 8) + nEncoding;
359*43ad51ffSHerbert Dürr 
360*43ad51ffSHerbert Dürr         int nValue;
361*43ad51ffSHerbert Dürr         rtl_TextEncoding eTmpEncoding = RTL_TEXTENCODING_UNICODE;
362*43ad51ffSHerbert Dürr         switch( nPlatformEncoding )
363*43ad51ffSHerbert Dürr         {
364*43ad51ffSHerbert Dürr             case 0x000: nValue = 20; break;                             // Unicode 1.0
365*43ad51ffSHerbert Dürr             case 0x001: nValue = 21; break;                             // Unicode 1.1
366*43ad51ffSHerbert Dürr             case 0x002: nValue = 22; break;                             // iso10646_1993
367*43ad51ffSHerbert Dürr             case 0x003: nValue = 23; break;                             // UCS-2
368*43ad51ffSHerbert Dürr             case 0x004: nValue = 24; break;                             // UCS-4
369*43ad51ffSHerbert Dürr             case 0x100: nValue = 22; break;                             // Mac Unicode<2.0
370*43ad51ffSHerbert Dürr             case 0x103: nValue = 23; break;                             // Mac Unicode>2.0
371*43ad51ffSHerbert Dürr             case 0x300: nValue =  5; rResult.mbSymbolic = true; break;  // Win Symbol
372*43ad51ffSHerbert Dürr             case 0x301: nValue = 28; break;                             // Win UCS-2
373*43ad51ffSHerbert Dürr             case 0x30A: nValue = 29; break;                             // Win-UCS-4
374*43ad51ffSHerbert Dürr             case 0x302: nValue = 11; eTmpEncoding = RTL_TEXTENCODING_SHIFT_JIS; break;
375*43ad51ffSHerbert Dürr             case 0x303: nValue = 12; eTmpEncoding = RTL_TEXTENCODING_GB_18030; break;
376*43ad51ffSHerbert Dürr             case 0x304: nValue = 11; eTmpEncoding = RTL_TEXTENCODING_BIG5; break;
377*43ad51ffSHerbert Dürr             case 0x305: nValue = 11; eTmpEncoding = RTL_TEXTENCODING_MS_949; break;
378*43ad51ffSHerbert Dürr             case 0x306: nValue = 11; eTmpEncoding = RTL_TEXTENCODING_MS_1361; break;
379*43ad51ffSHerbert Dürr             default:    nValue = 0; break;
380*43ad51ffSHerbert Dürr         }
381*43ad51ffSHerbert Dürr 
382*43ad51ffSHerbert Dürr         if( nValue <= 0 )   // ignore unknown encodings
383*43ad51ffSHerbert Dürr             continue;
384*43ad51ffSHerbert Dürr 
385*43ad51ffSHerbert Dürr         int nTmpOffset = GetUInt( p+4 );
386*43ad51ffSHerbert Dürr         int nTmpFormat = Getsal_uInt16( pCmap + nTmpOffset );
387*43ad51ffSHerbert Dürr         if( nTmpFormat == 12 )                  // 32bit code -> glyph map format
388*43ad51ffSHerbert Dürr             nValue += 3;
389*43ad51ffSHerbert Dürr         else if( nTmpFormat != 4 )              // 16bit code -> glyph map format
390*43ad51ffSHerbert Dürr             continue;                           // ignore other formats
391*43ad51ffSHerbert Dürr 
392*43ad51ffSHerbert Dürr         if( nBestVal < nValue )
393*43ad51ffSHerbert Dürr         {
394*43ad51ffSHerbert Dürr             nBestVal = nValue;
395*43ad51ffSHerbert Dürr             nOffset = nTmpOffset;
396*43ad51ffSHerbert Dürr             nFormat = nTmpFormat;
397*43ad51ffSHerbert Dürr             eRecodeFrom = eTmpEncoding;
398*43ad51ffSHerbert Dürr         }
399*43ad51ffSHerbert Dürr     }
400*43ad51ffSHerbert Dürr 
401*43ad51ffSHerbert Dürr     // parse the best CMAP subtable
402*43ad51ffSHerbert Dürr     int nRangeCount = 0;
403*43ad51ffSHerbert Dürr     sal_UCS4* pCodePairs = NULL;
404*43ad51ffSHerbert Dürr     int* pStartGlyphs = NULL;
405*43ad51ffSHerbert Dürr 
406*43ad51ffSHerbert Dürr     typedef std::vector<sal_uInt16> U16Vector;
407*43ad51ffSHerbert Dürr     U16Vector aGlyphIdArray;
408*43ad51ffSHerbert Dürr     aGlyphIdArray.reserve( 0x1000 );
409*43ad51ffSHerbert Dürr     aGlyphIdArray.push_back( 0 );
410*43ad51ffSHerbert Dürr 
411*43ad51ffSHerbert Dürr     // format 4, the most common 16bit char mapping table
412*43ad51ffSHerbert Dürr     if( (nFormat == 4) && ((nOffset+16) < nLength) )
413*43ad51ffSHerbert Dürr     {
414*43ad51ffSHerbert Dürr         int nSegCountX2 = Getsal_uInt16( pCmap + nOffset + 6 );
415*43ad51ffSHerbert Dürr         nRangeCount = nSegCountX2/2 - 1;
416*43ad51ffSHerbert Dürr         pCodePairs = new sal_UCS4[ nRangeCount * 2 ];
417*43ad51ffSHerbert Dürr         pStartGlyphs = new int[ nRangeCount ];
418*43ad51ffSHerbert Dürr         const unsigned char* pLimitBase = pCmap + nOffset + 14;
419*43ad51ffSHerbert Dürr         const unsigned char* pBeginBase = pLimitBase + nSegCountX2 + 2;
420*43ad51ffSHerbert Dürr         const unsigned char* pDeltaBase = pBeginBase + nSegCountX2;
421*43ad51ffSHerbert Dürr         const unsigned char* pOffsetBase = pDeltaBase + nSegCountX2;
422*43ad51ffSHerbert Dürr         sal_UCS4* pCP = pCodePairs;
423*43ad51ffSHerbert Dürr         for( int i = 0; i < nRangeCount; ++i )
424*43ad51ffSHerbert Dürr         {
425*43ad51ffSHerbert Dürr             const sal_UCS4 cMinChar = Getsal_uInt16( pBeginBase + 2*i );
426*43ad51ffSHerbert Dürr             const sal_UCS4 cMaxChar = Getsal_uInt16( pLimitBase + 2*i );
427*43ad51ffSHerbert Dürr             const int nGlyphDelta  = GetSShort( pDeltaBase + 2*i );
428*43ad51ffSHerbert Dürr             const int nRangeOffset = Getsal_uInt16( pOffsetBase + 2*i );
429*43ad51ffSHerbert Dürr             if( cMinChar > cMaxChar )   // no sane font should trigger this
430*43ad51ffSHerbert Dürr                 break;
431*43ad51ffSHerbert Dürr             if( cMaxChar == 0xFFFF )
432*43ad51ffSHerbert Dürr                 break;
433*43ad51ffSHerbert Dürr             *(pCP++) = cMinChar;
434*43ad51ffSHerbert Dürr             *(pCP++) = cMaxChar + 1;
435*43ad51ffSHerbert Dürr             if( !nRangeOffset ) {
436*43ad51ffSHerbert Dürr                 // glyphid can be calculated directly
437*43ad51ffSHerbert Dürr                 pStartGlyphs[i] = (cMinChar + nGlyphDelta) & 0xFFFF;
438*43ad51ffSHerbert Dürr             } else {
439*43ad51ffSHerbert Dürr                 // update the glyphid-array with the glyphs in this range
440*43ad51ffSHerbert Dürr                 pStartGlyphs[i] = -(int)aGlyphIdArray.size();
441*43ad51ffSHerbert Dürr                 const unsigned char* pGlyphIdPtr = pOffsetBase + 2*i + nRangeOffset;
442*43ad51ffSHerbert Dürr                 for( sal_UCS4 c = cMinChar; c <= cMaxChar; ++c, pGlyphIdPtr+=2 ) {
443*43ad51ffSHerbert Dürr                     const int nGlyphIndex = Getsal_uInt16( pGlyphIdPtr ) + nGlyphDelta;
444*43ad51ffSHerbert Dürr                     aGlyphIdArray.push_back( static_cast<sal_uInt16>(nGlyphIndex) );
445*43ad51ffSHerbert Dürr                 }
446*43ad51ffSHerbert Dürr             }
447*43ad51ffSHerbert Dürr         }
448*43ad51ffSHerbert Dürr         nRangeCount = (pCP - pCodePairs) / 2;
449*43ad51ffSHerbert Dürr     }
450*43ad51ffSHerbert Dürr     // format 12, the most common 32bit char mapping table
451*43ad51ffSHerbert Dürr     else if( (nFormat == 12) && ((nOffset+16) < nLength) )
452*43ad51ffSHerbert Dürr     {
453*43ad51ffSHerbert Dürr         nRangeCount = GetUInt( pCmap + nOffset + 12 );
454*43ad51ffSHerbert Dürr         pCodePairs = new sal_UCS4[ nRangeCount * 2 ];
455*43ad51ffSHerbert Dürr         pStartGlyphs = new int[ nRangeCount ];
456*43ad51ffSHerbert Dürr         const unsigned char* pGroup = pCmap + nOffset + 16;
457*43ad51ffSHerbert Dürr         sal_UCS4* pCP = pCodePairs;
458*43ad51ffSHerbert Dürr         for( int i = 0; i < nRangeCount; ++i )
459*43ad51ffSHerbert Dürr         {
460*43ad51ffSHerbert Dürr             sal_UCS4 cMinChar = GetUInt( pGroup + 0 );
461*43ad51ffSHerbert Dürr             sal_UCS4 cMaxChar = GetUInt( pGroup + 4 );
462*43ad51ffSHerbert Dürr             int nGlyphId = GetUInt( pGroup + 8 );
463*43ad51ffSHerbert Dürr             pGroup += 12;
464*43ad51ffSHerbert Dürr #if 0       // TODO: remove unicode baseplane clipping for UCS-4 support
465*43ad51ffSHerbert Dürr             if( cMinChar > 0xFFFF )
466*43ad51ffSHerbert Dürr                 continue;
467*43ad51ffSHerbert Dürr             if( cMaxChar > 0xFFFF )
468*43ad51ffSHerbert Dürr                 cMaxChar = 0xFFFF;
469*43ad51ffSHerbert Dürr #else
470*43ad51ffSHerbert Dürr             if( cMinChar > cMaxChar )   // no sane font should trigger this
471*43ad51ffSHerbert Dürr                 break;
472*43ad51ffSHerbert Dürr #endif
473*43ad51ffSHerbert Dürr             *(pCP++) = cMinChar;
474*43ad51ffSHerbert Dürr             *(pCP++) = cMaxChar + 1;
475*43ad51ffSHerbert Dürr             pStartGlyphs[i] = nGlyphId;
476*43ad51ffSHerbert Dürr         }
477*43ad51ffSHerbert Dürr         nRangeCount = (pCP - pCodePairs) / 2;
478*43ad51ffSHerbert Dürr     }
479*43ad51ffSHerbert Dürr 
480*43ad51ffSHerbert Dürr     // check if any subtable resulted in something usable
481*43ad51ffSHerbert Dürr     if( nRangeCount <= 0 )
482*43ad51ffSHerbert Dürr     {
483*43ad51ffSHerbert Dürr         delete[] pCodePairs;
484*43ad51ffSHerbert Dürr         delete[] pStartGlyphs;
485*43ad51ffSHerbert Dürr 
486*43ad51ffSHerbert Dürr         // even when no CMAP is available we know it for symbol fonts
487*43ad51ffSHerbert Dürr         if( rResult.mbSymbolic )
488*43ad51ffSHerbert Dürr         {
489*43ad51ffSHerbert Dürr             pCodePairs = new sal_UCS4[4];
490*43ad51ffSHerbert Dürr             pCodePairs[0] = 0x0020;    // aliased symbols
491*43ad51ffSHerbert Dürr             pCodePairs[1] = 0x0100;
492*43ad51ffSHerbert Dürr             pCodePairs[2] = 0xF020;    // original symbols
493*43ad51ffSHerbert Dürr             pCodePairs[3] = 0xF100;
494*43ad51ffSHerbert Dürr             rResult.mpRangeCodes = pCodePairs;
495*43ad51ffSHerbert Dürr             rResult.mnRangeCount = 2;
496*43ad51ffSHerbert Dürr             return true;
497*43ad51ffSHerbert Dürr         }
498*43ad51ffSHerbert Dürr 
499*43ad51ffSHerbert Dürr         return false;
500*43ad51ffSHerbert Dürr     }
501*43ad51ffSHerbert Dürr 
502*43ad51ffSHerbert Dürr     // recode the code ranges to their unicode encoded ranges if needed
503*43ad51ffSHerbert Dürr     rtl_TextToUnicodeConverter aConverter = NULL;
504*43ad51ffSHerbert Dürr     rtl_UnicodeToTextContext aCvtContext = NULL;
505*43ad51ffSHerbert Dürr 
506*43ad51ffSHerbert Dürr     rResult.mbRecoded = ( eRecodeFrom != RTL_TEXTENCODING_UNICODE );
507*43ad51ffSHerbert Dürr     if( rResult.mbRecoded )
508*43ad51ffSHerbert Dürr     {
509*43ad51ffSHerbert Dürr         aConverter = rtl_createTextToUnicodeConverter( eRecodeFrom );
510*43ad51ffSHerbert Dürr         aCvtContext = rtl_createTextToUnicodeContext( aConverter );
511*43ad51ffSHerbert Dürr     }
512*43ad51ffSHerbert Dürr 
513*43ad51ffSHerbert Dürr     if( aConverter && aCvtContext )
514*43ad51ffSHerbert Dürr     {
515*43ad51ffSHerbert Dürr         // determine the set of supported unicodes from encoded ranges
516*43ad51ffSHerbert Dürr         typedef std::set<sal_UCS4> Ucs4Set;
517*43ad51ffSHerbert Dürr         Ucs4Set aSupportedUnicodes;
518*43ad51ffSHerbert Dürr 
519*43ad51ffSHerbert Dürr         static const int NINSIZE = 64;
520*43ad51ffSHerbert Dürr         static const int NOUTSIZE = 64;
521*43ad51ffSHerbert Dürr         sal_Char    cCharsInp[ NINSIZE ];
522*43ad51ffSHerbert Dürr         sal_Unicode cCharsOut[ NOUTSIZE ];
523*43ad51ffSHerbert Dürr         sal_UCS4* pCP = pCodePairs;
524*43ad51ffSHerbert Dürr         for( int i = 0; i < nRangeCount; ++i )
525*43ad51ffSHerbert Dürr         {
526*43ad51ffSHerbert Dürr             sal_UCS4 cMin = *(pCP++);
527*43ad51ffSHerbert Dürr             sal_UCS4 cEnd = *(pCP++);
528*43ad51ffSHerbert Dürr             while( cMin < cEnd )
529*43ad51ffSHerbert Dürr             {
530*43ad51ffSHerbert Dürr                 int j = 0;
531*43ad51ffSHerbert Dürr                 for(; (cMin < cEnd) && (j < NINSIZE); ++cMin )
532*43ad51ffSHerbert Dürr                 {
533*43ad51ffSHerbert Dürr                     if( cMin >= 0x0100 )
534*43ad51ffSHerbert Dürr                         cCharsInp[ j++ ] = static_cast<sal_Char>(cMin >> 8);
535*43ad51ffSHerbert Dürr                     if( (cMin >= 0x0100) || (cMin < 0x00A0)  )
536*43ad51ffSHerbert Dürr                         cCharsInp[ j++ ] = static_cast<sal_Char>(cMin);
537*43ad51ffSHerbert Dürr                 }
538*43ad51ffSHerbert Dürr 
539*43ad51ffSHerbert Dürr                 sal_uInt32 nCvtInfo;
540*43ad51ffSHerbert Dürr                 sal_Size nSrcCvtBytes;
541*43ad51ffSHerbert Dürr                 int nOutLen = rtl_convertTextToUnicode(
542*43ad51ffSHerbert Dürr                     aConverter, aCvtContext,
543*43ad51ffSHerbert Dürr                     cCharsInp, j, cCharsOut, NOUTSIZE,
544*43ad51ffSHerbert Dürr                     RTL_TEXTTOUNICODE_FLAGS_INVALID_IGNORE
545*43ad51ffSHerbert Dürr                     | RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_IGNORE,
546*43ad51ffSHerbert Dürr                     &nCvtInfo, &nSrcCvtBytes );
547*43ad51ffSHerbert Dürr 
548*43ad51ffSHerbert Dürr                 for( j = 0; j < nOutLen; ++j )
549*43ad51ffSHerbert Dürr                     aSupportedUnicodes.insert( cCharsOut[j] );
550*43ad51ffSHerbert Dürr             }
551*43ad51ffSHerbert Dürr         }
552*43ad51ffSHerbert Dürr 
553*43ad51ffSHerbert Dürr         rtl_destroyTextToUnicodeConverter( aCvtContext );
554*43ad51ffSHerbert Dürr         rtl_destroyTextToUnicodeConverter( aConverter );
555*43ad51ffSHerbert Dürr 
556*43ad51ffSHerbert Dürr         // convert the set of supported unicodes to ranges
557*43ad51ffSHerbert Dürr         typedef std::vector<sal_UCS4> Ucs4Vector;
558*43ad51ffSHerbert Dürr         Ucs4Vector aSupportedRanges;
559*43ad51ffSHerbert Dürr 
560*43ad51ffSHerbert Dürr         Ucs4Set::const_iterator itChar = aSupportedUnicodes.begin();
561*43ad51ffSHerbert Dürr         for(; itChar != aSupportedUnicodes.end(); ++itChar )
562*43ad51ffSHerbert Dürr         {
563*43ad51ffSHerbert Dürr             if( aSupportedRanges.empty()
564*43ad51ffSHerbert Dürr             || (aSupportedRanges.back() != *itChar) )
565*43ad51ffSHerbert Dürr             {
566*43ad51ffSHerbert Dürr                 // add new range beginning with current unicode
567*43ad51ffSHerbert Dürr                 aSupportedRanges.push_back( *itChar );
568*43ad51ffSHerbert Dürr                 aSupportedRanges.push_back( 0 );
569*43ad51ffSHerbert Dürr             }
570*43ad51ffSHerbert Dürr 
571*43ad51ffSHerbert Dürr             // extend existing range to include current unicode
572*43ad51ffSHerbert Dürr             aSupportedRanges.back() = *itChar + 1;
573*43ad51ffSHerbert Dürr         }
574*43ad51ffSHerbert Dürr 
575*43ad51ffSHerbert Dürr         // glyph mapping for non-unicode fonts not implemented
576*43ad51ffSHerbert Dürr         delete[] pStartGlyphs;
577*43ad51ffSHerbert Dürr         pStartGlyphs = NULL;
578*43ad51ffSHerbert Dürr         aGlyphIdArray.clear();
579*43ad51ffSHerbert Dürr 
580*43ad51ffSHerbert Dürr         // make a pCodePairs array using the vector from above
581*43ad51ffSHerbert Dürr         delete[] pCodePairs;
582*43ad51ffSHerbert Dürr         nRangeCount = aSupportedRanges.size() / 2;
583*43ad51ffSHerbert Dürr         if( nRangeCount <= 0 )
584*43ad51ffSHerbert Dürr             return false;
585*43ad51ffSHerbert Dürr         pCodePairs = new sal_UCS4[ nRangeCount * 2 ];
586*43ad51ffSHerbert Dürr         Ucs4Vector::const_iterator itInt = aSupportedRanges.begin();
587*43ad51ffSHerbert Dürr         for( pCP = pCodePairs; itInt != aSupportedRanges.end(); ++itInt )
588*43ad51ffSHerbert Dürr             *(pCP++) = *itInt;
589*43ad51ffSHerbert Dürr     }
590*43ad51ffSHerbert Dürr 
591*43ad51ffSHerbert Dürr     // prepare the glyphid-array if needed
592*43ad51ffSHerbert Dürr     // TODO: merge ranges if they are close enough?
593*43ad51ffSHerbert Dürr     sal_uInt16* pGlyphIds = NULL;
594*43ad51ffSHerbert Dürr     if( !aGlyphIdArray.empty())
595*43ad51ffSHerbert Dürr     {
596*43ad51ffSHerbert Dürr         pGlyphIds = new sal_uInt16[ aGlyphIdArray.size() ];
597*43ad51ffSHerbert Dürr         sal_uInt16* pOut = pGlyphIds;
598*43ad51ffSHerbert Dürr         U16Vector::const_iterator it = aGlyphIdArray.begin();
599*43ad51ffSHerbert Dürr         while( it != aGlyphIdArray.end() )
600*43ad51ffSHerbert Dürr             *(pOut++) = *(it++);
601*43ad51ffSHerbert Dürr     }
602*43ad51ffSHerbert Dürr 
603*43ad51ffSHerbert Dürr     // update the result struct
604*43ad51ffSHerbert Dürr     rResult.mpRangeCodes = pCodePairs;
605*43ad51ffSHerbert Dürr     rResult.mpStartGlyphs = pStartGlyphs;
606*43ad51ffSHerbert Dürr     rResult.mnRangeCount = nRangeCount;
607*43ad51ffSHerbert Dürr     rResult.mpGlyphIds = pGlyphIds;
608*43ad51ffSHerbert Dürr     return true;
609*43ad51ffSHerbert Dürr }
610*43ad51ffSHerbert Dürr 
611*43ad51ffSHerbert Dürr // =======================================================================
612*43ad51ffSHerbert Dürr 
613*43ad51ffSHerbert Dürr FontCharMap::FontCharMap()
614*43ad51ffSHerbert Dürr :   mpImpl( ImplFontCharMap::GetDefaultMap() )
615*43ad51ffSHerbert Dürr {}
616*43ad51ffSHerbert Dürr 
617*43ad51ffSHerbert Dürr // -----------------------------------------------------------------------
618*43ad51ffSHerbert Dürr 
619*43ad51ffSHerbert Dürr FontCharMap::~FontCharMap()
620*43ad51ffSHerbert Dürr {
621*43ad51ffSHerbert Dürr 	mpImpl->DeReference();
622*43ad51ffSHerbert Dürr 	mpImpl = NULL;
623*43ad51ffSHerbert Dürr }
624*43ad51ffSHerbert Dürr 
625*43ad51ffSHerbert Dürr // -----------------------------------------------------------------------
626*43ad51ffSHerbert Dürr 
627*43ad51ffSHerbert Dürr int FontCharMap::GetCharCount() const
628*43ad51ffSHerbert Dürr {
629*43ad51ffSHerbert Dürr 	return mpImpl->GetCharCount();
630*43ad51ffSHerbert Dürr }
631*43ad51ffSHerbert Dürr 
632*43ad51ffSHerbert Dürr // -----------------------------------------------------------------------
633*43ad51ffSHerbert Dürr 
634*43ad51ffSHerbert Dürr int FontCharMap::CountCharsInRange( sal_UCS4 cMin, sal_UCS4 cMax ) const
635*43ad51ffSHerbert Dürr {
636*43ad51ffSHerbert Dürr 	return mpImpl->CountCharsInRange( cMin, cMax );
637*43ad51ffSHerbert Dürr }
638*43ad51ffSHerbert Dürr 
639*43ad51ffSHerbert Dürr // -----------------------------------------------------------------------
640*43ad51ffSHerbert Dürr 
641*43ad51ffSHerbert Dürr void FontCharMap::Reset( const ImplFontCharMap* pNewMap )
642*43ad51ffSHerbert Dürr {
643*43ad51ffSHerbert Dürr 	if( pNewMap == NULL )
644*43ad51ffSHerbert Dürr 	{
645*43ad51ffSHerbert Dürr 		mpImpl->DeReference();
646*43ad51ffSHerbert Dürr 		mpImpl = ImplFontCharMap::GetDefaultMap();
647*43ad51ffSHerbert Dürr 	}
648*43ad51ffSHerbert Dürr 	else if( pNewMap != mpImpl )
649*43ad51ffSHerbert Dürr 	{
650*43ad51ffSHerbert Dürr 		mpImpl->DeReference();
651*43ad51ffSHerbert Dürr 		mpImpl = pNewMap;
652*43ad51ffSHerbert Dürr 		mpImpl->AddReference();
653*43ad51ffSHerbert Dürr 	}
654*43ad51ffSHerbert Dürr }
655*43ad51ffSHerbert Dürr 
656*43ad51ffSHerbert Dürr // -----------------------------------------------------------------------
657*43ad51ffSHerbert Dürr 
658*43ad51ffSHerbert Dürr bool FontCharMap::IsDefaultMap() const
659*43ad51ffSHerbert Dürr {
660*43ad51ffSHerbert Dürr 	return mpImpl->IsDefaultMap();
661*43ad51ffSHerbert Dürr }
662*43ad51ffSHerbert Dürr 
663*43ad51ffSHerbert Dürr // -----------------------------------------------------------------------
664*43ad51ffSHerbert Dürr 
665*43ad51ffSHerbert Dürr bool FontCharMap::HasChar( sal_UCS4 cChar ) const
666*43ad51ffSHerbert Dürr {
667*43ad51ffSHerbert Dürr 	return mpImpl->HasChar( cChar );
668*43ad51ffSHerbert Dürr }
669*43ad51ffSHerbert Dürr 
670*43ad51ffSHerbert Dürr // -----------------------------------------------------------------------
671*43ad51ffSHerbert Dürr 
672*43ad51ffSHerbert Dürr sal_UCS4 FontCharMap::GetFirstChar() const
673*43ad51ffSHerbert Dürr {
674*43ad51ffSHerbert Dürr 	return mpImpl->GetFirstChar();
675*43ad51ffSHerbert Dürr }
676*43ad51ffSHerbert Dürr 
677*43ad51ffSHerbert Dürr // -----------------------------------------------------------------------
678*43ad51ffSHerbert Dürr 
679*43ad51ffSHerbert Dürr sal_UCS4 FontCharMap::GetLastChar() const
680*43ad51ffSHerbert Dürr {
681*43ad51ffSHerbert Dürr 	return mpImpl->GetLastChar();
682*43ad51ffSHerbert Dürr }
683*43ad51ffSHerbert Dürr 
684*43ad51ffSHerbert Dürr // -----------------------------------------------------------------------
685*43ad51ffSHerbert Dürr 
686*43ad51ffSHerbert Dürr sal_UCS4 FontCharMap::GetNextChar( sal_UCS4 cChar ) const
687*43ad51ffSHerbert Dürr {
688*43ad51ffSHerbert Dürr 	return mpImpl->GetNextChar( cChar );
689*43ad51ffSHerbert Dürr }
690*43ad51ffSHerbert Dürr 
691*43ad51ffSHerbert Dürr // -----------------------------------------------------------------------
692*43ad51ffSHerbert Dürr 
693*43ad51ffSHerbert Dürr sal_UCS4 FontCharMap::GetPrevChar( sal_UCS4 cChar ) const
694*43ad51ffSHerbert Dürr {
695*43ad51ffSHerbert Dürr 	return mpImpl->GetPrevChar( cChar );
696*43ad51ffSHerbert Dürr }
697*43ad51ffSHerbert Dürr 
698*43ad51ffSHerbert Dürr // -----------------------------------------------------------------------
699*43ad51ffSHerbert Dürr 
700*43ad51ffSHerbert Dürr int FontCharMap::GetIndexFromChar( sal_UCS4 cChar ) const
701*43ad51ffSHerbert Dürr {
702*43ad51ffSHerbert Dürr 	return mpImpl->GetIndexFromChar( cChar );
703*43ad51ffSHerbert Dürr }
704*43ad51ffSHerbert Dürr 
705*43ad51ffSHerbert Dürr // -----------------------------------------------------------------------
706*43ad51ffSHerbert Dürr 
707*43ad51ffSHerbert Dürr sal_UCS4 FontCharMap::GetCharFromIndex( int nIndex ) const
708*43ad51ffSHerbert Dürr {
709*43ad51ffSHerbert Dürr 	return mpImpl->GetCharFromIndex( nIndex );
710*43ad51ffSHerbert Dürr }
711*43ad51ffSHerbert Dürr 
712*43ad51ffSHerbert Dürr // =======================================================================
713*43ad51ffSHerbert Dürr 
714*43ad51ffSHerbert Dürr // on some systems we have to get the font attributes from the name table
715*43ad51ffSHerbert Dürr // since neither head's macStyle nor OS/2's panose are easily available
716*43ad51ffSHerbert Dürr // during font enumeration. macStyle bits would be not sufficient anyway
717*43ad51ffSHerbert Dürr // and SFNT fonts on Mac usually do not contain an OS/2 table.
718*43ad51ffSHerbert Dürr void UpdateAttributesFromPSName( const String& rPSName, ImplDevFontAttributes& rDFA )
719*43ad51ffSHerbert Dürr {
720*43ad51ffSHerbert Dürr 	ByteString aPSName( rPSName, RTL_TEXTENCODING_UTF8 );
721*43ad51ffSHerbert Dürr 	aPSName.ToLowerAscii();
722*43ad51ffSHerbert Dürr 
723*43ad51ffSHerbert Dürr 	// TODO: use a multi-string ignore-case matcher once it becomes available
724*43ad51ffSHerbert Dürr 	if( (aPSName.Search("regular") != STRING_NOTFOUND)
725*43ad51ffSHerbert Dürr 	||  (aPSName.Search("normal") != STRING_NOTFOUND)
726*43ad51ffSHerbert Dürr 	||  (aPSName.Search("roman") != STRING_NOTFOUND)
727*43ad51ffSHerbert Dürr 	||  (aPSName.Search("medium") != STRING_NOTFOUND)
728*43ad51ffSHerbert Dürr 	||  (aPSName.Search("plain") != STRING_NOTFOUND)
729*43ad51ffSHerbert Dürr 	||  (aPSName.Search("standard") != STRING_NOTFOUND)
730*43ad51ffSHerbert Dürr 	||  (aPSName.Search("std") != STRING_NOTFOUND) )
731*43ad51ffSHerbert Dürr 	{
732*43ad51ffSHerbert Dürr 		rDFA.meWidthType = WIDTH_NORMAL;
733*43ad51ffSHerbert Dürr 		rDFA.meWeight    = WEIGHT_NORMAL;
734*43ad51ffSHerbert Dürr 		rDFA.meItalic    = ITALIC_NONE;
735*43ad51ffSHerbert Dürr 	}
736*43ad51ffSHerbert Dürr 
737*43ad51ffSHerbert Dürr 	// heuristics for font weight
738*43ad51ffSHerbert Dürr 	if (aPSName.Search("extrablack") != STRING_NOTFOUND)
739*43ad51ffSHerbert Dürr 		rDFA.meWeight = WEIGHT_BLACK;
740*43ad51ffSHerbert Dürr 	else if (aPSName.Search("black") != STRING_NOTFOUND)
741*43ad51ffSHerbert Dürr 		rDFA.meWeight = WEIGHT_BLACK;
742*43ad51ffSHerbert Dürr #if 1
743*43ad51ffSHerbert Dürr 	else if (aPSName.Search("book") != STRING_NOTFOUND)
744*43ad51ffSHerbert Dürr 		rDFA.meWeight = WEIGHT_NORMAL;
745*43ad51ffSHerbert Dürr #endif
746*43ad51ffSHerbert Dürr 	else if( (aPSName.Search("semibold") != STRING_NOTFOUND)
747*43ad51ffSHerbert Dürr 	||       (aPSName.Search("smbd") != STRING_NOTFOUND))
748*43ad51ffSHerbert Dürr 		rDFA.meWeight = WEIGHT_SEMIBOLD;
749*43ad51ffSHerbert Dürr 	else if( aPSName.Search("ultrabold") != STRING_NOTFOUND)
750*43ad51ffSHerbert Dürr 		rDFA.meWeight = WEIGHT_ULTRABOLD;
751*43ad51ffSHerbert Dürr 	else if( aPSName.Search("extrabold") != STRING_NOTFOUND)
752*43ad51ffSHerbert Dürr 		rDFA.meWeight = WEIGHT_BLACK;
753*43ad51ffSHerbert Dürr 	else if( (aPSName.Search("bold") != STRING_NOTFOUND)
754*43ad51ffSHerbert Dürr 	||       (aPSName.Search("-bd") != STRING_NOTFOUND))
755*43ad51ffSHerbert Dürr 		rDFA.meWeight = WEIGHT_BOLD;
756*43ad51ffSHerbert Dürr 	else if( aPSName.Search("extralight") != STRING_NOTFOUND)
757*43ad51ffSHerbert Dürr 		rDFA.meWeight = WEIGHT_ULTRALIGHT;
758*43ad51ffSHerbert Dürr 	else if( aPSName.Search("ultralight") != STRING_NOTFOUND)
759*43ad51ffSHerbert Dürr 		rDFA.meWeight = WEIGHT_ULTRALIGHT;
760*43ad51ffSHerbert Dürr 	else if( aPSName.Search("light") != STRING_NOTFOUND)
761*43ad51ffSHerbert Dürr 		rDFA.meWeight = WEIGHT_LIGHT;
762*43ad51ffSHerbert Dürr 	else if( aPSName.Search("thin") != STRING_NOTFOUND)
763*43ad51ffSHerbert Dürr 		rDFA.meWeight = WEIGHT_THIN;
764*43ad51ffSHerbert Dürr 	else if( aPSName.Search("-w3") != STRING_NOTFOUND)
765*43ad51ffSHerbert Dürr 		rDFA.meWeight = WEIGHT_LIGHT;
766*43ad51ffSHerbert Dürr 	else if( aPSName.Search("-w4") != STRING_NOTFOUND)
767*43ad51ffSHerbert Dürr 		rDFA.meWeight = WEIGHT_SEMILIGHT;
768*43ad51ffSHerbert Dürr 	else if( aPSName.Search("-w5") != STRING_NOTFOUND)
769*43ad51ffSHerbert Dürr 		rDFA.meWeight = WEIGHT_NORMAL;
770*43ad51ffSHerbert Dürr 	else if( aPSName.Search("-w6") != STRING_NOTFOUND)
771*43ad51ffSHerbert Dürr 		rDFA.meWeight = WEIGHT_SEMIBOLD;
772*43ad51ffSHerbert Dürr 	else if( aPSName.Search("-w7") != STRING_NOTFOUND)
773*43ad51ffSHerbert Dürr 		rDFA.meWeight = WEIGHT_BOLD;
774*43ad51ffSHerbert Dürr 	else if( aPSName.Search("-w8") != STRING_NOTFOUND)
775*43ad51ffSHerbert Dürr 		rDFA.meWeight = WEIGHT_ULTRABOLD;
776*43ad51ffSHerbert Dürr 	else if( aPSName.Search("-w9") != STRING_NOTFOUND)
777*43ad51ffSHerbert Dürr 		rDFA.meWeight = WEIGHT_BLACK;
778*43ad51ffSHerbert Dürr 
779*43ad51ffSHerbert Dürr     // heuristics for font slant
780*43ad51ffSHerbert Dürr     if( (aPSName.Search("italic") != STRING_NOTFOUND)
781*43ad51ffSHerbert Dürr     ||  (aPSName.Search(" ital") != STRING_NOTFOUND)
782*43ad51ffSHerbert Dürr     ||  (aPSName.Search("cursive") != STRING_NOTFOUND)
783*43ad51ffSHerbert Dürr     ||  (aPSName.Search("-it") != STRING_NOTFOUND)
784*43ad51ffSHerbert Dürr     ||  (aPSName.Search("lightit") != STRING_NOTFOUND)
785*43ad51ffSHerbert Dürr     ||  (aPSName.Search("mediumit") != STRING_NOTFOUND)
786*43ad51ffSHerbert Dürr     ||  (aPSName.Search("boldit") != STRING_NOTFOUND)
787*43ad51ffSHerbert Dürr     ||  (aPSName.Search("cnit") != STRING_NOTFOUND)
788*43ad51ffSHerbert Dürr     ||  (aPSName.Search("bdcn") != STRING_NOTFOUND)
789*43ad51ffSHerbert Dürr     ||  (aPSName.Search("bdit") != STRING_NOTFOUND)
790*43ad51ffSHerbert Dürr     ||  (aPSName.Search("condit") != STRING_NOTFOUND)
791*43ad51ffSHerbert Dürr     ||  (aPSName.Search("bookit") != STRING_NOTFOUND)
792*43ad51ffSHerbert Dürr     ||  (aPSName.Search("blackit") != STRING_NOTFOUND) )
793*43ad51ffSHerbert Dürr 	    rDFA.meItalic = ITALIC_NORMAL;
794*43ad51ffSHerbert Dürr     if( (aPSName.Search("oblique") != STRING_NOTFOUND)
795*43ad51ffSHerbert Dürr     ||  (aPSName.Search("inclined") != STRING_NOTFOUND)
796*43ad51ffSHerbert Dürr     ||  (aPSName.Search("slanted") != STRING_NOTFOUND) )
797*43ad51ffSHerbert Dürr 	    rDFA.meItalic = ITALIC_OBLIQUE;
798*43ad51ffSHerbert Dürr 
799*43ad51ffSHerbert Dürr     // heuristics for font width
800*43ad51ffSHerbert Dürr     if( (aPSName.Search("condensed") != STRING_NOTFOUND)
801*43ad51ffSHerbert Dürr     ||  (aPSName.Search("-cond") != STRING_NOTFOUND)
802*43ad51ffSHerbert Dürr     ||  (aPSName.Search("boldcond") != STRING_NOTFOUND)
803*43ad51ffSHerbert Dürr     ||  (aPSName.Search("boldcn") != STRING_NOTFOUND)
804*43ad51ffSHerbert Dürr     ||  (aPSName.Search("cnit") != STRING_NOTFOUND) )
805*43ad51ffSHerbert Dürr 	    rDFA.meWidthType = WIDTH_CONDENSED;
806*43ad51ffSHerbert Dürr     else if (aPSName.Search("narrow") != STRING_NOTFOUND)
807*43ad51ffSHerbert Dürr 	    rDFA.meWidthType = WIDTH_SEMI_CONDENSED;
808*43ad51ffSHerbert Dürr     else if (aPSName.Search("expanded") != STRING_NOTFOUND)
809*43ad51ffSHerbert Dürr 	    rDFA.meWidthType = WIDTH_EXPANDED;
810*43ad51ffSHerbert Dürr     else if (aPSName.Search("wide") != STRING_NOTFOUND)
811*43ad51ffSHerbert Dürr 	    rDFA.meWidthType = WIDTH_EXPANDED;
812*43ad51ffSHerbert Dürr 
813*43ad51ffSHerbert Dürr     // heuristics for font pitch
814*43ad51ffSHerbert Dürr     if( (aPSName.Search("mono") != STRING_NOTFOUND)
815*43ad51ffSHerbert Dürr     ||  (aPSName.Search("courier") != STRING_NOTFOUND)
816*43ad51ffSHerbert Dürr     ||  (aPSName.Search("monaco") != STRING_NOTFOUND)
817*43ad51ffSHerbert Dürr     ||  (aPSName.Search("typewriter") != STRING_NOTFOUND) )
818*43ad51ffSHerbert Dürr 	    rDFA.mePitch = PITCH_FIXED;
819*43ad51ffSHerbert Dürr 
820*43ad51ffSHerbert Dürr     // heuristics for font family type
821*43ad51ffSHerbert Dürr     if( (aPSName.Search("script") != STRING_NOTFOUND)
822*43ad51ffSHerbert Dürr     ||  (aPSName.Search("chancery") != STRING_NOTFOUND)
823*43ad51ffSHerbert Dürr     ||  (aPSName.Search("zapfino") != STRING_NOTFOUND))
824*43ad51ffSHerbert Dürr 	    rDFA.meFamily = FAMILY_SCRIPT;
825*43ad51ffSHerbert Dürr     else if( (aPSName.Search("comic") != STRING_NOTFOUND)
826*43ad51ffSHerbert Dürr     ||  (aPSName.Search("outline") != STRING_NOTFOUND)
827*43ad51ffSHerbert Dürr     ||  (aPSName.Search("pinpoint") != STRING_NOTFOUND) )
828*43ad51ffSHerbert Dürr 	    rDFA.meFamily = FAMILY_DECORATIVE;
829*43ad51ffSHerbert Dürr     else if( (aPSName.Search("sans") != STRING_NOTFOUND)
830*43ad51ffSHerbert Dürr     ||  (aPSName.Search("arial") != STRING_NOTFOUND) )
831*43ad51ffSHerbert Dürr 	    rDFA.meFamily = FAMILY_SWISS;
832*43ad51ffSHerbert Dürr     else if( (aPSName.Search("roman") != STRING_NOTFOUND)
833*43ad51ffSHerbert Dürr     ||  (aPSName.Search("times") != STRING_NOTFOUND) )
834*43ad51ffSHerbert Dürr 	    rDFA.meFamily = FAMILY_ROMAN;
835*43ad51ffSHerbert Dürr 
836*43ad51ffSHerbert Dürr     // heuristics for codepoint semantic
837*43ad51ffSHerbert Dürr     if( (aPSName.Search("symbol") != STRING_NOTFOUND)
838*43ad51ffSHerbert Dürr     ||  (aPSName.Search("dings") != STRING_NOTFOUND)
839*43ad51ffSHerbert Dürr     ||  (aPSName.Search("dingbats") != STRING_NOTFOUND)
840*43ad51ffSHerbert Dürr     ||  (aPSName.Search("braille") != STRING_NOTFOUND)
841*43ad51ffSHerbert Dürr     ||  (aPSName.Search("ornaments") != STRING_NOTFOUND)
842*43ad51ffSHerbert Dürr     ||  (aPSName.Search("embellishments") != STRING_NOTFOUND) )
843*43ad51ffSHerbert Dürr         rDFA.mbSymbolFlag  = true;
844*43ad51ffSHerbert Dürr 
845*43ad51ffSHerbert Dürr    // #i100020# special heuristic for names with single-char styles
846*43ad51ffSHerbert Dürr    // NOTE: we are checking name that hasn't been lower-cased
847*43ad51ffSHerbert Dürr    if( rPSName.Len() > 3 )
848*43ad51ffSHerbert Dürr    {
849*43ad51ffSHerbert Dürr         int i = rPSName.Len();
850*43ad51ffSHerbert Dürr         sal_Unicode c = rPSName.GetChar( --i );
851*43ad51ffSHerbert Dürr         if( c == 'C' ) { // "capitals"
852*43ad51ffSHerbert Dürr             rDFA.meFamily = FAMILY_DECORATIVE;
853*43ad51ffSHerbert Dürr             c = rPSName.GetChar( --i );
854*43ad51ffSHerbert Dürr         }
855*43ad51ffSHerbert Dürr         if( c == 'O' ) { // CFF-based OpenType
856*43ad51ffSHerbert Dürr             c = rPSName.GetChar( --i );
857*43ad51ffSHerbert Dürr         }
858*43ad51ffSHerbert Dürr         if( c == 'I' ) { // "italic"
859*43ad51ffSHerbert Dürr             rDFA.meItalic = ITALIC_NORMAL;
860*43ad51ffSHerbert Dürr             c = rPSName.GetChar( --i );
861*43ad51ffSHerbert Dürr         }
862*43ad51ffSHerbert Dürr         if( c == 'B' )   // "bold"
863*43ad51ffSHerbert Dürr             rDFA.meWeight = WEIGHT_BOLD;
864*43ad51ffSHerbert Dürr         if( c == 'C' )   // "capitals"
865*43ad51ffSHerbert Dürr             rDFA.meFamily = FAMILY_DECORATIVE;
866*43ad51ffSHerbert Dürr         // TODO: check that all single-char styles have been resolved?
867*43ad51ffSHerbert Dürr     }
868*43ad51ffSHerbert Dürr }
869*43ad51ffSHerbert Dürr 
870*43ad51ffSHerbert Dürr // =======================================================================
871*43ad51ffSHerbert Dürr 
872