xref: /trunk/main/vcl/unx/generic/gdi/salcvt.cxx (revision c82f2877)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_vcl.hxx"
26 #include "salcvt.hxx"
27 
28 
SalConverterCache()29 SalConverterCache::SalConverterCache()
30 {
31 }
32 
33 SalConverterCache*
GetInstance()34 SalConverterCache::GetInstance ()
35 {
36 	static SalConverterCache* pCvt = NULL;
37 	if (pCvt == NULL)
38 		pCvt = new SalConverterCache;
39 
40 	return pCvt;
41 }
42 
~SalConverterCache()43 SalConverterCache::~SalConverterCache()
44 {
45 }
46 
47 // ---> FIXME
48 #include <stdio.h>
49 // <---
50 
51 rtl_UnicodeToTextConverter
GetU2TConverter(rtl_TextEncoding nEncoding)52 SalConverterCache::GetU2TConverter( rtl_TextEncoding nEncoding )
53 {
54     if( rtl_isOctetTextEncoding( nEncoding ) )
55 	{
56         ConverterT& rConverter( m_aConverters[ nEncoding ] );
57 		if ( rConverter.mpU2T == NULL )
58 		{
59 			rConverter.mpU2T =
60                 rtl_createUnicodeToTextConverter( nEncoding );
61 // ---> FIXME
62 if ( rConverter.mpU2T == NULL )
63 	fprintf( stderr, "failed to create Unicode -> %i converter\n", nEncoding);
64 // <---
65 		}
66 		return rConverter.mpU2T;
67 	}
68 	return NULL;
69 }
70 
71 rtl_TextToUnicodeConverter
GetT2UConverter(rtl_TextEncoding nEncoding)72 SalConverterCache::GetT2UConverter( rtl_TextEncoding nEncoding )
73 {
74     if( rtl_isOctetTextEncoding( nEncoding ) )
75 	{
76         ConverterT& rConverter( m_aConverters[ nEncoding ] );
77 		if ( rConverter.mpT2U == NULL )
78 		{
79 			rConverter.mpT2U =
80                 rtl_createTextToUnicodeConverter( nEncoding );
81 // ---> FIXME
82 if ( rConverter.mpT2U == NULL )
83 	fprintf( stderr, "failed to create %i -> Unicode converter\n", nEncoding );
84 // <---
85 		}
86 		return rConverter.mpT2U;
87 	}
88 	return NULL;
89 }
90 
91 Bool
IsSingleByteEncoding(rtl_TextEncoding nEncoding)92 SalConverterCache::IsSingleByteEncoding( rtl_TextEncoding nEncoding )
93 {
94     if( rtl_isOctetTextEncoding( nEncoding ) )
95 	{
96         ConverterT& rConverter( m_aConverters[ nEncoding ] );
97 		if ( ! rConverter.mbValid )
98 		{
99 			rConverter.mbValid = True;
100 
101 			rtl_TextEncodingInfo aTextEncInfo;
102 			aTextEncInfo.StructSize = sizeof( aTextEncInfo );
103 			rtl_getTextEncodingInfo( nEncoding, &aTextEncInfo );
104 
105 			if (   aTextEncInfo.MinimumCharSize == aTextEncInfo.MaximumCharSize
106 				&& aTextEncInfo.MinimumCharSize == 1)
107 				rConverter.mbSingleByteEncoding = True;
108 			else
109 				rConverter.mbSingleByteEncoding = False;
110 		}
111 
112 		return rConverter.mbSingleByteEncoding;
113 	}
114 	return False;
115 }
116 
117 // check whether the character set nEncoding contains the unicode
118 // code point nChar. This list has been compiled from the according
119 // ttmap files in /usr/openwin/lib/X11/fonts/TrueType/ttmap/
120 Bool
EncodingHasChar(rtl_TextEncoding nEncoding,sal_Unicode nChar)121 SalConverterCache::EncodingHasChar( rtl_TextEncoding nEncoding,
122 		sal_Unicode nChar )
123 {
124 	Bool bMatch = False;
125 
126 	switch ( nEncoding )
127 	{
128 		case RTL_TEXTENCODING_DONTKNOW:
129 			bMatch = False;
130 			break;
131 
132 		case RTL_TEXTENCODING_MS_1252:
133 		case RTL_TEXTENCODING_ISO_8859_1:
134 		case RTL_TEXTENCODING_ISO_8859_15:
135         // handle iso8859-15 and iso8859-1 the same (and both with euro)
136         // handle them also like ms1252
137         // this is due to the fact that so many X fonts say they are iso8859-1
138         // but have the other glyphs anyway because they are really ms1252
139 			bMatch = 	( /*nChar >= 0x0000 &&*/ nChar <= 0x00ff )
140                 ||	( nChar == 0x20ac )
141                 ||	( nChar == 0x201a )
142                 ||	( nChar == 0x0192 )
143                 ||	( nChar == 0x201e )
144                 ||	( nChar == 0x2026 )
145                 ||	( nChar == 0x2020 )
146                 ||	( nChar == 0x2021 )
147                 ||	( nChar == 0x02c6 )
148                 ||	( nChar == 0x2030 )
149                 ||	( nChar == 0x0160 )
150                 ||	( nChar == 0x2039 )
151                 ||	( nChar == 0x0152 )
152                 ||	( nChar == 0x017d )
153                 ||	( nChar == 0x2018 )
154                 ||	( nChar == 0x2019 )
155                 ||	( nChar == 0x201c )
156                 ||	( nChar == 0x201d )
157                 ||	( nChar == 0x2022 )
158                 ||	( nChar == 0x2013 )
159                 ||	( nChar == 0x2014 )
160                 ||	( nChar == 0x02dc )
161                 ||	( nChar == 0x2122 )
162                 ||	( nChar == 0x0161 )
163                 ||	( nChar == 0x203a )
164                 ||	( nChar == 0x0153 )
165                 ||	( nChar == 0x017e )
166                 ||	( nChar == 0x0178 )
167                 ;
168 			break;
169 
170 		case RTL_TEXTENCODING_ISO_8859_2:
171 			bMatch = 	( nChar >= 0x0020 && nChar <= 0x007e )
172 					||	( nChar >= 0x00a0 && nChar <= 0x017e )
173 					||	( nChar >= 0x02c7 && nChar <= 0x02dd );
174 			break;
175 
176 		case RTL_TEXTENCODING_ISO_8859_4:
177 			bMatch = 	( nChar >= 0x0020 && nChar <= 0x007e )
178 					||	( nChar >= 0x00a0 && nChar <= 0x017e )
179 					||	( nChar >= 0x02c7 && nChar <= 0x02db );
180 			break;
181 
182 		case RTL_TEXTENCODING_ISO_8859_5:
183 			bMatch = 	( nChar >= 0x0020 && nChar <= 0x007e )
184 					||	( nChar >= 0x00a0 && nChar <= 0x00ad )
185 					||	( nChar >= 0x0401 && nChar <= 0x045f )
186 					||	( nChar == 0x2116 );
187 			break;
188 
189 		case RTL_TEXTENCODING_ISO_8859_6:
190 			bMatch = 	( nChar >= 0x0020 && nChar <= 0x007e )
191 					||	( nChar >= 0x0600 && nChar <= 0x06ff )
192 					|| 	( nChar >= 0xfb50 && nChar <= 0xfffe );
193 			break;
194 
195 		case RTL_TEXTENCODING_ISO_8859_7:
196 			bMatch = 	( nChar >= 0x0020 && nChar <= 0x007e )
197 					||	( nChar >= 0x00a0 && nChar <= 0x00bd )
198 					||	( nChar == 0x02bd )
199 					||	( nChar >= 0x0384 && nChar <= 0x03ce )
200 					||	( nChar >= 0x2014 && nChar <= 0x2019 );
201 			break;
202 
203 		case RTL_TEXTENCODING_ISO_8859_8:
204 			bMatch = 	( nChar >= 0x0020 && nChar <= 0x007e )
205 					||	( nChar >= 0x00a0 && nChar <= 0x00f7 )
206 					||	( nChar >= 0x05d0 && nChar <= 0x05ea )
207 					||	( nChar == 0x2017 );
208 			break;
209 
210 		case RTL_TEXTENCODING_ISO_8859_9:
211 			bMatch = 	( nChar >= 0x0020 && nChar <= 0x007e )
212 					||	( nChar >= 0x00a0 && nChar <= 0x015f );
213  			break;
214 
215 		case RTL_TEXTENCODING_ISO_8859_13:
216 			bMatch =   	( nChar >= 0x0020 && nChar <= 0x007e )
217 					||	( nChar >= 0x00a0 && nChar <= 0x017e )
218 					||  ( nChar >= 0x2019 && nChar <= 0x201e );
219 			break;
220 
221         /* real case for RTL_TEXTENCODING_ISO_8859_15
222 		case RTL_TEXTENCODING_ISO_8859_15:
223 			bMatch =  	( nChar >= 0x0020 && nChar <= 0x007e )
224 					||	( nChar >= 0x00a0 && nChar <= 0x00ff )
225 					||	( nChar >= 0x0152 && nChar <= 0x017e )
226 					||  ( nChar == 0x20ac );
227 			break;
228         */
229 
230 		case RTL_TEXTENCODING_JIS_X_0201:
231 			bMatch = 	( nChar >= 0x0020 && nChar <= 0x007e )
232 					||	( nChar >= 0xff61 && nChar <= 0xff9f );
233 			break;
234 
235 		case RTL_TEXTENCODING_MS_1251:
236 			bMatch = 	( nChar >= 0x0020 && nChar <= 0x007e )
237 					||	( nChar >= 0x00a0 && nChar <= 0x00bb )
238 					||	( nChar >= 0x0401 && nChar <= 0x045f )
239 					||	( nChar >= 0x0490 && nChar <= 0x0491 )
240 					||	( nChar >= 0x2013 && nChar <= 0x203a )
241 					||	( nChar >= 0x2116 && nChar <= 0x2122 );
242 			break;
243 
244 		case RTL_TEXTENCODING_KOI8_R:
245 			bMatch = 	( nChar >= 0x0020 && nChar <= 0x007e )
246 					||	( nChar >= 0x00a0 && nChar <= 0x00b7 )
247 					||	( nChar == 0x00f7 )
248 					||	( nChar >= 0x0401 && nChar <= 0x0451 )
249 					||	( nChar >= 0x2219 && nChar <= 0x221a )
250 					||	( nChar >= 0x2248 && nChar <= 0x2265 )
251 					||	( nChar >= 0x2320 && nChar <= 0x2321 )
252 					||	( nChar >= 0x2500 && nChar <= 0x25a0 );
253 			break;
254 
255 		case RTL_TEXTENCODING_UNICODE:
256 			bMatch = True;
257 			break;
258 
259 		case RTL_TEXTENCODING_EUC_KR:
260 		case RTL_TEXTENCODING_BIG5:
261 		case RTL_TEXTENCODING_GBK:
262 		case RTL_TEXTENCODING_GB_2312:
263 		case RTL_TEXTENCODING_MS_1361:
264 		case RTL_TEXTENCODING_JIS_X_0208:
265 
266 			// XXX Big5 and Korean EUC contain Ascii chars, but Solaris
267 			// *-big5-1 and *-ksc5601.1992-3 fonts dont, in general CJK fonts
268 			// are monospaced, so dont trust them for latin chars
269 			if (nChar <= 0xFF)
270 			{
271 				bMatch = False;
272 				break;
273 			}
274 
275 		default:
276 			// XXX really convert the unicode char into the encoding
277 			// and check for conversion errors, this is expensive !
278 			rtl_UnicodeToTextConverter aConverter;
279 			rtl_UnicodeToTextContext   aContext;
280 
281 			aConverter = GetU2TConverter(nEncoding);
282 			aContext   = rtl_createUnicodeToTextContext( aConverter );
283 
284 			// ---> FIXME
285 			if ( aConverter == NULL )
286 				return False;
287 			// <---
288 
289 			sal_Char   pConversionBuffer[ 32 ];
290 			sal_uInt32 nConversionInfo;
291 			sal_Size   nConvertedChars;
292 			sal_Size   nSize;
293 
294 			nSize = rtl_convertUnicodeToText( aConverter, aContext,
295 					&nChar, 1, pConversionBuffer, sizeof(pConversionBuffer),
296 					  RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR
297 					| RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR,
298 					&nConversionInfo, &nConvertedChars );
299 
300 			rtl_destroyUnicodeToTextContext( aConverter, aContext );
301 
302 			bMatch =    (nConvertedChars == 1)
303 					 && (nSize == 1 || nSize == 2) // XXX Fix me this is a hack
304 					 && ((nConversionInfo & RTL_UNICODETOTEXT_INFO_ERROR) == 0);
305 			break;
306 	}
307 
308 	return bMatch;
309 }
310 
311 // wrapper for rtl_convertUnicodeToText that handles the usual cases for
312 // textconversion in drawtext and gettextwidth routines
313 sal_Size
ConvertStringUTF16(const sal_Unicode * pText,int nTextLen,sal_Char * pBuffer,sal_Size nBufferSize,rtl_TextEncoding nEncoding)314 SalConverterCache::ConvertStringUTF16( const sal_Unicode *pText, int nTextLen,
315 		sal_Char *pBuffer, sal_Size nBufferSize, rtl_TextEncoding nEncoding )
316 {
317 	rtl_UnicodeToTextConverter aConverter = GetU2TConverter(nEncoding);
318 
319 	const sal_uInt32 nCvtFlags =
320 			  RTL_UNICODETOTEXT_FLAGS_UNDEFINED_REPLACE
321 			| RTL_UNICODETOTEXT_FLAGS_UNDEFINED_QUESTIONMARK
322 			| RTL_UNICODETOTEXT_FLAGS_INVALID_QUESTIONMARK ;
323 	sal_uInt32  nCvtInfo;
324 	sal_Size    nCvtChars;
325 
326 	rtl_UnicodeToTextContext aContext =
327 		 	rtl_createUnicodeToTextContext( aConverter );
328 
329 	sal_Size nSize = rtl_convertUnicodeToText( aConverter, aContext,
330 				pText, nTextLen, pBuffer, nBufferSize,
331 				nCvtFlags, &nCvtInfo, &nCvtChars );
332 
333 	rtl_destroyUnicodeToTextContext( aConverter, aContext );
334 
335 	return nSize;
336 }
337 
338