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