xref: /AOO41X/main/vcl/source/gdi/metric.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1*cdf0e10cSrcweir /*************************************************************************
2*cdf0e10cSrcweir  *
3*cdf0e10cSrcweir  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4*cdf0e10cSrcweir  *
5*cdf0e10cSrcweir  * Copyright 2000, 2010 Oracle and/or its affiliates.
6*cdf0e10cSrcweir  *
7*cdf0e10cSrcweir  * OpenOffice.org - a multi-platform office productivity suite
8*cdf0e10cSrcweir  *
9*cdf0e10cSrcweir  * This file is part of OpenOffice.org.
10*cdf0e10cSrcweir  *
11*cdf0e10cSrcweir  * OpenOffice.org is free software: you can redistribute it and/or modify
12*cdf0e10cSrcweir  * it under the terms of the GNU Lesser General Public License version 3
13*cdf0e10cSrcweir  * only, as published by the Free Software Foundation.
14*cdf0e10cSrcweir  *
15*cdf0e10cSrcweir  * OpenOffice.org is distributed in the hope that it will be useful,
16*cdf0e10cSrcweir  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17*cdf0e10cSrcweir  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18*cdf0e10cSrcweir  * GNU Lesser General Public License version 3 for more details
19*cdf0e10cSrcweir  * (a copy is included in the LICENSE file that accompanied this code).
20*cdf0e10cSrcweir  *
21*cdf0e10cSrcweir  * You should have received a copy of the GNU Lesser General Public License
22*cdf0e10cSrcweir  * version 3 along with OpenOffice.org.  If not, see
23*cdf0e10cSrcweir  * <http://www.openoffice.org/license.html>
24*cdf0e10cSrcweir  * for a copy of the LGPLv3 License.
25*cdf0e10cSrcweir  *
26*cdf0e10cSrcweir  ************************************************************************/
27*cdf0e10cSrcweir 
28*cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
29*cdf0e10cSrcweir #include "precompiled_vcl.hxx"
30*cdf0e10cSrcweir 
31*cdf0e10cSrcweir #include <impfont.hxx>
32*cdf0e10cSrcweir #include <vcl/metric.hxx>
33*cdf0e10cSrcweir 
34*cdf0e10cSrcweir #include <vector>
35*cdf0e10cSrcweir #include <set>
36*cdf0e10cSrcweir 
37*cdf0e10cSrcweir #include <cstdio>
38*cdf0e10cSrcweir 
39*cdf0e10cSrcweir // =======================================================================
40*cdf0e10cSrcweir 
41*cdf0e10cSrcweir ImplFontMetric::ImplFontMetric()
42*cdf0e10cSrcweir :   mnAscent( 0 ),
43*cdf0e10cSrcweir     mnDescent( 0 ),
44*cdf0e10cSrcweir     mnIntLeading( 0 ),
45*cdf0e10cSrcweir     mnExtLeading( 0 ),
46*cdf0e10cSrcweir     mnLineHeight( 0 ),
47*cdf0e10cSrcweir     mnSlant( 0 ),
48*cdf0e10cSrcweir     mnMiscFlags( 0 ),
49*cdf0e10cSrcweir     mnRefCount( 1 )
50*cdf0e10cSrcweir {}
51*cdf0e10cSrcweir 
52*cdf0e10cSrcweir // -----------------------------------------------------------------------
53*cdf0e10cSrcweir 
54*cdf0e10cSrcweir inline void ImplFontMetric::AddReference()
55*cdf0e10cSrcweir {
56*cdf0e10cSrcweir     // TODO: disable refcounting on the default maps?
57*cdf0e10cSrcweir     ++mnRefCount;
58*cdf0e10cSrcweir }
59*cdf0e10cSrcweir 
60*cdf0e10cSrcweir // -----------------------------------------------------------------------
61*cdf0e10cSrcweir 
62*cdf0e10cSrcweir inline void ImplFontMetric::DeReference()
63*cdf0e10cSrcweir {
64*cdf0e10cSrcweir     // TODO: disable refcounting on the default maps?
65*cdf0e10cSrcweir     if( --mnRefCount <= 0 )
66*cdf0e10cSrcweir         delete this;
67*cdf0e10cSrcweir }
68*cdf0e10cSrcweir 
69*cdf0e10cSrcweir // -----------------------------------------------------------------------
70*cdf0e10cSrcweir 
71*cdf0e10cSrcweir bool ImplFontMetric::operator==( const ImplFontMetric& r ) const
72*cdf0e10cSrcweir {
73*cdf0e10cSrcweir     if( mnMiscFlags  != r.mnMiscFlags )
74*cdf0e10cSrcweir         return false;
75*cdf0e10cSrcweir     if( mnAscent     != r.mnAscent )
76*cdf0e10cSrcweir         return false;
77*cdf0e10cSrcweir     if( mnDescent    != r.mnDescent )
78*cdf0e10cSrcweir         return false;
79*cdf0e10cSrcweir     if( mnIntLeading != r.mnIntLeading )
80*cdf0e10cSrcweir         return false;
81*cdf0e10cSrcweir     if( mnExtLeading != r.mnExtLeading )
82*cdf0e10cSrcweir         return false;
83*cdf0e10cSrcweir     if( mnSlant      != r.mnSlant )
84*cdf0e10cSrcweir         return false;
85*cdf0e10cSrcweir 
86*cdf0e10cSrcweir     return true;
87*cdf0e10cSrcweir }
88*cdf0e10cSrcweir 
89*cdf0e10cSrcweir // =======================================================================
90*cdf0e10cSrcweir 
91*cdf0e10cSrcweir FontInfo::FontInfo()
92*cdf0e10cSrcweir :   mpImplMetric( new ImplFontMetric )
93*cdf0e10cSrcweir {}
94*cdf0e10cSrcweir 
95*cdf0e10cSrcweir // -----------------------------------------------------------------------
96*cdf0e10cSrcweir 
97*cdf0e10cSrcweir FontInfo::FontInfo( const FontInfo& rInfo )
98*cdf0e10cSrcweir :  Font( rInfo )
99*cdf0e10cSrcweir {
100*cdf0e10cSrcweir     mpImplMetric = rInfo.mpImplMetric;
101*cdf0e10cSrcweir     mpImplMetric->AddReference();
102*cdf0e10cSrcweir }
103*cdf0e10cSrcweir 
104*cdf0e10cSrcweir // -----------------------------------------------------------------------
105*cdf0e10cSrcweir 
106*cdf0e10cSrcweir FontInfo::~FontInfo()
107*cdf0e10cSrcweir {
108*cdf0e10cSrcweir     mpImplMetric->DeReference();
109*cdf0e10cSrcweir }
110*cdf0e10cSrcweir 
111*cdf0e10cSrcweir // -----------------------------------------------------------------------
112*cdf0e10cSrcweir 
113*cdf0e10cSrcweir FontInfo& FontInfo::operator=( const FontInfo& rInfo )
114*cdf0e10cSrcweir {
115*cdf0e10cSrcweir     Font::operator=( rInfo );
116*cdf0e10cSrcweir 
117*cdf0e10cSrcweir     if( mpImplMetric != rInfo.mpImplMetric )
118*cdf0e10cSrcweir     {
119*cdf0e10cSrcweir         mpImplMetric->DeReference();
120*cdf0e10cSrcweir         mpImplMetric = rInfo.mpImplMetric;
121*cdf0e10cSrcweir         mpImplMetric->AddReference();
122*cdf0e10cSrcweir     }
123*cdf0e10cSrcweir 
124*cdf0e10cSrcweir     return *this;
125*cdf0e10cSrcweir }
126*cdf0e10cSrcweir 
127*cdf0e10cSrcweir // -----------------------------------------------------------------------
128*cdf0e10cSrcweir 
129*cdf0e10cSrcweir sal_Bool FontInfo::operator==( const FontInfo& rInfo ) const
130*cdf0e10cSrcweir {
131*cdf0e10cSrcweir     if( !Font::operator==( rInfo ) )
132*cdf0e10cSrcweir         return sal_False;
133*cdf0e10cSrcweir     if( mpImplMetric == rInfo.mpImplMetric )
134*cdf0e10cSrcweir         return sal_True;
135*cdf0e10cSrcweir     if( *mpImplMetric == *rInfo.mpImplMetric  )
136*cdf0e10cSrcweir         return sal_True;
137*cdf0e10cSrcweir     return sal_False;
138*cdf0e10cSrcweir }
139*cdf0e10cSrcweir 
140*cdf0e10cSrcweir // -----------------------------------------------------------------------
141*cdf0e10cSrcweir 
142*cdf0e10cSrcweir FontType FontInfo::GetType() const
143*cdf0e10cSrcweir {
144*cdf0e10cSrcweir     return (mpImplMetric->IsScalable() ? TYPE_SCALABLE : TYPE_RASTER);
145*cdf0e10cSrcweir }
146*cdf0e10cSrcweir 
147*cdf0e10cSrcweir // -----------------------------------------------------------------------
148*cdf0e10cSrcweir 
149*cdf0e10cSrcweir sal_Bool FontInfo::IsDeviceFont() const
150*cdf0e10cSrcweir {
151*cdf0e10cSrcweir     return mpImplMetric->IsDeviceFont();
152*cdf0e10cSrcweir }
153*cdf0e10cSrcweir 
154*cdf0e10cSrcweir // -----------------------------------------------------------------------
155*cdf0e10cSrcweir 
156*cdf0e10cSrcweir sal_Bool FontInfo::SupportsLatin() const
157*cdf0e10cSrcweir {
158*cdf0e10cSrcweir     return mpImplMetric->SupportsLatin();
159*cdf0e10cSrcweir }
160*cdf0e10cSrcweir 
161*cdf0e10cSrcweir // -----------------------------------------------------------------------
162*cdf0e10cSrcweir 
163*cdf0e10cSrcweir sal_Bool FontInfo::SupportsCJK() const
164*cdf0e10cSrcweir {
165*cdf0e10cSrcweir     return mpImplMetric->SupportsCJK();
166*cdf0e10cSrcweir }
167*cdf0e10cSrcweir 
168*cdf0e10cSrcweir // -----------------------------------------------------------------------
169*cdf0e10cSrcweir 
170*cdf0e10cSrcweir sal_Bool FontInfo::SupportsCTL() const
171*cdf0e10cSrcweir {
172*cdf0e10cSrcweir     return mpImplMetric->SupportsCTL();
173*cdf0e10cSrcweir }
174*cdf0e10cSrcweir 
175*cdf0e10cSrcweir // =======================================================================
176*cdf0e10cSrcweir 
177*cdf0e10cSrcweir FontMetric::FontMetric( const FontMetric& rMetric )
178*cdf0e10cSrcweir :    FontInfo( rMetric )
179*cdf0e10cSrcweir {}
180*cdf0e10cSrcweir 
181*cdf0e10cSrcweir // -----------------------------------------------------------------------
182*cdf0e10cSrcweir 
183*cdf0e10cSrcweir long FontMetric::GetAscent() const
184*cdf0e10cSrcweir {
185*cdf0e10cSrcweir     return mpImplMetric->GetAscent();
186*cdf0e10cSrcweir }
187*cdf0e10cSrcweir 
188*cdf0e10cSrcweir // -----------------------------------------------------------------------
189*cdf0e10cSrcweir 
190*cdf0e10cSrcweir long FontMetric::GetDescent() const
191*cdf0e10cSrcweir {
192*cdf0e10cSrcweir     return mpImplMetric->GetDescent();
193*cdf0e10cSrcweir }
194*cdf0e10cSrcweir 
195*cdf0e10cSrcweir // -----------------------------------------------------------------------
196*cdf0e10cSrcweir 
197*cdf0e10cSrcweir long FontMetric::GetIntLeading() const
198*cdf0e10cSrcweir {
199*cdf0e10cSrcweir     return mpImplMetric->GetIntLeading();
200*cdf0e10cSrcweir }
201*cdf0e10cSrcweir 
202*cdf0e10cSrcweir // -----------------------------------------------------------------------
203*cdf0e10cSrcweir 
204*cdf0e10cSrcweir long FontMetric::GetExtLeading() const
205*cdf0e10cSrcweir {
206*cdf0e10cSrcweir     return mpImplMetric->GetExtLeading();
207*cdf0e10cSrcweir }
208*cdf0e10cSrcweir 
209*cdf0e10cSrcweir // -----------------------------------------------------------------------
210*cdf0e10cSrcweir 
211*cdf0e10cSrcweir long FontMetric::GetLineHeight() const
212*cdf0e10cSrcweir {
213*cdf0e10cSrcweir     return mpImplMetric->GetLineHeight();
214*cdf0e10cSrcweir }
215*cdf0e10cSrcweir 
216*cdf0e10cSrcweir // -----------------------------------------------------------------------
217*cdf0e10cSrcweir 
218*cdf0e10cSrcweir long FontMetric::GetSlant() const
219*cdf0e10cSrcweir {
220*cdf0e10cSrcweir     return mpImplMetric->GetSlant();
221*cdf0e10cSrcweir }
222*cdf0e10cSrcweir 
223*cdf0e10cSrcweir // -----------------------------------------------------------------------
224*cdf0e10cSrcweir 
225*cdf0e10cSrcweir FontMetric& FontMetric::operator =( const FontMetric& rMetric )
226*cdf0e10cSrcweir {
227*cdf0e10cSrcweir     FontInfo::operator=( rMetric );
228*cdf0e10cSrcweir     return *this;
229*cdf0e10cSrcweir }
230*cdf0e10cSrcweir 
231*cdf0e10cSrcweir // -----------------------------------------------------------------------
232*cdf0e10cSrcweir 
233*cdf0e10cSrcweir sal_Bool FontMetric::operator==( const FontMetric& rMetric ) const
234*cdf0e10cSrcweir {
235*cdf0e10cSrcweir     return FontInfo::operator==( rMetric );
236*cdf0e10cSrcweir }
237*cdf0e10cSrcweir 
238*cdf0e10cSrcweir // =======================================================================
239*cdf0e10cSrcweir 
240*cdf0e10cSrcweir CmapResult::CmapResult( bool bSymbolic,
241*cdf0e10cSrcweir 	const sal_uInt32* pRangeCodes, int nRangeCount,
242*cdf0e10cSrcweir 	const int* pStartGlyphs, const sal_uInt16* pExtraGlyphIds )
243*cdf0e10cSrcweir :	mpRangeCodes( pRangeCodes)
244*cdf0e10cSrcweir ,	mpStartGlyphs( pStartGlyphs)
245*cdf0e10cSrcweir ,	mpGlyphIds( pExtraGlyphIds)
246*cdf0e10cSrcweir ,	mnRangeCount( nRangeCount)
247*cdf0e10cSrcweir ,	mbSymbolic( bSymbolic)
248*cdf0e10cSrcweir ,	mbRecoded( false)
249*cdf0e10cSrcweir {}
250*cdf0e10cSrcweir 
251*cdf0e10cSrcweir // =======================================================================
252*cdf0e10cSrcweir 
253*cdf0e10cSrcweir ImplFontCharMap::ImplFontCharMap( const CmapResult& rCR )
254*cdf0e10cSrcweir :   mpRangeCodes( rCR.mpRangeCodes )
255*cdf0e10cSrcweir ,   mpStartGlyphs( rCR.mpStartGlyphs )
256*cdf0e10cSrcweir ,   mpGlyphIds( rCR.mpGlyphIds )
257*cdf0e10cSrcweir ,   mnRangeCount( rCR.mnRangeCount )
258*cdf0e10cSrcweir ,   mnCharCount( 0 )
259*cdf0e10cSrcweir ,   mnRefCount( 0 )
260*cdf0e10cSrcweir {
261*cdf0e10cSrcweir     const sal_uInt32* pRangePtr = mpRangeCodes;
262*cdf0e10cSrcweir     for( int i = mnRangeCount; --i >= 0; pRangePtr += 2 )
263*cdf0e10cSrcweir     {
264*cdf0e10cSrcweir         sal_uInt32 cFirst = pRangePtr[0];
265*cdf0e10cSrcweir         sal_uInt32 cLast  = pRangePtr[1];
266*cdf0e10cSrcweir         mnCharCount += cLast - cFirst;
267*cdf0e10cSrcweir     }
268*cdf0e10cSrcweir }
269*cdf0e10cSrcweir 
270*cdf0e10cSrcweir static ImplFontCharMap* pDefaultUnicodeImplFontCharMap = NULL;
271*cdf0e10cSrcweir static ImplFontCharMap* pDefaultSymbolImplFontCharMap = NULL;
272*cdf0e10cSrcweir static const sal_uInt32 aDefaultUnicodeRanges[] = {0x0020,0xD800, 0xE000,0xFFF0};
273*cdf0e10cSrcweir static const sal_uInt32 aDefaultSymbolRanges[] = {0x0020,0x0100, 0xF020,0xF100};
274*cdf0e10cSrcweir 
275*cdf0e10cSrcweir // -----------------------------------------------------------------------
276*cdf0e10cSrcweir 
277*cdf0e10cSrcweir bool ImplFontCharMap::IsDefaultMap() const
278*cdf0e10cSrcweir {
279*cdf0e10cSrcweir 	const bool bIsDefault = (mpRangeCodes == aDefaultUnicodeRanges) || (mpRangeCodes == aDefaultSymbolRanges);
280*cdf0e10cSrcweir 	return bIsDefault;
281*cdf0e10cSrcweir }
282*cdf0e10cSrcweir 
283*cdf0e10cSrcweir // -----------------------------------------------------------------------
284*cdf0e10cSrcweir 
285*cdf0e10cSrcweir ImplFontCharMap::~ImplFontCharMap()
286*cdf0e10cSrcweir {
287*cdf0e10cSrcweir 	if( IsDefaultMap() )
288*cdf0e10cSrcweir 		return;
289*cdf0e10cSrcweir 	delete[] mpRangeCodes;
290*cdf0e10cSrcweir 	delete[] mpStartGlyphs;
291*cdf0e10cSrcweir 	delete[] mpGlyphIds;
292*cdf0e10cSrcweir  }
293*cdf0e10cSrcweir 
294*cdf0e10cSrcweir // -----------------------------------------------------------------------
295*cdf0e10cSrcweir 
296*cdf0e10cSrcweir namespace
297*cdf0e10cSrcweir {
298*cdf0e10cSrcweir     ImplFontCharMap *GetDefaultUnicodeMap()
299*cdf0e10cSrcweir     {
300*cdf0e10cSrcweir         if( !pDefaultUnicodeImplFontCharMap )
301*cdf0e10cSrcweir         {
302*cdf0e10cSrcweir             const sal_uInt32* pRangeCodes = aDefaultUnicodeRanges;
303*cdf0e10cSrcweir             int nCodesCount = sizeof(aDefaultUnicodeRanges) / sizeof(*pRangeCodes);
304*cdf0e10cSrcweir             CmapResult aDefaultCR( false, pRangeCodes, nCodesCount/2 );
305*cdf0e10cSrcweir             pDefaultUnicodeImplFontCharMap = new ImplFontCharMap( aDefaultCR );
306*cdf0e10cSrcweir             pDefaultUnicodeImplFontCharMap->AddReference();
307*cdf0e10cSrcweir         }
308*cdf0e10cSrcweir 
309*cdf0e10cSrcweir         return pDefaultUnicodeImplFontCharMap;
310*cdf0e10cSrcweir     }
311*cdf0e10cSrcweir 
312*cdf0e10cSrcweir     ImplFontCharMap *GetDefaultSymbolMap()
313*cdf0e10cSrcweir     {
314*cdf0e10cSrcweir         if( !pDefaultSymbolImplFontCharMap )
315*cdf0e10cSrcweir         {
316*cdf0e10cSrcweir             const sal_uInt32* pRangeCodes = aDefaultSymbolRanges;
317*cdf0e10cSrcweir             int nCodesCount = sizeof(aDefaultSymbolRanges) / sizeof(*pRangeCodes);
318*cdf0e10cSrcweir             CmapResult aDefaultCR( true, pRangeCodes, nCodesCount/2 );
319*cdf0e10cSrcweir             pDefaultSymbolImplFontCharMap = new ImplFontCharMap( aDefaultCR );
320*cdf0e10cSrcweir             pDefaultSymbolImplFontCharMap->AddReference();
321*cdf0e10cSrcweir         }
322*cdf0e10cSrcweir 
323*cdf0e10cSrcweir         return pDefaultSymbolImplFontCharMap;
324*cdf0e10cSrcweir     }
325*cdf0e10cSrcweir }
326*cdf0e10cSrcweir 
327*cdf0e10cSrcweir ImplFontCharMap* ImplFontCharMap::GetDefaultMap( bool bSymbols)
328*cdf0e10cSrcweir {
329*cdf0e10cSrcweir     return bSymbols ? GetDefaultSymbolMap() : GetDefaultUnicodeMap();
330*cdf0e10cSrcweir }
331*cdf0e10cSrcweir 
332*cdf0e10cSrcweir // -----------------------------------------------------------------------
333*cdf0e10cSrcweir 
334*cdf0e10cSrcweir void ImplFontCharMap::AddReference( void ) const
335*cdf0e10cSrcweir {
336*cdf0e10cSrcweir     // TODO: disable refcounting on the default maps?
337*cdf0e10cSrcweir     ++mnRefCount;
338*cdf0e10cSrcweir }
339*cdf0e10cSrcweir 
340*cdf0e10cSrcweir // -----------------------------------------------------------------------
341*cdf0e10cSrcweir 
342*cdf0e10cSrcweir void ImplFontCharMap::DeReference( void ) const
343*cdf0e10cSrcweir {
344*cdf0e10cSrcweir     if( --mnRefCount <= 0 )
345*cdf0e10cSrcweir         if( (this != pDefaultUnicodeImplFontCharMap) && (this != pDefaultSymbolImplFontCharMap) )
346*cdf0e10cSrcweir             delete this;
347*cdf0e10cSrcweir }
348*cdf0e10cSrcweir 
349*cdf0e10cSrcweir // -----------------------------------------------------------------------
350*cdf0e10cSrcweir 
351*cdf0e10cSrcweir int ImplFontCharMap::GetCharCount() const
352*cdf0e10cSrcweir {
353*cdf0e10cSrcweir     return mnCharCount;
354*cdf0e10cSrcweir }
355*cdf0e10cSrcweir 
356*cdf0e10cSrcweir // -----------------------------------------------------------------------
357*cdf0e10cSrcweir 
358*cdf0e10cSrcweir int ImplFontCharMap::ImplFindRangeIndex( sal_uInt32 cChar ) const
359*cdf0e10cSrcweir {
360*cdf0e10cSrcweir     int nLower = 0;
361*cdf0e10cSrcweir     int nMid   = mnRangeCount;
362*cdf0e10cSrcweir     int nUpper = 2 * mnRangeCount - 1;
363*cdf0e10cSrcweir     while( nLower < nUpper )
364*cdf0e10cSrcweir     {
365*cdf0e10cSrcweir         if( cChar >= mpRangeCodes[ nMid ] )
366*cdf0e10cSrcweir             nLower = nMid;
367*cdf0e10cSrcweir         else
368*cdf0e10cSrcweir             nUpper = nMid - 1;
369*cdf0e10cSrcweir         nMid = (nLower + nUpper + 1) / 2;
370*cdf0e10cSrcweir     }
371*cdf0e10cSrcweir 
372*cdf0e10cSrcweir     return nMid;
373*cdf0e10cSrcweir }
374*cdf0e10cSrcweir 
375*cdf0e10cSrcweir // -----------------------------------------------------------------------
376*cdf0e10cSrcweir 
377*cdf0e10cSrcweir bool ImplFontCharMap::HasChar( sal_uInt32 cChar ) const
378*cdf0e10cSrcweir {
379*cdf0e10cSrcweir     bool bHasChar = false;
380*cdf0e10cSrcweir 
381*cdf0e10cSrcweir     if( mpStartGlyphs  == NULL ) { // only the char-ranges are known
382*cdf0e10cSrcweir         const int nRange = ImplFindRangeIndex( cChar );
383*cdf0e10cSrcweir         if( nRange==0 && cChar<mpRangeCodes[0] )
384*cdf0e10cSrcweir             return false;
385*cdf0e10cSrcweir         bHasChar = ((nRange & 1) == 0); // inside a range
386*cdf0e10cSrcweir     } else { // glyph mapping is available
387*cdf0e10cSrcweir         const int nGlyphIndex = GetGlyphIndex( cChar );
388*cdf0e10cSrcweir         bHasChar = (nGlyphIndex != 0); // not the notdef-glyph
389*cdf0e10cSrcweir     }
390*cdf0e10cSrcweir 
391*cdf0e10cSrcweir     return bHasChar;
392*cdf0e10cSrcweir }
393*cdf0e10cSrcweir 
394*cdf0e10cSrcweir // -----------------------------------------------------------------------
395*cdf0e10cSrcweir 
396*cdf0e10cSrcweir int ImplFontCharMap::GetGlyphIndex( sal_uInt32 cChar ) const
397*cdf0e10cSrcweir {
398*cdf0e10cSrcweir     // return -1 if the object doesn't know the glyph ids
399*cdf0e10cSrcweir     if( !mpStartGlyphs )
400*cdf0e10cSrcweir         return -1;
401*cdf0e10cSrcweir 
402*cdf0e10cSrcweir     // return 0 if the unicode doesn't have a matching glyph
403*cdf0e10cSrcweir     int nRange = ImplFindRangeIndex( cChar );
404*cdf0e10cSrcweir     // check that we are inside any range
405*cdf0e10cSrcweir     if( (nRange == 0) && (cChar < mpRangeCodes[0]) ) {
406*cdf0e10cSrcweir         // symbol aliasing gives symbol fonts a second chance
407*cdf0e10cSrcweir         const bool bSymbolic = (mpRangeCodes[0]>=0xF000) & (mpRangeCodes[1]<=0xF0FF);
408*cdf0e10cSrcweir         if( !bSymbolic )
409*cdf0e10cSrcweir             return 0;
410*cdf0e10cSrcweir         // check for symbol aliasing (U+00xx <-> U+F0xx)
411*cdf0e10cSrcweir         cChar |= 0xF000;
412*cdf0e10cSrcweir         nRange = ImplFindRangeIndex( cChar );
413*cdf0e10cSrcweir     }
414*cdf0e10cSrcweir     // check that we are inside a range
415*cdf0e10cSrcweir     if( (nRange & 1) != 0 )
416*cdf0e10cSrcweir         return 0;
417*cdf0e10cSrcweir 
418*cdf0e10cSrcweir     // get glyph index directly or indirectly
419*cdf0e10cSrcweir     int nGlyphIndex = cChar - mpRangeCodes[ nRange ];
420*cdf0e10cSrcweir     const int nStartIndex = mpStartGlyphs[ nRange/2 ];
421*cdf0e10cSrcweir     if( nStartIndex >= 0 ) {
422*cdf0e10cSrcweir         // the glyph index can be calculated
423*cdf0e10cSrcweir         nGlyphIndex += nStartIndex;
424*cdf0e10cSrcweir     } else {
425*cdf0e10cSrcweir         // the glyphid array has the glyph index
426*cdf0e10cSrcweir         nGlyphIndex = mpGlyphIds[ nGlyphIndex - nStartIndex ];
427*cdf0e10cSrcweir     }
428*cdf0e10cSrcweir 
429*cdf0e10cSrcweir     return nGlyphIndex;
430*cdf0e10cSrcweir }
431*cdf0e10cSrcweir 
432*cdf0e10cSrcweir // -----------------------------------------------------------------------
433*cdf0e10cSrcweir 
434*cdf0e10cSrcweir // returns the number of chars supported by the font, which
435*cdf0e10cSrcweir // are inside the unicode range from cMin to cMax (inclusive)
436*cdf0e10cSrcweir int ImplFontCharMap::CountCharsInRange( sal_uInt32 cMin, sal_uInt32 cMax ) const
437*cdf0e10cSrcweir {
438*cdf0e10cSrcweir     int nCount = 0;
439*cdf0e10cSrcweir 
440*cdf0e10cSrcweir     // find and adjust range and char count for cMin
441*cdf0e10cSrcweir     int nRangeMin = ImplFindRangeIndex( cMin );
442*cdf0e10cSrcweir     if( nRangeMin & 1 )
443*cdf0e10cSrcweir         ++nRangeMin;
444*cdf0e10cSrcweir     else if( cMin > mpRangeCodes[ nRangeMin ] )
445*cdf0e10cSrcweir         nCount -= cMin - mpRangeCodes[ nRangeMin ];
446*cdf0e10cSrcweir 
447*cdf0e10cSrcweir     // find and adjust range and char count for cMax
448*cdf0e10cSrcweir     int nRangeMax = ImplFindRangeIndex( cMax );
449*cdf0e10cSrcweir     if( nRangeMax & 1 )
450*cdf0e10cSrcweir         --nRangeMax;
451*cdf0e10cSrcweir     else
452*cdf0e10cSrcweir         nCount -= mpRangeCodes[ nRangeMax+1 ] - cMax - 1;
453*cdf0e10cSrcweir 
454*cdf0e10cSrcweir     // count chars in complete ranges between cMin and cMax
455*cdf0e10cSrcweir     for( int i = nRangeMin; i <= nRangeMax; i+=2 )
456*cdf0e10cSrcweir         nCount += mpRangeCodes[i+1] - mpRangeCodes[i];
457*cdf0e10cSrcweir 
458*cdf0e10cSrcweir     return nCount;
459*cdf0e10cSrcweir }
460*cdf0e10cSrcweir 
461*cdf0e10cSrcweir // -----------------------------------------------------------------------
462*cdf0e10cSrcweir 
463*cdf0e10cSrcweir sal_uInt32 ImplFontCharMap::GetFirstChar() const
464*cdf0e10cSrcweir {
465*cdf0e10cSrcweir     return mpRangeCodes[0];
466*cdf0e10cSrcweir }
467*cdf0e10cSrcweir 
468*cdf0e10cSrcweir // -----------------------------------------------------------------------
469*cdf0e10cSrcweir 
470*cdf0e10cSrcweir sal_uInt32 ImplFontCharMap::GetLastChar() const
471*cdf0e10cSrcweir {
472*cdf0e10cSrcweir     return (mpRangeCodes[ 2*mnRangeCount-1 ] - 1);
473*cdf0e10cSrcweir }
474*cdf0e10cSrcweir 
475*cdf0e10cSrcweir // -----------------------------------------------------------------------
476*cdf0e10cSrcweir 
477*cdf0e10cSrcweir sal_uInt32 ImplFontCharMap::GetNextChar( sal_uInt32 cChar ) const
478*cdf0e10cSrcweir {
479*cdf0e10cSrcweir     if( cChar < GetFirstChar() )
480*cdf0e10cSrcweir         return GetFirstChar();
481*cdf0e10cSrcweir     if( cChar >= GetLastChar() )
482*cdf0e10cSrcweir         return GetLastChar();
483*cdf0e10cSrcweir 
484*cdf0e10cSrcweir     int nRange = ImplFindRangeIndex( cChar + 1 );
485*cdf0e10cSrcweir     if( nRange & 1 )                       // outside of range?
486*cdf0e10cSrcweir         return mpRangeCodes[ nRange + 1 ]; // => first in next range
487*cdf0e10cSrcweir     return (cChar + 1);
488*cdf0e10cSrcweir }
489*cdf0e10cSrcweir 
490*cdf0e10cSrcweir // -----------------------------------------------------------------------
491*cdf0e10cSrcweir 
492*cdf0e10cSrcweir sal_uInt32 ImplFontCharMap::GetPrevChar( sal_uInt32 cChar ) const
493*cdf0e10cSrcweir {
494*cdf0e10cSrcweir     if( cChar <= GetFirstChar() )
495*cdf0e10cSrcweir         return GetFirstChar();
496*cdf0e10cSrcweir     if( cChar > GetLastChar() )
497*cdf0e10cSrcweir         return GetLastChar();
498*cdf0e10cSrcweir 
499*cdf0e10cSrcweir     int nRange = ImplFindRangeIndex( cChar - 1 );
500*cdf0e10cSrcweir     if( nRange & 1 )                            // outside a range?
501*cdf0e10cSrcweir         return (mpRangeCodes[ nRange ] - 1);    // => last in prev range
502*cdf0e10cSrcweir     return (cChar - 1);
503*cdf0e10cSrcweir }
504*cdf0e10cSrcweir 
505*cdf0e10cSrcweir // -----------------------------------------------------------------------
506*cdf0e10cSrcweir 
507*cdf0e10cSrcweir int ImplFontCharMap::GetIndexFromChar( sal_uInt32 cChar ) const
508*cdf0e10cSrcweir {
509*cdf0e10cSrcweir     // TODO: improve linear walk?
510*cdf0e10cSrcweir     int nCharIndex = 0;
511*cdf0e10cSrcweir     const sal_uInt32* pRange = &mpRangeCodes[0];
512*cdf0e10cSrcweir     for( int i = 0; i < mnRangeCount; ++i )
513*cdf0e10cSrcweir     {
514*cdf0e10cSrcweir         sal_uInt32 cFirst = *(pRange++);
515*cdf0e10cSrcweir         sal_uInt32 cLast  = *(pRange++);
516*cdf0e10cSrcweir         if( cChar >= cLast )
517*cdf0e10cSrcweir             nCharIndex += cLast - cFirst;
518*cdf0e10cSrcweir         else if( cChar >= cFirst )
519*cdf0e10cSrcweir             return nCharIndex + (cChar - cFirst);
520*cdf0e10cSrcweir         else
521*cdf0e10cSrcweir             break;
522*cdf0e10cSrcweir     }
523*cdf0e10cSrcweir 
524*cdf0e10cSrcweir     return -1;
525*cdf0e10cSrcweir }
526*cdf0e10cSrcweir 
527*cdf0e10cSrcweir // -----------------------------------------------------------------------
528*cdf0e10cSrcweir 
529*cdf0e10cSrcweir sal_uInt32 ImplFontCharMap::GetCharFromIndex( int nCharIndex ) const
530*cdf0e10cSrcweir {
531*cdf0e10cSrcweir     // TODO: improve linear walk?
532*cdf0e10cSrcweir     const sal_uInt32* pRange = &mpRangeCodes[0];
533*cdf0e10cSrcweir     for( int i = 0; i < mnRangeCount; ++i )
534*cdf0e10cSrcweir     {
535*cdf0e10cSrcweir         sal_uInt32 cFirst = *(pRange++);
536*cdf0e10cSrcweir         sal_uInt32 cLast  = *(pRange++);
537*cdf0e10cSrcweir         nCharIndex -= cLast - cFirst;
538*cdf0e10cSrcweir         if( nCharIndex < 0 )
539*cdf0e10cSrcweir             return (cLast + nCharIndex);
540*cdf0e10cSrcweir     }
541*cdf0e10cSrcweir 
542*cdf0e10cSrcweir     // we can only get here with an out-of-bounds charindex
543*cdf0e10cSrcweir     return mpRangeCodes[0];
544*cdf0e10cSrcweir }
545*cdf0e10cSrcweir 
546*cdf0e10cSrcweir // =======================================================================
547*cdf0e10cSrcweir 
548*cdf0e10cSrcweir static unsigned GetUInt( const unsigned char* p ) { return((p[0]<<24)+(p[1]<<16)+(p[2]<<8)+p[3]);}
549*cdf0e10cSrcweir static unsigned GetUShort( const unsigned char* p ){ return((p[0]<<8) | p[1]);}
550*cdf0e10cSrcweir static int GetSShort( const unsigned char* p ){ return((static_cast<signed char>(p[0])<<8)|p[1]);}
551*cdf0e10cSrcweir 
552*cdf0e10cSrcweir // TODO: move CMAP parsing directly into the ImplFontCharMap class
553*cdf0e10cSrcweir bool ParseCMAP( const unsigned char* pCmap, int nLength, CmapResult& rResult )
554*cdf0e10cSrcweir {
555*cdf0e10cSrcweir     rResult.mpRangeCodes = NULL;
556*cdf0e10cSrcweir     rResult.mpStartGlyphs= NULL;
557*cdf0e10cSrcweir     rResult.mpGlyphIds	 = NULL;
558*cdf0e10cSrcweir     rResult.mnRangeCount = 0;
559*cdf0e10cSrcweir     rResult.mbRecoded    = false;
560*cdf0e10cSrcweir     rResult.mbSymbolic   = false;
561*cdf0e10cSrcweir 
562*cdf0e10cSrcweir     // parse the table header and check for validity
563*cdf0e10cSrcweir     if( !pCmap || (nLength < 24) )
564*cdf0e10cSrcweir         return false;
565*cdf0e10cSrcweir 
566*cdf0e10cSrcweir     if( GetUShort( pCmap ) != 0x0000 ) // simple check for CMAP corruption
567*cdf0e10cSrcweir         return false;
568*cdf0e10cSrcweir 
569*cdf0e10cSrcweir     int nSubTables = GetUShort( pCmap + 2 );
570*cdf0e10cSrcweir     if( (nSubTables <= 0) || (nLength < (24 + 8*nSubTables)) )
571*cdf0e10cSrcweir         return false;
572*cdf0e10cSrcweir 
573*cdf0e10cSrcweir     // find the most interesting subtable in the CMAP
574*cdf0e10cSrcweir     rtl_TextEncoding eRecodeFrom = RTL_TEXTENCODING_UNICODE;
575*cdf0e10cSrcweir     int nOffset = 0;
576*cdf0e10cSrcweir     int nFormat = -1;
577*cdf0e10cSrcweir     int nBestVal = 0;
578*cdf0e10cSrcweir     for( const unsigned char* p = pCmap + 4; --nSubTables >= 0; p += 8 )
579*cdf0e10cSrcweir     {
580*cdf0e10cSrcweir         int nPlatform = GetUShort( p );
581*cdf0e10cSrcweir         int nEncoding = GetUShort( p+2 );
582*cdf0e10cSrcweir         int nPlatformEncoding = (nPlatform << 8) + nEncoding;
583*cdf0e10cSrcweir 
584*cdf0e10cSrcweir         int nValue;
585*cdf0e10cSrcweir         rtl_TextEncoding eTmpEncoding = RTL_TEXTENCODING_UNICODE;
586*cdf0e10cSrcweir         switch( nPlatformEncoding )
587*cdf0e10cSrcweir         {
588*cdf0e10cSrcweir             case 0x000: nValue = 20; break;                             // Unicode 1.0
589*cdf0e10cSrcweir             case 0x001: nValue = 21; break;                             // Unicode 1.1
590*cdf0e10cSrcweir             case 0x002: nValue = 22; break;                             // iso10646_1993
591*cdf0e10cSrcweir             case 0x003: nValue = 23; break;                             // UCS-2
592*cdf0e10cSrcweir             case 0x004: nValue = 24; break;                             // UCS-4
593*cdf0e10cSrcweir             case 0x100: nValue = 22; break;                             // Mac Unicode<2.0
594*cdf0e10cSrcweir             case 0x103: nValue = 23; break;                             // Mac Unicode>2.0
595*cdf0e10cSrcweir             case 0x300: nValue =  5; rResult.mbSymbolic = true; break;  // Win Symbol
596*cdf0e10cSrcweir             case 0x301: nValue = 28; break;                             // Win UCS-2
597*cdf0e10cSrcweir             case 0x30A: nValue = 29; break;                             // Win-UCS-4
598*cdf0e10cSrcweir             case 0x302: nValue = 11; eTmpEncoding = RTL_TEXTENCODING_SHIFT_JIS; break;
599*cdf0e10cSrcweir             case 0x303: nValue = 12; eTmpEncoding = RTL_TEXTENCODING_GB_18030; break;
600*cdf0e10cSrcweir             case 0x304: nValue = 11; eTmpEncoding = RTL_TEXTENCODING_BIG5; break;
601*cdf0e10cSrcweir             case 0x305: nValue = 11; eTmpEncoding = RTL_TEXTENCODING_MS_949; break;
602*cdf0e10cSrcweir             case 0x306: nValue = 11; eTmpEncoding = RTL_TEXTENCODING_MS_1361; break;
603*cdf0e10cSrcweir             default:    nValue = 0; break;
604*cdf0e10cSrcweir         }
605*cdf0e10cSrcweir 
606*cdf0e10cSrcweir         if( nValue <= 0 )   // ignore unknown encodings
607*cdf0e10cSrcweir             continue;
608*cdf0e10cSrcweir 
609*cdf0e10cSrcweir         int nTmpOffset = GetUInt( p+4 );
610*cdf0e10cSrcweir         int nTmpFormat = GetUShort( pCmap + nTmpOffset );
611*cdf0e10cSrcweir         if( nTmpFormat == 12 )                  // 32bit code -> glyph map format
612*cdf0e10cSrcweir             nValue += 3;
613*cdf0e10cSrcweir         else if( nTmpFormat != 4 )              // 16bit code -> glyph map format
614*cdf0e10cSrcweir             continue;                           // ignore other formats
615*cdf0e10cSrcweir 
616*cdf0e10cSrcweir         if( nBestVal < nValue )
617*cdf0e10cSrcweir         {
618*cdf0e10cSrcweir             nBestVal = nValue;
619*cdf0e10cSrcweir             nOffset = nTmpOffset;
620*cdf0e10cSrcweir             nFormat = nTmpFormat;
621*cdf0e10cSrcweir             eRecodeFrom = eTmpEncoding;
622*cdf0e10cSrcweir         }
623*cdf0e10cSrcweir     }
624*cdf0e10cSrcweir 
625*cdf0e10cSrcweir     // parse the best CMAP subtable
626*cdf0e10cSrcweir     int nRangeCount = 0;
627*cdf0e10cSrcweir     sal_uInt32* pCodePairs = NULL;
628*cdf0e10cSrcweir     int* pStartGlyphs = NULL;
629*cdf0e10cSrcweir 
630*cdf0e10cSrcweir     typedef std::vector<sal_uInt16> U16Vector;
631*cdf0e10cSrcweir     U16Vector aGlyphIdArray;
632*cdf0e10cSrcweir     aGlyphIdArray.reserve( 0x1000 );
633*cdf0e10cSrcweir     aGlyphIdArray.push_back( 0 );
634*cdf0e10cSrcweir 
635*cdf0e10cSrcweir     // format 4, the most common 16bit char mapping table
636*cdf0e10cSrcweir     if( (nFormat == 4) && ((nOffset+16) < nLength) )
637*cdf0e10cSrcweir     {
638*cdf0e10cSrcweir         int nSegCountX2 = GetUShort( pCmap + nOffset + 6 );
639*cdf0e10cSrcweir         nRangeCount = nSegCountX2/2 - 1;
640*cdf0e10cSrcweir         pCodePairs = new sal_uInt32[ nRangeCount * 2 ];
641*cdf0e10cSrcweir         pStartGlyphs = new int[ nRangeCount ];
642*cdf0e10cSrcweir         const unsigned char* pLimitBase = pCmap + nOffset + 14;
643*cdf0e10cSrcweir         const unsigned char* pBeginBase = pLimitBase + nSegCountX2 + 2;
644*cdf0e10cSrcweir         const unsigned char* pDeltaBase = pBeginBase + nSegCountX2;
645*cdf0e10cSrcweir         const unsigned char* pOffsetBase = pDeltaBase + nSegCountX2;
646*cdf0e10cSrcweir         sal_uInt32* pCP = pCodePairs;
647*cdf0e10cSrcweir         for( int i = 0; i < nRangeCount; ++i )
648*cdf0e10cSrcweir         {
649*cdf0e10cSrcweir             const sal_uInt32 cMinChar = GetUShort( pBeginBase + 2*i );
650*cdf0e10cSrcweir             const sal_uInt32 cMaxChar = GetUShort( pLimitBase + 2*i );
651*cdf0e10cSrcweir             const int nGlyphDelta  = GetSShort( pDeltaBase + 2*i );
652*cdf0e10cSrcweir             const int nRangeOffset = GetUShort( pOffsetBase + 2*i );
653*cdf0e10cSrcweir             if( cMinChar > cMaxChar )   // no sane font should trigger this
654*cdf0e10cSrcweir                 break;
655*cdf0e10cSrcweir             if( cMaxChar == 0xFFFF )
656*cdf0e10cSrcweir                 break;
657*cdf0e10cSrcweir             *(pCP++) = cMinChar;
658*cdf0e10cSrcweir             *(pCP++) = cMaxChar + 1;
659*cdf0e10cSrcweir             if( !nRangeOffset ) {
660*cdf0e10cSrcweir                 // glyphid can be calculated directly
661*cdf0e10cSrcweir                 pStartGlyphs[i] = (cMinChar + nGlyphDelta) & 0xFFFF;
662*cdf0e10cSrcweir             } else {
663*cdf0e10cSrcweir                 // update the glyphid-array with the glyphs in this range
664*cdf0e10cSrcweir                 pStartGlyphs[i] = -(int)aGlyphIdArray.size();
665*cdf0e10cSrcweir                 const unsigned char* pGlyphIdPtr = pOffsetBase + 2*i + nRangeOffset;
666*cdf0e10cSrcweir                 for( sal_uInt32 c = cMinChar; c <= cMaxChar; ++c, pGlyphIdPtr+=2 ) {
667*cdf0e10cSrcweir                     const int nGlyphIndex = GetUShort( pGlyphIdPtr ) + nGlyphDelta;
668*cdf0e10cSrcweir                     aGlyphIdArray.push_back( static_cast<sal_uInt16>(nGlyphIndex) );
669*cdf0e10cSrcweir                 }
670*cdf0e10cSrcweir             }
671*cdf0e10cSrcweir         }
672*cdf0e10cSrcweir         nRangeCount = (pCP - pCodePairs) / 2;
673*cdf0e10cSrcweir     }
674*cdf0e10cSrcweir     // format 12, the most common 32bit char mapping table
675*cdf0e10cSrcweir     else if( (nFormat == 12) && ((nOffset+16) < nLength) )
676*cdf0e10cSrcweir     {
677*cdf0e10cSrcweir         nRangeCount = GetUInt( pCmap + nOffset + 12 );
678*cdf0e10cSrcweir         pCodePairs = new sal_uInt32[ nRangeCount * 2 ];
679*cdf0e10cSrcweir         pStartGlyphs = new int[ nRangeCount ];
680*cdf0e10cSrcweir         const unsigned char* pGroup = pCmap + nOffset + 16;
681*cdf0e10cSrcweir         sal_uInt32* pCP = pCodePairs;
682*cdf0e10cSrcweir         for( int i = 0; i < nRangeCount; ++i )
683*cdf0e10cSrcweir         {
684*cdf0e10cSrcweir             sal_uInt32 cMinChar = GetUInt( pGroup + 0 );
685*cdf0e10cSrcweir             sal_uInt32 cMaxChar = GetUInt( pGroup + 4 );
686*cdf0e10cSrcweir             int nGlyphId = GetUInt( pGroup + 8 );
687*cdf0e10cSrcweir             pGroup += 12;
688*cdf0e10cSrcweir #if 0       // TODO: remove unicode baseplane clipping for UCS-4 support
689*cdf0e10cSrcweir             if( cMinChar > 0xFFFF )
690*cdf0e10cSrcweir                 continue;
691*cdf0e10cSrcweir             if( cMaxChar > 0xFFFF )
692*cdf0e10cSrcweir                 cMaxChar = 0xFFFF;
693*cdf0e10cSrcweir #else
694*cdf0e10cSrcweir             if( cMinChar > cMaxChar )   // no sane font should trigger this
695*cdf0e10cSrcweir                 break;
696*cdf0e10cSrcweir #endif
697*cdf0e10cSrcweir             *(pCP++) = cMinChar;
698*cdf0e10cSrcweir             *(pCP++) = cMaxChar + 1;
699*cdf0e10cSrcweir             pStartGlyphs[i] = nGlyphId;
700*cdf0e10cSrcweir         }
701*cdf0e10cSrcweir         nRangeCount = (pCP - pCodePairs) / 2;
702*cdf0e10cSrcweir     }
703*cdf0e10cSrcweir 
704*cdf0e10cSrcweir     // check if any subtable resulted in something usable
705*cdf0e10cSrcweir     if( nRangeCount <= 0 )
706*cdf0e10cSrcweir     {
707*cdf0e10cSrcweir         delete[] pCodePairs;
708*cdf0e10cSrcweir         delete[] pStartGlyphs;
709*cdf0e10cSrcweir 
710*cdf0e10cSrcweir         // even when no CMAP is available we know it for symbol fonts
711*cdf0e10cSrcweir         if( rResult.mbSymbolic )
712*cdf0e10cSrcweir         {
713*cdf0e10cSrcweir             pCodePairs = new sal_uInt32[4];
714*cdf0e10cSrcweir             pCodePairs[0] = 0x0020;    // aliased symbols
715*cdf0e10cSrcweir             pCodePairs[1] = 0x0100;
716*cdf0e10cSrcweir             pCodePairs[2] = 0xF020;    // original symbols
717*cdf0e10cSrcweir             pCodePairs[3] = 0xF100;
718*cdf0e10cSrcweir             rResult.mpRangeCodes = pCodePairs;
719*cdf0e10cSrcweir             rResult.mnRangeCount = 2;
720*cdf0e10cSrcweir             return true;
721*cdf0e10cSrcweir         }
722*cdf0e10cSrcweir 
723*cdf0e10cSrcweir         return false;
724*cdf0e10cSrcweir     }
725*cdf0e10cSrcweir 
726*cdf0e10cSrcweir     // recode the code ranges to their unicode encoded ranges if needed
727*cdf0e10cSrcweir     rtl_TextToUnicodeConverter aConverter = NULL;
728*cdf0e10cSrcweir     rtl_UnicodeToTextContext aCvtContext = NULL;
729*cdf0e10cSrcweir 
730*cdf0e10cSrcweir     rResult.mbRecoded = ( eRecodeFrom != RTL_TEXTENCODING_UNICODE );
731*cdf0e10cSrcweir     if( rResult.mbRecoded )
732*cdf0e10cSrcweir     {
733*cdf0e10cSrcweir         aConverter = rtl_createTextToUnicodeConverter( eRecodeFrom );
734*cdf0e10cSrcweir         aCvtContext = rtl_createTextToUnicodeContext( aConverter );
735*cdf0e10cSrcweir     }
736*cdf0e10cSrcweir 
737*cdf0e10cSrcweir     if( aConverter && aCvtContext )
738*cdf0e10cSrcweir     {
739*cdf0e10cSrcweir         // determine the set of supported unicodes from encoded ranges
740*cdf0e10cSrcweir         typedef std::set<sal_uInt32> IntSet;
741*cdf0e10cSrcweir         IntSet aSupportedUnicodes;
742*cdf0e10cSrcweir 
743*cdf0e10cSrcweir         static const int NINSIZE = 64;
744*cdf0e10cSrcweir         static const int NOUTSIZE = 64;
745*cdf0e10cSrcweir         sal_Char    cCharsInp[ NINSIZE ];
746*cdf0e10cSrcweir         sal_Unicode cCharsOut[ NOUTSIZE ];
747*cdf0e10cSrcweir         sal_uInt32* pCP = pCodePairs;
748*cdf0e10cSrcweir         for( int i = 0; i < nRangeCount; ++i )
749*cdf0e10cSrcweir         {
750*cdf0e10cSrcweir             sal_uInt32 cMin = *(pCP++);
751*cdf0e10cSrcweir             sal_uInt32 cEnd = *(pCP++);
752*cdf0e10cSrcweir             while( cMin < cEnd )
753*cdf0e10cSrcweir             {
754*cdf0e10cSrcweir                 int j = 0;
755*cdf0e10cSrcweir                 for(; (cMin < cEnd) && (j < NINSIZE); ++cMin )
756*cdf0e10cSrcweir                 {
757*cdf0e10cSrcweir                     if( cMin >= 0x0100 )
758*cdf0e10cSrcweir                         cCharsInp[ j++ ] = static_cast<sal_Char>(cMin >> 8);
759*cdf0e10cSrcweir                     if( (cMin >= 0x0100) || (cMin < 0x00A0)  )
760*cdf0e10cSrcweir                         cCharsInp[ j++ ] = static_cast<sal_Char>(cMin);
761*cdf0e10cSrcweir                 }
762*cdf0e10cSrcweir 
763*cdf0e10cSrcweir                 sal_uInt32 nCvtInfo;
764*cdf0e10cSrcweir                 sal_Size nSrcCvtBytes;
765*cdf0e10cSrcweir                 int nOutLen = rtl_convertTextToUnicode(
766*cdf0e10cSrcweir                     aConverter, aCvtContext,
767*cdf0e10cSrcweir                     cCharsInp, j, cCharsOut, NOUTSIZE,
768*cdf0e10cSrcweir                     RTL_TEXTTOUNICODE_FLAGS_INVALID_IGNORE
769*cdf0e10cSrcweir                     | RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_IGNORE,
770*cdf0e10cSrcweir                     &nCvtInfo, &nSrcCvtBytes );
771*cdf0e10cSrcweir 
772*cdf0e10cSrcweir                 for( j = 0; j < nOutLen; ++j )
773*cdf0e10cSrcweir                     aSupportedUnicodes.insert( cCharsOut[j] );
774*cdf0e10cSrcweir             }
775*cdf0e10cSrcweir         }
776*cdf0e10cSrcweir 
777*cdf0e10cSrcweir         rtl_destroyTextToUnicodeConverter( aCvtContext );
778*cdf0e10cSrcweir         rtl_destroyTextToUnicodeConverter( aConverter );
779*cdf0e10cSrcweir 
780*cdf0e10cSrcweir         // convert the set of supported unicodes to ranges
781*cdf0e10cSrcweir         typedef std::vector<sal_uInt32> IntVector;
782*cdf0e10cSrcweir         IntVector aSupportedRanges;
783*cdf0e10cSrcweir 
784*cdf0e10cSrcweir         IntSet::const_iterator itChar = aSupportedUnicodes.begin();
785*cdf0e10cSrcweir         for(; itChar != aSupportedUnicodes.end(); ++itChar )
786*cdf0e10cSrcweir         {
787*cdf0e10cSrcweir             if( aSupportedRanges.empty()
788*cdf0e10cSrcweir             || (aSupportedRanges.back() != *itChar) )
789*cdf0e10cSrcweir             {
790*cdf0e10cSrcweir                 // add new range beginning with current unicode
791*cdf0e10cSrcweir                 aSupportedRanges.push_back( *itChar );
792*cdf0e10cSrcweir                 aSupportedRanges.push_back( 0 );
793*cdf0e10cSrcweir             }
794*cdf0e10cSrcweir 
795*cdf0e10cSrcweir             // extend existing range to include current unicode
796*cdf0e10cSrcweir             aSupportedRanges.back() = *itChar + 1;
797*cdf0e10cSrcweir         }
798*cdf0e10cSrcweir 
799*cdf0e10cSrcweir         // glyph mapping for non-unicode fonts not implemented
800*cdf0e10cSrcweir         delete[] pStartGlyphs;
801*cdf0e10cSrcweir         pStartGlyphs = NULL;
802*cdf0e10cSrcweir         aGlyphIdArray.clear();
803*cdf0e10cSrcweir 
804*cdf0e10cSrcweir         // make a pCodePairs array using the vector from above
805*cdf0e10cSrcweir         delete[] pCodePairs;
806*cdf0e10cSrcweir         nRangeCount = aSupportedRanges.size() / 2;
807*cdf0e10cSrcweir         if( nRangeCount <= 0 )
808*cdf0e10cSrcweir             return false;
809*cdf0e10cSrcweir         pCodePairs = new sal_uInt32[ nRangeCount * 2 ];
810*cdf0e10cSrcweir         IntVector::const_iterator itInt = aSupportedRanges.begin();
811*cdf0e10cSrcweir         for( pCP = pCodePairs; itInt != aSupportedRanges.end(); ++itInt )
812*cdf0e10cSrcweir             *(pCP++) = *itInt;
813*cdf0e10cSrcweir     }
814*cdf0e10cSrcweir 
815*cdf0e10cSrcweir     // prepare the glyphid-array if needed
816*cdf0e10cSrcweir     // TODO: merge ranges if they are close enough?
817*cdf0e10cSrcweir     sal_uInt16* pGlyphIds = NULL;
818*cdf0e10cSrcweir     if( !aGlyphIdArray.empty())
819*cdf0e10cSrcweir     {
820*cdf0e10cSrcweir         pGlyphIds = new sal_uInt16[ aGlyphIdArray.size() ];
821*cdf0e10cSrcweir         sal_uInt16* pOut = pGlyphIds;
822*cdf0e10cSrcweir         U16Vector::const_iterator it = aGlyphIdArray.begin();
823*cdf0e10cSrcweir         while( it != aGlyphIdArray.end() )
824*cdf0e10cSrcweir             *(pOut++) = *(it++);
825*cdf0e10cSrcweir     }
826*cdf0e10cSrcweir 
827*cdf0e10cSrcweir     // update the result struct
828*cdf0e10cSrcweir     rResult.mpRangeCodes = pCodePairs;
829*cdf0e10cSrcweir     rResult.mpStartGlyphs = pStartGlyphs;
830*cdf0e10cSrcweir     rResult.mnRangeCount = nRangeCount;
831*cdf0e10cSrcweir     rResult.mpGlyphIds = pGlyphIds;
832*cdf0e10cSrcweir     return true;
833*cdf0e10cSrcweir }
834*cdf0e10cSrcweir 
835*cdf0e10cSrcweir // =======================================================================
836*cdf0e10cSrcweir 
837*cdf0e10cSrcweir FontCharMap::FontCharMap()
838*cdf0e10cSrcweir :   mpImpl( ImplFontCharMap::GetDefaultMap() )
839*cdf0e10cSrcweir {
840*cdf0e10cSrcweir 	mpImpl->AddReference();
841*cdf0e10cSrcweir }
842*cdf0e10cSrcweir 
843*cdf0e10cSrcweir // -----------------------------------------------------------------------
844*cdf0e10cSrcweir 
845*cdf0e10cSrcweir FontCharMap::~FontCharMap()
846*cdf0e10cSrcweir {
847*cdf0e10cSrcweir     mpImpl->DeReference();
848*cdf0e10cSrcweir     mpImpl = NULL;
849*cdf0e10cSrcweir }
850*cdf0e10cSrcweir 
851*cdf0e10cSrcweir // -----------------------------------------------------------------------
852*cdf0e10cSrcweir 
853*cdf0e10cSrcweir int FontCharMap::GetCharCount() const
854*cdf0e10cSrcweir {
855*cdf0e10cSrcweir     return mpImpl->GetCharCount();
856*cdf0e10cSrcweir }
857*cdf0e10cSrcweir 
858*cdf0e10cSrcweir // -----------------------------------------------------------------------
859*cdf0e10cSrcweir 
860*cdf0e10cSrcweir int FontCharMap::CountCharsInRange( sal_uInt32 cMin, sal_uInt32 cMax ) const
861*cdf0e10cSrcweir {
862*cdf0e10cSrcweir     return mpImpl->CountCharsInRange( cMin, cMax );
863*cdf0e10cSrcweir }
864*cdf0e10cSrcweir 
865*cdf0e10cSrcweir // -----------------------------------------------------------------------
866*cdf0e10cSrcweir 
867*cdf0e10cSrcweir void FontCharMap::Reset( const ImplFontCharMap* pNewMap )
868*cdf0e10cSrcweir {
869*cdf0e10cSrcweir     mpImpl->DeReference();
870*cdf0e10cSrcweir     if( pNewMap == NULL )
871*cdf0e10cSrcweir         mpImpl = ImplFontCharMap::GetDefaultMap();
872*cdf0e10cSrcweir     else if( pNewMap != mpImpl )
873*cdf0e10cSrcweir         mpImpl = pNewMap;
874*cdf0e10cSrcweir     mpImpl->AddReference();
875*cdf0e10cSrcweir }
876*cdf0e10cSrcweir 
877*cdf0e10cSrcweir // -----------------------------------------------------------------------
878*cdf0e10cSrcweir 
879*cdf0e10cSrcweir sal_Bool FontCharMap::IsDefaultMap() const
880*cdf0e10cSrcweir {
881*cdf0e10cSrcweir     return mpImpl->IsDefaultMap();
882*cdf0e10cSrcweir }
883*cdf0e10cSrcweir 
884*cdf0e10cSrcweir // -----------------------------------------------------------------------
885*cdf0e10cSrcweir 
886*cdf0e10cSrcweir sal_Bool FontCharMap::HasChar( sal_uInt32 cChar ) const
887*cdf0e10cSrcweir {
888*cdf0e10cSrcweir     return mpImpl->HasChar( cChar );
889*cdf0e10cSrcweir }
890*cdf0e10cSrcweir 
891*cdf0e10cSrcweir // -----------------------------------------------------------------------
892*cdf0e10cSrcweir 
893*cdf0e10cSrcweir sal_uInt32 FontCharMap::GetFirstChar() const
894*cdf0e10cSrcweir {
895*cdf0e10cSrcweir     return mpImpl->GetFirstChar();
896*cdf0e10cSrcweir }
897*cdf0e10cSrcweir 
898*cdf0e10cSrcweir // -----------------------------------------------------------------------
899*cdf0e10cSrcweir 
900*cdf0e10cSrcweir sal_uInt32 FontCharMap::GetLastChar() const
901*cdf0e10cSrcweir {
902*cdf0e10cSrcweir     return mpImpl->GetLastChar();
903*cdf0e10cSrcweir }
904*cdf0e10cSrcweir 
905*cdf0e10cSrcweir // -----------------------------------------------------------------------
906*cdf0e10cSrcweir 
907*cdf0e10cSrcweir sal_uInt32 FontCharMap::GetNextChar( sal_uInt32 cChar ) const
908*cdf0e10cSrcweir {
909*cdf0e10cSrcweir     return mpImpl->GetNextChar( cChar );
910*cdf0e10cSrcweir }
911*cdf0e10cSrcweir 
912*cdf0e10cSrcweir // -----------------------------------------------------------------------
913*cdf0e10cSrcweir 
914*cdf0e10cSrcweir sal_uInt32 FontCharMap::GetPrevChar( sal_uInt32 cChar ) const
915*cdf0e10cSrcweir {
916*cdf0e10cSrcweir     return mpImpl->GetPrevChar( cChar );
917*cdf0e10cSrcweir }
918*cdf0e10cSrcweir 
919*cdf0e10cSrcweir // -----------------------------------------------------------------------
920*cdf0e10cSrcweir 
921*cdf0e10cSrcweir int FontCharMap::GetIndexFromChar( sal_uInt32 cChar ) const
922*cdf0e10cSrcweir {
923*cdf0e10cSrcweir     return mpImpl->GetIndexFromChar( cChar );
924*cdf0e10cSrcweir }
925*cdf0e10cSrcweir 
926*cdf0e10cSrcweir // -----------------------------------------------------------------------
927*cdf0e10cSrcweir 
928*cdf0e10cSrcweir sal_uInt32 FontCharMap::GetCharFromIndex( int nIndex ) const
929*cdf0e10cSrcweir {
930*cdf0e10cSrcweir     return mpImpl->GetCharFromIndex( nIndex );
931*cdf0e10cSrcweir }
932*cdf0e10cSrcweir 
933*cdf0e10cSrcweir // =======================================================================
934*cdf0e10cSrcweir 
935